[Android7.0]NFC初始化的流程分析

1、NFC初始化的时序图:

[Android7.0]NFC初始化的流程分析_第1张图片
2、代码分析:
初始化分两部分,第一供应framework使用的服务端初始化,并将服务添加到ServiceManager中,第二是初始化NFC适配器NfcAdapter,其中就包含何种对应NFC协议的服务。

* 服务端的初始化:

NFC的服务端代码位于packages/apps/Nfc中,并且还包含了JNI代码,NFC的服务端类似phone app是一个应用程序,跟随系统启动并一直存在的一个服务进程。 可以看一下packages/apps/Nfc
目录中的AndroidManifest.xml中的定义:

其中android:persistent=”true”,表明该应用在系统启动之后直到系统关机一直是存在的。

NfcApplication 继承于Application,当程序启动的时候,调用onCreate()方法,代码如下:

public class NfcApplication extends Application {

…..
@Override
public void onCreate() {
super.onCreate();

    boolean isMainProcess = false;
    // We start a service in a separate process to do
    // handover transfer. We don't want to instantiate an NfcService
    // object in those cases, hence check the name of the process
    // to determine whether we're the main NFC service, or the
    // handover process
    ActivityManager am = (ActivityManager)this.getSystemService(ACTIVITY_SERVICE);
    List processes = am.getRunningAppProcesses();
    Iterator i = processes.iterator();
    while (i.hasNext()) {
        RunningAppProcessInfo appInfo = (RunningAppProcessInfo)(i.next());
        if (appInfo.pid == Process.myPid()) {
            isMainProcess =  (NFC_PROCESS.equals(appInfo.processName));
            break;
        }
    }
    if (UserHandle.myUserId() == 0 && isMainProcess) {
        mNfcService = new NfcService(this);
        ThreadedRenderer.enableForegroundTrimming();
    }
}

在onCreat()的方法中构建了NfcService对象。进一步的去分析一下NfcService的构造函数中的代码:

public NfcService(Application nfcApplication) {
mUserId = ActivityManager.getCurrentUser(); //获取当前userID,主要在多用户场景下进行用户切换到时候来更新上下文环境
mContext = nfcApplication;

    mNfcTagService = new TagService(); //与Tag相关,TagService最终会调用到NativeNfcTag中的方法
    mNfcAdapter = new NfcAdapterService(); //上层应用通过framework,间接通过binder调用到NfcAdapterService
    sService = this;
    mScreenStateHelper = new ScreenStateHelper(mContext); //检查屏幕的锁屏状态ON,OFF,ON_UNLOCK
    mContentResolver = mContext.getContentResolver();
    mDeviceHost = new NativeNfcManager(mContext, this); //NativeNfcManager提供和C++层进行交互的接口,最关键的一点NativeNfcManager将NFC的状态及时通知NfcService

    mNfcUnlockManager = NfcUnlockManager.getInstance();

    mHandoverDataParser = new HandoverDataParser();//handover的数据分析
    boolean isNfcProvisioningEnabled = false;
    try {
        isNfcProvisioningEnabled = mContext.getResources().getBoolean(
                R.bool.enable_nfc_provisioning);
    } catch (NotFoundException e) {
    }
  //设备是否在setup wizard阶段支持接收NFC 数据
    if (isNfcProvisioningEnabled) {
        mInProvisionMode = Settings.Secure.getInt(mContentResolver,
                Settings.Global.DEVICE_PROVISIONED, 0) == 0;
    } else {
        mInProvisionMode = false;
    }
   //收到NFC  消息处理流程,  最终调用到dispatchTag(),将Tag消息发送给对应的activity进行处理
    mNfcDispatcher = new NfcDispatcher(mContext, mHandoverDataParser, mInProvisionMode);
  //P2pLinkManager基于PPLC,对P2P的传输进行管理,主要完成数据的接收和发送
    mP2pLinkManager = new P2pLinkManager(mContext, mHandoverDataParser,
            mDeviceHost.getDefaultLlcpMiu(), mDeviceHost.getDefaultLlcpRwSize());

    mPrefs = mContext.getSharedPreferences(PREF, Context.MODE_PRIVATE);
    mPrefsEditor = mPrefs.edit();
  //和NFC的security相关,主要是读取解析/etc/nfcee_access.xml文件
    mNfceeAccessControl = new NfceeAccessControl(mContext);

    mState = NfcAdapter.STATE_OFF;
  //在nfc中会创建shareperference来保存NFC相关的一些状态值,在此处获取NdefPush是否enable
    mIsNdefPushEnabled = mPrefs.getBoolean(PREF_NDEF_PUSH_ON, NDEF_PUSH_ON_DEFAULT);
    setBeamShareActivityState(mIsNdefPushEnabled);

    mIsDebugBuild = "userdebug".equals(Build.TYPE) || "eng".equals(Build.TYPE);
  //电源管理相关,目的是和NFC是否响应相关
    mPowerManager = (PowerManager) mContext.getSystemService(Context.POWER_SERVICE);

    mRoutingWakeLock = mPowerManager.newWakeLock(
            PowerManager.PARTIAL_WAKE_LOCK, "NfcService:mRoutingWakeLock");

    mKeyguard = (KeyguardManager) mContext.getSystemService(Context.KEYGUARD_SERVICE);
    mUserManager = (UserManager) mContext.getSystemService(Context.USER_SERVICE);

    mScreenState = mScreenStateHelper.checkScreenState();

    mNumTagsDetected = new AtomicInteger();
    mNumP2pDetected = new AtomicInteger();
    mNumHceDetected = new AtomicInteger();

    // Intents for all users   //监听各种广播屏幕锁频状态,以及用户切换事件
    IntentFilter filter = new IntentFilter(Intent.ACTION_SCREEN_OFF);
    filter.addAction(Intent.ACTION_SCREEN_ON);
    filter.addAction(Intent.ACTION_USER_PRESENT);
    filter.addAction(Intent.ACTION_USER_SWITCHED);
    mContext.registerReceiverAsUser(mReceiver, UserHandle.ALL, filter, null, null);

    IntentFilter ownerFilter = new IntentFilter(Intent.ACTION_EXTERNAL_APPLICATIONS_AVAILABLE);
    ownerFilter.addAction(Intent.ACTION_EXTERNAL_APPLICATIONS_UNAVAILABLE);
    mContext.registerReceiver(mOwnerReceiver, ownerFilter);
  //检测应用安装和删除的事件,为了在dispatchTag的时候,显示相关处理的应用
    ownerFilter = new IntentFilter();
    ownerFilter.addAction(Intent.ACTION_PACKAGE_ADDED);
    ownerFilter.addAction(Intent.ACTION_PACKAGE_REMOVED);
    ownerFilter.addDataScheme("package");
    mContext.registerReceiver(mOwnerReceiver, ownerFilter);

    IntentFilter policyFilter = new IntentFilter(DevicePolicyManager.ACTION_DEVICE_POLICY_MANAGER_STATE_CHANGED);
    mContext.registerReceiverAsUser(mPolicyReceiver, UserHandle.ALL, policyFilter, null, null);

    updatePackageCache();
   //判断是否支持card emulation的功能
    PackageManager pm = mContext.getPackageManager();
    mIsHceCapable =
            pm.hasSystemFeature(PackageManager.FEATURE_NFC_HOST_CARD_EMULATION) ||
            pm.hasSystemFeature(PackageManager.FEATURE_NFC_HOST_CARD_EMULATION_NFCF);
    mIsHceFCapable =
            pm.hasSystemFeature(PackageManager.FEATURE_NFC_HOST_CARD_EMULATION_NFCF);
    if (mIsHceCapable) {
        mCardEmulationManager = new CardEmulationManager(mContext);
    }
    mForegroundUtils = ForegroundUtils.getInstance();

    // Make sure this is only called when object construction is complete.
    ServiceManager.addService(SERVICE_NAME, mNfcAdapter);//将服务添加到系统服务中,服务名称为“nfc”

    new EnableDisableTask().execute(TASK_BOOT);  // do blocking boot tasks //创建线程来处理TASK_BOOT

    mHandler.sendEmptyMessageDelayed(MSG_UPDATE_STATS, STATS_UPDATE_INTERVAL_MS);
}

在EnableDisableTask针对TASK_BOOT这个case,会根据当前NFC的状态,即NFC功能开启或者关闭,来进行相关的处理。当NFC功能开启就会执行enableInternal(),这个可以参考NFC开启的流程:
case TASK_BOOT:
Log.d(TAG, “checking on firmware download”);
if (mPrefs.getBoolean(PREF_NFC_ON, NFC_ON_DEFAULT)) {
Log.d(TAG, “NFC is on. Doing normal stuff”);
enableInternal();
} else {
Log.d(TAG, “NFC is off. Checking firmware version”);
mDeviceHost.checkFirmware();
}
if (mPrefs.getBoolean(PREF_FIRST_BOOT, true)) {
Log.i(TAG, “First Boot”);
mPrefsEditor.putBoolean(PREF_FIRST_BOOT, false);
mPrefsEditor.apply();
}
break;

关于NfsService中的服务,在核心类中会进行详细的说明。

* NFC适配器NfcAdapter的初始化:

SystemServiceRegistry来维护注册进去的所有服务,其中就包含了NfcManager,NfcManager中通过NfcAdapter.getNfcAdapter(context);而在NfcAdapter中通过服务名称”nfc”,间接调用到NfcAdapterService。
由于NfcAdapterService为NfcService的内部类,从而可以操作到NfcService中的各个实例化对象。
具体分析一下代码流程:
其中SystemServiceRegistry在ContextImpl中进行调用,就不具体说明了。主要看一下NfcManager的注册过程
在SystemServiceRegistry的私有构造函数中,发现创建了NfcManager,并将其注册到服务中去了。
registerService(Context.NFC_SERVICE, NfcManager.class,
new CachedServiceFetcher() {
@Override
public NfcManager createService(ContextImpl ctx) {
return new NfcManager(ctx);
}});
接着继续分析NfcManager中的代码处理:

public NfcManager(Context context) {
    NfcAdapter adapter;
    context = context.getApplicationContext();
    if (context == null) {
        throw new IllegalArgumentException(
                "context not associated with any application (using a mock context?)");
    }
    try {
        adapter = NfcAdapter.getNfcAdapter(context); //调用NfcAdapter中的getNfcAdapter方法类获取NfcAdapter
    } catch (UnsupportedOperationException e) {
        adapter = null;
    }
    mAdapter = adapter;
}

/**
 * Get the default NFC Adapter for this device.
 *
 * @return the default NFC Adapter
 */
public NfcAdapter getDefaultAdapter() {
    return mAdapter;
}

}

NfcAdapter中如何获取NfcAdapter的,其中getNfcAdapter()为静态方法,可以直接通过类名进行操作:

public static synchronized NfcAdapter getNfcAdapter(Context context) {
    if (!sIsInitialized) { //判断是否已经进行了初始化,如果没有就获取对应的状态和服务
        sHasNfcFeature = hasNfcFeature(); //判断是否支持NFC功能
        boolean hasHceFeature = hasNfcHceFeature(); //是否支持nfc 模拟卡的功能
        /* is this device meant to have NFC */
        if (!sHasNfcFeature && !hasHceFeature) { //如果不支持NFC功能就会抛出异常
            Log.v(TAG, "this device does not have NFC support");
            throw new UnsupportedOperationException();
        }
        sService = getServiceInterface(); //获取NFC服务,在下面的函数实例中可以看到通过服务名称'nfc'来获取
        if (sService == null) {
            Log.e(TAG, "could not retrieve NFC service");
            throw new UnsupportedOperationException();
        }
        if (sHasNfcFeature) { //如果支持NFC功能就获取TagService
            try {
                sTagService = sService.getNfcTagInterface();
            } catch (RemoteException e) {
                Log.e(TAG, "could not retrieve NFC Tag service");
                throw new UnsupportedOperationException();
            }
        }
        if (hasHceFeature) { //判断是否支持模拟卡功能,如果支持就获取模拟卡服务
            try {
                sNfcFCardEmulationService = sService.getNfcFCardEmulationInterface();
            } catch (RemoteException e) {
                Log.e(TAG, "could not retrieve NFC-F card emulation service");
                throw new UnsupportedOperationException();
            }
            try {
                sCardEmulationService = sService.getNfcCardEmulationInterface();
            } catch (RemoteException e) {
                Log.e(TAG, "could not retrieve card emulation service");
                throw new UnsupportedOperationException();
            }
        }

        sIsInitialized = true;
    }
    if (context == null) {
        if (sNullContextNfcAdapter == null) {
            sNullContextNfcAdapter = new NfcAdapter(null);
        }
        return sNullContextNfcAdapter;
    }
    NfcAdapter adapter = sNfcAdapters.get(context);
    if (adapter == null) {
        adapter = new NfcAdapter(context);
        sNfcAdapters.put(context, adapter);
    }
    return adapter;
}

/** get handle to NFC service interface */
private static INfcAdapter getServiceInterface() {
    /* get a handle to NFC service */
    IBinder b = ServiceManager.getService("nfc"); //通过名称来获取NfcService
    if (b == null) {
        return null;
    }
    return INfcAdapter.Stub.asInterface(b);
}

你可能感兴趣的:(nfc)