1590b73bc5b8e5f7b59bff1d9264a52388a5162e6Nick Pelly/*
2590b73bc5b8e5f7b59bff1d9264a52388a5162e6Nick Pelly * Copyright (C) 2010 The Android Open Source Project
3590b73bc5b8e5f7b59bff1d9264a52388a5162e6Nick Pelly *
4590b73bc5b8e5f7b59bff1d9264a52388a5162e6Nick Pelly * Licensed under the Apache License, Version 2.0 (the "License");
5590b73bc5b8e5f7b59bff1d9264a52388a5162e6Nick Pelly * you may not use this file except in compliance with the License.
6590b73bc5b8e5f7b59bff1d9264a52388a5162e6Nick Pelly * You may obtain a copy of the License at
7590b73bc5b8e5f7b59bff1d9264a52388a5162e6Nick Pelly *
8590b73bc5b8e5f7b59bff1d9264a52388a5162e6Nick Pelly *      http://www.apache.org/licenses/LICENSE-2.0
9590b73bc5b8e5f7b59bff1d9264a52388a5162e6Nick Pelly *
10590b73bc5b8e5f7b59bff1d9264a52388a5162e6Nick Pelly * Unless required by applicable law or agreed to in writing, software
11590b73bc5b8e5f7b59bff1d9264a52388a5162e6Nick Pelly * distributed under the License is distributed on an "AS IS" BASIS,
12590b73bc5b8e5f7b59bff1d9264a52388a5162e6Nick Pelly * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13590b73bc5b8e5f7b59bff1d9264a52388a5162e6Nick Pelly * See the License for the specific language governing permissions and
14590b73bc5b8e5f7b59bff1d9264a52388a5162e6Nick Pelly * limitations under the License.
15590b73bc5b8e5f7b59bff1d9264a52388a5162e6Nick Pelly */
16590b73bc5b8e5f7b59bff1d9264a52388a5162e6Nick Pelly
17590b73bc5b8e5f7b59bff1d9264a52388a5162e6Nick Pellypackage android.nfc;
18590b73bc5b8e5f7b59bff1d9264a52388a5162e6Nick Pelly
1974fe6c6b245ebe7d3b3d96962c32980d88dca4f5Nick Pellyimport android.content.Context;
20d88e9aa575eb3a9d20cdb0e8918d54993e1ce1e0Jeff Hamiltonimport android.nfc.tech.IsoDep;
21d88e9aa575eb3a9d20cdb0e8918d54993e1ce1e0Jeff Hamiltonimport android.nfc.tech.MifareClassic;
22d88e9aa575eb3a9d20cdb0e8918d54993e1ce1e0Jeff Hamiltonimport android.nfc.tech.MifareUltralight;
23d88e9aa575eb3a9d20cdb0e8918d54993e1ce1e0Jeff Hamiltonimport android.nfc.tech.Ndef;
24d88e9aa575eb3a9d20cdb0e8918d54993e1ce1e0Jeff Hamiltonimport android.nfc.tech.NdefFormatable;
25d88e9aa575eb3a9d20cdb0e8918d54993e1ce1e0Jeff Hamiltonimport android.nfc.tech.NfcA;
26d88e9aa575eb3a9d20cdb0e8918d54993e1ce1e0Jeff Hamiltonimport android.nfc.tech.NfcB;
27ca0cf4ee782e474961e6de74f6004781773f957cMartijn Coenenimport android.nfc.tech.NfcBarcode;
28d88e9aa575eb3a9d20cdb0e8918d54993e1ce1e0Jeff Hamiltonimport android.nfc.tech.NfcF;
29d88e9aa575eb3a9d20cdb0e8918d54993e1ce1e0Jeff Hamiltonimport android.nfc.tech.NfcV;
304e21e1d21a877cce4db5ec8c5786604cc10f2d7eJeff Hamiltonimport android.nfc.tech.TagTechnology;
316be655c768a82716612c00fdd156254d8dc00f42Jeff Hamiltonimport android.os.Bundle;
32590b73bc5b8e5f7b59bff1d9264a52388a5162e6Nick Pellyimport android.os.Parcel;
33590b73bc5b8e5f7b59bff1d9264a52388a5162e6Nick Pellyimport android.os.Parcelable;
342dcae567ab56285bc70b6857c4f3c87df09641b8Martijn Coenenimport android.os.RemoteException;
356be655c768a82716612c00fdd156254d8dc00f42Jeff Hamilton
362dcae567ab56285bc70b6857c4f3c87df09641b8Martijn Coenenimport java.io.IOException;
376be655c768a82716612c00fdd156254d8dc00f42Jeff Hamiltonimport java.util.Arrays;
38d8cf53f87d1416613aa34cfb28f5042033e3299cAndres Moralesimport java.util.HashMap;
39590b73bc5b8e5f7b59bff1d9264a52388a5162e6Nick Pelly
40590b73bc5b8e5f7b59bff1d9264a52388a5162e6Nick Pelly/**
4174fe6c6b245ebe7d3b3d96962c32980d88dca4f5Nick Pelly * Represents an NFC tag that has been discovered.
42590b73bc5b8e5f7b59bff1d9264a52388a5162e6Nick Pelly * <p>
4374fe6c6b245ebe7d3b3d96962c32980d88dca4f5Nick Pelly * {@link Tag} is an immutable object that represents the state of a NFC tag at
4474fe6c6b245ebe7d3b3d96962c32980d88dca4f5Nick Pelly * the time of discovery. It can be used as a handle to {@link TagTechnology} classes
4528319c0cec94977682db32b949628a8e4b8183dcJeff Hamilton * to perform advanced operations, or directly queried for its ID via {@link #getId} and the
4628319c0cec94977682db32b949628a8e4b8183dcJeff Hamilton * set of technologies it contains via {@link #getTechList}. Arrays passed to and
4728319c0cec94977682db32b949628a8e4b8183dcJeff Hamilton * returned by this class are <em>not</em> cloned, so be careful not to modify them.
48590b73bc5b8e5f7b59bff1d9264a52388a5162e6Nick Pelly * <p>
4974fe6c6b245ebe7d3b3d96962c32980d88dca4f5Nick Pelly * A new tag object is created every time a tag is discovered (comes into range), even
5074fe6c6b245ebe7d3b3d96962c32980d88dca4f5Nick Pelly * if it is the same physical tag. If a tag is removed and then returned into range, then
5174fe6c6b245ebe7d3b3d96962c32980d88dca4f5Nick Pelly * only the most recent tag object can be successfully used to create a {@link TagTechnology}.
5274fe6c6b245ebe7d3b3d96962c32980d88dca4f5Nick Pelly *
5374fe6c6b245ebe7d3b3d96962c32980d88dca4f5Nick Pelly * <h3>Tag Dispatch</h3>
5474fe6c6b245ebe7d3b3d96962c32980d88dca4f5Nick Pelly * When a tag is discovered, a {@link Tag} object is created and passed to a
5528319c0cec94977682db32b949628a8e4b8183dcJeff Hamilton * single activity via the {@link NfcAdapter#EXTRA_TAG} extra in an
5628319c0cec94977682db32b949628a8e4b8183dcJeff Hamilton * {@link android.content.Intent} via {@link Context#startActivity}. A four stage dispatch is used
5728319c0cec94977682db32b949628a8e4b8183dcJeff Hamilton * to select the
5828319c0cec94977682db32b949628a8e4b8183dcJeff Hamilton * most appropriate activity to handle the tag. The Android OS executes each stage in order,
5928319c0cec94977682db32b949628a8e4b8183dcJeff Hamilton * and completes dispatch as soon as a single matching activity is found. If there are multiple
6028319c0cec94977682db32b949628a8e4b8183dcJeff Hamilton * matching activities found at any one stage then the Android activity chooser dialog is shown
6128319c0cec94977682db32b949628a8e4b8183dcJeff Hamilton * to allow the user to select the activity to receive the tag.
6228319c0cec94977682db32b949628a8e4b8183dcJeff Hamilton *
6328319c0cec94977682db32b949628a8e4b8183dcJeff Hamilton * <p>The Tag dispatch mechanism was designed to give a high probability of dispatching
6428319c0cec94977682db32b949628a8e4b8183dcJeff Hamilton * a tag to the correct activity without showing the user an activity chooser dialog.
6528319c0cec94977682db32b949628a8e4b8183dcJeff Hamilton * This is important for NFC interactions because they are very transient -- if a user has to
6628319c0cec94977682db32b949628a8e4b8183dcJeff Hamilton * move the Android device to choose an application then the connection will likely be broken.
6728319c0cec94977682db32b949628a8e4b8183dcJeff Hamilton *
6874fe6c6b245ebe7d3b3d96962c32980d88dca4f5Nick Pelly * <h4>1. Foreground activity dispatch</h4>
6928319c0cec94977682db32b949628a8e4b8183dcJeff Hamilton * A foreground activity that has called
7028319c0cec94977682db32b949628a8e4b8183dcJeff Hamilton * {@link NfcAdapter#enableForegroundDispatch NfcAdapter.enableForegroundDispatch()} is
7128319c0cec94977682db32b949628a8e4b8183dcJeff Hamilton * given priority. See the documentation on
7228319c0cec94977682db32b949628a8e4b8183dcJeff Hamilton * {@link NfcAdapter#enableForegroundDispatch NfcAdapter.enableForegroundDispatch()} for
7374fe6c6b245ebe7d3b3d96962c32980d88dca4f5Nick Pelly * its usage.
7474fe6c6b245ebe7d3b3d96962c32980d88dca4f5Nick Pelly * <h4>2. NDEF data dispatch</h4>
7528319c0cec94977682db32b949628a8e4b8183dcJeff Hamilton * If the tag contains NDEF data the system inspects the first {@link NdefRecord} in the first
7628319c0cec94977682db32b949628a8e4b8183dcJeff Hamilton * {@link NdefMessage}. If the record is a URI, SmartPoster, or MIME data
7728319c0cec94977682db32b949628a8e4b8183dcJeff Hamilton * {@link Context#startActivity} is called with {@link NfcAdapter#ACTION_NDEF_DISCOVERED}. For URI
7828319c0cec94977682db32b949628a8e4b8183dcJeff Hamilton * and SmartPoster records the URI is put into the intent's data field. For MIME records the MIME
7928319c0cec94977682db32b949628a8e4b8183dcJeff Hamilton * type is put in the intent's type field. This allows activities to register to be launched only
8028319c0cec94977682db32b949628a8e4b8183dcJeff Hamilton * when data they know how to handle is present on a tag. This is the preferred method of handling
8128319c0cec94977682db32b949628a8e4b8183dcJeff Hamilton * data on a tag since NDEF data can be stored on many types of tags and doesn't depend on a
8228319c0cec94977682db32b949628a8e4b8183dcJeff Hamilton * specific tag technology.
8374fe6c6b245ebe7d3b3d96962c32980d88dca4f5Nick Pelly * See {@link NfcAdapter#ACTION_NDEF_DISCOVERED} for more detail. If the tag does not contain
8428319c0cec94977682db32b949628a8e4b8183dcJeff Hamilton * NDEF data, or if no activity is registered
8528319c0cec94977682db32b949628a8e4b8183dcJeff Hamilton * for {@link NfcAdapter#ACTION_NDEF_DISCOVERED} with a matching data URI or MIME type then dispatch
8628319c0cec94977682db32b949628a8e4b8183dcJeff Hamilton * moves to stage 3.
8774fe6c6b245ebe7d3b3d96962c32980d88dca4f5Nick Pelly * <h4>3. Tag Technology dispatch</h4>
8874fe6c6b245ebe7d3b3d96962c32980d88dca4f5Nick Pelly * {@link Context#startActivity} is called with {@link NfcAdapter#ACTION_TECH_DISCOVERED} to
8928319c0cec94977682db32b949628a8e4b8183dcJeff Hamilton * dispatch the tag to an activity that can handle the technologies present on the tag.
9074fe6c6b245ebe7d3b3d96962c32980d88dca4f5Nick Pelly * Technologies are defined as sub-classes of {@link TagTechnology}, see the package
9128319c0cec94977682db32b949628a8e4b8183dcJeff Hamilton * {@link android.nfc.tech}. The Android OS looks for an activity that can handle one or
9228319c0cec94977682db32b949628a8e4b8183dcJeff Hamilton * more technologies in the tag. See {@link NfcAdapter#ACTION_TECH_DISCOVERED} for more detail.
9374fe6c6b245ebe7d3b3d96962c32980d88dca4f5Nick Pelly * <h4>4. Fall-back dispatch</h4>
9428319c0cec94977682db32b949628a8e4b8183dcJeff Hamilton * If no activity has been matched then {@link Context#startActivity} is called with
9574fe6c6b245ebe7d3b3d96962c32980d88dca4f5Nick Pelly * {@link NfcAdapter#ACTION_TAG_DISCOVERED}. This is intended as a fall-back mechanism.
9674fe6c6b245ebe7d3b3d96962c32980d88dca4f5Nick Pelly * See {@link NfcAdapter#ACTION_TAG_DISCOVERED}.
9774fe6c6b245ebe7d3b3d96962c32980d88dca4f5Nick Pelly *
9874fe6c6b245ebe7d3b3d96962c32980d88dca4f5Nick Pelly * <h3>NFC Tag Background</h3>
9974fe6c6b245ebe7d3b3d96962c32980d88dca4f5Nick Pelly * An NFC tag is a passive NFC device, powered by the NFC field of this Android device while
10028319c0cec94977682db32b949628a8e4b8183dcJeff Hamilton * it is in range. Tag's can come in many forms, such as stickers, cards, key fobs, or
10174fe6c6b245ebe7d3b3d96962c32980d88dca4f5Nick Pelly * even embedded in a more sophisticated device.
10274fe6c6b245ebe7d3b3d96962c32980d88dca4f5Nick Pelly * <p>
10374fe6c6b245ebe7d3b3d96962c32980d88dca4f5Nick Pelly * Tags can have a wide range of capabilities. Simple tags just offer read/write semantics,
10474fe6c6b245ebe7d3b3d96962c32980d88dca4f5Nick Pelly * and contain some one time
10574fe6c6b245ebe7d3b3d96962c32980d88dca4f5Nick Pelly * programmable areas to make read-only. More complex tags offer math operations
10674fe6c6b245ebe7d3b3d96962c32980d88dca4f5Nick Pelly * and per-sector access control and authentication. The most sophisticated tags
10728319c0cec94977682db32b949628a8e4b8183dcJeff Hamilton * contain operating environments allowing complex interactions with the
10828319c0cec94977682db32b949628a8e4b8183dcJeff Hamilton * code executing on the tag. Use {@link TagTechnology} classes to access a broad
10974fe6c6b245ebe7d3b3d96962c32980d88dca4f5Nick Pelly * range of capabilities available in NFC tags.
110590b73bc5b8e5f7b59bff1d9264a52388a5162e6Nick Pelly * <p>
111590b73bc5b8e5f7b59bff1d9264a52388a5162e6Nick Pelly */
112f003e26df96067b4b136f0859012cb7ec3ed930fNick Pellypublic final class Tag implements Parcelable {
1131f5badc1cb08f10ddf4b09aaaf34060a23999a51Nick Pelly    final byte[] mId;
1141f5badc1cb08f10ddf4b09aaaf34060a23999a51Nick Pelly    final int[] mTechList;
1151f5badc1cb08f10ddf4b09aaaf34060a23999a51Nick Pelly    final String[] mTechStringList;
1161f5badc1cb08f10ddf4b09aaaf34060a23999a51Nick Pelly    final Bundle[] mTechExtras;
1171f5badc1cb08f10ddf4b09aaaf34060a23999a51Nick Pelly    final int mServiceHandle;  // for use by NFC service, 0 indicates a mock
1181f5badc1cb08f10ddf4b09aaaf34060a23999a51Nick Pelly    final INfcTag mTagService; // interface to NFC service, will be null if mock tag
119a926540d5455a973dd8ca19c00c108620d9c68c2Sylvain Fonteneau
1201f5badc1cb08f10ddf4b09aaaf34060a23999a51Nick Pelly    int mConnectedTechnology;
1214049f9d00a86f848d42d2429068496b31a6795adMartijn Coenen
122590b73bc5b8e5f7b59bff1d9264a52388a5162e6Nick Pelly    /**
12307f3bee2db8b6e93ebbf7222676bd9f468e85569Nick Pelly     * Hidden constructor to be used by NFC service and internal classes.
124590b73bc5b8e5f7b59bff1d9264a52388a5162e6Nick Pelly     * @hide
125590b73bc5b8e5f7b59bff1d9264a52388a5162e6Nick Pelly     */
1264e21e1d21a877cce4db5ec8c5786604cc10f2d7eJeff Hamilton    public Tag(byte[] id, int[] techList, Bundle[] techListExtras, int serviceHandle,
1274e21e1d21a877cce4db5ec8c5786604cc10f2d7eJeff Hamilton            INfcTag tagService) {
1286be655c768a82716612c00fdd156254d8dc00f42Jeff Hamilton        if (techList == null) {
12907f3bee2db8b6e93ebbf7222676bd9f468e85569Nick Pelly            throw new IllegalArgumentException("rawTargets cannot be null");
13007f3bee2db8b6e93ebbf7222676bd9f468e85569Nick Pelly        }
13107f3bee2db8b6e93ebbf7222676bd9f468e85569Nick Pelly        mId = id;
1326be655c768a82716612c00fdd156254d8dc00f42Jeff Hamilton        mTechList = Arrays.copyOf(techList, techList.length);
133d88e9aa575eb3a9d20cdb0e8918d54993e1ce1e0Jeff Hamilton        mTechStringList = generateTechStringList(techList);
1346be655c768a82716612c00fdd156254d8dc00f42Jeff Hamilton        // Ensure mTechExtras is as long as mTechList
1356be655c768a82716612c00fdd156254d8dc00f42Jeff Hamilton        mTechExtras = Arrays.copyOf(techListExtras, techList.length);
13607f3bee2db8b6e93ebbf7222676bd9f468e85569Nick Pelly        mServiceHandle = serviceHandle;
1374e21e1d21a877cce4db5ec8c5786604cc10f2d7eJeff Hamilton        mTagService = tagService;
1384049f9d00a86f848d42d2429068496b31a6795adMartijn Coenen
1394049f9d00a86f848d42d2429068496b31a6795adMartijn Coenen        mConnectedTechnology = -1;
14007f3bee2db8b6e93ebbf7222676bd9f468e85569Nick Pelly    }
14107f3bee2db8b6e93ebbf7222676bd9f468e85569Nick Pelly
14207f3bee2db8b6e93ebbf7222676bd9f468e85569Nick Pelly    /**
14307f3bee2db8b6e93ebbf7222676bd9f468e85569Nick Pelly     * Construct a mock Tag.
1444e21e1d21a877cce4db5ec8c5786604cc10f2d7eJeff Hamilton     * <p>This is an application constructed tag, so NfcAdapter methods on this Tag may fail
1454e21e1d21a877cce4db5ec8c5786604cc10f2d7eJeff Hamilton     * with {@link IllegalArgumentException} since it does not represent a physical Tag.
14607f3bee2db8b6e93ebbf7222676bd9f468e85569Nick Pelly     * <p>This constructor might be useful for mock testing.
14707f3bee2db8b6e93ebbf7222676bd9f468e85569Nick Pelly     * @param id The tag identifier, can be null
1486be655c768a82716612c00fdd156254d8dc00f42Jeff Hamilton     * @param techList must not be null
14907f3bee2db8b6e93ebbf7222676bd9f468e85569Nick Pelly     * @return freshly constructed tag
150f003e26df96067b4b136f0859012cb7ec3ed930fNick Pelly     * @hide
15107f3bee2db8b6e93ebbf7222676bd9f468e85569Nick Pelly     */
1526be655c768a82716612c00fdd156254d8dc00f42Jeff Hamilton    public static Tag createMockTag(byte[] id, int[] techList, Bundle[] techListExtras) {
15323fc93a7c1e340e79642d3d0bf4b4658c8645c8eMartijn Coenen        // set serviceHandle to 0 and tagService to null to indicate mock tag
1544e21e1d21a877cce4db5ec8c5786604cc10f2d7eJeff Hamilton        return new Tag(id, techList, techListExtras, 0, null);
155590b73bc5b8e5f7b59bff1d9264a52388a5162e6Nick Pelly    }
156590b73bc5b8e5f7b59bff1d9264a52388a5162e6Nick Pelly
157d88e9aa575eb3a9d20cdb0e8918d54993e1ce1e0Jeff Hamilton    private String[] generateTechStringList(int[] techList) {
158d88e9aa575eb3a9d20cdb0e8918d54993e1ce1e0Jeff Hamilton        final int size = techList.length;
159d88e9aa575eb3a9d20cdb0e8918d54993e1ce1e0Jeff Hamilton        String[] strings = new String[size];
160d88e9aa575eb3a9d20cdb0e8918d54993e1ce1e0Jeff Hamilton        for (int i = 0; i < size; i++) {
161d88e9aa575eb3a9d20cdb0e8918d54993e1ce1e0Jeff Hamilton            switch (techList[i]) {
162d88e9aa575eb3a9d20cdb0e8918d54993e1ce1e0Jeff Hamilton                case TagTechnology.ISO_DEP:
163d88e9aa575eb3a9d20cdb0e8918d54993e1ce1e0Jeff Hamilton                    strings[i] = IsoDep.class.getName();
164d88e9aa575eb3a9d20cdb0e8918d54993e1ce1e0Jeff Hamilton                    break;
165d88e9aa575eb3a9d20cdb0e8918d54993e1ce1e0Jeff Hamilton                case TagTechnology.MIFARE_CLASSIC:
166d88e9aa575eb3a9d20cdb0e8918d54993e1ce1e0Jeff Hamilton                    strings[i] = MifareClassic.class.getName();
167d88e9aa575eb3a9d20cdb0e8918d54993e1ce1e0Jeff Hamilton                    break;
168d88e9aa575eb3a9d20cdb0e8918d54993e1ce1e0Jeff Hamilton                case TagTechnology.MIFARE_ULTRALIGHT:
169d88e9aa575eb3a9d20cdb0e8918d54993e1ce1e0Jeff Hamilton                    strings[i] = MifareUltralight.class.getName();
170d88e9aa575eb3a9d20cdb0e8918d54993e1ce1e0Jeff Hamilton                    break;
171d88e9aa575eb3a9d20cdb0e8918d54993e1ce1e0Jeff Hamilton                case TagTechnology.NDEF:
172d88e9aa575eb3a9d20cdb0e8918d54993e1ce1e0Jeff Hamilton                    strings[i] = Ndef.class.getName();
173d88e9aa575eb3a9d20cdb0e8918d54993e1ce1e0Jeff Hamilton                    break;
174d88e9aa575eb3a9d20cdb0e8918d54993e1ce1e0Jeff Hamilton                case TagTechnology.NDEF_FORMATABLE:
175d88e9aa575eb3a9d20cdb0e8918d54993e1ce1e0Jeff Hamilton                    strings[i] = NdefFormatable.class.getName();
176d88e9aa575eb3a9d20cdb0e8918d54993e1ce1e0Jeff Hamilton                    break;
177d88e9aa575eb3a9d20cdb0e8918d54993e1ce1e0Jeff Hamilton                case TagTechnology.NFC_A:
178d88e9aa575eb3a9d20cdb0e8918d54993e1ce1e0Jeff Hamilton                    strings[i] = NfcA.class.getName();
179d88e9aa575eb3a9d20cdb0e8918d54993e1ce1e0Jeff Hamilton                    break;
180d88e9aa575eb3a9d20cdb0e8918d54993e1ce1e0Jeff Hamilton                case TagTechnology.NFC_B:
181d88e9aa575eb3a9d20cdb0e8918d54993e1ce1e0Jeff Hamilton                    strings[i] = NfcB.class.getName();
182d88e9aa575eb3a9d20cdb0e8918d54993e1ce1e0Jeff Hamilton                    break;
183d88e9aa575eb3a9d20cdb0e8918d54993e1ce1e0Jeff Hamilton                case TagTechnology.NFC_F:
184d88e9aa575eb3a9d20cdb0e8918d54993e1ce1e0Jeff Hamilton                    strings[i] = NfcF.class.getName();
185d88e9aa575eb3a9d20cdb0e8918d54993e1ce1e0Jeff Hamilton                    break;
186d88e9aa575eb3a9d20cdb0e8918d54993e1ce1e0Jeff Hamilton                case TagTechnology.NFC_V:
187d88e9aa575eb3a9d20cdb0e8918d54993e1ce1e0Jeff Hamilton                    strings[i] = NfcV.class.getName();
188d88e9aa575eb3a9d20cdb0e8918d54993e1ce1e0Jeff Hamilton                    break;
189ca0cf4ee782e474961e6de74f6004781773f957cMartijn Coenen                case TagTechnology.NFC_BARCODE:
190ca0cf4ee782e474961e6de74f6004781773f957cMartijn Coenen                    strings[i] = NfcBarcode.class.getName();
191ca0cf4ee782e474961e6de74f6004781773f957cMartijn Coenen                    break;
192d88e9aa575eb3a9d20cdb0e8918d54993e1ce1e0Jeff Hamilton                default:
193d88e9aa575eb3a9d20cdb0e8918d54993e1ce1e0Jeff Hamilton                    throw new IllegalArgumentException("Unknown tech type " + techList[i]);
194d88e9aa575eb3a9d20cdb0e8918d54993e1ce1e0Jeff Hamilton            }
195d88e9aa575eb3a9d20cdb0e8918d54993e1ce1e0Jeff Hamilton        }
196d88e9aa575eb3a9d20cdb0e8918d54993e1ce1e0Jeff Hamilton        return strings;
197d88e9aa575eb3a9d20cdb0e8918d54993e1ce1e0Jeff Hamilton    }
198d88e9aa575eb3a9d20cdb0e8918d54993e1ce1e0Jeff Hamilton
19911d2e53dc0d2682f66f8dcbd8f0ad52432cb4aa7Andres Morales    static int[] getTechCodesFromStrings(String[] techStringList) throws IllegalArgumentException {
200d8cf53f87d1416613aa34cfb28f5042033e3299cAndres Morales        if (techStringList == null) {
201d8cf53f87d1416613aa34cfb28f5042033e3299cAndres Morales            throw new IllegalArgumentException("List cannot be null");
202d8cf53f87d1416613aa34cfb28f5042033e3299cAndres Morales        }
203d8cf53f87d1416613aa34cfb28f5042033e3299cAndres Morales        int[] techIntList = new int[techStringList.length];
204d8cf53f87d1416613aa34cfb28f5042033e3299cAndres Morales        HashMap<String, Integer> stringToCodeMap = getTechStringToCodeMap();
205d8cf53f87d1416613aa34cfb28f5042033e3299cAndres Morales        for (int i = 0; i < techStringList.length; i++) {
206d8cf53f87d1416613aa34cfb28f5042033e3299cAndres Morales            Integer code = stringToCodeMap.get(techStringList[i]);
207d8cf53f87d1416613aa34cfb28f5042033e3299cAndres Morales
208d8cf53f87d1416613aa34cfb28f5042033e3299cAndres Morales            if (code == null) {
209d8cf53f87d1416613aa34cfb28f5042033e3299cAndres Morales                throw new IllegalArgumentException("Unknown tech type " + techStringList[i]);
210d8cf53f87d1416613aa34cfb28f5042033e3299cAndres Morales            }
211d8cf53f87d1416613aa34cfb28f5042033e3299cAndres Morales
212d8cf53f87d1416613aa34cfb28f5042033e3299cAndres Morales            techIntList[i] = code.intValue();
213d8cf53f87d1416613aa34cfb28f5042033e3299cAndres Morales        }
214d8cf53f87d1416613aa34cfb28f5042033e3299cAndres Morales        return techIntList;
215d8cf53f87d1416613aa34cfb28f5042033e3299cAndres Morales    }
216d8cf53f87d1416613aa34cfb28f5042033e3299cAndres Morales
217d8cf53f87d1416613aa34cfb28f5042033e3299cAndres Morales    private static HashMap<String, Integer> getTechStringToCodeMap() {
218d8cf53f87d1416613aa34cfb28f5042033e3299cAndres Morales        HashMap<String, Integer> techStringToCodeMap = new HashMap<String, Integer>();
219d8cf53f87d1416613aa34cfb28f5042033e3299cAndres Morales
220d8cf53f87d1416613aa34cfb28f5042033e3299cAndres Morales        techStringToCodeMap.put(IsoDep.class.getName(), TagTechnology.ISO_DEP);
221d8cf53f87d1416613aa34cfb28f5042033e3299cAndres Morales        techStringToCodeMap.put(MifareClassic.class.getName(), TagTechnology.MIFARE_CLASSIC);
222d8cf53f87d1416613aa34cfb28f5042033e3299cAndres Morales        techStringToCodeMap.put(MifareUltralight.class.getName(), TagTechnology.MIFARE_ULTRALIGHT);
223d8cf53f87d1416613aa34cfb28f5042033e3299cAndres Morales        techStringToCodeMap.put(Ndef.class.getName(), TagTechnology.NDEF);
224d8cf53f87d1416613aa34cfb28f5042033e3299cAndres Morales        techStringToCodeMap.put(NdefFormatable.class.getName(), TagTechnology.NDEF_FORMATABLE);
225d8cf53f87d1416613aa34cfb28f5042033e3299cAndres Morales        techStringToCodeMap.put(NfcA.class.getName(), TagTechnology.NFC_A);
226d8cf53f87d1416613aa34cfb28f5042033e3299cAndres Morales        techStringToCodeMap.put(NfcB.class.getName(), TagTechnology.NFC_B);
227d8cf53f87d1416613aa34cfb28f5042033e3299cAndres Morales        techStringToCodeMap.put(NfcF.class.getName(), TagTechnology.NFC_F);
228d8cf53f87d1416613aa34cfb28f5042033e3299cAndres Morales        techStringToCodeMap.put(NfcV.class.getName(), TagTechnology.NFC_V);
229d8cf53f87d1416613aa34cfb28f5042033e3299cAndres Morales        techStringToCodeMap.put(NfcBarcode.class.getName(), TagTechnology.NFC_BARCODE);
230d8cf53f87d1416613aa34cfb28f5042033e3299cAndres Morales
231d8cf53f87d1416613aa34cfb28f5042033e3299cAndres Morales        return techStringToCodeMap;
232d8cf53f87d1416613aa34cfb28f5042033e3299cAndres Morales    }
233d8cf53f87d1416613aa34cfb28f5042033e3299cAndres Morales
234590b73bc5b8e5f7b59bff1d9264a52388a5162e6Nick Pelly    /**
235590b73bc5b8e5f7b59bff1d9264a52388a5162e6Nick Pelly     * For use by NfcService only.
236590b73bc5b8e5f7b59bff1d9264a52388a5162e6Nick Pelly     * @hide
237590b73bc5b8e5f7b59bff1d9264a52388a5162e6Nick Pelly     */
23807f3bee2db8b6e93ebbf7222676bd9f468e85569Nick Pelly    public int getServiceHandle() {
23907f3bee2db8b6e93ebbf7222676bd9f468e85569Nick Pelly        return mServiceHandle;
240590b73bc5b8e5f7b59bff1d9264a52388a5162e6Nick Pelly    }
241590b73bc5b8e5f7b59bff1d9264a52388a5162e6Nick Pelly
242590b73bc5b8e5f7b59bff1d9264a52388a5162e6Nick Pelly    /**
2433e4b665bc607c81ccc018d753122a363dd95159bAndres Morales     * For use by NfcService only.
2443e4b665bc607c81ccc018d753122a363dd95159bAndres Morales     * @hide
2453e4b665bc607c81ccc018d753122a363dd95159bAndres Morales     */
2463e4b665bc607c81ccc018d753122a363dd95159bAndres Morales    public int[] getTechCodeList() {
2473e4b665bc607c81ccc018d753122a363dd95159bAndres Morales        return mTechList;
2483e4b665bc607c81ccc018d753122a363dd95159bAndres Morales    }
2493e4b665bc607c81ccc018d753122a363dd95159bAndres Morales
2503e4b665bc607c81ccc018d753122a363dd95159bAndres Morales    /**
25107f3bee2db8b6e93ebbf7222676bd9f468e85569Nick Pelly     * Get the Tag Identifier (if it has one).
25274fe6c6b245ebe7d3b3d96962c32980d88dca4f5Nick Pelly     * <p>The tag identifier is a low level serial number, used for anti-collision
25374fe6c6b245ebe7d3b3d96962c32980d88dca4f5Nick Pelly     * and identification.
25474fe6c6b245ebe7d3b3d96962c32980d88dca4f5Nick Pelly     * <p> Most tags have a stable unique identifier
25574fe6c6b245ebe7d3b3d96962c32980d88dca4f5Nick Pelly     * (UID), but some tags will generate a random ID every time they are discovered
25674fe6c6b245ebe7d3b3d96962c32980d88dca4f5Nick Pelly     * (RID), and there are some tags with no ID at all (the byte array will be zero-sized).
25774fe6c6b245ebe7d3b3d96962c32980d88dca4f5Nick Pelly     * <p> The size and format of an ID is specific to the RF technology used by the tag.
25874fe6c6b245ebe7d3b3d96962c32980d88dca4f5Nick Pelly     * <p> This function retrieves the ID as determined at discovery time, and does not
25974fe6c6b245ebe7d3b3d96962c32980d88dca4f5Nick Pelly     * perform any further RF communication or block.
26074fe6c6b245ebe7d3b3d96962c32980d88dca4f5Nick Pelly     * @return ID as byte array, never null
26107f3bee2db8b6e93ebbf7222676bd9f468e85569Nick Pelly     */
26207f3bee2db8b6e93ebbf7222676bd9f468e85569Nick Pelly    public byte[] getId() {
26307f3bee2db8b6e93ebbf7222676bd9f468e85569Nick Pelly        return mId;
26407f3bee2db8b6e93ebbf7222676bd9f468e85569Nick Pelly    }
26507f3bee2db8b6e93ebbf7222676bd9f468e85569Nick Pelly
26607f3bee2db8b6e93ebbf7222676bd9f468e85569Nick Pelly    /**
26774fe6c6b245ebe7d3b3d96962c32980d88dca4f5Nick Pelly     * Get the technologies available in this tag, as fully qualified class names.
26874fe6c6b245ebe7d3b3d96962c32980d88dca4f5Nick Pelly     * <p>
26974fe6c6b245ebe7d3b3d96962c32980d88dca4f5Nick Pelly     * A technology is an implementation of the {@link TagTechnology} interface,
27074fe6c6b245ebe7d3b3d96962c32980d88dca4f5Nick Pelly     * and can be instantiated by calling the static <code>get(Tag)</code>
27174fe6c6b245ebe7d3b3d96962c32980d88dca4f5Nick Pelly     * method on the implementation with this Tag. The {@link TagTechnology}
27274fe6c6b245ebe7d3b3d96962c32980d88dca4f5Nick Pelly     * object can then be used to perform advanced, technology-specific operations on a tag.
27374fe6c6b245ebe7d3b3d96962c32980d88dca4f5Nick Pelly     * <p>
27474fe6c6b245ebe7d3b3d96962c32980d88dca4f5Nick Pelly     * Android defines a mandatory set of technologies that must be correctly
27574fe6c6b245ebe7d3b3d96962c32980d88dca4f5Nick Pelly     * enumerated by all Android NFC devices, and an optional
27674fe6c6b245ebe7d3b3d96962c32980d88dca4f5Nick Pelly     * set of proprietary technologies.
27774fe6c6b245ebe7d3b3d96962c32980d88dca4f5Nick Pelly     * See {@link TagTechnology} for more details.
27874fe6c6b245ebe7d3b3d96962c32980d88dca4f5Nick Pelly     * <p>
279c1576ad627d3d2b2d3c0764c605ebbf3ddc24401Jeff Hamilton     * The ordering of the returned array is undefined and should not be relied upon.
28074fe6c6b245ebe7d3b3d96962c32980d88dca4f5Nick Pelly     * @return an array of fully-qualified {@link TagTechnology} class-names.
281590b73bc5b8e5f7b59bff1d9264a52388a5162e6Nick Pelly     */
282d88e9aa575eb3a9d20cdb0e8918d54993e1ce1e0Jeff Hamilton    public String[] getTechList() {
283d88e9aa575eb3a9d20cdb0e8918d54993e1ce1e0Jeff Hamilton        return mTechStringList;
284590b73bc5b8e5f7b59bff1d9264a52388a5162e6Nick Pelly    }
285590b73bc5b8e5f7b59bff1d9264a52388a5162e6Nick Pelly
2862dcae567ab56285bc70b6857c4f3c87df09641b8Martijn Coenen    /**
2872dcae567ab56285bc70b6857c4f3c87df09641b8Martijn Coenen     * Rediscover the technologies available on this tag.
2882dcae567ab56285bc70b6857c4f3c87df09641b8Martijn Coenen     * <p>
2892dcae567ab56285bc70b6857c4f3c87df09641b8Martijn Coenen     * The technologies that are available on a tag may change due to
2902dcae567ab56285bc70b6857c4f3c87df09641b8Martijn Coenen     * operations being performed on a tag. For example, formatting a
2912dcae567ab56285bc70b6857c4f3c87df09641b8Martijn Coenen     * tag as NDEF adds the {@link Ndef} technology. The {@link rediscover}
2922dcae567ab56285bc70b6857c4f3c87df09641b8Martijn Coenen     * method reenumerates the available technologies on the tag
2932dcae567ab56285bc70b6857c4f3c87df09641b8Martijn Coenen     * and returns a new {@link Tag} object containing these technologies.
2942dcae567ab56285bc70b6857c4f3c87df09641b8Martijn Coenen     * <p>
2952dcae567ab56285bc70b6857c4f3c87df09641b8Martijn Coenen     * You may not be connected to any of this {@link Tag}'s technologies
2962dcae567ab56285bc70b6857c4f3c87df09641b8Martijn Coenen     * when calling this method.
2972dcae567ab56285bc70b6857c4f3c87df09641b8Martijn Coenen     * This method guarantees that you will be returned the same Tag
2982dcae567ab56285bc70b6857c4f3c87df09641b8Martijn Coenen     * if it is still in the field.
2992dcae567ab56285bc70b6857c4f3c87df09641b8Martijn Coenen     * <p>May cause RF activity and may block. Must not be called
3002dcae567ab56285bc70b6857c4f3c87df09641b8Martijn Coenen     * from the main application thread. A blocked call will be canceled with
3012dcae567ab56285bc70b6857c4f3c87df09641b8Martijn Coenen     * {@link IOException} by calling {@link #close} from another thread.
3022dcae567ab56285bc70b6857c4f3c87df09641b8Martijn Coenen     * <p>Does not remove power from the RF field, so a tag having a random
3032dcae567ab56285bc70b6857c4f3c87df09641b8Martijn Coenen     * ID should not change its ID.
3042dcae567ab56285bc70b6857c4f3c87df09641b8Martijn Coenen     * @return the rediscovered tag object.
3052dcae567ab56285bc70b6857c4f3c87df09641b8Martijn Coenen     * @throws IOException if the tag cannot be rediscovered
3062dcae567ab56285bc70b6857c4f3c87df09641b8Martijn Coenen     * @hide
3072dcae567ab56285bc70b6857c4f3c87df09641b8Martijn Coenen     */
3082dcae567ab56285bc70b6857c4f3c87df09641b8Martijn Coenen    // TODO See if we need TagLostException
3092dcae567ab56285bc70b6857c4f3c87df09641b8Martijn Coenen    // TODO Unhide for ICS
3102dcae567ab56285bc70b6857c4f3c87df09641b8Martijn Coenen    // TODO Update documentation to make sure it matches with the final
3112dcae567ab56285bc70b6857c4f3c87df09641b8Martijn Coenen    //      implementation.
3122dcae567ab56285bc70b6857c4f3c87df09641b8Martijn Coenen    public Tag rediscover() throws IOException {
3132dcae567ab56285bc70b6857c4f3c87df09641b8Martijn Coenen        if (getConnectedTechnology() != -1) {
3142dcae567ab56285bc70b6857c4f3c87df09641b8Martijn Coenen            throw new IllegalStateException("Close connection to the technology first!");
3152dcae567ab56285bc70b6857c4f3c87df09641b8Martijn Coenen        }
3162dcae567ab56285bc70b6857c4f3c87df09641b8Martijn Coenen
31723fc93a7c1e340e79642d3d0bf4b4658c8645c8eMartijn Coenen        if (mTagService == null) {
31823fc93a7c1e340e79642d3d0bf4b4658c8645c8eMartijn Coenen            throw new IOException("Mock tags don't support this operation.");
31923fc93a7c1e340e79642d3d0bf4b4658c8645c8eMartijn Coenen        }
3202dcae567ab56285bc70b6857c4f3c87df09641b8Martijn Coenen        try {
3212dcae567ab56285bc70b6857c4f3c87df09641b8Martijn Coenen            Tag newTag = mTagService.rediscover(getServiceHandle());
3222dcae567ab56285bc70b6857c4f3c87df09641b8Martijn Coenen            if (newTag != null) {
3232dcae567ab56285bc70b6857c4f3c87df09641b8Martijn Coenen                return newTag;
3242dcae567ab56285bc70b6857c4f3c87df09641b8Martijn Coenen            } else {
3252dcae567ab56285bc70b6857c4f3c87df09641b8Martijn Coenen                throw new IOException("Failed to rediscover tag");
3262dcae567ab56285bc70b6857c4f3c87df09641b8Martijn Coenen            }
3272dcae567ab56285bc70b6857c4f3c87df09641b8Martijn Coenen        } catch (RemoteException e) {
3282dcae567ab56285bc70b6857c4f3c87df09641b8Martijn Coenen            throw new IOException("NFC service dead");
3292dcae567ab56285bc70b6857c4f3c87df09641b8Martijn Coenen        }
3302dcae567ab56285bc70b6857c4f3c87df09641b8Martijn Coenen    }
3312dcae567ab56285bc70b6857c4f3c87df09641b8Martijn Coenen
3322dcae567ab56285bc70b6857c4f3c87df09641b8Martijn Coenen
3334e21e1d21a877cce4db5ec8c5786604cc10f2d7eJeff Hamilton    /** @hide */
3344e21e1d21a877cce4db5ec8c5786604cc10f2d7eJeff Hamilton    public boolean hasTech(int techType) {
3354e21e1d21a877cce4db5ec8c5786604cc10f2d7eJeff Hamilton        for (int tech : mTechList) {
3364e21e1d21a877cce4db5ec8c5786604cc10f2d7eJeff Hamilton            if (tech == techType) return true;
3374e21e1d21a877cce4db5ec8c5786604cc10f2d7eJeff Hamilton        }
3384e21e1d21a877cce4db5ec8c5786604cc10f2d7eJeff Hamilton        return false;
3394e21e1d21a877cce4db5ec8c5786604cc10f2d7eJeff Hamilton    }
34074fe6c6b245ebe7d3b3d96962c32980d88dca4f5Nick Pelly
3414e21e1d21a877cce4db5ec8c5786604cc10f2d7eJeff Hamilton    /** @hide */
3424e21e1d21a877cce4db5ec8c5786604cc10f2d7eJeff Hamilton    public Bundle getTechExtras(int tech) {
3431253ebc74a8453a88dc47a2b698145098d201681Martijn Coenen        int pos = -1;
3441253ebc74a8453a88dc47a2b698145098d201681Martijn Coenen        for (int idx = 0; idx < mTechList.length; idx++) {
3451253ebc74a8453a88dc47a2b698145098d201681Martijn Coenen          if (mTechList[idx] == tech) {
3461253ebc74a8453a88dc47a2b698145098d201681Martijn Coenen              pos = idx;
3471253ebc74a8453a88dc47a2b698145098d201681Martijn Coenen              break;
3481253ebc74a8453a88dc47a2b698145098d201681Martijn Coenen          }
3491253ebc74a8453a88dc47a2b698145098d201681Martijn Coenen        }
3506be655c768a82716612c00fdd156254d8dc00f42Jeff Hamilton        if (pos < 0) {
3516be655c768a82716612c00fdd156254d8dc00f42Jeff Hamilton            return null;
3526be655c768a82716612c00fdd156254d8dc00f42Jeff Hamilton        }
3536be655c768a82716612c00fdd156254d8dc00f42Jeff Hamilton
3544e21e1d21a877cce4db5ec8c5786604cc10f2d7eJeff Hamilton        return mTechExtras[pos];
3554e21e1d21a877cce4db5ec8c5786604cc10f2d7eJeff Hamilton    }
3566be655c768a82716612c00fdd156254d8dc00f42Jeff Hamilton
3574e21e1d21a877cce4db5ec8c5786604cc10f2d7eJeff Hamilton    /** @hide */
3584e21e1d21a877cce4db5ec8c5786604cc10f2d7eJeff Hamilton    public INfcTag getTagService() {
3594e21e1d21a877cce4db5ec8c5786604cc10f2d7eJeff Hamilton        return mTagService;
36007f3bee2db8b6e93ebbf7222676bd9f468e85569Nick Pelly    }
36107f3bee2db8b6e93ebbf7222676bd9f468e85569Nick Pelly
36274fe6c6b245ebe7d3b3d96962c32980d88dca4f5Nick Pelly    /**
36374fe6c6b245ebe7d3b3d96962c32980d88dca4f5Nick Pelly     * Human-readable description of the tag, for debugging.
36474fe6c6b245ebe7d3b3d96962c32980d88dca4f5Nick Pelly     */
36507f3bee2db8b6e93ebbf7222676bd9f468e85569Nick Pelly    @Override
36607f3bee2db8b6e93ebbf7222676bd9f468e85569Nick Pelly    public String toString() {
3678856c4278d9fd727081083d0f88459a8152d88c0Jeff Hamilton        StringBuilder sb = new StringBuilder("TAG: Tech [");
3688856c4278d9fd727081083d0f88459a8152d88c0Jeff Hamilton        String[] techList = getTechList();
3698856c4278d9fd727081083d0f88459a8152d88c0Jeff Hamilton        int length = techList.length;
3708856c4278d9fd727081083d0f88459a8152d88c0Jeff Hamilton        for (int i = 0; i < length; i++) {
3718856c4278d9fd727081083d0f88459a8152d88c0Jeff Hamilton            sb.append(techList[i]);
3728856c4278d9fd727081083d0f88459a8152d88c0Jeff Hamilton            if (i < length - 1) {
3738856c4278d9fd727081083d0f88459a8152d88c0Jeff Hamilton                sb.append(", ");
3748856c4278d9fd727081083d0f88459a8152d88c0Jeff Hamilton            }
37507f3bee2db8b6e93ebbf7222676bd9f468e85569Nick Pelly        }
3768856c4278d9fd727081083d0f88459a8152d88c0Jeff Hamilton        sb.append("]");
37707f3bee2db8b6e93ebbf7222676bd9f468e85569Nick Pelly        return sb.toString();
37807f3bee2db8b6e93ebbf7222676bd9f468e85569Nick Pelly    }
37907f3bee2db8b6e93ebbf7222676bd9f468e85569Nick Pelly
38007f3bee2db8b6e93ebbf7222676bd9f468e85569Nick Pelly    /*package*/ static byte[] readBytesWithNull(Parcel in) {
38107f3bee2db8b6e93ebbf7222676bd9f468e85569Nick Pelly        int len = in.readInt();
38207f3bee2db8b6e93ebbf7222676bd9f468e85569Nick Pelly        byte[] result = null;
383e2e4ea9ea8f5724403e6267d193a740dc7c78785Sylvain Fonteneau        if (len >= 0) {
38407f3bee2db8b6e93ebbf7222676bd9f468e85569Nick Pelly            result = new byte[len];
38507f3bee2db8b6e93ebbf7222676bd9f468e85569Nick Pelly            in.readByteArray(result);
386590b73bc5b8e5f7b59bff1d9264a52388a5162e6Nick Pelly        }
38707f3bee2db8b6e93ebbf7222676bd9f468e85569Nick Pelly        return result;
38807f3bee2db8b6e93ebbf7222676bd9f468e85569Nick Pelly    }
38907f3bee2db8b6e93ebbf7222676bd9f468e85569Nick Pelly
39007f3bee2db8b6e93ebbf7222676bd9f468e85569Nick Pelly    /*package*/ static void writeBytesWithNull(Parcel out, byte[] b) {
39107f3bee2db8b6e93ebbf7222676bd9f468e85569Nick Pelly        if (b == null) {
39207f3bee2db8b6e93ebbf7222676bd9f468e85569Nick Pelly            out.writeInt(-1);
39307f3bee2db8b6e93ebbf7222676bd9f468e85569Nick Pelly            return;
39407f3bee2db8b6e93ebbf7222676bd9f468e85569Nick Pelly        }
39507f3bee2db8b6e93ebbf7222676bd9f468e85569Nick Pelly        out.writeInt(b.length);
39607f3bee2db8b6e93ebbf7222676bd9f468e85569Nick Pelly        out.writeByteArray(b);
397590b73bc5b8e5f7b59bff1d9264a52388a5162e6Nick Pelly    }
398590b73bc5b8e5f7b59bff1d9264a52388a5162e6Nick Pelly
399590b73bc5b8e5f7b59bff1d9264a52388a5162e6Nick Pelly    @Override
400590b73bc5b8e5f7b59bff1d9264a52388a5162e6Nick Pelly    public int describeContents() {
401590b73bc5b8e5f7b59bff1d9264a52388a5162e6Nick Pelly        return 0;
402590b73bc5b8e5f7b59bff1d9264a52388a5162e6Nick Pelly    }
403590b73bc5b8e5f7b59bff1d9264a52388a5162e6Nick Pelly
404590b73bc5b8e5f7b59bff1d9264a52388a5162e6Nick Pelly    @Override
405590b73bc5b8e5f7b59bff1d9264a52388a5162e6Nick Pelly    public void writeToParcel(Parcel dest, int flags) {
406c5a418ecb7681159ae6674a4d91177c6841537b1Sylvain Fonteneau        // Null mTagService means this is a mock tag
407c5a418ecb7681159ae6674a4d91177c6841537b1Sylvain Fonteneau        int isMock = (mTagService == null)?1:0;
408c5a418ecb7681159ae6674a4d91177c6841537b1Sylvain Fonteneau
40907f3bee2db8b6e93ebbf7222676bd9f468e85569Nick Pelly        writeBytesWithNull(dest, mId);
4106be655c768a82716612c00fdd156254d8dc00f42Jeff Hamilton        dest.writeInt(mTechList.length);
4116be655c768a82716612c00fdd156254d8dc00f42Jeff Hamilton        dest.writeIntArray(mTechList);
4126be655c768a82716612c00fdd156254d8dc00f42Jeff Hamilton        dest.writeTypedArray(mTechExtras, 0);
41307f3bee2db8b6e93ebbf7222676bd9f468e85569Nick Pelly        dest.writeInt(mServiceHandle);
414c5a418ecb7681159ae6674a4d91177c6841537b1Sylvain Fonteneau        dest.writeInt(isMock);
415c5a418ecb7681159ae6674a4d91177c6841537b1Sylvain Fonteneau        if (isMock == 0) {
416c5a418ecb7681159ae6674a4d91177c6841537b1Sylvain Fonteneau            dest.writeStrongBinder(mTagService.asBinder());
417c5a418ecb7681159ae6674a4d91177c6841537b1Sylvain Fonteneau        }
418590b73bc5b8e5f7b59bff1d9264a52388a5162e6Nick Pelly    }
419590b73bc5b8e5f7b59bff1d9264a52388a5162e6Nick Pelly
420590b73bc5b8e5f7b59bff1d9264a52388a5162e6Nick Pelly    public static final Parcelable.Creator<Tag> CREATOR =
421590b73bc5b8e5f7b59bff1d9264a52388a5162e6Nick Pelly            new Parcelable.Creator<Tag>() {
4226be655c768a82716612c00fdd156254d8dc00f42Jeff Hamilton        @Override
423590b73bc5b8e5f7b59bff1d9264a52388a5162e6Nick Pelly        public Tag createFromParcel(Parcel in) {
424c5a418ecb7681159ae6674a4d91177c6841537b1Sylvain Fonteneau            INfcTag tagService;
425c5a418ecb7681159ae6674a4d91177c6841537b1Sylvain Fonteneau
42607f3bee2db8b6e93ebbf7222676bd9f468e85569Nick Pelly            // Tag fields
42707f3bee2db8b6e93ebbf7222676bd9f468e85569Nick Pelly            byte[] id = Tag.readBytesWithNull(in);
4286be655c768a82716612c00fdd156254d8dc00f42Jeff Hamilton            int[] techList = new int[in.readInt()];
4296be655c768a82716612c00fdd156254d8dc00f42Jeff Hamilton            in.readIntArray(techList);
4306be655c768a82716612c00fdd156254d8dc00f42Jeff Hamilton            Bundle[] techExtras = in.createTypedArray(Bundle.CREATOR);
43107f3bee2db8b6e93ebbf7222676bd9f468e85569Nick Pelly            int serviceHandle = in.readInt();
432c5a418ecb7681159ae6674a4d91177c6841537b1Sylvain Fonteneau            int isMock = in.readInt();
433c5a418ecb7681159ae6674a4d91177c6841537b1Sylvain Fonteneau            if (isMock == 0) {
434c5a418ecb7681159ae6674a4d91177c6841537b1Sylvain Fonteneau                tagService = INfcTag.Stub.asInterface(in.readStrongBinder());
435c5a418ecb7681159ae6674a4d91177c6841537b1Sylvain Fonteneau            }
436c5a418ecb7681159ae6674a4d91177c6841537b1Sylvain Fonteneau            else {
437c5a418ecb7681159ae6674a4d91177c6841537b1Sylvain Fonteneau                tagService = null;
438c5a418ecb7681159ae6674a4d91177c6841537b1Sylvain Fonteneau            }
43907f3bee2db8b6e93ebbf7222676bd9f468e85569Nick Pelly
4404e21e1d21a877cce4db5ec8c5786604cc10f2d7eJeff Hamilton            return new Tag(id, techList, techExtras, serviceHandle, tagService);
441590b73bc5b8e5f7b59bff1d9264a52388a5162e6Nick Pelly        }
4426be655c768a82716612c00fdd156254d8dc00f42Jeff Hamilton
4436be655c768a82716612c00fdd156254d8dc00f42Jeff Hamilton        @Override
444590b73bc5b8e5f7b59bff1d9264a52388a5162e6Nick Pelly        public Tag[] newArray(int size) {
445590b73bc5b8e5f7b59bff1d9264a52388a5162e6Nick Pelly            return new Tag[size];
446590b73bc5b8e5f7b59bff1d9264a52388a5162e6Nick Pelly        }
447590b73bc5b8e5f7b59bff1d9264a52388a5162e6Nick Pelly    };
4484049f9d00a86f848d42d2429068496b31a6795adMartijn Coenen
449be372d6462605010910e771cef15d5adccd0a59eJeff Hamilton    /**
450be372d6462605010910e771cef15d5adccd0a59eJeff Hamilton     * For internal use only.
451be372d6462605010910e771cef15d5adccd0a59eJeff Hamilton     *
4524049f9d00a86f848d42d2429068496b31a6795adMartijn Coenen     * @hide
4534049f9d00a86f848d42d2429068496b31a6795adMartijn Coenen     */
4544049f9d00a86f848d42d2429068496b31a6795adMartijn Coenen    public synchronized void setConnectedTechnology(int technology) {
4554049f9d00a86f848d42d2429068496b31a6795adMartijn Coenen        if (mConnectedTechnology == -1) {
4564049f9d00a86f848d42d2429068496b31a6795adMartijn Coenen            mConnectedTechnology = technology;
4574049f9d00a86f848d42d2429068496b31a6795adMartijn Coenen        } else {
4584049f9d00a86f848d42d2429068496b31a6795adMartijn Coenen            throw new IllegalStateException("Close other technology first!");
4594049f9d00a86f848d42d2429068496b31a6795adMartijn Coenen        }
4604049f9d00a86f848d42d2429068496b31a6795adMartijn Coenen    }
4614049f9d00a86f848d42d2429068496b31a6795adMartijn Coenen
462be372d6462605010910e771cef15d5adccd0a59eJeff Hamilton    /**
463be372d6462605010910e771cef15d5adccd0a59eJeff Hamilton     * For internal use only.
464be372d6462605010910e771cef15d5adccd0a59eJeff Hamilton     *
4654049f9d00a86f848d42d2429068496b31a6795adMartijn Coenen     * @hide
4664049f9d00a86f848d42d2429068496b31a6795adMartijn Coenen     */
4674049f9d00a86f848d42d2429068496b31a6795adMartijn Coenen    public int getConnectedTechnology() {
4684049f9d00a86f848d42d2429068496b31a6795adMartijn Coenen        return mConnectedTechnology;
4694049f9d00a86f848d42d2429068496b31a6795adMartijn Coenen    }
4704049f9d00a86f848d42d2429068496b31a6795adMartijn Coenen
471be372d6462605010910e771cef15d5adccd0a59eJeff Hamilton    /**
472be372d6462605010910e771cef15d5adccd0a59eJeff Hamilton     * For internal use only.
473be372d6462605010910e771cef15d5adccd0a59eJeff Hamilton     *
4744049f9d00a86f848d42d2429068496b31a6795adMartijn Coenen     * @hide
4754049f9d00a86f848d42d2429068496b31a6795adMartijn Coenen     */
4764049f9d00a86f848d42d2429068496b31a6795adMartijn Coenen    public void setTechnologyDisconnected() {
4774049f9d00a86f848d42d2429068496b31a6795adMartijn Coenen        mConnectedTechnology = -1;
4784049f9d00a86f848d42d2429068496b31a6795adMartijn Coenen    }
4791253ebc74a8453a88dc47a2b698145098d201681Martijn Coenen}
480