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 #include <semaphore.h>
     18 #include <errno.h>
     19 #include <malloc.h>
     20 #include <time.h>
     21 #include <signal.h>
     22 #include <string.h>
     23 #include "_OverrideLog.h"
     24 #include "NfcJniUtil.h"
     25 #include "NfcTag.h"
     26 #include "config.h"
     27 #include "Mutex.h"
     28 #include "IntervalTimer.h"
     29 #include "JavaClassConstants.h"
     30 #include "Pn544Interop.h"
     31 #include <ScopedLocalRef.h>
     32 #include <ScopedPrimitiveArray.h>
     33 #include <string>
     34 
     35 extern "C"
     36 {
     37     #include "nfa_api.h"
     38     #include "nfa_rw_api.h"
     39     #include "nfc_brcm_defs.h"
     40     #include "ndef_utils.h"
     41     #include "rw_api.h"
     42     #include "phNxpExtns.h"
     43 }
     44 namespace android
     45 {
     46     extern nfc_jni_native_data* getNative(JNIEnv *e, jobject o);
     47     extern bool nfcManager_isNfcActive();
     48 }
     49 
     50 extern bool         gActivated;
     51 extern SyncEvent    gDeactivatedEvent;
     52 
     53 /*****************************************************************************
     54 **
     55 ** public variables and functions
     56 **
     57 *****************************************************************************/
     58 namespace android
     59 {
     60     bool    gIsTagDeactivating = false;    // flag for nfa callback indicating we are deactivating for RF interface switch
     61     bool    gIsSelectingRfInterface = false; // flag for nfa callback indicating we are selecting for RF interface switch
     62 }
     63 
     64 
     65 /*****************************************************************************
     66 **
     67 ** private variables and functions
     68 **
     69 *****************************************************************************/
     70 namespace android
     71 {
     72 
     73 
     74 // Pre-defined tag type values. These must match the values in
     75 // framework Ndef.java for Google public NFC API.
     76 #define NDEF_UNKNOWN_TYPE          (-1)
     77 #define NDEF_TYPE1_TAG             1
     78 #define NDEF_TYPE2_TAG             2
     79 #define NDEF_TYPE3_TAG             3
     80 #define NDEF_TYPE4_TAG             4
     81 #define NDEF_MIFARE_CLASSIC_TAG    101
     82 
     83 #define STATUS_CODE_TARGET_LOST    146	// this error code comes from the service
     84 
     85 static uint32_t     sCheckNdefCurrentSize = 0;
     86 static tNFA_STATUS  sCheckNdefStatus = 0; //whether tag already contains a NDEF message
     87 static bool         sCheckNdefCapable = false; //whether tag has NDEF capability
     88 static tNFA_HANDLE  sNdefTypeHandlerHandle = NFA_HANDLE_INVALID;
     89 static tNFA_INTF_TYPE   sCurrentRfInterface = NFA_INTERFACE_ISO_DEP;
     90 static std::basic_string<uint8_t> sRxDataBuffer;
     91 static tNFA_STATUS  sRxDataStatus = NFA_STATUS_OK;
     92 static bool         sWaitingForTransceive = false;
     93 static bool         sTransceiveRfTimeout = false;
     94 static Mutex        sRfInterfaceMutex;
     95 static uint32_t     sReadDataLen = 0;
     96 static uint8_t*     sReadData = NULL;
     97 static bool         sIsReadingNdefMessage = false;
     98 static SyncEvent    sReadEvent;
     99 static sem_t        sWriteSem;
    100 static sem_t        sFormatSem;
    101 static SyncEvent    sTransceiveEvent;
    102 static SyncEvent    sReconnectEvent;
    103 static sem_t        sCheckNdefSem;
    104 static SyncEvent    sPresenceCheckEvent;
    105 static sem_t        sMakeReadonlySem;
    106 static IntervalTimer sSwitchBackTimer; // timer used to tell us to switch back to ISO_DEP frame interface
    107 static jboolean     sWriteOk = JNI_FALSE;
    108 static jboolean     sWriteWaitingForComplete = JNI_FALSE;
    109 static bool         sFormatOk = false;
    110 static jboolean     sConnectOk = JNI_FALSE;
    111 static jboolean     sConnectWaitingForComplete = JNI_FALSE;
    112 static bool         sGotDeactivate = false;
    113 static uint32_t     sCheckNdefMaxSize = 0;
    114 static bool         sCheckNdefCardReadOnly = false;
    115 static jboolean     sCheckNdefWaitingForComplete = JNI_FALSE;
    116 static bool         sIsTagPresent = true;
    117 static tNFA_STATUS  sMakeReadonlyStatus = NFA_STATUS_FAILED;
    118 static jboolean     sMakeReadonlyWaitingForComplete = JNI_FALSE;
    119 static int          sCurrentConnectedTargetType = TARGET_TYPE_UNKNOWN;
    120 static int          sCurrentConnectedTargetProtocol = NFC_PROTOCOL_UNKNOWN;
    121 static int reSelect (tNFA_INTF_TYPE rfInterface, bool fSwitchIfNeeded);
    122 static bool switchRfInterface(tNFA_INTF_TYPE rfInterface);
    123 
    124 
    125 /*******************************************************************************
    126 **
    127 ** Function:        nativeNfcTag_abortWaits
    128 **
    129 ** Description:     Unblock all thread synchronization objects.
    130 **
    131 ** Returns:         None
    132 **
    133 *******************************************************************************/
    134 void nativeNfcTag_abortWaits ()
    135 {
    136     ALOGV("%s", __func__);
    137     {
    138         SyncEventGuard g (sReadEvent);
    139         sReadEvent.notifyOne ();
    140     }
    141     sem_post (&sWriteSem);
    142     sem_post (&sFormatSem);
    143     {
    144         SyncEventGuard g (sTransceiveEvent);
    145         sTransceiveEvent.notifyOne ();
    146     }
    147     {
    148         SyncEventGuard g (sReconnectEvent);
    149         sReconnectEvent.notifyOne ();
    150     }
    151 
    152     sem_post (&sCheckNdefSem);
    153     {
    154         SyncEventGuard guard (sPresenceCheckEvent);
    155         sPresenceCheckEvent.notifyOne ();
    156     }
    157     sem_post (&sMakeReadonlySem);
    158     sCurrentRfInterface = NFA_INTERFACE_ISO_DEP;
    159     sCurrentConnectedTargetType = TARGET_TYPE_UNKNOWN;
    160     sCurrentConnectedTargetProtocol = NFC_PROTOCOL_UNKNOWN;
    161 }
    162 
    163 /*******************************************************************************
    164 **
    165 ** Function:        nativeNfcTag_doReadCompleted
    166 **
    167 ** Description:     Receive the completion status of read operation.  Called by
    168 **                  NFA_READ_CPLT_EVT.
    169 **                  status: Status of operation.
    170 **
    171 ** Returns:         None
    172 **
    173 *******************************************************************************/
    174 void nativeNfcTag_doReadCompleted (tNFA_STATUS status)
    175 {
    176     ALOGV("%s: status=0x%X; is reading=%u", __func__, status, sIsReadingNdefMessage);
    177 
    178     if (sIsReadingNdefMessage == false)
    179         return; //not reading NDEF message right now, so just return
    180 
    181     if (status != NFA_STATUS_OK)
    182     {
    183         sReadDataLen = 0;
    184         if (sReadData)
    185             free (sReadData);
    186         sReadData = NULL;
    187     }
    188     SyncEventGuard g (sReadEvent);
    189     sReadEvent.notifyOne ();
    190 }
    191 
    192 
    193 /*******************************************************************************
    194 **
    195 ** Function:        nativeNfcTag_setRfInterface
    196 **
    197 ** Description:     Set rf interface.
    198 **
    199 ** Returns:         void
    200 **
    201 *******************************************************************************/
    202 void nativeNfcTag_setRfInterface (tNFA_INTF_TYPE rfInterface)
    203 {
    204     sCurrentRfInterface = rfInterface;
    205 }
    206 
    207 
    208 /*******************************************************************************
    209 **
    210 ** Function:        ndefHandlerCallback
    211 **
    212 ** Description:     Receive NDEF-message related events from stack.
    213 **                  event: Event code.
    214 **                  p_data: Event data.
    215 **
    216 ** Returns:         None
    217 **
    218 *******************************************************************************/
    219 static void ndefHandlerCallback (tNFA_NDEF_EVT event, tNFA_NDEF_EVT_DATA *eventData)
    220 {
    221     ALOGV("%s: event=%u, eventData=%p", __func__, event, eventData);
    222 
    223     switch (event)
    224     {
    225     case NFA_NDEF_REGISTER_EVT:
    226         {
    227             tNFA_NDEF_REGISTER& ndef_reg = eventData->ndef_reg;
    228             ALOGV("%s: NFA_NDEF_REGISTER_EVT; status=0x%X; h=0x%X", __func__, ndef_reg.status, ndef_reg.ndef_type_handle);
    229             sNdefTypeHandlerHandle = ndef_reg.ndef_type_handle;
    230         }
    231         break;
    232 
    233     case NFA_NDEF_DATA_EVT:
    234         {
    235             ALOGV("%s: NFA_NDEF_DATA_EVT; data_len = %u", __func__, eventData->ndef_data.len);
    236             sReadDataLen = eventData->ndef_data.len;
    237             sReadData = (uint8_t*) malloc (sReadDataLen);
    238             memcpy (sReadData, eventData->ndef_data.p_data, eventData->ndef_data.len);
    239         }
    240         break;
    241 
    242     default:
    243         ALOGE("%s: Unknown event %u ????", __func__, event);
    244         break;
    245     }
    246 }
    247 
    248 
    249 /*******************************************************************************
    250 **
    251 ** Function:        nativeNfcTag_doRead
    252 **
    253 ** Description:     Read the NDEF message on the tag.
    254 **                  e: JVM environment.
    255 **                  o: Java object.
    256 **
    257 ** Returns:         NDEF message.
    258 **
    259 *******************************************************************************/
    260 static jbyteArray nativeNfcTag_doRead (JNIEnv* e, jobject)
    261 {
    262     ALOGV("%s: enter", __func__);
    263     tNFA_STATUS status = NFA_STATUS_FAILED;
    264     jbyteArray buf = NULL;
    265 
    266     sReadDataLen = 0;
    267     if (sReadData != NULL)
    268     {
    269         free (sReadData);
    270         sReadData = NULL;
    271     }
    272 
    273     if (sCheckNdefCurrentSize > 0)
    274     {
    275         {
    276             SyncEventGuard g (sReadEvent);
    277             sIsReadingNdefMessage = true;
    278             if (sCurrentConnectedTargetProtocol == NFA_PROTOCOL_MIFARE)
    279             {
    280                 status = EXTNS_MfcReadNDef ();
    281             }
    282             else
    283             {
    284                 status = NFA_RwReadNDef ();
    285             }
    286             sReadEvent.wait (); //wait for NFA_READ_CPLT_EVT
    287         }
    288         sIsReadingNdefMessage = false;
    289 
    290         if (sReadDataLen > 0) //if stack actually read data from the tag
    291         {
    292             ALOGV("%s: read %u bytes", __func__, sReadDataLen);
    293             buf = e->NewByteArray (sReadDataLen);
    294             e->SetByteArrayRegion (buf, 0, sReadDataLen, (jbyte*) sReadData);
    295         }
    296     }
    297     else
    298     {
    299         ALOGV("%s: create empty buffer", __func__);
    300         sReadDataLen = 0;
    301         sReadData = (uint8_t*) malloc (1);
    302         buf = e->NewByteArray (sReadDataLen);
    303         e->SetByteArrayRegion (buf, 0, sReadDataLen, (jbyte*) sReadData);
    304     }
    305 
    306     if (sReadData)
    307     {
    308         free (sReadData);
    309         sReadData = NULL;
    310     }
    311     sReadDataLen = 0;
    312 
    313     ALOGV("%s: exit", __func__);
    314     return buf;
    315 }
    316 
    317 
    318 /*******************************************************************************
    319 **
    320 ** Function:        nativeNfcTag_doWriteStatus
    321 **
    322 ** Description:     Receive the completion status of write operation.  Called
    323 **                  by NFA_WRITE_CPLT_EVT.
    324 **                  isWriteOk: Status of operation.
    325 **
    326 ** Returns:         None
    327 **
    328 *******************************************************************************/
    329 void nativeNfcTag_doWriteStatus (jboolean isWriteOk)
    330 {
    331     if (sWriteWaitingForComplete != JNI_FALSE)
    332     {
    333         sWriteWaitingForComplete = JNI_FALSE;
    334         sWriteOk = isWriteOk;
    335         sem_post (&sWriteSem);
    336     }
    337 }
    338 
    339 
    340 /*******************************************************************************
    341 **
    342 ** Function:        nativeNfcTag_formatStatus
    343 **
    344 ** Description:     Receive the completion status of format operation.  Called
    345 **                  by NFA_FORMAT_CPLT_EVT.
    346 **                  isOk: Status of operation.
    347 **
    348 ** Returns:         None
    349 **
    350 *******************************************************************************/
    351 void nativeNfcTag_formatStatus (bool isOk)
    352 {
    353     sFormatOk = isOk;
    354     sem_post (&sFormatSem);
    355 }
    356 
    357 
    358 /*******************************************************************************
    359 **
    360 ** Function:        nativeNfcTag_doWrite
    361 **
    362 ** Description:     Write a NDEF message to the tag.
    363 **                  e: JVM environment.
    364 **                  o: Java object.
    365 **                  buf: Contains a NDEF message.
    366 **
    367 ** Returns:         True if ok.
    368 **
    369 *******************************************************************************/
    370 static jboolean nativeNfcTag_doWrite (JNIEnv* e, jobject, jbyteArray buf)
    371 {
    372     jboolean result = JNI_FALSE;
    373     tNFA_STATUS status = 0;
    374     const int maxBufferSize = 1024;
    375     uint8_t buffer[maxBufferSize] = { 0 };
    376     uint32_t curDataSize = 0;
    377 
    378     ScopedByteArrayRO bytes(e, buf);
    379     uint8_t* p_data = const_cast<uint8_t*>(reinterpret_cast<const uint8_t*>(&bytes[0])); // TODO: const-ness API bug in NFA_RwWriteNDef!
    380 
    381     ALOGV("%s: enter; len = %zu", __func__, bytes.size());
    382 
    383     /* Create the write semaphore */
    384     if (sem_init (&sWriteSem, 0, 0) == -1)
    385     {
    386         ALOGE("%s: semaphore creation failed (errno=0x%08x)", __func__, errno);
    387         return JNI_FALSE;
    388     }
    389 
    390     sWriteWaitingForComplete = JNI_TRUE;
    391     if (sCheckNdefStatus == NFA_STATUS_FAILED)
    392     {
    393         //if tag does not contain a NDEF message
    394         //and tag is capable of storing NDEF message
    395         if (sCheckNdefCapable)
    396         {
    397             ALOGV("%s: try format", __func__);
    398             sem_init (&sFormatSem, 0, 0);
    399             sFormatOk = false;
    400             if (sCurrentConnectedTargetProtocol == NFA_PROTOCOL_MIFARE)
    401             {
    402                 static uint8_t mfc_key1[6] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF};
    403                 static uint8_t mfc_key2[6] = {0xD3, 0xF7, 0xD3, 0xF7, 0xD3, 0xF7};
    404 
    405                 status = EXTNS_MfcFormatTag (mfc_key1, sizeof(mfc_key1));
    406                 if (status != NFA_STATUS_OK)
    407                 {
    408                     ALOGE("%s: can't format mifare classic tag", __func__);
    409                     sem_destroy (&sFormatSem);
    410                     goto TheEnd;
    411                 }
    412 
    413                 if (sFormatOk == false) //if format operation failed
    414                 {
    415                     sem_wait (&sFormatSem);
    416                     sem_destroy (&sFormatSem);
    417                     sem_init (&sFormatSem, 0, 0);
    418                     status = EXTNS_MfcFormatTag (mfc_key2, sizeof(mfc_key2));
    419                     if (status != NFA_STATUS_OK)
    420                     {
    421                         ALOGE("%s: can't format mifare classic tag", __func__);
    422                         sem_destroy (&sFormatSem);
    423                         goto TheEnd;
    424                     }
    425                 }
    426             }
    427             else
    428             {
    429                 status = NFA_RwFormatTag ();
    430             }
    431             sem_wait (&sFormatSem);
    432             sem_destroy (&sFormatSem);
    433             if (sFormatOk == false) //if format operation failed
    434                 goto TheEnd;
    435         }
    436         ALOGV("%s: try write", __func__);
    437         status = NFA_RwWriteNDef (p_data, bytes.size());
    438     }
    439     else if (bytes.size() == 0)
    440     {
    441         //if (NXP TagWriter wants to erase tag) then create and write an empty ndef message
    442         NDEF_MsgInit (buffer, maxBufferSize, &curDataSize);
    443         status = NDEF_MsgAddRec (buffer, maxBufferSize, &curDataSize, NDEF_TNF_EMPTY, NULL, 0, NULL, 0, NULL, 0);
    444         ALOGV("%s: create empty ndef msg; status=%u; size=%u", __func__, status, curDataSize);
    445         if (sCurrentConnectedTargetProtocol == NFA_PROTOCOL_MIFARE)
    446         {
    447             status = EXTNS_MfcWriteNDef (buffer, curDataSize);
    448         }
    449         else
    450         {
    451             status = NFA_RwWriteNDef (buffer, curDataSize);
    452         }
    453     }
    454     else
    455     {
    456         ALOGV("%s: NFA_RwWriteNDef", __func__);
    457         if (sCurrentConnectedTargetProtocol == NFA_PROTOCOL_MIFARE)
    458         {
    459             status = EXTNS_MfcWriteNDef (p_data, bytes.size());
    460         }
    461         else
    462         {
    463             status = NFA_RwWriteNDef (p_data, bytes.size());
    464         }
    465     }
    466 
    467     if (status != NFA_STATUS_OK)
    468     {
    469         ALOGE("%s: write/format error=%d", __func__, status);
    470         goto TheEnd;
    471     }
    472 
    473     /* Wait for write completion status */
    474     sWriteOk = false;
    475     if (sem_wait (&sWriteSem))
    476     {
    477         ALOGE("%s: wait semaphore (errno=0x%08x)", __func__, errno);
    478         goto TheEnd;
    479     }
    480 
    481     result = sWriteOk;
    482 
    483 TheEnd:
    484     /* Destroy semaphore */
    485     if (sem_destroy (&sWriteSem))
    486     {
    487         ALOGE("%s: failed destroy semaphore (errno=0x%08x)", __func__, errno);
    488     }
    489     sWriteWaitingForComplete = JNI_FALSE;
    490     ALOGV("%s: exit; result=%d", __func__, result);
    491     return result;
    492 }
    493 
    494 
    495 /*******************************************************************************
    496 **
    497 ** Function:        nativeNfcTag_doConnectStatus
    498 **
    499 ** Description:     Receive the completion status of connect operation.
    500 **                  isConnectOk: Status of the operation.
    501 **
    502 ** Returns:         None
    503 **
    504 *******************************************************************************/
    505 void nativeNfcTag_doConnectStatus (jboolean isConnectOk)
    506 {
    507     if (EXTNS_GetConnectFlag () == TRUE)
    508     {
    509         EXTNS_MfcActivated ();
    510         EXTNS_SetConnectFlag (FALSE);
    511         return;
    512     }
    513 
    514     if (sConnectWaitingForComplete != JNI_FALSE)
    515     {
    516         sConnectWaitingForComplete = JNI_FALSE;
    517         sConnectOk = isConnectOk;
    518         SyncEventGuard g (sReconnectEvent);
    519         sReconnectEvent.notifyOne ();
    520     }
    521 }
    522 
    523 
    524 /*******************************************************************************
    525 **
    526 ** Function:        nativeNfcTag_doDeactivateStatus
    527 **
    528 ** Description:     Receive the completion status of deactivate operation.
    529 **
    530 ** Returns:         None
    531 **
    532 *******************************************************************************/
    533 void nativeNfcTag_doDeactivateStatus (int status)
    534 {
    535     if (EXTNS_GetDeactivateFlag () == TRUE)
    536     {
    537         EXTNS_MfcDisconnect ();
    538         EXTNS_SetDeactivateFlag (FALSE);
    539         return;
    540     }
    541 
    542     sGotDeactivate = (status == 0);
    543 
    544     SyncEventGuard g (sReconnectEvent);
    545     sReconnectEvent.notifyOne ();
    546 }
    547 
    548 
    549 /*******************************************************************************
    550 **
    551 ** Function:        nativeNfcTag_doConnect
    552 **
    553 ** Description:     Connect to the tag in RF field.
    554 **                  e: JVM environment.
    555 **                  o: Java object.
    556 **                  targetHandle: Handle of the tag.
    557 **
    558 ** Returns:         Must return NXP status code, which NFC service expects.
    559 **
    560 *******************************************************************************/
    561 static jint nativeNfcTag_doConnect (JNIEnv*, jobject, jint targetHandle)
    562 {
    563     ALOGV("%s: targetHandle = %d", __func__, targetHandle);
    564     int i = targetHandle;
    565     NfcTag& natTag = NfcTag::getInstance ();
    566     int retCode = NFCSTATUS_SUCCESS;
    567 
    568     if (i >= NfcTag::MAX_NUM_TECHNOLOGY)
    569     {
    570         ALOGE("%s: Handle not found", __func__);
    571         retCode = NFCSTATUS_FAILED;
    572         goto TheEnd;
    573     }
    574 
    575     if (natTag.getActivationState() != NfcTag::Active)
    576     {
    577         ALOGE("%s: tag already deactivated", __func__);
    578         retCode = NFCSTATUS_FAILED;
    579         goto TheEnd;
    580     }
    581 
    582     sCurrentConnectedTargetType = natTag.mTechList[i];
    583     sCurrentConnectedTargetProtocol = natTag.mTechLibNfcTypes[i];
    584 
    585     if (sCurrentConnectedTargetProtocol != NFC_PROTOCOL_ISO_DEP)
    586     {
    587         ALOGV("%s() Nfc type = %d, do nothing for non ISO_DEP", __func__, sCurrentConnectedTargetProtocol);
    588         retCode = NFCSTATUS_SUCCESS;
    589         goto TheEnd;
    590     }
    591 
    592     if (sCurrentConnectedTargetType == TARGET_TYPE_ISO14443_3A || sCurrentConnectedTargetType == TARGET_TYPE_ISO14443_3B)
    593     {
    594         ALOGV("%s: switching to tech: %d need to switch rf intf to frame", __func__, sCurrentConnectedTargetType);
    595         retCode = switchRfInterface(NFA_INTERFACE_FRAME) ? NFA_STATUS_OK : NFA_STATUS_FAILED;
    596     }
    597     else
    598     {
    599         retCode = switchRfInterface(NFA_INTERFACE_ISO_DEP) ? NFA_STATUS_OK : NFA_STATUS_FAILED;
    600     }
    601 
    602 TheEnd:
    603     ALOGV("%s: exit 0x%X", __func__, retCode);
    604     return retCode;
    605 }
    606 
    607 
    608 /*******************************************************************************
    609 **
    610 ** Function:        reSelect
    611 **
    612 ** Description:     Deactivates the tag and re-selects it with the specified
    613 **                  rf interface.
    614 **
    615 ** Returns:         status code, 0 on success, 1 on failure,
    616 **                  146 (defined in service) on tag lost
    617 **
    618 *******************************************************************************/
    619 static int reSelect (tNFA_INTF_TYPE rfInterface, bool fSwitchIfNeeded)
    620 {
    621     ALOGV("%s: enter; rf intf = %d, current intf = %d", __func__, rfInterface, sCurrentRfInterface);
    622 
    623     sRfInterfaceMutex.lock ();
    624 
    625     if (fSwitchIfNeeded && (rfInterface == sCurrentRfInterface))
    626     {
    627         // already in the requested interface
    628         sRfInterfaceMutex.unlock ();
    629         return 0;   // success
    630     }
    631 
    632     NfcTag& natTag = NfcTag::getInstance ();
    633 
    634     tNFA_STATUS status;
    635     int rVal = 1;
    636 
    637     do
    638     {
    639         //if tag has shutdown, abort this method
    640         if (NfcTag::getInstance ().isNdefDetectionTimedOut())
    641         {
    642             ALOGV("%s: ndef detection timeout; break", __func__);
    643             rVal = STATUS_CODE_TARGET_LOST;
    644             break;
    645         }
    646 
    647         {
    648             SyncEventGuard g (sReconnectEvent);
    649             gIsTagDeactivating = true;
    650             sGotDeactivate = false;
    651             ALOGV("%s: deactivate to sleep", __func__);
    652             if (NFA_STATUS_OK != (status = NFA_Deactivate (TRUE))) //deactivate to sleep state
    653             {
    654                 ALOGE("%s: deactivate failed, status = %d", __func__, status);
    655                 break;
    656             }
    657 
    658             if (sReconnectEvent.wait (1000) == false) //if timeout occurred
    659             {
    660                 ALOGE("%s: timeout waiting for deactivate", __func__);
    661             }
    662         }
    663 
    664         if (!sGotDeactivate)
    665         {
    666             rVal = STATUS_CODE_TARGET_LOST;
    667             break;
    668         }
    669 
    670         if (NfcTag::getInstance ().getActivationState () != NfcTag::Sleep)
    671         {
    672             ALOGE("%s: tag is not in sleep", __func__);
    673             rVal = STATUS_CODE_TARGET_LOST;
    674             break;
    675         }
    676 
    677         gIsTagDeactivating = false;
    678 
    679         {
    680             SyncEventGuard g2 (sReconnectEvent);
    681 
    682             sConnectWaitingForComplete = JNI_TRUE;
    683             ALOGV("%s: select interface %u", __func__, rfInterface);
    684             gIsSelectingRfInterface = true;
    685             if (NFA_STATUS_OK != (status = NFA_Select (natTag.mTechHandles[0], natTag.mTechLibNfcTypes[0], rfInterface)))
    686             {
    687                 ALOGE("%s: NFA_Select failed, status = %d", __func__, status);
    688                 break;
    689             }
    690 
    691             sConnectOk = false;
    692             if (sReconnectEvent.wait (1000) == false) //if timeout occured
    693             {
    694                 ALOGE("%s: timeout waiting for select", __func__);
    695                 break;
    696             }
    697         }
    698 
    699         ALOGV("%s: select completed; sConnectOk=%d", __func__, sConnectOk);
    700         if (NfcTag::getInstance ().getActivationState () != NfcTag::Active)
    701         {
    702             ALOGE("%s: tag is not active", __func__);
    703             rVal = STATUS_CODE_TARGET_LOST;
    704             break;
    705         }
    706         if (sConnectOk)
    707         {
    708             rVal = 0;   // success
    709             sCurrentRfInterface = rfInterface;
    710         }
    711         else
    712         {
    713             rVal = 1;
    714         }
    715     } while (0);
    716 
    717     sConnectWaitingForComplete = JNI_FALSE;
    718     gIsTagDeactivating = false;
    719     gIsSelectingRfInterface = false;
    720     sRfInterfaceMutex.unlock ();
    721     ALOGV("%s: exit; status=%d", __func__, rVal);
    722     return rVal;
    723 }
    724 
    725 /*******************************************************************************
    726 **
    727 ** Function:        switchRfInterface
    728 **
    729 ** Description:     Switch controller's RF interface to frame, ISO-DEP, or NFC-DEP.
    730 **                  rfInterface: Type of RF interface.
    731 **
    732 ** Returns:         True if ok.
    733 **
    734 *******************************************************************************/
    735 static bool switchRfInterface (tNFA_INTF_TYPE rfInterface)
    736 {
    737     NfcTag& natTag = NfcTag::getInstance ();
    738 
    739     if (sCurrentConnectedTargetProtocol != NFC_PROTOCOL_ISO_DEP)
    740     {
    741         ALOGV("%s: protocol: %d not ISO_DEP, do nothing", __func__, natTag.mTechLibNfcTypes[0]);
    742         return true;
    743     }
    744 
    745     ALOGV("%s: new rf intf = %d, cur rf intf = %d", __func__, rfInterface, sCurrentRfInterface);
    746 
    747     return (0 == reSelect(rfInterface, true));
    748 }
    749 
    750 
    751 /*******************************************************************************
    752 **
    753 ** Function:        nativeNfcTag_doReconnect
    754 **
    755 ** Description:     Re-connect to the tag in RF field.
    756 **                  e: JVM environment.
    757 **                  o: Java object.
    758 **
    759 ** Returns:         Status code.
    760 **
    761 *******************************************************************************/
    762 static jint nativeNfcTag_doReconnect (JNIEnv*, jobject)
    763 {
    764     ALOGV("%s: enter", __func__);
    765     int retCode = NFCSTATUS_SUCCESS;
    766     NfcTag& natTag = NfcTag::getInstance ();
    767 
    768     if (natTag.getActivationState() != NfcTag::Active)
    769     {
    770         ALOGE("%s: tag already deactivated", __func__);
    771         retCode = NFCSTATUS_FAILED;
    772         goto TheEnd;
    773     }
    774 
    775     // special case for Kovio
    776     if (sCurrentConnectedTargetProtocol == TARGET_TYPE_KOVIO_BARCODE)
    777     {
    778         ALOGV("%s: fake out reconnect for Kovio", __func__);
    779         goto TheEnd;
    780     }
    781 
    782      // this is only supported for type 2 or 4 (ISO_DEP) tags
    783     if (sCurrentConnectedTargetProtocol == NFA_PROTOCOL_ISO_DEP)
    784         retCode = reSelect (NFA_INTERFACE_ISO_DEP, false);
    785     else if (sCurrentConnectedTargetProtocol == NFA_PROTOCOL_T2T)
    786         retCode = reSelect (NFA_INTERFACE_FRAME, false);
    787     else if (sCurrentConnectedTargetProtocol == NFA_PROTOCOL_MIFARE)
    788         retCode = reSelect (NFA_INTERFACE_MIFARE, false);
    789 
    790 TheEnd:
    791     ALOGV("%s: exit 0x%X", __func__, retCode);
    792     return retCode;
    793 }
    794 
    795 
    796 /*******************************************************************************
    797 **
    798 ** Function:        nativeNfcTag_doHandleReconnect
    799 **
    800 ** Description:     Re-connect to the tag in RF field.
    801 **                  e: JVM environment.
    802 **                  o: Java object.
    803 **                  targetHandle: Handle of the tag.
    804 **
    805 ** Returns:         Status code.
    806 **
    807 *******************************************************************************/
    808 static jint nativeNfcTag_doHandleReconnect (JNIEnv *e, jobject o, jint targetHandle)
    809 {
    810     ALOGV("%s: targetHandle = %d", __func__, targetHandle);
    811     return nativeNfcTag_doConnect (e, o, targetHandle);
    812 }
    813 
    814 
    815 /*******************************************************************************
    816 **
    817 ** Function:        nativeNfcTag_doDisconnect
    818 **
    819 ** Description:     Deactivate the RF field.
    820 **                  e: JVM environment.
    821 **                  o: Java object.
    822 **
    823 ** Returns:         True if ok.
    824 **
    825 *******************************************************************************/
    826 static jboolean nativeNfcTag_doDisconnect (JNIEnv*, jobject)
    827 {
    828     ALOGV("%s: enter", __func__);
    829     tNFA_STATUS nfaStat = NFA_STATUS_OK;
    830 
    831     NfcTag::getInstance().resetAllTransceiveTimeouts ();
    832 
    833     if (NfcTag::getInstance ().getActivationState () != NfcTag::Active)
    834     {
    835         ALOGE("%s: tag already deactivated", __func__);
    836         goto TheEnd;
    837     }
    838 
    839     nfaStat = NFA_Deactivate (FALSE);
    840     if (nfaStat != NFA_STATUS_OK)
    841         ALOGE("%s: deactivate failed; error=0x%X", __func__, nfaStat);
    842 
    843 TheEnd:
    844     ALOGV("%s: exit", __func__);
    845     return (nfaStat == NFA_STATUS_OK) ? JNI_TRUE : JNI_FALSE;
    846 }
    847 
    848 
    849 /*******************************************************************************
    850 **
    851 ** Function:        nativeNfcTag_doTransceiveStatus
    852 **
    853 ** Description:     Receive the completion status of transceive operation.
    854 **                  status: operation status.
    855 **                  buf: Contains tag's response.
    856 **                  bufLen: Length of buffer.
    857 **
    858 ** Returns:         None
    859 **
    860 *******************************************************************************/
    861 void nativeNfcTag_doTransceiveStatus (tNFA_STATUS status, uint8_t* buf, uint32_t bufLen)
    862 {
    863     SyncEventGuard g (sTransceiveEvent);
    864     ALOGV("%s: data len=%d", __func__, bufLen);
    865 
    866     if (sCurrentConnectedTargetProtocol == NFA_PROTOCOL_MIFARE)
    867     {
    868        if (EXTNS_GetCallBackFlag () == FALSE)
    869        {
    870            EXTNS_MfcCallBack (buf, bufLen);
    871            return;
    872        }
    873     }
    874 
    875     if (!sWaitingForTransceive)
    876     {
    877         ALOGE("%s: drop data", __func__);
    878         return;
    879     }
    880     sRxDataStatus = status;
    881     if (sRxDataStatus == NFA_STATUS_OK || sRxDataStatus == NFA_STATUS_CONTINUE)
    882         sRxDataBuffer.append (buf, bufLen);
    883 
    884     if (sRxDataStatus == NFA_STATUS_OK)
    885         sTransceiveEvent.notifyOne ();
    886 }
    887 
    888 
    889 void nativeNfcTag_notifyRfTimeout ()
    890 {
    891     SyncEventGuard g (sTransceiveEvent);
    892     ALOGV("%s: waiting for transceive: %d", __func__, sWaitingForTransceive);
    893     if (!sWaitingForTransceive)
    894         return;
    895 
    896     sTransceiveRfTimeout = true;
    897 
    898     sTransceiveEvent.notifyOne ();
    899 }
    900 
    901 
    902 /*******************************************************************************
    903 **
    904 ** Function:        nativeNfcTag_doTransceive
    905 **
    906 ** Description:     Send raw data to the tag; receive tag's response.
    907 **                  e: JVM environment.
    908 **                  o: Java object.
    909 **                  raw: Not used.
    910 **                  statusTargetLost: Whether tag responds or times out.
    911 **
    912 ** Returns:         Response from tag.
    913 **
    914 *******************************************************************************/
    915 static jbyteArray nativeNfcTag_doTransceive (JNIEnv* e, jobject o, jbyteArray data, jboolean raw, jintArray statusTargetLost)
    916 {
    917     int timeout = NfcTag::getInstance ().getTransceiveTimeout (sCurrentConnectedTargetType);
    918     ALOGV("%s: enter; raw=%u; timeout = %d", __func__, raw, timeout);
    919 
    920     bool waitOk = false;
    921     bool isNack = false;
    922     jint *targetLost = NULL;
    923     tNFA_STATUS status;
    924 
    925     if (NfcTag::getInstance ().getActivationState () != NfcTag::Active)
    926     {
    927         if (statusTargetLost)
    928         {
    929             targetLost = e->GetIntArrayElements (statusTargetLost, 0);
    930             if (targetLost)
    931                 *targetLost = 1; //causes NFC service to throw TagLostException
    932             e->ReleaseIntArrayElements (statusTargetLost, targetLost, 0);
    933         }
    934         ALOGV("%s: tag not active", __func__);
    935         return NULL;
    936     }
    937 
    938     NfcTag& natTag = NfcTag::getInstance ();
    939 
    940     // get input buffer and length from java call
    941     ScopedByteArrayRO bytes(e, data);
    942     uint8_t* buf = const_cast<uint8_t*>(reinterpret_cast<const uint8_t*>(&bytes[0])); // TODO: API bug; NFA_SendRawFrame should take const*!
    943     size_t bufLen = bytes.size();
    944 
    945     if (statusTargetLost)
    946     {
    947         targetLost = e->GetIntArrayElements (statusTargetLost, 0);
    948         if (targetLost)
    949             *targetLost = 0; //success, tag is still present
    950     }
    951 
    952     sSwitchBackTimer.kill ();
    953     ScopedLocalRef<jbyteArray> result(e, NULL);
    954     do
    955     {
    956         {
    957             SyncEventGuard g (sTransceiveEvent);
    958             sTransceiveRfTimeout = false;
    959             sWaitingForTransceive = true;
    960             sRxDataStatus = NFA_STATUS_OK;
    961             sRxDataBuffer.clear ();
    962 
    963             if (sCurrentConnectedTargetProtocol == NFA_PROTOCOL_MIFARE)
    964             {
    965                 status = EXTNS_MfcTransceive (buf, bufLen);
    966             }
    967             else
    968             {
    969                 status = NFA_SendRawFrame (buf, bufLen,
    970                         NFA_DM_DEFAULT_PRESENCE_CHECK_START_DELAY);
    971             }
    972 
    973             if (status != NFA_STATUS_OK)
    974             {
    975                 ALOGE("%s: fail send; error=%d", __func__, status);
    976                 break;
    977             }
    978             waitOk = sTransceiveEvent.wait (timeout);
    979         }
    980 
    981         if (waitOk == false || sTransceiveRfTimeout) //if timeout occurred
    982         {
    983             ALOGE("%s: wait response timeout", __func__);
    984             if (targetLost)
    985                 *targetLost = 1; //causes NFC service to throw TagLostException
    986             break;
    987         }
    988 
    989         if (NfcTag::getInstance ().getActivationState () != NfcTag::Active)
    990         {
    991             ALOGE("%s: already deactivated", __func__);
    992             if (targetLost)
    993                 *targetLost = 1; //causes NFC service to throw TagLostException
    994             break;
    995         }
    996 
    997         ALOGV("%s: response %zu bytes", __func__, sRxDataBuffer.size());
    998 
    999         if ((natTag.getProtocol () == NFA_PROTOCOL_T2T) &&
   1000             natTag.isT2tNackResponse (sRxDataBuffer.data(), sRxDataBuffer.size()))
   1001         {
   1002             isNack = true;
   1003         }
   1004 
   1005         if (sRxDataBuffer.size() > 0)
   1006         {
   1007             if (isNack)
   1008             {
   1009                 //Some Mifare Ultralight C tags enter the HALT state after it
   1010                 //responds with a NACK.  Need to perform a "reconnect" operation
   1011                 //to wake it.
   1012                 ALOGV("%s: try reconnect", __func__);
   1013                 nativeNfcTag_doReconnect (NULL, NULL);
   1014                 ALOGV("%s: reconnect finish", __func__);
   1015             }
   1016             else if (sCurrentConnectedTargetProtocol == NFA_PROTOCOL_MIFARE)
   1017             {
   1018                 uint32_t transDataLen = sRxDataBuffer.size ();
   1019                 uint8_t *transData = (uint8_t *) sRxDataBuffer.data ();
   1020                 if (EXTNS_CheckMfcResponse (&transData, &transDataLen) == NFCSTATUS_FAILED)
   1021                 {
   1022                     nativeNfcTag_doReconnect (e, o);
   1023                 }
   1024                 else
   1025                 {
   1026                     if (transDataLen != 0)
   1027                     {
   1028                         result.reset (e->NewByteArray (transDataLen));
   1029                     }
   1030                     if (result.get () != NULL)
   1031                     {
   1032                         e->SetByteArrayRegion (result.get (), 0, transDataLen, (const jbyte *) transData);
   1033                     }
   1034                     else
   1035                         ALOGE("%s: Failed to allocate java byte array", __func__);
   1036                 }
   1037             }
   1038             else
   1039             {
   1040                 // marshall data to java for return
   1041                 result.reset(e->NewByteArray(sRxDataBuffer.size()));
   1042                 if (result.get() != NULL)
   1043                 {
   1044                     e->SetByteArrayRegion(result.get(), 0, sRxDataBuffer.size(), (const jbyte *) sRxDataBuffer.data());
   1045                 }
   1046                 else
   1047                     ALOGE("%s: Failed to allocate java byte array", __func__);
   1048             } // else a nack is treated as a transceive failure to the upper layers
   1049 
   1050             sRxDataBuffer.clear();
   1051         }
   1052     } while (0);
   1053 
   1054     sWaitingForTransceive = false;
   1055     if (targetLost)
   1056         e->ReleaseIntArrayElements (statusTargetLost, targetLost, 0);
   1057 
   1058     ALOGV("%s: exit", __func__);
   1059     return result.release();
   1060 }
   1061 
   1062 
   1063 /*******************************************************************************
   1064 **
   1065 ** Function:        nativeNfcTag_doGetNdefType
   1066 **
   1067 ** Description:     Retrieve the type of tag.
   1068 **                  e: JVM environment.
   1069 **                  o: Java object.
   1070 **                  libnfcType: Type of tag represented by JNI.
   1071 **                  javaType: Not used.
   1072 **
   1073 ** Returns:         Type of tag represented by NFC Service.
   1074 **
   1075 *******************************************************************************/
   1076 static jint nativeNfcTag_doGetNdefType (JNIEnv*, jobject, jint libnfcType, jint javaType)
   1077 {
   1078     ALOGV("%s: enter; libnfc type=%d; java type=%d", __func__, libnfcType, javaType);
   1079     jint ndefType = NDEF_UNKNOWN_TYPE;
   1080 
   1081     // For NFA, libnfcType is mapped to the protocol value received
   1082     // in the NFA_ACTIVATED_EVT and NFA_DISC_RESULT_EVT event.
   1083     if (NFA_PROTOCOL_T1T == libnfcType)
   1084     {
   1085         ndefType = NDEF_TYPE1_TAG;
   1086     }
   1087     else if (NFA_PROTOCOL_T2T == libnfcType)
   1088     {
   1089         ndefType = NDEF_TYPE2_TAG;
   1090     }
   1091     else if (NFA_PROTOCOL_T3T == libnfcType)
   1092     {
   1093         ndefType = NDEF_TYPE3_TAG;
   1094     }
   1095     else if (NFA_PROTOCOL_ISO_DEP == libnfcType)
   1096     {
   1097         ndefType = NDEF_TYPE4_TAG;
   1098     }
   1099     else if (NFA_PROTOCOL_MIFARE == libnfcType)
   1100     {
   1101         ndefType = NDEF_MIFARE_CLASSIC_TAG;
   1102     }
   1103     else
   1104     {
   1105         /* NFA_PROTOCOL_ISO15693, NFA_PROTOCOL_INVALID and others */
   1106         ndefType = NDEF_UNKNOWN_TYPE;
   1107     }
   1108     ALOGV("%s: exit; ndef type=%d", __func__, ndefType);
   1109     return ndefType;
   1110 }
   1111 
   1112 
   1113 /*******************************************************************************
   1114 **
   1115 ** Function:        nativeNfcTag_doCheckNdefResult
   1116 **
   1117 ** Description:     Receive the result of checking whether the tag contains a NDEF
   1118 **                  message.  Called by the NFA_NDEF_DETECT_EVT.
   1119 **                  status: Status of the operation.
   1120 **                  maxSize: Maximum size of NDEF message.
   1121 **                  currentSize: Current size of NDEF message.
   1122 **                  flags: Indicate various states.
   1123 **
   1124 ** Returns:         None
   1125 **
   1126 *******************************************************************************/
   1127 void nativeNfcTag_doCheckNdefResult (tNFA_STATUS status, uint32_t maxSize, uint32_t currentSize, uint8_t flags)
   1128 {
   1129     //this function's flags parameter is defined using the following macros
   1130     //in nfc/include/rw_api.h;
   1131     //#define RW_NDEF_FL_READ_ONLY  0x01    /* Tag is read only              */
   1132     //#define RW_NDEF_FL_FORMATED   0x02    /* Tag formated for NDEF         */
   1133     //#define RW_NDEF_FL_SUPPORTED  0x04    /* NDEF supported by the tag     */
   1134     //#define RW_NDEF_FL_UNKNOWN    0x08    /* Unable to find if tag is ndef capable/formated/read only */
   1135     //#define RW_NDEF_FL_FORMATABLE 0x10    /* Tag supports format operation */
   1136 
   1137     if (!sCheckNdefWaitingForComplete)
   1138     {
   1139         ALOGE("%s: not waiting", __func__);
   1140         return;
   1141     }
   1142 
   1143     if (flags & RW_NDEF_FL_READ_ONLY)
   1144         ALOGV("%s: flag read-only", __func__);
   1145     if (flags & RW_NDEF_FL_FORMATED)
   1146         ALOGV("%s: flag formatted for ndef", __func__);
   1147     if (flags & RW_NDEF_FL_SUPPORTED)
   1148         ALOGV("%s: flag ndef supported", __func__);
   1149     if (flags & RW_NDEF_FL_UNKNOWN)
   1150         ALOGV("%s: flag all unknown", __func__);
   1151     if (flags & RW_NDEF_FL_FORMATABLE)
   1152         ALOGV("%s: flag formattable", __func__);
   1153 
   1154     sCheckNdefWaitingForComplete = JNI_FALSE;
   1155     sCheckNdefStatus = status;
   1156     if (sCheckNdefStatus != NFA_STATUS_OK && sCheckNdefStatus != NFA_STATUS_TIMEOUT)
   1157         sCheckNdefStatus = NFA_STATUS_FAILED;
   1158     sCheckNdefCapable = false; //assume tag is NOT ndef capable
   1159     if (sCheckNdefStatus == NFA_STATUS_OK)
   1160     {
   1161         //NDEF content is on the tag
   1162         sCheckNdefMaxSize = maxSize;
   1163         sCheckNdefCurrentSize = currentSize;
   1164         sCheckNdefCardReadOnly = flags & RW_NDEF_FL_READ_ONLY;
   1165         sCheckNdefCapable = true;
   1166     }
   1167     else if (sCheckNdefStatus == NFA_STATUS_FAILED)
   1168     {
   1169         //no NDEF content on the tag
   1170         sCheckNdefMaxSize = 0;
   1171         sCheckNdefCurrentSize = 0;
   1172         sCheckNdefCardReadOnly = flags & RW_NDEF_FL_READ_ONLY;
   1173         if ((flags & RW_NDEF_FL_UNKNOWN) == 0) //if stack understands the tag
   1174         {
   1175             if (flags & RW_NDEF_FL_SUPPORTED) //if tag is ndef capable
   1176                 sCheckNdefCapable = true;
   1177         }
   1178     }
   1179     else
   1180     {
   1181         ALOGE("%s: unknown status=0x%X", __func__, status);
   1182         sCheckNdefMaxSize = 0;
   1183         sCheckNdefCurrentSize = 0;
   1184         sCheckNdefCardReadOnly = false;
   1185     }
   1186     sem_post (&sCheckNdefSem);
   1187 }
   1188 
   1189 
   1190 /*******************************************************************************
   1191 **
   1192 ** Function:        nativeNfcTag_doCheckNdef
   1193 **
   1194 ** Description:     Does the tag contain a NDEF message?
   1195 **                  e: JVM environment.
   1196 **                  o: Java object.
   1197 **                  ndefInfo: NDEF info.
   1198 **
   1199 ** Returns:         Status code; 0 is success.
   1200 **
   1201 *******************************************************************************/
   1202 static jint nativeNfcTag_doCheckNdef (JNIEnv* e, jobject o, jintArray ndefInfo)
   1203 {
   1204     tNFA_STATUS status = NFA_STATUS_FAILED;
   1205     jint* ndef = NULL;
   1206 
   1207     ALOGV("%s: enter", __func__);
   1208 
   1209     // special case for Kovio
   1210     if (sCurrentConnectedTargetProtocol == TARGET_TYPE_KOVIO_BARCODE)
   1211     {
   1212         ALOGV("%s: Kovio tag, no NDEF", __func__);
   1213         ndef = e->GetIntArrayElements (ndefInfo, 0);
   1214         ndef[0] = 0;
   1215         ndef[1] = NDEF_MODE_READ_ONLY;
   1216         e->ReleaseIntArrayElements (ndefInfo, ndef, 0);
   1217         return NFA_STATUS_FAILED;
   1218     }
   1219     else if (sCurrentConnectedTargetProtocol == NFA_PROTOCOL_MIFARE)
   1220     {
   1221         nativeNfcTag_doReconnect (e, o);
   1222     }
   1223 
   1224     /* Create the write semaphore */
   1225     if (sem_init (&sCheckNdefSem, 0, 0) == -1)
   1226     {
   1227         ALOGE("%s: Check NDEF semaphore creation failed (errno=0x%08x)", __func__, errno);
   1228         return JNI_FALSE;
   1229     }
   1230 
   1231     if (NfcTag::getInstance ().getActivationState () != NfcTag::Active)
   1232     {
   1233         ALOGE("%s: tag already deactivated", __func__);
   1234         goto TheEnd;
   1235     }
   1236 
   1237     ALOGV("%s: try NFA_RwDetectNDef", __func__);
   1238     sCheckNdefWaitingForComplete = JNI_TRUE;
   1239 
   1240     if (sCurrentConnectedTargetProtocol == NFA_PROTOCOL_MIFARE)
   1241     {
   1242         status = EXTNS_MfcCheckNDef ();
   1243     }
   1244     else
   1245     {
   1246         status = NFA_RwDetectNDef ();
   1247     }
   1248 
   1249     if (status != NFA_STATUS_OK)
   1250     {
   1251         ALOGE("%s: NFA_RwDetectNDef failed, status = 0x%X", __func__, status);
   1252         goto TheEnd;
   1253     }
   1254 
   1255     /* Wait for check NDEF completion status */
   1256     if (sem_wait (&sCheckNdefSem))
   1257     {
   1258         ALOGE("%s: Failed to wait for check NDEF semaphore (errno=0x%08x)", __func__, errno);
   1259         goto TheEnd;
   1260     }
   1261 
   1262     if (sCheckNdefStatus == NFA_STATUS_OK)
   1263     {
   1264         //stack found a NDEF message on the tag
   1265         ndef = e->GetIntArrayElements (ndefInfo, 0);
   1266         if (NfcTag::getInstance ().getProtocol () == NFA_PROTOCOL_T1T)
   1267             ndef[0] = NfcTag::getInstance ().getT1tMaxMessageSize ();
   1268         else
   1269             ndef[0] = sCheckNdefMaxSize;
   1270         if (sCheckNdefCardReadOnly)
   1271             ndef[1] = NDEF_MODE_READ_ONLY;
   1272         else
   1273             ndef[1] = NDEF_MODE_READ_WRITE;
   1274         e->ReleaseIntArrayElements (ndefInfo, ndef, 0);
   1275         status = NFA_STATUS_OK;
   1276     }
   1277     else if (sCheckNdefStatus == NFA_STATUS_FAILED)
   1278     {
   1279         //stack did not find a NDEF message on the tag;
   1280         ndef = e->GetIntArrayElements (ndefInfo, 0);
   1281         if (NfcTag::getInstance ().getProtocol () == NFA_PROTOCOL_T1T)
   1282             ndef[0] = NfcTag::getInstance ().getT1tMaxMessageSize ();
   1283         else
   1284             ndef[0] = sCheckNdefMaxSize;
   1285         if (sCheckNdefCardReadOnly)
   1286             ndef[1] = NDEF_MODE_READ_ONLY;
   1287         else
   1288             ndef[1] = NDEF_MODE_READ_WRITE;
   1289         e->ReleaseIntArrayElements (ndefInfo, ndef, 0);
   1290         status = NFA_STATUS_FAILED;
   1291     }
   1292     else if ((sCheckNdefStatus == NFA_STATUS_TIMEOUT) && (NfcTag::getInstance ().getProtocol() == NFC_PROTOCOL_ISO_DEP))
   1293     {
   1294         pn544InteropStopPolling ();
   1295         status = sCheckNdefStatus;
   1296     }
   1297     else
   1298     {
   1299         ALOGV("%s: unknown status 0x%X", __func__, sCheckNdefStatus);
   1300         status = sCheckNdefStatus;
   1301     }
   1302 
   1303     /* Reconnect Mifare Classic Tag for furture use */
   1304     if (sCurrentConnectedTargetProtocol == NFA_PROTOCOL_MIFARE)
   1305     {
   1306         nativeNfcTag_doReconnect (e, o);
   1307     }
   1308 
   1309 TheEnd:
   1310     /* Destroy semaphore */
   1311     if (sem_destroy (&sCheckNdefSem))
   1312     {
   1313         ALOGE("%s: Failed to destroy check NDEF semaphore (errno=0x%08x)", __func__, errno);
   1314     }
   1315     sCheckNdefWaitingForComplete = JNI_FALSE;
   1316     ALOGV("%s: exit; status=0x%X", __func__, status);
   1317     return status;
   1318 }
   1319 
   1320 
   1321 /*******************************************************************************
   1322 **
   1323 ** Function:        nativeNfcTag_resetPresenceCheck
   1324 **
   1325 ** Description:     Reset variables related to presence-check.
   1326 **
   1327 ** Returns:         None
   1328 **
   1329 *******************************************************************************/
   1330 void nativeNfcTag_resetPresenceCheck ()
   1331 {
   1332     sIsTagPresent = true;
   1333 }
   1334 
   1335 
   1336 /*******************************************************************************
   1337 **
   1338 ** Function:        nativeNfcTag_doPresenceCheckResult
   1339 **
   1340 ** Description:     Receive the result of presence-check.
   1341 **                  status: Result of presence-check.
   1342 **
   1343 ** Returns:         None
   1344 **
   1345 *******************************************************************************/
   1346 void nativeNfcTag_doPresenceCheckResult (tNFA_STATUS status)
   1347 {
   1348     SyncEventGuard guard (sPresenceCheckEvent);
   1349     sIsTagPresent = status == NFA_STATUS_OK;
   1350     sPresenceCheckEvent.notifyOne ();
   1351 }
   1352 
   1353 
   1354 /*******************************************************************************
   1355 **
   1356 ** Function:        nativeNfcTag_doPresenceCheck
   1357 **
   1358 ** Description:     Check if the tag is in the RF field.
   1359 **                  e: JVM environment.
   1360 **                  o: Java object.
   1361 **
   1362 ** Returns:         True if tag is in RF field.
   1363 **
   1364 *******************************************************************************/
   1365 static jboolean nativeNfcTag_doPresenceCheck (JNIEnv*, jobject)
   1366 {
   1367     ALOGV("%s", __func__);
   1368     tNFA_STATUS status = NFA_STATUS_OK;
   1369     jboolean isPresent = JNI_FALSE;
   1370 
   1371     // Special case for Kovio.  The deactivation would have already occurred
   1372     // but was ignored so that normal tag opertions could complete.  Now we
   1373     // want to process as if the deactivate just happened.
   1374     if (sCurrentConnectedTargetProtocol == TARGET_TYPE_KOVIO_BARCODE)
   1375     {
   1376         ALOGV("%s: Kovio, force deactivate handling", __func__);
   1377         tNFA_DEACTIVATED deactivated = {NFA_DEACTIVATE_TYPE_IDLE};
   1378         {
   1379             SyncEventGuard g (gDeactivatedEvent);
   1380             gActivated = false; //guard this variable from multi-threaded access
   1381             gDeactivatedEvent.notifyOne ();
   1382         }
   1383 
   1384         NfcTag::getInstance().setDeactivationState (deactivated);
   1385         nativeNfcTag_resetPresenceCheck();
   1386         NfcTag::getInstance().connectionEventHandler (NFA_DEACTIVATED_EVT, NULL);
   1387         nativeNfcTag_abortWaits();
   1388         NfcTag::getInstance().abort ();
   1389 
   1390         return JNI_FALSE;
   1391     }
   1392 
   1393     if (nfcManager_isNfcActive() == false)
   1394     {
   1395         ALOGV("%s: NFC is no longer active.", __func__);
   1396         return JNI_FALSE;
   1397     }
   1398 
   1399     if (!sRfInterfaceMutex.tryLock())
   1400     {
   1401         ALOGV("%s: tag is being reSelected assume it is present", __func__);
   1402         return JNI_TRUE;
   1403     }
   1404 
   1405     sRfInterfaceMutex.unlock();
   1406 
   1407     if (NfcTag::getInstance ().isActivated () == false)
   1408     {
   1409         ALOGV("%s: tag already deactivated", __func__);
   1410         return JNI_FALSE;
   1411     }
   1412     if (sCurrentConnectedTargetProtocol == NFA_PROTOCOL_MIFARE)
   1413     {
   1414         status = EXTNS_MfcPresenceCheck ();
   1415         if (status == NFCSTATUS_SUCCESS)
   1416         {
   1417             return (NFCSTATUS_SUCCESS == EXTNS_GetPresenceCheckStatus ()) ? JNI_TRUE : JNI_FALSE;
   1418         }
   1419     }
   1420 
   1421     {
   1422         SyncEventGuard guard (sPresenceCheckEvent);
   1423         status = NFA_RwPresenceCheck (NfcTag::getInstance().getPresenceCheckAlgorithm());
   1424         if (status == NFA_STATUS_OK)
   1425         {
   1426             sPresenceCheckEvent.wait ();
   1427             isPresent = sIsTagPresent ? JNI_TRUE : JNI_FALSE;
   1428         }
   1429     }
   1430 
   1431     if (isPresent == JNI_FALSE)
   1432         ALOGV("%s: tag absent", __func__);
   1433     return isPresent;
   1434 }
   1435 
   1436 
   1437 /*******************************************************************************
   1438 **
   1439 ** Function:        nativeNfcTag_doIsNdefFormatable
   1440 **
   1441 ** Description:     Can tag be formatted to store NDEF message?
   1442 **                  e: JVM environment.
   1443 **                  o: Java object.
   1444 **                  libNfcType: Type of tag.
   1445 **                  uidBytes: Tag's unique ID.
   1446 **                  pollBytes: Data from activation.
   1447 **                  actBytes: Data from activation.
   1448 **
   1449 ** Returns:         True if formattable.
   1450 **
   1451 *******************************************************************************/
   1452 static jboolean nativeNfcTag_doIsNdefFormatable (JNIEnv* e,
   1453         jobject o, jint /*libNfcType*/, jbyteArray, jbyteArray,
   1454         jbyteArray)
   1455 {
   1456     jboolean isFormattable = JNI_FALSE;
   1457     tNFC_PROTOCOL protocol = NfcTag::getInstance().getProtocol();
   1458     if (NFA_PROTOCOL_T1T == protocol || NFA_PROTOCOL_ISO15693 == protocol
   1459         || NFA_PROTOCOL_MIFARE == protocol)
   1460     {
   1461         isFormattable = JNI_TRUE;
   1462     }
   1463     else if (NFA_PROTOCOL_T3T == protocol)
   1464     {
   1465         isFormattable = NfcTag::getInstance().isFelicaLite() ? JNI_TRUE : JNI_FALSE;
   1466     }
   1467     else if (NFA_PROTOCOL_T2T == protocol)
   1468     {
   1469         isFormattable = ( NfcTag::getInstance().isMifareUltralight() |
   1470                           NfcTag::getInstance().isInfineonMyDMove() |
   1471                           NfcTag::getInstance().isKovioType2Tag() )
   1472                         ? JNI_TRUE : JNI_FALSE;
   1473     }
   1474     else if (NFA_PROTOCOL_ISO_DEP == protocol)
   1475     {
   1476         /**
   1477          * Determines whether this is a formatable IsoDep tag - currectly only NXP DESFire
   1478          * is supported.
   1479          */
   1480         uint8_t cmd[] = {0x90, 0x60, 0x00, 0x00, 0x00};
   1481 
   1482         if (NfcTag::getInstance ().isMifareDESFire ())
   1483         {
   1484             /* Identifies as DESfire, use get version cmd to be sure */
   1485             jbyteArray versionCmd = e->NewByteArray (5);
   1486             e->SetByteArrayRegion (versionCmd, 0, 5, (jbyte*) cmd);
   1487             jbyteArray respBytes = nativeNfcTag_doTransceive(e, o, versionCmd, JNI_TRUE, NULL);
   1488             if (respBytes != NULL)
   1489             {
   1490                 // Check whether the response matches a typical DESfire
   1491                 // response.
   1492                 // libNFC even does more advanced checking than we do
   1493                 // here, and will only format DESfire's with a certain
   1494                 // major/minor sw version and NXP as a manufacturer.
   1495                 // We don't want to do such checking here, to avoid
   1496                 // having to change code in multiple places.
   1497                 // A succesful (wrapped) DESFire getVersion command returns
   1498                 // 9 bytes, with byte 7 0x91 and byte 8 having status
   1499                 // code 0xAF (these values are fixed and well-known).
   1500                 int respLength = e->GetArrayLength (respBytes);
   1501                 uint8_t* resp = (uint8_t*) e->GetByteArrayElements (respBytes, NULL);
   1502                 if (respLength == 9 && resp[7] == 0x91 && resp[8] == 0xAF)
   1503                 {
   1504                     isFormattable = JNI_TRUE;
   1505                 }
   1506                 e->ReleaseByteArrayElements (respBytes, (jbyte *) resp, JNI_ABORT);
   1507             }
   1508         }
   1509     }
   1510 
   1511     ALOGV("%s: is formattable=%u", __func__, isFormattable);
   1512     return isFormattable;
   1513 }
   1514 
   1515 
   1516 /*******************************************************************************
   1517 **
   1518 ** Function:        nativeNfcTag_doIsIsoDepNdefFormatable
   1519 **
   1520 ** Description:     Is ISO-DEP tag formattable?
   1521 **                  e: JVM environment.
   1522 **                  o: Java object.
   1523 **                  pollBytes: Data from activation.
   1524 **                  actBytes: Data from activation.
   1525 **
   1526 ** Returns:         True if formattable.
   1527 **
   1528 *******************************************************************************/
   1529 static jboolean nativeNfcTag_doIsIsoDepNdefFormatable (JNIEnv *e, jobject o, jbyteArray pollBytes, jbyteArray actBytes)
   1530 {
   1531     uint8_t uidFake[] = { 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0 };
   1532     ALOGV("%s", __func__);
   1533     jbyteArray uidArray = e->NewByteArray (8);
   1534     e->SetByteArrayRegion (uidArray, 0, 8, (jbyte*) uidFake);
   1535     return nativeNfcTag_doIsNdefFormatable (e, o, 0, uidArray, pollBytes, actBytes);
   1536 }
   1537 
   1538 
   1539 /*******************************************************************************
   1540 **
   1541 ** Function:        nativeNfcTag_makeMifareNdefFormat
   1542 **
   1543 ** Description:     Format a mifare classic tag so it can store NDEF message.
   1544 **                  e: JVM environment.
   1545 **                  o: Java object.
   1546 **                  key: Key to acces tag.
   1547 **                  keySize: size of Key.
   1548 **
   1549 ** Returns:         True if ok.
   1550 **
   1551 *******************************************************************************/
   1552 static jboolean nativeNfcTag_makeMifareNdefFormat (JNIEnv *e, jobject o, uint8_t *key, uint32_t keySize)
   1553 {
   1554     ALOGV("%s: enter", __func__);
   1555     tNFA_STATUS status = NFA_STATUS_OK;
   1556 
   1557     status = nativeNfcTag_doReconnect (e, o);
   1558     if (status != NFA_STATUS_OK)
   1559     {
   1560         ALOGV("%s: reconnect error, status=%u", __func__, status);
   1561         return JNI_FALSE;
   1562     }
   1563 
   1564     sem_init (&sFormatSem, 0, 0);
   1565     sFormatOk = false;
   1566 
   1567     status = EXTNS_MfcFormatTag (key, keySize);
   1568 
   1569     if (status == NFA_STATUS_OK)
   1570     {
   1571         ALOGV("%s: wait for completion", __func__);
   1572         sem_wait (&sFormatSem);
   1573         status = sFormatOk ? NFA_STATUS_OK : NFA_STATUS_FAILED;
   1574     }
   1575     else
   1576     {
   1577         ALOGE("%s: error status=%u", __func__, status);
   1578     }
   1579 
   1580     sem_destroy (&sFormatSem);
   1581     ALOGV("%s: exit", __func__);
   1582     return (status == NFA_STATUS_OK) ? JNI_TRUE : JNI_FALSE;
   1583 }
   1584 
   1585 
   1586 /*******************************************************************************
   1587 **
   1588 ** Function:        nativeNfcTag_doNdefFormat
   1589 **
   1590 ** Description:     Format a tag so it can store NDEF message.
   1591 **                  e: JVM environment.
   1592 **                  o: Java object.
   1593 **                  key: Not used.
   1594 **
   1595 ** Returns:         True if ok.
   1596 **
   1597 *******************************************************************************/
   1598 static jboolean nativeNfcTag_doNdefFormat (JNIEnv *e, jobject o, jbyteArray)
   1599 {
   1600     ALOGV("%s: enter", __func__);
   1601     tNFA_STATUS status = NFA_STATUS_OK;
   1602 
   1603     // Do not try to format if tag is already deactivated.
   1604     if (NfcTag::getInstance ().isActivated () == false)
   1605     {
   1606         ALOGV("%s: tag already deactivated(no need to format)", __func__);
   1607         return JNI_FALSE;
   1608     }
   1609 
   1610     if (sCurrentConnectedTargetProtocol == NFA_PROTOCOL_MIFARE)
   1611     {
   1612         static uint8_t mfc_key1[6] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF};
   1613         static uint8_t mfc_key2[6] = {0xD3, 0xF7, 0xD3, 0xF7, 0xD3, 0xF7};
   1614         jboolean result;
   1615 
   1616         result = nativeNfcTag_makeMifareNdefFormat (e, o, mfc_key1, sizeof(mfc_key1));
   1617         if (result == JNI_FALSE)
   1618         {
   1619             result = nativeNfcTag_makeMifareNdefFormat (e, o, mfc_key2, sizeof(mfc_key2));
   1620         }
   1621         return result;
   1622     }
   1623 
   1624     sem_init (&sFormatSem, 0, 0);
   1625     sFormatOk = false;
   1626     status = NFA_RwFormatTag ();
   1627     if (status == NFA_STATUS_OK)
   1628     {
   1629         ALOGV("%s: wait for completion", __func__);
   1630         sem_wait (&sFormatSem);
   1631         status = sFormatOk ? NFA_STATUS_OK : NFA_STATUS_FAILED;
   1632     }
   1633     else
   1634         ALOGE("%s: error status=%u", __func__, status);
   1635     sem_destroy (&sFormatSem);
   1636 
   1637     if (sCurrentConnectedTargetProtocol == NFA_PROTOCOL_ISO_DEP)
   1638     {
   1639         int retCode = NFCSTATUS_SUCCESS;
   1640         retCode = nativeNfcTag_doReconnect (e, o);
   1641     }
   1642     ALOGV("%s: exit", __func__);
   1643     return (status == NFA_STATUS_OK) ? JNI_TRUE : JNI_FALSE;
   1644 }
   1645 
   1646 
   1647 /*******************************************************************************
   1648 **
   1649 ** Function:        nativeNfcTag_doMakeReadonlyResult
   1650 **
   1651 ** Description:     Receive the result of making a tag read-only. Called by the
   1652 **                  NFA_SET_TAG_RO_EVT.
   1653 **                  status: Status of the operation.
   1654 **
   1655 ** Returns:         None
   1656 **
   1657 *******************************************************************************/
   1658 void nativeNfcTag_doMakeReadonlyResult (tNFA_STATUS status)
   1659 {
   1660     if (sMakeReadonlyWaitingForComplete != JNI_FALSE)
   1661     {
   1662         sMakeReadonlyWaitingForComplete = JNI_FALSE;
   1663         sMakeReadonlyStatus = status;
   1664 
   1665         sem_post (&sMakeReadonlySem);
   1666     }
   1667 }
   1668 
   1669 
   1670 /*******************************************************************************
   1671 **
   1672 ** Function:        nativeNfcTag_makeMifareReadonly
   1673 **
   1674 ** Description:     Make the mifare classic tag read-only.
   1675 **                  e: JVM environment.
   1676 **                  o: Java object.
   1677 **                  key: Key to access the tag.
   1678 **                  keySize: size of Key.
   1679 **
   1680 ** Returns:         True if ok.
   1681 **
   1682 *******************************************************************************/
   1683 static jboolean nativeNfcTag_makeMifareReadonly (JNIEnv *e, jobject o, uint8_t *key, int32_t keySize)
   1684 {
   1685     jboolean result = JNI_FALSE;
   1686     tNFA_STATUS status = NFA_STATUS_OK;
   1687 
   1688     sMakeReadonlyStatus = NFA_STATUS_FAILED;
   1689 
   1690     ALOGV("%s", __func__);
   1691 
   1692     /* Create the make_readonly semaphore */
   1693     if (sem_init (&sMakeReadonlySem, 0, 0) == -1)
   1694     {
   1695         ALOGE("%s: Make readonly semaphore creation failed (errno=0x%08x)", __func__, errno);
   1696         return JNI_FALSE;
   1697     }
   1698 
   1699     sMakeReadonlyWaitingForComplete = JNI_TRUE;
   1700 
   1701     status = nativeNfcTag_doReconnect (e, o);
   1702     if (status != NFA_STATUS_OK)
   1703     {
   1704         goto TheEnd;
   1705     }
   1706 
   1707     status = EXTNS_MfcSetReadOnly (key, keySize);
   1708     if (status != NFA_STATUS_OK)
   1709     {
   1710         goto TheEnd;
   1711     }
   1712     sem_wait (&sMakeReadonlySem);
   1713 
   1714     if (sMakeReadonlyStatus == NFA_STATUS_OK)
   1715     {
   1716         result = JNI_TRUE;
   1717     }
   1718 
   1719 TheEnd:
   1720     /* Destroy semaphore */
   1721     if (sem_destroy (&sMakeReadonlySem))
   1722     {
   1723         ALOGE("%s: Failed to destroy read_only semaphore (errno=0x%08x)", __func__, errno);
   1724     }
   1725     sMakeReadonlyWaitingForComplete = JNI_FALSE;
   1726     return result;
   1727 }
   1728 
   1729 
   1730 /*******************************************************************************
   1731 **
   1732 ** Function:        nativeNfcTag_doMakeReadonly
   1733 **
   1734 ** Description:     Make the tag read-only.
   1735 **                  e: JVM environment.
   1736 **                  o: Java object.
   1737 **                  key: Key to access the tag.
   1738 **
   1739 ** Returns:         True if ok.
   1740 **
   1741 *******************************************************************************/
   1742 static jboolean nativeNfcTag_doMakeReadonly (JNIEnv *e, jobject o, jbyteArray)
   1743 {
   1744     jboolean result = JNI_FALSE;
   1745     tNFA_STATUS status;
   1746 
   1747     ALOGV("%s", __func__);
   1748 
   1749     if (sCurrentConnectedTargetProtocol == NFA_PROTOCOL_MIFARE)
   1750     {
   1751         static uint8_t mfc_key1[6] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF};
   1752         static uint8_t mfc_key2[6] = {0xD3, 0xF7, 0xD3, 0xF7, 0xD3, 0xF7};
   1753         result = nativeNfcTag_makeMifareReadonly (e, o, mfc_key1, sizeof(mfc_key1));
   1754         if (result == JNI_FALSE)
   1755         {
   1756             result = nativeNfcTag_makeMifareReadonly (e, o, mfc_key2, sizeof(mfc_key2));
   1757         }
   1758         return result;
   1759     }
   1760 
   1761     /* Create the make_readonly semaphore */
   1762     if (sem_init (&sMakeReadonlySem, 0, 0) == -1)
   1763     {
   1764         ALOGE("%s: Make readonly semaphore creation failed (errno=0x%08x)", __func__, errno);
   1765         return JNI_FALSE;
   1766     }
   1767 
   1768     sMakeReadonlyWaitingForComplete = JNI_TRUE;
   1769 
   1770     // Hard-lock the tag (cannot be reverted)
   1771     status = NFA_RwSetTagReadOnly(TRUE);
   1772     if (status == NFA_STATUS_REJECTED)
   1773     {
   1774         status = NFA_RwSetTagReadOnly (FALSE); //try soft lock
   1775         if (status != NFA_STATUS_OK)
   1776         {
   1777             ALOGE("%s: fail soft lock, status=%d", __func__, status);
   1778             goto TheEnd;
   1779         }
   1780     }
   1781     else if (status != NFA_STATUS_OK)
   1782     {
   1783         ALOGE("%s: fail hard lock, status=%d", __func__, status);
   1784         goto TheEnd;
   1785     }
   1786 
   1787     /* Wait for check NDEF completion status */
   1788     if (sem_wait (&sMakeReadonlySem))
   1789     {
   1790         ALOGE("%s: Failed to wait for make_readonly semaphore (errno=0x%08x)", __func__, errno);
   1791         goto TheEnd;
   1792     }
   1793 
   1794     if (sMakeReadonlyStatus == NFA_STATUS_OK)
   1795     {
   1796         result = JNI_TRUE;
   1797     }
   1798 
   1799 TheEnd:
   1800     /* Destroy semaphore */
   1801     if (sem_destroy (&sMakeReadonlySem))
   1802     {
   1803         ALOGE("%s: Failed to destroy read_only semaphore (errno=0x%08x)", __func__, errno);
   1804     }
   1805     sMakeReadonlyWaitingForComplete = JNI_FALSE;
   1806     return result;
   1807 }
   1808 
   1809 
   1810 /*******************************************************************************
   1811 **
   1812 ** Function:        nativeNfcTag_registerNdefTypeHandler
   1813 **
   1814 ** Description:     Register a callback to receive NDEF message from the tag
   1815 **                  from the NFA_NDEF_DATA_EVT.
   1816 **
   1817 ** Returns:         None
   1818 **
   1819 *******************************************************************************/
   1820 //register a callback to receive NDEF message from the tag
   1821 //from the NFA_NDEF_DATA_EVT;
   1822 void nativeNfcTag_registerNdefTypeHandler ()
   1823 {
   1824     ALOGV("%s", __func__);
   1825     sNdefTypeHandlerHandle = NFA_HANDLE_INVALID;
   1826     NFA_RegisterNDefTypeHandler (TRUE, NFA_TNF_DEFAULT, (uint8_t *) "", 0, ndefHandlerCallback);
   1827     EXTNS_MfcRegisterNDefTypeHandler (ndefHandlerCallback);
   1828 }
   1829 
   1830 
   1831 /*******************************************************************************
   1832 **
   1833 ** Function:        nativeNfcTag_deregisterNdefTypeHandler
   1834 **
   1835 ** Description:     No longer need to receive NDEF message from the tag.
   1836 **
   1837 ** Returns:         None
   1838 **
   1839 *******************************************************************************/
   1840 void nativeNfcTag_deregisterNdefTypeHandler ()
   1841 {
   1842     ALOGV("%s", __func__);
   1843     NFA_DeregisterNDefTypeHandler (sNdefTypeHandlerHandle);
   1844     sNdefTypeHandlerHandle = NFA_HANDLE_INVALID;
   1845 }
   1846 
   1847 
   1848 /*****************************************************************************
   1849 **
   1850 ** JNI functions for Android 4.0.3
   1851 **
   1852 *****************************************************************************/
   1853 static JNINativeMethod gMethods[] =
   1854 {
   1855    {"doConnect", "(I)I", (void *)nativeNfcTag_doConnect},
   1856    {"doDisconnect", "()Z", (void *)nativeNfcTag_doDisconnect},
   1857    {"doReconnect", "()I", (void *)nativeNfcTag_doReconnect},
   1858    {"doHandleReconnect", "(I)I", (void *)nativeNfcTag_doHandleReconnect},
   1859    {"doTransceive", "([BZ[I)[B", (void *)nativeNfcTag_doTransceive},
   1860    {"doGetNdefType", "(II)I", (void *)nativeNfcTag_doGetNdefType},
   1861    {"doCheckNdef", "([I)I", (void *)nativeNfcTag_doCheckNdef},
   1862    {"doRead", "()[B", (void *)nativeNfcTag_doRead},
   1863    {"doWrite", "([B)Z", (void *)nativeNfcTag_doWrite},
   1864    {"doPresenceCheck", "()Z", (void *)nativeNfcTag_doPresenceCheck},
   1865    {"doIsIsoDepNdefFormatable", "([B[B)Z", (void *)nativeNfcTag_doIsIsoDepNdefFormatable},
   1866    {"doNdefFormat", "([B)Z", (void *)nativeNfcTag_doNdefFormat},
   1867    {"doMakeReadonly", "([B)Z", (void *)nativeNfcTag_doMakeReadonly},
   1868 };
   1869 
   1870 
   1871 /*******************************************************************************
   1872 **
   1873 ** Function:        register_com_android_nfc_NativeNfcTag
   1874 **
   1875 ** Description:     Regisgter JNI functions with Java Virtual Machine.
   1876 **                  e: Environment of JVM.
   1877 **
   1878 ** Returns:         Status of registration.
   1879 **
   1880 *******************************************************************************/
   1881 int register_com_android_nfc_NativeNfcTag (JNIEnv *e)
   1882 {
   1883     ALOGV("%s", __func__);
   1884     return jniRegisterNativeMethods (e, gNativeNfcTagClassName, gMethods, NELEM (gMethods));
   1885 }
   1886 
   1887 
   1888 } /* namespace android */
   1889