Return more accurate errors for NfcEe.open.
There are a number of different conditions under
which access to the SE is not possible. Since some
of these require user intervention to resolve (ie
external field present), return a more accurate
reason for NfcEe.open failure.
Bug: 4304698
Change-Id: Ie947c29be12d554a02d9246264a9f0e026a37af8
diff --git a/nci/jni/NativeSecureElement.cpp b/nci/jni/NativeSecureElement.cpp
index d1438bc..fea2e15 100755
--- a/nci/jni/NativeSecureElement.cpp
+++ b/nci/jni/NativeSecureElement.cpp
@@ -27,6 +27,13 @@
extern void com_android_nfc_NfcManager_enableDiscovery (JNIEnv* e, jobject o, jint mode);
extern int gGeneralTransceiveTimeout;
+// These must match the EE_ERROR_ types in NfcService.java
+static const int EE_ERROR_IO = -1;
+static const int EE_ERROR_ALREADY_OPEN = -2;
+static const int EE_ERROR_INIT = -3;
+static const int EE_ERROR_LISTEN_MODE = -4;
+static const int EE_ERROR_EXT_FIELD = -5;
+static const int EE_ERROR_NFC_DISABLED = -6;
/*******************************************************************************
**
@@ -36,23 +43,25 @@
** e: JVM environment.
** o: Java object.
**
-** Returns: Handle of secure element. 0 is failure.
+** Returns: Handle of secure element. values < 0 represent failure.
**
*******************************************************************************/
static jint nativeNfcSecureElement_doOpenSecureElementConnection (JNIEnv*, jobject)
{
ALOGD("%s: enter", __FUNCTION__);
bool stat = true;
- jint secElemHandle = 0;
+ jint secElemHandle = EE_ERROR_INIT;
SecureElement &se = SecureElement::getInstance();
if (se.isActivatedInListenMode()) {
ALOGD("Denying SE open due to SE listen mode active");
+ secElemHandle = EE_ERROR_LISTEN_MODE;
goto TheEnd;
}
if (se.isRfFieldOn()) {
ALOGD("Denying SE open due to SE in active RF field");
+ secElemHandle = EE_ERROR_EXT_FIELD;
goto TheEnd;
}
//tell the controller to power up to get ready for sec elem operations
@@ -69,9 +78,13 @@
//establish a pipe to sec elem
stat = se.connectEE();
if (stat)
+ {
secElemHandle = se.mActiveEeHandle;
+ }
else
+ {
se.deactivate (0);
+ }
}
//if code fails to connect to the secure element, and nothing is active, then
diff --git a/nxp/jni/com_android_nfc.h b/nxp/jni/com_android_nfc.h
index 56c229f..1eed204 100644
--- a/nxp/jni/com_android_nfc.h
+++ b/nxp/jni/com_android_nfc.h
@@ -105,6 +105,15 @@
#define SMX_SECURE_ELEMENT_ID 11259375
+
+/* These must match the EE_ERROR_ types in NfcService.java */
+#define EE_ERROR_IO -1
+#define EE_ERROR_ALREADY_OPEN -2
+#define EE_ERROR_INIT -3
+#define EE_ERROR_LISTEN_MODE -4
+#define EE_ERROR_EXT_FIELD -5
+#define EE_ERROR_NFC_DISABLED -6
+
/* Maximum byte length of an AID. */
#define AID_MAXLEN 16
diff --git a/nxp/jni/com_android_nfc_NativeNfcSecureElement.cpp b/nxp/jni/com_android_nfc_NativeNfcSecureElement.cpp
index 79887a0..9e0a6e2 100755
--- a/nxp/jni/com_android_nfc_NativeNfcSecureElement.cpp
+++ b/nxp/jni/com_android_nfc_NativeNfcSecureElement.cpp
@@ -179,6 +179,7 @@
{
NFCSTATUS ret;
int semResult;
+ jint errorCode = EE_ERROR_INIT;
phLibNfc_SE_List_t SE_List[PHLIBNFC_MAXNO_OF_SE];
uint8_t i, No_SE = PHLIBNFC_MAXNO_OF_SE, SmartMX_index=0, SmartMX_detected = 0;
@@ -224,7 +225,8 @@
/* Check if NFC device is already connected to a tag or P2P peer */
if (device_connected_flag == 1)
{
- ALOGD("Unable to open SE connection, device already connected to a P2P peer or a Tag");
+ ALOGE("Unable to open SE connection, device already connected to a P2P peer or a Tag");
+ errorCode = EE_ERROR_LISTEN_MODE;
goto clean_and_return;
}
@@ -263,6 +265,7 @@
{
// There is an external RF field present, fail the open request
ALOGD("Unable to open SE connection, external RF Field detected");
+ errorCode = EE_ERROR_EXT_FIELD;
goto clean_and_return;
}
@@ -464,7 +467,7 @@
nfc_cb_data_deinit(&cb_data_SE_Notification);
CONCURRENCY_UNLOCK();
- return 0;
+ return errorCode;
}
diff --git a/src/com/android/nfc/NfcService.java b/src/com/android/nfc/NfcService.java
index 2791307..4436927 100755
--- a/src/com/android/nfc/NfcService.java
+++ b/src/com/android/nfc/NfcService.java
@@ -132,6 +132,15 @@
static final int ROUTE_OFF = 1;
static final int ROUTE_ON_WHEN_SCREEN_ON = 2;
+ // Return values from NfcEe.open() - these are 1:1 mapped
+ // to the thrown EE_EXCEPTION_ exceptions in nfc-extras.
+ static final int EE_ERROR_IO = -1;
+ static final int EE_ERROR_ALREADY_OPEN = -2;
+ static final int EE_ERROR_INIT = -3;
+ static final int EE_ERROR_LISTEN_MODE = -4;
+ static final int EE_ERROR_EXT_FIELD = -5;
+ static final int EE_ERROR_NFC_DISABLED = -6;
+
/** minimum screen state that enables NFC polling (discovery) */
static final int POLLING_MODE = SCREEN_STATE_ON_UNLOCKED;
@@ -1297,10 +1306,11 @@
p.putInt("e", 0);
return p;
}
- private Bundle writeIoException(IOException e) {
+
+ private Bundle writeEeException(int exceptionType, String message) {
Bundle p = new Bundle();
- p.putInt("e", -1);
- p.putString("m", e.getMessage());
+ p.putInt("e", exceptionType);
+ p.putString("m", message);
return p;
}
@@ -1309,27 +1319,33 @@
NfcService.this.enforceNfceeAdminPerm(pkg);
Bundle result;
- try {
- _open(b);
+ int handle = _open(b);
+ if (handle < 0) {
+ result = writeEeException(handle, "NFCEE open exception.");
+ } else {
result = writeNoException();
- } catch (IOException e) {
- result = writeIoException(e);
}
return result;
}
- private void _open(IBinder b) throws IOException {
+ /**
+ * Opens a connection to the secure element.
+ *
+ * @return A handle with a value >= 0 in case of success, or a
+ * negative value in case of failure.
+ */
+ private int _open(IBinder b) {
synchronized(NfcService.this) {
if (!isNfcEnabled()) {
- throw new IOException("NFC adapter is disabled");
+ return EE_ERROR_NFC_DISABLED;
}
if (mOpenEe != null) {
- throw new IOException("NFC EE already open");
+ return EE_ERROR_ALREADY_OPEN;
}
int handle = doOpenSecureElementConnection();
- if (handle == 0) {
- throw new IOException("NFC EE failed to open");
+ if (handle < 0) {
+ return handle;
}
mDeviceHost.setTimeout(TagTechnology.ISO_DEP, 30000);
@@ -1345,6 +1361,8 @@
for (String packageName : mContext.getPackageManager().getPackagesForUid(getCallingUid())) {
mSePackages.add(packageName);
}
+
+ return handle;
}
}
@@ -1357,7 +1375,7 @@
_nfcEeClose(getCallingPid(), binder);
result = writeNoException();
} catch (IOException e) {
- result = writeIoException(e);
+ result = writeEeException(EE_ERROR_IO, e.getMessage());
}
return result;
}
@@ -1373,7 +1391,7 @@
result = writeNoException();
result.putByteArray("out", out);
} catch (IOException e) {
- result = writeIoException(e);
+ result = writeEeException(EE_ERROR_IO, e.getMessage());
}
return result;
}