diff options
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) { |