接上部分的分析,当前系统已经进入到applyRouting()阶段,后续应该是需要一直去监听当前是否有NFC设备进入通讯范围。如果有适合的NFC设备,则底层会先进行沟通,并将消息通知给上层。
进入NFC设备发现流程
下面从applyRouting()函数开始分析,可以参考系统注释:
void applyRouting(boolean force) {
synchronized (this) {
//@paul: 如果NFC没有打开或者已经关闭,则直接发挥
if (!isNfcEnabledOrShuttingDown()) {
return;
}
...
if (mInProvisionMode) {
mInProvisionMode = Settings.Secure.getInt(mContentResolver,
Settings.Global.DEVICE_PROVISIONED, 0) == 0;
if (!mInProvisionMode) {
//@paul: 原生的Android里面Provision只做了一件事,就是写入一个DEVICE_PROVISIONED标记。
//@paul: 不过这个标记作用很大,这个标记只会在系统全新升级(双清)的时候写入一次,代表了Android系统升级准备完成,可以正常工作。
mNfcDispatcher.disableProvisioningMode();
mHandoverManager.setEnabled(true);
}
}
//@paul: 如果有tag正在通讯时,delay一段时间再更新参数
// Special case: if we're transitioning to unlocked state while
// still talking to a tag, postpone re-configuration.
if (mScreenState == ScreenStateHelper.SCREEN_STATE_ON_UNLOCKED && isTagPresent()) {
Log.d(TAG, "Not updating discovery parameters, tag connected.");
mHandler.sendMessageDelayed(mHandler.obtainMessage(MSG_RESUME_POLLING),
APPLY_ROUTING_RETRY_TIMEOUT_MS);
return;
}
try {
watchDog.start();
//@paul: 依据前面初始化的参数来更新NfcDiscoveryParameters
// Compute new polling parameters
NfcDiscoveryParameters newParams = computeDiscoveryParameters(mScreenState);
if (force || !newParams.equals(mCurrentDiscoveryParameters)) {
//@paul: 判断条件为:mTechMask != 0 || mEnableHostRouting
//@paul:mTechMask一般不为0,mEnableHostRouting一般为false
if (newParams.shouldEnableDiscovery()) {
boolean shouldRestart = mCurrentDiscoveryParameters.shouldEnableDiscovery();
//@paul:系统一般会进入enableDiscovery()
mDeviceHost.enableDiscovery(newParams, shouldRestart);
} else {
mDeviceHost.disableDiscovery();
}
mCurrentDiscoveryParameters = newParams;
} else {
Log.d(TAG, "Discovery configuration equal, not updating.");
}
} finally {
watchDog.cancel();
}
}
}
由于系统调用到enableDiscovery()函数,此函数不论是nxp还是nci,都会调用到native函数doEnableDiscovery(),继续追踪此函数(后续都已NXP为例),最终调用到com_android_nfc_NativeNfcManager.cpp中的:
{"doEnableDiscovery", "(IZZZ)V",
(void *)com_android_nfc_NfcManager_enableDiscovery},
继续追踪com_android_nfc_NfcManager_enableDiscovery():
static void com_android_nfc_NfcManager_enableDiscovery(JNIEnv *e, jobject o, jint modes,
jboolean, jboolean reader_mode, jboolean restart)
{
...
/* Register callback for remote device notifications.
* Must re-register every time we turn on discovery, since other operations
* (such as opening the Secure Element) can change the remote device
* notification callback*/
//@paul: 注册侦听到NFC设备时的回调函数,后续的流程从此开始
REENTRANCE_LOCK();
ret = phLibNfc_RemoteDev_NtfRegister(&nat->registry_info, nfc_jni_Discovery_notification_callback, (void *)nat);
REENTRANCE_UNLOCK();
...
//@paul: 启动discovery流程
nfc_jni_start_discovery_locked(nat, restart);
clean_and_return:
CONCURRENCY_UNLOCK();
}
此处的两个函数nfc_jni_start_discovery_locked()和nfc_jni_Discovery_notification_callback()都需要在深入一点,一个一个的看:
static void nfc_jni_start_discovery_locked(struct nfc_jni_native_data *nat, bool resume)
{
...
configure:
/* Start Polling loop */
TRACE("****** Start NFC Discovery ******");
REENTRANCE_LOCK();
//@paul: nfc_jni_discover_callback()是discover后消息notify的开始
ret = phLibNfc_Mgt_ConfigureDiscovery(resume ? NFC_DISCOVERY_RESUME : NFC_DISCOVERY_CONFIG,
nat->discovery_cfg, nfc_jni_discover_callback, (void *)&cb_data);
REENTRANCE_UNLOCK();
...
clean_and_return:
nfc_cb_data_deinit(&cb_data);
}
一旦上面进入了nfc_jni_discover_callback(),后续就会进入nfc_jni_Discovery_notification_callback(),此函数就会把底层看到的信息开始一层一层的notify:
static void nfc_jni_Di