您的位置:首页 > 其它

NFC学习——NFC Enable 过程分析(三)

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

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

[html] view
plaincopy

public void enableDisable(boolean sendEnable, boolean receiveEnable) {

synchronized (this) {

if (!mIsReceiveEnabled && receiveEnable) {

//setp1:启动SnepServer

mDefaultSnepServer.start();

//setp2:启动NdefPushServer

mNdefPushServer.start();

if (mEchoServer != null) {

//setp3:启动EchoServer

mHandler.sendEmptyMessage(MSG_START_ECHOSERVER);

}

}

}

}

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
plaincopy

public void run() {

........

while (threadRunning) {

synchronized (SnepServer.this) {

//setp1-1:创建一个服务器端Socket连接

mServerSocket = NfcService.getInstance().createLlcpServerSocket(mServiceSap,

mServiceName, MIU, 1, 1024);

}

......

//接收Socket请求

LlcpSocket communicationSocket = serverSocket.accept();

if (communicationSocket != null) {

//setp1-2:miu 是什么,如何获取来的

int miu = communicationSocket.getRemoteMiu();

int fragmentLength = (mFragmentLength == -1) ?

miu : Math.min(miu, mFragmentLength);

//setp1-3: 启动线程处理SnepMessenger

new ConnectionThread(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()来实现其创建功能,其中的参数为了书写方便都省略了。

[html] view
plaincopy

static jobject com_android_nfc_NfcManager_doCreateLlcpServiceSocket(JNIEnv *e, jobject o,

jint nSap, jstring sn, jint miu, jint rw, jint linearBufferLength)

{

......

/* Create socket */

/*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);

......

/* Create new NativeLlcpServiceSocket object,到此出现了我们分析到目前的 mServerSocket的创建,返回的serviceSocket就是*/

if(nfc_jni_cache_object(e,"com/android/nfc/nxp/NativeLlcpServiceSocket",&(serviceSocket)) == -1)

{

ALOGE("Llcp Socket object creation error");

goto error;

}

......

return serviceSocket;

}

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



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



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

[html] view
plaincopy

NFCSTATUS phFriNfc_LlcpTransport_ConnectionOriented_SocketGetRemoteOptions(

phFriNfc_LlcpTransport_Socket_t* pLlcpSocket,

phLibNfc_Llcp_sSocketOptions_t* psRemoteOptions)

{

NFCSTATUS status = NFCSTATUS_SUCCESS;

/* Get Remote MIUX */

psRemoteOptions->miu = pLlcpSocket->remoteMIU;

/* Get Remote Receive Window */

psRemoteOptions->rw = pLlcpSocket->remoteRW;

return status;

}

上面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
plaincopy

static boolean handleRequest(SnepMessenger messenger, Callback callback) throws IOException {

SnepMessage request;

......

//从SnepMessenger中取出SnepMessage

request = messenger.getMessage();

if (((request.getVersion() & 0xF0) >> 4) != SnepMessage.VERSION_MAJOR) {

messenger.sendMessage(SnepMessage.getMessage(

SnepMessage.RESPONSE_UNSUPPORTED_VERSION));

} else if (request.getField() == SnepMessage.REQUEST_GET) {

/*发送SnepMessage,SnepMessage来源于CallBack的实现,sendMessage 把SnepMessage转换成byte[]通过LlcpSocket socket发送数据*/

messenger.sendMessage(callback.doGet(request.getAcceptableLength(),

request.getNdefMessage()));

} else if (request.getField() == SnepMessage.REQUEST_PUT) {

if (DBG) Log.d(TAG, "putting message " + request.toString());

//发送SnepMessage,SnepMessage来源于Callback的实现

messenger.sendMessage(callback.doPut(request.getNdefMessage()));

} else {

if (DBG) Log.d(TAG, "Unknown request (" + request.getField() +")");

messenger.sendMessage(SnepMessage.getMessage(

SnepMessage.RESPONSE_BAD_REQUEST));

}

return true;

}

上面code涉及到CallBack一个回调接口,它实现在P2pLinkManager.java中

[html] view
plaincopy

final SnepServer.Callback mDefaultSnepCallback = new SnepServer.Callback() {

@Override

public SnepMessage doPut(NdefMessage msg) {

/*该方法中有个EventLogTags.writeNfcNdefReceived 的调用,我始终没找到它的具体方法实现在哪儿*/

onReceiveComplete(msg);

return SnepMessage.getMessage(SnepMessage.RESPONSE_SUCCESS);

}

@Override

public SnepMessage doGet(int acceptableLength, NdefMessage msg) {

NdefMessage response = mHandoverManager.tryHandoverRequest(msg);

if (response != null) {

onReceiveHandover();

return SnepMessage.getSuccessResponse(response);

} else {

return SnepMessage.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是什么东西,故不做翻译了。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: