summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorMartijn Coenen <maco@google.com>2011-06-01 21:29:51 -0700
committerMartijn Coenen <maco@google.com>2011-06-08 17:07:09 +0200
commit3fb14d0868594c78a777e805545209636814e223 (patch)
tree67ce8223a2c37cc741e05c5d02fd0b28b209c0d4 /src
parentbad4dcc454a064f0c062f097d567a57633d1cb30 (diff)
downloadpackages_apps_nfc-3fb14d0868594c78a777e805545209636814e223.zip
packages_apps_nfc-3fb14d0868594c78a777e805545209636814e223.tar.gz
packages_apps_nfc-3fb14d0868594c78a777e805545209636814e223.tar.bz2
Added support for rediscovering a Tag.
This adds basic support for rediscovering the currently connected tag. At the moment rediscovering the same tag is not well supported by libnfc. The real usecase for rediscover is actually run-time adding and/or removing the Ndef and NdefFormatable technologes, and since we detect these in the upper layers of the stack anyway this makes the implementation a lot simpler. This change also required a cleaner split between connected technologies and connected handles. Connected technologies are something that only the Java part of the API is concerned with. Each technology is mapped to a handle, which is how libnfc refers to a tag. Previously we used the connected technology to derive the connected libnfc handle, but since this change allows run-time removal of technologies *without* disconnecting from a handle we need to keep track of them separately. Bug: 3378764 Change-Id: If4725fa266eb37aa17aa67b31491f4bd77b1ee68
Diffstat (limited to 'src')
-rwxr-xr-xsrc/com/android/nfc/NativeNfcTag.java117
-rwxr-xr-xsrc/com/android/nfc/NfcService.java197
2 files changed, 191 insertions, 123 deletions
diff --git a/src/com/android/nfc/NativeNfcTag.java b/src/com/android/nfc/NativeNfcTag.java
index 1489b23..f5af2f2 100755
--- a/src/com/android/nfc/NativeNfcTag.java
+++ b/src/com/android/nfc/NativeNfcTag.java
@@ -42,7 +42,19 @@ public class NativeNfcTag {
private byte[][] mTechActBytes;
private byte[] mUid;
- private int mConnectedTechnology; // Index in mTechList
+ // mConnectedHandle stores the *real* libnfc handle
+ // that we're connected to.
+ private int mConnectedHandle;
+
+ // mConnectedTechIndex stores to which technology
+ // the upper layer stack is connected. Note that
+ // we may be connected to a libnfchandle without being
+ // connected to a technology - technology changes
+ // may occur runtime, whereas the underlying handle
+ // could stay present. Usually all technologies are on the
+ // same handle, with the exception of multi-protocol
+ // tags.
+ private int mConnectedTechIndex; // Index in mTechHandles
private final String TAG = "NativeNfcTag";
@@ -125,52 +137,49 @@ public class NativeNfcTag {
for (int i = 0; i < mTechList.length; i++) {
if (mTechList[i] == technology) {
// Get the handle and connect, if not already connected
- if (mConnectedTechnology != i) {
- // We're not yet connected, there are a few scenario's
- // here:
+ if (mConnectedHandle != mTechHandles[i]) {
+ // We're not yet connected to this handle, there are
+ // a few scenario's here:
// 1) We are not connected to anything yet - allow
// 2) We are connected to a technology which has
// a different handle (multi-protocol tag); we support
// switching to that.
- // 3) We are connected to a technology which has the same
- // handle; we do not support connecting at a different
- // level (libnfc auto-activates to the max level on
- // any handle).
- // 4) We are connecting to the ndef technology - always
- // allowed.
- if (mConnectedTechnology == -1) {
+ if (mConnectedHandle == -1) {
// Not connected yet
isSuccess = doConnect(mTechHandles[i]);
- }
- else if ((mConnectedTechnology != -1) &&
- (mTechHandles[mConnectedTechnology] != mTechHandles[i])) {
+ } else {
// Connect to a tech with a different handle
isSuccess = reconnect(mTechHandles[i]);
}
- else {
- // Already connected to a tech with the same handle
- // Only allow Ndef / NdefFormatable techs to return
- // success
- if ((technology == TagTechnology.NDEF) ||
- (technology == TagTechnology.NDEF_FORMATABLE)) {
- isSuccess = true;
+ if (isSuccess) {
+ mConnectedHandle = mTechHandles[i];
+ mConnectedTechIndex = i;
+ }
+ } else {
+ // 1) We are connected to a technology which has the same
+ // handle; we do not support connecting at a different
+ // level (libnfc auto-activates to the max level on
+ // any handle).
+ // 2) We are connecting to the ndef technology - always
+ // allowed.
+ if ((technology == TagTechnology.NDEF) ||
+ (technology == TagTechnology.NDEF_FORMATABLE)) {
+ isSuccess = true;
+ } 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 {
- 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;
- }
+ isSuccess = true;
}
}
if (isSuccess) {
- mConnectedTechnology = i;
+ mConnectedTechIndex = i;
+ // Handle was already identical
}
- } else {
- isSuccess = true; // Already connect to this tech
}
break;
}
@@ -216,7 +225,8 @@ public class NativeNfcTag {
result = doDisconnect();
}
- mConnectedTechnology = -1;
+ mConnectedTechIndex = -1;
+ mConnectedHandle = -1;
return result;
}
@@ -372,24 +382,20 @@ public class NativeNfcTag {
}
public int getConnectedHandle() {
- if (mConnectedTechnology != -1 && mConnectedTechnology < mTechHandles.length) {
- return mTechHandles[mConnectedTechnology];
- } else {
- return 0;
- }
+ return mConnectedHandle;
}
public int getConnectedLibNfcType() {
- if (mConnectedTechnology != -1 && mConnectedTechnology < mTechLibNfcTypes.length) {
- return mTechLibNfcTypes[mConnectedTechnology];
+ if (mConnectedTechIndex != -1 && mConnectedTechIndex < mTechLibNfcTypes.length) {
+ return mTechLibNfcTypes[mConnectedTechIndex];
} else {
return 0;
}
}
public int getConnectedTechnology() {
- if (mConnectedTechnology != -1 && mConnectedTechnology < mTechList.length) {
- return mTechList[mConnectedTechnology];
+ if (mConnectedTechIndex != -1 && mConnectedTechIndex < mTechList.length) {
+ return mTechList[mConnectedTechIndex];
} else {
return 0;
}
@@ -416,6 +422,31 @@ public class NativeNfcTag {
mTechLibNfcTypes = mNewTypeList;
}
+ public void removeTechnology(int tech) {
+ synchronized (this) {
+ int techIndex = getTechIndex(tech);
+ if (techIndex != -1) {
+ int[] mNewTechList = new int[mTechList.length - 1];
+ System.arraycopy(mTechList, 0, mNewTechList, 0, techIndex);
+ System.arraycopy(mTechList, techIndex + 1, mNewTechList, techIndex,
+ mTechList.length - techIndex - 1);
+ mTechList = mNewTechList;
+
+ int[] mNewHandleList = new int[mTechHandles.length - 1];
+ System.arraycopy(mTechHandles, 0, mNewHandleList, 0, techIndex);
+ System.arraycopy(mTechHandles, techIndex + 1, mNewTechList, techIndex,
+ mTechHandles.length - techIndex - 1);
+ mTechHandles = mNewHandleList;
+
+ int[] mNewTypeList = new int[mTechLibNfcTypes.length - 1];
+ System.arraycopy(mTechLibNfcTypes, 0, mNewTypeList, 0, techIndex);
+ System.arraycopy(mTechLibNfcTypes, techIndex + 1, mNewTypeList, techIndex,
+ mTechLibNfcTypes.length - techIndex - 1);
+ mTechLibNfcTypes = mNewTypeList;
+ }
+ }
+ }
+
public void addNdefFormatableTechnology(int handle, int libnfcType) {
synchronized (this) {
addTechnology(TagTechnology.NDEF_FORMATABLE, handle, libnfcType);
diff --git a/src/com/android/nfc/NfcService.java b/src/com/android/nfc/NfcService.java
index 169d9d3..6156695 100755
--- a/src/com/android/nfc/NfcService.java
+++ b/src/com/android/nfc/NfcService.java
@@ -59,6 +59,7 @@ import android.nfc.NdefMessage;
import android.nfc.NdefRecord;
import android.nfc.NfcAdapter;
import android.nfc.Tag;
+import android.nfc.tech.TagTechnology;
import android.nfc.TechListParcel;
import android.nfc.TransceiveResult;
import android.nfc.tech.TagTechnology;
@@ -897,6 +898,7 @@ public class NfcService extends Application {
}
}
}
+
};
private final ILlcpSocket mLlcpSocket = new ILlcpSocket.Stub() {
@@ -1603,6 +1605,40 @@ public class NfcService extends Application {
}
@Override
+ public Tag rediscover(int nativeHandle) throws RemoteException {
+ mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR);
+
+ NativeNfcTag tag = null;
+
+ // Check if NFC is enabled
+ if (!mIsNfcEnabled) {
+ return null;
+ }
+
+ /* find the tag in the hmap */
+ tag = (NativeNfcTag) findObject(nativeHandle);
+ if (tag != null) {
+ // For now the prime usecase for rediscover() is to be able
+ // to access the NDEF technology after formatting without
+ // having to remove the tag from the field, or similar
+ // to have access to NdefFormatable in case low-level commands
+ // were used to remove NDEF. So instead of doing a full stack
+ // rediscover (which is poorly supported at the moment anyway),
+ // we simply remove these two technologies and detect them
+ // again.
+ tag.removeTechnology(TagTechnology.NDEF);
+ tag.removeTechnology(TagTechnology.NDEF_FORMATABLE);
+ NdefMessage[] msgs = findAndReadNdef(tag);
+ // Build a new Tag object to return
+ Tag newTag = new Tag(tag.getUid(), tag.getTechList(),
+ tag.getTechExtras(), tag.getHandle(), mNfcTagService);
+ return newTag;
+ }
+ return null;
+ }
+
+
+ @Override
public void setIsoDepTimeout(int timeout) throws RemoteException {
mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR);
@@ -2322,92 +2358,93 @@ public class NfcService extends Application {
mHandler.sendMessage(msg);
}
- final class NfcServiceHandler extends Handler {
-
- public NdefMessage[] findAndReadNdef(NativeNfcTag nativeTag) {
- // Try to find NDEF on any of the technologies.
- int[] technologies = nativeTag.getTechList();
- int[] handles = nativeTag.getHandleList();
- int techIndex = 0;
- int lastHandleScanned = 0;
- boolean ndefFoundAndConnected = false;
- NdefMessage[] ndefMsgs = null;
- boolean foundFormattable = false;
- int formattableHandle = 0;
- int formattableTechnology = 0;
-
- while ((!ndefFoundAndConnected) && (techIndex < technologies.length)) {
- if (handles[techIndex] != lastHandleScanned) {
- // We haven't seen this handle yet, connect and checkndef
- if (nativeTag.connect(technologies[techIndex])) {
- // Check if this type is NDEF formatable
- if (!foundFormattable) {
- if (nativeTag.isNdefFormatable()) {
- foundFormattable = true;
- formattableHandle = nativeTag.getConnectedHandle();
- formattableTechnology = nativeTag.getConnectedTechnology();
- // We'll only add formattable tech if no ndef is
- // found - this is because libNFC refuses to format
- // an already NDEF formatted tag.
- }
- nativeTag.reconnect();
- } // else, already found formattable technology
-
- int[] ndefinfo = new int[2];
- if (nativeTag.checkNdef(ndefinfo)) {
- ndefFoundAndConnected = true;
- boolean generateEmptyNdef = false;
-
- int supportedNdefLength = ndefinfo[0];
- int cardState = ndefinfo[1];
- byte[] buff = nativeTag.read();
- if (buff != null) {
- ndefMsgs = new NdefMessage[1];
- try {
- ndefMsgs[0] = new NdefMessage(buff);
- nativeTag.addNdefTechnology(ndefMsgs[0],
- nativeTag.getConnectedHandle(),
- nativeTag.getConnectedLibNfcType(),
- nativeTag.getConnectedTechnology(),
- supportedNdefLength, cardState);
- nativeTag.reconnect();
- } catch (FormatException e) {
- // Create an intent anyway, without NDEF messages
- generateEmptyNdef = true;
- }
- } else {
- generateEmptyNdef = true;
+ static public NdefMessage[] findAndReadNdef(NativeNfcTag nativeTag) {
+ // Try to find NDEF on any of the technologies.
+ int[] technologies = nativeTag.getTechList();
+ int[] handles = nativeTag.getHandleList();
+ int techIndex = 0;
+ int lastHandleScanned = 0;
+ boolean ndefFoundAndConnected = false;
+ NdefMessage[] ndefMsgs = null;
+ boolean foundFormattable = false;
+ int formattableHandle = 0;
+ int formattableLibNfcType = 0;
+
+ while ((!ndefFoundAndConnected) && (techIndex < technologies.length)) {
+ if (handles[techIndex] != lastHandleScanned) {
+ // We haven't seen this handle yet, connect and checkndef
+ if (nativeTag.connect(technologies[techIndex])) {
+ // Check if this type is NDEF formatable
+ if (!foundFormattable) {
+ if (nativeTag.isNdefFormatable()) {
+ foundFormattable = true;
+ formattableHandle = nativeTag.getConnectedHandle();
+ formattableLibNfcType = nativeTag.getConnectedLibNfcType();
+ // We'll only add formattable tech if no ndef is
+ // found - this is because libNFC refuses to format
+ // an already NDEF formatted tag.
+ }
+ nativeTag.reconnect();
+ } // else, already found formattable technology
+
+ int[] ndefinfo = new int[2];
+ if (nativeTag.checkNdef(ndefinfo)) {
+ ndefFoundAndConnected = true;
+ boolean generateEmptyNdef = false;
+
+ int supportedNdefLength = ndefinfo[0];
+ int cardState = ndefinfo[1];
+ byte[] buff = nativeTag.read();
+ if (buff != null) {
+ ndefMsgs = new NdefMessage[1];
+ try {
+ ndefMsgs[0] = new NdefMessage(buff);
+ nativeTag.addNdefTechnology(ndefMsgs[0],
+ nativeTag.getConnectedHandle(),
+ nativeTag.getConnectedLibNfcType(),
+ nativeTag.getConnectedTechnology(),
+ supportedNdefLength, cardState);
+ nativeTag.reconnect();
+ } catch (FormatException e) {
+ // Create an intent anyway, without NDEF messages
+ generateEmptyNdef = true;
}
+ } else {
+ generateEmptyNdef = true;
+ }
- if (generateEmptyNdef) {
- ndefMsgs = new NdefMessage[] { };
- nativeTag.addNdefTechnology(null,
- nativeTag.getConnectedHandle(),
- nativeTag.getConnectedLibNfcType(),
- nativeTag.getConnectedTechnology(),
- supportedNdefLength, cardState);
- nativeTag.reconnect();
- }
- } // else, no NDEF on this tech, continue loop
- } else {
- // Connect failed, tag maybe lost. Try next handle
- // anyway.
- }
+ if (generateEmptyNdef) {
+ ndefMsgs = new NdefMessage[] { };
+ nativeTag.addNdefTechnology(null,
+ nativeTag.getConnectedHandle(),
+ nativeTag.getConnectedLibNfcType(),
+ nativeTag.getConnectedTechnology(),
+ supportedNdefLength, cardState);
+ nativeTag.reconnect();
+ }
+ } // else, no NDEF on this tech, continue loop
+ } else {
+ // Connect failed, tag maybe lost. Try next handle
+ // anyway.
}
- lastHandleScanned = handles[techIndex];
- techIndex++;
- }
- if (ndefMsgs == null && foundFormattable) {
- // Tag is not NDEF yet, and found a formattable target,
- // so add formattable tech to tech list.
- nativeTag.addNdefFormatableTechnology(
- formattableHandle,
- formattableTechnology);
}
-
- return ndefMsgs;
+ lastHandleScanned = handles[techIndex];
+ techIndex++;
+ }
+ if (ndefMsgs == null && foundFormattable) {
+ // Tag is not NDEF yet, and found a formattable target,
+ // so add formattable tech to tech list.
+ nativeTag.addNdefFormatableTechnology(
+ formattableHandle,
+ formattableLibNfcType);
}
+ return ndefMsgs;
+ }
+
+
+ final class NfcServiceHandler extends Handler {
+
@Override
public void handleMessage(Message msg) {
switch (msg.what) {