NFC Enable 过程分析(三)
这篇文章用来分析NFC学习——NFC Enable 过程分析(一)中setp3-2:开启一些循环监听的线程服务。处理方法enableDisable().
code路径:packages/apps/nfc/src/com/android/nfc/P2pLinkManager.java,具体看enableDisable()中的处理code:
- publicvoidenableDisable(booleansendEnable,booleanreceiveEnable){
- synchronized(this){
- if(!mIsReceiveEnabled&&receiveEnable){
- //setp1:启动SnepServer
- mDefaultSnepServer.start();
- //setp2:启动NdefPushServer
- mNdefPushServer.start();
- if(mEchoServer!=null){
- //setp3:启动EchoServer
- mHandler.sendEmptyMessage(MSG_START_ECHOSERVER);
- }
- }
- }
- }
code路径:packages/apps/nfc/src/com/android/nfc/snep/SnepServer.java
- publicvoidrun(){
- ........
- while(threadRunning){
- synchronized(SnepServer.this){
- //setp1-1:创建一个服务器端Socket连接
- mServerSocket=NfcService.getInstance().createLlcpServerSocket(mServiceSap,
- mServiceName,MIU,1,1024);
- }
- ......
- //接收Socket请求
- LlcpSocketcommunicationSocket=serverSocket.accept();
- if(communicationSocket!=null){
- //setp1-2:miu是什么,如何获取来的
- intmiu=communicationSocket.getRemoteMiu();
- intfragmentLength=(mFragmentLength==-1)?
- miu:Math.min(miu,mFragmentLength);
- //setp1-3:启动线程处理SnepMessenger
- newConnectionThread(communicationSocket,fragmentLength).start();
- }
- ......
- }
- }
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()来实现其创建功能,其中的参数为了书写方便都省略了。
- staticjobjectcom_android_nfc_NfcManager_doCreateLlcpServiceSocket(JNIEnv*e,jobjecto,
- jintnSap,jstringsn,jintmiu,jintrw,jintlinearBufferLength)
- {
- ......
- /*Createsocket*/
- /*setp1-1-1:函数在external/libnfc-nxp/src/phLibNfc.h声明,具体的函数作用,函数参数含义请查看代码中注释,&hLlcpSocket即是创建成功的Sokect的指针*/
- ret=phLibNfc_Llcp_Socket(phFriNfc_LlcpTransport_eConnectionOriented,
- &sOptions,
- &sWorkingBuffer,
- &hLlcpSocket,
- nfc_jni_llcp_transport_socket_err_callback,
- (void*)nat);
- ......
- /*CreatenewNativeLlcpServiceSocketobject,到此出现了我们分析到目前的mServerSocket的创建,返回的serviceSocket就是*/
- if(nfc_jni_cache_object(e,"com/android/nfc/nxp/NativeLlcpServiceSocket",&(serviceSocket))==-1)
- {
- ALOGE("LlcpSocketobjectcreationerror");
- gotoerror;
- }
- ......
- returnserviceSocket;
- }
附上一张思路图,就清晰点
Setp1-2:miu如何得来的,看下面分析图
看到这张图,可能只是对函数的调用过程有个清晰的了解,但是miu到底是如何获取到的呢??这次我们从函数的调用最后来分析,即phFriNfc_LlcpTransport_Connection.c这个文件的函数。
- NFCSTATUSphFriNfc_LlcpTransport_ConnectionOriented_SocketGetRemoteOptions(
- phFriNfc_LlcpTransport_Socket_t*pLlcpSocket,
- phLibNfc_Llcp_sSocketOptions_t*psRemoteOptions)
- {
- NFCSTATUSstatus=NFCSTATUS_SUCCESS;
- /*GetRemoteMIUX*/
- psRemoteOptions->miu=pLlcpSocket->remoteMIU;
- /*GetRemoteReceiveWindow*/
- psRemoteOptions->rw=pLlcpSocket->remoteRW;
- returnstatus;
- }
setp1-3: 启动线程处理SnepMessenger,从新开启一个Thread处理SnepMessage,处理code 还是SnepServer.java
- staticbooleanhandleRequest(SnepMessengermessenger,Callbackcallback)throwsIOException{
- SnepMessagerequest;
- ......
- //从SnepMessenger中取出SnepMessage
- request=messenger.getMessage();
- if(((request.getVersion()&0xF0)>>4)!=SnepMessage.VERSION_MAJOR){
- messenger.sendMessage(SnepMessage.getMessage(
- SnepMessage.RESPONSE_UNSUPPORTED_VERSION));
- }elseif(request.getField()==SnepMessage.REQUEST_GET){
- /*发送SnepMessage,SnepMessage来源于CallBack的实现,sendMessage把SnepMessage转换成byte[]通过LlcpSocketsocket发送数据*/
- messenger.sendMessage(callback.doGet(request.getAcceptableLength(),
- request.getNdefMessage()));
- }elseif(request.getField()==SnepMessage.REQUEST_PUT){
- if(DBG)Log.d(TAG,"puttingmessage"+request.toString());
- //发送SnepMessage,SnepMessage来源于Callback的实现
- messenger.sendMessage(callback.doPut(request.getNdefMessage()));
- }else{
- if(DBG)Log.d(TAG,"Unknownrequest("+request.getField()+")");
- messenger.sendMessage(SnepMessage.getMessage(
- SnepMessage.RESPONSE_BAD_REQUEST));
- }
- returntrue;
- }
- finalSnepServer.CallbackmDefaultSnepCallback=newSnepServer.Callback(){
- @Override
- publicSnepMessagedoPut(NdefMessagemsg){
- /*该方法中有个EventLogTags.writeNfcNdefReceived的调用,我始终没找到它的具体方法实现在哪儿*/
- onReceiveComplete(msg);
- returnSnepMessage.getMessage(SnepMessage.RESPONSE_SUCCESS);
- }
- @Override
- publicSnepMessagedoGet(intacceptableLength,NdefMessagemsg){
- NdefMessageresponse=mHandoverManager.tryHandoverRequest(msg);
- if(response!=null){
- onReceiveHandover();
- returnSnepMessage.getSuccessResponse(response);
- }else{
- returnSnepMessage.getMessage(SnepMessage.RESPONSE_NOT_FOUND);
- }
- }
- };
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是什么东西,故不做翻译了。