Tag.java revision 4049f9d00a86f848d42d2429068496b31a6795ad
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.nfc.technology.IsoDep; 20import android.nfc.technology.MifareClassic; 21import android.nfc.technology.MifareUltralight; 22import android.nfc.technology.NfcV; 23import android.nfc.technology.Ndef; 24import android.nfc.technology.NdefFormatable; 25import android.nfc.technology.NfcA; 26import android.nfc.technology.NfcB; 27import android.nfc.technology.NfcF; 28import android.nfc.technology.TagTechnology; 29import android.os.Bundle; 30import android.os.Parcel; 31import android.os.Parcelable; 32import android.os.RemoteException; 33 34import java.util.Arrays; 35 36/** 37 * Represents a (generic) discovered tag. 38 * <p> 39 * A tag is a passive NFC element, such as NFC Forum Tag's, Mifare class Tags, 40 * Sony Felica Tags. 41 * <p> 42 * Tag's have a type and usually have a UID. 43 * <p> 44 * {@link Tag} objects are passed to applications via the {@link NfcAdapter#EXTRA_TAG} extra 45 * in {@link NfcAdapter#ACTION_TAG_DISCOVERED} intents. A {@link Tag} object is immutable 46 * and represents the state of the tag at the time of discovery. It can be 47 * directly queried for its UID and Type, or used to create a {@link TagTechnology} 48 * (with {@link Tag#getTechnology(int)}). 49 * <p> 50 * A {@link Tag} can be used to create a {@link TagTechnology} only while the tag is in 51 * range. If it is removed and then returned to range, then the most recent 52 * {@link Tag} object (in {@link NfcAdapter#ACTION_TAG_DISCOVERED}) should be used to create a 53 * {@link TagTechnology}. 54 * <p>This is an immutable data class. All properties are set at Tag discovery 55 * time and calls on this class will retrieve those read-only properties, and 56 * not cause any further RF activity or block. Note however that arrays passed to and 57 * returned by this class are *not* cloned, so be careful not to modify them. 58 * @hide 59 */ 60public class Tag implements Parcelable { 61 /*package*/ final byte[] mId; 62 /*package*/ final int[] mTechList; 63 /*package*/ final Bundle[] mTechExtras; 64 /*package*/ final int mServiceHandle; // for use by NFC service, 0 indicates a mock 65 66 /*package*/ int mConnectedTechnology; 67 68 /** 69 * Hidden constructor to be used by NFC service and internal classes. 70 * @hide 71 */ 72 public Tag(byte[] id, int[] techList, Bundle[] techListExtras, int serviceHandle) { 73 if (techList == null) { 74 throw new IllegalArgumentException("rawTargets cannot be null"); 75 } 76 mId = id; 77 mTechList = Arrays.copyOf(techList, techList.length); 78 // Ensure mTechExtras is as long as mTechList 79 mTechExtras = Arrays.copyOf(techListExtras, techList.length); 80 mServiceHandle = serviceHandle; 81 82 mConnectedTechnology = -1; 83 } 84 85 /** 86 * Construct a mock Tag. 87 * <p>This is an application constructed tag, so NfcAdapter methods on this 88 * Tag such as {@link #getTechnology} may fail with 89 * {@link IllegalArgumentException} since it does not represent a physical Tag. 90 * <p>This constructor might be useful for mock testing. 91 * @param id The tag identifier, can be null 92 * @param techList must not be null 93 * @return freshly constructed tag 94 */ 95 public static Tag createMockTag(byte[] id, int[] techList, Bundle[] techListExtras) { 96 // set serviceHandle to 0 to indicate mock tag 97 return new Tag(id, techList, techListExtras, 0); 98 } 99 100 /** 101 * For use by NfcService only. 102 * @hide 103 */ 104 public int getServiceHandle() { 105 return mServiceHandle; 106 } 107 108 /** 109 * Get the Tag Identifier (if it has one). 110 * <p>Tag ID is usually a serial number for the tag. 111 * 112 * @return ID, or null if it does not exist 113 */ 114 public byte[] getId() { 115 return mId; 116 } 117 118 /** 119 * Returns technologies present in the tag that this implementation understands, 120 * or a zero length array if there are no supported technologies on this tag. 121 * 122 * The elements of the list are guaranteed be one of the constants defined in 123 * {@link TagTechnology}. 124 * 125 * The ordering of the returned array is undefined and should not be relied upon. 126 */ 127 public int[] getTechnologyList() { 128 return Arrays.copyOf(mTechList, mTechList.length); 129 } 130 131 /** 132 * Returns the technology, or null if not present 133 */ 134 public TagTechnology getTechnology(NfcAdapter adapter, int tech) { 135 int pos = -1; 136 for (int idx = 0; idx < mTechList.length; idx++) { 137 if (mTechList[idx] == tech) { 138 pos = idx; 139 break; 140 } 141 } 142 if (pos < 0) { 143 return null; 144 } 145 146 Bundle extras = mTechExtras[pos]; 147 try { 148 switch (tech) { 149 case TagTechnology.NFC_A: { 150 return new NfcA(adapter, this, extras); 151 } 152 case TagTechnology.NFC_B: { 153 return new NfcB(adapter, this, extras); 154 } 155 case TagTechnology.ISO_DEP: { 156 return new IsoDep(adapter, this, extras); 157 } 158 case TagTechnology.NFC_V: { 159 return new NfcV(adapter, this, extras); 160 } 161 case TagTechnology.NDEF: { 162 return new Ndef(adapter, this, tech, extras); 163 } 164 case TagTechnology.NDEF_FORMATABLE: { 165 return new NdefFormatable(adapter, this, tech, extras); 166 } 167 case TagTechnology.NFC_F: { 168 return new NfcF(adapter, this, extras); 169 } 170 case TagTechnology.MIFARE_CLASSIC: { 171 return new MifareClassic(adapter, this, extras); 172 } 173 case TagTechnology.MIFARE_ULTRALIGHT: { 174 return new MifareUltralight(adapter, this, extras); 175 } 176 177 default: { 178 throw new UnsupportedOperationException("Tech " + tech + " not supported"); 179 } 180 } 181 } catch (RemoteException e) { 182 return null; 183 } 184 } 185 186 @Override 187 public String toString() { 188 StringBuilder sb = new StringBuilder("TAG ") 189 .append("uid = ") 190 .append(mId) 191 .append(" Tech ["); 192 for (int i : mTechList) { 193 sb.append(i) 194 .append(", "); 195 } 196 return sb.toString(); 197 } 198 199 /*package*/ static byte[] readBytesWithNull(Parcel in) { 200 int len = in.readInt(); 201 byte[] result = null; 202 if (len >= 0) { 203 result = new byte[len]; 204 in.readByteArray(result); 205 } 206 return result; 207 } 208 209 /*package*/ static void writeBytesWithNull(Parcel out, byte[] b) { 210 if (b == null) { 211 out.writeInt(-1); 212 return; 213 } 214 out.writeInt(b.length); 215 out.writeByteArray(b); 216 } 217 218 @Override 219 public int describeContents() { 220 return 0; 221 } 222 223 @Override 224 public void writeToParcel(Parcel dest, int flags) { 225 writeBytesWithNull(dest, mId); 226 dest.writeInt(mTechList.length); 227 dest.writeIntArray(mTechList); 228 dest.writeTypedArray(mTechExtras, 0); 229 dest.writeInt(mServiceHandle); 230 } 231 232 public static final Parcelable.Creator<Tag> CREATOR = 233 new Parcelable.Creator<Tag>() { 234 @Override 235 public Tag createFromParcel(Parcel in) { 236 // Tag fields 237 byte[] id = Tag.readBytesWithNull(in); 238 int[] techList = new int[in.readInt()]; 239 in.readIntArray(techList); 240 Bundle[] techExtras = in.createTypedArray(Bundle.CREATOR); 241 int serviceHandle = in.readInt(); 242 243 return new Tag(id, techList, techExtras, serviceHandle); 244 } 245 246 @Override 247 public Tag[] newArray(int size) { 248 return new Tag[size]; 249 } 250 }; 251 252 /* 253 * @hide 254 */ 255 public synchronized void setConnectedTechnology(int technology) { 256 if (mConnectedTechnology == -1) { 257 mConnectedTechnology = technology; 258 } else { 259 throw new IllegalStateException("Close other technology first!"); 260 } 261 } 262 263 /* 264 * @hide 265 */ 266 public int getConnectedTechnology() { 267 return mConnectedTechnology; 268 } 269 270 /* 271 * @hide 272 */ 273 public void setTechnologyDisconnected() { 274 mConnectedTechnology = -1; 275 } 276} 277