天天看點

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

這篇文章用來分析NFC學習——NFC Enable 過程分析(一) 中setp 3-2:開啟一些循環監聽的線程服務。處理方法enableDisable().

        code路徑:packages/apps/nfc/src/com/android/nfc/P2pLinkManager.java,具體看enableDisable()中的處理code:

[html]  view plain copy

  1. public void enableDisable(boolean sendEnable, boolean receiveEnable) {  
  2.         synchronized (this) {  
  3.             if (!mIsReceiveEnabled && receiveEnable) {   
  4.                 //setp1:啟動SnepServer  
  5.                 mDefaultSnepServer.start();    
  6.                 //setp2:啟動NdefPushServer  
  7.                 mNdefPushServer.start();  
  8.                 if (mEchoServer != null) {   
  9.                     //setp3:啟動EchoServer  
  10.                     mHandler.sendEmptyMessage(MSG_START_ECHOSERVER);  
  11.                 }  
  12.             }   
  13.         }  
  14.     }  

Setp1:啟動SnepServer,此Server的作用是接收NDEF消息,并把它推送給LLCP(Logical Link Control Protocol).啟動SnepServer最後轉到其内部類ServerThread去處理,ServerThread繼承Thread,具體分析它的run方法。

code路徑:packages/apps/nfc/src/com/android/nfc/snep/SnepServer.java 

[html]  view plain copy

  1. public void run() {  
  2.           ........  
  3.          while (threadRunning) {  
  4.                synchronized (SnepServer.this) {   
  5.                //setp1-1:建立一個伺服器端Socket連接配接  
  6.          mServerSocket = NfcService.getInstance().createLlcpServerSocket(mServiceSap,  
  7.                                 mServiceName, MIU, 1, 1024);  
  8.                    }  
  9.                  ......   
  10.                //接收Socket請求  
  11.                LlcpSocket communicationSocket = serverSocket.accept();  
  12.                if (communicationSocket != null) {   
  13.                //setp1-2:miu 是什麼,如何擷取來的  
  14.                int miu = communicationSocket.getRemoteMiu();  
  15.                int fragmentLength = (mFragmentLength == -1) ?  
  16.                           miu : Math.min(miu, mFragmentLength);  
  17.                 //setp1-3: 啟動線程處理SnepMessenger  
  18.                 new ConnectionThread(communicationSocket, fragmentLength).start();  
  19.                }  
  20.                ......  
  21.          }  
  22. }  

Setp1-1:建立伺服器端mServerSocket中參數如下:

mServiceSap:socket 端口,預設是4;

mServiceName:從命名可以看出,它是socket名稱

MIU:全稱是Maximum information Unit ,LLCP中資料單元中消息最大的長度(不知道是不是按byte算的),

1:

1024:是buffer的長度,至于它的作用是什麼,贊時還不知道。

mServerSocket的建立過程:通過NfcService調用createLlcpServerSocket(),而NfcService直接傳回的DeviceHost.createLlcpServerSocket()的調用,DeviceHost僅僅隻是一個接口,DeviceHost.createLlcpServerSocket()具體實作在NativeNfcManager.createLlcpServerSocket().NativeNfcManager則直接調用JNI方法com_android_nfc_NfcManager_doCreateLlcpServiceSocket()來實作其建立功能,其中的參數為了書寫友善都省略了。

[html]  view plain copy

  1. static jobject com_android_nfc_NfcManager_doCreateLlcpServiceSocket(JNIEnv *e, jobject o,  
  2.                jint nSap, jstring sn, jint miu, jint rw, jint linearBufferLength)  
  3. {  
  4.   ......   
  5.  ret = phLibNfc_Llcp_Socket(phFriNfc_LlcpTransport_eConnectionOriented,  
  6.                               &sOptions,  
  7.                               &sWorkingBuffer,  
  8.                               &hLlcpSocket,  
  9.                               nfc_jni_llcp_transport_socket_err_callback,  
  10.                               (void*)nat);   
  11.  ......   
  12.    if(nfc_jni_cache_object(e,"com/android/nfc/nxp/NativeLlcpServiceSocket",&(serviceSocket)) == -1)  
  13.    {  
  14.       ALOGE("Llcp Socket object creation error");  
  15.       goto error;  
  16.    }  
  17.   ......   
  18.    return serviceSocket;  
  19. }  

附上一張思路圖,就清晰點

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

Setp1-2:miu如何得來的,看下面分析圖

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

看到這張圖,可能隻是對函數的調用過程有個清晰的了解,但是miu到底是如何擷取到的呢??這次我們從函數的調用最後來分析,即phFriNfc_LlcpTransport_Connection.c這個檔案的函數。

[html]  view plain copy

  1. NFCSTATUS phFriNfc_LlcpTransport_ConnectionOriented_SocketGetRemoteOptions(  
  2.                   phFriNfc_LlcpTransport_Socket_t*   pLlcpSocket,  
  3.                   phLibNfc_Llcp_sSocketOptions_t*    psRemoteOptions)  
  4. {  
  5.    NFCSTATUS status = NFCSTATUS_SUCCESS;  
  6.    psRemoteOptions->miu = pLlcpSocket->remoteMIU;  
  7.    psRemoteOptions->rw = pLlcpSocket->remoteRW;  
  8.    return status;  
  9. }  

上面code可以發現phFriNfc_LlcpTransport_Socket_t 的remoteMIU 直接賦給phLibNfc_Llcp_sSocketOptions_t的miu.這就是我們要找的答案。phFriNfc_LlcpTransport_Socket_t 和phLibNfc_Llcp_sSocketOptions_t具體是什麼就不做研究了。

setp1-3: 啟動線程處理SnepMessenger,從新開啟一個Thread處理SnepMessage,處理code 還是SnepServer.java

[html]  view plain copy

  1.  static boolean handleRequest(SnepMessenger messenger, Callback callback) throws IOException {  
  2.         SnepMessage request;  
  3.         ......  
  4.         //從SnepMessenger中取出SnepMessage          
  5.         request = messenger.getMessage();   
  6.         if (((request.getVersion() & 0xF0) >> 4) != SnepMessage.VERSION_MAJOR) {  
  7.             messenger.sendMessage(SnepMessage.getMessage(  
  8.                     SnepMessage.RESPONSE_UNSUPPORTED_VERSION));  
  9.         } else if (request.getField() == SnepMessage.REQUEST_GET) {   
  10.             messenger.sendMessage(callback.doGet(request.getAcceptableLength(),  
  11.                     request.getNdefMessage()));  
  12.         } else if (request.getField() == SnepMessage.REQUEST_PUT) {  
  13.             if (DBG) Log.d(TAG, "putting message " + request.toString());         
  14.             //發送SnepMessage,SnepMessage來源于Callback的實作  
  15.             messenger.sendMessage(callback.doPut(request.getNdefMessage()));  
  16.         } else {  
  17.             if (DBG) Log.d(TAG, "Unknown request (" + request.getField() +")");  
  18.             messenger.sendMessage(SnepMessage.getMessage(  
  19.                     SnepMessage.RESPONSE_BAD_REQUEST));  
  20.         }  
  21.         return true;  
  22.     }  

上面code涉及到CallBack一個回調接口,它實作在P2pLinkManager.java中

[html]  view plain copy

  1. final SnepServer.Callback mDefaultSnepCallback = new SnepServer.Callback() {  
  2.         @Override  
  3.         public SnepMessage doPut(NdefMessage msg) {           
  4.             onReceiveComplete(msg);  
  5.             return SnepMessage.getMessage(SnepMessage.RESPONSE_SUCCESS);  
  6.         }  
  7.         @Override  
  8.         public SnepMessage doGet(int acceptableLength, NdefMessage msg) {  
  9.             NdefMessage response = mHandoverManager.tryHandoverRequest(msg);  
  10.             if (response != null) {  
  11.                 onReceiveHandover();  
  12.                 return SnepMessage.getSuccessResponse(response);  
  13.             } else {  
  14.                 return SnepMessage.getMessage(SnepMessage.RESPONSE_NOT_FOUND);  
  15.             }  
  16.         }  
  17.     };  

setp2:啟動NdefPushServer,setp3:啟動EchoServer的過程和setp1:啟動SnepServer過程類似,具體可以參照setp1,在此就不做詳細分析。

以上分析中涉及到SnepServer,NdefPushServer,EchoServer。看下這三個檔案中對自己的注釋說明。。

SnepServer:A simple server that accepts NDEF messages pushed to it over an LLCP connection. Those messages are typically set on the client side by using NfcAdapter.enableForegroundNdefPush.通過LLCP接收NDEF 消息,并把消息通過NfcAdapter.enableForegroundNdefPush設定到用戶端。

NdefPushServer:同SnepServer。

EchoServer:EchoServer is an implementation of the echo server that is used in the nfcpy LLCP test suite. Enabling the EchoServer allows to test Android NFC devices against nfcpy,這是code中給的注釋說明,但不知到nfcpy是什麼東西,故不做翻譯了。

nfc

繼續閱讀