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