Added support for (re)-connecting to tag technologies.
- Connect() now takes a technology as an argument.
- NativeNfcTag now knows to which technology it is connected.
The default connected handle is for now always the first in the
tech list; also, NDEF is only checked on the first tech.
Still to be done:
- Check ndef on other techs if not found on first
- Expose the connect(technology) API to the framework
- Fix some calls that still use nfc_jni_get_tag_handle and need to work
on the selected technology instead.
- Get rid of mHandle and the globals for keeping tag handles
Change-Id: If76d4d458565ab0be7ca986c080a59ed8fd0668f
diff --git a/jni/com_android_nfc.cpp b/jni/com_android_nfc.cpp
index 8395350..fc63210 100644
--- a/jni/com_android_nfc.cpp
+++ b/jni/com_android_nfc.cpp
@@ -232,6 +232,64 @@
}
+int nfc_jni_get_connected_tech_index(JNIEnv *e, jobject o)
+{
+
+ jclass c;
+ jfieldID f;
+
+ c = e->GetObjectClass(o);
+ f = e->GetFieldID(c, "mConnectedTechnology", "I");
+
+ return e->GetIntField(o, f);
+
+}
+
+jint nfc_jni_get_connected_technology(JNIEnv *e, jobject o)
+{
+ jclass c;
+ jfieldID f;
+ int connectedTech = -1;
+
+ int connectedTechIndex = nfc_jni_get_connected_tech_index(e,o);
+ jintArray techTypes = nfc_jni_get_nfc_tag_type(e, o);
+
+ if ((connectedTechIndex != -1) && (techTypes != NULL) &&
+ (connectedTechIndex < e->GetArrayLength(techTypes))) {
+ jint* technologies = e->GetIntArrayElements(techTypes, 0);
+ if (technologies != NULL) {
+ connectedTech = technologies[connectedTechIndex];
+ e->ReleaseIntArrayElements(techTypes, technologies, JNI_ABORT);
+ }
+ }
+
+ return connectedTech;
+
+}
+
+phLibNfc_Handle nfc_jni_get_connected_handle(JNIEnv *e, jobject o)
+{
+ jclass c;
+ jfieldID f;
+ phLibNfc_Handle connectedHandle = -1;
+
+ int connectedTechIndex = nfc_jni_get_connected_tech_index(e,o);
+ c = e->GetObjectClass(o);
+ f = e->GetFieldID(c, "mTechHandles", "[I");
+ jintArray techHandles = (jintArray) e->GetObjectField(o, f);
+
+ if ((connectedTechIndex != -1) && (techHandles != NULL) &&
+ (connectedTechIndex < e->GetArrayLength(techHandles))) {
+ jint* handles = e->GetIntArrayElements(techHandles, 0);
+ if (handles != NULL) {
+ connectedHandle = handles[connectedTechIndex];
+ e->ReleaseIntArrayElements(techHandles, handles, JNI_ABORT);
+ }
+ }
+ return connectedHandle;
+
+}
+
phLibNfc_Handle nfc_jni_get_nfc_tag_handle(JNIEnv *e, jobject o)
{
jclass c;
diff --git a/jni/com_android_nfc.h b/jni/com_android_nfc.h
index 04a4249..375bafa 100644
--- a/jni/com_android_nfc.h
+++ b/jni/com_android_nfc.h
@@ -194,6 +194,8 @@
jshort nfc_jni_get_p2p_device_mode(JNIEnv *e, jobject o);
/* TAG */
+jint nfc_jni_get_connected_technology(JNIEnv *e, jobject o);
+phLibNfc_Handle nfc_jni_get_connected_handle(JNIEnv *e, jobject o);
phLibNfc_Handle nfc_jni_get_nfc_tag_handle(JNIEnv *e, jobject o);
jintArray nfc_jni_get_nfc_tag_type(JNIEnv *e, jobject o);
diff --git a/jni/com_android_nfc_NativeNfcManager.cpp b/jni/com_android_nfc_NativeNfcManager.cpp
index 0a54c20..9ac00b4 100644
--- a/jni/com_android_nfc_NativeNfcManager.cpp
+++ b/jni/com_android_nfc_NativeNfcManager.cpp
@@ -959,6 +959,9 @@
f = e->GetFieldID(tag_cls, "mTechHandles", "[I");
e->SetObjectField(tag, f, handleList);
+
+ f = e->GetFieldID(tag_cls, "mConnectedTechnology", "I");
+ e->SetIntField(tag, f,(jint)-1);
}
/* Set tag handle */
diff --git a/jni/com_android_nfc_NativeNfcTag.cpp b/jni/com_android_nfc_NativeNfcTag.cpp
index 2d9ecf8..8ca7388 100644
--- a/jni/com_android_nfc_NativeNfcTag.cpp
+++ b/jni/com_android_nfc_NativeNfcTag.cpp
@@ -458,9 +458,8 @@
}
static jboolean com_android_nfc_NativeNfcTag_doConnect(JNIEnv *e,
- jobject o)
+ jobject o, phLibNfc_Handle handle)
{
- phLibNfc_Handle handle = 0;
jclass cls;
jfieldID f;
NFCSTATUS status;
@@ -470,8 +469,6 @@
CONCURRENCY_LOCK();
- handle = nfc_jni_get_nfc_tag_handle(e, o);
-
/* Create the local semaphore */
if (!nfc_cb_data_init(&cb_data, &pRemDevInfo))
{
@@ -519,7 +516,21 @@
{
// Reconnect is provided by libnfc by just calling connect again
// on the same handle.
- return com_android_nfc_NativeNfcTag_doConnect(e, o);
+ // Note that some tag types are stateless, hence we do not reconnect
+ // those. Currently those are the Jewel and Iso15693 technologies.
+ int selectedTech = nfc_jni_get_connected_technology(e, o);
+ if (selectedTech != -1) {
+ if (selectedTech != TARGET_TYPE_ISO15693) {
+ phLibNfc_Handle handle = nfc_jni_get_connected_handle(e,o);
+ return com_android_nfc_NativeNfcTag_doConnect(e, o, handle);
+ }
+ else {
+ return JNI_TRUE;
+ }
+ }
+ else {
+ return JNI_FALSE;
+ }
}
@@ -665,6 +676,7 @@
}
}
+
static jbyteArray com_android_nfc_NativeNfcTag_doTransceive(JNIEnv *e,
jobject o, jbyteArray data, jboolean raw)
{
@@ -680,7 +692,6 @@
phLibNfc_sTransceiveInfo_t transceive_info;
jbyteArray result = NULL;
int res;
- jintArray techtypes = nfc_jni_get_nfc_tag_type(e, o);
phLibNfc_Handle handle = nfc_jni_get_nfc_tag_handle(e, o);
NFCSTATUS status;
struct nfc_jni_callback_data cb_data;
@@ -688,6 +699,7 @@
jint* technologies = NULL;
bool checkResponseCrc = false;
+ memset(&transceive_info, 0, sizeof(transceive_info));
CONCURRENCY_LOCK();
/* Create the local semaphore */
@@ -696,15 +708,7 @@
goto clean_and_return;
}
- if ((techtypes == NULL) || (e->GetArrayLength(techtypes) == 0)) {
- goto clean_and_return;
- }
- // TODO: code to determine the selected technology
- // For now, take the first
- technologies = e->GetIntArrayElements(techtypes, 0);
- selectedTech = technologies[0];
-
- TRACE("Transceive thinks selected tag technology = %d\n", selectedTech);
+ selectedTech = nfc_jni_get_connected_technology(e, o);
buf = outbuf = (uint8_t *)e->GetByteArrayElements(data, NULL);
buflen = outlen = (uint32_t)e->GetArrayLength(data);
@@ -830,9 +834,6 @@
{
free(transceive_info.sRecvData.buffer);
}
- if (technologies != NULL) {
- e->ReleaseIntArrayElements(techtypes, technologies, JNI_ABORT);
- }
if ((outbuf != buf) && (outbuf != NULL)) {
// Buf was extended and re-alloced with crc bytes, free separately
@@ -1024,7 +1025,7 @@
*/
static JNINativeMethod gMethods[] =
{
- {"doConnect", "()Z",
+ {"doConnect", "(I)Z",
(void *)com_android_nfc_NativeNfcTag_doConnect},
{"doDisconnect", "()Z",
(void *)com_android_nfc_NativeNfcTag_doDisconnect},
diff --git a/src/com/android/nfc/NativeNfcTag.java b/src/com/android/nfc/NativeNfcTag.java
index 51f5987..26595d5 100755
--- a/src/com/android/nfc/NativeNfcTag.java
+++ b/src/com/android/nfc/NativeNfcTag.java
@@ -41,6 +41,8 @@
private byte[][] mTechActBytes;
private byte[] mUid;
+ private int mConnectedTechnology; // Index in mTechList
+
private final String TAG = "NativeNfcTag";
private PresenceCheckWatchdog mWatchdog;
@@ -78,12 +80,35 @@
}
}
- private native boolean doConnect();
+ private native boolean doConnect(int handle);
+ public synchronized boolean connect(int technology) {
+ boolean isSuccess = false;
+ for (int i = 0; i < mTechList.length; i++) {
+ if (mTechList[i] == technology) {
+ // Get the handle and connect
+ isSuccess = doConnect(mTechHandles[i]);
+ if (isSuccess) {
+ mConnectedTechnology = i;
+ mWatchdog = new PresenceCheckWatchdog();
+ mWatchdog.start();
+ }
+ break;
+ }
+ }
+ return isSuccess;
+ }
+
public synchronized boolean connect() {
- boolean isSuccess = doConnect();
- if (isSuccess) {
- mWatchdog = new PresenceCheckWatchdog();
- mWatchdog.start();
+ // Just take the first handle in the list
+ boolean isSuccess = false;
+ if ((mTechHandles.length > 0) && (mTechList.length > 0)) {
+ int handle = mTechHandles[0];
+ isSuccess = doConnect(handle);
+ if (isSuccess) {
+ mConnectedTechnology = 0;
+ mWatchdog = new PresenceCheckWatchdog();
+ mWatchdog.start();
+ }
}
return isSuccess;
}
@@ -93,6 +118,7 @@
if (mWatchdog != null) {
mWatchdog.end();
}
+ mConnectedTechnology = -1;
return doDisconnect();
}
diff --git a/src/com/android/nfc/NfcService.java b/src/com/android/nfc/NfcService.java
index a5e6b2d..2e857da 100755
--- a/src/com/android/nfc/NfcService.java
+++ b/src/com/android/nfc/NfcService.java
@@ -1610,7 +1610,7 @@
@Override
public int getLastError(int nativeHandle) throws RemoteException {
- throw new UnsupportedOperationException();
+ return(mManager.doGetLastError());
}
@Override
@@ -2483,6 +2483,9 @@
case MSG_NDEF_TAG:
if (DBG) Log.d(TAG, "Tag detected, notifying applications");
NativeNfcTag nativeTag = (NativeNfcTag) msg.obj;
+ // TODO: should check on next handle if ndef not available
+ // on the first. For now, just connect to the first handle
+ // in the list.
if (nativeTag.connect()) {
int[] ndefinfo = new int[2];
if (nativeTag.checkNdef(ndefinfo)) {
@@ -2496,6 +2499,7 @@
msgNdef[0] = new NdefMessage(buff);
nativeTag.addNdefTechnology(msgNdef[0],
supportedNdefLength, cardState);
+ nativeTag.reconnect();
dispatchNativeTag(nativeTag, msgNdef);
} catch (FormatException e) {
// Create an intent anyway, without NDEF messages
@@ -2511,6 +2515,7 @@
nativeTag.addNdefTechnology(null, supportedNdefLength, cardState);
if (DBG) Log.d(TAG, "NDEF tag found, but length 0 or invalid format, " +
"starting corresponding activity");
+ nativeTag.reconnect();
dispatchNativeTag(nativeTag, new NdefMessage[] { });
}
} else {