summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
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) {