summaryrefslogtreecommitdiff
path: root/core/java
diff options
context:
space:
mode:
authorNick Pelly <npelly@google.com>2010-10-21 21:42:24 -0700
committerNick Pelly <npelly@google.com>2010-10-22 16:29:43 -0700
commit07f3bee2db8b6e93ebbf7222676bd9f468e85569 (patch)
tree4d1d6a9f81252ebda078954da4380b470f0b320b /core/java
parent67496e591dca9c7faa07f6e1c8849c9d5af4edb9 (diff)
Push Tag/NdefTag implementation details into the service.
Tag/NdefTag objects should just be simple data objects. Push the mapping of internal tag type to public rawTarget/ndefTarget into Nfc Service. This gives an oppurtunity to clean up some Tag/NdefTag API methods. Most significantly, adding createMockTag() and createMockNdefTag() to help with application testing. There will probably be some more tweaking of the types/targets in Tag/NdefTag to come, this commit makes that a lot easier. Also: - Introduce getActivationBytes() and getPollBytes(). These are just stubs for NFC service to implement, we have feedback these are really important to help identify NFC tags. - Based on outside advice, remove 3B_PRIME (roll into 3B) and TOPAZ (roll into 3A). Change-Id: I3e6789c047f6ee5c298bf76c65e0885cf3c15d97 Signed-off-by: Nick Pelly <npelly@google.com>
Diffstat (limited to 'core/java')
-rw-r--r--core/java/android/nfc/NdefTag.java207
-rw-r--r--core/java/android/nfc/NdefTagConnection.java10
-rw-r--r--core/java/android/nfc/NfcAdapter.java12
-rw-r--r--core/java/android/nfc/RawTagConnection.java6
-rw-r--r--core/java/android/nfc/Tag.java295
5 files changed, 301 insertions, 229 deletions
diff --git a/core/java/android/nfc/NdefTag.java b/core/java/android/nfc/NdefTag.java
index 45cdc317f010..d8681dc21798 100644
--- a/core/java/android/nfc/NdefTag.java
+++ b/core/java/android/nfc/NdefTag.java
@@ -16,8 +16,6 @@
package android.nfc;
-import java.util.HashMap;
-
import android.os.Parcel;
import android.os.Parcelable;
@@ -33,19 +31,92 @@ import android.os.Parcelable;
* is possible for {@link NdefTag}s to contain multiple {@link NdefMessage}s.
* <p>{@link NfcAdapter#createNdefTagConnection createNdefTagConnection()} can be used to modify the
* contents of some tags.
- * <p>This is an immutable data class.
+ * <p>This is an immutable data class. All properties are set at Tag discovery
+ * time and calls on this class will retrieve those read-only properties, and
+ * not cause any further RF activity or block. Note however that arrays passed to and
+ * returned by this class are *not* cloned, so be careful not to modify them.
*/
public class NdefTag extends Tag implements Parcelable {
- private final NdefMessage[] mMessages;
+ /**
+ * Target for NFC Forum Type 1 compliant tag.
+ * <p>This is based on Jewel/Topaz technology
+ */
+ public static final String TARGET_TYPE_1 = "type_1";
+
+ /**
+ * Target for NFC Forum Type 2 compliant tag.
+ * <p>This is based on Mifare Ultralight technology.
+ */
+ public static final String TARGET_TYPE_2 = "type_2";
/**
- * Hidden constructor to be used by NFC service when a
- * tag is discovered and by Parcelable methods.
+ * Target for NFC Forum Type 3 compliant tag.
+ * <p>This is based on Felica technology.
+ */
+ public static final String TARGET_TYPE_3 = "type_3";
+
+ /**
+ * Target for NFC Forum Type 4 compliant tag.
+ * <p>This is based on Mifare Desfire technology.
+ */
+ public static final String TARGET_TYPE_4 = "type_4";
+
+ /**
+ * Target for NFC Forum Enabled: Mifare Classic tag.
+ * <p>This is not strictly a NFC Forum tag type, but is a common
+ * NDEF message container.
+ */
+ public static final String TARGET_MIFARE_CLASSIC = "type_mifare_classic";
+
+ /**
+ * Any other target.
+ */
+ public static final String TARGET_OTHER = "other";
+
+ private final String[] mNdefTargets;
+ private final NdefMessage[][] mMessages; // one NdefMessage[] per NDEF target
+ private NdefMessage[] mFlatMessages; // collapsed mMessages, built lazily, protected by (this)
+
+ /**
+ * Hidden constructor to be used by NFC service only.
* @hide
*/
- public NdefTag(String typeName, byte[] uid, int nativeHandle, NdefMessage[] messages) {
- super(typeName, true, uid, nativeHandle);
- mMessages = messages.clone();
+ public NdefTag(byte[] id, String[] rawTargets, byte[] pollBytes, byte[] activationBytes,
+ int serviceHandle, String[] ndefTargets, NdefMessage[][] messages) {
+ super(id, true, rawTargets, pollBytes, activationBytes, serviceHandle);
+ if (ndefTargets == null || messages == null) {
+ throw new IllegalArgumentException("ndefTargets or messages cannot be null");
+ }
+ if (ndefTargets.length != messages.length){
+ throw new IllegalArgumentException("ndefTargets and messages arrays must match");
+ }
+ for (NdefMessage[] ms : messages) {
+ if (ms == null) {
+ throw new IllegalArgumentException("messages elements cannot be null");
+ }
+ }
+ mNdefTargets = ndefTargets;
+ mMessages = messages;
+ }
+
+ /**
+ * Construct a mock NdefTag.
+ * <p>This is an application constructed tag, so NfcAdapter methods on this
+ * Tag such as {@link NfcAdapter#createRawTagConnection} will fail with
+ * {@link IllegalArgumentException} since it does not represent a physical Tag.
+ * <p>This constructor might be useful for mock testing.
+ * @param id The tag identifier, can be null
+ * @param rawTargets must not be null
+ * @param pollBytes can be null
+ * @param activationBytes can be null
+ * @param ndefTargets NDEF target array, such as {TARGET_TYPE_2}, cannot be null
+ * @param messages messages, one array per NDEF target, cannot be null
+ * @return freshly constructed NdefTag
+ */
+ public static NdefTag createMockNdefTag(byte[] id, String[] rawTargets, byte[] pollBytes,
+ byte[] activationBytes, String[] ndefTargets, NdefMessage[][] messages) {
+ // set serviceHandle to 0 to indicate mock tag
+ return new NdefTag(id, rawTargets, pollBytes, activationBytes, 0, ndefTargets, messages);
}
/**
@@ -59,7 +130,29 @@ public class NdefTag extends Tag implements Parcelable {
* @return NDEF Messages found at Tag discovery
*/
public NdefMessage[] getNdefMessages() {
- return mMessages.clone();
+ // common-case optimization
+ if (mMessages.length == 1) {
+ return mMessages[0];
+ }
+
+ // return cached flat array
+ synchronized(this) {
+ if (mFlatMessages != null) {
+ return mFlatMessages;
+ }
+ // not cached - build a flat array
+ int sz = 0;
+ for (NdefMessage[] ms : mMessages) {
+ sz += ms.length;
+ }
+ mFlatMessages = new NdefMessage[sz];
+ int i = 0;
+ for (NdefMessage[] ms : mMessages) {
+ System.arraycopy(ms, 0, mFlatMessages, i, ms.length);
+ i += ms.length;
+ }
+ return mFlatMessages;
+ }
}
/**
@@ -70,58 +163,25 @@ public class NdefTag extends Tag implements Parcelable {
* <p>
* Most tags only contain a single NDEF message.
*
- * @param target One of targets strings provided by getNdefTargets()
+ * @param target one of targets strings provided by getNdefTargets()
* @return NDEF Messages found at Tag discovery
*/
public NdefMessage[] getNdefMessages(String target) {
- // TODO: handle multiprotocol
- String[] localTypes = convertToNdefType(mTypeName);
- if (!target.equals(localTypes[0])) {
- throw new IllegalArgumentException();
- }
- return getNdefMessages();
- }
-
- /** TODO(npelly):
- * - check that any single tag can only have one of each NDEF type
- * - ok to include mifare_classic?
- */
- public static final String TARGET_TYPE_1 = "type_1";
- public static final String TARGET_TYPE_2 = "type_2";
- public static final String TARGET_TYPE_3 = "type_3";
- public static final String TARGET_TYPE_4 = "type_4";
- public static final String TARGET_MIFARE_CLASSIC = "type_mifare_classic";
- public static final String TARGET_OTHER = "other";
-
- private static final HashMap<String, String[]> NDEF_TYPES_CONVERTION_TABLE = new HashMap<String, String[]>() {
- {
- // TODO: handle multiprotocol
- // TODO: move INTERNAL_TARGET_Type to TARGET_TYPE mapping to NFC service
- put(Tag.INTERNAL_TARGET_TYPE_JEWEL, new String[] { NdefTag.TARGET_TYPE_1 });
- put(Tag.INTERNAL_TARGET_TYPE_MIFARE_UL, new String[] { NdefTag.TARGET_TYPE_2 });
- put(Tag.INTERNAL_TARGET_TYPE_MIFARE_1K, new String[] { NdefTag.TARGET_MIFARE_CLASSIC });
- put(Tag.INTERNAL_TARGET_TYPE_MIFARE_4K, new String[] { NdefTag.TARGET_MIFARE_CLASSIC });
- put(Tag.INTERNAL_TARGET_TYPE_FELICA, new String[] { NdefTag.TARGET_TYPE_3 });
- put(Tag.INTERNAL_TARGET_TYPE_ISO14443_4, new String[] { NdefTag.TARGET_TYPE_4 });
- put(Tag.INTERNAL_TARGET_TYPE_MIFARE_DESFIRE, new String[] { NdefTag.TARGET_TYPE_4 });
+ for (int i=0; i<mNdefTargets.length; i++) {
+ if (target.equals(mNdefTargets[i])) {
+ return mMessages[i];
+ }
}
- };
-
- private String[] convertToNdefType(String internalTypeName) {
- String[] result = NDEF_TYPES_CONVERTION_TABLE.get(internalTypeName);
- if (result == null) {
- return new String[] { NdefTag.TARGET_OTHER };
- }
- return result;
+ throw new IllegalArgumentException("target (" + target + ") not found");
}
/**
- * Return the
+ * Return the NDEF targets on this Tag that support NDEF messages.
*
* @return
*/
public String[] getNdefTargets() {
- return convertToNdefType(mTypeName);
+ return mNdefTargets;
}
@Override
@@ -131,19 +191,50 @@ public class NdefTag extends Tag implements Parcelable {
@Override
public void writeToParcel(Parcel dest, int flags) {
- super.writeToParcel(dest, flags);
+ // Tag fields
+ dest.writeInt(mIsNdef ? 1 : 0);
+ writeBytesWithNull(dest, mId);
+ dest.writeInt(mRawTargets.length);
+ dest.writeStringArray(mRawTargets);
+ writeBytesWithNull(dest, mPollBytes);
+ writeBytesWithNull(dest, mActivationBytes);
+ dest.writeInt(mServiceHandle);
+
+ // NdefTag fields
+ dest.writeInt(mNdefTargets.length);
+ dest.writeStringArray(mNdefTargets);
dest.writeInt(mMessages.length);
- dest.writeTypedArray(mMessages, flags);
+ for (NdefMessage[] ms : mMessages) {
+ dest.writeTypedArray(ms, flags);
+ }
}
public static final Parcelable.Creator<NdefTag> CREATOR =
new Parcelable.Creator<NdefTag>() {
public NdefTag createFromParcel(Parcel in) {
- Tag tag = Tag.CREATOR.createFromParcel(in);
- int messagesLength = in.readInt();
- NdefMessage[] messages = new NdefMessage[messagesLength];
- in.readTypedArray(messages, NdefMessage.CREATOR);
- return new NdefTag(tag.mTypeName, tag.mUid, tag.mNativeHandle, messages);
+ boolean isNdef = (in.readInt() == 1);
+ if (!isNdef) {
+ throw new IllegalArgumentException("Creating NdefTag from Tag parcel");
+ }
+
+ // Tag fields
+ byte[] id = readBytesWithNull(in);
+ String[] rawTargets = new String[in.readInt()];
+ in.readStringArray(rawTargets);
+ byte[] pollBytes = readBytesWithNull(in);
+ byte[] activationBytes = readBytesWithNull(in);
+ int serviceHandle = in.readInt();
+
+ // NdefTag fields
+ String[] ndefTargets = new String[in.readInt()];
+ in.readStringArray(ndefTargets);
+ NdefMessage[][] messages = new NdefMessage[in.readInt()][];
+ for (int i=0; i<messages.length; i++) {
+ messages[i] = new NdefMessage[in.readInt()];
+ in.readTypedArray(messages[i], NdefMessage.CREATOR);
+ }
+ return new NdefTag(id, rawTargets, pollBytes, activationBytes, serviceHandle,
+ ndefTargets, messages);
}
public NdefTag[] newArray(int size) {
return new NdefTag[size];
diff --git a/core/java/android/nfc/NdefTagConnection.java b/core/java/android/nfc/NdefTagConnection.java
index 4795fa72ec6c..321b0eca1685 100644
--- a/core/java/android/nfc/NdefTagConnection.java
+++ b/core/java/android/nfc/NdefTagConnection.java
@@ -81,9 +81,9 @@ public class NdefTagConnection extends RawTagConnection {
//TODO(nxp): do not use getLastError(), it is racy
try {
NdefMessage[] msgArray = new NdefMessage[1];
- NdefMessage msg = mTagService.read(mTag.mNativeHandle);
+ NdefMessage msg = mTagService.read(mTag.mServiceHandle);
if (msg == null) {
- int errorCode = mTagService.getLastError(mTag.mNativeHandle);
+ int errorCode = mTagService.getLastError(mTag.mServiceHandle);
switch (errorCode) {
case ErrorCodes.ERROR_IO:
throw new IOException();
@@ -121,7 +121,7 @@ public class NdefTagConnection extends RawTagConnection {
*/
public void writeNdefMessage(NdefMessage message) throws IOException, FormatException {
try {
- int errorCode = mTagService.write(mTag.mNativeHandle, message);
+ int errorCode = mTagService.write(mTag.mServiceHandle, message);
switch (errorCode) {
case ErrorCodes.SUCCESS:
break;
@@ -148,7 +148,7 @@ public class NdefTagConnection extends RawTagConnection {
*/
public boolean makeReadOnly() throws IOException {
try {
- int errorCode = mTagService.makeReadOnly(mTag.mNativeHandle);
+ int errorCode = mTagService.makeReadOnly(mTag.mServiceHandle);
switch (errorCode) {
case ErrorCodes.SUCCESS:
return true;
@@ -175,7 +175,7 @@ public class NdefTagConnection extends RawTagConnection {
*/
public int getModeHint() throws IOException {
try {
- int result = mTagService.getModeHint(mTag.mNativeHandle);
+ int result = mTagService.getModeHint(mTag.mServiceHandle);
if (ErrorCodes.isError(result)) {
switch (result) {
case ErrorCodes.ERROR_IO:
diff --git a/core/java/android/nfc/NfcAdapter.java b/core/java/android/nfc/NfcAdapter.java
index 6884abb59c99..7f4b4a260ac9 100644
--- a/core/java/android/nfc/NfcAdapter.java
+++ b/core/java/android/nfc/NfcAdapter.java
@@ -327,6 +327,9 @@ public final class NfcAdapter {
* <p>Requires {@link android.Manifest.permission#NFC} permission.
*/
public RawTagConnection createRawTagConnection(Tag tag) {
+ if (tag.mServiceHandle == 0) {
+ throw new IllegalArgumentException("mock tag cannot be used for connections");
+ }
try {
return new RawTagConnection(mService, tag);
} catch (RemoteException e) {
@@ -340,6 +343,9 @@ public final class NfcAdapter {
* <p>Requires {@link android.Manifest.permission#NFC} permission.
*/
public RawTagConnection createRawTagConnection(Tag tag, String target) {
+ if (tag.mServiceHandle == 0) {
+ throw new IllegalArgumentException("mock tag cannot be used for connections");
+ }
try {
return new RawTagConnection(mService, tag, target);
} catch (RemoteException e) {
@@ -353,6 +359,9 @@ public final class NfcAdapter {
* <p>Requires {@link android.Manifest.permission#NFC} permission.
*/
public NdefTagConnection createNdefTagConnection(NdefTag tag) {
+ if (tag.mServiceHandle == 0) {
+ throw new IllegalArgumentException("mock tag cannot be used for connections");
+ }
try {
return new NdefTagConnection(mService, tag);
} catch (RemoteException e) {
@@ -366,6 +375,9 @@ public final class NfcAdapter {
* <p>Requires {@link android.Manifest.permission#NFC} permission.
*/
public NdefTagConnection createNdefTagConnection(NdefTag tag, String target) {
+ if (tag.mServiceHandle == 0) {
+ throw new IllegalArgumentException("mock tag cannot be used for connections");
+ }
try {
return new NdefTagConnection(mService, tag, target);
} catch (RemoteException e) {
diff --git a/core/java/android/nfc/RawTagConnection.java b/core/java/android/nfc/RawTagConnection.java
index 1261db10a86c..cf8283b762be 100644
--- a/core/java/android/nfc/RawTagConnection.java
+++ b/core/java/android/nfc/RawTagConnection.java
@@ -100,7 +100,7 @@ public class RawTagConnection {
}
try {
- return mTagService.isPresent(mTag.mNativeHandle);
+ return mTagService.isPresent(mTag.mServiceHandle);
} catch (RemoteException e) {
Log.e(TAG, "NFC service died", e);
return false;
@@ -135,7 +135,7 @@ public class RawTagConnection {
public void close() {
mIsConnected = false;
try {
- mTagService.close(mTag.mNativeHandle);
+ mTagService.close(mTag.mServiceHandle);
} catch (RemoteException e) {
Log.e(TAG, "NFC service died", e);
}
@@ -154,7 +154,7 @@ public class RawTagConnection {
*/
public byte[] transceive(byte[] data) throws IOException {
try {
- byte[] response = mTagService.transceive(mTag.mNativeHandle, data);
+ byte[] response = mTagService.transceive(mTag.mServiceHandle, data);
if (response == null) {
throw new IOException("transcieve failed");
}
diff --git a/core/java/android/nfc/Tag.java b/core/java/android/nfc/Tag.java
index abf02b5024f2..7741ad2ae462 100644
--- a/core/java/android/nfc/Tag.java
+++ b/core/java/android/nfc/Tag.java
@@ -16,8 +16,6 @@
package android.nfc;
-import java.util.HashMap;
-
import android.os.Parcel;
import android.os.Parcelable;
@@ -39,202 +37,168 @@ import android.os.Parcelable;
* range. If it is removed and then returned to range, then the most recent
* {@link Tag} object (in {@link NfcAdapter#ACTION_TAG_DISCOVERED}) should be used to create a
* {@link RawTagConnection}.
- * <p>This is an immutable data class.
+ * <p>This is an immutable data class. All properties are set at Tag discovery
+ * time and calls on this class will retrieve those read-only properties, and
+ * not cause any further RF activity or block. Note however that arrays passed to and
+ * returned by this class are *not* cloned, so be careful not to modify them.
*/
public class Tag implements Parcelable {
-
- /**
- * @hide
- */
- public static final int NFC_TAG_ISO14443_A = 1; /* phNfc_eISO14443_A_PICC */
-
- /**
- * @hide
- */
- public static final int NFC_TAG_ISO14443_4A = 2; /* phNfc_eISO14443_4A_PICC */
-
- /**
- * @hide
- */
- public static final int NFC_TAG_ISO14443_3A = 3; /* phNfc_eISO14443_3A_PICC */
-
- /**
- * @hide
- */
- public static final int NFC_TAG_MIFARE = 4; /* phNfc_eMifare_PICC */
-
- /**
- * @hide
- */
- public static final int NFC_TAG_ISO14443_B = 5; /* phNfc_eISO14443_B_PICC */
-
/**
- * @hide
+ * ISO 14443-3A technology.
+ * <p>
+ * Includes Topaz (which is -3A compatible)
*/
- public static final int NFC_TAG_ISO14443_4B = 6; /* phNfc_eISO14443_4B_PICC */
+ public static final String TARGET_ISO_14443_3A = "iso14443_3a";
/**
- * @hide
+ * ISO 14443-3B technology.
*/
- public static final int NFC_TAG_ISO14443_B_PRIME = 7; /* phNfc_eISO14443_BPrime_PICC */
+ public static final String TARGET_ISO_14443_3B = "iso14443_3b";
/**
- * @hide
+ * ISO 14443-4 technology.
*/
- public static final int NFC_TAG_FELICA = 8; /* phNfc_eFelica_PICC */
+ public static final String TARGET_ISO_14443_4 = "iso14443_4";
/**
- * @hide
+ * ISO 15693 technology, commonly known as RFID.
*/
- public static final int NFC_TAG_JEWEL = 9; /* phNfc_eJewel_PICC */
+ public static final String TARGET_ISO_15693 = "iso15693";
/**
- * @hide
+ * JIS X-6319-4 technology, commonly known as Felica.
*/
- public static final int NFC_TAG_ISO15693 = 10; /* phNfc_eISO15693_PICC */
+ public static final String TARGET_JIS_X_6319_4 = "jis_x_6319_4";
/**
- * @hide
+ * Any other technology.
*/
- public static final int NFC_TAG_OTHER = 11; /* phNfc_ePICC_DevType */
-
-
- public static final String TARGET_ISO_14443_3A = "iso14443_3a";
-
- public static final String TARGET_ISO_14443_3B = "iso14443_3b";
-
- public static final String TARGET_ISO_14443_3B_PRIME = "iso14443_3b";
-
- public static final String TARGET_ISO_14443_4 = "iso14443_4";
-
- public static final String TARGET_ISO_15693 = "iso15693";
-
- public static final String TARGET_JIS_X_6319_4 = "jis_x_6319_4";
-
- public static final String TARGET_TOPAZ = "topaz";
-
public static final String TARGET_OTHER = "other";
- /*package*/ final String mTypeName;
/*package*/ final boolean mIsNdef;
- /*package*/ final byte[] mUid;
- /*package*/ final int mNativeHandle;
-
- /*package*/ static final String INTERNAL_TARGET_TYPE_ISO14443_3A = "Iso14443-3A";
- /*package*/ static final String INTERNAL_TARGET_TYPE_ISO14443_3B = "Iso14443-3B";
- /*package*/ static final String INTERNAL_TARGET_TYPE_ISO14443_4 = "Iso14443-4";
- /*package*/ static final String INTERNAL_TARGET_TYPE_MIFARE_UL = "MifareUL";
- /*package*/ static final String INTERNAL_TARGET_TYPE_MIFARE_1K = "Mifare1K";
- /*package*/ static final String INTERNAL_TARGET_TYPE_MIFARE_4K = "Mifare4K";
- /*package*/ static final String INTERNAL_TARGET_TYPE_MIFARE_DESFIRE = "MifareDESFIRE";
- /*package*/ static final String INTERNAL_TARGET_TYPE_MIFARE_UNKNOWN = "Unknown Mifare";
- /*package*/ static final String INTERNAL_TARGET_TYPE_FELICA = "Felica";
- /*package*/ static final String INTERNAL_TARGET_TYPE_JEWEL = "Jewel";
- /*package*/ static final String INTERNAL_TARGET_TYPE_UNKNOWN = "Unknown Type";
-
- private static final HashMap<String, Integer> INT_TYPES_CONVERTION_TABLE = new HashMap<String, Integer>() {
- {
- put(Tag.INTERNAL_TARGET_TYPE_ISO14443_3A, Tag.NFC_TAG_ISO14443_A );
- put(Tag.INTERNAL_TARGET_TYPE_ISO14443_3B, Tag.NFC_TAG_ISO14443_B );
- put(Tag.INTERNAL_TARGET_TYPE_MIFARE_UL, Tag.NFC_TAG_MIFARE );
- put(Tag.INTERNAL_TARGET_TYPE_MIFARE_1K, Tag.NFC_TAG_MIFARE );
- put(Tag.INTERNAL_TARGET_TYPE_MIFARE_4K, Tag.NFC_TAG_MIFARE );
- put(Tag.INTERNAL_TARGET_TYPE_MIFARE_DESFIRE, Tag.NFC_TAG_MIFARE );
- put(Tag.INTERNAL_TARGET_TYPE_FELICA, Tag.NFC_TAG_FELICA );
- put(Tag.INTERNAL_TARGET_TYPE_JEWEL, Tag.NFC_TAG_JEWEL );
- }
- };
-
- private int convertToInt(String internalTypeName) {
- Integer result = INT_TYPES_CONVERTION_TABLE.get(internalTypeName);
- if (result == null) {
- return Tag.NFC_TAG_OTHER;
- }
- return result;
- }
-
- private static final HashMap<String, String[]> RAW_TYPES_CONVERTION_TABLE = new HashMap<String, String[]>() {
- {
- /* TODO: handle multiprotocol */
- put(Tag.INTERNAL_TARGET_TYPE_ISO14443_3A, new String[] { Tag.TARGET_ISO_14443_3A });
- put(Tag.INTERNAL_TARGET_TYPE_ISO14443_3B, new String[] { Tag.TARGET_ISO_14443_3B });
- put(Tag.INTERNAL_TARGET_TYPE_MIFARE_UL, new String[] { Tag.TARGET_ISO_14443_3A });
- put(Tag.INTERNAL_TARGET_TYPE_MIFARE_1K, new String[] { Tag.TARGET_ISO_14443_3A });
- put(Tag.INTERNAL_TARGET_TYPE_MIFARE_4K, new String[] { Tag.TARGET_ISO_14443_3A });
- put(Tag.INTERNAL_TARGET_TYPE_MIFARE_DESFIRE, new String[] { Tag.TARGET_ISO_14443_3A });
- put(Tag.INTERNAL_TARGET_TYPE_MIFARE_UNKNOWN, new String[] { Tag.TARGET_ISO_14443_3A });
- put(Tag.INTERNAL_TARGET_TYPE_FELICA, new String[] { Tag.TARGET_JIS_X_6319_4 });
- put(Tag.INTERNAL_TARGET_TYPE_JEWEL, new String[] { Tag.TARGET_TOPAZ });
- }
- };
-
- private String[] convertToRaw(String internalTypeName) {
- String[] result = RAW_TYPES_CONVERTION_TABLE.get(internalTypeName);
- if (result == null) {
- return new String[] { Tag.TARGET_OTHER };
- }
- return result;
- }
+ /*package*/ final byte[] mId;
+ /*package*/ final String[] mRawTargets;
+ /*package*/ final byte[] mPollBytes;
+ /*package*/ final byte[] mActivationBytes;
+ /*package*/ final int mServiceHandle; // for use by NFC service, 0 indicates a mock
/**
- * Hidden constructor to be used by NFC service only.
+ * Hidden constructor to be used by NFC service and internal classes.
* @hide
*/
- public Tag(String typeName, boolean isNdef, byte[] uid, int nativeHandle) {
- mTypeName = typeName;
+ public Tag(byte[] id, boolean isNdef, String[] rawTargets, byte[] pollBytes,
+ byte[] activationBytes, int serviceHandle) {
+ if (rawTargets == null) {
+ throw new IllegalArgumentException("rawTargets cannot be null");
+ }
mIsNdef = isNdef;
- mUid = uid.clone();
- mNativeHandle = nativeHandle;
+ mId = id;
+ mRawTargets = rawTargets;
+ mPollBytes = pollBytes;
+ mActivationBytes = activationBytes;
+ mServiceHandle = serviceHandle;
+ }
+
+ /**
+ * Construct a mock Tag.
+ * <p>This is an application constructed tag, so NfcAdapter methods on this
+ * Tag such as {@link NfcAdapter#createRawTagConnection} will fail with
+ * {@link IllegalArgumentException} since it does not represent a physical Tag.
+ * <p>This constructor might be useful for mock testing.
+ * @param id The tag identifier, can be null
+ * @param rawTargets must not be null
+ * @param pollBytes can be null
+ * @param activationBytes can be null
+ * @return freshly constructed tag
+ */
+ public static Tag createMockTag(byte[] id, String[] rawTargets, byte[] pollBytes,
+ byte[] activationBytes) {
+ // set serviceHandle to 0 to indicate mock tag
+ return new Tag(id, false, rawTargets, pollBytes, activationBytes, 0);
}
/**
* For use by NfcService only.
* @hide
*/
- public int getHandle() {
- return mNativeHandle;
+ public int getServiceHandle() {
+ return mServiceHandle;
}
/**
* Return the available targets that this NFC adapter can use to create
* a RawTagConnection.
*
- * @return
+ * @return raw targets, will not be null
*/
public String[] getRawTargets() {
- return convertToRaw(mTypeName);
+ return mRawTargets;
}
/**
- * Get the Tag type.
- * <p>
- * The Tag type is one of the NFC_TAG constants. It is read at discovery
- * time and this method does not cause any further RF activity and does not
- * block.
+ * Get the Tag Identifier (if it has one).
+ * <p>Tag ID is usually a serial number for the tag.
*
- * @return a NFC_TAG constant
- * @hide
+ * @return ID, or null if it does not exist
+ */
+ public byte[] getId() {
+ return mId;
+ }
+
+ /**
+ * Get the low-level bytes returned by this Tag at poll-time.
+ * <p>These can be used to help with advanced identification of a Tag.
+ * <p>The meaning of these bytes depends on the Tag technology.
+ * @return poll bytes, or null if they do not exist for this Tag technology
*/
- public int getType() {
- return convertToInt(mTypeName);
+ public byte[] getPollBytes() {
+ return mPollBytes;
}
/**
- * Get the Tag Identifier (if it has one).
- * <p>
- * Tag ID is usually a serial number for the tag.
- * <p>
- * The Tag ID is read at discovery time and this method does not cause any
- * further RF activity and does not block.
- *
- * @return ID, or null if it does not exist
+ * Get the low-level bytes returned by this Tag at activation-time.
+ * <p>These can be used to help with advanced identification of a Tag.
+ * <p>The meaning of these bytes depends on the Tag technology.
+ * @return activation bytes, or null if they do not exist for this Tag technology
*/
- public byte[] getId() {
- if (mUid.length > 0) {
- return mUid.clone();
- } else {
- return null;
+ public byte[] getActivationBytes() {
+ return mActivationBytes;
+ }
+
+ @Override
+ public String toString() {
+ StringBuilder sb = new StringBuilder("TAG ")
+ .append("uid = ")
+ .append(mId)
+ .append(" poll ")
+ .append(mPollBytes)
+ .append(" activation ")
+ .append(mActivationBytes)
+ .append(" Raw [");
+ for (String s : mRawTargets) {
+ sb.append(s)
+ .append(", ");
+ }
+ return sb.toString();
+ }
+
+ /*package*/ static byte[] readBytesWithNull(Parcel in) {
+ int len = in.readInt();
+ byte[] result = null;
+ if (len > 0) {
+ result = new byte[len];
+ in.readByteArray(result);
}
+ return result;
+ }
+
+ /*package*/ static void writeBytesWithNull(Parcel out, byte[] b) {
+ if (b == null) {
+ out.writeInt(-1);
+ return;
+ }
+ out.writeInt(b.length);
+ out.writeByteArray(b);
}
@Override
@@ -242,29 +206,34 @@ public class Tag implements Parcelable {
return 0;
}
+
@Override
public void writeToParcel(Parcel dest, int flags) {
- boolean[] booleans = new boolean[] {mIsNdef};
- dest.writeString(mTypeName);
- dest.writeBooleanArray(booleans);
- dest.writeInt(mUid.length);
- dest.writeByteArray(mUid);
- dest.writeInt(mNativeHandle);
+ dest.writeInt(mIsNdef ? 1 : 0);
+ writeBytesWithNull(dest, mId);
+ dest.writeInt(mRawTargets.length);
+ dest.writeStringArray(mRawTargets);
+ writeBytesWithNull(dest, mPollBytes);
+ writeBytesWithNull(dest, mActivationBytes);
+ dest.writeInt(mServiceHandle);
}
public static final Parcelable.Creator<Tag> CREATOR =
new Parcelable.Creator<Tag>() {
public Tag createFromParcel(Parcel in) {
- boolean[] booleans = new boolean[1];
- String type = in.readString();
- in.readBooleanArray(booleans);
- boolean isNdef = booleans[0];
- int uidLength = in.readInt();
- byte[] uid = new byte[uidLength];
- in.readByteArray(uid);
- int nativeHandle = in.readInt();
-
- return new Tag(type, isNdef, uid, nativeHandle);
+ boolean isNdef = (in.readInt() == 1);
+ if (isNdef) {
+ throw new IllegalArgumentException("Creating Tag from NdefTag parcel");
+ }
+ // Tag fields
+ byte[] id = Tag.readBytesWithNull(in);
+ String[] rawTargets = new String[in.readInt()];
+ in.readStringArray(rawTargets);
+ byte[] pollBytes = Tag.readBytesWithNull(in);
+ byte[] activationBytes = Tag.readBytesWithNull(in);
+ int serviceHandle = in.readInt();
+
+ return new Tag(id, isNdef, rawTargets, pollBytes, activationBytes, serviceHandle);
}
public Tag[] newArray(int size) {
return new Tag[size];