/* * Copyright (C) 2010 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package android.nfc.tech; import android.nfc.ErrorCodes; import android.nfc.Tag; import android.nfc.TransceiveResult; import android.os.RemoteException; import android.util.Log; import java.io.IOException; /** * A base class for tag technologies that are built on top of transceive(). */ abstract class BasicTagTechnology implements TagTechnology { private static final String TAG = "NFC"; final Tag mTag; boolean mIsConnected; int mSelectedTechnology; BasicTagTechnology(Tag tag, int tech) throws RemoteException { mTag = tag; mSelectedTechnology = tech; } @Override public Tag getTag() { return mTag; } /** Internal helper to throw IllegalStateException if the technology isn't connected */ void checkConnected() { if ((mTag.getConnectedTechnology() != mSelectedTechnology) || (mTag.getConnectedTechnology() == -1)) { throw new IllegalStateException("Call connect() first!"); } } @Override public boolean isConnected() { if (!mIsConnected) { return false; } try { return mTag.getTagService().isPresent(mTag.getServiceHandle()); } catch (RemoteException e) { Log.e(TAG, "NFC service dead", e); return false; } } @Override public void connect() throws IOException { try { int errorCode = mTag.getTagService().connect(mTag.getServiceHandle(), mSelectedTechnology); if (errorCode == ErrorCodes.SUCCESS) { // Store this in the tag object mTag.setConnectedTechnology(mSelectedTechnology); mIsConnected = true; } else if (errorCode == ErrorCodes.ERROR_NOT_SUPPORTED) { throw new UnsupportedOperationException("Connecting to " + "this technology is not supported by the NFC " + "adapter."); } else { throw new IOException(); } } catch (RemoteException e) { Log.e(TAG, "NFC service dead", e); throw new IOException("NFC service died"); } } /** @hide */ @Override public void reconnect() throws IOException { if (!mIsConnected) { throw new IllegalStateException("Technology not connected yet"); } try { int errorCode = mTag.getTagService().reconnect(mTag.getServiceHandle()); if (errorCode != ErrorCodes.SUCCESS) { mIsConnected = false; mTag.setTechnologyDisconnected(); throw new IOException(); } } catch (RemoteException e) { mIsConnected = false; mTag.setTechnologyDisconnected(); Log.e(TAG, "NFC service dead", e); throw new IOException("NFC service died"); } } @Override public void close() throws IOException { try { /* Note that we don't want to physically disconnect the tag, * but just reconnect to it to reset its state */ mTag.getTagService().resetTimeouts(); mTag.getTagService().reconnect(mTag.getServiceHandle()); } catch (RemoteException e) { Log.e(TAG, "NFC service dead", e); } finally { mIsConnected = false; mTag.setTechnologyDisconnected(); } } /** Internal getMaxTransceiveLength() */ int getMaxTransceiveLengthInternal() { try { return mTag.getTagService().getMaxTransceiveLength(mSelectedTechnology); } catch (RemoteException e) { Log.e(TAG, "NFC service dead", e); return 0; } } /** Internal transceive */ byte[] transceive(byte[] data, boolean raw) throws IOException { checkConnected(); try { TransceiveResult result = mTag.getTagService().transceive(mTag.getServiceHandle(), data, raw); if (result == null) { throw new IOException("transceive failed"); } else { return result.getResponseOrThrow(); } } catch (RemoteException e) { Log.e(TAG, "NFC service dead", e); throw new IOException("NFC service died"); } } }