diff options
-rw-r--r-- | jni/com_android_nfc_NativeNfcTag.cpp | 63 | ||||
-rwxr-xr-x | src/com/android/nfc/NativeNfcTag.java | 53 | ||||
-rwxr-xr-x | src/com/android/nfc/NfcService.java | 54 |
3 files changed, 98 insertions, 72 deletions
diff --git a/jni/com_android_nfc_NativeNfcTag.cpp b/jni/com_android_nfc_NativeNfcTag.cpp index ade5307..e724309 100644 --- a/jni/com_android_nfc_NativeNfcTag.cpp +++ b/jni/com_android_nfc_NativeNfcTag.cpp @@ -444,13 +444,12 @@ static void set_target_activationBytes(JNIEnv *e, jobject tag, e->ReleaseIntArrayElements(techList, techId, 0); } -static jboolean com_android_nfc_NativeNfcTag_doConnect(JNIEnv *e, +static jint com_android_nfc_NativeNfcTag_doConnect(JNIEnv *e, jobject o, phLibNfc_Handle handle) { jclass cls; jfieldID f; - NFCSTATUS status; - jboolean result = JNI_FALSE; + jint status; struct nfc_jni_callback_data cb_data; phLibNfc_sRemoteDevInformation_t* pRemDevInfo = NULL; @@ -459,6 +458,7 @@ static jboolean com_android_nfc_NativeNfcTag_doConnect(JNIEnv *e, /* Create the local semaphore */ if (!nfc_cb_data_init(&cb_data, &pRemDevInfo)) { + status = NFCSTATUS_NOT_ENOUGH_MEMORY; goto clean_and_return; } @@ -478,11 +478,15 @@ static jboolean com_android_nfc_NativeNfcTag_doConnect(JNIEnv *e, if(sem_wait(&cb_data.sem)) { LOGE("Failed to wait for semaphore (errno=0x%08x)", errno); + status = NFCSTATUS_ABORTED; goto clean_and_return; } - + + status = cb_data.status; + TRACE("phLibNfc_RemoteDev_Connect() - Status code = %d", status); + /* Connect Status */ - if(cb_data.status != NFCSTATUS_SUCCESS) + if(status != NFCSTATUS_SUCCESS) { goto clean_and_return; } @@ -491,21 +495,18 @@ static jboolean com_android_nfc_NativeNfcTag_doConnect(JNIEnv *e, set_target_pollBytes(e, o, pRemDevInfo); set_target_activationBytes(e, o, pRemDevInfo); - result = JNI_TRUE; - clean_and_return: nfc_cb_data_deinit(&cb_data); CONCURRENCY_UNLOCK(); - return result; + return status; } -static jboolean com_android_nfc_NativeNfcTag_doHandleReconnect(JNIEnv *e, +static jint com_android_nfc_NativeNfcTag_doHandleReconnect(JNIEnv *e, jobject o, phLibNfc_Handle handle) { jclass cls; jfieldID f; - NFCSTATUS status; - jboolean result = JNI_FALSE; + jint status; struct nfc_jni_callback_data cb_data; phLibNfc_sRemoteDevInformation_t* pRemDevInfo = NULL; CONCURRENCY_LOCK(); @@ -513,6 +514,7 @@ static jboolean com_android_nfc_NativeNfcTag_doHandleReconnect(JNIEnv *e, /* Create the local semaphore */ if (!nfc_cb_data_init(&cb_data, &pRemDevInfo)) { + status = NFCSTATUS_NOT_ENOUGH_MEMORY; goto clean_and_return; } @@ -532,24 +534,25 @@ static jboolean com_android_nfc_NativeNfcTag_doHandleReconnect(JNIEnv *e, if(sem_wait(&cb_data.sem)) { LOGE("Failed to wait for semaphore (errno=0x%08x)", errno); + status = NFCSTATUS_ABORTED; goto clean_and_return; } + status = cb_data.status; + /* Connect Status */ - if(cb_data.status != NFCSTATUS_SUCCESS) + if(status != NFCSTATUS_SUCCESS) { goto clean_and_return; } - result = JNI_TRUE; - clean_and_return: nfc_cb_data_deinit(&cb_data); CONCURRENCY_UNLOCK(); - return result; + return status; } -static jboolean com_android_nfc_NativeNfcTag_doReconnect(JNIEnv *e, +static jint com_android_nfc_NativeNfcTag_doReconnect(JNIEnv *e, jobject o) { // Reconnect is provided by libnfc by just calling connect again @@ -563,11 +566,11 @@ static jboolean com_android_nfc_NativeNfcTag_doReconnect(JNIEnv *e, return com_android_nfc_NativeNfcTag_doConnect(e, o, handle); } else { - return JNI_TRUE; + return NFCSTATUS_SUCCESS; } } else { - return JNI_FALSE; + return NFCSTATUS_REJECTED; } } @@ -940,11 +943,10 @@ static jint com_android_nfc_NativeNfcTag_doGetNdefType(JNIEnv *e, jobject o, return ndefType; } -static bool com_android_nfc_NativeNfcTag_doCheckNdef(JNIEnv *e, jobject o, jintArray ndefinfo) +static jint com_android_nfc_NativeNfcTag_doCheckNdef(JNIEnv *e, jobject o, jintArray ndefinfo) { phLibNfc_Handle handle = 0; - NFCSTATUS status; - bool result = JNI_FALSE; + jint status; phLibNfc_ChkNdef_Info_t sNdefInfo; struct nfc_jni_callback_data cb_data; jint *ndef = e->GetIntArrayElements(ndefinfo, 0); @@ -955,6 +957,7 @@ static bool com_android_nfc_NativeNfcTag_doCheckNdef(JNIEnv *e, jobject o, jintA /* Create the local semaphore */ if (!nfc_cb_data_init(&cb_data, NULL)) { + status = NFCSTATUS_NOT_ENOUGH_MEMORY; goto clean_and_return; } cb_data.pContext = &sNdefInfo; @@ -976,16 +979,18 @@ static bool com_android_nfc_NativeNfcTag_doCheckNdef(JNIEnv *e, jobject o, jintA if(sem_wait(&cb_data.sem)) { LOGE("Failed to wait for semaphore (errno=0x%08x)", errno); + status = NFCSTATUS_ABORTED; goto clean_and_return; } - if (cb_data.status != NFCSTATUS_SUCCESS) + status = cb_data.status; + TRACE("phLibNfc_Ndef_CheckNdef() - Status code = %d", status); + + if (status != NFCSTATUS_SUCCESS) { goto clean_and_return; } - result = JNI_TRUE; - ndef[0] = sNdefInfo.MaxNdefMsgLength; // Translate the card state to know values for the NFC API switch (sNdefInfo.NdefCardState) { @@ -1008,7 +1013,7 @@ clean_and_return: e->ReleaseIntArrayElements(ndefinfo, ndef, 0); nfc_cb_data_deinit(&cb_data); CONCURRENCY_UNLOCK(); - return result; + return status; } static jboolean com_android_nfc_NativeNfcTag_doPresenceCheck(JNIEnv *e, jobject o) @@ -1221,19 +1226,19 @@ clean_and_return: */ static JNINativeMethod gMethods[] = { - {"doConnect", "(I)Z", + {"doConnect", "(I)I", (void *)com_android_nfc_NativeNfcTag_doConnect}, {"doDisconnect", "()Z", (void *)com_android_nfc_NativeNfcTag_doDisconnect}, - {"doReconnect", "()Z", + {"doReconnect", "()I", (void *)com_android_nfc_NativeNfcTag_doReconnect}, - {"doHandleReconnect", "(I)Z", + {"doHandleReconnect", "(I)I", (void *)com_android_nfc_NativeNfcTag_doHandleReconnect}, {"doTransceive", "([BZ[I)[B", (void *)com_android_nfc_NativeNfcTag_doTransceive}, {"doGetNdefType", "(II)I", (void *)com_android_nfc_NativeNfcTag_doGetNdefType}, - {"doCheckNdef", "([I)Z", + {"doCheckNdef", "([I)I", (void *)com_android_nfc_NativeNfcTag_doCheckNdef}, {"doRead", "()[B", (void *)com_android_nfc_NativeNfcTag_doRead}, diff --git a/src/com/android/nfc/NativeNfcTag.java b/src/com/android/nfc/NativeNfcTag.java index 94df1d2..1937744 100755 --- a/src/com/android/nfc/NativeNfcTag.java +++ b/src/com/android/nfc/NativeNfcTag.java @@ -43,6 +43,8 @@ public class NativeNfcTag { private int mConnectedTechnology; // Index in mTechList + private int mLastStatusCode; + private final String TAG = "NativeNfcTag"; private boolean mIsPresent; // Whether the tag is known to be still present @@ -115,12 +117,12 @@ public class NativeNfcTag { } } - private native boolean doConnect(int handle); - public synchronized boolean connect(int technology) { + private native int doConnect(int handle); + public synchronized int connect(int technology) { if (mWatchdog != null) { mWatchdog.pause(); } - boolean isSuccess = false; + int status = -1; for (int i = 0; i < mTechList.length; i++) { if (mTechList[i] == technology) { // Get the handle and connect, if not already connected @@ -139,12 +141,12 @@ public class NativeNfcTag { // allowed. if (mConnectedTechnology == -1) { // Not connected yet - isSuccess = doConnect(mTechHandles[i]); + status = doConnect(mTechHandles[i]); } else if ((mConnectedTechnology != -1) && (mTechHandles[mConnectedTechnology] != mTechHandles[i])) { // Connect to a tech with a different handle - isSuccess = reconnect(mTechHandles[i]); + status = reconnect(mTechHandles[i]); } else { // Already connected to a tech with the same handle @@ -152,24 +154,23 @@ public class NativeNfcTag { // success if ((technology == TagTechnology.NDEF) || (technology == TagTechnology.NDEF_FORMATABLE)) { - isSuccess = true; + status = 0; } else { if ((technology != TagTechnology.ISO_DEP) && (hasTechOnHandle(TagTechnology.ISO_DEP, mTechHandles[i]))) { // Don't allow to connect a -4 tag at a different level // than IsoDep, as this is not supported by // libNFC. - isSuccess = false; } else { - isSuccess = true; + status = 0; } } } - if (isSuccess) { + if (status == 0) { mConnectedTechnology = i; } } else { - isSuccess = true; // Already connect to this tech + status = 0; // Already connect to this tech } break; } @@ -177,7 +178,8 @@ public class NativeNfcTag { if (mWatchdog != null) { mWatchdog.doResume(); } - return isSuccess; + mLastStatusCode = status; + return status; } public synchronized void startPresenceChecking() { @@ -219,28 +221,28 @@ public class NativeNfcTag { return result; } - native boolean doReconnect(); - public synchronized boolean reconnect() { + native int doReconnect(); + public synchronized int reconnect() { if (mWatchdog != null) { mWatchdog.pause(); } - boolean result = doReconnect(); + int status = doReconnect(); if (mWatchdog != null) { mWatchdog.doResume(); } - return result; + return status; } - native boolean doHandleReconnect(int handle); - public synchronized boolean reconnect(int handle) { + native int doHandleReconnect(int handle); + public synchronized int reconnect(int handle) { if (mWatchdog != null) { mWatchdog.pause(); } - boolean result = doHandleReconnect(handle); + int status = doHandleReconnect(handle); if (mWatchdog != null) { mWatchdog.doResume(); } - return result; + return status; } private native byte[] doTransceive(byte[] data, boolean raw, int[] returnCode); @@ -255,16 +257,17 @@ public class NativeNfcTag { return result; } - private native boolean doCheckNdef(int[] ndefinfo); - public synchronized boolean checkNdef(int[] ndefinfo) { + private native int doCheckNdef(int[] ndefinfo); + public synchronized int checkNdef(int[] ndefinfo) { if (mWatchdog != null) { mWatchdog.pause(); } - boolean result = doCheckNdef(ndefinfo); + int status = doCheckNdef(ndefinfo); if (mWatchdog != null) { mWatchdog.doResume(); } - return result; + mLastStatusCode = status; + return status; } private native byte[] doRead(); @@ -348,6 +351,10 @@ public class NativeNfcTag { private NativeNfcTag() { } + public int getLastStatusCode() { + return mLastStatusCode; + } + public int getHandle() { // This is just a handle for the clients; it can simply use the first // technology handle we have. diff --git a/src/com/android/nfc/NfcService.java b/src/com/android/nfc/NfcService.java index 17615fb..acbfc5e 100755 --- a/src/com/android/nfc/NfcService.java +++ b/src/com/android/nfc/NfcService.java @@ -225,6 +225,8 @@ public class NfcService extends Application { static final int MSG_SE_EMV_CARD_REMOVAL = 11; static final int MSG_SE_MIFARE_ACCESS = 12; + static final int STATUS_CODE_TARGET_LOST = 146; + // Copied from com.android.nfc_extras to avoid library dependency // Must keep in sync with com.android.nfc_extras static final int ROUTE_OFF = 1; @@ -1305,7 +1307,7 @@ public class NfcService extends Application { // Note that on most tags, all technologies are behind a single // handle. This means that the connect at the lower levels // will do nothing, as the tag is already connected to that handle. - if (tag.connect(technology)) { + if (tag.connect(technology) == 0) { return ErrorCodes.SUCCESS; } else { return ErrorCodes.ERROR_DISCONNECT; @@ -1326,7 +1328,7 @@ public class NfcService extends Application { /* find the tag in the hmap */ tag = (NativeNfcTag) findObject(nativeHandle); if (tag != null) { - if (tag.reconnect()) { + if (tag.reconnect() == 0) { return ErrorCodes.SUCCESS; } else { return ErrorCodes.ERROR_DISCONNECT; @@ -1392,20 +1394,19 @@ public class NfcService extends Application { @Override public boolean isNdef(int nativeHandle) throws RemoteException { NativeNfcTag tag = null; - boolean isSuccess = false; // Check if NFC is enabled if (!mIsNfcEnabled) { - return isSuccess; + return false; } /* find the tag in the hmap */ tag = (NativeNfcTag) findObject(nativeHandle); int[] ndefInfo = new int[2]; - if (tag != null) { - isSuccess = tag.checkNdef(ndefInfo); + if (tag == null) { + return false; } - return isSuccess; + return tag.checkNdef(ndefInfo) == 0; } @Override @@ -2360,15 +2361,19 @@ public class NfcService extends Application { int techIndex = 0; int lastHandleScanned = 0; boolean ndefFoundAndConnected = false; + boolean isTargetLost = false; NdefMessage[] ndefMsgs = null; boolean foundFormattable = false; int formattableHandle = 0; int formattableTechnology = 0; + int status; - while ((!ndefFoundAndConnected) && (techIndex < technologies.length)) { + while ((!ndefFoundAndConnected) && (techIndex < technologies.length) && (!isTargetLost)) + { if (handles[techIndex] != lastHandleScanned) { // We haven't seen this handle yet, connect and checkndef - if (nativeTag.connect(technologies[techIndex])) { + status = nativeTag.connect(technologies[techIndex]); + if (status == 0) { // Check if this type is NDEF formatable if (!foundFormattable) { if (nativeTag.isNdefFormatable()) { @@ -2383,7 +2388,8 @@ public class NfcService extends Application { } // else, already found formattable technology int[] ndefinfo = new int[2]; - if (nativeTag.checkNdef(ndefinfo)) { + status = nativeTag.checkNdef(ndefinfo); + if (status == 0) { ndefFoundAndConnected = true; boolean generateEmptyNdef = false; @@ -2417,10 +2423,17 @@ public class NfcService extends Application { supportedNdefLength, cardState); nativeTag.reconnect(); } - } // else, no NDEF on this tech, continue loop + } else { // else, no NDEF on this tech, continue loop + Log.d(TAG, "Check NDEF Failed - status = "+ status); + if (status == STATUS_CODE_TARGET_LOST) { + isTargetLost = true; + } + } } else { - // Connect failed, tag maybe lost. Try next handle - // anyway. + Log.d(TAG, "Connect Failed - status = "+ status); + if (status == STATUS_CODE_TARGET_LOST) { + isTargetLost = true; + } } } lastHandleScanned = handles[techIndex]; @@ -2461,13 +2474,14 @@ public class NfcService extends Application { dispatchNativeTag(nativeTag, ndefMsgs); } else { // No ndef found or connect failed, just try to reconnect and dispatch - if (nativeTag.reconnect()) { - nativeTag.startPresenceChecking(); - dispatchNativeTag(nativeTag, null); - } else { - Log.w(TAG, "Failed to connect to tag"); - nativeTag.disconnect(); - } + if (nativeTag.getLastStatusCode() != STATUS_CODE_TARGET_LOST) { + if (nativeTag.reconnect() == 0) { + nativeTag.startPresenceChecking(); + dispatchNativeTag(nativeTag, null); + } + } else { + nativeTag.disconnect(); + } } break; |