Nick Pelly | 590b73b | 2010-10-12 13:00:50 -0700 | [diff] [blame] | 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 | |
| 17 | package android.nfc; |
| 18 | |
Nick Pelly | 74fe6c6 | 2011-02-02 22:37:40 -0800 | [diff] [blame] | 19 | import android.content.Context; |
Jeff Hamilton | d88e9aa | 2011-01-24 14:53:00 -0600 | [diff] [blame] | 20 | import android.nfc.tech.IsoDep; |
| 21 | import android.nfc.tech.MifareClassic; |
| 22 | import android.nfc.tech.MifareUltralight; |
| 23 | import android.nfc.tech.Ndef; |
| 24 | import android.nfc.tech.NdefFormatable; |
| 25 | import android.nfc.tech.NfcA; |
| 26 | import android.nfc.tech.NfcB; |
Martijn Coenen | ca0cf4e | 2012-09-24 16:38:57 -0700 | [diff] [blame] | 27 | import android.nfc.tech.NfcBarcode; |
Jeff Hamilton | d88e9aa | 2011-01-24 14:53:00 -0600 | [diff] [blame] | 28 | import android.nfc.tech.NfcF; |
| 29 | import android.nfc.tech.NfcV; |
Jeff Hamilton | 4e21e1d | 2011-01-21 01:13:06 -0600 | [diff] [blame] | 30 | import android.nfc.tech.TagTechnology; |
Jeff Hamilton | 6be655c | 2010-11-12 12:28:16 -0600 | [diff] [blame] | 31 | import android.os.Bundle; |
Nick Pelly | 590b73b | 2010-10-12 13:00:50 -0700 | [diff] [blame] | 32 | import android.os.Parcel; |
| 33 | import android.os.Parcelable; |
Martijn Coenen | 2dcae567 | 2011-06-02 16:02:00 -0700 | [diff] [blame] | 34 | import android.os.RemoteException; |
Jeff Hamilton | 6be655c | 2010-11-12 12:28:16 -0600 | [diff] [blame] | 35 | |
Martijn Coenen | 2dcae567 | 2011-06-02 16:02:00 -0700 | [diff] [blame] | 36 | import java.io.IOException; |
Jeff Hamilton | 6be655c | 2010-11-12 12:28:16 -0600 | [diff] [blame] | 37 | import java.util.Arrays; |
Nick Pelly | 590b73b | 2010-10-12 13:00:50 -0700 | [diff] [blame] | 38 | |
| 39 | /** |
Nick Pelly | 74fe6c6 | 2011-02-02 22:37:40 -0800 | [diff] [blame] | 40 | * Represents an NFC tag that has been discovered. |
Nick Pelly | 590b73b | 2010-10-12 13:00:50 -0700 | [diff] [blame] | 41 | * <p> |
Nick Pelly | 74fe6c6 | 2011-02-02 22:37:40 -0800 | [diff] [blame] | 42 | * {@link Tag} is an immutable object that represents the state of a NFC tag at |
| 43 | * the time of discovery. It can be used as a handle to {@link TagTechnology} classes |
Jeff Hamilton | 28319c0 | 2011-02-09 17:26:47 +0900 | [diff] [blame] | 44 | * to perform advanced operations, or directly queried for its ID via {@link #getId} and the |
| 45 | * set of technologies it contains via {@link #getTechList}. Arrays passed to and |
| 46 | * returned by this class are <em>not</em> cloned, so be careful not to modify them. |
Nick Pelly | 74fe6c6 | 2011-02-02 22:37:40 -0800 | [diff] [blame] | 47 | * <p> |
| 48 | * A new tag object is created every time a tag is discovered (comes into range), even |
| 49 | * if it is the same physical tag. If a tag is removed and then returned into range, then |
| 50 | * only the most recent tag object can be successfully used to create a {@link TagTechnology}. |
| 51 | * |
| 52 | * <h3>Tag Dispatch</h3> |
| 53 | * When a tag is discovered, a {@link Tag} object is created and passed to a |
Jeff Hamilton | 28319c0 | 2011-02-09 17:26:47 +0900 | [diff] [blame] | 54 | * single activity via the {@link NfcAdapter#EXTRA_TAG} extra in an |
| 55 | * {@link android.content.Intent} via {@link Context#startActivity}. A four stage dispatch is used |
| 56 | * to select the |
| 57 | * most appropriate activity to handle the tag. The Android OS executes each stage in order, |
| 58 | * and completes dispatch as soon as a single matching activity is found. If there are multiple |
| 59 | * matching activities found at any one stage then the Android activity chooser dialog is shown |
| 60 | * to allow the user to select the activity to receive the tag. |
| 61 | * |
| 62 | * <p>The Tag dispatch mechanism was designed to give a high probability of dispatching |
| 63 | * a tag to the correct activity without showing the user an activity chooser dialog. |
| 64 | * This is important for NFC interactions because they are very transient -- if a user has to |
| 65 | * move the Android device to choose an application then the connection will likely be broken. |
| 66 | * |
Nick Pelly | 74fe6c6 | 2011-02-02 22:37:40 -0800 | [diff] [blame] | 67 | * <h4>1. Foreground activity dispatch</h4> |
Jeff Hamilton | 28319c0 | 2011-02-09 17:26:47 +0900 | [diff] [blame] | 68 | * A foreground activity that has called |
| 69 | * {@link NfcAdapter#enableForegroundDispatch NfcAdapter.enableForegroundDispatch()} is |
| 70 | * given priority. See the documentation on |
| 71 | * {@link NfcAdapter#enableForegroundDispatch NfcAdapter.enableForegroundDispatch()} for |
Nick Pelly | 74fe6c6 | 2011-02-02 22:37:40 -0800 | [diff] [blame] | 72 | * its usage. |
| 73 | * <h4>2. NDEF data dispatch</h4> |
Jeff Hamilton | 28319c0 | 2011-02-09 17:26:47 +0900 | [diff] [blame] | 74 | * If the tag contains NDEF data the system inspects the first {@link NdefRecord} in the first |
| 75 | * {@link NdefMessage}. If the record is a URI, SmartPoster, or MIME data |
| 76 | * {@link Context#startActivity} is called with {@link NfcAdapter#ACTION_NDEF_DISCOVERED}. For URI |
| 77 | * and SmartPoster records the URI is put into the intent's data field. For MIME records the MIME |
| 78 | * type is put in the intent's type field. This allows activities to register to be launched only |
| 79 | * when data they know how to handle is present on a tag. This is the preferred method of handling |
| 80 | * data on a tag since NDEF data can be stored on many types of tags and doesn't depend on a |
| 81 | * specific tag technology. |
Nick Pelly | 74fe6c6 | 2011-02-02 22:37:40 -0800 | [diff] [blame] | 82 | * See {@link NfcAdapter#ACTION_NDEF_DISCOVERED} for more detail. If the tag does not contain |
Jeff Hamilton | 28319c0 | 2011-02-09 17:26:47 +0900 | [diff] [blame] | 83 | * NDEF data, or if no activity is registered |
| 84 | * for {@link NfcAdapter#ACTION_NDEF_DISCOVERED} with a matching data URI or MIME type then dispatch |
| 85 | * moves to stage 3. |
Nick Pelly | 74fe6c6 | 2011-02-02 22:37:40 -0800 | [diff] [blame] | 86 | * <h4>3. Tag Technology dispatch</h4> |
| 87 | * {@link Context#startActivity} is called with {@link NfcAdapter#ACTION_TECH_DISCOVERED} to |
Jeff Hamilton | 28319c0 | 2011-02-09 17:26:47 +0900 | [diff] [blame] | 88 | * dispatch the tag to an activity that can handle the technologies present on the tag. |
Nick Pelly | 74fe6c6 | 2011-02-02 22:37:40 -0800 | [diff] [blame] | 89 | * Technologies are defined as sub-classes of {@link TagTechnology}, see the package |
Jeff Hamilton | 28319c0 | 2011-02-09 17:26:47 +0900 | [diff] [blame] | 90 | * {@link android.nfc.tech}. The Android OS looks for an activity that can handle one or |
| 91 | * more technologies in the tag. See {@link NfcAdapter#ACTION_TECH_DISCOVERED} for more detail. |
Nick Pelly | 74fe6c6 | 2011-02-02 22:37:40 -0800 | [diff] [blame] | 92 | * <h4>4. Fall-back dispatch</h4> |
Jeff Hamilton | 28319c0 | 2011-02-09 17:26:47 +0900 | [diff] [blame] | 93 | * If no activity has been matched then {@link Context#startActivity} is called with |
Nick Pelly | 74fe6c6 | 2011-02-02 22:37:40 -0800 | [diff] [blame] | 94 | * {@link NfcAdapter#ACTION_TAG_DISCOVERED}. This is intended as a fall-back mechanism. |
| 95 | * See {@link NfcAdapter#ACTION_TAG_DISCOVERED}. |
| 96 | * |
Nick Pelly | 74fe6c6 | 2011-02-02 22:37:40 -0800 | [diff] [blame] | 97 | * <h3>NFC Tag Background</h3> |
| 98 | * An NFC tag is a passive NFC device, powered by the NFC field of this Android device while |
Jeff Hamilton | 28319c0 | 2011-02-09 17:26:47 +0900 | [diff] [blame] | 99 | * it is in range. Tag's can come in many forms, such as stickers, cards, key fobs, or |
Nick Pelly | 74fe6c6 | 2011-02-02 22:37:40 -0800 | [diff] [blame] | 100 | * even embedded in a more sophisticated device. |
| 101 | * <p> |
| 102 | * Tags can have a wide range of capabilities. Simple tags just offer read/write semantics, |
| 103 | * and contain some one time |
| 104 | * programmable areas to make read-only. More complex tags offer math operations |
| 105 | * and per-sector access control and authentication. The most sophisticated tags |
Jeff Hamilton | 28319c0 | 2011-02-09 17:26:47 +0900 | [diff] [blame] | 106 | * contain operating environments allowing complex interactions with the |
| 107 | * code executing on the tag. Use {@link TagTechnology} classes to access a broad |
Nick Pelly | 74fe6c6 | 2011-02-02 22:37:40 -0800 | [diff] [blame] | 108 | * range of capabilities available in NFC tags. |
| 109 | * <p> |
Nick Pelly | 590b73b | 2010-10-12 13:00:50 -0700 | [diff] [blame] | 110 | */ |
Nick Pelly | f003e26 | 2011-01-31 23:27:37 -0800 | [diff] [blame] | 111 | public final class Tag implements Parcelable { |
Nick Pelly | 1f5badc | 2012-01-24 13:22:58 -0800 | [diff] [blame] | 112 | final byte[] mId; |
| 113 | final int[] mTechList; |
| 114 | final String[] mTechStringList; |
| 115 | final Bundle[] mTechExtras; |
| 116 | final int mServiceHandle; // for use by NFC service, 0 indicates a mock |
| 117 | final INfcTag mTagService; // interface to NFC service, will be null if mock tag |
Sylvain Fonteneau | a926540 | 2010-10-15 14:41:22 -0700 | [diff] [blame] | 118 | |
Nick Pelly | 1f5badc | 2012-01-24 13:22:58 -0800 | [diff] [blame] | 119 | int mConnectedTechnology; |
Martijn Coenen | 4049f9d0 | 2010-12-14 16:58:27 +0100 | [diff] [blame] | 120 | |
Nick Pelly | 590b73b | 2010-10-12 13:00:50 -0700 | [diff] [blame] | 121 | /** |
Nick Pelly | 07f3bee | 2010-10-21 21:42:24 -0700 | [diff] [blame] | 122 | * Hidden constructor to be used by NFC service and internal classes. |
Nick Pelly | 590b73b | 2010-10-12 13:00:50 -0700 | [diff] [blame] | 123 | * @hide |
| 124 | */ |
Jeff Hamilton | 4e21e1d | 2011-01-21 01:13:06 -0600 | [diff] [blame] | 125 | public Tag(byte[] id, int[] techList, Bundle[] techListExtras, int serviceHandle, |
| 126 | INfcTag tagService) { |
Jeff Hamilton | 6be655c | 2010-11-12 12:28:16 -0600 | [diff] [blame] | 127 | if (techList == null) { |
Nick Pelly | 07f3bee | 2010-10-21 21:42:24 -0700 | [diff] [blame] | 128 | throw new IllegalArgumentException("rawTargets cannot be null"); |
| 129 | } |
Nick Pelly | 07f3bee | 2010-10-21 21:42:24 -0700 | [diff] [blame] | 130 | mId = id; |
Jeff Hamilton | 6be655c | 2010-11-12 12:28:16 -0600 | [diff] [blame] | 131 | mTechList = Arrays.copyOf(techList, techList.length); |
Jeff Hamilton | d88e9aa | 2011-01-24 14:53:00 -0600 | [diff] [blame] | 132 | mTechStringList = generateTechStringList(techList); |
Jeff Hamilton | 6be655c | 2010-11-12 12:28:16 -0600 | [diff] [blame] | 133 | // Ensure mTechExtras is as long as mTechList |
| 134 | mTechExtras = Arrays.copyOf(techListExtras, techList.length); |
Nick Pelly | 07f3bee | 2010-10-21 21:42:24 -0700 | [diff] [blame] | 135 | mServiceHandle = serviceHandle; |
Jeff Hamilton | 4e21e1d | 2011-01-21 01:13:06 -0600 | [diff] [blame] | 136 | mTagService = tagService; |
Martijn Coenen | 4049f9d0 | 2010-12-14 16:58:27 +0100 | [diff] [blame] | 137 | |
| 138 | mConnectedTechnology = -1; |
Nick Pelly | 07f3bee | 2010-10-21 21:42:24 -0700 | [diff] [blame] | 139 | } |
| 140 | |
| 141 | /** |
| 142 | * Construct a mock Tag. |
Jeff Hamilton | 4e21e1d | 2011-01-21 01:13:06 -0600 | [diff] [blame] | 143 | * <p>This is an application constructed tag, so NfcAdapter methods on this Tag may fail |
| 144 | * with {@link IllegalArgumentException} since it does not represent a physical Tag. |
Nick Pelly | 07f3bee | 2010-10-21 21:42:24 -0700 | [diff] [blame] | 145 | * <p>This constructor might be useful for mock testing. |
| 146 | * @param id The tag identifier, can be null |
Jeff Hamilton | 6be655c | 2010-11-12 12:28:16 -0600 | [diff] [blame] | 147 | * @param techList must not be null |
Nick Pelly | 07f3bee | 2010-10-21 21:42:24 -0700 | [diff] [blame] | 148 | * @return freshly constructed tag |
Nick Pelly | f003e26 | 2011-01-31 23:27:37 -0800 | [diff] [blame] | 149 | * @hide |
Nick Pelly | 07f3bee | 2010-10-21 21:42:24 -0700 | [diff] [blame] | 150 | */ |
Jeff Hamilton | 6be655c | 2010-11-12 12:28:16 -0600 | [diff] [blame] | 151 | public static Tag createMockTag(byte[] id, int[] techList, Bundle[] techListExtras) { |
Martijn Coenen | 23fc93a | 2011-11-28 10:43:14 -0800 | [diff] [blame] | 152 | // set serviceHandle to 0 and tagService to null to indicate mock tag |
Jeff Hamilton | 4e21e1d | 2011-01-21 01:13:06 -0600 | [diff] [blame] | 153 | return new Tag(id, techList, techListExtras, 0, null); |
Nick Pelly | 590b73b | 2010-10-12 13:00:50 -0700 | [diff] [blame] | 154 | } |
| 155 | |
Jeff Hamilton | d88e9aa | 2011-01-24 14:53:00 -0600 | [diff] [blame] | 156 | private String[] generateTechStringList(int[] techList) { |
| 157 | final int size = techList.length; |
| 158 | String[] strings = new String[size]; |
| 159 | for (int i = 0; i < size; i++) { |
| 160 | switch (techList[i]) { |
| 161 | case TagTechnology.ISO_DEP: |
| 162 | strings[i] = IsoDep.class.getName(); |
| 163 | break; |
| 164 | case TagTechnology.MIFARE_CLASSIC: |
| 165 | strings[i] = MifareClassic.class.getName(); |
| 166 | break; |
| 167 | case TagTechnology.MIFARE_ULTRALIGHT: |
| 168 | strings[i] = MifareUltralight.class.getName(); |
| 169 | break; |
| 170 | case TagTechnology.NDEF: |
| 171 | strings[i] = Ndef.class.getName(); |
| 172 | break; |
| 173 | case TagTechnology.NDEF_FORMATABLE: |
| 174 | strings[i] = NdefFormatable.class.getName(); |
| 175 | break; |
| 176 | case TagTechnology.NFC_A: |
| 177 | strings[i] = NfcA.class.getName(); |
| 178 | break; |
| 179 | case TagTechnology.NFC_B: |
| 180 | strings[i] = NfcB.class.getName(); |
| 181 | break; |
| 182 | case TagTechnology.NFC_F: |
| 183 | strings[i] = NfcF.class.getName(); |
| 184 | break; |
| 185 | case TagTechnology.NFC_V: |
| 186 | strings[i] = NfcV.class.getName(); |
| 187 | break; |
Martijn Coenen | ca0cf4e | 2012-09-24 16:38:57 -0700 | [diff] [blame] | 188 | case TagTechnology.NFC_BARCODE: |
| 189 | strings[i] = NfcBarcode.class.getName(); |
| 190 | break; |
Jeff Hamilton | d88e9aa | 2011-01-24 14:53:00 -0600 | [diff] [blame] | 191 | default: |
| 192 | throw new IllegalArgumentException("Unknown tech type " + techList[i]); |
| 193 | } |
| 194 | } |
| 195 | return strings; |
| 196 | } |
| 197 | |
Nick Pelly | 590b73b | 2010-10-12 13:00:50 -0700 | [diff] [blame] | 198 | /** |
| 199 | * For use by NfcService only. |
| 200 | * @hide |
| 201 | */ |
Nick Pelly | 07f3bee | 2010-10-21 21:42:24 -0700 | [diff] [blame] | 202 | public int getServiceHandle() { |
| 203 | return mServiceHandle; |
Nick Pelly | 590b73b | 2010-10-12 13:00:50 -0700 | [diff] [blame] | 204 | } |
| 205 | |
| 206 | /** |
Nick Pelly | 590b73b | 2010-10-12 13:00:50 -0700 | [diff] [blame] | 207 | * Get the Tag Identifier (if it has one). |
Nick Pelly | 74fe6c6 | 2011-02-02 22:37:40 -0800 | [diff] [blame] | 208 | * <p>The tag identifier is a low level serial number, used for anti-collision |
| 209 | * and identification. |
| 210 | * <p> Most tags have a stable unique identifier |
| 211 | * (UID), but some tags will generate a random ID every time they are discovered |
| 212 | * (RID), and there are some tags with no ID at all (the byte array will be zero-sized). |
| 213 | * <p> The size and format of an ID is specific to the RF technology used by the tag. |
| 214 | * <p> This function retrieves the ID as determined at discovery time, and does not |
| 215 | * perform any further RF communication or block. |
| 216 | * @return ID as byte array, never null |
Nick Pelly | 590b73b | 2010-10-12 13:00:50 -0700 | [diff] [blame] | 217 | */ |
| 218 | public byte[] getId() { |
Nick Pelly | 07f3bee | 2010-10-21 21:42:24 -0700 | [diff] [blame] | 219 | return mId; |
| 220 | } |
| 221 | |
| 222 | /** |
Nick Pelly | 74fe6c6 | 2011-02-02 22:37:40 -0800 | [diff] [blame] | 223 | * Get the technologies available in this tag, as fully qualified class names. |
| 224 | * <p> |
| 225 | * A technology is an implementation of the {@link TagTechnology} interface, |
| 226 | * and can be instantiated by calling the static <code>get(Tag)</code> |
| 227 | * method on the implementation with this Tag. The {@link TagTechnology} |
| 228 | * object can then be used to perform advanced, technology-specific operations on a tag. |
| 229 | * <p> |
| 230 | * Android defines a mandatory set of technologies that must be correctly |
| 231 | * enumerated by all Android NFC devices, and an optional |
| 232 | * set of proprietary technologies. |
| 233 | * See {@link TagTechnology} for more details. |
| 234 | * <p> |
Jeff Hamilton | c1576ad | 2010-12-05 21:45:22 -0600 | [diff] [blame] | 235 | * The ordering of the returned array is undefined and should not be relied upon. |
Nick Pelly | 74fe6c6 | 2011-02-02 22:37:40 -0800 | [diff] [blame] | 236 | * @return an array of fully-qualified {@link TagTechnology} class-names. |
Nick Pelly | 07f3bee | 2010-10-21 21:42:24 -0700 | [diff] [blame] | 237 | */ |
Jeff Hamilton | d88e9aa | 2011-01-24 14:53:00 -0600 | [diff] [blame] | 238 | public String[] getTechList() { |
| 239 | return mTechStringList; |
Nick Pelly | 07f3bee | 2010-10-21 21:42:24 -0700 | [diff] [blame] | 240 | } |
| 241 | |
Martijn Coenen | 2dcae567 | 2011-06-02 16:02:00 -0700 | [diff] [blame] | 242 | /** |
| 243 | * Rediscover the technologies available on this tag. |
| 244 | * <p> |
| 245 | * The technologies that are available on a tag may change due to |
| 246 | * operations being performed on a tag. For example, formatting a |
| 247 | * tag as NDEF adds the {@link Ndef} technology. The {@link rediscover} |
| 248 | * method reenumerates the available technologies on the tag |
| 249 | * and returns a new {@link Tag} object containing these technologies. |
| 250 | * <p> |
| 251 | * You may not be connected to any of this {@link Tag}'s technologies |
| 252 | * when calling this method. |
| 253 | * This method guarantees that you will be returned the same Tag |
| 254 | * if it is still in the field. |
| 255 | * <p>May cause RF activity and may block. Must not be called |
| 256 | * from the main application thread. A blocked call will be canceled with |
| 257 | * {@link IOException} by calling {@link #close} from another thread. |
| 258 | * <p>Does not remove power from the RF field, so a tag having a random |
| 259 | * ID should not change its ID. |
| 260 | * @return the rediscovered tag object. |
| 261 | * @throws IOException if the tag cannot be rediscovered |
| 262 | * @hide |
| 263 | */ |
| 264 | // TODO See if we need TagLostException |
| 265 | // TODO Unhide for ICS |
| 266 | // TODO Update documentation to make sure it matches with the final |
| 267 | // implementation. |
| 268 | public Tag rediscover() throws IOException { |
| 269 | if (getConnectedTechnology() != -1) { |
| 270 | throw new IllegalStateException("Close connection to the technology first!"); |
| 271 | } |
| 272 | |
Martijn Coenen | 23fc93a | 2011-11-28 10:43:14 -0800 | [diff] [blame] | 273 | if (mTagService == null) { |
| 274 | throw new IOException("Mock tags don't support this operation."); |
| 275 | } |
Martijn Coenen | 2dcae567 | 2011-06-02 16:02:00 -0700 | [diff] [blame] | 276 | try { |
| 277 | Tag newTag = mTagService.rediscover(getServiceHandle()); |
| 278 | if (newTag != null) { |
| 279 | return newTag; |
| 280 | } else { |
| 281 | throw new IOException("Failed to rediscover tag"); |
| 282 | } |
| 283 | } catch (RemoteException e) { |
| 284 | throw new IOException("NFC service dead"); |
| 285 | } |
| 286 | } |
| 287 | |
| 288 | |
Jeff Hamilton | 4e21e1d | 2011-01-21 01:13:06 -0600 | [diff] [blame] | 289 | /** @hide */ |
| 290 | public boolean hasTech(int techType) { |
| 291 | for (int tech : mTechList) { |
| 292 | if (tech == techType) return true; |
| 293 | } |
| 294 | return false; |
| 295 | } |
Nick Pelly | 74fe6c6 | 2011-02-02 22:37:40 -0800 | [diff] [blame] | 296 | |
Jeff Hamilton | 4e21e1d | 2011-01-21 01:13:06 -0600 | [diff] [blame] | 297 | /** @hide */ |
| 298 | public Bundle getTechExtras(int tech) { |
Martijn Coenen | 1253ebc | 2010-11-24 11:13:57 +0100 | [diff] [blame] | 299 | int pos = -1; |
| 300 | for (int idx = 0; idx < mTechList.length; idx++) { |
| 301 | if (mTechList[idx] == tech) { |
| 302 | pos = idx; |
| 303 | break; |
| 304 | } |
| 305 | } |
Jeff Hamilton | 6be655c | 2010-11-12 12:28:16 -0600 | [diff] [blame] | 306 | if (pos < 0) { |
| 307 | return null; |
| 308 | } |
| 309 | |
Jeff Hamilton | 4e21e1d | 2011-01-21 01:13:06 -0600 | [diff] [blame] | 310 | return mTechExtras[pos]; |
| 311 | } |
Jeff Hamilton | 6be655c | 2010-11-12 12:28:16 -0600 | [diff] [blame] | 312 | |
Jeff Hamilton | 4e21e1d | 2011-01-21 01:13:06 -0600 | [diff] [blame] | 313 | /** @hide */ |
| 314 | public INfcTag getTagService() { |
| 315 | return mTagService; |
Nick Pelly | 07f3bee | 2010-10-21 21:42:24 -0700 | [diff] [blame] | 316 | } |
| 317 | |
Nick Pelly | 74fe6c6 | 2011-02-02 22:37:40 -0800 | [diff] [blame] | 318 | /** |
| 319 | * Human-readable description of the tag, for debugging. |
| 320 | */ |
Nick Pelly | 07f3bee | 2010-10-21 21:42:24 -0700 | [diff] [blame] | 321 | @Override |
| 322 | public String toString() { |
Jeff Hamilton | 8856c42 | 2011-06-30 17:35:05 -0500 | [diff] [blame] | 323 | StringBuilder sb = new StringBuilder("TAG: Tech ["); |
| 324 | String[] techList = getTechList(); |
| 325 | int length = techList.length; |
| 326 | for (int i = 0; i < length; i++) { |
| 327 | sb.append(techList[i]); |
| 328 | if (i < length - 1) { |
| 329 | sb.append(", "); |
| 330 | } |
Nick Pelly | 590b73b | 2010-10-12 13:00:50 -0700 | [diff] [blame] | 331 | } |
Jeff Hamilton | 8856c42 | 2011-06-30 17:35:05 -0500 | [diff] [blame] | 332 | sb.append("]"); |
Nick Pelly | 07f3bee | 2010-10-21 21:42:24 -0700 | [diff] [blame] | 333 | return sb.toString(); |
| 334 | } |
| 335 | |
| 336 | /*package*/ static byte[] readBytesWithNull(Parcel in) { |
| 337 | int len = in.readInt(); |
| 338 | byte[] result = null; |
Sylvain Fonteneau | e2e4ea9 | 2010-10-25 07:28:03 -0700 | [diff] [blame] | 339 | if (len >= 0) { |
Nick Pelly | 07f3bee | 2010-10-21 21:42:24 -0700 | [diff] [blame] | 340 | result = new byte[len]; |
| 341 | in.readByteArray(result); |
| 342 | } |
| 343 | return result; |
| 344 | } |
| 345 | |
| 346 | /*package*/ static void writeBytesWithNull(Parcel out, byte[] b) { |
| 347 | if (b == null) { |
| 348 | out.writeInt(-1); |
| 349 | return; |
| 350 | } |
| 351 | out.writeInt(b.length); |
| 352 | out.writeByteArray(b); |
Nick Pelly | 590b73b | 2010-10-12 13:00:50 -0700 | [diff] [blame] | 353 | } |
| 354 | |
| 355 | @Override |
| 356 | public int describeContents() { |
| 357 | return 0; |
| 358 | } |
| 359 | |
| 360 | @Override |
| 361 | public void writeToParcel(Parcel dest, int flags) { |
Sylvain Fonteneau | c5a418e | 2011-01-24 10:23:43 +0100 | [diff] [blame] | 362 | // Null mTagService means this is a mock tag |
| 363 | int isMock = (mTagService == null)?1:0; |
| 364 | |
Nick Pelly | 07f3bee | 2010-10-21 21:42:24 -0700 | [diff] [blame] | 365 | writeBytesWithNull(dest, mId); |
Jeff Hamilton | 6be655c | 2010-11-12 12:28:16 -0600 | [diff] [blame] | 366 | dest.writeInt(mTechList.length); |
| 367 | dest.writeIntArray(mTechList); |
| 368 | dest.writeTypedArray(mTechExtras, 0); |
Nick Pelly | 07f3bee | 2010-10-21 21:42:24 -0700 | [diff] [blame] | 369 | dest.writeInt(mServiceHandle); |
Sylvain Fonteneau | c5a418e | 2011-01-24 10:23:43 +0100 | [diff] [blame] | 370 | dest.writeInt(isMock); |
| 371 | if (isMock == 0) { |
| 372 | dest.writeStrongBinder(mTagService.asBinder()); |
| 373 | } |
Nick Pelly | 590b73b | 2010-10-12 13:00:50 -0700 | [diff] [blame] | 374 | } |
| 375 | |
| 376 | public static final Parcelable.Creator<Tag> CREATOR = |
| 377 | new Parcelable.Creator<Tag>() { |
Jeff Hamilton | 6be655c | 2010-11-12 12:28:16 -0600 | [diff] [blame] | 378 | @Override |
Nick Pelly | 590b73b | 2010-10-12 13:00:50 -0700 | [diff] [blame] | 379 | public Tag createFromParcel(Parcel in) { |
Sylvain Fonteneau | c5a418e | 2011-01-24 10:23:43 +0100 | [diff] [blame] | 380 | INfcTag tagService; |
| 381 | |
Nick Pelly | 07f3bee | 2010-10-21 21:42:24 -0700 | [diff] [blame] | 382 | // Tag fields |
| 383 | byte[] id = Tag.readBytesWithNull(in); |
Jeff Hamilton | 6be655c | 2010-11-12 12:28:16 -0600 | [diff] [blame] | 384 | int[] techList = new int[in.readInt()]; |
| 385 | in.readIntArray(techList); |
| 386 | Bundle[] techExtras = in.createTypedArray(Bundle.CREATOR); |
Nick Pelly | 07f3bee | 2010-10-21 21:42:24 -0700 | [diff] [blame] | 387 | int serviceHandle = in.readInt(); |
Sylvain Fonteneau | c5a418e | 2011-01-24 10:23:43 +0100 | [diff] [blame] | 388 | int isMock = in.readInt(); |
| 389 | if (isMock == 0) { |
| 390 | tagService = INfcTag.Stub.asInterface(in.readStrongBinder()); |
| 391 | } |
| 392 | else { |
| 393 | tagService = null; |
| 394 | } |
Nick Pelly | 590b73b | 2010-10-12 13:00:50 -0700 | [diff] [blame] | 395 | |
Jeff Hamilton | 4e21e1d | 2011-01-21 01:13:06 -0600 | [diff] [blame] | 396 | return new Tag(id, techList, techExtras, serviceHandle, tagService); |
Nick Pelly | 590b73b | 2010-10-12 13:00:50 -0700 | [diff] [blame] | 397 | } |
Jeff Hamilton | 6be655c | 2010-11-12 12:28:16 -0600 | [diff] [blame] | 398 | |
| 399 | @Override |
Nick Pelly | 590b73b | 2010-10-12 13:00:50 -0700 | [diff] [blame] | 400 | public Tag[] newArray(int size) { |
| 401 | return new Tag[size]; |
| 402 | } |
| 403 | }; |
Martijn Coenen | 4049f9d0 | 2010-12-14 16:58:27 +0100 | [diff] [blame] | 404 | |
Jeff Hamilton | be372d6 | 2010-12-22 19:20:26 -0600 | [diff] [blame] | 405 | /** |
| 406 | * For internal use only. |
| 407 | * |
Martijn Coenen | 4049f9d0 | 2010-12-14 16:58:27 +0100 | [diff] [blame] | 408 | * @hide |
| 409 | */ |
| 410 | public synchronized void setConnectedTechnology(int technology) { |
| 411 | if (mConnectedTechnology == -1) { |
| 412 | mConnectedTechnology = technology; |
| 413 | } else { |
| 414 | throw new IllegalStateException("Close other technology first!"); |
| 415 | } |
| 416 | } |
| 417 | |
Jeff Hamilton | be372d6 | 2010-12-22 19:20:26 -0600 | [diff] [blame] | 418 | /** |
| 419 | * For internal use only. |
| 420 | * |
Martijn Coenen | 4049f9d0 | 2010-12-14 16:58:27 +0100 | [diff] [blame] | 421 | * @hide |
| 422 | */ |
| 423 | public int getConnectedTechnology() { |
| 424 | return mConnectedTechnology; |
| 425 | } |
| 426 | |
Jeff Hamilton | be372d6 | 2010-12-22 19:20:26 -0600 | [diff] [blame] | 427 | /** |
| 428 | * For internal use only. |
| 429 | * |
Martijn Coenen | 4049f9d0 | 2010-12-14 16:58:27 +0100 | [diff] [blame] | 430 | * @hide |
| 431 | */ |
| 432 | public void setTechnologyDisconnected() { |
| 433 | mConnectedTechnology = -1; |
| 434 | } |
Martijn Coenen | 1253ebc | 2010-11-24 11:13:57 +0100 | [diff] [blame] | 435 | } |