NFC学习——NfcService 启动过程分析

在机器开机过程中,可以抓取到以下的正常logcat信息:

[html]  view plain copy
  1. //setp1  
  2. I/NfcService( 3809): Starting NFC service  
  3. D/NFCJNI  ( 3809): NFC Service : loading JNI  
  4. I/RegisteredComponentCache( 3809): ComponentInfo: ResolveInfo{41344108   
  5. com.android.apps.tag.TagViewer p=0 o=0 m=0x108000}, techs: android.nfc.tech.Ndef,   
  6. W/NfceeAccess( 3809): could not find /etc/nfcee_access.xml, no NFCEE access allowed  
  7. I/NfceeAccess( 3809): read 0 signature(s) for NFCEE access  
  8. D/NfcService( 3809): checking on firmware download  

下面是硬件不支持NFC的异常logcat信息:
[html]  view plain copy
  1. I/NfcService( 3485): Starting NFC service  
  2. D/NFCJNI  ( 3485): NFC Service : loading JNI  
  3. W/NfceeAccess( 3485): could not find /etc/nfcee_access.xml, no NFCEE access allowed  
  4. I/NfceeAccess( 3485): read 0 signature(s) for NFCEE access  
  5. D/NfcService( 3485): checking on firmware download  
  6. D/NfcService( 3485): NFC is on. Doing normal stuff  
  7. I/NfcService( 3485): Enabling NFC  
  8. D/NFCJNI  ( 3485): Start Initialization  
  9. E/NFCJNI  ( 3485): hw_get_module() failed.  
  10. D/NFCJNI  ( 3485): Terminating client thread...  
  11. W/NfcService( 3485): Error enabling NFC  
来看正常logcat信息setp1,NfcService 是application,它的onCreate()方法:

[html]  view plain copy
  1. @Override  
  2.     public void onCreate() {  
  3.         super.onCreate();  
  4.   
  5.         mNfcTagService = new TagService();  
  6.         mNfcAdapter = new NfcAdapterService();  
  7.         mExtrasService = new NfcAdapterExtrasService();  
  8.   
  9.         Log.i(TAG, "Starting NFC service");  
  10.           
  11.         //setp2:NFC Service : loading JNI  
  12.         mDeviceHost = new NativeNfcManager(this, this);  
  13.   
  14.         HandoverManager handoverManager = new HandoverManager(mContext);  
  15.           
  16.     //NfcDispatcher主要负责tag消息处理,并派发Intent消息,启动Activity。  
  17.     mNfcDispatcher = new NfcDispatcher(this, handoverManager);   
  18.           
  19.     mP2pLinkManager = new P2pLinkManager(mContext, handoverManager);   
  20.     mSecureElement = new NativeNfcSecureElement(mContext);                   
  21.           
  22.         //setp3:could not find /etc/nfcee_access.xml, no NFCEE access allowed   
  23.         mNfceeAccessControl = new NfceeAccessControl(this);   
  24.           
  25.    //把mNfcAdapter 作为Service 添加到系统服务中,ServiceManager.getService("nfc")可以获取到binder                        
  26.         ServiceManager.addService(SERVICE_NAME, mNfcAdapter);  
  27.           
  28.     updatePackageCache();           
  29.           
  30.     //setp4:checking on firmware download          
  31.     new EnableDisableTask().execute(TASK_BOOT); // do blocking boot tasks   
  32.     }  
Setp2:NFC Service loading JNI,这一部分是在NativeNfcManager.java中处理的  

[html]  view plain copy
  1. //加载jni编译生成的nfc_jni.so.通过NativeNfcManager调用jni部分  
  2. static {  
  3.         System.loadLibrary("nfc_jni");  
  4.     }  
  5.   
  6. //NativeNfcManager 构造方法  
  7. public NativeNfcManager(Context context, DeviceHostListener listener) {  
  8.         mListener = listener;  
  9.   
  10.         //setp2-1:com_android_nfc_NativeNfcManager.cpp的native方法  
  11.         //com_android_nfc_NfcManager_init_native_struc(JNIEnv *e, jobject o)  
  12.         initializeNativeStructure();  
  13.         mContext = context;  
  14.     }  
Setp2-1:com_android_nfc_NfcManager_init_native_struc(),初始化nfc_jni_native_data结构体

[html]  view plain copy
  1. static jboolean com_android_nfc_NfcManager_init_native_struc(JNIEnv *e, jobject o)  
  2. {   
  3.   /* Initialize native structure */     
  4.   // 涉及到nfc_jni_native_date结构体的定义在com_android_nfc.h  
  5.    nat = (nfc_jni_native_data*)malloc(sizeof(struct nfc_jni_native_data));  
  6.    if(nat == NULL)  
  7.    {  
  8.       ALOGD("malloc of nfc_jni_native_data failed");  
  9.       return FALSE;     
  10.    }  
  11.    memset(nat, 0, sizeof(*nat));  
  12.   
  13.    /* Initialize native cached references */   
  14.    //通过jni 调用java 层的方法  
  15.    cached_NfcManager_notifyNdefMessageListeners = e->GetMethodID(cls,  
  16.       "notifyNdefMessageListeners","(Lcom/android/nfc/nxp/NativeNfcTag;)V");  
  17.   
  18.    cached_NfcManager_notifyTransactionListeners = e->GetMethodID(cls,  
  19.       "notifyTransactionListeners", "([B)V");  
  20.            
  21.    cached_NfcManager_notifyLlcpLinkActivation = e->GetMethodID(cls,  
  22.       "notifyLlcpLinkActivation","(Lcom/android/nfc/nxp/NativeP2pDevice;)V");  
  23.            
  24.    cached_NfcManager_notifyLlcpLinkDeactivated = e->GetMethodID(cls,  
  25.       "notifyLlcpLinkDeactivated","(Lcom/android/nfc/nxp/NativeP2pDevice;)V");   
  26.         
  27.    cached_NfcManager_notifyTargetDeselected = e->GetMethodID(cls,  
  28.       "notifyTargetDeselected","()V");     
  29.      
  30.    //nfc_jni_cache_object 原型在com_android_nfc.cpp中,有什么作用,做什么动作暂时没有搞清楚?  
  31.    if(nfc_jni_cache_object(e,"com/android/nfc/nxp/NativeNfcTag",&(nat->cached_NfcTag)) == -1)  
  32.    {  
  33.       ALOGD("Native Structure initialization failed");  
  34.       return FALSE;  
  35.    }  
  36.            
  37.    if(nfc_jni_cache_object(e,"com/android/nfc/nxp/NativeP2pDevice",&(nat->cached_P2pDevice)) == -1)  
  38.    {  
  39.       ALOGD("Native Structure initialization failed");  
  40.       return FALSE;     
  41.    }  
  42.    TRACE("****** Init Native Structure OK ******");  
  43.    return TRUE;  
  44. }  
Setp3:解析/etc/nfcee_access.xml,NfceeAccessControl.java主要用来解析nfcee_access,xml并做一些证书和安全方面的check。nfcee_access.xml的文件内容:

[html]  view plain copy
  1. <?xml version="1.0" encoding="utf-8"?>  
  2. <resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">  
  3.     <!-- The built in list of signatures and package names that are allowed  
  4.     access to the NFCEE (Secure Element).  
  5.   
  6.     Format:  
  7.     <signer android:signature="SIGNATURE">  
  8.         <package android:name="PACKAGE_NAME" />  
  9.         ...  
  10.     </signer>         
  11.      Example:  
  12.     <signer android:signature="308201c53082012ea00302010202044ebb27cc300d06092a864886f70d01010505003026310f300d060355040a1306476f6f676c65311330110603550403130a4e69636b2050656c6c793020170d3131313131303031323432385a180f32313131313031373031323432385a3026310f300d060355040a1306476f6f676c65311330110603550403130a4e69636b2050656c6c7930819f300d06092a864886f70d010101050003818d00308189028181008d43e546b3f5572707a095ced120d8f06781fa162bcf0ffa0ed0ecb48eb90ed009f65a5a1afd69fb4d38cf24e931b69b061741b8c7ca9f785ba59509e883f5a308f5e2da3c496bb362a2229da8f95f08a92f7f94c829c56e78a34e5147d138d0be0671cb5b7caceaffae6199ba544496a7645e7df3c9f02c5ac156eb0501584f0203010001300d06092a864886f70d0101050500038181003511bcb73651a7927db71ad76e4f6dc5ba121c941ae0fd4dfe519aae8775520b204a5e3cdad2c61ad41aff2c510dbe3376a7578d8aba00f35633e1ae72c91ec83d80eac6f5f081fb8361c6c30c47b0a17932d859d7e991e02cba410a82b35234b2b1bc859e50fe308bf9b64b71a8046777300c07ead159287c187b8865e23f23" />  
  13.     <signer android:signature="3082044c30820334a003020102020900de7695041d7650c0300d06092a864886f70d01010505003077310b3009060355040613025553311330110603550408130a43616c69666f726e6961311630140603550407130d4d6f756e7461696e205669657731143012060355040a130b476f6f676c6520496e632e3110300e060355040b1307416e64726f6964311330110603550403130a476f6f676c65204e4643301e170d3131303332343031303332345a170d3338303830393031303332345a3077310b3009060355040613025553311330110603550408130a43616c69666f726e6961311630140603550407130d4d6f756e7461696e205669657731143012060355040a130b476f6f676c6520496e632e3110300e060355040b1307416e64726f6964311330110603550403130a476f6f676c65204e464330820120300d06092a864886f70d01010105000382010d00308201080282010100e6ff3defe92aa10d71eb0fa6408bc036b7e243eeed68a6a4763dc7a52a31757cdac61fe510bb73c716e4000104265b347fcecef4c42bf1e1379dd0a876f028227fbbc1f9bdd5d713b2f6a935a379d2cba9c96f92d2d0787c11f1eb19548008a6a072b34b91836cfa0ae1276780e9007530166986a11c9cef46cef7c704806dde9431fb60284d120ab0e7de1d633f07687d468c51139afffdc6bc9a207ca904b8be1da0aa7b4e97756f43606488be5cae3c68e8bb7942cdf51607c930a2fcda655b75d0759cba89ad06e739bd0ba29b1f404296c2c0a85a847f5ab0d067c6c3ec9c49212042ac63a7e53b546c65b46080b4e3e680e23e1f77cfe7f6de744b1a65020103a381dc3081d9301d0603551d0e04160414a2e89064b05d08865c34db930a9d840050117aec3081a90603551d230481a130819e8014a2e89064b05d08865c34db930a9d840050117aeca17ba4793077310b3009060355040613025553311330110603550408130a43616c69666f726e6961311630140603550407130d4d6f756e7461696e205669657731143012060355040a130b476f6f676c6520496e632e3110300e060355040b1307416e64726f6964311330110603550403130a476f6f676c65204e4643820900de7695041d7650c0300c0603551d13040530030101ff300d06092a864886f70d010105050003820101003771870ce87c3c52ea84899230c6e962d94b4d5f1293c25d88261541fd90b5555d1285cef3b8312c3f5df691a8aae04cb981b305e427fd1d2d9e1987e1d29078f13c8452990f1821980263d8d4bd36519348d8d8ba26d8b99fbf09f5fd3ebb0ea3c2f0c9376f1e1fca76f3a6a405429d081b752a7a90b756e9ab44da41abc8e1e8f88ac2758da743fb73e650719a57840ccb6b7add21b99fc681e456e1872c223d5c074adf55f6abda268c2d8b64ea0a8845eecd968f92b493127e75c753c3ff30cbc678b51c9f52961472f17da20a0dc6274aa2463434c1a9b614df697d8ff5ca8101e7a25c7db3fb055d65569c04b01d389cabba57b3a1703ec2e74a88d334">  
  14.         <package android:name="com.foo.my.awesome.wallet" />  
  15.         <package android:name="com.foo.my.awesome.wallet.tests" />  
  16.     </signer>      -->  
  17. </resources>  
 我的理解nfcee_access.xml是用来控制一些Apps对NFC的访问的,可能用于手机钱包,手机支付等安全性要求高的应用中。不知道对不对,欢迎探讨。

             Setp4:用以个AsyncTask来后台处理,检测NFC 是否打开,NFC是否具备打开的环境等问题。如果没有打开,调用Jni初始化NFC。
             以上是根据logcat信息来一步一步分析的。还有背后没有发现的信息,NfcAdapter的初始化.NfcService 作为一个application启动时,会创建一个ContextIml的对象。在               ContextIml中有如下code:

[html]  view plain copy
  1. tatic{  
  2.   
  3. registerService(NFC_SERVICE, new ServiceFetcher() {  
  4.   
  5.                 public Object createService(ContextImpl ctx) {  
  6.   
  7.                     return new NfcManager(ctx);  
  8.   
  9.                 }});  
  10.   
  11. }  
在NfcManager的构造函数中,调用了NfcAdapter.getNfcAdapter(context),创建NFC Adapter。
[html]  view plain copy
  1. public static synchronized NfcAdapter getNfcAdapter(Context context) {  
  2. ……  
  3.   
  4.             sService = getServiceInterface();//获取NFC服务接口  
  5.   
  6.         ……  
  7.   
  8.             try {  
  9.   
  10.                 sTagService = sService.getNfcTagInterface();//获取NFC tag服务接口  
  11.   
  12.             } catch (RemoteException e) {  
  13.   
  14.             }  
  15.   
  16.         ……  
  17.   
  18.         NfcAdapter adapter = sNfcAdapters.get(context);  
  19.   
  20.         if (adapter == null) {  
  21.   
  22.             adapter = new NfcAdapter(context);  
  23.   
  24.             sNfcAdapters.put(context, adapter);  
  25.   
  26.         }  
  27.        return adapter;  
  28.   
  29. }  
  30.   
  31. private static INfcAdapter getServiceInterface() {//获取NFC服务接口  
  32.   
  33.         IBinder b = ServiceManager.getService("nfc");  
  34.   
  35.         if (b == null) {  
  36.            return null;  
  37.   
  38.         }  
  39.   
  40.         return INfcAdapter.Stub.asInterface(b);  
  41.   
  42. }  
我们看看getServiceInterface()方法,调用ServiceManager.addService()将NfcAdapterService的实例添加到系统的服务列表中,这里我们调用ServiceManager.getService(“nfc”)获取到了服务端的NfcAdapterService对象的实例。
在NfcAdapterService类中提供了getNfcTagInterface接口,用于获取远程服务端的TagService对象的实例。
如果一切正常,那么将创建NfcAdapter的实例,在其构造函数中,创建了NfcActivityManager的实例。
有张图可以更说明问题,且很清晰:

NFC学习——NfcService 启动过程分析_第1张图片

以上部分转自:
NFC framework introduce(一)

你可能感兴趣的:(NFC学习——NfcService 启动过程分析)