初始化分程兩大部份:
因為函式呼叫通常就是跳來跳去的,所以參考下圖會更清楚一些:
NFC 的服務端位於源碼的 packages/apps/Nfc
位置,
並且包含了 JNI 的部份,
串接到 library 和 framework 層應用。
它有點像是 phone app 那樣,是一個應用程序,
跟著 Android 開機啟動後一直存在在背景。
這時可以稍微看一下 AndroidManifest.xml
內容,
裡面宣告了一些需要用到的權限 (permission) 和意圖 (intent):
<!-- 權限的宣告 -->
21 <uses-permission android:name="android.permission.BLUETOOTH" />
22 <uses-permission android:name="android.permission.BLUETOOTH_ADMIN" />
23 <uses-permission android:name="android.permission.BLUETOOTH_PRIVILEGED" />
24 <uses-permission android:name="android.permission.NFC" />
25 <uses-permission android:name="android.permission.NFC_UNLOCK" />
... ...
<!-- 主要的應用服務宣告 -->
62 <application android:name=".NfcApplication"
63 android:icon="@drawable/icon"
64 android:label="@string/app_name"
65 android:theme="@android:style/Theme.Material.Light"
66 android:persistent="true"
67 android:persistentWhenFeatureAvailable="android.hardware.nfc.any"
68 android:backupAgent="com.android.nfc.NfcBackupAgent"
69 android:killAfterRestore="false"
70 android:usesCleartextTraffic="false"
71 android:supportsRtl="true"
72 android:hardwareAccelerated="false"
73 >
... ...
<!-- 服務的宣告 -->
143 <service android:name=".beam.BeamSendService"
144 android:process=":beam"
145 />
146 <service android:name=".beam.BeamReceiveService"
147 android:process=":beam"
148 />
... ...
<!-- 意圖的宣告 -->
150 <receiver android:name=".NfcBootCompletedReceiver">
151 <intent-filter>
152 <action android:name="android.intent.action.BOOT_COMPLETED" />
153 </intent-filter>
154 </receiver>
其中 android:persistent=”true”
,
表明該應用在系統啟動之後直到系統關機一直是存在的。
再看一下應用程序的起始點 ./src/com/android/nfc/NfcApplication.java
,
裡面的 onCreate()
函數,其實很短:
41 @Override
42 public void onCreate() {
43 super.onCreate();
44 PackageManager pm = getApplicationContext().getPackageManager();
45 if (!pm.hasSystemFeature(PackageManager.FEATURE_NFC_ANY)) {
46 return;
47 }
48
49 boolean isMainProcess = false;
50 // We start a service in a separate process to do
51 // handover transfer. We don't want to instantiate an NfcService
52 // object in those cases, hence check the name of the process
53 // to determine whether we're the main NFC service, or the
54 // handover process
55 ActivityManager am = (ActivityManager)this.getSystemService(ACTIVITY_SERVICE);
56 List processes = am.getRunningAppProcesses();
57 Iterator i = processes.iterator();
58 while (i.hasNext()) {
59 RunningAppProcessInfo appInfo = (RunningAppProcessInfo)(i.next());
60 if (appInfo.pid == Process.myPid()) {
61 isMainProcess = (NFC_PROCESS.equals(appInfo.processName));
62 break;
63 }
64 }
65 if (UserHandle.myUserId() == 0 && isMainProcess) {
66 mNfcService = new NfcService(this);
67 ThreadedRenderer.enableForegroundTrimming();
68 }
69 }
70 }
我們可以看到這段分成兩大部份:
第一部份在註解講得非常清楚,
總之是它啟動了一個分支的服務叫 com.android.nfc:handover
,
主要負責一些藍芽耳機、鍵盤、滑鼠這類外設 (peripheral) 的資料傳輸和移轉;
還有一些容量較大的檔案透過 Android Beam 也是用這個服務,
這樣它就可以和 NFC 主服務切割開來。
第二部份就是先確定自己是主服務之後,
執行 new NfcService(this)
後宣告了一個 NfcService 對象,
再來看一下 ./src/com/android/nfc/NfcService.java
內容,
說明都在註解中:
374 public NfcService(Application nfcApplication) {
//獲取當前userID,主要在多用戶場景下進行用戶切換到時候來更新上下文環境
375 mUserId = ActivityManager.getCurrentUser();
376 mContext = nfcApplication;
377
//與Tag相關,TagService 最终會調用到NativeNfcTag中的方法
378 mNfcTagService = new TagService();
//上層應用通過framework,間接通過binder調用到NfcAdapterService
379 mNfcAdapter = new NfcAdapterService();
380 Log.i(TAG, "Starting NFC service"); //開始囉!
381
382 sService = this;
383
//檢查屏幕的鎖屏狀態 (ON/OFF/ON_UNLOCK)
384 mScreenStateHelper = new ScreenStateHelper(mContext);
385 mContentResolver = mContext.getContentResolver();
//NativeNfcManager提供和C++層進行交互的接口,最關鍵的一點NativeNfcManager將NFC的狀態及時通知NfcService
386 mDeviceHost = new NativeNfcManager(mContext, this);
387
388 mNfcUnlockManager = NfcUnlockManager.getInstance();
389
//handover的數據分析
390 mHandoverDataParser = new HandoverDataParser();
391 boolean isNfcProvisioningEnabled = false;
392 try {
//宣告在res/values/provisioning.xml裡面預設是true
393 isNfcProvisioningEnabled = mContext.getResources().getBoolean(
394 R.bool.enable_nfc_provisioning);
395 } catch (NotFoundException e) {
396 }
397 //看要支援NFC哪幾種Type,通常就是看模組支援
398 try {
//宣告在res/values/live_cases.xml裡面預設是true
399 mIsLiveCaseEnabled = mContext.getResources().getBoolean(R.bool.enable_live_cases);
400 } catch (NotFoundException e) {
401 mIsLiveCaseEnabled = false;
402 }
403
404 mLiveCaseTechnology = 0;
405 String[] liveCaseTechList;
406 try {
// 宣告在res/values/live_cases.xml裡面預設只有TypeA
407 liveCaseTechList = mContext.getResources().getStringArray(R.array.live_case_tag_types);
408 for (int i=0; i < liveCaseTechList.length; i++) {
409 if (liveCaseTechList[i].equals("TypeA")) {
410 mLiveCaseTechnology |= NFC_POLL_A;
411 } else if (liveCaseTechList[i].equals("TypeB")) {
412 mLiveCaseTechnology |= NFC_POLL_B;
413 } else if (liveCaseTechList[i].equals("TypeF")) {
414 mLiveCaseTechnology |= NFC_POLL_F;
415 } else if (liveCaseTechList[i].equals("TypeV")) {
416 mLiveCaseTechnology |= NFC_POLL_V;
417 }
418 }
419 } catch (NotFoundException e) {
420 mLiveCaseTechnology = 0;
421 }
422 //設備是否在setup wizard階段支持接收NFC數據
423 if (isNfcProvisioningEnabled) {
//官網說明連結:[Settings.Global#DEVICE_PROVISIONED](https://developer.android.com/reference/android/provider/Settings.Global#DEVICE_PROVISIONED)
424 mInProvisionMode = Settings.Secure.getInt(mContentResolver,
425 Settings.Global.DEVICE_PROVISIONED, 0) == 0;
426 } else {
427 mInProvisionMode = false;
428 }
429 //收到NFC消息處理流程, 最終調用到dispatchTag(),將Tag消息發送給對應的activity進行處理
430 mNfcDispatcher = new NfcDispatcher(mContext, mHandoverDataParser, mInProvisionMode,
431 mIsLiveCaseEnabled);
//P2pLinkManager基於PPLC,對P2P的傳輸進行管理,主要完成數據的接收和發送
432 mP2pLinkManager = new P2pLinkManager(mContext, mHandoverDataParser,
433 mDeviceHost.getDefaultLlcpMiu(), mDeviceHost.getDefaultLlcpRwSize());
434
435 mPrefs = mContext.getSharedPreferences(PREF, Context.MODE_PRIVATE);
436 mPrefsEditor = mPrefs.edit();
437
438 mState = NfcAdapter.STATE_OFF;
//在nfc中會創建shareperference來保存NFC相關的一些狀態值,在此處獲取NdefPush是否enable
439 mIsNdefPushEnabled = mPrefs.getBoolean(PREF_NDEF_PUSH_ON, NDEF_PUSH_ON_DEFAULT);
440 enforceBeamShareActivityPolicy(mContext, new UserHandle(mUserId));
441
442 mIsDebugBuild = "userdebug".equals(Build.TYPE) || "eng".equals(Build.TYPE);
443
//電源管理相關,目的是和NFC是否響應相關
444 mPowerManager = (PowerManager) mContext.getSystemService(Context.POWER_SERVICE);
445
446 mRoutingWakeLock = mPowerManager.newWakeLock(
447 PowerManager.PARTIAL_WAKE_LOCK, "NfcService:mRoutingWakeLock");
448
449 mKeyguard = (KeyguardManager) mContext.getSystemService(Context.KEYGUARD_SERVICE);
450 mUserManager = (UserManager) mContext.getSystemService(Context.USER_SERVICE);
451 mVibrator = (Vibrator) mContext.getSystemService(Context.VIBRATOR_SERVICE);
452 mVibrationEffect = VibrationEffect.createOneShot(200, VibrationEffect.DEFAULT_AMPLITUDE);
453
454 mScreenState = mScreenStateHelper.checkScreenState();
455
456 mNumTagsDetected = new AtomicInteger();
457 mNumP2pDetected = new AtomicInteger();
458 mNumHceDetected = new AtomicInteger();
459
460 mBackupManager = new BackupManager(mContext);
461
//監聽各種廣播屏幕鎖頻狀態,以及用戶切換事件
462 // Intents for all users
463 IntentFilter filter = new IntentFilter(Intent.ACTION_SCREEN_OFF);
464 filter.addAction(Intent.ACTION_SCREEN_ON);
465 filter.addAction(Intent.ACTION_USER_PRESENT);
466 filter.addAction(Intent.ACTION_USER_SWITCHED);
467 mContext.registerReceiverAsUser(mReceiver, UserHandle.ALL, filter, null, null);
468
469 IntentFilter ownerFilter = new IntentFilter(Intent.ACTION_EXTERNAL_APPLICATIONS_AVAILABLE);
470 ownerFilter.addAction(Intent.ACTION_EXTERNAL_APPLICATIONS_UNAVAILABLE);
471 ownerFilter.addAction(Intent.ACTION_SHUTDOWN);
472 mContext.registerReceiver(mOwnerReceiver, ownerFilter);
473
//檢測應用安裝和刪除的事件,為了在dispatchTag的時候,顯示相關處理的應用
474 ownerFilter = new IntentFilter();
475 ownerFilter.addAction(Intent.ACTION_PACKAGE_ADDED);
476 ownerFilter.addAction(Intent.ACTION_PACKAGE_REMOVED);
477 ownerFilter.addDataScheme("package");
478 mContext.registerReceiver(mOwnerReceiver, ownerFilter);
479
480 IntentFilter policyFilter = new IntentFilter(DevicePolicyManager.ACTION_DEVICE_POLICY_MANAGER_STATE_CHANGED);
481 mContext.registerReceiverAsUser(mPolicyReceiver, UserHandle.ALL, policyFilter, null, null);
482
483 updatePackageCache();
484
//判斷是否支持card emulation的功能
485 PackageManager pm = mContext.getPackageManager();
486 mIsHceCapable =
487 pm.hasSystemFeature(PackageManager.FEATURE_NFC_HOST_CARD_EMULATION) ||
488 pm.hasSystemFeature(PackageManager.FEATURE_NFC_HOST_CARD_EMULATION_NFCF);
489 mIsHceFCapable =
490 pm.hasSystemFeature(PackageManager.FEATURE_NFC_HOST_CARD_EMULATION_NFCF);
491 if (mIsHceCapable) {
492 mCardEmulationManager = new CardEmulationManager(mContext);
493 }
494 mForegroundUtils = ForegroundUtils.getInstance();
495
//將服務添加到系統服務中,SERVICE_NAME 服務名稱為 “nfc”
496 // Make sure this is only called when object construction is complete.
497 ServiceManager.addService(SERVICE_NAME, mNfcAdapter);
498
//創建線程來處理TASK_BOOT
499 new EnableDisableTask().execute(TASK_BOOT); // do blocking boot tasks
500
501 mHandler.sendEmptyMessageDelayed(MSG_UPDATE_STATS, STATS_UPDATE_INTERVAL_MS);
502
503 IVrManager mVrManager = IVrManager.Stub.asInterface(ServiceManager.getService(
504 mContext.VR_SERVICE));
505 if (mVrManager != null) {
506 try {
507 mVrManager.registerListener(mVrStateCallbacks);
508 mIsVrModeEnabled = mVrManager.getVrModeState();
509 } catch (RemoteException e) {
510 Log.e(TAG, "Failed to register VR mode state listener: " + e);
511 }
512 }
513 mSEService = ISecureElementService.Stub.asInterface(ServiceManager.getService(
514 Context.SECURE_ELEMENT_SERVICE));
515 }
在 EnableDisableTask
針對 TASK_BOOT 這個 case,
會根據當前 NFC 的狀態,即 NFC 功能開啟或者關閉,來進行相關的處理。
當 NFC 功能開啟就會執行 enableInternal()
;
第一次開機時則會執行 factoryReset()
。
這個可以參考 ./src/com/android/nfc/NfcService.java
中 NFC 開啟的流程:
613 case TASK_BOOT:
614 if (mPrefs.getBoolean(PREF_FIRST_BOOT, true)) {
615 Log.i(TAG, "First Boot");
616 mPrefsEditor.putBoolean(PREF_FIRST_BOOT, false);
617 mPrefsEditor.apply();
618 mDeviceHost.factoryReset();
619 }
620 Log.d(TAG, "checking on firmware download");
621 if (mPrefs.getBoolean(PREF_NFC_ON, NFC_ON_DEFAULT)) {
622 Log.d(TAG, "NFC is on. Doing normal stuff");
623 enableInternal();
624 } else {
625 Log.d(TAG, "NFC is off. Checking firmware version");
626 mDeviceHost.checkFirmware();
627 }
628 SystemProperties.set("nfc.initialized", "true");
629 break;
好的!那第二部份 NfcAdapter 相關的內容就在下篇做詳細介紹。
很受用的文章 請問你service trace function的圖是怎麼做的? 另外有什麼方便的trace tool嗎 這樣子一目了然 感謝