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 
17 package android.nfc.tech;
18 
19 import android.nfc.ErrorCodes;
20 import android.nfc.Tag;
21 import android.nfc.TransceiveResult;
22 import android.os.RemoteException;
23 import android.util.Log;
24 
25 import java.io.IOException;
26 
27 /**
28  * A base class for tag technologies that are built on top of transceive().
29  */
30 abstract class BasicTagTechnology implements TagTechnology {
31     private static final String TAG = "NFC";
32 
33     final Tag mTag;
34 
35     boolean mIsConnected;
36     int mSelectedTechnology;
37 
BasicTagTechnology(Tag tag, int tech)38     BasicTagTechnology(Tag tag, int tech) throws RemoteException {
39         mTag = tag;
40         mSelectedTechnology = tech;
41     }
42 
43     @Override
getTag()44     public Tag getTag() {
45         return mTag;
46     }
47 
48     /** Internal helper to throw IllegalStateException if the technology isn't connected */
checkConnected()49     void checkConnected() {
50        if ((mTag.getConnectedTechnology() != mSelectedTechnology) ||
51                (mTag.getConnectedTechnology() == -1)) {
52            throw new IllegalStateException("Call connect() first!");
53        }
54     }
55 
56     @Override
isConnected()57     public boolean isConnected() {
58         if (!mIsConnected) {
59             return false;
60         }
61 
62         try {
63             return mTag.getTagService().isPresent(mTag.getServiceHandle());
64         } catch (RemoteException e) {
65             Log.e(TAG, "NFC service dead", e);
66             return false;
67         }
68     }
69 
70     @Override
connect()71     public void connect() throws IOException {
72         try {
73             int errorCode = mTag.getTagService().connect(mTag.getServiceHandle(),
74                     mSelectedTechnology);
75 
76             if (errorCode == ErrorCodes.SUCCESS) {
77                 // Store this in the tag object
78                 mTag.setConnectedTechnology(mSelectedTechnology);
79                 mIsConnected = true;
80             } else if (errorCode == ErrorCodes.ERROR_NOT_SUPPORTED) {
81                 throw new UnsupportedOperationException("Connecting to " +
82                         "this technology is not supported by the NFC " +
83                         "adapter.");
84             } else {
85                 throw new IOException();
86             }
87         } catch (RemoteException e) {
88             Log.e(TAG, "NFC service dead", e);
89             throw new IOException("NFC service died");
90         }
91     }
92 
93     /** @hide */
94     @Override
reconnect()95     public void reconnect() throws IOException {
96         if (!mIsConnected) {
97             throw new IllegalStateException("Technology not connected yet");
98         }
99 
100         try {
101             int errorCode = mTag.getTagService().reconnect(mTag.getServiceHandle());
102 
103             if (errorCode != ErrorCodes.SUCCESS) {
104                 mIsConnected = false;
105                 mTag.setTechnologyDisconnected();
106                 throw new IOException();
107             }
108         } catch (RemoteException e) {
109             mIsConnected = false;
110             mTag.setTechnologyDisconnected();
111             Log.e(TAG, "NFC service dead", e);
112             throw new IOException("NFC service died");
113         }
114     }
115 
116     @Override
close()117     public void close() throws IOException {
118         try {
119             /* Note that we don't want to physically disconnect the tag,
120              * but just reconnect to it to reset its state
121              */
122             mTag.getTagService().resetTimeouts();
123             mTag.getTagService().reconnect(mTag.getServiceHandle());
124         } catch (RemoteException e) {
125             Log.e(TAG, "NFC service dead", e);
126         } finally {
127             mIsConnected = false;
128             mTag.setTechnologyDisconnected();
129         }
130     }
131 
132     /** Internal getMaxTransceiveLength() */
getMaxTransceiveLengthInternal()133     int getMaxTransceiveLengthInternal() {
134         try {
135             return mTag.getTagService().getMaxTransceiveLength(mSelectedTechnology);
136         } catch (RemoteException e) {
137             Log.e(TAG, "NFC service dead", e);
138             return 0;
139         }
140     }
141     /** Internal transceive */
transceive(byte[] data, boolean raw)142     byte[] transceive(byte[] data, boolean raw) throws IOException {
143         checkConnected();
144 
145         try {
146             TransceiveResult result = mTag.getTagService().transceive(mTag.getServiceHandle(),
147                     data, raw);
148             if (result == null) {
149                 throw new IOException("transceive failed");
150             } else {
151                 return result.getResponseOrThrow();
152             }
153         } catch (RemoteException e) {
154             Log.e(TAG, "NFC service dead", e);
155             throw new IOException("NFC service died");
156         }
157     }
158 }
159