NFC Discovery
NFC系統在初始化完成後EnableDisableTask.enableInternal()會默認開啟掃描,應用apk也可以主動發起搜索掃描NFC設備NfcAdapter. resumePolling( )。
各個指令的下發無非就是根據指令的不同封裝不同的數據,最後通過mHal->write()將數據下發到底層NFC芯片模塊,芯片模塊解析下發的數據來執行不同的動作,並將指令執行的結果及時上報。下圖為NFC搜索指令的一個完整的時序圖:
從該時序圖可以看出Discovery指令執行結果的上報經過線程NFC_TASK的處理最後會走到nfc_ncif_rf_management_status()函數中。又經回調函數nfc_cb.p_discv_cback( )處理送入Discovery狀態機,這可以說是NFC Discovery的關鍵所在,狀態機會及時改變當前搜索的狀態並做出對應的上報處理。nfc_cb.p_discv_cback是在下發搜索指令NFC_DiscoveryStart()時設置的。
NFC Discovery狀態機的變化見協議:NFCForum-TS-NCI-1.0_Candidate-1.pdf(最新的協議請查看2.1版本)。
<code>/* DM RF discovery state */
enum {
NFA_DM_RFST_IDLE, /* idle state */
NFA_DM_RFST_DISCOVERY, /* discovery state */
NFA_DM_RFST_W4_ALL_DISCOVERIES, /* wait for all discoveries state */
NFA_DM_RFST_W4_HOST_SELECT, /* wait for host selection state */
NFA_DM_RFST_POLL_ACTIVE, /* poll mode activated state */
NFA_DM_RFST_LISTEN_ACTIVE, /* listen mode activated state */
NFA_DM_RFST_LISTEN_SLEEP, /* listen mode sleep state */
NFA_DM_RFST_LP_LISTEN, /* Listening in Low Power mode */
NFA_DM_RFST_LP_ACTIVE /* Activated in Low Power mode */
};/<code>
他們之間的切換關係見下圖:
這些狀態機變化中比較重要的事件都用紅色框圖標註出來了,收到Discovery指令的執行結果也就是event = NFA_DM_RF_DISCOVER_RSP,狀態機會從 RFST_IDLE -> RFST_DISCOVERY,後面隨著流程的講解其他狀態的切換也會做出說明。
NFC芯片接收到搜索指令後,就會掃描周圍環境中的NFC設備,並將掃描到的結果依次上報,該流程見下圖:
NFC Discovery狀態機由於result的上報,狀態值設置為 NFA_DM_RFST_W4_HOST_SELECT ,等待上層選擇一個result進行操作。這裡我們以Tag為列進行介紹,P2P的操作我們放到以後的篇章中再做分析。
選擇Tag,最終調用NFA_Select()讓底層NFC芯片和對端NFC Tag建立連接。一旦連接完成,NFC Controller會通知上層。
具體流程見下圖:
上報RF_INTF_ACTIVATED_NTF後,nfc的搜索狀態機會跳到NFA_DM_RFST_POLL_ACTIVE,代表nfc連接已經和對端Tag建立成功。同時nfc的狀態也設為 NFC_STATE_OPEN,表示nfc鏈路建立成功。標籤Tag相關信息會上報到nfc服務層,進行標籤的分發,流程最後可以看到有四種不同的標籤分發方式,在後續文章中會選擇"前臺發佈系統"和"Intent發佈系統"這兩種分發方式做重點分析,敬請期待。。。
在分發標籤前,需要獲取當前Tag的NDEF數據,在上面的流程圖中可以看到獲取數據是通過TagEndpoint.findAndReadNdef()讀取NDEF數據的,流程見如下時序圖(Type-1-Tag):
通過搜索的狀態機圖可以發現,現在已經對5個紅色框圖完成分析,最後一個紅色框圖對應的操作是斷開Tag標籤的連接。有兩種主要情況:1、Tag標籤遠離RF場;2、上層主動下發命令斷開連接,隨著標籤的斷開NFC系統又重新開始新一輪的搜索。每一次搜索的時間為500ms,超時後重新搜索。
#define NFA_DM_DISC_DURATION_POLL 500 /* Android requires 500 */
超時的處理流程和result上報一致,只是後面和Tag標籤建立連接失敗的處理流程類似斷開Tag標籤連接的流程。
閱讀更多 Connectivity 的文章