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;
27f8538594fe6ba6db3310da042597840601d78cdaMartijn 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;
38590b73bc5b8e5f7b59bff1d9264a52388a5162e6Nick Pelly
39590b73bc5b8e5f7b59bff1d9264a52388a5162e6Nick Pelly/**
4074fe6c6b245ebe7d3b3d96962c32980d88dca4f5Nick Pelly * Represents an NFC tag that has been discovered.
41590b73bc5b8e5f7b59bff1d9264a52388a5162e6Nick Pelly * <p>
4274fe6c6b245ebe7d3b3d96962c32980d88dca4f5Nick Pelly * {@link Tag} is an immutable object that represents the state of a NFC tag at
4374fe6c6b245ebe7d3b3d96962c32980d88dca4f5Nick Pelly * the time of discovery. It can be used as a handle to {@link TagTechnology} classes
4428319c0cec94977682db32b949628a8e4b8183dcJeff Hamilton * to perform advanced operations, or directly queried for its ID via {@link #getId} and the
4528319c0cec94977682db32b949628a8e4b8183dcJeff Hamilton * set of technologies it contains via {@link #getTechList}. Arrays passed to and
4628319c0cec94977682db32b949628a8e4b8183dcJeff Hamilton * returned by this class are <em>not</em> cloned, so be careful not to modify them.
47590b73bc5b8e5f7b59bff1d9264a52388a5162e6Nick Pelly * <p>
4874fe6c6b245ebe7d3b3d96962c32980d88dca4f5Nick Pelly * A new tag object is created every time a tag is discovered (comes into range), even
4974fe6c6b245ebe7d3b3d96962c32980d88dca4f5Nick Pelly * if it is the same physical tag. If a tag is removed and then returned into range, then
5074fe6c6b245ebe7d3b3d96962c32980d88dca4f5Nick Pelly * only the most recent tag object can be successfully used to create a {@link TagTechnology}.
5174fe6c6b245ebe7d3b3d96962c32980d88dca4f5Nick Pelly *
5274fe6c6b245ebe7d3b3d96962c32980d88dca4f5Nick Pelly * <h3>Tag Dispatch</h3>
5374fe6c6b245ebe7d3b3d96962c32980d88dca4f5Nick Pelly * When a tag is discovered, a {@link Tag} object is created and passed to a
5428319c0cec94977682db32b949628a8e4b8183dcJeff Hamilton * single activity via the {@link NfcAdapter#EXTRA_TAG} extra in an
5528319c0cec94977682db32b949628a8e4b8183dcJeff Hamilton * {@link android.content.Intent} via {@link Context#startActivity}. A four stage dispatch is used
5628319c0cec94977682db32b949628a8e4b8183dcJeff Hamilton * to select the
5728319c0cec94977682db32b949628a8e4b8183dcJeff Hamilton * most appropriate activity to handle the tag. The Android OS executes each stage in order,
5828319c0cec94977682db32b949628a8e4b8183dcJeff Hamilton * and completes dispatch as soon as a single matching activity is found. If there are multiple
5928319c0cec94977682db32b949628a8e4b8183dcJeff Hamilton * matching activities found at any one stage then the Android activity chooser dialog is shown
6028319c0cec94977682db32b949628a8e4b8183dcJeff Hamilton * to allow the user to select the activity to receive the tag.
6128319c0cec94977682db32b949628a8e4b8183dcJeff Hamilton *
6228319c0cec94977682db32b949628a8e4b8183dcJeff Hamilton * <p>The Tag dispatch mechanism was designed to give a high probability of dispatching
6328319c0cec94977682db32b949628a8e4b8183dcJeff Hamilton * a tag to the correct activity without showing the user an activity chooser dialog.
6428319c0cec94977682db32b949628a8e4b8183dcJeff Hamilton * This is important for NFC interactions because they are very transient -- if a user has to
6528319c0cec94977682db32b949628a8e4b8183dcJeff Hamilton * move the Android device to choose an application then the connection will likely be broken.
6628319c0cec94977682db32b949628a8e4b8183dcJeff Hamilton *
6774fe6c6b245ebe7d3b3d96962c32980d88dca4f5Nick Pelly * <h4>1. Foreground activity dispatch</h4>
6828319c0cec94977682db32b949628a8e4b8183dcJeff Hamilton * A foreground activity that has called
6928319c0cec94977682db32b949628a8e4b8183dcJeff Hamilton * {@link NfcAdapter#enableForegroundDispatch NfcAdapter.enableForegroundDispatch()} is
7028319c0cec94977682db32b949628a8e4b8183dcJeff Hamilton * given priority. See the documentation on
7128319c0cec94977682db32b949628a8e4b8183dcJeff Hamilton * {@link NfcAdapter#enableForegroundDispatch NfcAdapter.enableForegroundDispatch()} for
7274fe6c6b245ebe7d3b3d96962c32980d88dca4f5Nick Pelly * its usage.
7374fe6c6b245ebe7d3b3d96962c32980d88dca4f5Nick Pelly * <h4>2. NDEF data dispatch</h4>
7428319c0cec94977682db32b949628a8e4b8183dcJeff Hamilton * If the tag contains NDEF data the system inspects the first {@link NdefRecord} in the first
7528319c0cec94977682db32b949628a8e4b8183dcJeff Hamilton * {@link NdefMessage}. If the record is a URI, SmartPoster, or MIME data
7628319c0cec94977682db32b949628a8e4b8183dcJeff Hamilton * {@link Context#startActivity} is called with {@link NfcAdapter#ACTION_NDEF_DISCOVERED}. For URI
7728319c0cec94977682db32b949628a8e4b8183dcJeff Hamilton * and SmartPoster records the URI is put into the intent's data field. For MIME records the MIME
7828319c0cec94977682db32b949628a8e4b8183dcJeff Hamilton * type is put in the intent's type field. This allows activities to register to be launched only
7928319c0cec94977682db32b949628a8e4b8183dcJeff Hamilton * when data they know how to handle is present on a tag. This is the preferred method of handling
8028319c0cec94977682db32b949628a8e4b8183dcJeff Hamilton * data on a tag since NDEF data can be stored on many types of tags and doesn't depend on a
8128319c0cec94977682db32b949628a8e4b8183dcJeff Hamilton * specific tag technology.
8274fe6c6b245ebe7d3b3d96962c32980d88dca4f5Nick Pelly * See {@link NfcAdapter#ACTION_NDEF_DISCOVERED} for more detail. If the tag does not contain
8328319c0cec94977682db32b949628a8e4b8183dcJeff Hamilton * NDEF data, or if no activity is registered
8428319c0cec94977682db32b949628a8e4b8183dcJeff Hamilton * for {@link NfcAdapter#ACTION_NDEF_DISCOVERED} with a matching data URI or MIME type then dispatch
8528319c0cec94977682db32b949628a8e4b8183dcJeff Hamilton * moves to stage 3.
8674fe6c6b245ebe7d3b3d96962c32980d88dca4f5Nick Pelly * <h4>3. Tag Technology dispatch</h4>
8774fe6c6b245ebe7d3b3d96962c32980d88dca4f5Nick Pelly * {@link Context#startActivity} is called with {@link NfcAdapter#ACTION_TECH_DISCOVERED} to
8828319c0cec94977682db32b949628a8e4b8183dcJeff Hamilton * dispatch the tag to an activity that can handle the technologies present on the tag.
8974fe6c6b245ebe7d3b3d96962c32980d88dca4f5Nick Pelly * Technologies are defined as sub-classes of {@link TagTechnology}, see the package
9028319c0cec94977682db32b949628a8e4b8183dcJeff Hamilton * {@link android.nfc.tech}. The Android OS looks for an activity that can handle one or
9128319c0cec94977682db32b949628a8e4b8183dcJeff Hamilton * more technologies in the tag. See {@link NfcAdapter#ACTION_TECH_DISCOVERED} for more detail.
9274fe6c6b245ebe7d3b3d96962c32980d88dca4f5Nick Pelly * <h4>4. Fall-back dispatch</h4>
9328319c0cec94977682db32b949628a8e4b8183dcJeff Hamilton * If no activity has been matched then {@link Context#startActivity} is called with
9474fe6c6b245ebe7d3b3d96962c32980d88dca4f5Nick Pelly * {@link NfcAdapter#ACTION_TAG_DISCOVERED}. This is intended as a fall-back mechanism.
9574fe6c6b245ebe7d3b3d96962c32980d88dca4f5Nick Pelly * See {@link NfcAdapter#ACTION_TAG_DISCOVERED}.
9674fe6c6b245ebe7d3b3d96962c32980d88dca4f5Nick Pelly *
9774fe6c6b245ebe7d3b3d96962c32980d88dca4f5Nick Pelly * <h3>NFC Tag Background</h3>
9874fe6c6b245ebe7d3b3d96962c32980d88dca4f5Nick Pelly * An NFC tag is a passive NFC device, powered by the NFC field of this Android device while
9928319c0cec94977682db32b949628a8e4b8183dcJeff Hamilton * it is in range. Tag's can come in many forms, such as stickers, cards, key fobs, or
10074fe6c6b245ebe7d3b3d96962c32980d88dca4f5Nick Pelly * even embedded in a more sophisticated device.
10174fe6c6b245ebe7d3b3d96962c32980d88dca4f5Nick Pelly * <p>
10274fe6c6b245ebe7d3b3d96962c32980d88dca4f5Nick Pelly * Tags can have a wide range of capabilities. Simple tags just offer read/write semantics,
10374fe6c6b245ebe7d3b3d96962c32980d88dca4f5Nick Pelly * and contain some one time
10474fe6c6b245ebe7d3b3d96962c32980d88dca4f5Nick Pelly * programmable areas to make read-only. More complex tags offer math operations
10574fe6c6b245ebe7d3b3d96962c32980d88dca4f5Nick Pelly * and per-sector access control and authentication. The most sophisticated tags
10628319c0cec94977682db32b949628a8e4b8183dcJeff Hamilton * contain operating environments allowing complex interactions with the
10728319c0cec94977682db32b949628a8e4b8183dcJeff Hamilton * code executing on the tag. Use {@link TagTechnology} classes to access a broad
10874fe6c6b245ebe7d3b3d96962c32980d88dca4f5Nick Pelly * range of capabilities available in NFC tags.
109590b73bc5b8e5f7b59bff1d9264a52388a5162e6Nick Pelly * <p>
110590b73bc5b8e5f7b59bff1d9264a52388a5162e6Nick Pelly */
111f003e26df96067b4b136f0859012cb7ec3ed930fNick Pellypublic final class Tag implements Parcelable {
1121f5badc1cb08f10ddf4b09aaaf34060a23999a51Nick Pelly    final byte[] mId;
1131f5badc1cb08f10ddf4b09aaaf34060a23999a51Nick Pelly    final int[] mTechList;
1141f5badc1cb08f10ddf4b09aaaf34060a23999a51Nick Pelly    final String[] mTechStringList;
1151f5badc1cb08f10ddf4b09aaaf34060a23999a51Nick Pelly    final Bundle[] mTechExtras;
1161f5badc1cb08f10ddf4b09aaaf34060a23999a51Nick Pelly    final int mServiceHandle;  // for use by NFC service, 0 indicates a mock
1171f5badc1cb08f10ddf4b09aaaf34060a23999a51Nick Pelly    final INfcTag mTagService; // interface to NFC service, will be null if mock tag
118a926540d5455a973dd8ca19c00c108620d9c68c2Sylvain Fonteneau
1191f5badc1cb08f10ddf4b09aaaf34060a23999a51Nick Pelly    int mConnectedTechnology;
1204049f9d00a86f848d42d2429068496b31a6795adMartijn Coenen
121590b73bc5b8e5f7b59bff1d9264a52388a5162e6Nick Pelly    /**
12207f3bee2db8b6e93ebbf7222676bd9f468e85569Nick Pelly     * Hidden constructor to be used by NFC service and internal classes.
123590b73bc5b8e5f7b59bff1d9264a52388a5162e6Nick Pelly     * @hide
124590b73bc5b8e5f7b59bff1d9264a52388a5162e6Nick Pelly     */
1254e21e1d21a877cce4db5ec8c5786604cc10f2d7eJeff Hamilton    public Tag(byte[] id, int[] techList, Bundle[] techListExtras, int serviceHandle,
1264e21e1d21a877cce4db5ec8c5786604cc10f2d7eJeff Hamilton            INfcTag tagService) {
1276be655c768a82716612c00fdd156254d8dc00f42Jeff Hamilton        if (techList == null) {
12807f3bee2db8b6e93ebbf7222676bd9f468e85569Nick Pelly            throw new IllegalArgumentException("rawTargets cannot be null");
12907f3bee2db8b6e93ebbf7222676bd9f468e85569Nick Pelly        }
13007f3bee2db8b6e93ebbf7222676bd9f468e85569Nick Pelly        mId = id;
1316be655c768a82716612c00fdd156254d8dc00f42Jeff Hamilton        mTechList = Arrays.copyOf(techList, techList.length);
132d88e9aa575eb3a9d20cdb0e8918d54993e1ce1e0Jeff Hamilton        mTechStringList = generateTechStringList(techList);
1336be655c768a82716612c00fdd156254d8dc00f42Jeff Hamilton        // Ensure mTechExtras is as long as mTechList
1346be655c768a82716612c00fdd156254d8dc00f42Jeff Hamilton        mTechExtras = Arrays.copyOf(techListExtras, techList.length);
13507f3bee2db8b6e93ebbf7222676bd9f468e85569Nick Pelly        mServiceHandle = serviceHandle;
1364e21e1d21a877cce4db5ec8c5786604cc10f2d7eJeff Hamilton        mTagService = tagService;
1374049f9d00a86f848d42d2429068496b31a6795adMartijn Coenen
1384049f9d00a86f848d42d2429068496b31a6795adMartijn Coenen        mConnectedTechnology = -1;
13907f3bee2db8b6e93ebbf7222676bd9f468e85569Nick Pelly    }
14007f3bee2db8b6e93ebbf7222676bd9f468e85569Nick Pelly
14107f3bee2db8b6e93ebbf7222676bd9f468e85569Nick Pelly    /**
14207f3bee2db8b6e93ebbf7222676bd9f468e85569Nick Pelly     * Construct a mock Tag.
1434e21e1d21a877cce4db5ec8c5786604cc10f2d7eJeff Hamilton     * <p>This is an application constructed tag, so NfcAdapter methods on this Tag may fail
1444e21e1d21a877cce4db5ec8c5786604cc10f2d7eJeff Hamilton     * with {@link IllegalArgumentException} since it does not represent a physical Tag.
14507f3bee2db8b6e93ebbf7222676bd9f468e85569Nick Pelly     * <p>This constructor might be useful for mock testing.
14607f3bee2db8b6e93ebbf7222676bd9f468e85569Nick Pelly     * @param id The tag identifier, can be null
1476be655c768a82716612c00fdd156254d8dc00f42Jeff Hamilton     * @param techList must not be null
14807f3bee2db8b6e93ebbf7222676bd9f468e85569Nick Pelly     * @return freshly constructed tag
149f003e26df96067b4b136f0859012cb7ec3ed930fNick Pelly     * @hide
15007f3bee2db8b6e93ebbf7222676bd9f468e85569Nick Pelly     */
1516be655c768a82716612c00fdd156254d8dc00f42Jeff Hamilton    public static Tag createMockTag(byte[] id, int[] techList, Bundle[] techListExtras) {
15223fc93a7c1e340e79642d3d0bf4b4658c8645c8eMartijn Coenen        // set serviceHandle to 0 and tagService to null to indicate mock tag
1534e21e1d21a877cce4db5ec8c5786604cc10f2d7eJeff Hamilton        return new Tag(id, techList, techListExtras, 0, null);
154590b73bc5b8e5f7b59bff1d9264a52388a5162e6Nick Pelly    }
155590b73bc5b8e5f7b59bff1d9264a52388a5162e6Nick Pelly
156d88e9aa575eb3a9d20cdb0e8918d54993e1ce1e0Jeff Hamilton    private String[] generateTechStringList(int[] techList) {
157d88e9aa575eb3a9d20cdb0e8918d54993e1ce1e0Jeff Hamilton        final int size = techList.length;
158d88e9aa575eb3a9d20cdb0e8918d54993e1ce1e0Jeff Hamilton        String[] strings = new String[size];
159d88e9aa575eb3a9d20cdb0e8918d54993e1ce1e0Jeff Hamilton        for (int i = 0; i < size; i++) {
160d88e9aa575eb3a9d20cdb0e8918d54993e1ce1e0Jeff Hamilton            switch (techList[i]) {
161d88e9aa575eb3a9d20cdb0e8918d54993e1ce1e0Jeff Hamilton                case TagTechnology.ISO_DEP:
162d88e9aa575eb3a9d20cdb0e8918d54993e1ce1e0Jeff Hamilton                    strings[i] = IsoDep.class.getName();
163d88e9aa575eb3a9d20cdb0e8918d54993e1ce1e0Jeff Hamilton                    break;
164d88e9aa575eb3a9d20cdb0e8918d54993e1ce1e0Jeff Hamilton                case TagTechnology.MIFARE_CLASSIC:
165d88e9aa575eb3a9d20cdb0e8918d54993e1ce1e0Jeff Hamilton                    strings[i] = MifareClassic.class.getName();
166d88e9aa575eb3a9d20cdb0e8918d54993e1ce1e0Jeff Hamilton                    break;
167d88e9aa575eb3a9d20cdb0e8918d54993e1ce1e0Jeff Hamilton                case TagTechnology.MIFARE_ULTRALIGHT:
168d88e9aa575eb3a9d20cdb0e8918d54993e1ce1e0Jeff Hamilton                    strings[i] = MifareUltralight.class.getName();
169d88e9aa575eb3a9d20cdb0e8918d54993e1ce1e0Jeff Hamilton                    break;
170d88e9aa575eb3a9d20cdb0e8918d54993e1ce1e0Jeff Hamilton                case TagTechnology.NDEF:
171d88e9aa575eb3a9d20cdb0e8918d54993e1ce1e0Jeff Hamilton                    strings[i] = Ndef.class.getName();
172d88e9aa575eb3a9d20cdb0e8918d54993e1ce1e0Jeff Hamilton                    break;
173d88e9aa575eb3a9d20cdb0e8918d54993e1ce1e0Jeff Hamilton                case TagTechnology.NDEF_FORMATABLE:
174d88e9aa575eb3a9d20cdb0e8918d54993e1ce1e0Jeff Hamilton                    strings[i] = NdefFormatable.class.getName();
175d88e9aa575eb3a9d20cdb0e8918d54993e1ce1e0Jeff Hamilton                    break;
176d88e9aa575eb3a9d20cdb0e8918d54993e1ce1e0Jeff Hamilton                case TagTechnology.NFC_A:
177d88e9aa575eb3a9d20cdb0e8918d54993e1ce1e0Jeff Hamilton                    strings[i] = NfcA.class.getName();
178d88e9aa575eb3a9d20cdb0e8918d54993e1ce1e0Jeff Hamilton                    break;
179d88e9aa575eb3a9d20cdb0e8918d54993e1ce1e0Jeff Hamilton                case TagTechnology.NFC_B:
180d88e9aa575eb3a9d20cdb0e8918d54993e1ce1e0Jeff Hamilton                    strings[i] = NfcB.class.getName();
181d88e9aa575eb3a9d20cdb0e8918d54993e1ce1e0Jeff Hamilton                    break;
182d88e9aa575eb3a9d20cdb0e8918d54993e1ce1e0Jeff Hamilton                case TagTechnology.NFC_F:
183d88e9aa575eb3a9d20cdb0e8918d54993e1ce1e0Jeff Hamilton                    strings[i] = NfcF.class.getName();
184d88e9aa575eb3a9d20cdb0e8918d54993e1ce1e0Jeff Hamilton                    break;
185d88e9aa575eb3a9d20cdb0e8918d54993e1ce1e0Jeff Hamilton                case TagTechnology.NFC_V:
186d88e9aa575eb3a9d20cdb0e8918d54993e1ce1e0Jeff Hamilton                    strings[i] = NfcV.class.getName();
187d88e9aa575eb3a9d20cdb0e8918d54993e1ce1e0Jeff Hamilton                    break;
188f8538594fe6ba6db3310da042597840601d78cdaMartijn Coenen                case TagTechnology.NFC_BARCODE:
189f8538594fe6ba6db3310da042597840601d78cdaMartijn Coenen                    strings[i] = NfcBarcode.class.getName();
190f8538594fe6ba6db3310da042597840601d78cdaMartijn Coenen                    break;
191d88e9aa575eb3a9d20cdb0e8918d54993e1ce1e0Jeff Hamilton                default:
192d88e9aa575eb3a9d20cdb0e8918d54993e1ce1e0Jeff Hamilton                    throw new IllegalArgumentException("Unknown tech type " + techList[i]);
193d88e9aa575eb3a9d20cdb0e8918d54993e1ce1e0Jeff Hamilton            }
194d88e9aa575eb3a9d20cdb0e8918d54993e1ce1e0Jeff Hamilton        }
195d88e9aa575eb3a9d20cdb0e8918d54993e1ce1e0Jeff Hamilton        return strings;
196d88e9aa575eb3a9d20cdb0e8918d54993e1ce1e0Jeff Hamilton    }
197d88e9aa575eb3a9d20cdb0e8918d54993e1ce1e0Jeff Hamilton
198590b73bc5b8e5f7b59bff1d9264a52388a5162e6Nick Pelly    /**
199590b73bc5b8e5f7b59bff1d9264a52388a5162e6Nick Pelly     * For use by NfcService only.
200590b73bc5b8e5f7b59bff1d9264a52388a5162e6Nick Pelly     * @hide
201590b73bc5b8e5f7b59bff1d9264a52388a5162e6Nick Pelly     */
20207f3bee2db8b6e93ebbf7222676bd9f468e85569Nick Pelly    public int getServiceHandle() {
20307f3bee2db8b6e93ebbf7222676bd9f468e85569Nick Pelly        return mServiceHandle;
204590b73bc5b8e5f7b59bff1d9264a52388a5162e6Nick Pelly    }
205590b73bc5b8e5f7b59bff1d9264a52388a5162e6Nick Pelly
206590b73bc5b8e5f7b59bff1d9264a52388a5162e6Nick Pelly    /**
20707f3bee2db8b6e93ebbf7222676bd9f468e85569Nick Pelly     * Get the Tag Identifier (if it has one).
20874fe6c6b245ebe7d3b3d96962c32980d88dca4f5Nick Pelly     * <p>The tag identifier is a low level serial number, used for anti-collision
20974fe6c6b245ebe7d3b3d96962c32980d88dca4f5Nick Pelly     * and identification.
21074fe6c6b245ebe7d3b3d96962c32980d88dca4f5Nick Pelly     * <p> Most tags have a stable unique identifier
21174fe6c6b245ebe7d3b3d96962c32980d88dca4f5Nick Pelly     * (UID), but some tags will generate a random ID every time they are discovered
21274fe6c6b245ebe7d3b3d96962c32980d88dca4f5Nick Pelly     * (RID), and there are some tags with no ID at all (the byte array will be zero-sized).
21374fe6c6b245ebe7d3b3d96962c32980d88dca4f5Nick Pelly     * <p> The size and format of an ID is specific to the RF technology used by the tag.
21474fe6c6b245ebe7d3b3d96962c32980d88dca4f5Nick Pelly     * <p> This function retrieves the ID as determined at discovery time, and does not
21574fe6c6b245ebe7d3b3d96962c32980d88dca4f5Nick Pelly     * perform any further RF communication or block.
21674fe6c6b245ebe7d3b3d96962c32980d88dca4f5Nick Pelly     * @return ID as byte array, never null
21707f3bee2db8b6e93ebbf7222676bd9f468e85569Nick Pelly     */
21807f3bee2db8b6e93ebbf7222676bd9f468e85569Nick Pelly    public byte[] getId() {
21907f3bee2db8b6e93ebbf7222676bd9f468e85569Nick Pelly        return mId;
22007f3bee2db8b6e93ebbf7222676bd9f468e85569Nick Pelly    }
22107f3bee2db8b6e93ebbf7222676bd9f468e85569Nick Pelly
22207f3bee2db8b6e93ebbf7222676bd9f468e85569Nick Pelly    /**
22374fe6c6b245ebe7d3b3d96962c32980d88dca4f5Nick Pelly     * Get the technologies available in this tag, as fully qualified class names.
22474fe6c6b245ebe7d3b3d96962c32980d88dca4f5Nick Pelly     * <p>
22574fe6c6b245ebe7d3b3d96962c32980d88dca4f5Nick Pelly     * A technology is an implementation of the {@link TagTechnology} interface,
22674fe6c6b245ebe7d3b3d96962c32980d88dca4f5Nick Pelly     * and can be instantiated by calling the static <code>get(Tag)</code>
22774fe6c6b245ebe7d3b3d96962c32980d88dca4f5Nick Pelly     * method on the implementation with this Tag. The {@link TagTechnology}
22874fe6c6b245ebe7d3b3d96962c32980d88dca4f5Nick Pelly     * object can then be used to perform advanced, technology-specific operations on a tag.
22974fe6c6b245ebe7d3b3d96962c32980d88dca4f5Nick Pelly     * <p>
23074fe6c6b245ebe7d3b3d96962c32980d88dca4f5Nick Pelly     * Android defines a mandatory set of technologies that must be correctly
23174fe6c6b245ebe7d3b3d96962c32980d88dca4f5Nick Pelly     * enumerated by all Android NFC devices, and an optional
23274fe6c6b245ebe7d3b3d96962c32980d88dca4f5Nick Pelly     * set of proprietary technologies.
23374fe6c6b245ebe7d3b3d96962c32980d88dca4f5Nick Pelly     * See {@link TagTechnology} for more details.
23474fe6c6b245ebe7d3b3d96962c32980d88dca4f5Nick Pelly     * <p>
235c1576ad627d3d2b2d3c0764c605ebbf3ddc24401Jeff Hamilton     * The ordering of the returned array is undefined and should not be relied upon.
23674fe6c6b245ebe7d3b3d96962c32980d88dca4f5Nick Pelly     * @return an array of fully-qualified {@link TagTechnology} class-names.
237590b73bc5b8e5f7b59bff1d9264a52388a5162e6Nick Pelly     */
238d88e9aa575eb3a9d20cdb0e8918d54993e1ce1e0Jeff Hamilton    public String[] getTechList() {
239d88e9aa575eb3a9d20cdb0e8918d54993e1ce1e0Jeff Hamilton        return mTechStringList;
240590b73bc5b8e5f7b59bff1d9264a52388a5162e6Nick Pelly    }
241590b73bc5b8e5f7b59bff1d9264a52388a5162e6Nick Pelly
2422dcae567ab56285bc70b6857c4f3c87df09641b8Martijn Coenen    /**
2432dcae567ab56285bc70b6857c4f3c87df09641b8Martijn Coenen     * Rediscover the technologies available on this tag.
2442dcae567ab56285bc70b6857c4f3c87df09641b8Martijn Coenen     * <p>
2452dcae567ab56285bc70b6857c4f3c87df09641b8Martijn Coenen     * The technologies that are available on a tag may change due to
2462dcae567ab56285bc70b6857c4f3c87df09641b8Martijn Coenen     * operations being performed on a tag. For example, formatting a
2472dcae567ab56285bc70b6857c4f3c87df09641b8Martijn Coenen     * tag as NDEF adds the {@link Ndef} technology. The {@link rediscover}
2482dcae567ab56285bc70b6857c4f3c87df09641b8Martijn Coenen     * method reenumerates the available technologies on the tag
2492dcae567ab56285bc70b6857c4f3c87df09641b8Martijn Coenen     * and returns a new {@link Tag} object containing these technologies.
2502dcae567ab56285bc70b6857c4f3c87df09641b8Martijn Coenen     * <p>
2512dcae567ab56285bc70b6857c4f3c87df09641b8Martijn Coenen     * You may not be connected to any of this {@link Tag}'s technologies
2522dcae567ab56285bc70b6857c4f3c87df09641b8Martijn Coenen     * when calling this method.
2532dcae567ab56285bc70b6857c4f3c87df09641b8Martijn Coenen     * This method guarantees that you will be returned the same Tag
2542dcae567ab56285bc70b6857c4f3c87df09641b8Martijn Coenen     * if it is still in the field.
2552dcae567ab56285bc70b6857c4f3c87df09641b8Martijn Coenen     * <p>May cause RF activity and may block. Must not be called
2562dcae567ab56285bc70b6857c4f3c87df09641b8Martijn Coenen     * from the main application thread. A blocked call will be canceled with
2572dcae567ab56285bc70b6857c4f3c87df09641b8Martijn Coenen     * {@link IOException} by calling {@link #close} from another thread.
2582dcae567ab56285bc70b6857c4f3c87df09641b8Martijn Coenen     * <p>Does not remove power from the RF field, so a tag having a random
2592dcae567ab56285bc70b6857c4f3c87df09641b8Martijn Coenen     * ID should not change its ID.
2602dcae567ab56285bc70b6857c4f3c87df09641b8Martijn Coenen     * @return the rediscovered tag object.
2612dcae567ab56285bc70b6857c4f3c87df09641b8Martijn Coenen     * @throws IOException if the tag cannot be rediscovered
2622dcae567ab56285bc70b6857c4f3c87df09641b8Martijn Coenen     * @hide
2632dcae567ab56285bc70b6857c4f3c87df09641b8Martijn Coenen     */
2642dcae567ab56285bc70b6857c4f3c87df09641b8Martijn Coenen    // TODO See if we need TagLostException
2652dcae567ab56285bc70b6857c4f3c87df09641b8Martijn Coenen    // TODO Unhide for ICS
2662dcae567ab56285bc70b6857c4f3c87df09641b8Martijn Coenen    // TODO Update documentation to make sure it matches with the final
2672dcae567ab56285bc70b6857c4f3c87df09641b8Martijn Coenen    //      implementation.
2682dcae567ab56285bc70b6857c4f3c87df09641b8Martijn Coenen    public Tag rediscover() throws IOException {
2692dcae567ab56285bc70b6857c4f3c87df09641b8Martijn Coenen        if (getConnectedTechnology() != -1) {
2702dcae567ab56285bc70b6857c4f3c87df09641b8Martijn Coenen            throw new IllegalStateException("Close connection to the technology first!");
2712dcae567ab56285bc70b6857c4f3c87df09641b8Martijn Coenen        }
2722dcae567ab56285bc70b6857c4f3c87df09641b8Martijn Coenen
27323fc93a7c1e340e79642d3d0bf4b4658c8645c8eMartijn Coenen        if (mTagService == null) {
27423fc93a7c1e340e79642d3d0bf4b4658c8645c8eMartijn Coenen            throw new IOException("Mock tags don't support this operation.");
27523fc93a7c1e340e79642d3d0bf4b4658c8645c8eMartijn Coenen        }
2762dcae567ab56285bc70b6857c4f3c87df09641b8Martijn Coenen        try {
2772dcae567ab56285bc70b6857c4f3c87df09641b8Martijn Coenen            Tag newTag = mTagService.rediscover(getServiceHandle());
2782dcae567ab56285bc70b6857c4f3c87df09641b8Martijn Coenen            if (newTag != null) {
2792dcae567ab56285bc70b6857c4f3c87df09641b8Martijn Coenen                return newTag;
2802dcae567ab56285bc70b6857c4f3c87df09641b8Martijn Coenen            } else {
2812dcae567ab56285bc70b6857c4f3c87df09641b8Martijn Coenen                throw new IOException("Failed to rediscover tag");
2822dcae567ab56285bc70b6857c4f3c87df09641b8Martijn Coenen            }
2832dcae567ab56285bc70b6857c4f3c87df09641b8Martijn Coenen        } catch (RemoteException e) {
2842dcae567ab56285bc70b6857c4f3c87df09641b8Martijn Coenen            throw new IOException("NFC service dead");
2852dcae567ab56285bc70b6857c4f3c87df09641b8Martijn Coenen        }
2862dcae567ab56285bc70b6857c4f3c87df09641b8Martijn Coenen    }
2872dcae567ab56285bc70b6857c4f3c87df09641b8Martijn Coenen
2882dcae567ab56285bc70b6857c4f3c87df09641b8Martijn Coenen
2894e21e1d21a877cce4db5ec8c5786604cc10f2d7eJeff Hamilton    /** @hide */
2904e21e1d21a877cce4db5ec8c5786604cc10f2d7eJeff Hamilton    public boolean hasTech(int techType) {
2914e21e1d21a877cce4db5ec8c5786604cc10f2d7eJeff Hamilton        for (int tech : mTechList) {
2924e21e1d21a877cce4db5ec8c5786604cc10f2d7eJeff Hamilton            if (tech == techType) return true;
2934e21e1d21a877cce4db5ec8c5786604cc10f2d7eJeff Hamilton        }
2944e21e1d21a877cce4db5ec8c5786604cc10f2d7eJeff Hamilton        return false;
2954e21e1d21a877cce4db5ec8c5786604cc10f2d7eJeff Hamilton    }
29674fe6c6b245ebe7d3b3d96962c32980d88dca4f5Nick Pelly
2974e21e1d21a877cce4db5ec8c5786604cc10f2d7eJeff Hamilton    /** @hide */
2984e21e1d21a877cce4db5ec8c5786604cc10f2d7eJeff Hamilton    public Bundle getTechExtras(int tech) {
2991253ebc74a8453a88dc47a2b698145098d201681Martijn Coenen        int pos = -1;
3001253ebc74a8453a88dc47a2b698145098d201681Martijn Coenen        for (int idx = 0; idx < mTechList.length; idx++) {
3011253ebc74a8453a88dc47a2b698145098d201681Martijn Coenen          if (mTechList[idx] == tech) {
3021253ebc74a8453a88dc47a2b698145098d201681Martijn Coenen              pos = idx;
3031253ebc74a8453a88dc47a2b698145098d201681Martijn Coenen              break;
3041253ebc74a8453a88dc47a2b698145098d201681Martijn Coenen          }
3051253ebc74a8453a88dc47a2b698145098d201681Martijn Coenen        }
3066be655c768a82716612c00fdd156254d8dc00f42Jeff Hamilton        if (pos < 0) {
3076be655c768a82716612c00fdd156254d8dc00f42Jeff Hamilton            return null;
3086be655c768a82716612c00fdd156254d8dc00f42Jeff Hamilton        }
3096be655c768a82716612c00fdd156254d8dc00f42Jeff Hamilton
3104e21e1d21a877cce4db5ec8c5786604cc10f2d7eJeff Hamilton        return mTechExtras[pos];
3114e21e1d21a877cce4db5ec8c5786604cc10f2d7eJeff Hamilton    }
3126be655c768a82716612c00fdd156254d8dc00f42Jeff Hamilton
3134e21e1d21a877cce4db5ec8c5786604cc10f2d7eJeff Hamilton    /** @hide */
3144e21e1d21a877cce4db5ec8c5786604cc10f2d7eJeff Hamilton    public INfcTag getTagService() {
3154e21e1d21a877cce4db5ec8c5786604cc10f2d7eJeff Hamilton        return mTagService;
31607f3bee2db8b6e93ebbf7222676bd9f468e85569Nick Pelly    }
31707f3bee2db8b6e93ebbf7222676bd9f468e85569Nick Pelly
31874fe6c6b245ebe7d3b3d96962c32980d88dca4f5Nick Pelly    /**
31974fe6c6b245ebe7d3b3d96962c32980d88dca4f5Nick Pelly     * Human-readable description of the tag, for debugging.
32074fe6c6b245ebe7d3b3d96962c32980d88dca4f5Nick Pelly     */
32107f3bee2db8b6e93ebbf7222676bd9f468e85569Nick Pelly    @Override
32207f3bee2db8b6e93ebbf7222676bd9f468e85569Nick Pelly    public String toString() {
3238856c4278d9fd727081083d0f88459a8152d88c0Jeff Hamilton        StringBuilder sb = new StringBuilder("TAG: Tech [");
3248856c4278d9fd727081083d0f88459a8152d88c0Jeff Hamilton        String[] techList = getTechList();
3258856c4278d9fd727081083d0f88459a8152d88c0Jeff Hamilton        int length = techList.length;
3268856c4278d9fd727081083d0f88459a8152d88c0Jeff Hamilton        for (int i = 0; i < length; i++) {
3278856c4278d9fd727081083d0f88459a8152d88c0Jeff Hamilton            sb.append(techList[i]);
3288856c4278d9fd727081083d0f88459a8152d88c0Jeff Hamilton            if (i < length - 1) {
3298856c4278d9fd727081083d0f88459a8152d88c0Jeff Hamilton                sb.append(", ");
3308856c4278d9fd727081083d0f88459a8152d88c0Jeff Hamilton            }
33107f3bee2db8b6e93ebbf7222676bd9f468e85569Nick Pelly        }
3328856c4278d9fd727081083d0f88459a8152d88c0Jeff Hamilton        sb.append("]");
33307f3bee2db8b6e93ebbf7222676bd9f468e85569Nick Pelly        return sb.toString();
33407f3bee2db8b6e93ebbf7222676bd9f468e85569Nick Pelly    }
33507f3bee2db8b6e93ebbf7222676bd9f468e85569Nick Pelly
33607f3bee2db8b6e93ebbf7222676bd9f468e85569Nick Pelly    /*package*/ static byte[] readBytesWithNull(Parcel in) {
33707f3bee2db8b6e93ebbf7222676bd9f468e85569Nick Pelly        int len = in.readInt();
33807f3bee2db8b6e93ebbf7222676bd9f468e85569Nick Pelly        byte[] result = null;
339e2e4ea9ea8f5724403e6267d193a740dc7c78785Sylvain Fonteneau        if (len >= 0) {
34007f3bee2db8b6e93ebbf7222676bd9f468e85569Nick Pelly            result = new byte[len];
34107f3bee2db8b6e93ebbf7222676bd9f468e85569Nick Pelly            in.readByteArray(result);
342590b73bc5b8e5f7b59bff1d9264a52388a5162e6Nick Pelly        }
34307f3bee2db8b6e93ebbf7222676bd9f468e85569Nick Pelly        return result;
34407f3bee2db8b6e93ebbf7222676bd9f468e85569Nick Pelly    }
34507f3bee2db8b6e93ebbf7222676bd9f468e85569Nick Pelly
34607f3bee2db8b6e93ebbf7222676bd9f468e85569Nick Pelly    /*package*/ static void writeBytesWithNull(Parcel out, byte[] b) {
34707f3bee2db8b6e93ebbf7222676bd9f468e85569Nick Pelly        if (b == null) {
34807f3bee2db8b6e93ebbf7222676bd9f468e85569Nick Pelly            out.writeInt(-1);
34907f3bee2db8b6e93ebbf7222676bd9f468e85569Nick Pelly            return;
35007f3bee2db8b6e93ebbf7222676bd9f468e85569Nick Pelly        }
35107f3bee2db8b6e93ebbf7222676bd9f468e85569Nick Pelly        out.writeInt(b.length);
35207f3bee2db8b6e93ebbf7222676bd9f468e85569Nick Pelly        out.writeByteArray(b);
353590b73bc5b8e5f7b59bff1d9264a52388a5162e6Nick Pelly    }
354590b73bc5b8e5f7b59bff1d9264a52388a5162e6Nick Pelly
355590b73bc5b8e5f7b59bff1d9264a52388a5162e6Nick Pelly    @Override
356590b73bc5b8e5f7b59bff1d9264a52388a5162e6Nick Pelly    public int describeContents() {
357590b73bc5b8e5f7b59bff1d9264a52388a5162e6Nick Pelly        return 0;
358590b73bc5b8e5f7b59bff1d9264a52388a5162e6Nick Pelly    }
359590b73bc5b8e5f7b59bff1d9264a52388a5162e6Nick Pelly
360590b73bc5b8e5f7b59bff1d9264a52388a5162e6Nick Pelly    @Override
361590b73bc5b8e5f7b59bff1d9264a52388a5162e6Nick Pelly    public void writeToParcel(Parcel dest, int flags) {
362c5a418ecb7681159ae6674a4d91177c6841537b1Sylvain Fonteneau        // Null mTagService means this is a mock tag
363c5a418ecb7681159ae6674a4d91177c6841537b1Sylvain Fonteneau        int isMock = (mTagService == null)?1:0;
364c5a418ecb7681159ae6674a4d91177c6841537b1Sylvain Fonteneau
36507f3bee2db8b6e93ebbf7222676bd9f468e85569Nick Pelly        writeBytesWithNull(dest, mId);
3666be655c768a82716612c00fdd156254d8dc00f42Jeff Hamilton        dest.writeInt(mTechList.length);
3676be655c768a82716612c00fdd156254d8dc00f42Jeff Hamilton        dest.writeIntArray(mTechList);
3686be655c768a82716612c00fdd156254d8dc00f42Jeff Hamilton        dest.writeTypedArray(mTechExtras, 0);
36907f3bee2db8b6e93ebbf7222676bd9f468e85569Nick Pelly        dest.writeInt(mServiceHandle);
370c5a418ecb7681159ae6674a4d91177c6841537b1Sylvain Fonteneau        dest.writeInt(isMock);
371c5a418ecb7681159ae6674a4d91177c6841537b1Sylvain Fonteneau        if (isMock == 0) {
372c5a418ecb7681159ae6674a4d91177c6841537b1Sylvain Fonteneau            dest.writeStrongBinder(mTagService.asBinder());
373c5a418ecb7681159ae6674a4d91177c6841537b1Sylvain Fonteneau        }
374590b73bc5b8e5f7b59bff1d9264a52388a5162e6Nick Pelly    }
375590b73bc5b8e5f7b59bff1d9264a52388a5162e6Nick Pelly
376590b73bc5b8e5f7b59bff1d9264a52388a5162e6Nick Pelly    public static final Parcelable.Creator<Tag> CREATOR =
377590b73bc5b8e5f7b59bff1d9264a52388a5162e6Nick Pelly            new Parcelable.Creator<Tag>() {
3786be655c768a82716612c00fdd156254d8dc00f42Jeff Hamilton        @Override
379590b73bc5b8e5f7b59bff1d9264a52388a5162e6Nick Pelly        public Tag createFromParcel(Parcel in) {
380c5a418ecb7681159ae6674a4d91177c6841537b1Sylvain Fonteneau            INfcTag tagService;
381c5a418ecb7681159ae6674a4d91177c6841537b1Sylvain Fonteneau
38207f3bee2db8b6e93ebbf7222676bd9f468e85569Nick Pelly            // Tag fields
38307f3bee2db8b6e93ebbf7222676bd9f468e85569Nick Pelly            byte[] id = Tag.readBytesWithNull(in);
3846be655c768a82716612c00fdd156254d8dc00f42Jeff Hamilton            int[] techList = new int[in.readInt()];
3856be655c768a82716612c00fdd156254d8dc00f42Jeff Hamilton            in.readIntArray(techList);
3866be655c768a82716612c00fdd156254d8dc00f42Jeff Hamilton            Bundle[] techExtras = in.createTypedArray(Bundle.CREATOR);
38707f3bee2db8b6e93ebbf7222676bd9f468e85569Nick Pelly            int serviceHandle = in.readInt();
388c5a418ecb7681159ae6674a4d91177c6841537b1Sylvain Fonteneau            int isMock = in.readInt();
389c5a418ecb7681159ae6674a4d91177c6841537b1Sylvain Fonteneau            if (isMock == 0) {
390c5a418ecb7681159ae6674a4d91177c6841537b1Sylvain Fonteneau                tagService = INfcTag.Stub.asInterface(in.readStrongBinder());
391c5a418ecb7681159ae6674a4d91177c6841537b1Sylvain Fonteneau            }
392c5a418ecb7681159ae6674a4d91177c6841537b1Sylvain Fonteneau            else {
393c5a418ecb7681159ae6674a4d91177c6841537b1Sylvain Fonteneau                tagService = null;
394c5a418ecb7681159ae6674a4d91177c6841537b1Sylvain Fonteneau            }
39507f3bee2db8b6e93ebbf7222676bd9f468e85569Nick Pelly
3964e21e1d21a877cce4db5ec8c5786604cc10f2d7eJeff Hamilton            return new Tag(id, techList, techExtras, serviceHandle, tagService);
397590b73bc5b8e5f7b59bff1d9264a52388a5162e6Nick Pelly        }
3986be655c768a82716612c00fdd156254d8dc00f42Jeff Hamilton
3996be655c768a82716612c00fdd156254d8dc00f42Jeff Hamilton        @Override
400590b73bc5b8e5f7b59bff1d9264a52388a5162e6Nick Pelly        public Tag[] newArray(int size) {
401590b73bc5b8e5f7b59bff1d9264a52388a5162e6Nick Pelly            return new Tag[size];
402590b73bc5b8e5f7b59bff1d9264a52388a5162e6Nick Pelly        }
403590b73bc5b8e5f7b59bff1d9264a52388a5162e6Nick Pelly    };
4044049f9d00a86f848d42d2429068496b31a6795adMartijn Coenen
405be372d6462605010910e771cef15d5adccd0a59eJeff Hamilton    /**
406be372d6462605010910e771cef15d5adccd0a59eJeff Hamilton     * For internal use only.
407be372d6462605010910e771cef15d5adccd0a59eJeff Hamilton     *
4084049f9d00a86f848d42d2429068496b31a6795adMartijn Coenen     * @hide
4094049f9d00a86f848d42d2429068496b31a6795adMartijn Coenen     */
4104049f9d00a86f848d42d2429068496b31a6795adMartijn Coenen    public synchronized void setConnectedTechnology(int technology) {
4114049f9d00a86f848d42d2429068496b31a6795adMartijn Coenen        if (mConnectedTechnology == -1) {
4124049f9d00a86f848d42d2429068496b31a6795adMartijn Coenen            mConnectedTechnology = technology;
4134049f9d00a86f848d42d2429068496b31a6795adMartijn Coenen        } else {
4144049f9d00a86f848d42d2429068496b31a6795adMartijn Coenen            throw new IllegalStateException("Close other technology first!");
4154049f9d00a86f848d42d2429068496b31a6795adMartijn Coenen        }
4164049f9d00a86f848d42d2429068496b31a6795adMartijn Coenen    }
4174049f9d00a86f848d42d2429068496b31a6795adMartijn Coenen
418be372d6462605010910e771cef15d5adccd0a59eJeff Hamilton    /**
419be372d6462605010910e771cef15d5adccd0a59eJeff Hamilton     * For internal use only.
420be372d6462605010910e771cef15d5adccd0a59eJeff Hamilton     *
4214049f9d00a86f848d42d2429068496b31a6795adMartijn Coenen     * @hide
4224049f9d00a86f848d42d2429068496b31a6795adMartijn Coenen     */
4234049f9d00a86f848d42d2429068496b31a6795adMartijn Coenen    public int getConnectedTechnology() {
4244049f9d00a86f848d42d2429068496b31a6795adMartijn Coenen        return mConnectedTechnology;
4254049f9d00a86f848d42d2429068496b31a6795adMartijn Coenen    }
4264049f9d00a86f848d42d2429068496b31a6795adMartijn Coenen
427be372d6462605010910e771cef15d5adccd0a59eJeff Hamilton    /**
428be372d6462605010910e771cef15d5adccd0a59eJeff Hamilton     * For internal use only.
429be372d6462605010910e771cef15d5adccd0a59eJeff Hamilton     *
4304049f9d00a86f848d42d2429068496b31a6795adMartijn Coenen     * @hide
4314049f9d00a86f848d42d2429068496b31a6795adMartijn Coenen     */
4324049f9d00a86f848d42d2429068496b31a6795adMartijn Coenen    public void setTechnologyDisconnected() {
4334049f9d00a86f848d42d2429068496b31a6795adMartijn Coenen        mConnectedTechnology = -1;
4344049f9d00a86f848d42d2429068496b31a6795adMartijn Coenen    }
4351253ebc74a8453a88dc47a2b698145098d201681Martijn Coenen}
436