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