From 5e93195e37834429229350bdce670a64e536367a Mon Sep 17 00:00:00 2001 From: mike wakerly Date: Tue, 29 Mar 2011 19:09:53 -0700 Subject: NFC JNI: log detected AID as a single message. Change-Id: If8de4243ae945dd4203ac37e77d52521dfa31044 --- jni/com_android_nfc.h | 3 +++ jni/com_android_nfc_NativeNfcManager.cpp | 16 +++++++++------- 2 files changed, 12 insertions(+), 7 deletions(-) diff --git a/jni/com_android_nfc.h b/jni/com_android_nfc.h index 4fa5d73..b2009f2 100644 --- a/jni/com_android_nfc.h +++ b/jni/com_android_nfc.h @@ -101,6 +101,9 @@ extern "C" { #define TARGET_TYPE_MIFARE_CLASSIC 8 #define TARGET_TYPE_MIFARE_UL 9 +/* Maximum byte length of an AID. */ +#define AID_MAXLEN 16 + /* Utility macros for logging */ #define GET_LEVEL(status) ((status)==NFCSTATUS_SUCCESS)?ANDROID_LOG_DEBUG:ANDROID_LOG_WARN diff --git a/jni/com_android_nfc_NativeNfcManager.cpp b/jni/com_android_nfc_NativeNfcManager.cpp index 6ad736e..7f00088 100644 --- a/jni/com_android_nfc_NativeNfcManager.cpp +++ b/jni/com_android_nfc_NativeNfcManager.cpp @@ -18,6 +18,7 @@ #include #include #include +#include #include #include @@ -1152,20 +1153,21 @@ static void nfc_jni_transaction_callback(void *context, case phLibNfc_eSE_EvtStartTransaction: { TRACE("> SE EVT_START_TRANSACTION"); - if(evt_info->UiccEvtInfo.aid.length <= 16) + if(evt_info->UiccEvtInfo.aid.length <= AID_MAXLEN) { aid = &(evt_info->UiccEvtInfo.aid); LOGD("> AID DETECTED"); - LOGD("> AID:"); - for(i=0; i<(aid->length);i++) - { - LOGD("Ox%02x",aid->buffer[i]); - } - if(aid != NULL) { + char aid_str[AID_MAXLEN * 2 + 1]; + aid_str[0] = '\0'; + for (i = 0; i < (aid->length) && i < AID_MAXLEN; i++) { + snprintf(&aid_str[i*2], 3, "%02x", aid->buffer[i]); + } + LOGD("> AID: %s", aid_str); + aid_array = e->NewByteArray(aid->length); if(aid_array == NULL) { -- cgit v1.1 From 5e7b58d9c95a9074a42c3e4820e2467dfa85af10 Mon Sep 17 00:00:00 2001 From: Jeff Hamilton Date: Sun, 3 Apr 2011 19:20:00 -0500 Subject: Don't crash when an unregistered package is removed. Bug: 4205311 Change-Id: I116e7c2e12c7e160d81154d22589b1bdefe93e44 --- src/com/android/nfc/NfcService.java | 25 +++++++++++++++++-------- 1 file changed, 17 insertions(+), 8 deletions(-) diff --git a/src/com/android/nfc/NfcService.java b/src/com/android/nfc/NfcService.java index d681ae6..c47134d 100755 --- a/src/com/android/nfc/NfcService.java +++ b/src/com/android/nfc/NfcService.java @@ -2914,7 +2914,19 @@ public class NfcService extends Application { mSecureElement.doDisconnect(handle); } else if (intent.getAction().equals(Intent.ACTION_PACKAGE_REMOVED)) { - final String packageName = intent.getData().getSchemeSpecificPart(); + Uri data = intent.getData(); + if (data == null) return; + String packageName = data.getSchemeSpecificPart(); + ApduList apdus = null; + + synchronized (NfcService.this) { + apdus = mTearDownApdus.remove(packageName); + if (apdus == null) { + return; + } + + writeTearDownApdusLocked(); + } int handle = mSecureElement.doOpenSecureElementConnection(); if (handle == 0) { @@ -2922,16 +2934,13 @@ public class NfcService extends Application { return; } - synchronized (NfcService.this) { - for (byte[] cmd : mTearDownApdus.get(packageName).get()) { + try { + for (byte[] cmd : apdus.get()) { mSecureElement.doTransceive(handle, cmd); } - - mTearDownApdus.remove(packageName); - writeTearDownApdusLocked(); + } finally { + mSecureElement.doDisconnect(handle); } - - mSecureElement.doDisconnect(handle); } } }; -- cgit v1.1 From 7a7f8f8fd82936f0ee005ccfa7ac5c36760ed902 Mon Sep 17 00:00:00 2001 From: Jeff Hamilton Date: Wed, 20 Apr 2011 14:15:24 -0500 Subject: Only execute the teardown APDUs when a package is being fully removed. Bug: 4316508 Change-Id: I498eb09cfb48b3b14268c649936186000f360c16 --- src/com/android/nfc/NfcService.java | 46 ++++++++++++++++++++----------------- 1 file changed, 25 insertions(+), 21 deletions(-) diff --git a/src/com/android/nfc/NfcService.java b/src/com/android/nfc/NfcService.java index c47134d..34a100d 100755 --- a/src/com/android/nfc/NfcService.java +++ b/src/com/android/nfc/NfcService.java @@ -2914,32 +2914,36 @@ public class NfcService extends Application { mSecureElement.doDisconnect(handle); } else if (intent.getAction().equals(Intent.ACTION_PACKAGE_REMOVED)) { - Uri data = intent.getData(); - if (data == null) return; - String packageName = data.getSchemeSpecificPart(); - ApduList apdus = null; + boolean dataRemoved = intent.getBooleanExtra(Intent.EXTRA_DATA_REMOVED, false); + if (dataRemoved) { + Uri data = intent.getData(); + if (data == null) return; + String packageName = data.getSchemeSpecificPart(); + ApduList apdus = null; + + synchronized (NfcService.this) { + apdus = mTearDownApdus.remove(packageName); + if (apdus == null) { + return; + } - synchronized (NfcService.this) { - apdus = mTearDownApdus.remove(packageName); - if (apdus == null) { - return; - } - writeTearDownApdusLocked(); - } + writeTearDownApdusLocked(); + } - int handle = mSecureElement.doOpenSecureElementConnection(); - if (handle == 0) { - Log.e(TAG, "Could not open the secure element!"); - return; - } + int handle = mSecureElement.doOpenSecureElementConnection(); + if (handle == 0) { + Log.e(TAG, "Could not open the secure element!"); + return; + } - try { - for (byte[] cmd : apdus.get()) { - mSecureElement.doTransceive(handle, cmd); + try { + for (byte[] cmd : apdus.get()) { + mSecureElement.doTransceive(handle, cmd); + } + } finally { + mSecureElement.doDisconnect(handle); } - } finally { - mSecureElement.doDisconnect(handle); } } } -- cgit v1.1 From a8d8c1fa5058573c0d9d1305549c4326737db0b8 Mon Sep 17 00:00:00 2001 From: Jeff Hamilton Date: Wed, 20 Apr 2011 16:23:48 -0500 Subject: Avoid reference table overflows when dealing with secure elements. Bug: 4258601 Change-Id: Ib21892b6efa8e23ea86566ed6f88c2e9d284fa89 --- jni/com_android_nfc_NativeNfcSecureElement.cpp | 76 +++++++++----------------- 1 file changed, 27 insertions(+), 49 deletions(-) diff --git a/jni/com_android_nfc_NativeNfcSecureElement.cpp b/jni/com_android_nfc_NativeNfcSecureElement.cpp index b6e936c..7defeb2 100755 --- a/jni/com_android_nfc_NativeNfcSecureElement.cpp +++ b/jni/com_android_nfc_NativeNfcSecureElement.cpp @@ -122,63 +122,41 @@ static void com_android_nfc_jni_open_secure_element_notification_callback(void * else { LOG_CALLBACK("com_android_nfc_jni_open_secure_element_notification_callback", status); - TRACE("Discovered %d tags", uNofRemoteDev); + TRACE("Discovered %d secure elements", uNofRemoteDev); if(status == NFCSTATUS_MULTIPLE_PROTOCOLS) { TRACE("Multiple Protocol supported\n"); - - TRACE("Secure Element Handle: 0x%08x",psRemoteDevList[1].hTargetDev); - secureElementHandle = psRemoteDevList[1].hTargetDev; - - /* Set type name */ - jintArray techList; - jintArray handleList; - jintArray typeList; - - nfc_jni_get_technology_tree(e, psRemoteDevList,uNofRemoteDev, &techList, - &handleList, &typeList); - // TODO: Should use the "connected" technology, for now use the first - if (e->GetArrayLength(techList) > 0) { - jint* technologies = e->GetIntArrayElements(techList, 0); - SecureElementTech = technologies[0]; - TRACE("Store Secure Element Info\n"); - SecureElementInfo = psRemoteDevList->psRemoteDevInfo; - - TRACE("Discovered secure element: tech=%d", SecureElementTech); - } - else { - LOGE("Discovered secure element, but could not resolve tech"); - status = NFCSTATUS_FAILED; - } - + secureElementHandle = psRemoteDevList[1].hTargetDev; } else { - TRACE("Secure Element Handle: 0x%08x",psRemoteDevList->hTargetDev); - secureElementHandle = psRemoteDevList->hTargetDev; - - /* Set type name */ - jintArray techList; - jintArray handleList; - jintArray typeList; - nfc_jni_get_technology_tree(e, psRemoteDevList,uNofRemoteDev, &techList, - &handleList, &typeList); - - // TODO: Should use the "connected" technology, for now use the first - if ((techList != NULL) && e->GetArrayLength(techList) > 0) { - jint* technologies = e->GetIntArrayElements(techList, 0); - SecureElementTech = technologies[0]; - TRACE("Store Secure Element Info\n"); - SecureElementInfo = psRemoteDevList->psRemoteDevInfo; - - TRACE("Discovered secure element: tech=%d", SecureElementTech); - } - else { - LOGE("Discovered secure element, but could not resolve tech"); - status = NFCSTATUS_FAILED; - } + secureElementHandle = psRemoteDevList->hTargetDev; } + + TRACE("Secure Element Handle: 0x%08x", secureElementHandle); + + /* Set type name */ + jintArray techList; + jintArray handleList; + jintArray typeList; + nfc_jni_get_technology_tree(e, psRemoteDevList,uNofRemoteDev, &techList, + &handleList, &typeList); + + // TODO: Should use the "connected" technology, for now use the first + if ((techList != NULL) && e->GetArrayLength(techList) > 0) { + jint* technologies = e->GetIntArrayElements(techList, 0); + SecureElementTech = technologies[0]; + e->ReleaseIntArrayElements(techList, technologies, JNI_ABORT); + TRACE("Store Secure Element Info\n"); + SecureElementInfo = psRemoteDevList->psRemoteDevInfo; + + TRACE("Discovered secure element: tech=%d", SecureElementTech); + } + else { + LOGE("Discovered secure element, but could not resolve tech"); + status = NFCSTATUS_FAILED; + } } pContextData->status = status; -- cgit v1.1 From 275376f9e469a9e014d82978ba3b8d57fe4a7739 Mon Sep 17 00:00:00 2001 From: Jeff Hamilton Date: Wed, 20 Apr 2011 16:37:09 -0500 Subject: Better logging on SE open failure. If the secure element connection fails to open due to an external RF field being detected it's now logged to make debugging easier. Bug: 4304698 Change-Id: Iea6e23968ee18d4f99e7ecbbf1b60b7c1688f5b6 --- jni/com_android_nfc_NativeNfcSecureElement.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/jni/com_android_nfc_NativeNfcSecureElement.cpp b/jni/com_android_nfc_NativeNfcSecureElement.cpp index b6e936c..c8b7037 100755 --- a/jni/com_android_nfc_NativeNfcSecureElement.cpp +++ b/jni/com_android_nfc_NativeNfcSecureElement.cpp @@ -257,7 +257,8 @@ static jint com_android_nfc_NativeNfcSecureElement_doOpenSecureElementConnection if(mask_value == 0x40) { - TRACE("External RF Field detected"); + // There is an external RF field present, fail the open request + LOGD("Unable to open SE connection, external RF Field detected"); goto clean_and_return; } -- cgit v1.1 From 6344b6540f191d4ddeab4003965d81407ca48dea Mon Sep 17 00:00:00 2001 From: mike wakerly Date: Thu, 12 May 2011 13:33:34 -0700 Subject: Add Rev Change-Id: Ide8d8dfe75eebb93420bc7a95130b0f6a72756b6 --- jni/com_android_nfc_NativeNfcManager.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/jni/com_android_nfc_NativeNfcManager.cpp b/jni/com_android_nfc_NativeNfcManager.cpp index 7f00088..e220a33 100644 --- a/jni/com_android_nfc_NativeNfcManager.cpp +++ b/jni/com_android_nfc_NativeNfcManager.cpp @@ -400,13 +400,14 @@ static int nfc_jni_initialize(struct nfc_jni_native_data *nat) { } else { - LOGD("NFC capabilities: HAL = %x, FW = %x, HW = %x, Model = %x, HCI = %x, Full_FW = %d, FW Update Info = %d", + LOGD("NFC capabilities: HAL = %x, FW = %x, HW = %x, Model = %x, HCI = %x, Full_FW = %d, Rev = %d, FW Update Info = %d", caps.psDevCapabilities.hal_version, caps.psDevCapabilities.fw_version, caps.psDevCapabilities.hw_version, caps.psDevCapabilities.model_id, caps.psDevCapabilities.hci_version, caps.psDevCapabilities.full_version[NXP_FULL_VERSION_LEN-1], + caps.psDevCapabilities.full_version[NXP_FULL_VERSION_LEN-2], caps.psDevCapabilities.firmware_update_info); } -- cgit v1.1 From 6a8cddd71f669bb313788eea562c7e01cd587ae5 Mon Sep 17 00:00:00 2001 From: Jeff Hamilton Date: Sat, 21 May 2011 17:46:52 -0500 Subject: Another attempt at fixing JNI local reference leaks. The thread making the call here may never make it into the virtual machine, so the local reference is explicitly deleted. Bug: 4383243 Change-Id: I44d546f7f71a4fb2631133d65573cee19d466fb6 --- jni/com_android_nfc.cpp | 40 +++++++++++++++++--------- jni/com_android_nfc_NativeNfcSecureElement.cpp | 9 +++--- 2 files changed, 31 insertions(+), 18 deletions(-) diff --git a/jni/com_android_nfc.cpp b/jni/com_android_nfc.cpp index 6187c13..c9b9da1 100644 --- a/jni/com_android_nfc.cpp +++ b/jni/com_android_nfc.cpp @@ -560,23 +560,35 @@ void nfc_jni_get_technology_tree(JNIEnv* e, phLibNfc_RemoteDevList_t* devList, } } } + // Build the Java arrays - *techList = e->NewIntArray(index); - *handleList = e->NewIntArray(index); - *libnfcTypeList = e->NewIntArray(index); - - jint* techItems = e->GetIntArrayElements(*techList, NULL); - jint* handleItems = e->GetIntArrayElements(*handleList, NULL); - jint* typeItems = e->GetIntArrayElements(*libnfcTypeList, NULL); - for (int i = 0; i < index; i++) { - techItems[i] = technologies[i]; - handleItems[i] = handles[i]; - typeItems[i] = libnfctypes[i]; + if (techList != NULL) { + *techList = e->NewIntArray(index); + jint* techItems = e->GetIntArrayElements(*techList, NULL); + for (int i = 0; i < index; i++) { + techItems[i] = technologies[i]; + } + e->ReleaseIntArrayElements(*techList, techItems, 0); + } + + if (handleList != NULL) { + *handleList = e->NewIntArray(index); + jint* handleItems = e->GetIntArrayElements(*handleList, NULL); + for (int i = 0; i < index; i++) { + handleItems[i] = handles[i]; + } + e->ReleaseIntArrayElements(*handleList, handleItems, 0); } - e->ReleaseIntArrayElements(*techList, techItems, 0); - e->ReleaseIntArrayElements(*handleList, handleItems, 0); - e->ReleaseIntArrayElements(*libnfcTypeList, typeItems, 0); + if (libnfcTypeList != NULL) { + *libnfcTypeList = e->NewIntArray(index); + + jint* typeItems = e->GetIntArrayElements(*libnfcTypeList, NULL); + for (int i = 0; i < index; i++) { + typeItems[i] = libnfctypes[i]; + } + e->ReleaseIntArrayElements(*libnfcTypeList, typeItems, 0); + } } } // namespace android diff --git a/jni/com_android_nfc_NativeNfcSecureElement.cpp b/jni/com_android_nfc_NativeNfcSecureElement.cpp index 1e70839..f309122 100755 --- a/jni/com_android_nfc_NativeNfcSecureElement.cpp +++ b/jni/com_android_nfc_NativeNfcSecureElement.cpp @@ -138,10 +138,7 @@ static void com_android_nfc_jni_open_secure_element_notification_callback(void * /* Set type name */ jintArray techList; - jintArray handleList; - jintArray typeList; - nfc_jni_get_technology_tree(e, psRemoteDevList,uNofRemoteDev, &techList, - &handleList, &typeList); + nfc_jni_get_technology_tree(e, psRemoteDevList,uNofRemoteDev, &techList, NULL, NULL); // TODO: Should use the "connected" technology, for now use the first if ((techList != NULL) && e->GetArrayLength(techList) > 0) { @@ -157,6 +154,10 @@ static void com_android_nfc_jni_open_secure_element_notification_callback(void * LOGE("Discovered secure element, but could not resolve tech"); status = NFCSTATUS_FAILED; } + + // This thread may not return to the virtual machine for a long time + // so make sure to delete the local refernce to the tech list. + if (techList != NULL) e->DeleteLocalRef(techList); } pContextData->status = status; -- cgit v1.1 From a60e8301ea9d0d33921982c3cfe7d8854f187c40 Mon Sep 17 00:00:00 2001 From: Nick Pelly Date: Mon, 23 May 2011 16:06:27 -0700 Subject: Change default P2P initiator mode to phNfc_eP2P_ALL (all passive and 424A). Also add debug hooks to manually set P2P modes. Change-Id: I4abd8d5ac35c3ef6c6ffee475760b917a8bcebf1 --- jni/com_android_nfc_NativeNfcManager.cpp | 28 ++++++++++++++++++++++++++-- 1 file changed, 26 insertions(+), 2 deletions(-) diff --git a/jni/com_android_nfc_NativeNfcManager.cpp b/jni/com_android_nfc_NativeNfcManager.cpp index e220a33..c4d88f5 100644 --- a/jni/com_android_nfc_NativeNfcManager.cpp +++ b/jni/com_android_nfc_NativeNfcManager.cpp @@ -1271,6 +1271,30 @@ static void nfc_jni_start_card_emu_discovery_locked(struct nfc_jni_native_data * return; } +static short get_p2p_mode() { + char value[PROPERTY_VALUE_MAX]; + property_get("debug.nfc.NXP_NFCI_MODE", value, ""); + if (value[0]) { + short mode; + mode = atoi(value); + LOGD("debug.nfc.NXP_NFCI_MODE = %X", mode); + return mode; + } + return phNfc_eP2P_ALL; // default +} + +static bool get_p2p_target_disable() { + char value[PROPERTY_VALUE_MAX]; + property_get("debug.nfc.TARGET_DISABLE", value, ""); + if (value[0]) { + int mode; + mode = atoi(value); + LOGD("debug.nfc.TARGET_DISABLE = %d", mode); + return mode; + } + return FALSE; // default +} + static void nfc_jni_start_discovery_locked(struct nfc_jni_native_data *nat) { @@ -1299,9 +1323,9 @@ static void nfc_jni_start_discovery_locked(struct nfc_jni_native_data *nat) #endif nat->discovery_cfg.PollDevInfo.PollCfgInfo.DisableCardEmulation = FALSE; - nat->discovery_cfg.NfcIP_Mode = phNfc_ePassive424; + nat->discovery_cfg.NfcIP_Mode = get_p2p_mode(); //initiator nat->discovery_cfg.Duration = 300000; /* in ms */ - nat->discovery_cfg.NfcIP_Tgt_Disable = FALSE; + nat->discovery_cfg.NfcIP_Tgt_Disable = get_p2p_target_disable(); nat->registry_info.MifareUL = TRUE; -- cgit v1.1 From 30f99b9a446029bac5cb02b6efe5cae2f0349749 Mon Sep 17 00:00:00 2001 From: Daniel Tomas Date: Fri, 20 May 2011 03:40:05 +0200 Subject: Patch to set the ATQA of the P2P NFC Target 106 passive to 0x00 0x02 This patch permit to avoid a collision between NFC-WI and P2P NFC Target 106 passive mode in front of a payment reader. Change-Id: Ie044cf519c7cf56f70277a2bc4cb661cf43529db --- jni/com_android_nfc_NativeNfcManager.cpp | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/jni/com_android_nfc_NativeNfcManager.cpp b/jni/com_android_nfc_NativeNfcManager.cpp index c4d88f5..d0bd3b7 100644 --- a/jni/com_android_nfc_NativeNfcManager.cpp +++ b/jni/com_android_nfc_NativeNfcManager.cpp @@ -26,7 +26,7 @@ #define ERROR_BUFFER_TOO_SMALL -12 #define ERROR_INSUFFICIENT_RESOURCES -9 -#define EEDATA_SETTINGS_NUMBER 26 +#define EEDATA_SETTINGS_NUMBER 28 static phLibNfc_sConfig_t gDrvCfg; void *gHWRef; @@ -98,6 +98,10 @@ uint8_t EEDATA_Settings[EEDATA_SETTINGS_NUMBER][4] = { //SE GPIO ,{0x00, 0x98, 0x93, 0x40} + + // Set NFCT ATQA + ,{0x00, 0x98, 0x7D, 0x02} + ,{0x00, 0x98, 0x7E, 0x00} }; /* Internal functions declaration */ -- cgit v1.1 From 21ee4b2e782188cbc8e8b7752dd992844a904615 Mon Sep 17 00:00:00 2001 From: Jeff Hamilton Date: Tue, 24 May 2011 16:30:33 -0500 Subject: Add support for TNF_EXTERNAL in NDEF_DISCOVERED intents. The URN is converted to a URL in the form: vnd.android.nfc://ext/: so that it can be processed by IntentFilter. For example to catch all TNF_EXTERNAL entries for example.com you would use the following in your manifest: Change-Id: I5f5b121aa217364611923113985261a5c9a2171e --- src/com/android/nfc/NfcService.java | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/com/android/nfc/NfcService.java b/src/com/android/nfc/NfcService.java index 34a100d..7ab701b 100755 --- a/src/com/android/nfc/NfcService.java +++ b/src/com/android/nfc/NfcService.java @@ -2591,10 +2591,12 @@ public class NfcService extends Application { intent.setType(new String(type, Charsets.US_ASCII)); return true; } + case NdefRecord.TNF_ABSOLUTE_URI: { intent.setData(Uri.parse(new String(record.getPayload(), Charsets.UTF_8))); return true; } + case NdefRecord.TNF_WELL_KNOWN: { byte[] payload = record.getPayload(); if (payload == null || payload.length == 0) return false; @@ -2627,6 +2629,12 @@ public class NfcService extends Application { } return false; } + + case NdefRecord.TNF_EXTERNAL_TYPE: { + intent.setData(Uri.parse("vnd.android.nfc://ext/" + + new String(record.getType(), Charsets.US_ASCII))); + return true; + } } return false; } catch (Exception e) { -- cgit v1.1 From a8b7cca914e4a17f5c432f7bbeed0f1b236c55b4 Mon Sep 17 00:00:00 2001 From: Nick Pelly Date: Tue, 24 May 2011 17:59:04 -0700 Subject: Use a hardcoded SE reset script. Remove per-package support for tear-down. It just complicates things. Change-Id: I9ab413df339b2d5407084b2b83c0c2a8feabc0e4 --- src/com/android/nfc/NfcService.java | 173 ++++++++++++++---------------------- 1 file changed, 68 insertions(+), 105 deletions(-) diff --git a/src/com/android/nfc/NfcService.java b/src/com/android/nfc/NfcService.java index 34a100d..0227047 100755 --- a/src/com/android/nfc/NfcService.java +++ b/src/com/android/nfc/NfcService.java @@ -88,7 +88,7 @@ public class NfcService extends Application { static final boolean DBG = false; private static final String MY_TAG_FILE_NAME = "mytag"; - private static final String TEAR_DOWN_SCRIPTS_FILE_NAME = "teardowns"; + private static final String SE_RESET_SCRIPT_FILE_NAME = "/system/etc/se-reset-script"; static { System.loadLibrary("nfc_jni"); @@ -146,9 +146,7 @@ public class NfcService extends Application { private static final String NFC_PERM_ERROR = "NFC permission required"; private static final String ADMIN_PERM = android.Manifest.permission.WRITE_SECURE_SETTINGS; private static final String ADMIN_PERM_ERROR = "WRITE_SECURE_SETTINGS permission required"; - // STOPSHIP: This needs to be updated to the line below -// private static final String NFCEE_ADMIN_PERM = "com.android.nfc.permission.NFCEE_ADMIN"; - private static final String NFCEE_ADMIN_PERM = NFC_PERM; + private static final String NFCEE_ADMIN_PERM = "com.android.nfc.permission.NFCEE_ADMIN"; private static final String NFCEE_ADMIN_PERM_ERROR = "NFCEE_ADMIN permission required"; private static final String PREF = "NfcServicePrefs"; @@ -156,6 +154,8 @@ public class NfcService extends Application { private static final String PREF_NFC_ON = "nfc_on"; private static final boolean NFC_ON_DEFAULT = true; + private static final String PREF_FIRST_BOOT = "first_boot"; + private static final String PREF_LLCP_LTO = "llcp_lto"; private static final int LLCP_LTO_DEFAULT = 150; private static final int LLCP_LTO_MAX = 255; @@ -256,6 +256,7 @@ public class NfcService extends Application { private final HashMap mObjectMap = new HashMap(); private final HashMap mSocketMap = new HashMap(); private boolean mScreenOn; + private String mSePackageName; // fields below are final after onCreate() Context mContext; @@ -270,8 +271,6 @@ public class NfcService extends Application { private static NfcService sService; - private HashMap mTearDownApdus = new HashMap(); - public static void enforceAdminPerm(Context context) { int admin = context.checkCallingOrSelfPermission(ADMIN_PERM); int nfcee = context.checkCallingOrSelfPermission(NFCEE_ADMIN_PERM); @@ -320,8 +319,6 @@ public class NfcService extends Application { mIActivityManager = ActivityManagerNative.getDefault(); - readTearDownApdus(); - ServiceManager.addService(SERVICE_NAME, mNfcAdapter); IntentFilter filter = new IntentFilter(NativeNfcManager.INTERNAL_TARGET_DESELECTED_ACTION); @@ -343,6 +340,7 @@ public class NfcService extends Application { if (nfc_on) { _enable(false); } + resetSeOnFirstBoot(); } }; t.start(); @@ -1912,19 +1910,15 @@ public class NfcService extends Application { @Override public void registerTearDownApdus(String packageName, ApduList apdu) throws RemoteException { NfcService.enforceNfceeAdminPerm(mContext); - synchronized(NfcService.this) { - mTearDownApdus.put(packageName, apdu); - writeTearDownApdusLocked(); - } + Log.w(TAG, "NOP"); + //TODO: Remove this API } @Override public void unregisterTearDownApdus(String packageName) throws RemoteException { NfcService.enforceNfceeAdminPerm(mContext); - synchronized(NfcService.this) { - mTearDownApdus.remove(packageName); - writeTearDownApdusLocked(); - } + Log.w(TAG, "NOP"); + //TODO: Remove this API } }; @@ -2026,81 +2020,83 @@ public class NfcService extends Application { } } - private void readTearDownApdus() { - FileInputStream input = null; - - try { - input = openFileInput(TEAR_DOWN_SCRIPTS_FILE_NAME); - DataInputStream stream = new DataInputStream(input); - - int packagesSize = stream.readInt(); - - for (int i = 0 ; i < packagesSize ; i++) { - String packageName = stream.readUTF(); - ApduList apdu = new ApduList(); - - int commandsSize = stream.readInt(); - - for (int j = 0 ; j < commandsSize ; j++) { - int length = stream.readInt(); + //TODO: dont hardcode this + private static final byte[][] SE_RESET_APDUS = { + {(byte)0x00, (byte)0xa4, (byte)0x04, (byte)0x00, (byte)0x00}, + {(byte)0x00, (byte)0xa4, (byte)0x04, (byte)0x00, (byte)0x07, (byte)0xa0, (byte)0x00, (byte)0x00, (byte)0x04, (byte)0x76, (byte)0x20, (byte)0x10, (byte)0x00}, + {(byte)0x80, (byte)0xe2, (byte)0x01, (byte)0x03, (byte)0x00}, + {(byte)0x00, (byte)0xa4, (byte)0x04, (byte)0x00, (byte)0x00}, + {(byte)0x00, (byte)0xa4, (byte)0x04, (byte)0x00, (byte)0x07, (byte)0xa0, (byte)0x00, (byte)0x00, (byte)0x04, (byte)0x76, (byte)0x30, (byte)0x30, (byte)0x00}, + {(byte)0x80, (byte)0xb4, (byte)0x00, (byte)0x00, (byte)0x00}, + {(byte)0x00, (byte)0xa4, (byte)0x04, (byte)0x00, (byte)0x00}, + }; - byte[] cmd = new byte[length]; + private void resetSeOnFirstBoot() { + if (mPrefs.getBoolean(PREF_FIRST_BOOT, true)) { + Log.i(TAG, "First Boot"); + executeSeReset(); + mPrefsEditor.putBoolean(PREF_FIRST_BOOT, false); + mPrefsEditor.apply(); + } + } - stream.read(cmd); - apdu.add(cmd); - } + private synchronized void executeSeReset() { + // TODO: read SE reset list from /system/etc + //List apdus = readSeResetApdus(); + byte[][]apdus = SE_RESET_APDUS; + if (apdus == null) { + return; + } + Log.i(TAG, "Executing SE Reset Script"); + int handle = mSecureElement.doOpenSecureElementConnection(); + if (handle == 0) { + Log.e(TAG, "Could not open the secure element!"); + return; + } - mTearDownApdus.put(packageName, apdu); - } - } catch (FileNotFoundException e) { - // Ignore. - } catch (IOException e) { - Log.e(TAG, "Could not read tear down scripts file: ", e); - deleteFile(TEAR_DOWN_SCRIPTS_FILE_NAME); - } finally { - try { - if (input != null) { - input.close(); - } - } catch (IOException e) { - // Ignore - } + for (byte[] cmd : apdus) { + mSecureElement.doTransceive(handle, cmd); } + + mSecureElement.doDisconnect(handle); } - private void writeTearDownApdusLocked() { - FileOutputStream output = null; - DataOutputStream stream = null; + private List readSeResetApdus() { + FileInputStream input = null; + List apdus = null; try { - output = openFileOutput(TEAR_DOWN_SCRIPTS_FILE_NAME, Context.MODE_PRIVATE); - stream = new DataOutputStream(output); + input = openFileInput(SE_RESET_SCRIPT_FILE_NAME); + DataInputStream stream = new DataInputStream(input); - stream.writeInt(mTearDownApdus.size()); + int commandsSize = stream.readInt(); + apdus = new ArrayList(commandsSize); - for (String packageName : mTearDownApdus.keySet()) { - stream.writeUTF(packageName); + for (int i = 0 ; i < commandsSize ; i++) { + int length = stream.readInt(); - List commands = mTearDownApdus.get(packageName).get(); - stream.writeInt(commands.size()); + byte[] cmd = new byte[length]; - for (byte[] cmd : commands) { - stream.writeInt(cmd.length); - stream.write(cmd, 0, cmd.length); - } + stream.read(cmd); + apdus.add(cmd); } + return apdus; + } catch (FileNotFoundException e) { + Log.e(TAG, "SE Reset Script not found: " + SE_RESET_SCRIPT_FILE_NAME); } catch (IOException e) { + Log.e(TAG, "SE Reset Script corrupt: ", e); + apdus = null; } finally { try { - if (output != null) { - stream.flush(); - stream.close(); + if (input != null) { + input.close(); } } catch (IOException e) { // Ignore } } + return apdus; } private void applyProperties() { @@ -2898,51 +2894,18 @@ public class NfcService extends Application { // be safe on the main thread, and the NFC stack should not wedge. new EnableDisableDiscoveryTask().execute(new Boolean(false)); } else if (intent.getAction().equals(ACTION_MASTER_CLEAR_NOTIFICATION)) { - int handle = mSecureElement.doOpenSecureElementConnection(); - if (handle == 0) { - Log.e(TAG, "Could not open the secure element!"); - return; - } - - synchronized (NfcService.this) { - for (String packageName : mTearDownApdus.keySet()) { - for (byte[] cmd : mTearDownApdus.get(packageName).get()) { - mSecureElement.doTransceive(handle, cmd); - } - } - } - - mSecureElement.doDisconnect(handle); + executeSeReset(); } else if (intent.getAction().equals(Intent.ACTION_PACKAGE_REMOVED)) { boolean dataRemoved = intent.getBooleanExtra(Intent.EXTRA_DATA_REMOVED, false); if (dataRemoved) { Uri data = intent.getData(); if (data == null) return; String packageName = data.getSchemeSpecificPart(); - ApduList apdus = null; synchronized (NfcService.this) { - apdus = mTearDownApdus.remove(packageName); - if (apdus == null) { - return; - } - - - writeTearDownApdusLocked(); - } - - int handle = mSecureElement.doOpenSecureElementConnection(); - if (handle == 0) { - Log.e(TAG, "Could not open the secure element!"); - return; - } - - try { - for (byte[] cmd : apdus.get()) { - mSecureElement.doTransceive(handle, cmd); + if (packageName.equals(mSePackageName)) { + executeSeReset(); } - } finally { - mSecureElement.doDisconnect(handle); } } } -- cgit v1.1 From 5223d6aafa38c8dbbe684f1f8611ee0f46e7ef02 Mon Sep 17 00:00:00 2001 From: Jeff Hamilton Date: Wed, 25 May 2011 15:46:38 -0500 Subject: Fix a bug with absolute URI processing. Change-Id: Ic9dc3f981e6abe52d7732eab35d6cc2c535a2dad --- src/com/android/nfc/NfcService.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/com/android/nfc/NfcService.java b/src/com/android/nfc/NfcService.java index 7ab701b..d0fabb1 100755 --- a/src/com/android/nfc/NfcService.java +++ b/src/com/android/nfc/NfcService.java @@ -2593,7 +2593,7 @@ public class NfcService extends Application { } case NdefRecord.TNF_ABSOLUTE_URI: { - intent.setData(Uri.parse(new String(record.getPayload(), Charsets.UTF_8))); + intent.setData(Uri.parse(new String(type, Charsets.UTF_8))); return true; } @@ -2615,7 +2615,7 @@ public class NfcService extends Application { intent.setData(parseWellKnownUriRecord(subRecord)); return true; } else if (subTnf == NdefRecord.TNF_ABSOLUTE_URI) { - intent.setData(Uri.parse(new String(subRecord.getPayload(), + intent.setData(Uri.parse(new String(subRecord.getType(), Charsets.UTF_8))); return true; } -- cgit v1.1 From aa122139d77645149c09c9815fd45e7b87ce7170 Mon Sep 17 00:00:00 2001 From: Nick Pelly Date: Tue, 31 May 2011 15:09:34 -0700 Subject: Make sure NFC stack is initialized before attempting SE reset. This fixes a regression at about GRJ46 where phones that had NFC turned off would fail to perform SE reset on first boot of GRJ46 and later. This would prevent NFC from being turned on, and caused NFC service to eat battery. Change-Id: I4714f06e8a3c92a5974851dd1be90b797e3058ac Bug: 4504474 --- src/com/android/nfc/NfcService.java | 74 ++++++++++++++++++++++++------------- 1 file changed, 49 insertions(+), 25 deletions(-) diff --git a/src/com/android/nfc/NfcService.java b/src/com/android/nfc/NfcService.java index 25937a2..fe88b46 100755 --- a/src/com/android/nfc/NfcService.java +++ b/src/com/android/nfc/NfcService.java @@ -378,32 +378,8 @@ public class NfcService extends Application { if (DBG) Log.d(TAG, "Disabling NFC. previous=" + previouslyEnabled); if (previouslyEnabled) { - /* tear down the my tag server */ - mNdefPushServer.stop(); - - // Stop watchdog if tag present - // A convenient way to stop the watchdog properly consists of - // disconnecting the tag. The polling loop shall be stopped before - // to avoid the tag being discovered again. - mIsDiscoveryOn = false; - applyRouting(); - maybeDisconnectTarget(); - - isSuccess = mManager.deinitialize(); - if (DBG) Log.d(TAG, "NFC success of deinitialize = " + isSuccess); - if (isSuccess) { - mIsNfcEnabled = false; - // Clear out any old dispatch overrides and NDEF push message - synchronized (this) { - mDispatchOverrideFilters = null; - mDispatchOverrideIntent = null; - } - mNdefPushClient.setForegroundMessage(null); - } + isSuccess = _disable(previouslyEnabled); } - - updateNfcOnSetting(previouslyEnabled); - return isSuccess; } @@ -1957,6 +1933,7 @@ public class NfcService extends Application { mNdefPushServer.start(); } else { + Log.w(TAG, "Error enabling NFC"); mIsNfcEnabled = false; } @@ -1965,6 +1942,37 @@ public class NfcService extends Application { return isSuccess; } + private boolean _disable(boolean oldEnabledState) { + boolean isSuccess; + + /* tear down the my tag server */ + mNdefPushServer.stop(); + + // Stop watchdog if tag present + // A convenient way to stop the watchdog properly consists of + // disconnecting the tag. The polling loop shall be stopped before + // to avoid the tag being discovered again. + mIsDiscoveryOn = false; + applyRouting(); + maybeDisconnectTarget(); + + isSuccess = mManager.deinitialize(); + if (DBG) Log.d(TAG, "NFC success of deinitialize = " + isSuccess); + if (isSuccess) { + mIsNfcEnabled = false; + // Clear out any old dispatch overrides and NDEF push message + synchronized (this) { + mDispatchOverrideFilters = null; + mDispatchOverrideIntent = null; + } + mNdefPushClient.setForegroundMessage(null); + } + + updateNfcOnSetting(oldEnabledState); + + return isSuccess; + } + /** apply NFC discovery and EE routing */ private synchronized void applyRouting() { if (mIsNfcEnabled && mOpenEe == null) { @@ -2047,10 +2055,22 @@ public class NfcService extends Application { if (apdus == null) { return; } + + boolean tempEnable = !mIsNfcEnabled; + if (tempEnable) { + if (!_enable(false)) { + Log.w(TAG, "Could not enable NFC to reset EE!"); + return; + } + } + Log.i(TAG, "Executing SE Reset Script"); int handle = mSecureElement.doOpenSecureElementConnection(); if (handle == 0) { Log.e(TAG, "Could not open the secure element!"); + if (tempEnable) { + _disable(true); + } return; } @@ -2059,6 +2079,10 @@ public class NfcService extends Application { } mSecureElement.doDisconnect(handle); + + if (tempEnable) { + _disable(true); + } } private List readSeResetApdus() { -- cgit v1.1 From c93ab99496ed7c1d8b23aac53db5202bccb6c38f Mon Sep 17 00:00:00 2001 From: daniel_tomas Date: Thu, 17 Feb 2011 12:38:36 -0800 Subject: Patch to add a recovery mechanism in case of a download failure Change-Id: Id5e1443fefa3a79d6a9da1ff79d1ddde6dada5f2 --- jni/com_android_nfc_NativeNfcManager.cpp | 103 +++++++++++++++++++++---------- 1 file changed, 70 insertions(+), 33 deletions(-) diff --git a/jni/com_android_nfc_NativeNfcManager.cpp b/jni/com_android_nfc_NativeNfcManager.cpp index d0bd3b7..8df3a19 100644 --- a/jni/com_android_nfc_NativeNfcManager.cpp +++ b/jni/com_android_nfc_NativeNfcManager.cpp @@ -205,12 +205,13 @@ static void nfc_jni_deinit_download_callback(void *pContext, NFCSTATUS status) sem_post(&pCallbackData->sem); } -static int nfc_jni_download(struct nfc_jni_native_data *nat) +static int nfc_jni_download(struct nfc_jni_native_data *nat, uint8_t update) { uint8_t OutputBuffer[1]; uint8_t InputBuffer[1]; struct timespec ts; NFCSTATUS status; + phLibNfc_StackCapabilities_t caps; struct nfc_jni_callback_data cb_data; /* Create the local semaphore */ @@ -219,33 +220,33 @@ static int nfc_jni_download(struct nfc_jni_native_data *nat) goto clean_and_return; } - //deinit - TRACE("phLibNfc_Mgt_DeInitialize() (download)"); - REENTRANCE_LOCK(); - status = phLibNfc_Mgt_DeInitialize(gHWRef, nfc_jni_deinit_download_callback, (void *)&cb_data); - REENTRANCE_UNLOCK(); - if (status != NFCSTATUS_PENDING) + if(update) { - LOGE("phLibNfc_Mgt_DeInitialize() (download) returned 0x%04x[%s]", status, nfc_jni_get_status_name(status)); - goto reinit; - } + //deinit + TRACE("phLibNfc_Mgt_DeInitialize() (download)"); + REENTRANCE_LOCK(); + status = phLibNfc_Mgt_DeInitialize(gHWRef, nfc_jni_deinit_download_callback, (void *)&cb_data); + REENTRANCE_UNLOCK(); + if (status != NFCSTATUS_PENDING) + { + LOGE("phLibNfc_Mgt_DeInitialize() (download) returned 0x%04x[%s]", status, nfc_jni_get_status_name(status)); + } - clock_gettime(CLOCK_REALTIME, &ts); - ts.tv_sec += 5; + clock_gettime(CLOCK_REALTIME, &ts); + ts.tv_sec += 5; - /* Wait for callback response */ - if(sem_timedwait(&cb_data.sem, &ts)) - { - LOGW("Deinitialization timed out (download)"); - goto reinit; - } + /* Wait for callback response */ + if(sem_timedwait(&cb_data.sem, &ts)) + { + LOGW("Deinitialization timed out (download)"); + } - if(cb_data.status != NFCSTATUS_SUCCESS) - { - LOGW("Deinitialization FAILED (download)"); - goto reinit; + if(cb_data.status != NFCSTATUS_SUCCESS) + { + LOGW("Deinitialization FAILED (download)"); + } + TRACE("Deinitialization SUCCESS (download)"); } - TRACE("Deinitialization SUCCESS (download)"); TRACE("Go in Download Mode"); phLibNfc_Download_Mode(); @@ -263,7 +264,8 @@ static int nfc_jni_download(struct nfc_jni_native_data *nat) if(status != NFCSTATUS_PENDING) { LOGE("phLibNfc_Mgt_IoCtl() (download) returned 0x%04x[%s]", status, nfc_jni_get_status_name(status)); - goto reinit; + status = NFCSTATUS_FAILED; + goto clean_and_return; } TRACE("phLibNfc_Mgt_IoCtl() (download) returned 0x%04x[%s]", status, nfc_jni_get_status_name(status)); @@ -275,6 +277,13 @@ static int nfc_jni_download(struct nfc_jni_native_data *nat) goto clean_and_return; } + /* Download Status */ + if(cb_data.status != NFCSTATUS_SUCCESS) + { + status = cb_data.status; + goto clean_and_return; + } + reinit: TRACE("phLibNfc_HW_Reset()"); phLibNfc_HW_Reset(); @@ -304,6 +313,26 @@ reinit: goto clean_and_return; } + /* ====== CAPABILITIES ======= */ + REENTRANCE_LOCK(); + status = phLibNfc_Mgt_GetstackCapabilities(&caps, (void*)nat); + REENTRANCE_UNLOCK(); + if (status != NFCSTATUS_SUCCESS) + { + LOGW("phLibNfc_Mgt_GetstackCapabilities returned 0x%04x[%s]", status, nfc_jni_get_status_name(status)); + } + else + { + LOGD("NFC capabilities: HAL = %x, FW = %x, HW = %x, Model = %x, HCI = %x, Full_FW = %d, FW Update Info = %d", + caps.psDevCapabilities.hal_version, + caps.psDevCapabilities.fw_version, + caps.psDevCapabilities.hw_version, + caps.psDevCapabilities.model_id, + caps.psDevCapabilities.hci_version, + caps.psDevCapabilities.full_version[NXP_FULL_VERSION_LEN-1], + caps.psDevCapabilities.firmware_update_info); + } + /*Download is successful*/ status = NFCSTATUS_SUCCESS; @@ -325,6 +354,7 @@ static int nfc_jni_initialize(struct nfc_jni_native_data *nat) { phLibNfc_Llcp_sLinkParameters_t LlcpConfigInfo; struct nfc_jni_callback_data cb_data; uint8_t firmware_status; + uint8_t update = TRUE; LOGD("Start Initialization\n"); @@ -375,7 +405,8 @@ static int nfc_jni_initialize(struct nfc_jni_native_data *nat) { if(status != NFCSTATUS_PENDING) { LOGE("phLibNfc_Mgt_Initialize() returned 0x%04x[%s]", status, nfc_jni_get_status_name(status)); - goto clean_and_return; + update = FALSE; + goto force_download; } TRACE("phLibNfc_Mgt_Initialize returned 0x%04x[%s]", status, nfc_jni_get_status_name(status)); @@ -389,10 +420,10 @@ static int nfc_jni_initialize(struct nfc_jni_native_data *nat) { /* Initialization Status */ if(cb_data.status != NFCSTATUS_SUCCESS) { - goto clean_and_return; + update = FALSE; + goto force_download; } - /* ====== CAPABILITIES ======= */ REENTRANCE_LOCK(); @@ -418,15 +449,21 @@ static int nfc_jni_initialize(struct nfc_jni_native_data *nat) { /* ====== FIRMWARE VERSION ======= */ if(caps.psDevCapabilities.firmware_update_info) { - TRACE("Firmware version not UpToDate"); - status = nfc_jni_download(nat); - if(status == NFCSTATUS_SUCCESS) +force_download: + for (i=0; i<3; i++) { - TRACE("Firmware update SUCCESS"); + TRACE("Firmware version not UpToDate"); + status = nfc_jni_download(nat, update); + if(status == NFCSTATUS_SUCCESS) + { + LOGI("Firmware update SUCCESS"); + break; + } + LOGW("Firmware update FAILED"); } - else + if(i>=3) { - TRACE("Firmware update FAILED"); + LOGE("Unable to update firmware, giving up"); goto clean_and_return; } } -- cgit v1.1 From dfac80d25dd2816ad5af74cc4131b74134cc81b7 Mon Sep 17 00:00:00 2001 From: Nick Pelly Date: Wed, 1 Jun 2011 17:30:35 -0700 Subject: Fix regression in NFC-EE close() cleanup path for dead applications. The regression occured when we switched to certificate based checking for NFC-EE access control (this switch was only fully completed a few days ago). Change-Id: I43d7adfad020446af8e863e876c59caf3b852920 --- src/com/android/nfc/NfcService.java | 54 ++++++++++++++++++------------------- 1 file changed, 27 insertions(+), 27 deletions(-) diff --git a/src/com/android/nfc/NfcService.java b/src/com/android/nfc/NfcService.java index fe88b46..244a3bf 100755 --- a/src/com/android/nfc/NfcService.java +++ b/src/com/android/nfc/NfcService.java @@ -1749,6 +1749,30 @@ public class NfcService extends Application { } }; + private void _nfcEeClose(boolean checkPid, int callingPid) throws IOException { + // Blocks until a pending open() or transceive() times out. + //TODO: This is incorrect behavior - the close should interrupt pending + // operations. However this is not supported by current hardware. + + synchronized(NfcService.this) { + if (!mIsNfcEnabled) { + throw new IOException("NFC adapter is disabled"); + } + if (mOpenEe == null) { + throw new IOException("NFC EE closed"); + } + if (checkPid && mOpenEe.pid != -1 && callingPid != mOpenEe.pid) { + throw new SecurityException("Wrong PID"); + } + + mManager.doResetIsoDepTimeout(); + mSecureElement.doDisconnect(mOpenEe.handle); + mOpenEe = null; + + applyRouting(); + } + } + private INfcAdapterExtras mExtrasService = new INfcAdapterExtras.Stub() { private Bundle writeNoException() { Bundle p = new Bundle(); @@ -1806,7 +1830,7 @@ public class NfcService extends Application { Bundle result; try { - _close(); + _nfcEeClose(true, getCallingPid()); result = writeNoException(); } catch (IOException e) { result = writeIoException(e); @@ -1814,30 +1838,6 @@ public class NfcService extends Application { return result; } - void _close() throws IOException, RemoteException { - // Blocks until a pending open() or transceive() times out. - //TODO: This is incorrect behavior - the close should interrupt pending - // operations. However this is not supported by current hardware. - - synchronized(NfcService.this) { - if (!mIsNfcEnabled) { - throw new IOException("NFC adapter is disabled"); - } - if (mOpenEe == null) { - throw new IOException("NFC EE closed"); - } - if (mOpenEe.pid != -1 && getCallingPid() != mOpenEe.pid) { - throw new SecurityException("Wrong PID"); - } - - mManager.doResetIsoDepTimeout(); - mSecureElement.doDisconnect(mOpenEe.handle); - mOpenEe = null; - - applyRouting(); - } - } - @Override public Bundle transceive(byte[] in) throws RemoteException { NfcService.enforceNfceeAdminPerm(mContext); @@ -1912,8 +1912,8 @@ public class NfcService extends Application { if (DBG) Log.d(TAG, "Tracked app " + pid + " died"); pid = -1; try { - mExtrasService.close(); - } catch (RemoteException e) { /* local call never fails */ } + _nfcEeClose(false, -1); + } catch (IOException e) { /* already closed */ } } } } -- cgit v1.1 From 2edb3ee5e28ab719a3bb17b8d76b2b588405be9a Mon Sep 17 00:00:00 2001 From: Nick Pelly Date: Sun, 12 Jun 2011 21:36:46 -0700 Subject: Fix NFC service wake-lock, again. 1) Put a watchdog on the NFC Service disable path. All the bug-reports show we were stuck in _disable(), watch-dog this path (10 seconds). 2) Only attempt a SE reset once, even if it fails the first time. All the bugs reports should the _disable() was due to SE reset on first boot. 3) Grab the NFC service lock before the wake-lock. So even if someone has NFC service lock, at least we don't hold a wake-lock waiting for it. Bug: 4581084 Change-Id: Ic9829dddde8d0c67cf0e8e4912357fa2902faa11 --- jni/com_android_nfc_NativeNfcManager.cpp | 9 ++++++++ src/com/android/nfc/NativeNfcManager.java | 1 + src/com/android/nfc/NfcService.java | 35 ++++++++++++++++++++++++++++--- 3 files changed, 42 insertions(+), 3 deletions(-) diff --git a/jni/com_android_nfc_NativeNfcManager.cpp b/jni/com_android_nfc_NativeNfcManager.cpp index 8df3a19..cba4691 100644 --- a/jni/com_android_nfc_NativeNfcManager.cpp +++ b/jni/com_android_nfc_NativeNfcManager.cpp @@ -2378,6 +2378,12 @@ static void com_android_nfc_NfcManager_doSetProperties(JNIEnv *e, jobject o, jin } + +static void com_android_nfc_NfcManager_doAbort(JNIEnv *e, jobject o) +{ + emergency_recovery(NULL); +} + /* * JNI registration. */ @@ -2433,6 +2439,9 @@ static JNINativeMethod gMethods[] = {"doResetIsoDepTimeout", "()V", (void *)com_android_nfc_NfcManager_doResetIsoDepTimeout}, + + {"doAbort", "()V", + (void *)com_android_nfc_NfcManager_doAbort}, }; diff --git a/src/com/android/nfc/NativeNfcManager.java b/src/com/android/nfc/NativeNfcManager.java index 7e4db32..3f0f532 100755 --- a/src/com/android/nfc/NativeNfcManager.java +++ b/src/com/android/nfc/NativeNfcManager.java @@ -92,6 +92,7 @@ public class NativeNfcManager { public native boolean doActivateLlcp(); + public native void doAbort(); public native void doResetIsoDepTimeout(); public void resetIsoDepTimeout() { diff --git a/src/com/android/nfc/NfcService.java b/src/com/android/nfc/NfcService.java index 244a3bf..667565b 100755 --- a/src/com/android/nfc/NfcService.java +++ b/src/com/android/nfc/NfcService.java @@ -1943,6 +1943,10 @@ public class NfcService extends Application { } private boolean _disable(boolean oldEnabledState) { + /* sometimes mManager.deinitialize() hangs, watch-dog it */ + WatchDogThread watchDog = new WatchDogThread(); + watchDog.start(); + boolean isSuccess; /* tear down the my tag server */ @@ -1970,9 +1974,34 @@ public class NfcService extends Application { updateNfcOnSetting(oldEnabledState); + watchDog.cancel(); return isSuccess; } + private class WatchDogThread extends Thread { + boolean mWatchDogCanceled = false; + @Override + public void run() { + boolean slept = false; + while (!slept) { + try { + Thread.sleep(10000); + slept = true; + } catch (InterruptedException e) { } + } + synchronized (this) { + if (!mWatchDogCanceled) { + // Trigger watch-dog + Log.e(TAG, "Watch dog triggered"); + mManager.doAbort(); + } + } + } + public synchronized void cancel() { + mWatchDogCanceled = true; + } + } + /** apply NFC discovery and EE routing */ private synchronized void applyRouting() { if (mIsNfcEnabled && mOpenEe == null) { @@ -2042,9 +2071,9 @@ public class NfcService extends Application { private void resetSeOnFirstBoot() { if (mPrefs.getBoolean(PREF_FIRST_BOOT, true)) { Log.i(TAG, "First Boot"); - executeSeReset(); mPrefsEditor.putBoolean(PREF_FIRST_BOOT, false); mPrefsEditor.apply(); + executeSeReset(); } } @@ -2891,13 +2920,13 @@ public class NfcService extends Application { applyRouting(); } } else { - mWakeLock.acquire(); synchronized (NfcService.this) { + mWakeLock.acquire(); mScreenOn = false; applyRouting(); maybeDisconnectTarget(); + mWakeLock.release(); } - mWakeLock.release(); } return null; } -- cgit v1.1 From 95b352ec03226adf812d63e6fee568b1a4581021 Mon Sep 17 00:00:00 2001 From: Daniel Tomas Date: Thu, 16 Jun 2011 16:16:10 -0700 Subject: Set the transceive timeout to 10s when executeSeReset() is called Change-Id: Id89207194a87e918aee2493c8c0fa93a97a1ff4a --- src/com/android/nfc/NfcService.java | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/com/android/nfc/NfcService.java b/src/com/android/nfc/NfcService.java index 667565b..0095761 100755 --- a/src/com/android/nfc/NfcService.java +++ b/src/com/android/nfc/NfcService.java @@ -2103,10 +2103,14 @@ public class NfcService extends Application { return; } + mManager.doSetIsoDepTimeout(10000); + for (byte[] cmd : apdus) { mSecureElement.doTransceive(handle, cmd); } + mManager.doResetIsoDepTimeout(); + mSecureElement.doDisconnect(handle); if (tempEnable) { -- cgit v1.1 From e4d9ddebb676325c6abfe3b0d4c0aefa8a17d952 Mon Sep 17 00:00:00 2001 From: Nick Pelly Date: Tue, 28 Jun 2011 18:11:07 -0700 Subject: Do not change NFC on/off preference while executing SE reset. Bug: 4967769 Change-Id: I7a72cbe831d4b3f44bed7feeea8abaf468cdc19b Signed-off-by: Nick Pelly --- src/com/android/nfc/NfcService.java | 24 ++++++++++++++---------- 1 file changed, 14 insertions(+), 10 deletions(-) diff --git a/src/com/android/nfc/NfcService.java b/src/com/android/nfc/NfcService.java index 0095761..283d72d 100755 --- a/src/com/android/nfc/NfcService.java +++ b/src/com/android/nfc/NfcService.java @@ -338,7 +338,7 @@ public class NfcService extends Application { public void run() { boolean nfc_on = mPrefs.getBoolean(PREF_NFC_ON, NFC_ON_DEFAULT); if (nfc_on) { - _enable(false); + _enable(false, true); } resetSeOnFirstBoot(); } @@ -365,7 +365,7 @@ public class NfcService extends Application { boolean previouslyEnabled = isEnabled(); if (!previouslyEnabled) { reset(); - isSuccess = _enable(previouslyEnabled); + isSuccess = _enable(previouslyEnabled, true); } return isSuccess; } @@ -378,7 +378,7 @@ public class NfcService extends Application { if (DBG) Log.d(TAG, "Disabling NFC. previous=" + previouslyEnabled); if (previouslyEnabled) { - isSuccess = _disable(previouslyEnabled); + isSuccess = _disable(previouslyEnabled, true); } return isSuccess; } @@ -1918,7 +1918,7 @@ public class NfcService extends Application { } } - private boolean _enable(boolean oldEnabledState) { + private boolean _enable(boolean oldEnabledState, boolean savePref) { applyProperties(); boolean isSuccess = mManager.initialize(); @@ -1937,12 +1937,14 @@ public class NfcService extends Application { mIsNfcEnabled = false; } - updateNfcOnSetting(oldEnabledState); + if (savePref) { + updateNfcOnSetting(oldEnabledState); + } return isSuccess; } - private boolean _disable(boolean oldEnabledState) { + private boolean _disable(boolean oldEnabledState, boolean savePref) { /* sometimes mManager.deinitialize() hangs, watch-dog it */ WatchDogThread watchDog = new WatchDogThread(); watchDog.start(); @@ -1972,7 +1974,9 @@ public class NfcService extends Application { mNdefPushClient.setForegroundMessage(null); } - updateNfcOnSetting(oldEnabledState); + if (savePref) { + updateNfcOnSetting(oldEnabledState); + } watchDog.cancel(); return isSuccess; @@ -2087,7 +2091,7 @@ public class NfcService extends Application { boolean tempEnable = !mIsNfcEnabled; if (tempEnable) { - if (!_enable(false)) { + if (!_enable(false, false)) { Log.w(TAG, "Could not enable NFC to reset EE!"); return; } @@ -2098,7 +2102,7 @@ public class NfcService extends Application { if (handle == 0) { Log.e(TAG, "Could not open the secure element!"); if (tempEnable) { - _disable(true); + _disable(true, false); } return; } @@ -2114,7 +2118,7 @@ public class NfcService extends Application { mSecureElement.doDisconnect(handle); if (tempEnable) { - _disable(true); + _disable(true, false); } } -- cgit v1.1