BasicTagTechnology.java revision 4e21e1d21a877cce4db5ec8c5786604cc10f2d7e
1/*
2 * Copyright (C) 2010 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 *      http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17package android.nfc.tech;
18
19import android.nfc.ErrorCodes;
20import android.nfc.Tag;
21import android.nfc.TagLostException;
22import android.nfc.TransceiveResult;
23import android.os.RemoteException;
24import android.util.Log;
25
26import java.io.IOException;
27
28/**
29 * A base class for tag technologies that are built on top of transceive().
30 */
31/* package */ abstract class BasicTagTechnology implements TagTechnology {
32    private static final String TAG = "NFC";
33
34    /*package*/ final Tag mTag;
35    /*package*/ boolean mIsConnected;
36    /*package*/ int mSelectedTechnology;
37
38    BasicTagTechnology(Tag tag, int tech) throws RemoteException {
39        int[] techList = tag.getTechnologyList();
40        int i;
41
42        // Check target validity
43        for (i = 0; i < techList.length; i++) {
44            if (tech == techList[i]) {
45                break;
46            }
47        }
48        if (i >= techList.length) {
49            // Technology not found
50            throw new IllegalArgumentException("Technology " + tech + " not present on tag " + tag);
51        }
52
53        mTag = tag;
54        mSelectedTechnology = tech;
55    }
56
57    BasicTagTechnology(Tag tag) throws RemoteException {
58        this(tag, tag.getTechnologyList()[0]);
59    }
60
61    @Override
62    public Tag getTag() {
63        return mTag;
64    }
65
66    /** Internal helper to throw IllegalStateException if the technology isn't connected */
67    void checkConnected() {
68       if ((mTag.getConnectedTechnology() != getTechnologyId()) ||
69               (mTag.getConnectedTechnology() == -1)) {
70           throw new IllegalStateException("Call connect() first!");
71       }
72    }
73
74    @Override
75    public int getTechnologyId() {
76        return mSelectedTechnology;
77    }
78
79    /**
80     * Helper to indicate if {@link #connect} has succeeded.
81     * <p>
82     * Does not cause RF activity, and does not block.
83     * @return true if {@link #connect} has completed successfully and the {@link Tag} is believed
84     * to be within range. Applications must still handle {@link java.io.IOException}
85     * while using methods that require a connection in case the connection is lost after this
86     * method returns.
87     */
88    public boolean isConnected() {
89        if (!mIsConnected) {
90            return false;
91        }
92
93        try {
94            return mTag.getTagService().isPresent(mTag.getServiceHandle());
95        } catch (RemoteException e) {
96            Log.e(TAG, "NFC service dead", e);
97            return false;
98        }
99    }
100
101    @Override
102    public void connect() throws IOException {
103        try {
104            int errorCode = mTag.getTagService().connect(mTag.getServiceHandle(), getTechnologyId());
105
106            if (errorCode == ErrorCodes.SUCCESS) {
107                // Store this in the tag object
108                mTag.setConnectedTechnology(getTechnologyId());
109                mIsConnected = true;
110            } else {
111                throw new IOException();
112            }
113        } catch (RemoteException e) {
114            Log.e(TAG, "NFC service dead", e);
115            throw new IOException("NFC service died");
116        }
117    }
118
119    @Override
120    public void reconnect() throws IOException {
121        if (!mIsConnected) {
122            throw new IllegalStateException("Technology not connected yet");
123        }
124
125        try {
126            int errorCode = mTag.getTagService().reconnect(mTag.getServiceHandle());
127
128            if (errorCode != ErrorCodes.SUCCESS) {
129                mIsConnected = false;
130                mTag.setTechnologyDisconnected();
131                throw new IOException();
132            }
133        } catch (RemoteException e) {
134            mIsConnected = false;
135            mTag.setTechnologyDisconnected();
136            Log.e(TAG, "NFC service dead", e);
137            throw new IOException("NFC service died");
138        }
139    }
140
141    @Override
142    public void close() {
143        try {
144            /* Note that we don't want to physically disconnect the tag,
145             * but just reconnect to it to reset its state
146             */
147            mTag.getTagService().reconnect(mTag.getServiceHandle());
148        } catch (RemoteException e) {
149            Log.e(TAG, "NFC service dead", e);
150        } finally {
151            mIsConnected = false;
152            mTag.setTechnologyDisconnected();
153        }
154    }
155
156    /** Internal transceive */
157    /*package*/ byte[] transceive(byte[] data, boolean raw) throws IOException {
158        checkConnected();
159
160        try {
161            TransceiveResult result = mTag.getTagService().transceive(mTag.getServiceHandle(), data, raw);
162            if (result == null) {
163                throw new IOException("transceive failed");
164            } else {
165                if (result.isSuccessful()) {
166                    return result.getResponseData();
167                } else {
168                    if (result.isTagLost()) {
169                        throw new TagLostException("Tag was lost.");
170                    }
171                    else {
172                        throw new IOException("transceive failed");
173                    }
174                }
175            }
176        } catch (RemoteException e) {
177            Log.e(TAG, "NFC service dead", e);
178            throw new IOException("NFC service died");
179        }
180    }
181}
182