Tag.java revision f003e26df96067b4b136f0859012cb7ec3ed930f
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
19d88e9aa575eb3a9d20cdb0e8918d54993e1ce1e0Jeff Hamiltonimport android.nfc.tech.IsoDep;
20d88e9aa575eb3a9d20cdb0e8918d54993e1ce1e0Jeff Hamiltonimport android.nfc.tech.MifareClassic;
21d88e9aa575eb3a9d20cdb0e8918d54993e1ce1e0Jeff Hamiltonimport android.nfc.tech.MifareUltralight;
22d88e9aa575eb3a9d20cdb0e8918d54993e1ce1e0Jeff Hamiltonimport android.nfc.tech.Ndef;
23d88e9aa575eb3a9d20cdb0e8918d54993e1ce1e0Jeff Hamiltonimport android.nfc.tech.NdefFormatable;
24d88e9aa575eb3a9d20cdb0e8918d54993e1ce1e0Jeff Hamiltonimport android.nfc.tech.NfcA;
25d88e9aa575eb3a9d20cdb0e8918d54993e1ce1e0Jeff Hamiltonimport android.nfc.tech.NfcB;
26d88e9aa575eb3a9d20cdb0e8918d54993e1ce1e0Jeff Hamiltonimport android.nfc.tech.NfcF;
27d88e9aa575eb3a9d20cdb0e8918d54993e1ce1e0Jeff Hamiltonimport android.nfc.tech.NfcV;
284e21e1d21a877cce4db5ec8c5786604cc10f2d7eJeff Hamiltonimport android.nfc.tech.TagTechnology;
296be655c768a82716612c00fdd156254d8dc00f42Jeff Hamiltonimport android.os.Bundle;
30590b73bc5b8e5f7b59bff1d9264a52388a5162e6Nick Pellyimport android.os.Parcel;
31590b73bc5b8e5f7b59bff1d9264a52388a5162e6Nick Pellyimport android.os.Parcelable;
326be655c768a82716612c00fdd156254d8dc00f42Jeff Hamilton
336be655c768a82716612c00fdd156254d8dc00f42Jeff Hamiltonimport java.util.Arrays;
34590b73bc5b8e5f7b59bff1d9264a52388a5162e6Nick Pelly
35590b73bc5b8e5f7b59bff1d9264a52388a5162e6Nick Pelly/**
36c9f7890a203a013646650a695157277df81b6a17Scott Main * Represents a (generic) discovered tag.
37590b73bc5b8e5f7b59bff1d9264a52388a5162e6Nick Pelly * <p>
38ce3224cda51f946871daa1e11e3976e25c59e6faJeff Hamilton * A tag is a passive NFC element, such as NFC Forum Tag's, MIFARE class Tags,
39ce3224cda51f946871daa1e11e3976e25c59e6faJeff Hamilton * Sony FeliCa Tags, etc.
40590b73bc5b8e5f7b59bff1d9264a52388a5162e6Nick Pelly * <p>
41590b73bc5b8e5f7b59bff1d9264a52388a5162e6Nick Pelly * Tag's have a type and usually have a UID.
42590b73bc5b8e5f7b59bff1d9264a52388a5162e6Nick Pelly * <p>
43c9f7890a203a013646650a695157277df81b6a17Scott Main * {@link Tag} objects are passed to applications via the {@link NfcAdapter#EXTRA_TAG} extra
44c9f7890a203a013646650a695157277df81b6a17Scott Main * in {@link NfcAdapter#ACTION_TAG_DISCOVERED} intents. A {@link Tag} object is immutable
45c9f7890a203a013646650a695157277df81b6a17Scott Main * and represents the state of the tag at the time of discovery. It can be
464e21e1d21a877cce4db5ec8c5786604cc10f2d7eJeff Hamilton * directly queried for its UID and Type, or used to create a {@link TagTechnology} using the
474e21e1d21a877cce4db5ec8c5786604cc10f2d7eJeff Hamilton * static <code>get()</code> methods on the varios tech classes.
48590b73bc5b8e5f7b59bff1d9264a52388a5162e6Nick Pelly * <p>
496be655c768a82716612c00fdd156254d8dc00f42Jeff Hamilton * A {@link Tag} can  be used to create a {@link TagTechnology} only while the tag is in
50c9f7890a203a013646650a695157277df81b6a17Scott Main * range. If it is removed and then returned to range, then the most recent
51c9f7890a203a013646650a695157277df81b6a17Scott Main * {@link Tag} object (in {@link NfcAdapter#ACTION_TAG_DISCOVERED}) should be used to create a
526be655c768a82716612c00fdd156254d8dc00f42Jeff Hamilton * {@link TagTechnology}.
5307f3bee2db8b6e93ebbf7222676bd9f468e85569Nick Pelly * <p>This is an immutable data class. All properties are set at Tag discovery
5407f3bee2db8b6e93ebbf7222676bd9f468e85569Nick Pelly * time and calls on this class will retrieve those read-only properties, and
5507f3bee2db8b6e93ebbf7222676bd9f468e85569Nick Pelly * not cause any further RF activity or block. Note however that arrays passed to and
5607f3bee2db8b6e93ebbf7222676bd9f468e85569Nick Pelly * returned by this class are *not* cloned, so be careful not to modify them.
57590b73bc5b8e5f7b59bff1d9264a52388a5162e6Nick Pelly */
58f003e26df96067b4b136f0859012cb7ec3ed930fNick Pellypublic final class Tag implements Parcelable {
5907f3bee2db8b6e93ebbf7222676bd9f468e85569Nick Pelly    /*package*/ final byte[] mId;
606be655c768a82716612c00fdd156254d8dc00f42Jeff Hamilton    /*package*/ final int[] mTechList;
61d88e9aa575eb3a9d20cdb0e8918d54993e1ce1e0Jeff Hamilton    /*package*/ final String[] mTechStringList;
626be655c768a82716612c00fdd156254d8dc00f42Jeff Hamilton    /*package*/ final Bundle[] mTechExtras;
6307f3bee2db8b6e93ebbf7222676bd9f468e85569Nick Pelly    /*package*/ final int mServiceHandle;  // for use by NFC service, 0 indicates a mock
644e21e1d21a877cce4db5ec8c5786604cc10f2d7eJeff Hamilton    /*package*/ final INfcTag mTagService;
65a926540d5455a973dd8ca19c00c108620d9c68c2Sylvain Fonteneau
664049f9d00a86f848d42d2429068496b31a6795adMartijn Coenen    /*package*/ int mConnectedTechnology;
674049f9d00a86f848d42d2429068496b31a6795adMartijn Coenen
68590b73bc5b8e5f7b59bff1d9264a52388a5162e6Nick Pelly    /**
6907f3bee2db8b6e93ebbf7222676bd9f468e85569Nick Pelly     * Hidden constructor to be used by NFC service and internal classes.
70590b73bc5b8e5f7b59bff1d9264a52388a5162e6Nick Pelly     * @hide
71590b73bc5b8e5f7b59bff1d9264a52388a5162e6Nick Pelly     */
724e21e1d21a877cce4db5ec8c5786604cc10f2d7eJeff Hamilton    public Tag(byte[] id, int[] techList, Bundle[] techListExtras, int serviceHandle,
734e21e1d21a877cce4db5ec8c5786604cc10f2d7eJeff Hamilton            INfcTag tagService) {
746be655c768a82716612c00fdd156254d8dc00f42Jeff Hamilton        if (techList == null) {
7507f3bee2db8b6e93ebbf7222676bd9f468e85569Nick Pelly            throw new IllegalArgumentException("rawTargets cannot be null");
7607f3bee2db8b6e93ebbf7222676bd9f468e85569Nick Pelly        }
7707f3bee2db8b6e93ebbf7222676bd9f468e85569Nick Pelly        mId = id;
786be655c768a82716612c00fdd156254d8dc00f42Jeff Hamilton        mTechList = Arrays.copyOf(techList, techList.length);
79d88e9aa575eb3a9d20cdb0e8918d54993e1ce1e0Jeff Hamilton        mTechStringList = generateTechStringList(techList);
806be655c768a82716612c00fdd156254d8dc00f42Jeff Hamilton        // Ensure mTechExtras is as long as mTechList
816be655c768a82716612c00fdd156254d8dc00f42Jeff Hamilton        mTechExtras = Arrays.copyOf(techListExtras, techList.length);
8207f3bee2db8b6e93ebbf7222676bd9f468e85569Nick Pelly        mServiceHandle = serviceHandle;
834e21e1d21a877cce4db5ec8c5786604cc10f2d7eJeff Hamilton        mTagService = tagService;
844049f9d00a86f848d42d2429068496b31a6795adMartijn Coenen
854049f9d00a86f848d42d2429068496b31a6795adMartijn Coenen        mConnectedTechnology = -1;
8607f3bee2db8b6e93ebbf7222676bd9f468e85569Nick Pelly    }
8707f3bee2db8b6e93ebbf7222676bd9f468e85569Nick Pelly
8807f3bee2db8b6e93ebbf7222676bd9f468e85569Nick Pelly    /**
8907f3bee2db8b6e93ebbf7222676bd9f468e85569Nick Pelly     * Construct a mock Tag.
904e21e1d21a877cce4db5ec8c5786604cc10f2d7eJeff Hamilton     * <p>This is an application constructed tag, so NfcAdapter methods on this Tag may fail
914e21e1d21a877cce4db5ec8c5786604cc10f2d7eJeff Hamilton     * with {@link IllegalArgumentException} since it does not represent a physical Tag.
9207f3bee2db8b6e93ebbf7222676bd9f468e85569Nick Pelly     * <p>This constructor might be useful for mock testing.
9307f3bee2db8b6e93ebbf7222676bd9f468e85569Nick Pelly     * @param id The tag identifier, can be null
946be655c768a82716612c00fdd156254d8dc00f42Jeff Hamilton     * @param techList must not be null
9507f3bee2db8b6e93ebbf7222676bd9f468e85569Nick Pelly     * @return freshly constructed tag
96f003e26df96067b4b136f0859012cb7ec3ed930fNick Pelly     * @hide
9707f3bee2db8b6e93ebbf7222676bd9f468e85569Nick Pelly     */
986be655c768a82716612c00fdd156254d8dc00f42Jeff Hamilton    public static Tag createMockTag(byte[] id, int[] techList, Bundle[] techListExtras) {
9907f3bee2db8b6e93ebbf7222676bd9f468e85569Nick Pelly        // set serviceHandle to 0 to indicate mock tag
1004e21e1d21a877cce4db5ec8c5786604cc10f2d7eJeff Hamilton        return new Tag(id, techList, techListExtras, 0, null);
101590b73bc5b8e5f7b59bff1d9264a52388a5162e6Nick Pelly    }
102590b73bc5b8e5f7b59bff1d9264a52388a5162e6Nick Pelly
103d88e9aa575eb3a9d20cdb0e8918d54993e1ce1e0Jeff Hamilton    private String[] generateTechStringList(int[] techList) {
104d88e9aa575eb3a9d20cdb0e8918d54993e1ce1e0Jeff Hamilton        final int size = techList.length;
105d88e9aa575eb3a9d20cdb0e8918d54993e1ce1e0Jeff Hamilton        String[] strings = new String[size];
106d88e9aa575eb3a9d20cdb0e8918d54993e1ce1e0Jeff Hamilton        for (int i = 0; i < size; i++) {
107d88e9aa575eb3a9d20cdb0e8918d54993e1ce1e0Jeff Hamilton            switch (techList[i]) {
108d88e9aa575eb3a9d20cdb0e8918d54993e1ce1e0Jeff Hamilton                case TagTechnology.ISO_DEP:
109d88e9aa575eb3a9d20cdb0e8918d54993e1ce1e0Jeff Hamilton                    strings[i] = IsoDep.class.getName();
110d88e9aa575eb3a9d20cdb0e8918d54993e1ce1e0Jeff Hamilton                    break;
111d88e9aa575eb3a9d20cdb0e8918d54993e1ce1e0Jeff Hamilton                case TagTechnology.MIFARE_CLASSIC:
112d88e9aa575eb3a9d20cdb0e8918d54993e1ce1e0Jeff Hamilton                    strings[i] = MifareClassic.class.getName();
113d88e9aa575eb3a9d20cdb0e8918d54993e1ce1e0Jeff Hamilton                    break;
114d88e9aa575eb3a9d20cdb0e8918d54993e1ce1e0Jeff Hamilton                case TagTechnology.MIFARE_ULTRALIGHT:
115d88e9aa575eb3a9d20cdb0e8918d54993e1ce1e0Jeff Hamilton                    strings[i] = MifareUltralight.class.getName();
116d88e9aa575eb3a9d20cdb0e8918d54993e1ce1e0Jeff Hamilton                    break;
117d88e9aa575eb3a9d20cdb0e8918d54993e1ce1e0Jeff Hamilton                case TagTechnology.NDEF:
118d88e9aa575eb3a9d20cdb0e8918d54993e1ce1e0Jeff Hamilton                    strings[i] = Ndef.class.getName();
119d88e9aa575eb3a9d20cdb0e8918d54993e1ce1e0Jeff Hamilton                    break;
120d88e9aa575eb3a9d20cdb0e8918d54993e1ce1e0Jeff Hamilton                case TagTechnology.NDEF_FORMATABLE:
121d88e9aa575eb3a9d20cdb0e8918d54993e1ce1e0Jeff Hamilton                    strings[i] = NdefFormatable.class.getName();
122d88e9aa575eb3a9d20cdb0e8918d54993e1ce1e0Jeff Hamilton                    break;
123d88e9aa575eb3a9d20cdb0e8918d54993e1ce1e0Jeff Hamilton                case TagTechnology.NFC_A:
124d88e9aa575eb3a9d20cdb0e8918d54993e1ce1e0Jeff Hamilton                    strings[i] = NfcA.class.getName();
125d88e9aa575eb3a9d20cdb0e8918d54993e1ce1e0Jeff Hamilton                    break;
126d88e9aa575eb3a9d20cdb0e8918d54993e1ce1e0Jeff Hamilton                case TagTechnology.NFC_B:
127d88e9aa575eb3a9d20cdb0e8918d54993e1ce1e0Jeff Hamilton                    strings[i] = NfcB.class.getName();
128d88e9aa575eb3a9d20cdb0e8918d54993e1ce1e0Jeff Hamilton                    break;
129d88e9aa575eb3a9d20cdb0e8918d54993e1ce1e0Jeff Hamilton                case TagTechnology.NFC_F:
130d88e9aa575eb3a9d20cdb0e8918d54993e1ce1e0Jeff Hamilton                    strings[i] = NfcF.class.getName();
131d88e9aa575eb3a9d20cdb0e8918d54993e1ce1e0Jeff Hamilton                    break;
132d88e9aa575eb3a9d20cdb0e8918d54993e1ce1e0Jeff Hamilton                case TagTechnology.NFC_V:
133d88e9aa575eb3a9d20cdb0e8918d54993e1ce1e0Jeff Hamilton                    strings[i] = NfcV.class.getName();
134d88e9aa575eb3a9d20cdb0e8918d54993e1ce1e0Jeff Hamilton                    break;
135d88e9aa575eb3a9d20cdb0e8918d54993e1ce1e0Jeff Hamilton                default:
136d88e9aa575eb3a9d20cdb0e8918d54993e1ce1e0Jeff Hamilton                    throw new IllegalArgumentException("Unknown tech type " + techList[i]);
137d88e9aa575eb3a9d20cdb0e8918d54993e1ce1e0Jeff Hamilton            }
138d88e9aa575eb3a9d20cdb0e8918d54993e1ce1e0Jeff Hamilton        }
139d88e9aa575eb3a9d20cdb0e8918d54993e1ce1e0Jeff Hamilton        return strings;
140d88e9aa575eb3a9d20cdb0e8918d54993e1ce1e0Jeff Hamilton    }
141d88e9aa575eb3a9d20cdb0e8918d54993e1ce1e0Jeff Hamilton
142590b73bc5b8e5f7b59bff1d9264a52388a5162e6Nick Pelly    /**
143590b73bc5b8e5f7b59bff1d9264a52388a5162e6Nick Pelly     * For use by NfcService only.
144590b73bc5b8e5f7b59bff1d9264a52388a5162e6Nick Pelly     * @hide
145590b73bc5b8e5f7b59bff1d9264a52388a5162e6Nick Pelly     */
14607f3bee2db8b6e93ebbf7222676bd9f468e85569Nick Pelly    public int getServiceHandle() {
14707f3bee2db8b6e93ebbf7222676bd9f468e85569Nick Pelly        return mServiceHandle;
148590b73bc5b8e5f7b59bff1d9264a52388a5162e6Nick Pelly    }
149590b73bc5b8e5f7b59bff1d9264a52388a5162e6Nick Pelly
150590b73bc5b8e5f7b59bff1d9264a52388a5162e6Nick Pelly    /**
15107f3bee2db8b6e93ebbf7222676bd9f468e85569Nick Pelly     * Get the Tag Identifier (if it has one).
15207f3bee2db8b6e93ebbf7222676bd9f468e85569Nick Pelly     * <p>Tag ID is usually a serial number for the tag.
153590b73bc5b8e5f7b59bff1d9264a52388a5162e6Nick Pelly     *
15407f3bee2db8b6e93ebbf7222676bd9f468e85569Nick Pelly     * @return ID, or null if it does not exist
15507f3bee2db8b6e93ebbf7222676bd9f468e85569Nick Pelly     */
15607f3bee2db8b6e93ebbf7222676bd9f468e85569Nick Pelly    public byte[] getId() {
15707f3bee2db8b6e93ebbf7222676bd9f468e85569Nick Pelly        return mId;
15807f3bee2db8b6e93ebbf7222676bd9f468e85569Nick Pelly    }
15907f3bee2db8b6e93ebbf7222676bd9f468e85569Nick Pelly
16007f3bee2db8b6e93ebbf7222676bd9f468e85569Nick Pelly    /**
1616be655c768a82716612c00fdd156254d8dc00f42Jeff Hamilton     * Returns technologies present in the tag that this implementation understands,
1626be655c768a82716612c00fdd156254d8dc00f42Jeff Hamilton     * or a zero length array if there are no supported technologies on this tag.
163c1576ad627d3d2b2d3c0764c605ebbf3ddc24401Jeff Hamilton     *
164d88e9aa575eb3a9d20cdb0e8918d54993e1ce1e0Jeff Hamilton     * The elements of the list are the names of the classes implementing the technology.
165c1576ad627d3d2b2d3c0764c605ebbf3ddc24401Jeff Hamilton     *
166c1576ad627d3d2b2d3c0764c605ebbf3ddc24401Jeff Hamilton     * The ordering of the returned array is undefined and should not be relied upon.
167590b73bc5b8e5f7b59bff1d9264a52388a5162e6Nick Pelly     */
168d88e9aa575eb3a9d20cdb0e8918d54993e1ce1e0Jeff Hamilton    public String[] getTechList() {
169d88e9aa575eb3a9d20cdb0e8918d54993e1ce1e0Jeff Hamilton        return mTechStringList;
170590b73bc5b8e5f7b59bff1d9264a52388a5162e6Nick Pelly    }
171590b73bc5b8e5f7b59bff1d9264a52388a5162e6Nick Pelly
1724e21e1d21a877cce4db5ec8c5786604cc10f2d7eJeff Hamilton    /** @hide */
1734e21e1d21a877cce4db5ec8c5786604cc10f2d7eJeff Hamilton    public boolean hasTech(int techType) {
1744e21e1d21a877cce4db5ec8c5786604cc10f2d7eJeff Hamilton        for (int tech : mTechList) {
1754e21e1d21a877cce4db5ec8c5786604cc10f2d7eJeff Hamilton            if (tech == techType) return true;
1764e21e1d21a877cce4db5ec8c5786604cc10f2d7eJeff Hamilton        }
1774e21e1d21a877cce4db5ec8c5786604cc10f2d7eJeff Hamilton        return false;
1784e21e1d21a877cce4db5ec8c5786604cc10f2d7eJeff Hamilton    }
1794e21e1d21a877cce4db5ec8c5786604cc10f2d7eJeff Hamilton
1804e21e1d21a877cce4db5ec8c5786604cc10f2d7eJeff Hamilton    /** @hide */
1814e21e1d21a877cce4db5ec8c5786604cc10f2d7eJeff Hamilton    public Bundle getTechExtras(int tech) {
1821253ebc74a8453a88dc47a2b698145098d201681Martijn Coenen        int pos = -1;
1831253ebc74a8453a88dc47a2b698145098d201681Martijn Coenen        for (int idx = 0; idx < mTechList.length; idx++) {
1841253ebc74a8453a88dc47a2b698145098d201681Martijn Coenen          if (mTechList[idx] == tech) {
1851253ebc74a8453a88dc47a2b698145098d201681Martijn Coenen              pos = idx;
1861253ebc74a8453a88dc47a2b698145098d201681Martijn Coenen              break;
1871253ebc74a8453a88dc47a2b698145098d201681Martijn Coenen          }
1881253ebc74a8453a88dc47a2b698145098d201681Martijn Coenen        }
1896be655c768a82716612c00fdd156254d8dc00f42Jeff Hamilton        if (pos < 0) {
1906be655c768a82716612c00fdd156254d8dc00f42Jeff Hamilton            return null;
1916be655c768a82716612c00fdd156254d8dc00f42Jeff Hamilton        }
1926be655c768a82716612c00fdd156254d8dc00f42Jeff Hamilton
1934e21e1d21a877cce4db5ec8c5786604cc10f2d7eJeff Hamilton        return mTechExtras[pos];
1944e21e1d21a877cce4db5ec8c5786604cc10f2d7eJeff Hamilton    }
1956be655c768a82716612c00fdd156254d8dc00f42Jeff Hamilton
1964e21e1d21a877cce4db5ec8c5786604cc10f2d7eJeff Hamilton    /** @hide */
1974e21e1d21a877cce4db5ec8c5786604cc10f2d7eJeff Hamilton    public INfcTag getTagService() {
1984e21e1d21a877cce4db5ec8c5786604cc10f2d7eJeff Hamilton        return mTagService;
19907f3bee2db8b6e93ebbf7222676bd9f468e85569Nick Pelly    }
20007f3bee2db8b6e93ebbf7222676bd9f468e85569Nick Pelly
20107f3bee2db8b6e93ebbf7222676bd9f468e85569Nick Pelly    @Override
20207f3bee2db8b6e93ebbf7222676bd9f468e85569Nick Pelly    public String toString() {
20307f3bee2db8b6e93ebbf7222676bd9f468e85569Nick Pelly        StringBuilder sb = new StringBuilder("TAG ")
20407f3bee2db8b6e93ebbf7222676bd9f468e85569Nick Pelly            .append("uid = ")
20507f3bee2db8b6e93ebbf7222676bd9f468e85569Nick Pelly            .append(mId)
2066be655c768a82716612c00fdd156254d8dc00f42Jeff Hamilton            .append(" Tech [");
2076be655c768a82716612c00fdd156254d8dc00f42Jeff Hamilton        for (int i : mTechList) {
2086be655c768a82716612c00fdd156254d8dc00f42Jeff Hamilton            sb.append(i)
20907f3bee2db8b6e93ebbf7222676bd9f468e85569Nick Pelly            .append(", ");
21007f3bee2db8b6e93ebbf7222676bd9f468e85569Nick Pelly        }
21107f3bee2db8b6e93ebbf7222676bd9f468e85569Nick Pelly        return sb.toString();
21207f3bee2db8b6e93ebbf7222676bd9f468e85569Nick Pelly    }
21307f3bee2db8b6e93ebbf7222676bd9f468e85569Nick Pelly
21407f3bee2db8b6e93ebbf7222676bd9f468e85569Nick Pelly    /*package*/ static byte[] readBytesWithNull(Parcel in) {
21507f3bee2db8b6e93ebbf7222676bd9f468e85569Nick Pelly        int len = in.readInt();
21607f3bee2db8b6e93ebbf7222676bd9f468e85569Nick Pelly        byte[] result = null;
217e2e4ea9ea8f5724403e6267d193a740dc7c78785Sylvain Fonteneau        if (len >= 0) {
21807f3bee2db8b6e93ebbf7222676bd9f468e85569Nick Pelly            result = new byte[len];
21907f3bee2db8b6e93ebbf7222676bd9f468e85569Nick Pelly            in.readByteArray(result);
220590b73bc5b8e5f7b59bff1d9264a52388a5162e6Nick Pelly        }
22107f3bee2db8b6e93ebbf7222676bd9f468e85569Nick Pelly        return result;
22207f3bee2db8b6e93ebbf7222676bd9f468e85569Nick Pelly    }
22307f3bee2db8b6e93ebbf7222676bd9f468e85569Nick Pelly
22407f3bee2db8b6e93ebbf7222676bd9f468e85569Nick Pelly    /*package*/ static void writeBytesWithNull(Parcel out, byte[] b) {
22507f3bee2db8b6e93ebbf7222676bd9f468e85569Nick Pelly        if (b == null) {
22607f3bee2db8b6e93ebbf7222676bd9f468e85569Nick Pelly            out.writeInt(-1);
22707f3bee2db8b6e93ebbf7222676bd9f468e85569Nick Pelly            return;
22807f3bee2db8b6e93ebbf7222676bd9f468e85569Nick Pelly        }
22907f3bee2db8b6e93ebbf7222676bd9f468e85569Nick Pelly        out.writeInt(b.length);
23007f3bee2db8b6e93ebbf7222676bd9f468e85569Nick Pelly        out.writeByteArray(b);
231590b73bc5b8e5f7b59bff1d9264a52388a5162e6Nick Pelly    }
232590b73bc5b8e5f7b59bff1d9264a52388a5162e6Nick Pelly
233590b73bc5b8e5f7b59bff1d9264a52388a5162e6Nick Pelly    @Override
234590b73bc5b8e5f7b59bff1d9264a52388a5162e6Nick Pelly    public int describeContents() {
235590b73bc5b8e5f7b59bff1d9264a52388a5162e6Nick Pelly        return 0;
236590b73bc5b8e5f7b59bff1d9264a52388a5162e6Nick Pelly    }
237590b73bc5b8e5f7b59bff1d9264a52388a5162e6Nick Pelly
238590b73bc5b8e5f7b59bff1d9264a52388a5162e6Nick Pelly    @Override
239590b73bc5b8e5f7b59bff1d9264a52388a5162e6Nick Pelly    public void writeToParcel(Parcel dest, int flags) {
240c5a418ecb7681159ae6674a4d91177c6841537b1Sylvain Fonteneau        // Null mTagService means this is a mock tag
241c5a418ecb7681159ae6674a4d91177c6841537b1Sylvain Fonteneau        int isMock = (mTagService == null)?1:0;
242c5a418ecb7681159ae6674a4d91177c6841537b1Sylvain Fonteneau
24307f3bee2db8b6e93ebbf7222676bd9f468e85569Nick Pelly        writeBytesWithNull(dest, mId);
2446be655c768a82716612c00fdd156254d8dc00f42Jeff Hamilton        dest.writeInt(mTechList.length);
2456be655c768a82716612c00fdd156254d8dc00f42Jeff Hamilton        dest.writeIntArray(mTechList);
2466be655c768a82716612c00fdd156254d8dc00f42Jeff Hamilton        dest.writeTypedArray(mTechExtras, 0);
24707f3bee2db8b6e93ebbf7222676bd9f468e85569Nick Pelly        dest.writeInt(mServiceHandle);
248c5a418ecb7681159ae6674a4d91177c6841537b1Sylvain Fonteneau        dest.writeInt(isMock);
249c5a418ecb7681159ae6674a4d91177c6841537b1Sylvain Fonteneau        if (isMock == 0) {
250c5a418ecb7681159ae6674a4d91177c6841537b1Sylvain Fonteneau            dest.writeStrongBinder(mTagService.asBinder());
251c5a418ecb7681159ae6674a4d91177c6841537b1Sylvain Fonteneau        }
252590b73bc5b8e5f7b59bff1d9264a52388a5162e6Nick Pelly    }
253590b73bc5b8e5f7b59bff1d9264a52388a5162e6Nick Pelly
254590b73bc5b8e5f7b59bff1d9264a52388a5162e6Nick Pelly    public static final Parcelable.Creator<Tag> CREATOR =
255590b73bc5b8e5f7b59bff1d9264a52388a5162e6Nick Pelly            new Parcelable.Creator<Tag>() {
2566be655c768a82716612c00fdd156254d8dc00f42Jeff Hamilton        @Override
257590b73bc5b8e5f7b59bff1d9264a52388a5162e6Nick Pelly        public Tag createFromParcel(Parcel in) {
258c5a418ecb7681159ae6674a4d91177c6841537b1Sylvain Fonteneau            INfcTag tagService;
259c5a418ecb7681159ae6674a4d91177c6841537b1Sylvain Fonteneau
26007f3bee2db8b6e93ebbf7222676bd9f468e85569Nick Pelly            // Tag fields
26107f3bee2db8b6e93ebbf7222676bd9f468e85569Nick Pelly            byte[] id = Tag.readBytesWithNull(in);
2626be655c768a82716612c00fdd156254d8dc00f42Jeff Hamilton            int[] techList = new int[in.readInt()];
2636be655c768a82716612c00fdd156254d8dc00f42Jeff Hamilton            in.readIntArray(techList);
2646be655c768a82716612c00fdd156254d8dc00f42Jeff Hamilton            Bundle[] techExtras = in.createTypedArray(Bundle.CREATOR);
26507f3bee2db8b6e93ebbf7222676bd9f468e85569Nick Pelly            int serviceHandle = in.readInt();
266c5a418ecb7681159ae6674a4d91177c6841537b1Sylvain Fonteneau            int isMock = in.readInt();
267c5a418ecb7681159ae6674a4d91177c6841537b1Sylvain Fonteneau            if (isMock == 0) {
268c5a418ecb7681159ae6674a4d91177c6841537b1Sylvain Fonteneau                tagService = INfcTag.Stub.asInterface(in.readStrongBinder());
269c5a418ecb7681159ae6674a4d91177c6841537b1Sylvain Fonteneau            }
270c5a418ecb7681159ae6674a4d91177c6841537b1Sylvain Fonteneau            else {
271c5a418ecb7681159ae6674a4d91177c6841537b1Sylvain Fonteneau                tagService = null;
272c5a418ecb7681159ae6674a4d91177c6841537b1Sylvain Fonteneau            }
27307f3bee2db8b6e93ebbf7222676bd9f468e85569Nick Pelly
2744e21e1d21a877cce4db5ec8c5786604cc10f2d7eJeff Hamilton            return new Tag(id, techList, techExtras, serviceHandle, tagService);
275590b73bc5b8e5f7b59bff1d9264a52388a5162e6Nick Pelly        }
2766be655c768a82716612c00fdd156254d8dc00f42Jeff Hamilton
2776be655c768a82716612c00fdd156254d8dc00f42Jeff Hamilton        @Override
278590b73bc5b8e5f7b59bff1d9264a52388a5162e6Nick Pelly        public Tag[] newArray(int size) {
279590b73bc5b8e5f7b59bff1d9264a52388a5162e6Nick Pelly            return new Tag[size];
280590b73bc5b8e5f7b59bff1d9264a52388a5162e6Nick Pelly        }
281590b73bc5b8e5f7b59bff1d9264a52388a5162e6Nick Pelly    };
2824049f9d00a86f848d42d2429068496b31a6795adMartijn Coenen
283be372d6462605010910e771cef15d5adccd0a59eJeff Hamilton    /**
284be372d6462605010910e771cef15d5adccd0a59eJeff Hamilton     * For internal use only.
285be372d6462605010910e771cef15d5adccd0a59eJeff Hamilton     *
2864049f9d00a86f848d42d2429068496b31a6795adMartijn Coenen     * @hide
2874049f9d00a86f848d42d2429068496b31a6795adMartijn Coenen     */
2884049f9d00a86f848d42d2429068496b31a6795adMartijn Coenen    public synchronized void setConnectedTechnology(int technology) {
2894049f9d00a86f848d42d2429068496b31a6795adMartijn Coenen        if (mConnectedTechnology == -1) {
2904049f9d00a86f848d42d2429068496b31a6795adMartijn Coenen            mConnectedTechnology = technology;
2914049f9d00a86f848d42d2429068496b31a6795adMartijn Coenen        } else {
2924049f9d00a86f848d42d2429068496b31a6795adMartijn Coenen            throw new IllegalStateException("Close other technology first!");
2934049f9d00a86f848d42d2429068496b31a6795adMartijn Coenen        }
2944049f9d00a86f848d42d2429068496b31a6795adMartijn Coenen    }
2954049f9d00a86f848d42d2429068496b31a6795adMartijn Coenen
296be372d6462605010910e771cef15d5adccd0a59eJeff Hamilton    /**
297be372d6462605010910e771cef15d5adccd0a59eJeff Hamilton     * For internal use only.
298be372d6462605010910e771cef15d5adccd0a59eJeff Hamilton     *
2994049f9d00a86f848d42d2429068496b31a6795adMartijn Coenen     * @hide
3004049f9d00a86f848d42d2429068496b31a6795adMartijn Coenen     */
3014049f9d00a86f848d42d2429068496b31a6795adMartijn Coenen    public int getConnectedTechnology() {
3024049f9d00a86f848d42d2429068496b31a6795adMartijn Coenen        return mConnectedTechnology;
3034049f9d00a86f848d42d2429068496b31a6795adMartijn Coenen    }
3044049f9d00a86f848d42d2429068496b31a6795adMartijn Coenen
305be372d6462605010910e771cef15d5adccd0a59eJeff Hamilton    /**
306be372d6462605010910e771cef15d5adccd0a59eJeff Hamilton     * For internal use only.
307be372d6462605010910e771cef15d5adccd0a59eJeff Hamilton     *
3084049f9d00a86f848d42d2429068496b31a6795adMartijn Coenen     * @hide
3094049f9d00a86f848d42d2429068496b31a6795adMartijn Coenen     */
3104049f9d00a86f848d42d2429068496b31a6795adMartijn Coenen    public void setTechnologyDisconnected() {
3114049f9d00a86f848d42d2429068496b31a6795adMartijn Coenen        mConnectedTechnology = -1;
3124049f9d00a86f848d42d2429068496b31a6795adMartijn Coenen    }
3131253ebc74a8453a88dc47a2b698145098d201681Martijn Coenen}
314