diff --git a/api/current.xml b/api/current.xml index 8aba74af27cfa..c91c2b5e469b8 100644 --- a/api/current.xml +++ b/api/current.xml @@ -100172,6 +100172,29 @@ > + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - {@link NfcAdapter#createNdefTagConnection createNdefTagConnection()} can be used to modify the * contents of some tags. - *

This is an immutable data class. + *

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. + *

This is based on Jewel/Topaz technology + */ + public static final String TARGET_TYPE_1 = "type_1"; /** - * Hidden constructor to be used by NFC service when a - * tag is discovered and by Parcelable methods. + * Target for NFC Forum Type 2 compliant tag. + *

This is based on Mifare Ultralight technology. + */ + public static final String TARGET_TYPE_2 = "type_2"; + + /** + * Target for NFC Forum Type 3 compliant tag. + *

This is based on Felica technology. + */ + public static final String TARGET_TYPE_3 = "type_3"; + + /** + * Target for NFC Forum Type 4 compliant tag. + *

This is based on Mifare Desfire technology. + */ + public static final String TARGET_TYPE_4 = "type_4"; + + /** + * Target for NFC Forum Enabled: Mifare Classic tag. + *

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. + *

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. + *

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 { *

* 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(); + for (int i=0; i NDEF_TYPES_CONVERTION_TABLE = new HashMap() { - { - // 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 }); - } - }; - - 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 CREATOR = new Parcelable.Creator() { 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; iRequires {@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 { *

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 { *

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 { *

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 1261db10a86c5..cf8283b762be4 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 abf02b5024f2b..7741ad2ae462c 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}. - *

This is an immutable data class. + *

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 + * ISO 14443-3A technology. + *

+ * Includes Topaz (which is -3A compatible) */ - 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 - */ - public static final int NFC_TAG_ISO14443_4B = 6; /* phNfc_eISO14443_4B_PICC */ - - /** - * @hide - */ - public static final int NFC_TAG_ISO14443_B_PRIME = 7; /* phNfc_eISO14443_BPrime_PICC */ - - /** - * @hide - */ - public static final int NFC_TAG_FELICA = 8; /* phNfc_eFelica_PICC */ - - /** - * @hide - */ - public static final int NFC_TAG_JEWEL = 9; /* phNfc_eJewel_PICC */ - - /** - * @hide - */ - public static final int NFC_TAG_ISO15693 = 10; /* phNfc_eISO15693_PICC */ - - /** - * @hide - */ - public static final int NFC_TAG_OTHER = 11; /* phNfc_ePICC_DevType */ - - public static final String TARGET_ISO_14443_3A = "iso14443_3a"; + /** + * ISO 14443-3B technology. + */ public static final String TARGET_ISO_14443_3B = "iso14443_3b"; - public static final String TARGET_ISO_14443_3B_PRIME = "iso14443_3b"; - + /** + * ISO 14443-4 technology. + */ public static final String TARGET_ISO_14443_4 = "iso14443_4"; + /** + * ISO 15693 technology, commonly known as RFID. + */ public static final String TARGET_ISO_15693 = "iso15693"; + /** + * JIS X-6319-4 technology, commonly known as Felica. + */ public static final String TARGET_JIS_X_6319_4 = "jis_x_6319_4"; - public static final String TARGET_TOPAZ = "topaz"; - + /** + * Any other technology. + */ 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 INT_TYPES_CONVERTION_TABLE = new HashMap() { - { - 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 RAW_TYPES_CONVERTION_TABLE = new HashMap() { - { - /* 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. + *

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. + *

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); - } - - /** - * Get the Tag type. - *

- * 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. - * - * @return a NFC_TAG constant - * @hide - */ - public int getType() { - return convertToInt(mTypeName); + return mRawTargets; } /** * Get the Tag Identifier (if it has one). - *

- * Tag ID is usually a serial number for the tag. - *

- * The Tag ID is read at discovery time and this method does not cause any - * further RF activity and does not block. + *

Tag ID is usually a serial number for the tag. * * @return ID, or null if it does not exist */ public byte[] getId() { - if (mUid.length > 0) { - return mUid.clone(); - } else { - return null; + return mId; + } + + /** + * Get the low-level bytes returned by this Tag at poll-time. + *

These can be used to help with advanced identification of a Tag. + *

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 byte[] getPollBytes() { + return mPollBytes; + } + + /** + * Get the low-level bytes returned by this Tag at activation-time. + *

These can be used to help with advanced identification of a Tag. + *

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[] 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 CREATOR = new Parcelable.Creator() { 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(); + 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(type, isNdef, uid, nativeHandle); + return new Tag(id, isNdef, rawTargets, pollBytes, activationBytes, serviceHandle); } public Tag[] newArray(int size) { return new Tag[size];