diff options
author | Martijn Coenen <maco@google.com> | 2011-06-01 21:29:51 -0700 |
---|---|---|
committer | Martijn Coenen <maco@google.com> | 2011-06-08 17:07:09 +0200 |
commit | 3fb14d0868594c78a777e805545209636814e223 (patch) | |
tree | 67ce8223a2c37cc741e05c5d02fd0b28b209c0d4 /src | |
parent | bad4dcc454a064f0c062f097d567a57633d1cb30 (diff) | |
download | packages_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-x | src/com/android/nfc/NativeNfcTag.java | 117 | ||||
-rwxr-xr-x | src/com/android/nfc/NfcService.java | 197 |
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) { |