1. 程式人生 > >NFC學習——NfcService 啟動過程分析

NFC學習——NfcService 啟動過程分析

在機器開機過程中,可以抓取到以下的正常logcat資訊:

//setp1
I/NfcService( 3809): Starting NFC service
D/NFCJNI  ( 3809): NFC Service : loading JNI
I/RegisteredComponentCache( 3809): ComponentInfo: ResolveInfo{41344108 
com.android.apps.tag.TagViewer p=0 o=0 m=0x108000}, techs: android.nfc.tech.Ndef, 
W/NfceeAccess( 3809): could not find /etc/nfcee_access.xml, no NFCEE access allowed
I/NfceeAccess( 3809): read 0 signature(s) for NFCEE access
D/NfcService( 3809): checking on firmware download
下面是硬體不支援NFC的異常logcat資訊:
I/NfcService( 3485): Starting NFC service
D/NFCJNI  ( 3485): NFC Service : loading JNI
W/NfceeAccess( 3485): could not find /etc/nfcee_access.xml, no NFCEE access allowed
I/NfceeAccess( 3485): read 0 signature(s) for NFCEE access
D/NfcService( 3485): checking on firmware download
D/NfcService( 3485): NFC is on. Doing normal stuff
I/NfcService( 3485): Enabling NFC
D/NFCJNI  ( 3485): Start Initialization
E/NFCJNI  ( 3485): hw_get_module() failed.
D/NFCJNI  ( 3485): Terminating client thread...
W/NfcService( 3485): Error enabling NFC
來看正常logcat資訊setp1,NfcService 是application,它的onCreate()方法:
@Override
    public void onCreate() {
        super.onCreate();

        mNfcTagService = new TagService();
        mNfcAdapter = new NfcAdapterService();
        mExtrasService = new NfcAdapterExtrasService();

        Log.i(TAG, "Starting NFC service");
        
        //setp2:NFC Service : loading JNI
        mDeviceHost = new NativeNfcManager(this, this);

        HandoverManager handoverManager = new HandoverManager(mContext);
 		
 	//NfcDispatcher主要負責tag訊息處理,並派發Intent訊息,啟動Activity。
 	mNfcDispatcher = new NfcDispatcher(this, handoverManager); 
 	    
 	mP2pLinkManager = new P2pLinkManager(mContext, handoverManager); 
 	mSecureElement = new NativeNfcSecureElement(mContext);                 
 	    
        //setp3:could not find /etc/nfcee_access.xml, no NFCEE access allowed 
        mNfceeAccessControl = new NfceeAccessControl(this); 
        
   //把mNfcAdapter 作為Service 新增到系統服務中,ServiceManager.getService("nfc")可以獲取到binder                      
        ServiceManager.addService(SERVICE_NAME, mNfcAdapter);
 	    
 	updatePackageCache();         
 	    
 	//setp4:checking on firmware download        
 	new EnableDisableTask().execute(TASK_BOOT); // do blocking boot tasks 
    }
Setp2:NFC Service loading JNI,這一部分是在NativeNfcManager.java中處理的  
//載入jni編譯生成的nfc_jni.so.通過NativeNfcManager呼叫jni部分
static {
        System.loadLibrary("nfc_jni");
    }

//NativeNfcManager 構造方法
public NativeNfcManager(Context context, DeviceHostListener listener) {
        mListener = listener;

        //setp2-1:com_android_nfc_NativeNfcManager.cpp的native方法
        //com_android_nfc_NfcManager_init_native_struc(JNIEnv *e, jobject o)
        initializeNativeStructure();
        mContext = context;
    }
Setp2-1:com_android_nfc_NfcManager_init_native_struc(),初始化nfc_jni_native_data結構體
static jboolean com_android_nfc_NfcManager_init_native_struc(JNIEnv *e, jobject o)
{ 
  /* Initialize native structure */   
  // 涉及到nfc_jni_native_date結構體的定義在com_android_nfc.h
   nat = (nfc_jni_native_data*)malloc(sizeof(struct nfc_jni_native_data));
   if(nat == NULL)
   {
      ALOGD("malloc of nfc_jni_native_data failed");
      return FALSE;   
   }
   memset(nat, 0, sizeof(*nat));

   /* Initialize native cached references */ 
   //通過jni 呼叫java 層的方法
   cached_NfcManager_notifyNdefMessageListeners = e->GetMethodID(cls,
      "notifyNdefMessageListeners","(Lcom/android/nfc/nxp/NativeNfcTag;)V");

   cached_NfcManager_notifyTransactionListeners = e->GetMethodID(cls,
      "notifyTransactionListeners", "([B)V");
         
   cached_NfcManager_notifyLlcpLinkActivation = e->GetMethodID(cls,
      "notifyLlcpLinkActivation","(Lcom/android/nfc/nxp/NativeP2pDevice;)V");
         
   cached_NfcManager_notifyLlcpLinkDeactivated = e->GetMethodID(cls,
      "notifyLlcpLinkDeactivated","(Lcom/android/nfc/nxp/NativeP2pDevice;)V"); 
      
   cached_NfcManager_notifyTargetDeselected = e->GetMethodID(cls,
      "notifyTargetDeselected","()V");   
   
   //nfc_jni_cache_object 原型在com_android_nfc.cpp中,有什麼作用,做什麼動作暫時沒有搞清楚?
   if(nfc_jni_cache_object(e,"com/android/nfc/nxp/NativeNfcTag",&(nat->cached_NfcTag)) == -1)
   {
      ALOGD("Native Structure initialization failed");
      return FALSE;
   }
         
   if(nfc_jni_cache_object(e,"com/android/nfc/nxp/NativeP2pDevice",&(nat->cached_P2pDevice)) == -1)
   {
      ALOGD("Native Structure initialization failed");
      return FALSE;   
   }
   TRACE("****** Init Native Structure OK ******");
   return TRUE;
}
Setp3:解析/etc/nfcee_access.xml,NfceeAccessControl.java主要用來解析nfcee_access,xml並做一些證書和安全方面的check。nfcee_access.xml的檔案內容:
<?xml version="1.0" encoding="utf-8"?>
<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
    <!-- The built in list of signatures and package names that are allowed
    access to the NFCEE (Secure Element).

    Format:
    <signer android:signature="SIGNATURE">
        <package android:name="PACKAGE_NAME" />
        ...
    </signer>       
     Example:
    <signer android:signature="308201c53082012ea00302010202044ebb27cc300d06092a864886f70d01010505003026310f300d060355040a1306476f6f676c65311330110603550403130a4e69636b2050656c6c793020170d3131313131303031323432385a180f32313131313031373031323432385a3026310f300d060355040a1306476f6f676c65311330110603550403130a4e69636b2050656c6c7930819f300d06092a864886f70d010101050003818d00308189028181008d43e546b3f5572707a095ced120d8f06781fa162bcf0ffa0ed0ecb48eb90ed009f65a5a1afd69fb4d38cf24e931b69b061741b8c7ca9f785ba59509e883f5a308f5e2da3c496bb362a2229da8f95f08a92f7f94c829c56e78a34e5147d138d0be0671cb5b7caceaffae6199ba544496a7645e7df3c9f02c5ac156eb0501584f0203010001300d06092a864886f70d0101050500038181003511bcb73651a7927db71ad76e4f6dc5ba121c941ae0fd4dfe519aae8775520b204a5e3cdad2c61ad41aff2c510dbe3376a7578d8aba00f35633e1ae72c91ec83d80eac6f5f081fb8361c6c30c47b0a17932d859d7e991e02cba410a82b35234b2b1bc859e50fe308bf9b64b71a8046777300c07ead159287c187b8865e23f23" />
    <signer android:signature="3082044c30820334a003020102020900de7695041d7650c0300d06092a864886f70d01010505003077310b3009060355040613025553311330110603550408130a43616c69666f726e6961311630140603550407130d4d6f756e7461696e205669657731143012060355040a130b476f6f676c6520496e632e3110300e060355040b1307416e64726f6964311330110603550403130a476f6f676c65204e4643301e170d3131303332343031303332345a170d3338303830393031303332345a3077310b3009060355040613025553311330110603550408130a43616c69666f726e6961311630140603550407130d4d6f756e7461696e205669657731143012060355040a130b476f6f676c6520496e632e3110300e060355040b1307416e64726f6964311330110603550403130a476f6f676c65204e464330820120300d06092a864886f70d01010105000382010d00308201080282010100e6ff3defe92aa10d71eb0fa6408bc036b7e243eeed68a6a4763dc7a52a31757cdac61fe510bb73c716e4000104265b347fcecef4c42bf1e1379dd0a876f028227fbbc1f9bdd5d713b2f6a935a379d2cba9c96f92d2d0787c11f1eb19548008a6a072b34b91836cfa0ae1276780e9007530166986a11c9cef46cef7c704806dde9431fb60284d120ab0e7de1d633f07687d468c51139afffdc6bc9a207ca904b8be1da0aa7b4e97756f43606488be5cae3c68e8bb7942cdf51607c930a2fcda655b75d0759cba89ad06e739bd0ba29b1f404296c2c0a85a847f5ab0d067c6c3ec9c49212042ac63a7e53b546c65b46080b4e3e680e23e1f77cfe7f6de744b1a65020103a381dc3081d9301d0603551d0e04160414a2e89064b05d08865c34db930a9d840050117aec3081a90603551d230481a130819e8014a2e89064b05d08865c34db930a9d840050117aeca17ba4793077310b3009060355040613025553311330110603550408130a43616c69666f726e6961311630140603550407130d4d6f756e7461696e205669657731143012060355040a130b476f6f676c6520496e632e3110300e060355040b1307416e64726f6964311330110603550403130a476f6f676c65204e4643820900de7695041d7650c0300c0603551d13040530030101ff300d06092a864886f70d010105050003820101003771870ce87c3c52ea84899230c6e962d94b4d5f1293c25d88261541fd90b5555d1285cef3b8312c3f5df691a8aae04cb981b305e427fd1d2d9e1987e1d29078f13c8452990f1821980263d8d4bd36519348d8d8ba26d8b99fbf09f5fd3ebb0ea3c2f0c9376f1e1fca76f3a6a405429d081b752a7a90b756e9ab44da41abc8e1e8f88ac2758da743fb73e650719a57840ccb6b7add21b99fc681e456e1872c223d5c074adf55f6abda268c2d8b64ea0a8845eecd968f92b493127e75c753c3ff30cbc678b51c9f52961472f17da20a0dc6274aa2463434c1a9b614df697d8ff5ca8101e7a25c7db3fb055d65569c04b01d389cabba57b3a1703ec2e74a88d334">
        <package android:name="com.foo.my.awesome.wallet" />
        <package android:name="com.foo.my.awesome.wallet.tests" />
    </signer>      -->
</resources>
 我的理解nfcee_access.xml是用來控制一些Apps對NFC的訪問的,可能用於手機錢包,手機支付等安全性要求高的應用中。不知道對不對,歡迎探討。

             Setp4:用以個AsyncTask來後臺處理,檢測NFC 是否開啟,NFC是否具備開啟的環境等問題。如果沒有開啟,呼叫Jni初始化NFC。
             以上是根據logcat資訊來一步一步分析的。還有背後沒有發現的資訊,NfcAdapter的初始化.NfcService 作為一個application啟動時,會建立一個ContextIml的物件。在               ContextIml中有如下code:
tatic{

registerService(NFC_SERVICE, new ServiceFetcher() {

                public Object createService(ContextImpl ctx) {

                    return new NfcManager(ctx);

                }});

}
在NfcManager的建構函式中,呼叫了NfcAdapter.getNfcAdapter(context),建立NFC Adapter。
public static synchronized NfcAdapter getNfcAdapter(Context context) {
……

            sService = getServiceInterface();//獲取NFC服務介面

        ……

            try {

                sTagService = sService.getNfcTagInterface();//獲取NFC tag服務介面

            } catch (RemoteException e) {

            }

        ……

        NfcAdapter adapter = sNfcAdapters.get(context);

        if (adapter == null) {

            adapter = new NfcAdapter(context);

            sNfcAdapters.put(context, adapter);

        }
       return adapter;

}

private static INfcAdapter getServiceInterface() {//獲取NFC服務介面

        IBinder b = ServiceManager.getService("nfc");

        if (b == null) {
           return null;

        }

        return INfcAdapter.Stub.asInterface(b);

}
我們看看getServiceInterface()方法,呼叫ServiceManager.addService()將NfcAdapterService的例項新增到系統的服務列表中,這裡我們呼叫ServiceManager.getService(“nfc”)獲取到了服務端的NfcAdapterService物件的例項。
在NfcAdapterService類中提供了getNfcTagInterface介面,用於獲取遠端服務端的TagService物件的例項。
如果一切正常,那麼將建立NfcAdapter的例項,在其建構函式中,建立了NfcActivityManager的例項。
有張圖可以更說明問題,且很清晰:


相關推薦

NFC學習——NfcService 啟動過程分析

在機器開機過程中,可以抓取到以下的正常logcat資訊: //setp1 I/NfcService( 3809): Starting NFC service D/NFCJNI ( 3809): NFC Service : loading JNI I/Registered

STM32之啟動過程分析學習筆記

 System memory內建了ST提供的boot loader,可以通過該boot loader下載程式到Flash中。 使用者程式實際只能儲存在Flash中,且能在Flash和SRAM中執行(因為cortex-m3核採用哈佛結構,程式

Tomcat 學習進階歷程之Tomcat啟動過程分析

本節通過跟蹤Tomcat的原始碼來分析Tomcat是如何啟動及裝配各個元件的。最好下載Tomcat的原始碼匯入到Eclipse,這樣方便跟蹤。方法可參考: http://www.cnblogs.com/huangfox/archive/2011/10/20/2218970.

區塊鏈學習——HyperLedger-Fabric v1.0 啟動過程分析

本章我們從fabric v1.0的e2e_cli示例開始分析整個啟動過程以及在過程中的一些配置檔案 首先呢,還是確保你的基本環境已經搭建完成,v1.0原始碼和映象也都下載完畢 fabric啟動過程中的相關指令碼檔案解析 network_setup.sh指令碼檔案 在原始碼目錄下的network_set

【轉】Android 4.0 Launcher2源碼分析——啟動過程分析

handler flag 這一 第一次啟動 asynctask pla size ontouch wait Android的應用程序的入口定義在AndroidManifest.xml文件中可以找出:[html] <manifest xmlns:android="htt

X86架構下Linux啟動過程分析

重要 ack csdn 檢查 point article span 註意 eap 1、X86架構下的從開機到Start_kernel啟動的整體過程 這個過程簡要概述為: 開機——>BIOS——>GRUB/LILO——>Linux Kernel

Linux開機啟動過程分析

物理內存 登錄 page thread 陷阱門 execute 啟動過程 font 定義 Linux開機啟動過程分析 開機過程指的是從打開計算機電源直到LINUX顯示用戶登錄畫面的全過程。分析LINUX開機過程也是深入了解LINUX核心工作原理的一個很好的途徑。 啟動第一

u-boot-201611 啟動過程分析——基於smdk2410

u-bootu-boot-201611 啟動過程分析——基於smdk2410

linux 系統啟動過程分析

系統root 密碼丟失故障 linux啟動順序主板BIOS加電自檢 檢查硬件--> 讀取硬盤引導扇區(MBR)--> 啟動引導程序(grub)--> 選擇系統--> 加載系統內核(kernel shell)--> 啟動系統讀取相應的默認設置(環境變量,運行級別)--

Ocata Neutron代碼分析(一)——Neutron API啟動過程分析

process fig ddr arch 異常 run tap 文件中 bridge 首先,Neutron Server作為一種服務(neutron-server.service),可以到Neutron項目目錄中的setup.cfg配置文件中找到對應的代碼入口。 [ent

Ocata Neutron代碼分析(二)——Neutron RPC啟動過程分析

gre add ice common multi tween wait函數 tex 依次 RPC啟動跟Neutron API的啟動在同一個函數中執行,neutron.server.wsgi_eventlet.py中的eventlet_wsgi_server。 def ev

Linux進程啟動過程分析do_execve(可執行程序的加載和運行)---Linux進程的管理與調度(十一)

[] flag 表示 conn nali 最終 roc 不同的 recursion execve系統調用 execve系統調用 我們前面提到了, fork, vfork等復制出來的進程是父進程的一個副本, 那麽如何我們想加載新的程序, 可以通過execve來加載和啟動新的程

AliOS Things的啟動過程分析(二)

AliOS Things的啟動過程分析(二) 在AliOS Things的啟動過程分析(一)中分析了developerkit從系統上電到呼叫main函式所經歷的一些步驟,接下來詳細分析一下main函式的一些工作,主要是核心的相關初始化工作。main函式所處的位置位於    

OpenWrt啟動過程分析+新增自啟動指令碼[轉載]

一、OpenWrt啟動過程分析 總結一下OpenWrt的啟動流程:1.CFE->2.linux->3./etc/preinit->4./sbin/init ->5./etc/inittab ->6./etc/init.d/rcS->7./etc/rc.d/S*

OSAL啟動過程分析

一、SimpleBLEBroadcaster  OSAL啟動過程分析: Main() ==> HAL_BOARD_INIT();//初始化硬體 ==> InitBoard( OB_COLD );//初始化板卡IO ==> HalDriverInit();

《16.核心的啟動過程分析

《16.核心的啟動過程分析》 第一部分、章節目錄 2.16.1.做好核心分析的準備工作 2.16.2.head.S檔案分析1 2.16.3.核心啟動的彙編階段 2.16.4.核心啟動的C語言階段1 2.16.5.核心啟動的C語言階段2 2.16.6.核心啟動的C語言階段3 2.16.7.

Linux啟動過程分析(十一)---da850_set_emif_clk_rate()函式分析

/* * 雖然在bootloader中已經把emif的時鐘速率設定為允許的值,但是核心需要重新 *設定以使它支援平臺請求的特定時鐘速率。 */ ret = da850_set_emif_clk_rate()-> static __init int da850_set_emif_c

Linux啟動過程分析(十一)-----customize_machine(註冊開發板相關硬體資訊)

初始化過程進行到下面這一步: c0599c48 t __initcall_customize_machine3 呼叫的函式及其位置如下: Setup.c (arch\arm\kernel):arch_initcall(customize_machine) static int __in

Linux核心啟動過程分析(十)-----RTC驅動分析

參考https://blog.csdn.net/xuao20060793/article/details/46433263這篇博文 RTC驅動分析: Class.c (drivers\rtc):subsys_initcall(rtc_init); static int __init

Android安全/開發基礎--9--Android系統的啟動過程分析

================================================================= 整個Android系統的啟動分為Linux核心的啟動和Android系統的啟動。 Android系統的啟動流程圖中部分名詞簡介: