BasicTagTechnology.java revision d88e9aa575eb3a9d20cdb0e8918d54993e1ce1e0
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        mTag = tag;
40        mSelectedTechnology = tech;
41    }
42
43    @Override
44    public Tag getTag() {
45        return mTag;
46    }
47
48    /** Internal helper to throw IllegalStateException if the technology isn't connected */
49    void checkConnected() {
50       if ((mTag.getConnectedTechnology() != mSelectedTechnology) ||
51               (mTag.getConnectedTechnology() == -1)) {
52           throw new IllegalStateException("Call connect() first!");
53       }
54    }
55
56    /**
57     * Helper to indicate if {@link #connect} has succeeded.
58     * <p>
59     * Does not cause RF activity, and does not block.
60     * @return true if {@link #connect} has completed successfully and the {@link Tag} is believed
61     * to be within range. Applications must still handle {@link java.io.IOException}
62     * while using methods that require a connection in case the connection is lost after this
63     * method returns.
64     */
65    public boolean isConnected() {
66        if (!mIsConnected) {
67            return false;
68        }
69
70        try {
71            return mTag.getTagService().isPresent(mTag.getServiceHandle());
72        } catch (RemoteException e) {
73            Log.e(TAG, "NFC service dead", e);
74            return false;
75        }
76    }
77
78    @Override
79    public void connect() throws IOException {
80        try {
81            int errorCode = mTag.getTagService().connect(mTag.getServiceHandle(),
82                    mSelectedTechnology);
83
84            if (errorCode == ErrorCodes.SUCCESS) {
85                // Store this in the tag object
86                mTag.setConnectedTechnology(mSelectedTechnology);
87                mIsConnected = true;
88            } else {
89                throw new IOException();
90            }
91        } catch (RemoteException e) {
92            Log.e(TAG, "NFC service dead", e);
93            throw new IOException("NFC service died");
94        }
95    }
96
97    @Override
98    public void reconnect() throws IOException {
99        if (!mIsConnected) {
100            throw new IllegalStateException("Technology not connected yet");
101        }
102
103        try {
104            int errorCode = mTag.getTagService().reconnect(mTag.getServiceHandle());
105
106            if (errorCode != ErrorCodes.SUCCESS) {
107                mIsConnected = false;
108                mTag.setTechnologyDisconnected();
109                throw new IOException();
110            }
111        } catch (RemoteException e) {
112            mIsConnected = false;
113            mTag.setTechnologyDisconnected();
114            Log.e(TAG, "NFC service dead", e);
115            throw new IOException("NFC service died");
116        }
117    }
118
119    @Override
120    public void close() {
121        try {
122            /* Note that we don't want to physically disconnect the tag,
123             * but just reconnect to it to reset its state
124             */
125            mTag.getTagService().reconnect(mTag.getServiceHandle());
126        } catch (RemoteException e) {
127            Log.e(TAG, "NFC service dead", e);
128        } finally {
129            mIsConnected = false;
130            mTag.setTechnologyDisconnected();
131        }
132    }
133
134    /** Internal transceive */
135    /*package*/ byte[] transceive(byte[] data, boolean raw) throws IOException {
136        checkConnected();
137
138        try {
139            TransceiveResult result = mTag.getTagService().transceive(mTag.getServiceHandle(),
140                    data, raw);
141            if (result == null) {
142                throw new IOException("transceive failed");
143            } else {
144                if (result.isSuccessful()) {
145                    return result.getResponseData();
146                } else {
147                    if (result.isTagLost()) {
148                        throw new TagLostException("Tag was lost.");
149                    }
150                    else {
151                        throw new IOException("transceive failed");
152                    }
153                }
154            }
155        } catch (RemoteException e) {
156            Log.e(TAG, "NFC service dead", e);
157            throw new IOException("NFC service died");
158        }
159    }
160}
161