Tag.java revision 07f3bee2db8b6e93ebbf7222676bd9f468e85569
1/*
2 * Copyright (C) 2010 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 *      http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17package android.nfc;
18
19import android.os.Parcel;
20import android.os.Parcelable;
21
22/**
23 * Represents a (generic) discovered tag.
24 * <p>
25 * A tag is a passive NFC element, such as NFC Forum Tag's, Mifare class Tags,
26 * Sony Felica Tags.
27 * <p>
28 * Tag's have a type and usually have a UID.
29 * <p>
30 * {@link Tag} objects are passed to applications via the {@link NfcAdapter#EXTRA_TAG} extra
31 * in {@link NfcAdapter#ACTION_TAG_DISCOVERED} intents. A {@link Tag} object is immutable
32 * and represents the state of the tag at the time of discovery. It can be
33 * directly queried for its UID and Type, or used to create a {@link RawTagConnection}
34 * (with {@link NfcAdapter#createRawTagConnection createRawTagConnection()}).
35 * <p>
36 * A {@link Tag} can  be used to create a {@link RawTagConnection} only while the tag is in
37 * range. If it is removed and then returned to range, then the most recent
38 * {@link Tag} object (in {@link NfcAdapter#ACTION_TAG_DISCOVERED}) should be used to create a
39 * {@link RawTagConnection}.
40 * <p>This is an immutable data class. All properties are set at Tag discovery
41 * time and calls on this class will retrieve those read-only properties, and
42 * not cause any further RF activity or block. Note however that arrays passed to and
43 * returned by this class are *not* cloned, so be careful not to modify them.
44 */
45public class Tag implements Parcelable {
46    /**
47     * ISO 14443-3A technology.
48     * <p>
49     * Includes Topaz (which is -3A compatible)
50     */
51    public static final String TARGET_ISO_14443_3A = "iso14443_3a";
52
53    /**
54     * ISO 14443-3B technology.
55     */
56    public static final String TARGET_ISO_14443_3B = "iso14443_3b";
57
58    /**
59     * ISO 14443-4 technology.
60     */
61    public static final String TARGET_ISO_14443_4 = "iso14443_4";
62
63    /**
64     * ISO 15693 technology, commonly known as RFID.
65     */
66    public static final String TARGET_ISO_15693 = "iso15693";
67
68    /**
69     * JIS X-6319-4 technology, commonly known as Felica.
70     */
71    public static final String TARGET_JIS_X_6319_4 = "jis_x_6319_4";
72
73    /**
74     * Any other technology.
75     */
76    public static final String TARGET_OTHER = "other";
77
78    /*package*/ final boolean mIsNdef;
79    /*package*/ final byte[] mId;
80    /*package*/ final String[] mRawTargets;
81    /*package*/ final byte[] mPollBytes;
82    /*package*/ final byte[] mActivationBytes;
83    /*package*/ final int mServiceHandle;  // for use by NFC service, 0 indicates a mock
84
85    /**
86     * Hidden constructor to be used by NFC service and internal classes.
87     * @hide
88     */
89    public Tag(byte[] id, boolean isNdef, String[] rawTargets, byte[] pollBytes,
90            byte[] activationBytes, int serviceHandle) {
91        if (rawTargets == null) {
92            throw new IllegalArgumentException("rawTargets cannot be null");
93        }
94        mIsNdef = isNdef;
95        mId = id;
96        mRawTargets = rawTargets;
97        mPollBytes = pollBytes;
98        mActivationBytes = activationBytes;
99        mServiceHandle = serviceHandle;
100    }
101
102    /**
103     * Construct a mock Tag.
104     * <p>This is an application constructed tag, so NfcAdapter methods on this
105     * Tag such as {@link NfcAdapter#createRawTagConnection} will fail with
106     * {@link IllegalArgumentException} since it does not represent a physical Tag.
107     * <p>This constructor might be useful for mock testing.
108     * @param id The tag identifier, can be null
109     * @param rawTargets must not be null
110     * @param pollBytes can be null
111     * @param activationBytes can be null
112     * @return freshly constructed tag
113     */
114    public static Tag createMockTag(byte[] id, String[] rawTargets, byte[] pollBytes,
115            byte[] activationBytes) {
116        // set serviceHandle to 0 to indicate mock tag
117        return new Tag(id, false, rawTargets, pollBytes, activationBytes, 0);
118    }
119
120    /**
121     * For use by NfcService only.
122     * @hide
123     */
124    public int getServiceHandle() {
125        return mServiceHandle;
126    }
127
128    /**
129     * Return the available targets that this NFC adapter can use to create
130     * a RawTagConnection.
131     *
132     * @return raw targets, will not be null
133     */
134    public String[] getRawTargets() {
135        return mRawTargets;
136    }
137
138    /**
139     * Get the Tag Identifier (if it has one).
140     * <p>Tag ID is usually a serial number for the tag.
141     *
142     * @return ID, or null if it does not exist
143     */
144    public byte[] getId() {
145        return mId;
146    }
147
148    /**
149     * Get the low-level bytes returned by this Tag at poll-time.
150     * <p>These can be used to help with advanced identification of a Tag.
151     * <p>The meaning of these bytes depends on the Tag technology.
152     * @return poll bytes, or null if they do not exist for this Tag technology
153     */
154    public byte[] getPollBytes() {
155        return mPollBytes;
156    }
157
158    /**
159     * Get the low-level bytes returned by this Tag at activation-time.
160     * <p>These can be used to help with advanced identification of a Tag.
161     * <p>The meaning of these bytes depends on the Tag technology.
162     * @return activation bytes, or null if they do not exist for this Tag technology
163     */
164    public byte[] getActivationBytes() {
165        return mActivationBytes;
166    }
167
168    @Override
169    public String toString() {
170        StringBuilder sb = new StringBuilder("TAG ")
171            .append("uid = ")
172            .append(mId)
173            .append(" poll ")
174            .append(mPollBytes)
175            .append(" activation ")
176            .append(mActivationBytes)
177            .append(" Raw [");
178        for (String s : mRawTargets) {
179            sb.append(s)
180            .append(", ");
181        }
182        return sb.toString();
183    }
184
185    /*package*/ static byte[] readBytesWithNull(Parcel in) {
186        int len = in.readInt();
187        byte[] result = null;
188        if (len > 0) {
189            result = new byte[len];
190            in.readByteArray(result);
191        }
192        return result;
193    }
194
195    /*package*/ static void writeBytesWithNull(Parcel out, byte[] b) {
196        if (b == null) {
197            out.writeInt(-1);
198            return;
199        }
200        out.writeInt(b.length);
201        out.writeByteArray(b);
202    }
203
204    @Override
205    public int describeContents() {
206        return 0;
207    }
208
209
210    @Override
211    public void writeToParcel(Parcel dest, int flags) {
212        dest.writeInt(mIsNdef ? 1 : 0);
213        writeBytesWithNull(dest, mId);
214        dest.writeInt(mRawTargets.length);
215        dest.writeStringArray(mRawTargets);
216        writeBytesWithNull(dest, mPollBytes);
217        writeBytesWithNull(dest, mActivationBytes);
218        dest.writeInt(mServiceHandle);
219    }
220
221    public static final Parcelable.Creator<Tag> CREATOR =
222            new Parcelable.Creator<Tag>() {
223        public Tag createFromParcel(Parcel in) {
224            boolean isNdef = (in.readInt() == 1);
225            if (isNdef) {
226                throw new IllegalArgumentException("Creating Tag from NdefTag parcel");
227            }
228            // Tag fields
229            byte[] id = Tag.readBytesWithNull(in);
230            String[] rawTargets = new String[in.readInt()];
231            in.readStringArray(rawTargets);
232            byte[] pollBytes = Tag.readBytesWithNull(in);
233            byte[] activationBytes = Tag.readBytesWithNull(in);
234            int serviceHandle = in.readInt();
235
236            return new Tag(id, isNdef, rawTargets, pollBytes, activationBytes, serviceHandle);
237        }
238        public Tag[] newArray(int size) {
239            return new Tag[size];
240        }
241    };
242}