Home | History | Annotate | Download | only in jni
      1 /*
      2  * Copyright (C) 2012 The Android Open Source Project
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *      http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 
     17 /*
     18  *  Communicate with a peer using NFC-DEP, LLCP, SNEP.
     19  */
     20 #include "PeerToPeer.h"
     21 
     22 #include <android-base/stringprintf.h>
     23 #include <base/logging.h>
     24 #include <nativehelper/ScopedLocalRef.h>
     25 
     26 #include "JavaClassConstants.h"
     27 #include "NfcJniUtil.h"
     28 #include "llcp_defs.h"
     29 #include "nfc_config.h"
     30 
     31 using android::base::StringPrintf;
     32 
     33 /* Some older PN544-based solutions would only send the first SYMM back
     34  * (as an initiator) after the full LTO (750ms). But our connect timer
     35  * starts immediately, and hence we may timeout if the timer is set to
     36  * 1000 ms. Worse, this causes us to immediately connect to the NPP
     37  * socket, causing concurrency issues in that stack. Increase the default
     38  * timeout to 2000 ms, giving us enough time to complete the first connect.
     39  */
     40 #define LLCP_DATA_LINK_TIMEOUT 2000
     41 
     42 using namespace android;
     43 
     44 namespace android {
     45 extern void nativeNfcTag_registerNdefTypeHandler();
     46 extern void nativeNfcTag_deregisterNdefTypeHandler();
     47 extern void startRfDiscovery(bool isStart);
     48 extern bool isDiscoveryStarted();
     49 }  // namespace android
     50 
     51 PeerToPeer PeerToPeer::sP2p;
     52 const std::string P2pServer::sSnepServiceName("urn:nfc:sn:snep");
     53 
     54 extern bool nfc_debug_enabled;
     55 
     56 /*******************************************************************************
     57 **
     58 ** Function:        PeerToPeer
     59 **
     60 ** Description:     Initialize member variables.
     61 **
     62 ** Returns:         None
     63 **
     64 *******************************************************************************/
     65 PeerToPeer::PeerToPeer()
     66     : mRemoteWKS(0),
     67       mIsP2pListening(false),
     68       mP2pListenTechMask(NFA_TECHNOLOGY_MASK_A | NFA_TECHNOLOGY_MASK_F |
     69                          NFA_TECHNOLOGY_MASK_A_ACTIVE |
     70                          NFA_TECHNOLOGY_MASK_F_ACTIVE),
     71       mNextJniHandle(1) {
     72   memset(mServers, 0, sizeof(mServers));
     73   memset(mClients, 0, sizeof(mClients));
     74 }
     75 
     76 /*******************************************************************************
     77 **
     78 ** Function:        ~PeerToPeer
     79 **
     80 ** Description:     Free all resources.
     81 **
     82 ** Returns:         None
     83 **
     84 *******************************************************************************/
     85 PeerToPeer::~PeerToPeer() {}
     86 
     87 /*******************************************************************************
     88 **
     89 ** Function:        getInstance
     90 **
     91 ** Description:     Get the singleton PeerToPeer object.
     92 **
     93 ** Returns:         Singleton PeerToPeer object.
     94 **
     95 *******************************************************************************/
     96 PeerToPeer& PeerToPeer::getInstance() { return sP2p; }
     97 
     98 /*******************************************************************************
     99 **
    100 ** Function:        initialize
    101 **
    102 ** Description:     Initialize member variables.
    103 **
    104 ** Returns:         None
    105 **
    106 *******************************************************************************/
    107 void PeerToPeer::initialize() {
    108   DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf("PeerToPeer::initialize");
    109 
    110   if (NfcConfig::hasKey(NAME_P2P_LISTEN_TECH_MASK))
    111     mP2pListenTechMask = NfcConfig::getUnsigned(NAME_P2P_LISTEN_TECH_MASK);
    112 }
    113 
    114 /*******************************************************************************
    115 **
    116 ** Function:        findServerLocked
    117 **
    118 ** Description:     Find a PeerToPeer object by connection handle.
    119 **                  Assumes mMutex is already held
    120 **                  nfaP2pServerHandle: Connectin handle.
    121 **
    122 ** Returns:         PeerToPeer object.
    123 **
    124 *******************************************************************************/
    125 sp<P2pServer> PeerToPeer::findServerLocked(tNFA_HANDLE nfaP2pServerHandle) {
    126   for (int i = 0; i < sMax; i++) {
    127     if ((mServers[i] != NULL) &&
    128         (mServers[i]->mNfaP2pServerHandle == nfaP2pServerHandle)) {
    129       return (mServers[i]);
    130     }
    131   }
    132 
    133   // If here, not found
    134   return NULL;
    135 }
    136 
    137 /*******************************************************************************
    138 **
    139 ** Function:        findServerLocked
    140 **
    141 ** Description:     Find a PeerToPeer object by connection handle.
    142 **                  Assumes mMutex is already held
    143 **                  serviceName: service name.
    144 **
    145 ** Returns:         PeerToPeer object.
    146 **
    147 *******************************************************************************/
    148 sp<P2pServer> PeerToPeer::findServerLocked(tJNI_HANDLE jniHandle) {
    149   for (int i = 0; i < sMax; i++) {
    150     if ((mServers[i] != NULL) && (mServers[i]->mJniHandle == jniHandle)) {
    151       return (mServers[i]);
    152     }
    153   }
    154 
    155   // If here, not found
    156   return NULL;
    157 }
    158 
    159 /*******************************************************************************
    160 **
    161 ** Function:        findServerLocked
    162 **
    163 ** Description:     Find a PeerToPeer object by service name
    164 **                  Assumes mMutex is already heldf
    165 **                  serviceName: service name.
    166 **
    167 ** Returns:         PeerToPeer object.
    168 **
    169 *******************************************************************************/
    170 sp<P2pServer> PeerToPeer::findServerLocked(const char* serviceName) {
    171   for (int i = 0; i < sMax; i++) {
    172     if ((mServers[i] != NULL) &&
    173         (mServers[i]->mServiceName.compare(serviceName) == 0))
    174       return (mServers[i]);
    175   }
    176 
    177   // If here, not found
    178   return NULL;
    179 }
    180 
    181 /*******************************************************************************
    182 **
    183 ** Function:        registerServer
    184 **
    185 ** Description:     Let a server start listening for peer's connection request.
    186 **                  jniHandle: Connection handle.
    187 **                  serviceName: Server's service name.
    188 **
    189 ** Returns:         True if ok.
    190 **
    191 *******************************************************************************/
    192 bool PeerToPeer::registerServer(tJNI_HANDLE jniHandle,
    193                                 const char* serviceName) {
    194   static const char fn[] = "PeerToPeer::registerServer";
    195   DLOG_IF(INFO, nfc_debug_enabled)
    196       << StringPrintf("%s: enter; service name: %s  JNI handle: %u", fn,
    197                       serviceName, jniHandle);
    198   sp<P2pServer> pSrv = NULL;
    199 
    200   mMutex.lock();
    201   // Check if already registered
    202   if ((pSrv = findServerLocked(serviceName)) != NULL) {
    203     DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf(
    204         "%s: service name=%s  already registered, handle: 0x%04x", fn,
    205         serviceName, pSrv->mNfaP2pServerHandle);
    206 
    207     // Update JNI handle
    208     pSrv->mJniHandle = jniHandle;
    209     mMutex.unlock();
    210     return (true);
    211   }
    212 
    213   for (int ii = 0; ii < sMax; ii++) {
    214     if (mServers[ii] == NULL) {
    215       pSrv = mServers[ii] = new P2pServer(jniHandle, serviceName);
    216 
    217       DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf(
    218           "%s: added new p2p server  index: %d  handle: %u  name: %s", fn, ii,
    219           jniHandle, serviceName);
    220       break;
    221     }
    222   }
    223   mMutex.unlock();
    224 
    225   if (pSrv == NULL) {
    226     LOG(ERROR) << StringPrintf("%s: service name=%s  no free entry", fn,
    227                                serviceName);
    228     return (false);
    229   }
    230 
    231   if (pSrv->registerWithStack()) {
    232     DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf(
    233         "%s: got new p2p server h=0x%X", fn, pSrv->mNfaP2pServerHandle);
    234     return (true);
    235   } else {
    236     LOG(ERROR) << StringPrintf("%s: invalid server handle", fn);
    237     removeServer(jniHandle);
    238     return (false);
    239   }
    240 }
    241 
    242 /*******************************************************************************
    243 **
    244 ** Function:        removeServer
    245 **
    246 ** Description:     Free resources related to a server.
    247 **                  jniHandle: Connection handle.
    248 **
    249 ** Returns:         None
    250 **
    251 *******************************************************************************/
    252 void PeerToPeer::removeServer(tJNI_HANDLE jniHandle) {
    253   static const char fn[] = "PeerToPeer::removeServer";
    254 
    255   AutoMutex mutex(mMutex);
    256 
    257   for (int i = 0; i < sMax; i++) {
    258     if ((mServers[i] != NULL) && (mServers[i]->mJniHandle == jniHandle)) {
    259       DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf(
    260           "%s: server jni_handle: %u;  nfa_handle: 0x%04x; name: %s; index=%d",
    261           fn, jniHandle, mServers[i]->mNfaP2pServerHandle,
    262           mServers[i]->mServiceName.c_str(), i);
    263 
    264       mServers[i] = NULL;
    265       return;
    266     }
    267   }
    268   LOG(ERROR) << StringPrintf("%s: unknown server jni handle: %u", fn,
    269                              jniHandle);
    270 }
    271 
    272 /*******************************************************************************
    273 **
    274 ** Function:        llcpActivatedHandler
    275 **
    276 ** Description:     Receive LLLCP-activated event from stack.
    277 **                  nat: JVM-related data.
    278 **                  activated: Event data.
    279 **
    280 ** Returns:         None
    281 **
    282 *******************************************************************************/
    283 void PeerToPeer::llcpActivatedHandler(nfc_jni_native_data* nat,
    284                                       tNFA_LLCP_ACTIVATED& activated) {
    285   static const char fn[] = "PeerToPeer::llcpActivatedHandler";
    286   DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf("%s: enter", fn);
    287 
    288   // no longer need to receive NDEF message from a tag
    289   android::nativeNfcTag_deregisterNdefTypeHandler();
    290 
    291   mRemoteWKS = activated.remote_wks;
    292 
    293   JNIEnv* e = NULL;
    294   ScopedAttach attach(nat->vm, &e);
    295   if (e == NULL) {
    296     LOG(ERROR) << StringPrintf("%s: jni env is null", fn);
    297     return;
    298   }
    299 
    300   DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf("%s: get object class", fn);
    301   ScopedLocalRef<jclass> tag_cls(e, e->GetObjectClass(nat->cached_P2pDevice));
    302   if (e->ExceptionCheck()) {
    303     e->ExceptionClear();
    304     LOG(ERROR) << StringPrintf("%s: fail get p2p device", fn);
    305     return;
    306   }
    307 
    308   DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf("%s: instantiate", fn);
    309   /* New target instance */
    310   jmethodID ctor = e->GetMethodID(tag_cls.get(), "<init>", "()V");
    311   ScopedLocalRef<jobject> tag(e, e->NewObject(tag_cls.get(), ctor));
    312 
    313   /* Set P2P Target mode */
    314   jfieldID f = e->GetFieldID(tag_cls.get(), "mMode", "I");
    315 
    316   if (activated.is_initiator == TRUE) {
    317     DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf("%s: p2p initiator", fn);
    318     e->SetIntField(tag.get(), f, (jint)MODE_P2P_INITIATOR);
    319   } else {
    320     DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf("%s: p2p target", fn);
    321     e->SetIntField(tag.get(), f, (jint)MODE_P2P_TARGET);
    322   }
    323   /* Set LLCP version */
    324   f = e->GetFieldID(tag_cls.get(), "mLlcpVersion", "B");
    325   e->SetByteField(tag.get(), f, (jbyte)activated.remote_version);
    326 
    327   /* Set tag handle */
    328   f = e->GetFieldID(tag_cls.get(), "mHandle", "I");
    329   e->SetIntField(tag.get(), f,
    330                  (jint)0x1234);  // ?? This handle is not used for anything
    331 
    332   if (nat->tag != NULL) {
    333     e->DeleteGlobalRef(nat->tag);
    334   }
    335   nat->tag = e->NewGlobalRef(tag.get());
    336 
    337   DLOG_IF(INFO, nfc_debug_enabled)
    338       << StringPrintf("%s: notify nfc service", fn);
    339 
    340   /* Notify manager that new a P2P device was found */
    341   e->CallVoidMethod(nat->manager,
    342                     android::gCachedNfcManagerNotifyLlcpLinkActivation,
    343                     tag.get());
    344   if (e->ExceptionCheck()) {
    345     e->ExceptionClear();
    346     LOG(ERROR) << StringPrintf("%s: fail notify", fn);
    347   }
    348 
    349   DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf("%s: exit", fn);
    350 }
    351 
    352 /*******************************************************************************
    353 **
    354 ** Function:        llcpDeactivatedHandler
    355 **
    356 ** Description:     Receive LLLCP-deactivated event from stack.
    357 **                  nat: JVM-related data.
    358 **                  deactivated: Event data.
    359 **
    360 ** Returns:         None
    361 **
    362 *******************************************************************************/
    363 void PeerToPeer::llcpDeactivatedHandler(
    364     nfc_jni_native_data* nat, tNFA_LLCP_DEACTIVATED& /*deactivated*/) {
    365   static const char fn[] = "PeerToPeer::llcpDeactivatedHandler";
    366   DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf("%s: enter", fn);
    367 
    368   JNIEnv* e = NULL;
    369   ScopedAttach attach(nat->vm, &e);
    370   if (e == NULL) {
    371     LOG(ERROR) << StringPrintf("%s: jni env is null", fn);
    372     return;
    373   }
    374 
    375   DLOG_IF(INFO, nfc_debug_enabled)
    376       << StringPrintf("%s: notify nfc service", fn);
    377   /* Notify manager that the LLCP is lost or deactivated */
    378   e->CallVoidMethod(nat->manager,
    379                     android::gCachedNfcManagerNotifyLlcpLinkDeactivated,
    380                     nat->tag);
    381   if (e->ExceptionCheck()) {
    382     e->ExceptionClear();
    383     LOG(ERROR) << StringPrintf("%s: fail notify", fn);
    384   }
    385 
    386   // let the tag-reading code handle NDEF data event
    387   android::nativeNfcTag_registerNdefTypeHandler();
    388   DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf("%s: exit", fn);
    389 }
    390 
    391 void PeerToPeer::llcpFirstPacketHandler(nfc_jni_native_data* nat) {
    392   static const char fn[] = "PeerToPeer::llcpFirstPacketHandler";
    393   DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf("%s: enter", fn);
    394 
    395   JNIEnv* e = NULL;
    396   ScopedAttach attach(nat->vm, &e);
    397   if (e == NULL) {
    398     LOG(ERROR) << StringPrintf("%s: jni env is null", fn);
    399     return;
    400   }
    401 
    402   DLOG_IF(INFO, nfc_debug_enabled)
    403       << StringPrintf("%s: notify nfc service", fn);
    404   /* Notify manager that the LLCP is lost or deactivated */
    405   e->CallVoidMethod(nat->manager,
    406                     android::gCachedNfcManagerNotifyLlcpFirstPacketReceived,
    407                     nat->tag);
    408   if (e->ExceptionCheck()) {
    409     e->ExceptionClear();
    410     LOG(ERROR) << StringPrintf("%s: fail notify", fn);
    411   }
    412 
    413   DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf("%s: exit", fn);
    414 }
    415 /*******************************************************************************
    416 **
    417 ** Function:        accept
    418 **
    419 ** Description:     Accept a peer's request to connect.
    420 **                  serverJniHandle: Server's handle.
    421 **                  connJniHandle: Connection handle.
    422 **                  maxInfoUnit: Maximum information unit.
    423 **                  recvWindow: Receive window size.
    424 **
    425 ** Returns:         True if ok.
    426 **
    427 *******************************************************************************/
    428 bool PeerToPeer::accept(tJNI_HANDLE serverJniHandle, tJNI_HANDLE connJniHandle,
    429                         int maxInfoUnit, int recvWindow) {
    430   static const char fn[] = "PeerToPeer::accept";
    431   sp<P2pServer> pSrv = NULL;
    432 
    433   DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf(
    434       "%s: enter; server jni handle: %u; conn jni handle: %u; maxInfoUnit: %d; "
    435       "recvWindow: %d",
    436       fn, serverJniHandle, connJniHandle, maxInfoUnit, recvWindow);
    437 
    438   mMutex.lock();
    439   if ((pSrv = findServerLocked(serverJniHandle)) == NULL) {
    440     LOG(ERROR) << StringPrintf("%s: unknown server jni handle: %u", fn,
    441                                serverJniHandle);
    442     mMutex.unlock();
    443     return (false);
    444   }
    445   mMutex.unlock();
    446 
    447   return pSrv->accept(serverJniHandle, connJniHandle, maxInfoUnit, recvWindow);
    448 }
    449 
    450 /*******************************************************************************
    451 **
    452 ** Function:        deregisterServer
    453 **
    454 ** Description:     Stop a P2pServer from listening for peer.
    455 **
    456 ** Returns:         True if ok.
    457 **
    458 *******************************************************************************/
    459 bool PeerToPeer::deregisterServer(tJNI_HANDLE jniHandle) {
    460   static const char fn[] = "PeerToPeer::deregisterServer";
    461   DLOG_IF(INFO, nfc_debug_enabled)
    462       << StringPrintf("%s: enter; JNI handle: %u", fn, jniHandle);
    463   tNFA_STATUS nfaStat = NFA_STATUS_FAILED;
    464   sp<P2pServer> pSrv = NULL;
    465   bool isPollingTempStopped = false;
    466 
    467   mMutex.lock();
    468   if ((pSrv = findServerLocked(jniHandle)) == NULL) {
    469     LOG(ERROR) << StringPrintf("%s: unknown service handle: %u", fn, jniHandle);
    470     mMutex.unlock();
    471     return (false);
    472   }
    473   mMutex.unlock();
    474   if (isDiscoveryStarted()) {
    475     isPollingTempStopped = true;
    476     startRfDiscovery(false);
    477   }
    478 
    479   {
    480     // Server does not call NFA_P2pDisconnect(), so unblock the accept()
    481     SyncEventGuard guard(pSrv->mConnRequestEvent);
    482     pSrv->mConnRequestEvent.notifyOne();
    483   }
    484 
    485   nfaStat = NFA_P2pDeregister(pSrv->mNfaP2pServerHandle);
    486   if (nfaStat != NFA_STATUS_OK) {
    487     LOG(ERROR) << StringPrintf("%s: deregister error=0x%X", fn, nfaStat);
    488   }
    489 
    490   removeServer(jniHandle);
    491 
    492   if (isPollingTempStopped) {
    493     startRfDiscovery(true);
    494   }
    495 
    496   DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf("%s: exit", fn);
    497   return true;
    498 }
    499 
    500 /*******************************************************************************
    501 **
    502 ** Function:        createClient
    503 **
    504 ** Description:     Create a P2pClient object for a new out-bound connection.
    505 **                  jniHandle: Connection handle.
    506 **                  miu: Maximum information unit.
    507 **                  rw: Receive window size.
    508 **
    509 ** Returns:         True if ok.
    510 **
    511 *******************************************************************************/
    512 bool PeerToPeer::createClient(tJNI_HANDLE jniHandle, uint16_t miu, uint8_t rw) {
    513   static const char fn[] = "PeerToPeer::createClient";
    514   int i = 0;
    515   DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf(
    516       "%s: enter: jni h: %u  miu: %u  rw: %u", fn, jniHandle, miu, rw);
    517 
    518   mMutex.lock();
    519   sp<P2pClient> client = NULL;
    520   for (i = 0; i < sMax; i++) {
    521     if (mClients[i] == NULL) {
    522       mClients[i] = client = new P2pClient();
    523 
    524       mClients[i]->mClientConn->mJniHandle = jniHandle;
    525       mClients[i]->mClientConn->mMaxInfoUnit = miu;
    526       mClients[i]->mClientConn->mRecvWindow = rw;
    527       break;
    528     }
    529   }
    530   mMutex.unlock();
    531 
    532   if (client == NULL) {
    533     LOG(ERROR) << StringPrintf("%s: fail", fn);
    534     return (false);
    535   }
    536 
    537   DLOG_IF(INFO, nfc_debug_enabled)
    538       << StringPrintf("%s: pClient: 0x%p  assigned for client jniHandle: %u",
    539                       fn, client.get(), jniHandle);
    540 
    541   {
    542     SyncEventGuard guard(mClients[i]->mRegisteringEvent);
    543     NFA_P2pRegisterClient(NFA_P2P_DLINK_TYPE, nfaClientCallback);
    544     mClients[i]->mRegisteringEvent.wait();  // wait for NFA_P2P_REG_CLIENT_EVT
    545   }
    546 
    547   if (mClients[i]->mNfaP2pClientHandle != NFA_HANDLE_INVALID) {
    548     DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf(
    549         "%s: exit; new client jniHandle: %u   NFA Handle: 0x%04x", fn,
    550         jniHandle, client->mClientConn->mNfaConnHandle);
    551     return (true);
    552   } else {
    553     LOG(ERROR) << StringPrintf(
    554         "%s: FAILED; new client jniHandle: %u   NFA Handle: 0x%04x", fn,
    555         jniHandle, client->mClientConn->mNfaConnHandle);
    556     removeConn(jniHandle);
    557     return (false);
    558   }
    559 }
    560 
    561 /*******************************************************************************
    562 **
    563 ** Function:        removeConn
    564 **
    565 ** Description:     Free resources related to a connection.
    566 **                  jniHandle: Connection handle.
    567 **
    568 ** Returns:         None
    569 **
    570 *******************************************************************************/
    571 void PeerToPeer::removeConn(tJNI_HANDLE jniHandle) {
    572   static const char fn[] = "PeerToPeer::removeConn";
    573 
    574   AutoMutex mutex(mMutex);
    575   // If the connection is a for a client, delete the client itself
    576   for (int ii = 0; ii < sMax; ii++) {
    577     if ((mClients[ii] != NULL) &&
    578         (mClients[ii]->mClientConn->mJniHandle == jniHandle)) {
    579       if (mClients[ii]->mNfaP2pClientHandle != NFA_HANDLE_INVALID)
    580         NFA_P2pDeregister(mClients[ii]->mNfaP2pClientHandle);
    581 
    582       mClients[ii] = NULL;
    583       DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf(
    584           "%s: deleted client handle: %u  index: %u", fn, jniHandle, ii);
    585       return;
    586     }
    587   }
    588 
    589   // If the connection is for a server, just delete the connection
    590   for (int ii = 0; ii < sMax; ii++) {
    591     if (mServers[ii] != NULL) {
    592       if (mServers[ii]->removeServerConnection(jniHandle)) {
    593         return;
    594       }
    595     }
    596   }
    597 
    598   LOG(ERROR) << StringPrintf("%s: could not find handle: %u", fn, jniHandle);
    599 }
    600 
    601 /*******************************************************************************
    602 **
    603 ** Function:        connectConnOriented
    604 **
    605 ** Description:     Establish a connection-oriented connection to a peer.
    606 **                  jniHandle: Connection handle.
    607 **                  serviceName: Peer's service name.
    608 **
    609 ** Returns:         True if ok.
    610 **
    611 *******************************************************************************/
    612 bool PeerToPeer::connectConnOriented(tJNI_HANDLE jniHandle,
    613                                      const char* serviceName) {
    614   static const char fn[] = "PeerToPeer::connectConnOriented";
    615   DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf(
    616       "%s: enter; h: %u  service name=%s", fn, jniHandle, serviceName);
    617   bool stat = createDataLinkConn(jniHandle, serviceName, 0);
    618   DLOG_IF(INFO, nfc_debug_enabled)
    619       << StringPrintf("%s: exit; h: %u  stat: %u", fn, jniHandle, stat);
    620   return stat;
    621 }
    622 
    623 /*******************************************************************************
    624 **
    625 ** Function:        connectConnOriented
    626 **
    627 ** Description:     Establish a connection-oriented connection to a peer.
    628 **                  jniHandle: Connection handle.
    629 **                  destinationSap: Peer's service access point.
    630 **
    631 ** Returns:         True if ok.
    632 **
    633 *******************************************************************************/
    634 bool PeerToPeer::connectConnOriented(tJNI_HANDLE jniHandle,
    635                                      uint8_t destinationSap) {
    636   static const char fn[] = "PeerToPeer::connectConnOriented";
    637   DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf(
    638       "%s: enter; h: %u  dest sap: 0x%X", fn, jniHandle, destinationSap);
    639   bool stat = createDataLinkConn(jniHandle, NULL, destinationSap);
    640   DLOG_IF(INFO, nfc_debug_enabled)
    641       << StringPrintf("%s: exit; h: %u  stat: %u", fn, jniHandle, stat);
    642   return stat;
    643 }
    644 
    645 /*******************************************************************************
    646 **
    647 ** Function:        createDataLinkConn
    648 **
    649 ** Description:     Establish a connection-oriented connection to a peer.
    650 **                  jniHandle: Connection handle.
    651 **                  serviceName: Peer's service name.
    652 **                  destinationSap: Peer's service access point.
    653 **
    654 ** Returns:         True if ok.
    655 **
    656 *******************************************************************************/
    657 bool PeerToPeer::createDataLinkConn(tJNI_HANDLE jniHandle,
    658                                     const char* serviceName,
    659                                     uint8_t destinationSap) {
    660   static const char fn[] = "PeerToPeer::createDataLinkConn";
    661   DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf("%s: enter", fn);
    662   tNFA_STATUS nfaStat = NFA_STATUS_FAILED;
    663   sp<P2pClient> pClient = NULL;
    664 
    665   if ((pClient = findClient(jniHandle)) == NULL) {
    666     LOG(ERROR) << StringPrintf("%s: can't find client, JNI handle: %u", fn,
    667                                jniHandle);
    668     return (false);
    669   }
    670 
    671   {
    672     SyncEventGuard guard(pClient->mConnectingEvent);
    673     pClient->mIsConnecting = true;
    674 
    675     if (serviceName)
    676       nfaStat = NFA_P2pConnectByName(pClient->mNfaP2pClientHandle,
    677                                      const_cast<char*>(serviceName),
    678                                      pClient->mClientConn->mMaxInfoUnit,
    679                                      pClient->mClientConn->mRecvWindow);
    680     else if (destinationSap)
    681       nfaStat =
    682           NFA_P2pConnectBySap(pClient->mNfaP2pClientHandle, destinationSap,
    683                               pClient->mClientConn->mMaxInfoUnit,
    684                               pClient->mClientConn->mRecvWindow);
    685     if (nfaStat == NFA_STATUS_OK) {
    686       DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf(
    687           "%s: wait for connected event  mConnectingEvent: 0x%p", fn,
    688           pClient.get());
    689       pClient->mConnectingEvent.wait();
    690     }
    691   }
    692 
    693   if (nfaStat == NFA_STATUS_OK) {
    694     if (pClient->mClientConn->mNfaConnHandle == NFA_HANDLE_INVALID) {
    695       removeConn(jniHandle);
    696       nfaStat = NFA_STATUS_FAILED;
    697     } else
    698       pClient->mIsConnecting = false;
    699   } else {
    700     removeConn(jniHandle);
    701     LOG(ERROR) << StringPrintf("%s: fail; error=0x%X", fn, nfaStat);
    702   }
    703 
    704   DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf("%s: exit", fn);
    705   return nfaStat == NFA_STATUS_OK;
    706 }
    707 
    708 /*******************************************************************************
    709 **
    710 ** Function:        findClient
    711 **
    712 ** Description:     Find a PeerToPeer object with a client connection handle.
    713 **                  nfaConnHandle: Connection handle.
    714 **
    715 ** Returns:         PeerToPeer object.
    716 **
    717 *******************************************************************************/
    718 sp<P2pClient> PeerToPeer::findClient(tNFA_HANDLE nfaConnHandle) {
    719   AutoMutex mutex(mMutex);
    720   for (int i = 0; i < sMax; i++) {
    721     if ((mClients[i] != NULL) &&
    722         (mClients[i]->mNfaP2pClientHandle == nfaConnHandle))
    723       return (mClients[i]);
    724   }
    725   return (NULL);
    726 }
    727 
    728 /*******************************************************************************
    729 **
    730 ** Function:        findClient
    731 **
    732 ** Description:     Find a PeerToPeer object with a client connection handle.
    733 **                  jniHandle: Connection handle.
    734 **
    735 ** Returns:         PeerToPeer object.
    736 **
    737 *******************************************************************************/
    738 sp<P2pClient> PeerToPeer::findClient(tJNI_HANDLE jniHandle) {
    739   AutoMutex mutex(mMutex);
    740   for (int i = 0; i < sMax; i++) {
    741     if ((mClients[i] != NULL) &&
    742         (mClients[i]->mClientConn->mJniHandle == jniHandle))
    743       return (mClients[i]);
    744   }
    745   return (NULL);
    746 }
    747 
    748 /*******************************************************************************
    749 **
    750 ** Function:        findClientCon
    751 **
    752 ** Description:     Find a PeerToPeer object with a client connection handle.
    753 **                  nfaConnHandle: Connection handle.
    754 **
    755 ** Returns:         PeerToPeer object.
    756 **
    757 *******************************************************************************/
    758 sp<P2pClient> PeerToPeer::findClientCon(tNFA_HANDLE nfaConnHandle) {
    759   AutoMutex mutex(mMutex);
    760   for (int i = 0; i < sMax; i++) {
    761     if ((mClients[i] != NULL) &&
    762         (mClients[i]->mClientConn->mNfaConnHandle == nfaConnHandle))
    763       return (mClients[i]);
    764   }
    765   return (NULL);
    766 }
    767 
    768 /*******************************************************************************
    769 **
    770 ** Function:        findConnection
    771 **
    772 ** Description:     Find a PeerToPeer object with a connection handle.
    773 **                  nfaConnHandle: Connection handle.
    774 **
    775 ** Returns:         PeerToPeer object.
    776 **
    777 *******************************************************************************/
    778 sp<NfaConn> PeerToPeer::findConnection(tNFA_HANDLE nfaConnHandle) {
    779   AutoMutex mutex(mMutex);
    780   // First, look through all the client control blocks
    781   for (int ii = 0; ii < sMax; ii++) {
    782     if ((mClients[ii] != NULL) &&
    783         (mClients[ii]->mClientConn->mNfaConnHandle == nfaConnHandle)) {
    784       return mClients[ii]->mClientConn;
    785     }
    786   }
    787 
    788   // Not found yet. Look through all the server control blocks
    789   for (int ii = 0; ii < sMax; ii++) {
    790     if (mServers[ii] != NULL) {
    791       sp<NfaConn> conn = mServers[ii]->findServerConnection(nfaConnHandle);
    792       if (conn != NULL) {
    793         return conn;
    794       }
    795     }
    796   }
    797 
    798   // Not found...
    799   return NULL;
    800 }
    801 
    802 /*******************************************************************************
    803 **
    804 ** Function:        findConnection
    805 **
    806 ** Description:     Find a PeerToPeer object with a connection handle.
    807 **                  jniHandle: Connection handle.
    808 **
    809 ** Returns:         PeerToPeer object.
    810 **
    811 *******************************************************************************/
    812 sp<NfaConn> PeerToPeer::findConnection(tJNI_HANDLE jniHandle) {
    813   AutoMutex mutex(mMutex);
    814   // First, look through all the client control blocks
    815   for (int ii = 0; ii < sMax; ii++) {
    816     if ((mClients[ii] != NULL) &&
    817         (mClients[ii]->mClientConn->mJniHandle == jniHandle)) {
    818       return mClients[ii]->mClientConn;
    819     }
    820   }
    821 
    822   // Not found yet. Look through all the server control blocks
    823   for (int ii = 0; ii < sMax; ii++) {
    824     if (mServers[ii] != NULL) {
    825       sp<NfaConn> conn = mServers[ii]->findServerConnection(jniHandle);
    826       if (conn != NULL) {
    827         return conn;
    828       }
    829     }
    830   }
    831 
    832   // Not found...
    833   return NULL;
    834 }
    835 
    836 /*******************************************************************************
    837 **
    838 ** Function:        send
    839 **
    840 ** Description:     Send data to peer.
    841 **                  jniHandle: Handle of connection.
    842 **                  buffer: Buffer of data.
    843 **                  bufferLen: Length of data.
    844 **
    845 ** Returns:         True if ok.
    846 **
    847 *******************************************************************************/
    848 bool PeerToPeer::send(tJNI_HANDLE jniHandle, uint8_t* buffer,
    849                       uint16_t bufferLen) {
    850   static const char fn[] = "PeerToPeer::send";
    851   tNFA_STATUS nfaStat = NFA_STATUS_FAILED;
    852   sp<NfaConn> pConn = NULL;
    853 
    854   if ((pConn = findConnection(jniHandle)) == NULL) {
    855     LOG(ERROR) << StringPrintf("%s: can't find connection handle: %u", fn,
    856                                jniHandle);
    857     return (false);
    858   }
    859 
    860   DLOG_IF(INFO, nfc_debug_enabled)
    861       << StringPrintf("%s: send data; jniHandle: %u  nfaHandle: 0x%04X", fn,
    862                       pConn->mJniHandle, pConn->mNfaConnHandle);
    863 
    864   while (true) {
    865     SyncEventGuard guard(pConn->mCongEvent);
    866     nfaStat = NFA_P2pSendData(pConn->mNfaConnHandle, bufferLen, buffer);
    867     if (nfaStat == NFA_STATUS_CONGESTED)
    868       pConn->mCongEvent.wait();  // wait for NFA_P2P_CONGEST_EVT
    869     else
    870       break;
    871 
    872     if (pConn->mNfaConnHandle ==
    873         NFA_HANDLE_INVALID)  // peer already disconnected
    874     {
    875       DLOG_IF(INFO, nfc_debug_enabled)
    876           << StringPrintf("%s: peer disconnected", fn);
    877       return (false);
    878     }
    879   }
    880 
    881   if (nfaStat == NFA_STATUS_OK)
    882     DLOG_IF(INFO, nfc_debug_enabled)
    883         << StringPrintf("%s: exit OK; JNI handle: %u  NFA Handle: 0x%04x", fn,
    884                         jniHandle, pConn->mNfaConnHandle);
    885   else
    886     LOG(ERROR) << StringPrintf(
    887         "%s: Data not sent; JNI handle: %u  NFA Handle: 0x%04x  error: 0x%04x",
    888         fn, jniHandle, pConn->mNfaConnHandle, nfaStat);
    889 
    890   return nfaStat == NFA_STATUS_OK;
    891 }
    892 
    893 /*******************************************************************************
    894 **
    895 ** Function:        receive
    896 **
    897 ** Description:     Receive data from peer.
    898 **                  jniHandle: Handle of connection.
    899 **                  buffer: Buffer to store data.
    900 **                  bufferLen: Max length of buffer.
    901 **                  actualLen: Actual length received.
    902 **
    903 ** Returns:         True if ok.
    904 **
    905 *******************************************************************************/
    906 bool PeerToPeer::receive(tJNI_HANDLE jniHandle, uint8_t* buffer,
    907                          uint16_t bufferLen, uint16_t& actualLen) {
    908   static const char fn[] = "PeerToPeer::receive";
    909   DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf(
    910       "%s: enter; jniHandle: %u  bufferLen: %u", fn, jniHandle, bufferLen);
    911   sp<NfaConn> pConn = NULL;
    912   tNFA_STATUS stat = NFA_STATUS_FAILED;
    913   uint32_t actualDataLen2 = 0;
    914   bool isMoreData = TRUE;
    915   bool retVal = false;
    916 
    917   if ((pConn = findConnection(jniHandle)) == NULL) {
    918     LOG(ERROR) << StringPrintf("%s: can't find connection handle: %u", fn,
    919                                jniHandle);
    920     return (false);
    921   }
    922 
    923   DLOG_IF(INFO, nfc_debug_enabled)
    924       << StringPrintf("%s: jniHandle: %u  nfaHandle: 0x%04X  buf len=%u", fn,
    925                       pConn->mJniHandle, pConn->mNfaConnHandle, bufferLen);
    926 
    927   while (pConn->mNfaConnHandle != NFA_HANDLE_INVALID) {
    928     // NFA_P2pReadData() is synchronous
    929     stat = NFA_P2pReadData(pConn->mNfaConnHandle, bufferLen, &actualDataLen2,
    930                            buffer, &isMoreData);
    931     if ((stat == NFA_STATUS_OK) && (actualDataLen2 > 0))  // received some data
    932     {
    933       actualLen = (uint16_t)actualDataLen2;
    934       retVal = true;
    935       break;
    936     }
    937     DLOG_IF(INFO, nfc_debug_enabled)
    938         << StringPrintf("%s: waiting for data...", fn);
    939     {
    940       SyncEventGuard guard(pConn->mReadEvent);
    941       pConn->mReadEvent.wait();
    942     }
    943   }  // while
    944 
    945   DLOG_IF(INFO, nfc_debug_enabled)
    946       << StringPrintf("%s: exit; nfa h: 0x%X  ok: %u  actual len: %u", fn,
    947                       pConn->mNfaConnHandle, retVal, actualLen);
    948   return retVal;
    949 }
    950 
    951 /*******************************************************************************
    952 **
    953 ** Function:        disconnectConnOriented
    954 **
    955 ** Description:     Disconnect a connection-oriented connection with peer.
    956 **                  jniHandle: Handle of connection.
    957 **
    958 ** Returns:         True if ok.
    959 **
    960 *******************************************************************************/
    961 bool PeerToPeer::disconnectConnOriented(tJNI_HANDLE jniHandle) {
    962   static const char fn[] = "PeerToPeer::disconnectConnOriented";
    963   tNFA_STATUS nfaStat = NFA_STATUS_FAILED;
    964   sp<P2pClient> pClient = NULL;
    965   sp<NfaConn> pConn = NULL;
    966 
    967   DLOG_IF(INFO, nfc_debug_enabled)
    968       << StringPrintf("%s: enter; jni handle: %u", fn, jniHandle);
    969 
    970   if ((pConn = findConnection(jniHandle)) == NULL) {
    971     LOG(ERROR) << StringPrintf("%s: can't find connection handle: %u", fn,
    972                                jniHandle);
    973     return (false);
    974   }
    975 
    976   // If this is a client, he may not be connected yet, so unblock him just in
    977   // case
    978   if (((pClient = findClient(jniHandle)) != NULL) && (pClient->mIsConnecting)) {
    979     SyncEventGuard guard(pClient->mConnectingEvent);
    980     pClient->mConnectingEvent.notifyOne();
    981     return (true);
    982   }
    983 
    984   {
    985     SyncEventGuard guard1(pConn->mCongEvent);
    986     pConn->mCongEvent.notifyOne();  // unblock send() if congested
    987   }
    988   {
    989     SyncEventGuard guard2(pConn->mReadEvent);
    990     pConn->mReadEvent.notifyOne();  // unblock receive()
    991   }
    992 
    993   if (pConn->mNfaConnHandle != NFA_HANDLE_INVALID) {
    994     DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf(
    995         "%s: try disconn nfa h=0x%04X", fn, pConn->mNfaConnHandle);
    996     SyncEventGuard guard(pConn->mDisconnectingEvent);
    997     nfaStat = NFA_P2pDisconnect(pConn->mNfaConnHandle, FALSE);
    998 
    999     if (nfaStat != NFA_STATUS_OK)
   1000       LOG(ERROR) << StringPrintf("%s: fail p2p disconnect", fn);
   1001     else
   1002       pConn->mDisconnectingEvent.wait();
   1003   }
   1004 
   1005   mDisconnectMutex.lock();
   1006   removeConn(jniHandle);
   1007   mDisconnectMutex.unlock();
   1008 
   1009   DLOG_IF(INFO, nfc_debug_enabled)
   1010       << StringPrintf("%s: exit; jni handle: %u", fn, jniHandle);
   1011   return nfaStat == NFA_STATUS_OK;
   1012 }
   1013 
   1014 /*******************************************************************************
   1015 **
   1016 ** Function:        getRemoteMaxInfoUnit
   1017 **
   1018 ** Description:     Get peer's max information unit.
   1019 **                  jniHandle: Handle of the connection.
   1020 **
   1021 ** Returns:         Peer's max information unit.
   1022 **
   1023 *******************************************************************************/
   1024 uint16_t PeerToPeer::getRemoteMaxInfoUnit(tJNI_HANDLE jniHandle) {
   1025   static const char fn[] = "PeerToPeer::getRemoteMaxInfoUnit";
   1026   sp<NfaConn> pConn = NULL;
   1027 
   1028   if ((pConn = findConnection(jniHandle)) == NULL) {
   1029     LOG(ERROR) << StringPrintf("%s: can't find client  jniHandle: %u", fn,
   1030                                jniHandle);
   1031     return 0;
   1032   }
   1033   DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf(
   1034       "%s: jniHandle: %u   MIU: %u", fn, jniHandle, pConn->mRemoteMaxInfoUnit);
   1035   return (pConn->mRemoteMaxInfoUnit);
   1036 }
   1037 
   1038 /*******************************************************************************
   1039 **
   1040 ** Function:        getRemoteRecvWindow
   1041 **
   1042 ** Description:     Get peer's receive window size.
   1043 **                  jniHandle: Handle of the connection.
   1044 **
   1045 ** Returns:         Peer's receive window size.
   1046 **
   1047 *******************************************************************************/
   1048 uint8_t PeerToPeer::getRemoteRecvWindow(tJNI_HANDLE jniHandle) {
   1049   static const char fn[] = "PeerToPeer::getRemoteRecvWindow";
   1050   DLOG_IF(INFO, nfc_debug_enabled)
   1051       << StringPrintf("%s: client jni handle: %u", fn, jniHandle);
   1052   sp<NfaConn> pConn = NULL;
   1053 
   1054   if ((pConn = findConnection(jniHandle)) == NULL) {
   1055     LOG(ERROR) << StringPrintf("%s: can't find client", fn);
   1056     return 0;
   1057   }
   1058   return pConn->mRemoteRecvWindow;
   1059 }
   1060 
   1061 /*******************************************************************************
   1062 **
   1063 ** Function:        setP2pListenMask
   1064 **
   1065 ** Description:     Sets the p2p listen technology mask.
   1066 **                  p2pListenMask: the p2p listen mask to be set?
   1067 **
   1068 ** Returns:         None
   1069 **
   1070 *******************************************************************************/
   1071 void PeerToPeer::setP2pListenMask(tNFA_TECHNOLOGY_MASK p2pListenMask) {
   1072   mP2pListenTechMask = p2pListenMask;
   1073 }
   1074 
   1075 /*******************************************************************************
   1076 **
   1077 ** Function:        getP2pListenMask
   1078 **
   1079 ** Description:     Get the set of technologies that P2P is listening.
   1080 **
   1081 ** Returns:         Set of technologies.
   1082 **
   1083 *******************************************************************************/
   1084 tNFA_TECHNOLOGY_MASK PeerToPeer::getP2pListenMask() {
   1085   return mP2pListenTechMask;
   1086 }
   1087 
   1088 /*******************************************************************************
   1089 **
   1090 ** Function:        resetP2pListenMask
   1091 **
   1092 ** Description:     Reset the p2p listen technology mask to initial value.
   1093 **
   1094 ** Returns:         None.
   1095 **
   1096 *******************************************************************************/
   1097 void PeerToPeer::resetP2pListenMask() {
   1098   mP2pListenTechMask = NFA_TECHNOLOGY_MASK_A | NFA_TECHNOLOGY_MASK_F |
   1099                        NFA_TECHNOLOGY_MASK_A_ACTIVE |
   1100                        NFA_TECHNOLOGY_MASK_F_ACTIVE;
   1101   if (NfcConfig::hasKey("P2P_LISTEN_TECH_MASK"))
   1102     mP2pListenTechMask = NfcConfig::getUnsigned("P2P_LISTEN_TECH_MASK");
   1103 }
   1104 
   1105 /*******************************************************************************
   1106 **
   1107 ** Function:        enableP2pListening
   1108 **
   1109 ** Description:     Start/stop polling/listening to peer that supports P2P.
   1110 **                  isEnable: Is enable polling/listening?
   1111 **
   1112 ** Returns:         None
   1113 **
   1114 *******************************************************************************/
   1115 void PeerToPeer::enableP2pListening(bool isEnable) {
   1116   static const char fn[] = "PeerToPeer::enableP2pListening";
   1117   tNFA_STATUS nfaStat = NFA_STATUS_FAILED;
   1118 
   1119   DLOG_IF(INFO, nfc_debug_enabled)
   1120       << StringPrintf("%s: enter isEnable: %u  mIsP2pListening: %u", fn,
   1121                       isEnable, mIsP2pListening);
   1122 
   1123   // If request to enable P2P listening, and we were not already listening
   1124   if ((isEnable == true) && (mIsP2pListening == false) &&
   1125       (mP2pListenTechMask != 0)) {
   1126     SyncEventGuard guard(mSetTechEvent);
   1127     if ((nfaStat = NFA_SetP2pListenTech(mP2pListenTechMask)) == NFA_STATUS_OK) {
   1128       mSetTechEvent.wait();
   1129       mIsP2pListening = true;
   1130     } else
   1131       LOG(ERROR) << StringPrintf("%s: fail enable listen; error=0x%X", fn,
   1132                                  nfaStat);
   1133   } else if ((isEnable == false) && (mIsP2pListening == true)) {
   1134     SyncEventGuard guard(mSetTechEvent);
   1135     // Request to disable P2P listening, check if it was enabled
   1136     if ((nfaStat = NFA_SetP2pListenTech(0)) == NFA_STATUS_OK) {
   1137       mSetTechEvent.wait();
   1138       mIsP2pListening = false;
   1139     } else
   1140       LOG(ERROR) << StringPrintf("%s: fail disable listen; error=0x%X", fn,
   1141                                  nfaStat);
   1142   }
   1143   DLOG_IF(INFO, nfc_debug_enabled)
   1144       << StringPrintf("%s: exit; mIsP2pListening: %u", fn, mIsP2pListening);
   1145 }
   1146 
   1147 /*******************************************************************************
   1148 **
   1149 ** Function:        handleNfcOnOff
   1150 **
   1151 ** Description:     Handle events related to turning NFC on/off by the user.
   1152 **                  isOn: Is NFC turning on?
   1153 **
   1154 ** Returns:         None
   1155 **
   1156 *******************************************************************************/
   1157 void PeerToPeer::handleNfcOnOff(bool isOn) {
   1158   static const char fn[] = "PeerToPeer::handleNfcOnOff";
   1159   DLOG_IF(INFO, nfc_debug_enabled)
   1160       << StringPrintf("%s: enter; is on=%u", fn, isOn);
   1161 
   1162   mIsP2pListening = false;  // In both cases, P2P will not be listening
   1163 
   1164   AutoMutex mutex(mMutex);
   1165   if (isOn) {
   1166     // Start with no clients or servers
   1167     memset(mServers, 0, sizeof(mServers));
   1168     memset(mClients, 0, sizeof(mClients));
   1169   } else {
   1170     // Disconnect through all the clients
   1171     for (int ii = 0; ii < sMax; ii++) {
   1172       if (mClients[ii] != NULL) {
   1173         if (mClients[ii]->mClientConn->mNfaConnHandle == NFA_HANDLE_INVALID) {
   1174           SyncEventGuard guard(mClients[ii]->mConnectingEvent);
   1175           mClients[ii]->mConnectingEvent.notifyOne();
   1176         } else {
   1177           mClients[ii]->mClientConn->mNfaConnHandle = NFA_HANDLE_INVALID;
   1178           {
   1179             SyncEventGuard guard1(mClients[ii]->mClientConn->mCongEvent);
   1180             mClients[ii]
   1181                 ->mClientConn->mCongEvent.notifyOne();  // unblock send()
   1182           }
   1183           {
   1184             SyncEventGuard guard2(mClients[ii]->mClientConn->mReadEvent);
   1185             mClients[ii]
   1186                 ->mClientConn->mReadEvent.notifyOne();  // unblock receive()
   1187           }
   1188         }
   1189       }
   1190     }  // loop
   1191 
   1192     // Now look through all the server control blocks
   1193     for (int ii = 0; ii < sMax; ii++) {
   1194       if (mServers[ii] != NULL) {
   1195         mServers[ii]->unblockAll();
   1196       }
   1197     }  // loop
   1198   }
   1199   DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf("%s: exit", fn);
   1200 }
   1201 
   1202 /*******************************************************************************
   1203 **
   1204 ** Function:        nfaServerCallback
   1205 **
   1206 ** Description:     Receive LLCP-related events from the stack.
   1207 **                  p2pEvent: Event code.
   1208 **                  eventData: Event data.
   1209 **
   1210 ** Returns:         None
   1211 **
   1212 *******************************************************************************/
   1213 void PeerToPeer::nfaServerCallback(tNFA_P2P_EVT p2pEvent,
   1214                                    tNFA_P2P_EVT_DATA* eventData) {
   1215   static const char fn[] = "PeerToPeer::nfaServerCallback";
   1216   sp<P2pServer> pSrv = NULL;
   1217   sp<NfaConn> pConn = NULL;
   1218 
   1219   DLOG_IF(INFO, nfc_debug_enabled)
   1220       << StringPrintf("%s: enter; event=0x%X", fn, p2pEvent);
   1221 
   1222   switch (p2pEvent) {
   1223     case NFA_P2P_REG_SERVER_EVT:  // NFA_P2pRegisterServer() has started to
   1224                                   // listen
   1225       DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf(
   1226           "%s: NFA_P2P_REG_SERVER_EVT; handle: 0x%04x; service sap=0x%02x  "
   1227           "name: "
   1228           "%s",
   1229           fn, eventData->reg_server.server_handle,
   1230           eventData->reg_server.server_sap, eventData->reg_server.service_name);
   1231 
   1232       sP2p.mMutex.lock();
   1233       pSrv = sP2p.findServerLocked(eventData->reg_server.service_name);
   1234       sP2p.mMutex.unlock();
   1235       if (pSrv == NULL) {
   1236         LOG(ERROR) << StringPrintf(
   1237             "%s: NFA_P2P_REG_SERVER_EVT for unknown service: %s", fn,
   1238             eventData->reg_server.service_name);
   1239       } else {
   1240         SyncEventGuard guard(pSrv->mRegServerEvent);
   1241         pSrv->mNfaP2pServerHandle = eventData->reg_server.server_handle;
   1242         pSrv->mRegServerEvent.notifyOne();  // unblock registerServer()
   1243       }
   1244       break;
   1245 
   1246     case NFA_P2P_ACTIVATED_EVT:  // remote device has activated
   1247       DLOG_IF(INFO, nfc_debug_enabled)
   1248           << StringPrintf("%s: NFA_P2P_ACTIVATED_EVT; handle: 0x%04x", fn,
   1249                           eventData->activated.handle);
   1250       break;
   1251 
   1252     case NFA_P2P_DEACTIVATED_EVT:
   1253       DLOG_IF(INFO, nfc_debug_enabled)
   1254           << StringPrintf("%s: NFA_P2P_DEACTIVATED_EVT; handle: 0x%04x", fn,
   1255                           eventData->activated.handle);
   1256       break;
   1257 
   1258     case NFA_P2P_CONN_REQ_EVT:
   1259       DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf(
   1260           "%s: NFA_P2P_CONN_REQ_EVT; nfa server h=0x%04x; nfa conn h=0x%04x; "
   1261           "remote sap=0x%02x",
   1262           fn, eventData->conn_req.server_handle,
   1263           eventData->conn_req.conn_handle, eventData->conn_req.remote_sap);
   1264 
   1265       sP2p.mMutex.lock();
   1266       pSrv = sP2p.findServerLocked(eventData->conn_req.server_handle);
   1267       sP2p.mMutex.unlock();
   1268       if (pSrv == NULL) {
   1269         LOG(ERROR) << StringPrintf("%s: NFA_P2P_CONN_REQ_EVT; unknown server h",
   1270                                    fn);
   1271         return;
   1272       }
   1273       DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf(
   1274           "%s: NFA_P2P_CONN_REQ_EVT; server jni h=%u", fn, pSrv->mJniHandle);
   1275 
   1276       // Look for a connection block that is waiting (handle invalid)
   1277       if ((pConn = pSrv->findServerConnection(
   1278                (tNFA_HANDLE)NFA_HANDLE_INVALID)) == NULL) {
   1279         LOG(ERROR) << StringPrintf(
   1280             "%s: NFA_P2P_CONN_REQ_EVT; server not listening", fn);
   1281       } else {
   1282         SyncEventGuard guard(pSrv->mConnRequestEvent);
   1283         pConn->mNfaConnHandle = eventData->conn_req.conn_handle;
   1284         pConn->mRemoteMaxInfoUnit = eventData->conn_req.remote_miu;
   1285         pConn->mRemoteRecvWindow = eventData->conn_req.remote_rw;
   1286         DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf(
   1287             "%s: NFA_P2P_CONN_REQ_EVT; server jni h=%u; conn jni "
   1288             "h=%u; notify conn req",
   1289             fn, pSrv->mJniHandle, pConn->mJniHandle);
   1290         pSrv->mConnRequestEvent.notifyOne();  // unblock accept()
   1291       }
   1292       break;
   1293 
   1294     case NFA_P2P_CONNECTED_EVT:
   1295       DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf(
   1296           "%s: NFA_P2P_CONNECTED_EVT; h=0x%x  remote sap=0x%X", fn,
   1297           eventData->connected.client_handle, eventData->connected.remote_sap);
   1298       break;
   1299 
   1300     case NFA_P2P_DISC_EVT:
   1301       DLOG_IF(INFO, nfc_debug_enabled)
   1302           << StringPrintf("%s: NFA_P2P_DISC_EVT; h=0x%04x; reason=0x%X", fn,
   1303                           eventData->disc.handle, eventData->disc.reason);
   1304       // Look for the connection block
   1305       if ((pConn = sP2p.findConnection(eventData->disc.handle)) == NULL) {
   1306         LOG(ERROR) << StringPrintf(
   1307             "%s: NFA_P2P_DISC_EVT: can't find conn for NFA handle: 0x%04x", fn,
   1308             eventData->disc.handle);
   1309       } else {
   1310         sP2p.mDisconnectMutex.lock();
   1311         pConn->mNfaConnHandle = NFA_HANDLE_INVALID;
   1312         {
   1313           DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf(
   1314               "%s: NFA_P2P_DISC_EVT; try guard disconn event", fn);
   1315           SyncEventGuard guard3(pConn->mDisconnectingEvent);
   1316           pConn->mDisconnectingEvent.notifyOne();
   1317           DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf(
   1318               "%s: NFA_P2P_DISC_EVT; notified disconn event", fn);
   1319         }
   1320         {
   1321           DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf(
   1322               "%s: NFA_P2P_DISC_EVT; try guard congest event", fn);
   1323           SyncEventGuard guard1(pConn->mCongEvent);
   1324           pConn->mCongEvent.notifyOne();  // unblock write (if congested)
   1325           DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf(
   1326               "%s: NFA_P2P_DISC_EVT; notified congest event", fn);
   1327         }
   1328         {
   1329           DLOG_IF(INFO, nfc_debug_enabled)
   1330               << StringPrintf("%s: NFA_P2P_DISC_EVT; try guard read event", fn);
   1331           SyncEventGuard guard2(pConn->mReadEvent);
   1332           pConn->mReadEvent.notifyOne();  // unblock receive()
   1333           DLOG_IF(INFO, nfc_debug_enabled)
   1334               << StringPrintf("%s: NFA_P2P_DISC_EVT; notified read event", fn);
   1335         }
   1336         sP2p.mDisconnectMutex.unlock();
   1337       }
   1338       break;
   1339 
   1340     case NFA_P2P_DATA_EVT:
   1341       // Look for the connection block
   1342       if ((pConn = sP2p.findConnection(eventData->data.handle)) == NULL) {
   1343         LOG(ERROR) << StringPrintf(
   1344             "%s: NFA_P2P_DATA_EVT: can't find conn for NFA handle: 0x%04x", fn,
   1345             eventData->data.handle);
   1346       } else {
   1347         DLOG_IF(INFO, nfc_debug_enabled)
   1348             << StringPrintf("%s: NFA_P2P_DATA_EVT; h=0x%X; remote sap=0x%X", fn,
   1349                             eventData->data.handle, eventData->data.remote_sap);
   1350         SyncEventGuard guard(pConn->mReadEvent);
   1351         pConn->mReadEvent.notifyOne();
   1352       }
   1353       break;
   1354 
   1355     case NFA_P2P_CONGEST_EVT:
   1356       // Look for the connection block
   1357       if ((pConn = sP2p.findConnection(eventData->congest.handle)) == NULL) {
   1358         LOG(ERROR) << StringPrintf(
   1359             "%s: NFA_P2P_CONGEST_EVT: can't find conn for NFA handle: 0x%04x",
   1360             fn, eventData->congest.handle);
   1361       } else {
   1362         DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf(
   1363             "%s: NFA_P2P_CONGEST_EVT; nfa handle: 0x%04x  congested: %u", fn,
   1364             eventData->congest.handle, eventData->congest.is_congested);
   1365         if (eventData->congest.is_congested == FALSE) {
   1366           SyncEventGuard guard(pConn->mCongEvent);
   1367           pConn->mCongEvent.notifyOne();
   1368         }
   1369       }
   1370       break;
   1371 
   1372     default:
   1373       DLOG_IF(INFO, nfc_debug_enabled)
   1374           << StringPrintf("%s: unknown event 0x%X ????", fn, p2pEvent);
   1375       break;
   1376   }
   1377   DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf("%s: exit", fn);
   1378 }
   1379 
   1380 /*******************************************************************************
   1381 **
   1382 ** Function:        nfaClientCallback
   1383 **
   1384 ** Description:     Receive LLCP-related events from the stack.
   1385 **                  p2pEvent: Event code.
   1386 **                  eventData: Event data.
   1387 **
   1388 ** Returns:         None
   1389 **
   1390 *******************************************************************************/
   1391 void PeerToPeer::nfaClientCallback(tNFA_P2P_EVT p2pEvent,
   1392                                    tNFA_P2P_EVT_DATA* eventData) {
   1393   static const char fn[] = "PeerToPeer::nfaClientCallback";
   1394   sp<NfaConn> pConn = NULL;
   1395   sp<P2pClient> pClient = NULL;
   1396 
   1397   DLOG_IF(INFO, nfc_debug_enabled)
   1398       << StringPrintf("%s: enter; event=%u", fn, p2pEvent);
   1399 
   1400   switch (p2pEvent) {
   1401     case NFA_P2P_REG_CLIENT_EVT:
   1402       // Look for a client that is trying to register
   1403       if ((pClient = sP2p.findClient((tNFA_HANDLE)NFA_HANDLE_INVALID)) ==
   1404           NULL) {
   1405         LOG(ERROR) << StringPrintf(
   1406             "%s: NFA_P2P_REG_CLIENT_EVT: can't find waiting client", fn);
   1407       } else {
   1408         DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf(
   1409             "%s: NFA_P2P_REG_CLIENT_EVT; Conn Handle: 0x%04x, pClient: 0x%p",
   1410             fn, eventData->reg_client.client_handle, pClient.get());
   1411 
   1412         SyncEventGuard guard(pClient->mRegisteringEvent);
   1413         pClient->mNfaP2pClientHandle = eventData->reg_client.client_handle;
   1414         pClient->mRegisteringEvent.notifyOne();
   1415       }
   1416       break;
   1417 
   1418     case NFA_P2P_ACTIVATED_EVT:
   1419       // Look for a client that is trying to register
   1420       if ((pClient = sP2p.findClient(eventData->activated.handle)) == NULL) {
   1421         LOG(ERROR) << StringPrintf(
   1422             "%s: NFA_P2P_ACTIVATED_EVT: can't find client", fn);
   1423       } else {
   1424         DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf(
   1425             "%s: NFA_P2P_ACTIVATED_EVT; Conn Handle: 0x%04x, pClient: 0x%p", fn,
   1426             eventData->activated.handle, pClient.get());
   1427       }
   1428       break;
   1429 
   1430     case NFA_P2P_DEACTIVATED_EVT:
   1431       DLOG_IF(INFO, nfc_debug_enabled)
   1432           << StringPrintf("%s: NFA_P2P_DEACTIVATED_EVT: conn handle: 0x%X", fn,
   1433                           eventData->deactivated.handle);
   1434       break;
   1435 
   1436     case NFA_P2P_CONNECTED_EVT:
   1437       // Look for the client that is trying to connect
   1438       if ((pClient = sP2p.findClient(eventData->connected.client_handle)) ==
   1439           NULL) {
   1440         LOG(ERROR) << StringPrintf(
   1441             "%s: NFA_P2P_CONNECTED_EVT: can't find client: 0x%04x", fn,
   1442             eventData->connected.client_handle);
   1443       } else {
   1444         DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf(
   1445             "%s: NFA_P2P_CONNECTED_EVT; client_handle=0x%04x  "
   1446             "conn_handle: 0x%04x  remote sap=0x%X  pClient: 0x%p",
   1447             fn, eventData->connected.client_handle,
   1448             eventData->connected.conn_handle, eventData->connected.remote_sap,
   1449             pClient.get());
   1450 
   1451         SyncEventGuard guard(pClient->mConnectingEvent);
   1452         pClient->mClientConn->mNfaConnHandle = eventData->connected.conn_handle;
   1453         pClient->mClientConn->mRemoteMaxInfoUnit =
   1454             eventData->connected.remote_miu;
   1455         pClient->mClientConn->mRemoteRecvWindow =
   1456             eventData->connected.remote_rw;
   1457         pClient->mConnectingEvent.notifyOne();  // unblock createDataLinkConn()
   1458       }
   1459       break;
   1460 
   1461     case NFA_P2P_DISC_EVT:
   1462       DLOG_IF(INFO, nfc_debug_enabled)
   1463           << StringPrintf("%s: NFA_P2P_DISC_EVT; h=0x%04x; reason=0x%X", fn,
   1464                           eventData->disc.handle, eventData->disc.reason);
   1465       // Look for the connection block
   1466       if ((pConn = sP2p.findConnection(eventData->disc.handle)) == NULL) {
   1467         // If no connection, may be a client that is trying to connect
   1468         if ((pClient = sP2p.findClient(eventData->disc.handle)) == NULL) {
   1469           LOG(ERROR) << StringPrintf(
   1470               "%s: NFA_P2P_DISC_EVT: can't find client for NFA handle: 0x%04x",
   1471               fn, eventData->disc.handle);
   1472           return;
   1473         }
   1474         // Unblock createDataLinkConn()
   1475         SyncEventGuard guard(pClient->mConnectingEvent);
   1476         pClient->mConnectingEvent.notifyOne();
   1477       } else {
   1478         sP2p.mDisconnectMutex.lock();
   1479         pConn->mNfaConnHandle = NFA_HANDLE_INVALID;
   1480         {
   1481           DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf(
   1482               "%s: NFA_P2P_DISC_EVT; try guard disconn event", fn);
   1483           SyncEventGuard guard3(pConn->mDisconnectingEvent);
   1484           pConn->mDisconnectingEvent.notifyOne();
   1485           DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf(
   1486               "%s: NFA_P2P_DISC_EVT; notified disconn event", fn);
   1487         }
   1488         {
   1489           DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf(
   1490               "%s: NFA_P2P_DISC_EVT; try guard congest event", fn);
   1491           SyncEventGuard guard1(pConn->mCongEvent);
   1492           pConn->mCongEvent.notifyOne();  // unblock write (if congested)
   1493           DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf(
   1494               "%s: NFA_P2P_DISC_EVT; notified congest event", fn);
   1495         }
   1496         {
   1497           DLOG_IF(INFO, nfc_debug_enabled)
   1498               << StringPrintf("%s: NFA_P2P_DISC_EVT; try guard read event", fn);
   1499           SyncEventGuard guard2(pConn->mReadEvent);
   1500           pConn->mReadEvent.notifyOne();  // unblock receive()
   1501           DLOG_IF(INFO, nfc_debug_enabled)
   1502               << StringPrintf("%s: NFA_P2P_DISC_EVT; notified read event", fn);
   1503         }
   1504         sP2p.mDisconnectMutex.unlock();
   1505       }
   1506       break;
   1507 
   1508     case NFA_P2P_DATA_EVT:
   1509       // Look for the connection block
   1510       if ((pConn = sP2p.findConnection(eventData->data.handle)) == NULL) {
   1511         LOG(ERROR) << StringPrintf(
   1512             "%s: NFA_P2P_DATA_EVT: can't find conn for NFA handle: 0x%04x", fn,
   1513             eventData->data.handle);
   1514       } else {
   1515         DLOG_IF(INFO, nfc_debug_enabled)
   1516             << StringPrintf("%s: NFA_P2P_DATA_EVT; h=0x%X; remote sap=0x%X", fn,
   1517                             eventData->data.handle, eventData->data.remote_sap);
   1518         SyncEventGuard guard(pConn->mReadEvent);
   1519         pConn->mReadEvent.notifyOne();
   1520       }
   1521       break;
   1522 
   1523     case NFA_P2P_CONGEST_EVT:
   1524       // Look for the connection block
   1525       if ((pConn = sP2p.findConnection(eventData->congest.handle)) == NULL) {
   1526         LOG(ERROR) << StringPrintf(
   1527             "%s: NFA_P2P_CONGEST_EVT: can't find conn for NFA handle: 0x%04x",
   1528             fn, eventData->congest.handle);
   1529       } else {
   1530         DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf(
   1531             "%s: NFA_P2P_CONGEST_EVT; nfa handle: 0x%04x  congested: %u", fn,
   1532             eventData->congest.handle, eventData->congest.is_congested);
   1533 
   1534         SyncEventGuard guard(pConn->mCongEvent);
   1535         pConn->mCongEvent.notifyOne();
   1536       }
   1537       break;
   1538 
   1539     default:
   1540       LOG(ERROR) << StringPrintf("%s: unknown event 0x%X ????", fn, p2pEvent);
   1541       break;
   1542   }
   1543 }
   1544 
   1545 /*******************************************************************************
   1546 **
   1547 ** Function:        connectionEventHandler
   1548 **
   1549 ** Description:     Receive events from the stack.
   1550 **                  event: Event code.
   1551 **                  eventData: Event data.
   1552 **
   1553 ** Returns:         None
   1554 **
   1555 *******************************************************************************/
   1556 void PeerToPeer::connectionEventHandler(uint8_t event,
   1557                                         tNFA_CONN_EVT_DATA* /*eventData*/) {
   1558   switch (event) {
   1559     case NFA_SET_P2P_LISTEN_TECH_EVT: {
   1560       SyncEventGuard guard(mSetTechEvent);
   1561       mSetTechEvent.notifyOne();  // unblock NFA_SetP2pListenTech()
   1562       break;
   1563     }
   1564   }
   1565 }
   1566 
   1567 /*******************************************************************************
   1568 **
   1569 ** Function:        getNextJniHandle
   1570 **
   1571 ** Description:     Get a new JNI handle.
   1572 **
   1573 ** Returns:         A new JNI handle.
   1574 **
   1575 *******************************************************************************/
   1576 PeerToPeer::tJNI_HANDLE PeerToPeer::getNewJniHandle() {
   1577   tJNI_HANDLE newHandle = 0;
   1578 
   1579   mNewJniHandleMutex.lock();
   1580   newHandle = mNextJniHandle++;
   1581   mNewJniHandleMutex.unlock();
   1582   return newHandle;
   1583 }
   1584 
   1585 /////////////////////////////////////////////////////////////////////////
   1586 /////////////////////////////////////////////////////////////////////////
   1587 
   1588 /*******************************************************************************
   1589 **
   1590 ** Function:        P2pServer
   1591 **
   1592 ** Description:     Initialize member variables.
   1593 **
   1594 ** Returns:         None
   1595 **
   1596 *******************************************************************************/
   1597 P2pServer::P2pServer(PeerToPeer::tJNI_HANDLE jniHandle, const char* serviceName)
   1598     : mNfaP2pServerHandle(NFA_HANDLE_INVALID), mJniHandle(jniHandle) {
   1599   mServiceName.assign(serviceName);
   1600 
   1601   memset(mServerConn, 0, sizeof(mServerConn));
   1602 }
   1603 
   1604 bool P2pServer::registerWithStack() {
   1605   static const char fn[] = "P2pServer::registerWithStack";
   1606   DLOG_IF(INFO, nfc_debug_enabled)
   1607       << StringPrintf("%s: enter; service name: %s  JNI handle: %u", fn,
   1608                       mServiceName.c_str(), mJniHandle);
   1609   tNFA_STATUS stat = NFA_STATUS_OK;
   1610   uint8_t serverSap = NFA_P2P_ANY_SAP;
   1611 
   1612   /**********************
   1613  default values for all LLCP parameters:
   1614  - Local Link MIU (LLCP_MIU)
   1615  - Option parameter (LLCP_OPT_VALUE)
   1616  - Response Waiting Time Index (LLCP_WAITING_TIME)
   1617  - Local Link Timeout (LLCP_LTO_VALUE)
   1618  - Inactivity Timeout as initiator role (LLCP_INIT_INACTIVITY_TIMEOUT)
   1619  - Inactivity Timeout as target role (LLCP_TARGET_INACTIVITY_TIMEOUT)
   1620  - Delay SYMM response (LLCP_DELAY_RESP_TIME)
   1621  - Data link connection timeout (LLCP_DATA_LINK_CONNECTION_TOUT)
   1622  - Delay timeout to send first PDU as initiator
   1623  (LLCP_DELAY_TIME_TO_SEND_FIRST_PDU)
   1624  ************************/
   1625   stat = NFA_P2pSetLLCPConfig(LLCP_MAX_MIU, LLCP_OPT_VALUE, LLCP_WAITING_TIME,
   1626                               LLCP_LTO_VALUE,
   1627                               0,  // use 0 for infinite timeout for symmetry
   1628                                   // procedure when acting as initiator
   1629                               0,  // use 0 for infinite timeout for symmetry
   1630                                   // procedure when acting as target
   1631                               LLCP_DELAY_RESP_TIME, LLCP_DATA_LINK_TIMEOUT,
   1632                               LLCP_DELAY_TIME_TO_SEND_FIRST_PDU);
   1633   if (stat != NFA_STATUS_OK)
   1634     LOG(ERROR) << StringPrintf("%s: fail set LLCP config; error=0x%X", fn,
   1635                                stat);
   1636 
   1637   if (sSnepServiceName.compare(mServiceName) == 0)
   1638     serverSap = 4;  // LLCP_SAP_SNEP == 4
   1639 
   1640   {
   1641     SyncEventGuard guard(mRegServerEvent);
   1642     stat = NFA_P2pRegisterServer(serverSap, NFA_P2P_DLINK_TYPE,
   1643                                  const_cast<char*>(mServiceName.c_str()),
   1644                                  PeerToPeer::nfaServerCallback);
   1645     if (stat != NFA_STATUS_OK) {
   1646       LOG(ERROR) << StringPrintf("%s: fail register p2p server; error=0x%X", fn,
   1647                                  stat);
   1648       return (false);
   1649     }
   1650     DLOG_IF(INFO, nfc_debug_enabled)
   1651         << StringPrintf("%s: wait for listen-completion event", fn);
   1652     // Wait for NFA_P2P_REG_SERVER_EVT
   1653     mRegServerEvent.wait();
   1654   }
   1655 
   1656   return (mNfaP2pServerHandle != NFA_HANDLE_INVALID);
   1657 }
   1658 
   1659 bool P2pServer::accept(PeerToPeer::tJNI_HANDLE serverJniHandle,
   1660                        PeerToPeer::tJNI_HANDLE connJniHandle, int maxInfoUnit,
   1661                        int recvWindow) {
   1662   static const char fn[] = "P2pServer::accept";
   1663   tNFA_STATUS nfaStat = NFA_STATUS_OK;
   1664 
   1665   sp<NfaConn> connection = allocateConnection(connJniHandle);
   1666   if (connection == NULL) {
   1667     LOG(ERROR) << StringPrintf("%s: failed to allocate new server connection",
   1668                                fn);
   1669     return false;
   1670   }
   1671 
   1672   {
   1673     // Wait for NFA_P2P_CONN_REQ_EVT or NFA_NDEF_DATA_EVT when remote device
   1674     // requests connection
   1675     SyncEventGuard guard(mConnRequestEvent);
   1676     DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf(
   1677         "%s: serverJniHandle: %u; connJniHandle: %u; wait for "
   1678         "incoming connection",
   1679         fn, serverJniHandle, connJniHandle);
   1680     mConnRequestEvent.wait();
   1681     DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf(
   1682         "%s: serverJniHandle: %u; connJniHandle: %u; nfa conn h: 0x%X; got "
   1683         "incoming connection",
   1684         fn, serverJniHandle, connJniHandle, connection->mNfaConnHandle);
   1685   }
   1686 
   1687   if (connection->mNfaConnHandle == NFA_HANDLE_INVALID) {
   1688     removeServerConnection(connJniHandle);
   1689     DLOG_IF(INFO, nfc_debug_enabled)
   1690         << StringPrintf("%s: no handle assigned", fn);
   1691     return (false);
   1692   }
   1693 
   1694   if (maxInfoUnit > (int)LLCP_MIU) {
   1695     DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf(
   1696         "%s: overriding the miu passed by the app(%d) with stack miu(%zu)", fn,
   1697         maxInfoUnit, LLCP_MIU);
   1698     maxInfoUnit = LLCP_MIU;
   1699   }
   1700 
   1701   DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf(
   1702       "%s: serverJniHandle: %u; connJniHandle: %u; nfa conn h: 0x%X; try "
   1703       "accept",
   1704       fn, serverJniHandle, connJniHandle, connection->mNfaConnHandle);
   1705   nfaStat =
   1706       NFA_P2pAcceptConn(connection->mNfaConnHandle, maxInfoUnit, recvWindow);
   1707 
   1708   if (nfaStat != NFA_STATUS_OK) {
   1709     LOG(ERROR) << StringPrintf("%s: fail to accept remote; error=0x%X", fn,
   1710                                nfaStat);
   1711     return (false);
   1712   }
   1713 
   1714   DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf(
   1715       "%s: exit; serverJniHandle: %u; connJniHandle: %u; nfa conn h: 0x%X", fn,
   1716       serverJniHandle, connJniHandle, connection->mNfaConnHandle);
   1717   return (true);
   1718 }
   1719 
   1720 void P2pServer::unblockAll() {
   1721   AutoMutex mutex(mMutex);
   1722   for (int jj = 0; jj < MAX_NFA_CONNS_PER_SERVER; jj++) {
   1723     if (mServerConn[jj] != NULL) {
   1724       mServerConn[jj]->mNfaConnHandle = NFA_HANDLE_INVALID;
   1725       {
   1726         SyncEventGuard guard1(mServerConn[jj]->mCongEvent);
   1727         mServerConn[jj]
   1728             ->mCongEvent.notifyOne();  // unblock write (if congested)
   1729       }
   1730       {
   1731         SyncEventGuard guard2(mServerConn[jj]->mReadEvent);
   1732         mServerConn[jj]->mReadEvent.notifyOne();  // unblock receive()
   1733       }
   1734     }
   1735   }
   1736 }
   1737 
   1738 sp<NfaConn> P2pServer::allocateConnection(PeerToPeer::tJNI_HANDLE jniHandle) {
   1739   AutoMutex mutex(mMutex);
   1740   // First, find a free connection block to handle the connection
   1741   for (int ii = 0; ii < MAX_NFA_CONNS_PER_SERVER; ii++) {
   1742     if (mServerConn[ii] == NULL) {
   1743       mServerConn[ii] = new NfaConn;
   1744       mServerConn[ii]->mJniHandle = jniHandle;
   1745       return mServerConn[ii];
   1746     }
   1747   }
   1748 
   1749   return NULL;
   1750 }
   1751 
   1752 /*******************************************************************************
   1753 **
   1754 ** Function:        findServerConnection
   1755 **
   1756 ** Description:     Find a P2pServer that has the handle.
   1757 **                  nfaConnHandle: NFA connection handle.
   1758 **
   1759 ** Returns:         P2pServer object.
   1760 **
   1761 *******************************************************************************/
   1762 sp<NfaConn> P2pServer::findServerConnection(tNFA_HANDLE nfaConnHandle) {
   1763   int jj = 0;
   1764 
   1765   AutoMutex mutex(mMutex);
   1766   for (jj = 0; jj < MAX_NFA_CONNS_PER_SERVER; jj++) {
   1767     if ((mServerConn[jj] != NULL) &&
   1768         (mServerConn[jj]->mNfaConnHandle == nfaConnHandle))
   1769       return (mServerConn[jj]);
   1770   }
   1771 
   1772   // If here, not found
   1773   return (NULL);
   1774 }
   1775 
   1776 /*******************************************************************************
   1777 **
   1778 ** Function:        findServerConnection
   1779 **
   1780 ** Description:     Find a P2pServer that has the handle.
   1781 **                  nfaConnHandle: NFA connection handle.
   1782 **
   1783 ** Returns:         P2pServer object.
   1784 **
   1785 *******************************************************************************/
   1786 sp<NfaConn> P2pServer::findServerConnection(PeerToPeer::tJNI_HANDLE jniHandle) {
   1787   int jj = 0;
   1788 
   1789   AutoMutex mutex(mMutex);
   1790   for (jj = 0; jj < MAX_NFA_CONNS_PER_SERVER; jj++) {
   1791     if ((mServerConn[jj] != NULL) && (mServerConn[jj]->mJniHandle == jniHandle))
   1792       return (mServerConn[jj]);
   1793   }
   1794 
   1795   // If here, not found
   1796   return (NULL);
   1797 }
   1798 
   1799 /*******************************************************************************
   1800 **
   1801 ** Function:        removeServerConnection
   1802 **
   1803 ** Description:     Find a P2pServer that has the handle.
   1804 **                  nfaConnHandle: NFA connection handle.
   1805 **
   1806 ** Returns:         P2pServer object.
   1807 **
   1808 *******************************************************************************/
   1809 bool P2pServer::removeServerConnection(PeerToPeer::tJNI_HANDLE jniHandle) {
   1810   int jj = 0;
   1811 
   1812   AutoMutex mutex(mMutex);
   1813   for (jj = 0; jj < MAX_NFA_CONNS_PER_SERVER; jj++) {
   1814     if ((mServerConn[jj] != NULL) &&
   1815         (mServerConn[jj]->mJniHandle == jniHandle)) {
   1816       mServerConn[jj] = NULL;
   1817       return true;
   1818     }
   1819   }
   1820 
   1821   // If here, not found
   1822   return false;
   1823 }
   1824 /////////////////////////////////////////////////////////////////////////
   1825 /////////////////////////////////////////////////////////////////////////
   1826 
   1827 /*******************************************************************************
   1828 **
   1829 ** Function:        P2pClient
   1830 **
   1831 ** Description:     Initialize member variables.
   1832 **
   1833 ** Returns:         None
   1834 **
   1835 *******************************************************************************/
   1836 P2pClient::P2pClient()
   1837     : mNfaP2pClientHandle(NFA_HANDLE_INVALID), mIsConnecting(false) {
   1838   mClientConn = new NfaConn();
   1839 }
   1840 
   1841 /*******************************************************************************
   1842 **
   1843 ** Function:        ~P2pClient
   1844 **
   1845 ** Description:     Free all resources.
   1846 **
   1847 ** Returns:         None
   1848 **
   1849 *******************************************************************************/
   1850 P2pClient::~P2pClient() {}
   1851 
   1852 /////////////////////////////////////////////////////////////////////////
   1853 /////////////////////////////////////////////////////////////////////////
   1854 
   1855 /*******************************************************************************
   1856 **
   1857 ** Function:        NfaConn
   1858 **
   1859 ** Description:     Initialize member variables.
   1860 **
   1861 ** Returns:         None
   1862 **
   1863 *******************************************************************************/
   1864 NfaConn::NfaConn()
   1865     : mNfaConnHandle(NFA_HANDLE_INVALID),
   1866       mJniHandle(0),
   1867       mMaxInfoUnit(0),
   1868       mRecvWindow(0),
   1869       mRemoteMaxInfoUnit(0),
   1870       mRemoteRecvWindow(0) {}
   1871