Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 1d952ff8 authored by Nick Pelly's avatar Nick Pelly Committed by Android Git Automerger
Browse files

am f5b5d177: am 07f3bee2: Push Tag/NdefTag implementation details into the service.

Merge commit 'f5b5d177'

* commit 'f5b5d177':
  Push Tag/NdefTag implementation details into the service.
parents a139f102 f5b5d177
Loading
Loading
Loading
Loading
+64 −22
Original line number Diff line number Diff line
@@ -112360,6 +112360,29 @@
>
<implements name="android.os.Parcelable">
</implements>
<method name="createMockNdefTag"
 return="android.nfc.NdefTag"
 abstract="false"
 native="false"
 synchronized="false"
 static="true"
 final="false"
 deprecated="not deprecated"
 visibility="public"
>
<parameter name="id" type="byte[]">
</parameter>
<parameter name="rawTargets" type="java.lang.String[]">
</parameter>
<parameter name="pollBytes" type="byte[]">
</parameter>
<parameter name="activationBytes" type="byte[]">
</parameter>
<parameter name="ndefTargets" type="java.lang.String[]">
</parameter>
<parameter name="messages" type="android.nfc.NdefMessage[][]">
</parameter>
</method>
<method name="getNdefMessages"
 return="android.nfc.NdefMessage[]"
 abstract="false"
@@ -112829,6 +112852,25 @@
>
<implements name="android.os.Parcelable">
</implements>
<method name="createMockTag"
 return="android.nfc.Tag"
 abstract="false"
 native="false"
 synchronized="false"
 static="true"
 final="false"
 deprecated="not deprecated"
 visibility="public"
>
<parameter name="id" type="byte[]">
</parameter>
<parameter name="rawTargets" type="java.lang.String[]">
</parameter>
<parameter name="pollBytes" type="byte[]">
</parameter>
<parameter name="activationBytes" type="byte[]">
</parameter>
</method>
<method name="describeContents"
 return="int"
 abstract="false"
@@ -112840,6 +112882,17 @@
 visibility="public"
>
</method>
<method name="getActivationBytes"
 return="byte[]"
 abstract="false"
 native="false"
 synchronized="false"
 static="false"
 final="false"
 deprecated="not deprecated"
 visibility="public"
>
</method>
<method name="getId"
 return="byte[]"
 abstract="false"
@@ -112851,6 +112904,17 @@
 visibility="public"
>
</method>
<method name="getPollBytes"
 return="byte[]"
 abstract="false"
 native="false"
 synchronized="false"
 static="false"
 final="false"
 deprecated="not deprecated"
 visibility="public"
>
</method>
<method name="getRawTargets"
 return="java.lang.String[]"
 abstract="false"
@@ -112909,17 +112973,6 @@
 visibility="public"
>
</field>
<field name="TARGET_ISO_14443_3B_PRIME"
 type="java.lang.String"
 transient="false"
 volatile="false"
 value="&quot;iso14443_3b&quot;"
 static="true"
 final="true"
 deprecated="not deprecated"
 visibility="public"
>
</field>
<field name="TARGET_ISO_14443_4"
 type="java.lang.String"
 transient="false"
@@ -112964,17 +113017,6 @@
 visibility="public"
>
</field>
<field name="TARGET_TOPAZ"
 type="java.lang.String"
 transient="false"
 volatile="false"
 value="&quot;topaz&quot;"
 static="true"
 final="true"
 deprecated="not deprecated"
 visibility="public"
>
</field>
</class>
</package>
<package name="android.opengl"
+149 −58
Original line number Diff line number Diff line
@@ -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();
        for (int i=0; i<mNdefTargets.length; i++) {
            if (target.equals(mNdefTargets[i])) {
                return mMessages[i];
            }
        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 });
        }
    };

    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];
+5 −5
Original line number Diff line number Diff line
@@ -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:
+12 −0
Original line number Diff line number Diff line
@@ -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) {
+3 −3
Original line number Diff line number Diff line
@@ -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");
            }
Loading