NFC學習——NFC Enable 過程分析(一)

         拿到一臺支持NFC手機或是平板設備時,在Settings->more可以看到NFC的enble,disnable的選項,還有android Beam這個東西。現在來分析NFC enable的過程   

          wireless_settings.xml 在Settings配置了NFC功能項:

    <CheckBoxPreference
        android:key="toggle_nfc"
        android:title="@string/nfc_quick_toggle_title"
        android:summary="@string/nfc_quick_toggle_summary"
        android:persistent="false" />

    <PreferenceScreen
        android:fragment="com.android.settings.nfc.AndroidBeam"
        android:key="android_beam_settings"
        android:title="@string/android_beam_settings_title" />
         xml配置的對應處理代碼在:packages/apps/Settings/src/com/android/settings/WirelessSettings.java

public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        addPreferencesFromResource(R.xml.wireless_settings); 
        CheckBoxPreference nfc = (CheckBoxPreference) findPreference(KEY_TOGGLE_NFC);
        PreferenceScreen androidBeam = (PreferenceScreen) findPreference(KEY_ANDROID_BEAM_SETTINGS); 

        //setp1:獲取NfcEnable的實例
        mNfcEnabler = new NfcEnabler(activity, nfc, androidBeam); 
        ......

        // Remove NFC if its not available            
        //setp2:獲取NfcAdapter實例,查看NFC功能是否可能
        mNfcAdapter = NfcAdapter.getDefaultAdapter(activity);
        if (mNfcAdapter == null) {
            getPreferenceScreen().removePreference(nfc);
            getPreferenceScreen().removePreference(androidBeam);
            mNfcEnabler = null;
        } 
 }

setp1:NFcEnable實例 packages/apps/Settings/src/com/android/settings/nfc/NfcEnabler.java 實現Preference.OnPreferenceChangeListener接口監聽NFC Enable,disnable事件

public boolean onPreferenceChange(Preference preference, Object value) {
        // Turn NFC on/off

        final boolean desiredState = (Boolean) value;
        mCheckbox.setEnabled(false);

        if (desiredState) {           
           //setp3:用setp2一樣的方式獲取NfcAdapter實例出來nfc enable
            mNfcAdapter.enable();
        } else {
            mNfcAdapter.disable();
        }

        return false;
    }
         同時也是在這個NfcEnabler.java中處理了,Nfc enble,diable時,android beam的灰亮顯示問題。

Setp2:現在所有的分析點集中到了NfcAdaper這個類中,首先來看下NfcAdapter實例的獲取

源代碼的路徑:frameworks/base/core/java/android/nfc/NfcAdapter.java

    public static NfcAdapter getDefaultAdapter(Context context) { 
          ......  

       /* use getSystemService() for consistency */
        NfcManager manager = (NfcManager) context.getSystemService(Context.NFC_SERVICE);
        if (manager == null) {
            // NFC not available
            return null;
        }          
        //setp2-1
        return manager.getDefaultAdapter();
    }
NFC學習——NfcService 啓動過程分析  文章中NfcService的onCreate()方法中有如下code:

 //把mNfcAdapter 作爲Service 添加到系統服務中,ServiceManager.getService("nfc")可以獲取到binder 
 ServiceManager.addService(SERVICE_NAME, mNfcAdapter); 
NfcManager manager = (NfcManager) context.getSystemService(Context.NFC_SERVICE);獲取到的Service 就是之前add的service。

           Setp2-1:manager.getDefaultAdapter其實饒了一圈又回到NfcAdapter類中獲取NfcAdapter實例,具體看下面code

code路徑:frameworks/base/core/java/android/nfc/NfcManager.java

public NfcAdapter getDefaultAdapter() {
        return mAdapter;
    }
這個mAdaper如何來的呢?

    public NfcManager(Context context) {
        NfcAdapter adapter;
        ......
         try {
            adapter = NfcAdapter.getNfcAdapter(context);
        } catch (UnsupportedOperationException e) {
            adapter = null;
        }
        mAdapter = adapter;
    }
最終又回到NfcAdapter.gerNfcAdapter(context)這個方法上獲取實例,具體來分析:

  public static synchronized NfcAdapter getNfcAdapter(Context context) {
        if (!sIsInitialized) {
            ......
            //setp2-2:應用INfcAdapter.aidl和NfcService通信 
            sService = getServiceInterface();
            if (sService == null) {
                Log.e(TAG, "could not retrieve NFC service");
                throw new UnsupportedOperationException();
            }
            try { 
                //note2
                sTagService = sService.getNfcTagInterface();
            } catch (RemoteException e) {
                Log.e(TAG, "could not retrieve NFC Tag service");
                throw new UnsupportedOperationException();
            }

            sIsInitialized = true;
        }
        if (context == null) {
            if (sNullContextNfcAdapter == null) {
                sNullContextNfcAdapter = new NfcAdapter(null);
            }
            return sNullContextNfcAdapter;
        }              
        //sNFcAdapter 是個HashMap,從中取出之前創建的NfcAdapter實例
        NfcAdapter adapter = sNfcAdapters.get(context);
        if (adapter == null) {
            adapter = new NfcAdapter(context);
            sNfcAdapters.put(context, adapter);
        }
        return adapter;
    }
          Setp2-2:應用INfcAdapter.aidl和NfcService通信 ,INfcAdapter的方法都在NfcService的內部類NfcAdapterService中實現。

    /** get handle to NFC service interface */
    private static INfcAdapter getServiceInterface() {
        /* get a handle to NFC service */
        IBinder b = ServiceManager.getService("nfc");
        if (b == null) {
            return null;
        }
        return INfcAdapter.Stub.asInterface(b);
    }
現在Setp2的NfcAdapter已經得到了它的實例,接下來就Setp3,NfcAdapter.enable()和NfcAdapter.disable():

    public boolean enable() {
        try { 
            //從setp2-2可以知道sService.enable()通過NfcAdapterService來實現的
            return sService.enable();
        } catch (RemoteException e) {
            attemptDeadServiceRecovery(e);
            return false;
        }
    }
接下來看NfcAdapterService extends INfcAdapter.Stub 中的enable()方法:

public boolean enable() throws RemoteException {            
      //Question 1:
      NfcService.enforceAdminPerm(mContext);
      //把NFC 打開狀態寫到SharedPreferences中保存起來
      saveNfcOnSetting(true);             
      ......   
      //AsyncTash後臺處理NFC的打開      
      new EnableDisableTask().execute(TASK_ENABLE);
      return true;
}

上面code 提到一個Question 1,其實它就是給NFC 賦予一個寫的權限。

EnableDisableTask 在doInBackground中調用enableInternal();來處理NFC  turn on。

 boolean enableInternal() { 
            //logcat 信息可以看到的log信息
            Log.i(TAG, "Enabling NFC");
            updateState(NfcAdapter.STATE_TURNING_ON);                   
            //setp3-1:調用jni initialize做init相關的動作
            if (!mDeviceHost.initialize()) {
                Log.w(TAG, "Error enabling NFC");
                updateState(NfcAdapter.STATE_OFF);
                return false;
            }
            synchronized(NfcService.this) {
                mObjectMap.clear(); 
                //setp 3-2:開啓一些循環監聽的線程服務
                mP2pLinkManager.enableDisable(mIsNdefPushEnabled, true);
                updateState(NfcAdapter.STATE_ON);
            }

            initSoundPool();

            /* Start polling loop */
            applyRouting(true);//開始掃描查詢tag和P2p設備 
           return true;
        }

setp3-1:initialize()對應的是在NativeNfcManager.java 中initialize()實現的,NativeNfcManager.initialize()直接調用的是jni方法doInitialize(),doInitialize()對應的在jni的方法:com_android_nfc_NfcManager_initialize(JNIEnv *e, jobject o),這部分將在NFC學習——NFC Enable 過程分析(二)   分析。       

setp3-2:這一部分將在NFC學習——NFC Enable 過程分析(三)   分析   

以上部分的分析配合下面這張圖就更清晰了

以上圖片來自:NFC framework introduce(一)

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章