[转载][NFC]NFC启动流程1

https://blog.csdn.net/weixin_38503885/article/details/80927541

  前面介绍过NFC相关的Spec后,从本章节开始,将进入Android AOSP NFC Frameworks部分的学习。

 

      代码主要的路径存放在:

      Android5.0\packages\apps\Nfc 包含以下目录:

             Assets:含start.png

             etc:nfcee_access实例

             nci:nci规范中的接口和驱动

             nxp:nxp芯片对应的接口和驱动

             res:app用到的图片,字串资源等

             src:主要代码流程

             tests:Google提供的部分测试程序

      Android5.0\packages\apps\Settings\src\com\android\settings\nfc是Setting中关于NFC的代码。

 

      NFC Application的启动不同于Wi-Fi及Wi-Fi P2P等service。

 

      NFC Application对应的AndroidManifest.xml文件中含有关键信息如下:

    <applicationandroid: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 application启动的机制。此处不详细的分析,列举对应的代码,方便大家学习:

     Android5.0\frameworks\base\services\core\java\com\android\server\am\ActivityManagerService.java

 public void systemReady(final RunnablegoingCallback) {
          ....
          if (mFactoryTest !=FactoryTest.FACTORY_TEST_LOW_LEVEL) {
                try {
                    List apps =AppGlobals.getPackageManager().
                       getPersistentApplications(STOCK_PM_FLAGS);
                    if (apps != null) {
                        int N = apps.size();
                        int i;
                        for (i=0; i<N; i++){
                            ApplicationInfoinfo
                                =(ApplicationInfo)apps.get(i);
                            if (info != null &&
                                   !info.packageName.equals("android")) {
                               addAppLocked(info, false, null /* ABI override */);
                            }
                        }
                    }
                } catch (RemoteException ex) {
                    // pm is in same process,this will never happen.
                }
         }
          ...
}

 

      继续分析addAppLocked()

final ProcessRecordaddAppLocked(ApplicationInfo info, boolean isolated,
            String abiOverride) {
          ...
        if (app.thread == null &&mPersistentStartingProcesses.indexOf(app) < 0) {
           mPersistentStartingProcesses.add(app);
            startProcessLocked(app, "addedapplication", app.processName, abiOverride,
                    null /* entryPoint */, null /*entryPointArgs */);
        }
          ...
}

 

      最终会call到NfcApplication.java中的NfcApplication()构造函数,其中的onCreate()会被调用到。   

@Override
    public void onCreate() {
        super.onCreate();
        boolean isMainProcess = false;
        // We start a service in a separateprocess to do
        // handover transfer. We don't want toinstantiate an NfcService
        // object in those cases, hence checkthe name of the process
        // to determine whether we're the mainNFC service, or the
        // handover process
        ActivityManager am =(ActivityManager)this.getSystemService(ACTIVITY_SERVICE);
        List processes =am.getRunningAppProcesses();
        Iterator i = processes.iterator();
        while (i.hasNext()) {
            //检查当前运行的App名字是否为"com.android.nfc",如果名字相同,则表示当前启动的程序是主程序
            RunningAppProcessInfo appInfo =(RunningAppProcessInfo)(i.next());
            if (appInfo.pid == Process.myPid()){
               isMainProcess =  (NFC_PROCESS.equals(appInfo.processName));
                break;
            }
        }
        if (UserHandle.myUserId() == 0&& isMainProcess) {</span>
            //启动NfcService
           mNfcService = new NfcService(this);
            HardwareRenderer.enableForegroundTrimming();
        }
    }




      当调用了new NfcService()之后,后面会依次创建各个Service。

 

     在进行后续分析前,简单的列举一下NFC的类图,方便后续的理解:

     上层APP主要透过调用android.nfc.tech及android.nfc的接口来实现期望的功能;而android.nfc.tech和android.nfc透过AIDL的方式调用到NfcService中的接口。Framework中NfcService透过JNI与底层NFC Driver进行沟通,实现发送命令和接收event功能。

 

 

 

 

        在进入NFCService.java前,需要对整个系统的架构有个初步的了解。

 

        DeviceHost.java定义了目前几乎NFC需要的全部interface和API。不同的厂家依据DeviceHost.java提供的interface,实现对应的内容,就可以和上层app进行沟通了。

 

 

 

 

正式进入NFCService.java,开始NFC framework探索, jiu~~~~



        接上篇文章内容,进入NfcService后,就开始启动各种Services,Hold on,一大波代码马上到来:


   
   
  1. {
  2. mUserId = ActivityManager.getCurrentUser();
  3. mContext = nfcApplication;
  4. //@paul: Tag相关; extend INfcTag;最终调用到NativeNfcTag
  5. mNfcTagService = new TagService();
  6. //@paul: 上层APP 调用 NFC 功能时, 中间变量adapter;extend INfcAdaptor;最终调用到NfcAdaptor
  7. mNfcAdapter = new NfcAdapterService();
  8. Log.i(TAG, "Starting NFC service");
  9. sService = this;
  10. //@paul: NFC与屏幕解锁的关系,含OFF / ON_LOCK / ON_UNLOCK
  11. mScreenStateHelper = new ScreenStateHelper(mContext);
  12. mContentResolver = mContext.getContentResolver();
  13. //@paul: 底层Driver 相关的JNI 接口
  14. mDeviceHost = new NativeNfcManager(mContext, this);
  15. //@paul: 还不懂
  16. mNfcUnlockManager = NfcUnlockManager.getInstance();
  17. //@paul: 和handover 相关接口;主要是bluetooth, 实际上wifi 也是可以实现的
  18. mHandoverManager = new HandoverManager(mContext);
  19. boolean isNfcProvisioningEnabled = false;
  20. try {
  21. isNfcProvisioningEnabled = mContext.getResources().getBoolean(
  22. R.bool.enable_nfc_provisioning);
  23. } catch (NotFoundException e) {
  24. }
  25. //@paul: 设备是否在setup wizard阶段支持接收NFC 数据
  26. if (isNfcProvisioningEnabled) {
  27. mInProvisionMode = Settings.Secure.getInt(mContentResolver,
  28. Settings.Global.DEVICE_PROVISIONED, 0) == 0;
  29. } else {
  30. mInProvisionMode = false;
  31. }
  32. //@paul: 收到NFC 消息处理流程, 最终调用到dispatchTag()
  33. mNfcDispatcher = new NfcDispatcher(mContext, mHandoverManager, mInProvisionMode);
  34. //@paul: 基于LLCP 连接的服务,含NdefPushService/SnepService/P2pEventManager
  35. //@paul: 此类会定义doPut/doGet, 后续还会提到
  36. mP2pLinkManager = new P2pLinkManager(mContext, mHandoverManager,
  37. mDeviceHost.getDefaultLlcpMiu(), mDeviceHost.getDefaultLlcpRwSize());
  38. //@paul: 获取shared_pref 信息,一般存储位置在/data/data/<包名>/shared_prefs
  39. mPrefs = mContext.getSharedPreferences(PREF, Context.MODE_PRIVATE);
  40. mPrefsEditor = mPrefs.edit();
  41. //@paul: 和security相关,主要是读取解析/etc/nfcee_access.xml文件
  42. mNfceeAccessControl = new NfceeAccessControl(mContext);
  43. mState = NfcAdapter.STATE_OFF;
  44. //@paul: 依prefs 文件定义,检查NdefPush 是否enable
  45. mIsNdefPushEnabled = mPrefs.getBoolean(PREF_NDEF_PUSH_ON, NDEF_PUSH_ON_DEFAULT);
  46. setBeamShareActivityState(mIsNdefPushEnabled);
  47. mIsDebugBuild = "userdebug".equals(Build.TYPE) || "eng".equals(Build.TYPE);
  48. //@paul: 电源管理模块,主要是屏幕状态与NFC 是否响应有关系
  49. mPowerManager = (PowerManager) mContext.getSystemService(Context.POWER_SERVICE);
  50. //@paul: 获取WakeLock
  51. // 步骤:1.获取powermanager 实例
  52. // 2.生成实例: new WakeLock
  53. // 3.通过acquire() 获取锁
  54. mRoutingWakeLock = mPowerManager.newWakeLock(
  55. PowerManager.PARTIAL_WAKE_LOCK, "NfcService:mRoutingWakeLock");
  56. //@paul: 屏幕锁
  57. mKeyguard = (KeyguardManager) mContext.getSystemService(Context.KEYGUARD_SERVICE);
  58. mUserManager = (UserManager) mContext.getSystemService(Context.USER_SERVICE);
  59. mScreenState = mScreenStateHelper.checkScreenState();
  60. //@Paul: 将NFC 加入到系统service中
  61. ServiceManager.addService(SERVICE_NAME, mNfcAdapter);
  62. // Intents for all users
  63. //@paul: 注册屏幕亮/灭,用户激活和切换
  64. IntentFilter filter = new IntentFilter(Intent.ACTION_SCREEN_OFF);
  65. filter.addAction(Intent.ACTION_SCREEN_ON);
  66. filter.addAction(Intent.ACTION_USER_PRESENT);
  67. filter.addAction(Intent.ACTION_USER_SWITCHED);
  68. registerForAirplaneMode(filter);
  69. mContext.registerReceiverAsUser(mReceiver, UserHandle.ALL, filter, null, null);
  70. IntentFilter ownerFilter = new IntentFilter(Intent.ACTION_EXTERNAL_APPLICATIONS_AVAILABLE);
  71. ownerFilter.addAction(Intent.ACTION_EXTERNAL_APPLICATIONS_UNAVAILABLE);
  72. mContext.registerReceiver(mOwnerReceiver, ownerFilter);
  73. //@paul: 关注程序安装和卸载
  74. ownerFilter = new IntentFilter();
  75. ownerFilter.addAction(Intent.ACTION_PACKAGE_ADDED);
  76. ownerFilter.addAction(Intent.ACTION_PACKAGE_REMOVED);
  77. ownerFilter.addDataScheme( "package");
  78. mContext.registerReceiver(mOwnerReceiver, ownerFilter);
  79. updatePackageCache();
  80. PackageManager pm = mContext.getPackageManager();
  81. //@paul: 判断系统是否支持卡模拟
  82. mIsHceCapable = pm.hasSystemFeature(PackageManager.FEATURE_NFC_HOST_CARD_EMULATION);
  83. if (mIsHceCapable) {
  84. mCardEmulationManager = new CardEmulationManager(mContext);
  85. }
  86. mForegroundUtils = ForegroundUtils.getInstance();
  87. //@paul: 开始执行NFC , 参数TASK_BOOT
  88. new EnableDisableTask().execute(TASK_BOOT); // do blocking boot tasks
  89. }

        看完这么多的代码,是不是还不确定各个部分的意义。没有关系,继续挖。


1. TagService

        此部分实现的接口都在INfcTag.aidl中定义,接口如下:


   
   
  1. {
  2. int close(int nativeHandle);
  3. int connect(int nativeHandle, int technology);
  4. int reconnect(int nativeHandle);
  5. int[] getTechList( int nativeHandle);
  6. boolean isNdef(int nativeHandle);
  7. boolean isPresent(int nativeHandle);
  8. TransceiveResult transceive(int nativeHandle, in byte[] data, boolean raw);
  9. NdefMessage ndefRead(int nativeHandle);
  10. int ndefWrite(int nativeHandle, in NdefMessage msg);
  11. int ndefMakeReadOnly(int nativeHandle);
  12. boolean ndefIsWritable(int nativeHandle);
  13. int formatNdef(int nativeHandle, in byte[] key);
  14. Tag rediscover(int nativehandle);
  15. int setTimeout(int technology, int timeout);
  16. int getTimeout(int technology);
  17. void resetTimeouts();
  18. boolean canMakeReadOnly(int ndefType);
  19. int getMaxTransceiveLength(int technology);
  20. boolean getExtendedLengthApdusSupported();
  21. }

        以其中connect()函数为例,解释一下此部分的流程和逻辑,其余的函数基本上可以参考connect()函数:


   
   
  1. @Override
  2. public int connect(int nativeHandle, int technology) throws RemoteException {
  3. //@paul: 检查manifest中是否有nfc操作权限
  4. NfcPermissions.enforceUserPermissions(mContext);
  5. TagEndpoint tag = null;
  6. //@paul: 判断NFC是否启动,在执行enableInternal()时,条件为真
  7. if (!isNfcEnabled()) {
  8. return ErrorCodes.ERROR_NOT_INITIALIZED;
  9. }
  10. /* find the tag in the hmap */
  11. tag = (TagEndpoint) findObject(nativeHandle);
  12. if (tag == null) {
  13. return ErrorCodes.ERROR_DISCONNECT;
  14. }
  15. //@paul: 判断Tag是否还在范围内,NativeNfcTag会自动更新连接的标记
  16. if (!tag.isPresent()) {
  17. return ErrorCodes.ERROR_DISCONNECT;
  18. }
  19. // Note that on most tags, all technologies are behind a single
  20. // handle. This means that the connect at the lower levels
  21. // will do nothing, as the tag is already connected to that handle.
  22. //@paul: NativeNfcTag中定义了connect函数,最终调用到doConnect()
  23. if (tag.connect(technology)) {
  24. return ErrorCodes.SUCCESS;
  25. } else {
  26. return ErrorCodes.ERROR_DISCONNECT;
  27. }
  28. }

        上述函数中的tag.connect()最终调用到NativeNfcTag.java中的connect,此处的调用就是aidl实现的。 下面以NXP的流程介绍一下NativeNfcTag.java中的connect。


   
   
  1. @Override
  2. public synchronized boolean connect(int technology) {
  3. return connectWithStatus(technology) == 0;
  4. }

        看起来还要继续挖:


   
   
  1. private native int doConnect(int handle);
  2. public synchronized int connectWithStatus(int technology) {
  3. if (technology == TagTechnology.NFC_B) {
  4. // Not supported by PN544
  5. //@paul: 芯片特性,不支持怎么的
  6. return - 1;
  7. }
  8. if (mWatchdog != null) {
  9. mWatchdog.pause();
  10. }
  11. int status = - 1;
  12. for ( int i = 0; i < mTechList.length; i++) {
  13. if (mTechList[i] == technology) {
  14. // Get the handle and connect, if not already connected
  15. if (mConnectedHandle != mTechHandles[i]) {
  16. // We're not yet connected to this handle, there are
  17. // a few scenario's here:
  18. // 1) We are not connected to anything yet - allow
  19. // 2) We are connected to a technology which has
  20. // a different handle (multi-protocol tag); we support
  21. // switching to that.
  22. if (mConnectedHandle == - 1) {
  23. // Not connected yet
  24. //@paul: 如果是没有连接过,则直接调用到doConnect()
  25. status = doConnect(mTechHandles[i]);
  26. } else {
  27. // Connect to a tech with a different handle
  28. status = reconnectWithStatus(mTechHandles[i]);
  29. }
  30. if (status == 0) {
  31. mConnectedHandle = mTechHandles[i];
  32. mConnectedTechIndex = i;
  33. }
  34. } else {
  35. ......
  36. }
  37. break;
  38. }
  39. }
  40. if (mWatchdog != null) {
  41. mWatchdog.doResume();
  42. }
  43. return status;
  44. }

        看了这么多,重要的就是最后的doConnect(),这个是JNI的一个接口:


   
   
  1. { "doConnect", "(I)I",
  2. ( void *)com_android_nfc_NativeNfcTag_doConnect},

        继续挖吧:


   
   
  1. static jint com_android_nfc_NativeNfcTag_doConnect(JNIEnv *e,jobject o, phLibNfc_Handle handle)
  2. {
  3. jint status;
  4. struct nfc_jni_callback_data cb_data;
  5. phLibNfc_sRemoteDevInformation_t* pRemDevInfo = NULL;
  6. CONCURRENCY_LOCK();
  7. /* Create the local semaphore */
  8. if (!nfc_cb_data_init(&cb_data, &pRemDevInfo))
  9. {
  10. status = NFCSTATUS_NOT_ENOUGH_MEMORY;
  11. goto clean_and_return;
  12. }
  13. TRACE( "phLibNfc_RemoteDev_Connect(RW)");
  14. REENTRANCE_LOCK();
  15. storedHandle = handle;
  16. status = phLibNfc_RemoteDev_Connect(handle, nfc_jni_connect_callback,( void *)&cb_data);
  17. ......
  18. /* Connect Status */
  19. if(status != NFCSTATUS_SUCCESS)
  20. {
  21. goto clean_and_return;
  22. }
  23. // Success, set poll & act bytes
  24. set_target_pollBytes(e, o, pRemDevInfo);
  25. set_target_activationBytes(e, o, pRemDevInfo);
  26. clean_and_return:
  27. nfc_cb_data_deinit(&cb_data);
  28. CONCURRENCY_UNLOCK();
  29. return status;
  30. }
        好吧,你也不想看了,我也看不到了,最后这些API都是在nxp提供的so中export出来的,目前还看不到源码。


2. NfcAdaptorService

        此部分定义的接口主要是提供给上层,接口定义在INfcAdaptor.aidl中,目的是透过该接口,可以直接操作Framework中的API,最终调用到JNI层。INfcAdaptor中接口如下:


   
   
  1. {
  2. //@paul: 获取NfcService中初始化的mNfcTagService
  3. INfcTag getNfcTagInterface();
  4. //@paul: 获取NfcService中初始化的mCardEmulationInterface
  5. INfcCardEmulation getNfcCardEmulationInterface();
  6. //@paul: AOSP默认不支持
  7. INfcAdapterExtras getNfcAdapterExtrasInterface(in String pkg);
  8. //@paul: 获取NFC当前状态
  9. int getState();
  10. //@paul: 关闭NFC功能
  11. boolean disable(boolean saveState);
  12. //@paul: 启动NFC功能
  13. boolean enable();
  14. //@paul: 更新prefs中ndef值,同时启动p2p发送功能service
  15. boolean enableNdefPush();
  16. //@paul: 更新prefs中ndef值,同时关闭p2p发送功能service
  17. boolean disableNdefPush();
  18. //@paul: NdefPush功能是否打开
  19. boolean isNdefPushEnabled();
  20. //@paul: 启动底层polling流程,最终会调用到JNI,到Driver
  21. void pausePolling(int timeoutInMs);
  22. void resumePolling();
  23. //@paul: 写APP时候的常用方法,设置此函数后,收到的消息会只在前台的APP处理
  24. void setForegroundDispatch(in PendingIntent intent,in IntentFilter[] filters, in TechListParcel techLists);
  25. //@paul: 上层APP设置回调,用于Beam过程中产生shareData
  26. void setAppCallback(in IAppCallback callback);
  27. //@paul: 启动Beam流程
  28. oneway void invokeBeam();
  29. oneway void invokeBeamInternal(in BeamShareData shareData);
  30. //@paul: 分发收到的tag信息
  31. void dispatch(in Tag tag);
  32. void setReaderMode (IBinder b, IAppCallback callback, int flags, in Bundle extras);
  33. void setP2pModes(int initatorModes, int targetModes);
  34. void addNfcUnlockHandler(INfcUnlockHandler unlockHandler, in int[] techList);
  35. void removeNfcUnlockHandler(INfcUnlockHandler unlockHandler);
  36. }


3. ScreenStateHelper

        这个类主要作用是检查当前屏幕状态,原因是NFC的一些应用需要在屏灭以及锁屏的情况下也能应用(例如刷公交卡),主要的函数如下:


   
   
  1. int checkScreenState() {
  2. //TODO: fix deprecated api
  3. if (!mPowerManager.isScreenOn()) {
  4. //@paul: 依据pm提供的接口判断屏幕是否点亮
  5. return SCREEN_STATE_OFF;
  6. } else if (mKeyguardManager.isKeyguardLocked()) {
  7. //@paul: 依据KeyguardManager判断是否在解锁状态
  8. return SCREEN_STATE_ON_LOCKED;
  9. } else {
  10. //@paul: 上述都不是,则设备处于屏幕解锁状态
  11. return SCREEN_STATE_ON_UNLOCKED;
  12. }
  13. }


4.NativeNfcManager

        此类是各chip vendor实现,目前AOSP下包含了nxp和nci两类。下面的例子都是以nxp的接口为例,nci接口也类似。

        此类的开头就有以下的信息,表示实例化该类时,先加载且只加载一次libnfc_jni.so:


   
   
  1. static {
  2. System.loadLibrary( "nfc_jni");
  3. }


        进入构造函数后:


   
   
  1. public NativeNfcManager(Context context, DeviceHostListener listener) {
  2. mListener = listener;
  3. initializeNativeStructure();
  4. mContext = context;
  5. }

        其中initializeNativeStructure()是native函数,其定义在:

   {"initializeNativeStructure", "()Z",(void *)com_android_nfc_NfcManager_init_native_struc},
   
   

        继续分析:


   
   
  1. static jboolean com_android_nfc_NfcManager_init_native_struc(JNIEnv *e, jobject o)
  2. {
  3. ...
  4. TRACE( "****** Init Native Structure ******");
  5. /* Initialize native structure */
  6. nat = (nfc_jni_native_data*) malloc( sizeof(struct nfc_jni_native_data));
  7. ...
  8. /* Initialize native cached references */
  9. //@paul: 定义native层和framework沟通的API
  10. cached_NfcManager_notifyNdefMessageListeners = e->GetMethodID(cls,
  11. "notifyNdefMessageListeners", "(Lcom/android/nfc/dhimpl/NativeNfcTag;)V");
  12. cached_NfcManager_notifyLlcpLinkActivation = e->GetMethodID(cls,
  13. "notifyLlcpLinkActivation", "(Lcom/android/nfc/dhimpl/NativeP2pDevice;)V");
  14. cached_NfcManager_notifyLlcpLinkDeactivated = e->GetMethodID(cls,
  15. "notifyLlcpLinkDeactivated", "(Lcom/android/nfc/dhimpl/NativeP2pDevice;)V");
  16. cached_NfcManager_notifyRfFieldActivated = e->GetMethodID(cls,
  17. "notifyRfFieldActivated", "()V");
  18. cached_NfcManager_notifyRfFieldDeactivated = e->GetMethodID(cls,
  19. "notifyRfFieldDeactivated", "()V");
  20. if(nfc_jni_cache_object(e, "com/android/nfc/dhimpl/NativeNfcTag",&(nat->cached_NfcTag)) == -1)
  21. {
  22. ALOGD( "Native Structure initialization failed");
  23. return FALSE;
  24. }
  25. if(nfc_jni_cache_object(e, "com/android/nfc/dhimpl/NativeP2pDevice",&(nat->cached_P2pDevice)) == -1)
  26. {
  27. ALOGD( "Native Structure initialization failed");
  28. return FALSE;
  29. }
  30. TRACE( "****** Init Native Structure OK ******");
  31. return TRUE;
  32. }

        在以其中cached_NfcManager_notifyNdefMessageListeners引用为例,该引用在nfc_jni_Discovery_notification_callback中以下列方式被调用,从而将底层的消息notify到上层APP:


   
   
  1. /* Notify manager that new a tag was found */
  2. e->CallVoidMethod(nat->manager, cached_NfcManager_notifyNdefMessageListeners, tag.get());
  3. if(e->ExceptionCheck())
  4. {
  5. ALOGE( "Exception occurred");
  6. kill_client(nat);
  7. }

        以其中enableDiscovery()函数为例,说明一下该类的基本操作流程:


   
   
  1. //@paul: native接口,
  2. private native void doEnableDiscovery(int techMask,
  3. boolean enableLowPowerPolling,
  4. boolean enableReaderMode,
  5. boolean restart);
  6. @Override
  7. public void enableDiscovery(NfcDiscoveryParameters params, boolean restart) {
  8. doEnableDiscovery(params.getTechMask(), params.shouldEnableLowPowerDiscovery(),params.shouldEnableReaderMode(), restart);
  9. }


4.HandoverManager

        此类主要负责NFC到其他传输媒介的跳转,例如Wi-Fi/BT,只是目前AOSP只有是做BT的跳转。Wi-Fi还没有定义Spec,所以还没有这部分的代码。关于BT Handover的spec,可以参考NFC简单介绍中Spec下载章节。


        后续会继续讲解Handover的流程,此部分就不做详细介绍。


5.NfcDispatcher

        此类主要是收到底层Tag消息后,依据tag的类型进行内容解析和数据分发。


   
   
  1. public int dispatchTag(Tag tag) {
  2. ...
  3. //@paul: APP在调用setForegroundDispatch()时,会赋值下列变量
  4. synchronized ( this) {
  5. overrideFilters = mOverrideFilters;
  6. overrideIntent = mOverrideIntent;
  7. overrideTechLists = mOverrideTechLists;
  8. provisioningOnly = mProvisioningOnly;
  9. }
  10. //@paul: 屏幕解锁相关流程
  11. boolean screenUnlocked = false;
  12. if (!provisioningOnly &&
  13. mScreenStateHelper.checkScreenState() == ScreenStateHelper.SCREEN_STATE_ON_LOCKED) {
  14. screenUnlocked = handleNfcUnlock(tag);
  15. if (!screenUnlocked) {
  16. return DISPATCH_FAIL;
  17. }
  18. }
  19. ...
  20. //@paul: 如果前台Activity启动分发功能,则只需要处理前台分发相关工作即可
  21. if (tryOverrides(dispatch, tag, message, overrideIntent, overrideFilters,
  22. overrideTechLists)) {
  23. return screenUnlocked ? DISPATCH_UNLOCK : DISPATCH_SUCCESS;
  24. }
  25. //@paul: 判断是否为Handover事件
  26. if (mHandoverManager.tryHandover(message)) {
  27. if (DBG) Log.i(TAG, "matched BT HANDOVER");
  28. return screenUnlocked ? DISPATCH_UNLOCK : DISPATCH_SUCCESS;
  29. }
  30. //@paul: 判断是否为Wifi的handover
  31. if (NfcWifiProtectedSetup.tryNfcWifiSetup(ndef, mContext)) {
  32. if (DBG) Log.i(TAG, "matched NFC WPS TOKEN");
  33. return screenUnlocked ? DISPATCH_UNLOCK : DISPATCH_SUCCESS;
  34. }
  35. //@paul: 判断是否为ACTION_NDEF_DISCOVERD
  36. if (tryNdef(dispatch, message, provisioningOnly)) {
  37. return screenUnlocked ? DISPATCH_UNLOCK : DISPATCH_SUCCESS;
  38. }
  39. //@paul: 只有在NDEF格式下,才会判断此流程
  40. if (screenUnlocked) {
  41. // We only allow NDEF-based mimeType matching in case of an unlock
  42. return DISPATCH_UNLOCK;
  43. }
  44. if (provisioningOnly) {
  45. // We only allow NDEF-based mimeType matching
  46. return DISPATCH_FAIL;
  47. }
  48. //@paul: 判断是否为ACTION_TECH_DISCOVERD
  49. if (tryTech(dispatch, tag)) {
  50. return DISPATCH_SUCCESS;
  51. }
  52. //@paul: 设置intent为ACTION_TAG_DISCOVERD
  53. dispatch.setTagIntent();
  54. //@paul: 查询对ACTION_TAG_DISCOVERD感兴趣的activity,并尝试启动
  55. if (dispatch.tryStartActivity()) {
  56. if (DBG) Log.i(TAG, "matched TAG");
  57. return DISPATCH_SUCCESS;
  58. }
  59. if (DBG) Log.i(TAG, "no match");
  60. return DISPATCH_FAIL;
  61. }

6.P2pLinkManager

        此类主要包含基于LLCP连接的server,构造函数中会创建后续需要的类:


   
   
  1. public P2pLinkManager(Context context, HandoverManager handoverManager, int defaultMiu,int defaultRwSize) {
  2. //@paul: 创建NdefPushServer()
  3. mNdefPushServer = new NdefPushServer(NDEFPUSH_SAP, mNppCallback);
  4. //@paul: 创建SnepServer()
  5. mDefaultSnepServer = new SnepServer(mDefaultSnepCallback, defaultMiu, defaultRwSize);
  6. //@paul: 创建HandoverServer()
  7. mHandoverServer = new HandoverServer(HANDOVER_SAP, handoverManager, mHandoverCallback);
  8. //@paul: 创建EchoServer()
  9. if (ECHOSERVER_ENABLED) {
  10. mEchoServer = new EchoServer();
  11. } else {
  12. mEchoServer = null;
  13. }
  14. mPackageManager = context.getPackageManager();
  15. mContext = context;
  16. //@paul: 创建P2pEventManager()
  17. mEventListener = new P2pEventManager(context, this);
  18. mHandler = new Handler( this);
  19. ...
  20. }


        其中会分别创建NdefPushServer,SnepServer,HandoverServer,P2pEventManager这几个重要类。

        NdefPushServer:启动NPP Server,等待Client连接

        SnepServer:启动NPP Server,等待Client连接

        HandoverServer:启动Handover Server,等待Client连接

        P2pEventManager: 启动Event Manager,用于将底层消息notify到UI或者上层APP


        下面分别以SnepServer,P2pEventManager为例,简单说明一下流程(也会补充一下handle的流程)。


        SnepServer的构造函数调用后,会被调用到启动函数start():


   
   
  1. //@paul: 启动SNEP server
  2. public void start() {
  3. synchronized (SnepServer. this) {
  4. if (DBG) Log.d(TAG, "start, thread = " + mServerThread);
  5. if (mServerThread == null) {
  6. if (DBG) Log.d(TAG, "starting new server thread");
  7. mServerThread = new ServerThread();
  8. //@paul: ServerThread.run()
  9. mServerThread.start();
  10. mServerRunning = true;
  11. }
  12. }
  13. }


        其中ServerThread流程如下:


   
   
  1. @Override
  2. public void run() {
  3. ...
  4. while (threadRunning) {
  5. if (DBG) Log.d(TAG, "about create LLCP service socket");
  6. try {
  7. synchronized (SnepServer. this) {
  8. //@paul: 创建llcp 服务端socket
  9. //@paul: 包含创建socket,绑定并监听socket
  10. mServerSocket = NfcService.getInstance().createLlcpServerSocket(mServiceSap,
  11. mServiceName, mMiu, mRwSize, 1024);
  12. }
  13. ...
  14. while (threadRunning) {
  15. ...
  16. if (DBG) Log.d(TAG, "about to accept");
  17. //@paul: 阻塞等待客户端连接
  18. //@paul: 一个server 端,可以有多个客户端连接
  • 0
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
在Linux系统中,可以使用libnfc库来调用NFC(Near Field Communication)设备。libnfc是一个开源的NFC库,支持多种NFC芯片和读写器设备。 以下是使用libnfc库在Linux系统中调用NFC设备的基本步骤: 1. 安装libnfc库。可以使用以下命令在Ubuntu系统中安装libnfc库: ``` sudo apt-get install libnfc-dev ``` 2. 连接NFC设备。将NFC设备连接到计算机的USB接口或其他接口上,并确认系统已经正确识别了设备。 3. 编写程序。使用C或C++等编程语言编写程序,调用libnfc库中的函数来实现对NFC设备的读写操作。以下是一个简单的例子: ```c #include <stdio.h> #include <stdlib.h> #include <nfc/nfc.h> int main(int argc, char **argv) { nfc_device *pnd; nfc_context *context; nfc_init(&context); if (context == NULL) { printf("Unable to init libnfc (malloc)\n"); exit(EXIT_FAILURE); } pnd = nfc_open(context, NULL); if (pnd == NULL) { printf("Unable to open NFC device\n"); exit(EXIT_FAILURE); } if (nfc_initiator_init(pnd) < 0) { nfc_perror(pnd, "nfc_initiator_init"); exit(EXIT_FAILURE); } printf("NFC reader opened\n"); // TODO: 进行读写操作 nfc_close(pnd); nfc_exit(context); return 0; } ``` 在上述代码中,首先使用nfc_init()函数初始化libnfc库和NFC设备的上下文环境,然后使用nfc_open()函数打开NFC设备。接着使用nfc_initiator_init()函数初始化NFC设备,完成NFC设备的初始化工作。最后,调用nfc_close()函数关闭NFC设备,并使用nfc_exit()函数释放libnfc库和NFC设备的上下文环境。 4. 编译程序。使用gcc等编译器编译程序,并链接libnfc库。以下是一个简单的编译命令: ``` gcc -o nfc_demo nfc_demo.c -lnfc ``` 在编译完成后,可以使用./nfc_demo命令运行程序,并进行NFC设备的读写操作。 需要注意的是,具体的程序和操作方法可能会因不同的NFC设备和应用场景而有所不同,需要根据具体情况进行调整。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值