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> 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 ALOGD ("%s", __FUNCTION__); 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 ALOGD ("%s: status=0x%X; is reading=%u", __FUNCTION__, 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 ALOGD ("%s: event=%u, eventData=%p", __FUNCTION__, event, eventData); 222 223 switch (event) 224 { 225 case NFA_NDEF_REGISTER_EVT: 226 { 227 tNFA_NDEF_REGISTER& ndef_reg = eventData->ndef_reg; 228 ALOGD ("%s: NFA_NDEF_REGISTER_EVT; status=0x%X; h=0x%X", __FUNCTION__, 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 ALOGD ("%s: NFA_NDEF_DATA_EVT; data_len = %lu", __FUNCTION__, 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 ????", __FUNCTION__, 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 ALOGD ("%s: enter", __FUNCTION__); 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 ALOGD ("%s: read %u bytes", __FUNCTION__, sReadDataLen); 293 buf = e->NewByteArray (sReadDataLen); 294 e->SetByteArrayRegion (buf, 0, sReadDataLen, (jbyte*) sReadData); 295 } 296 } 297 else 298 { 299 ALOGD ("%s: create empty buffer", __FUNCTION__); 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 ALOGD ("%s: exit", __FUNCTION__); 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 buffer[maxBufferSize] = { 0 }; 376 UINT32 curDataSize = 0; 377 378 ScopedByteArrayRO bytes(e, buf); 379 UINT8* p_data = const_cast<UINT8*>(reinterpret_cast<const UINT8*>(&bytes[0])); // TODO: const-ness API bug in NFA_RwWriteNDef! 380 381 ALOGD ("%s: enter; len = %zu", __FUNCTION__, 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)", __FUNCTION__, 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 ALOGD ("%s: try format", __FUNCTION__); 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", __FUNCTION__); 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", __FUNCTION__); 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 ALOGD ("%s: try write", __FUNCTION__); 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 ALOGD ("%s: create empty ndef msg; status=%u; size=%lu", __FUNCTION__, 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 ALOGD ("%s: NFA_RwWriteNDef", __FUNCTION__); 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", __FUNCTION__, 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)", __FUNCTION__, 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)", __FUNCTION__, errno); 488 } 489 sWriteWaitingForComplete = JNI_FALSE; 490 ALOGD ("%s: exit; result=%d", __FUNCTION__, 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 ALOGD ("%s: targetHandle = %d", __FUNCTION__, 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", __FUNCTION__); 571 retCode = NFCSTATUS_FAILED; 572 goto TheEnd; 573 } 574 575 if (natTag.getActivationState() != NfcTag::Active) 576 { 577 ALOGE ("%s: tag already deactivated", __FUNCTION__); 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 ALOGD ("%s() Nfc type = %d, do nothing for non ISO_DEP", __FUNCTION__, sCurrentConnectedTargetProtocol); 588 retCode = NFCSTATUS_SUCCESS; 589 goto TheEnd; 590 } 591 592 if (sCurrentConnectedTargetType == TARGET_TYPE_ISO14443_3A || sCurrentConnectedTargetType == TARGET_TYPE_ISO14443_3B) 593 { 594 ALOGD ("%s: switching to tech: %d need to switch rf intf to frame", __FUNCTION__, 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 ALOGD ("%s: exit 0x%X", __FUNCTION__, 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 ALOGD ("%s: enter; rf intf = %d, current intf = %d", __FUNCTION__, 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 ALOGD ("%s: ndef detection timeout; break", __FUNCTION__); 643 rVal = STATUS_CODE_TARGET_LOST; 644 break; 645 } 646 647 { 648 SyncEventGuard g (sReconnectEvent); 649 gIsTagDeactivating = true; 650 sGotDeactivate = false; 651 ALOGD ("%s: deactivate to sleep", __FUNCTION__); 652 if (NFA_STATUS_OK != (status = NFA_Deactivate (TRUE))) //deactivate to sleep state 653 { 654 ALOGE ("%s: deactivate failed, status = %d", __FUNCTION__, status); 655 break; 656 } 657 658 if (sReconnectEvent.wait (1000) == false) //if timeout occurred 659 { 660 ALOGE ("%s: timeout waiting for deactivate", __FUNCTION__); 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", __FUNCTION__); 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 ALOGD ("%s: select interface %u", __FUNCTION__, 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", __FUNCTION__, 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", __FUNCTION__); 695 break; 696 } 697 } 698 699 ALOGD("%s: select completed; sConnectOk=%d", __FUNCTION__, sConnectOk); 700 if (NfcTag::getInstance ().getActivationState () != NfcTag::Active) 701 { 702 ALOGE("%s: tag is not active", __FUNCTION__); 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 ALOGD ("%s: exit; status=%d", __FUNCTION__, 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 ALOGD ("%s: protocol: %d not ISO_DEP, do nothing", __FUNCTION__, natTag.mTechLibNfcTypes[0]); 742 return true; 743 } 744 745 ALOGD ("%s: new rf intf = %d, cur rf intf = %d", __FUNCTION__, 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 ALOGD ("%s: enter", __FUNCTION__); 765 int retCode = NFCSTATUS_SUCCESS; 766 NfcTag& natTag = NfcTag::getInstance (); 767 768 if (natTag.getActivationState() != NfcTag::Active) 769 { 770 ALOGE ("%s: tag already deactivated", __FUNCTION__); 771 retCode = NFCSTATUS_FAILED; 772 goto TheEnd; 773 } 774 775 // special case for Kovio 776 if (sCurrentConnectedTargetProtocol == TARGET_TYPE_KOVIO_BARCODE) 777 { 778 ALOGD ("%s: fake out reconnect for Kovio", __FUNCTION__); 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 ALOGD ("%s: exit 0x%X", __FUNCTION__, 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 ALOGD ("%s: targetHandle = %d", __FUNCTION__, 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 ALOGD ("%s: enter", __FUNCTION__); 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", __FUNCTION__); 836 goto TheEnd; 837 } 838 839 nfaStat = NFA_Deactivate (FALSE); 840 if (nfaStat != NFA_STATUS_OK) 841 ALOGE ("%s: deactivate failed; error=0x%X", __FUNCTION__, nfaStat); 842 843 TheEnd: 844 ALOGD ("%s: exit", __FUNCTION__); 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 ALOGD ("%s: data len=%d", __FUNCTION__, 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", __FUNCTION__); 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 ALOGD ("%s: waiting for transceive: %d", __FUNCTION__, 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 ALOGD ("%s: enter; raw=%u; timeout = %d", __FUNCTION__, 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 ALOGD ("%s: tag not active", __FUNCTION__); 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", __FUNCTION__, 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", __FUNCTION__); 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", __FUNCTION__); 992 if (targetLost) 993 *targetLost = 1; //causes NFC service to throw TagLostException 994 break; 995 } 996 997 ALOGD ("%s: response %zu bytes", __FUNCTION__, 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 ALOGD ("%s: try reconnect", __FUNCTION__); 1013 nativeNfcTag_doReconnect (NULL, NULL); 1014 ALOGD ("%s: reconnect finish", __FUNCTION__); 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", __FUNCTION__); 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", __FUNCTION__); 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 ALOGD ("%s: exit", __FUNCTION__); 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 ALOGD ("%s: enter; libnfc type=%d; java type=%d", __FUNCTION__, 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 ALOGD ("%s: exit; ndef type=%d", __FUNCTION__, 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", __FUNCTION__); 1140 return; 1141 } 1142 1143 if (flags & RW_NDEF_FL_READ_ONLY) 1144 ALOGD ("%s: flag read-only", __FUNCTION__); 1145 if (flags & RW_NDEF_FL_FORMATED) 1146 ALOGD ("%s: flag formatted for ndef", __FUNCTION__); 1147 if (flags & RW_NDEF_FL_SUPPORTED) 1148 ALOGD ("%s: flag ndef supported", __FUNCTION__); 1149 if (flags & RW_NDEF_FL_UNKNOWN) 1150 ALOGD ("%s: flag all unknown", __FUNCTION__); 1151 if (flags & RW_NDEF_FL_FORMATABLE) 1152 ALOGD ("%s: flag formattable", __FUNCTION__); 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", __FUNCTION__, 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 ALOGD ("%s: enter", __FUNCTION__); 1208 1209 // special case for Kovio 1210 if (sCurrentConnectedTargetProtocol == TARGET_TYPE_KOVIO_BARCODE) 1211 { 1212 ALOGD ("%s: Kovio tag, no NDEF", __FUNCTION__); 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)", __FUNCTION__, errno); 1228 return JNI_FALSE; 1229 } 1230 1231 if (NfcTag::getInstance ().getActivationState () != NfcTag::Active) 1232 { 1233 ALOGE ("%s: tag already deactivated", __FUNCTION__); 1234 goto TheEnd; 1235 } 1236 1237 ALOGD ("%s: try NFA_RwDetectNDef", __FUNCTION__); 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", __FUNCTION__, 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)", __FUNCTION__, 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 ALOGD ("%s: unknown status 0x%X", __FUNCTION__, 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)", __FUNCTION__, errno); 1314 } 1315 sCheckNdefWaitingForComplete = JNI_FALSE; 1316 ALOGD ("%s: exit; status=0x%X", __FUNCTION__, 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 ALOGD ("%s", __FUNCTION__); 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 ALOGD ("%s: Kovio, force deactivate handling", __FUNCTION__); 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 ALOGD ("%s: NFC is no longer active.", __FUNCTION__); 1396 return JNI_FALSE; 1397 } 1398 1399 if (!sRfInterfaceMutex.tryLock()) 1400 { 1401 ALOGD ("%s: tag is being reSelected assume it is present", __FUNCTION__); 1402 return JNI_TRUE; 1403 } 1404 1405 sRfInterfaceMutex.unlock(); 1406 1407 if (NfcTag::getInstance ().isActivated () == false) 1408 { 1409 ALOGD ("%s: tag already deactivated", __FUNCTION__); 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 ALOGD ("%s: tag absent", __FUNCTION__); 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 ALOGD("%s: is formattable=%u", __FUNCTION__, 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 ALOGD ("%s", __FUNCTION__); 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 ALOGD ("%s: enter", __FUNCTION__); 1555 tNFA_STATUS status = NFA_STATUS_OK; 1556 1557 status = nativeNfcTag_doReconnect (e, o); 1558 if (status != NFA_STATUS_OK) 1559 { 1560 ALOGD ("%s: reconnect error, status=%u", __FUNCTION__, 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 ALOGD ("%s: wait for completion", __FUNCTION__); 1572 sem_wait (&sFormatSem); 1573 status = sFormatOk ? NFA_STATUS_OK : NFA_STATUS_FAILED; 1574 } 1575 else 1576 { 1577 ALOGE ("%s: error status=%u", __FUNCTION__, status); 1578 } 1579 1580 sem_destroy (&sFormatSem); 1581 ALOGD ("%s: exit", __FUNCTION__); 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 ALOGD ("%s: enter", __FUNCTION__); 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 ALOGD ("%s: tag already deactivated(no need to format)", __FUNCTION__); 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 ALOGD ("%s: wait for completion", __FUNCTION__); 1630 sem_wait (&sFormatSem); 1631 status = sFormatOk ? NFA_STATUS_OK : NFA_STATUS_FAILED; 1632 } 1633 else 1634 ALOGE ("%s: error status=%u", __FUNCTION__, 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 ALOGD ("%s: exit", __FUNCTION__); 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 ALOGD ("%s", __FUNCTION__); 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)", __FUNCTION__, 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)", __FUNCTION__, 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 ALOGD ("%s", __FUNCTION__); 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)", __FUNCTION__, 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", __FUNCTION__, status); 1778 goto TheEnd; 1779 } 1780 } 1781 else if (status != NFA_STATUS_OK) 1782 { 1783 ALOGE ("%s: fail hard lock, status=%d", __FUNCTION__, 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)", __FUNCTION__, 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)", __FUNCTION__, 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 ALOGD ("%s", __FUNCTION__); 1825 sNdefTypeHandlerHandle = NFA_HANDLE_INVALID; 1826 NFA_RegisterNDefTypeHandler (TRUE, NFA_TNF_DEFAULT, (UINT8 *) "", 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 ALOGD ("%s", __FUNCTION__); 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 ALOGD ("%s", __FUNCTION__); 1884 return jniRegisterNativeMethods (e, gNativeNfcTagClassName, gMethods, NELEM (gMethods)); 1885 } 1886 1887 1888 } /* namespace android */ 1889