NFC Enable 过程分析(三)

这篇文章用来分析NFC学习——NFC Enable 过程分析(一)中setp3-2:开启一些循环监听的线程服务。处理方法enableDisable().

code路径:packages/apps/nfc/src/com/android/nfc/P2pLinkManager.java,具体看enableDisable()中的处理code:

  1. publicvoidenableDisable(booleansendEnable,booleanreceiveEnable){
  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

  1. publicvoidrun(){
  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. LlcpSocketcommunicationSocket=serverSocket.accept();
  12. if(communicationSocket!=null){
  13. //setp1-2:miu是什么,如何获取来的
  14. intmiu=communicationSocket.getRemoteMiu();
  15. intfragmentLength=(mFragmentLength==-1)?
  16. miu:Math.min(miu,mFragmentLength);
  17. //setp1-3:启动线程处理SnepMessenger
  18. newConnectionThread(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()来实现其创建功能,其中的参数为了书写方便都省略了。

  1. staticjobjectcom_android_nfc_NfcManager_doCreateLlcpServiceSocket(JNIEnv*e,jobjecto,
  2. jintnSap,jstringsn,jintmiu,jintrw,jintlinearBufferLength)
  3. {
  4. ......
  5. /*Createsocket*/
  6. /*setp1-1-1:函数在external/libnfc-nxp/src/phLibNfc.h声明,具体的函数作用,函数参数含义请查看代码中注释,&hLlcpSocket即是创建成功的Sokect的指针*/
  7. ret=phLibNfc_Llcp_Socket(phFriNfc_LlcpTransport_eConnectionOriented,
  8. &sOptions,
  9. &sWorkingBuffer,
  10. &hLlcpSocket,
  11. nfc_jni_llcp_transport_socket_err_callback,
  12. (void*)nat);
  13. ......
  14. /*CreatenewNativeLlcpServiceSocketobject,到此出现了我们分析到目前的mServerSocket的创建,返回的serviceSocket就是*/
  15. if(nfc_jni_cache_object(e,"com/android/nfc/nxp/NativeLlcpServiceSocket",&(serviceSocket))==-1)
  16. {
  17. ALOGE("LlcpSocketobjectcreationerror");
  18. gotoerror;
  19. }
  20. ......
  21. returnserviceSocket;
  22. }

附上一张思路图,就清晰点

NFC Enable 过程分析(三)

Setp1-2:miu如何得来的,看下面分析图

NFC Enable 过程分析(三)

看到这张图,可能只是对函数的调用过程有个清晰的了解,但是miu到底是如何获取到的呢??这次我们从函数的调用最后来分析,即phFriNfc_LlcpTransport_Connection.c这个文件的函数。

  1. NFCSTATUSphFriNfc_LlcpTransport_ConnectionOriented_SocketGetRemoteOptions(
  2. phFriNfc_LlcpTransport_Socket_t*pLlcpSocket,
  3. phLibNfc_Llcp_sSocketOptions_t*psRemoteOptions)
  4. {
  5. NFCSTATUSstatus=NFCSTATUS_SUCCESS;
  6. /*GetRemoteMIUX*/
  7. psRemoteOptions->miu=pLlcpSocket->remoteMIU;
  8. /*GetRemoteReceiveWindow*/
  9. psRemoteOptions->rw=pLlcpSocket->remoteRW;
  10. returnstatus;
  11. }
上面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

  1. staticbooleanhandleRequest(SnepMessengermessenger,Callbackcallback)throwsIOException{
  2. SnepMessagerequest;
  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. }elseif(request.getField()==SnepMessage.REQUEST_GET){
  10. /*发送SnepMessage,SnepMessage来源于CallBack的实现,sendMessage把SnepMessage转换成byte[]通过LlcpSocketsocket发送数据*/
  11. messenger.sendMessage(callback.doGet(request.getAcceptableLength(),
  12. request.getNdefMessage()));
  13. }elseif(request.getField()==SnepMessage.REQUEST_PUT){
  14. if(DBG)Log.d(TAG,"puttingmessage"+request.toString());
  15. //发送SnepMessage,SnepMessage来源于Callback的实现
  16. messenger.sendMessage(callback.doPut(request.getNdefMessage()));
  17. }else{
  18. if(DBG)Log.d(TAG,"Unknownrequest("+request.getField()+")");
  19. messenger.sendMessage(SnepMessage.getMessage(
  20. SnepMessage.RESPONSE_BAD_REQUEST));
  21. }
  22. returntrue;
  23. }
上面code涉及到CallBack一个回调接口,它实现在P2pLinkManager.java中

  1. finalSnepServer.CallbackmDefaultSnepCallback=newSnepServer.Callback(){
  2. @Override
  3. publicSnepMessagedoPut(NdefMessagemsg){
  4. /*该方法中有个EventLogTags.writeNfcNdefReceived的调用,我始终没找到它的具体方法实现在哪儿*/
  5. onReceiveComplete(msg);
  6. returnSnepMessage.getMessage(SnepMessage.RESPONSE_SUCCESS);
  7. }
  8. @Override
  9. publicSnepMessagedoGet(intacceptableLength,NdefMessagemsg){
  10. NdefMessageresponse=mHandoverManager.tryHandoverRequest(msg);
  11. if(response!=null){
  12. onReceiveHandover();
  13. returnSnepMessage.getSuccessResponse(response);
  14. }else{
  15. returnSnepMessage.getMessage(SnepMessage.RESPONSE_NOT_FOUND);
  16. }
  17. }
  18. };

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是什么东西,故不做翻译了。