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

时间:2022-05-29 19:45:59

1、NFC初始化的时序图:

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

* 服务端的初始化:

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

<application android:name=".NfcApplication"
android:icon="@drawable/icon"
android:label="@string/app_name"
android:theme="@android:style/Theme.Material.Light"
android:persistent="true"
android:backupAgent="com.android.nfc.NfcBackupAgent"
android:killAfterRestore="false"
android:usesCleartextTraffic="false"

其中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);
}