1590b73bc5b8e5f7b59bff1d9264a52388a5162e6Nick Pelly/* 2590b73bc5b8e5f7b59bff1d9264a52388a5162e6Nick Pelly * Copyright (C) 2010 The Android Open Source Project 3590b73bc5b8e5f7b59bff1d9264a52388a5162e6Nick Pelly * 4590b73bc5b8e5f7b59bff1d9264a52388a5162e6Nick Pelly * Licensed under the Apache License, Version 2.0 (the "License"); 5590b73bc5b8e5f7b59bff1d9264a52388a5162e6Nick Pelly * you may not use this file except in compliance with the License. 6590b73bc5b8e5f7b59bff1d9264a52388a5162e6Nick Pelly * You may obtain a copy of the License at 7590b73bc5b8e5f7b59bff1d9264a52388a5162e6Nick Pelly * 8590b73bc5b8e5f7b59bff1d9264a52388a5162e6Nick Pelly * http://www.apache.org/licenses/LICENSE-2.0 9590b73bc5b8e5f7b59bff1d9264a52388a5162e6Nick Pelly * 10590b73bc5b8e5f7b59bff1d9264a52388a5162e6Nick Pelly * Unless required by applicable law or agreed to in writing, software 11590b73bc5b8e5f7b59bff1d9264a52388a5162e6Nick Pelly * distributed under the License is distributed on an "AS IS" BASIS, 12590b73bc5b8e5f7b59bff1d9264a52388a5162e6Nick Pelly * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13590b73bc5b8e5f7b59bff1d9264a52388a5162e6Nick Pelly * See the License for the specific language governing permissions and 14590b73bc5b8e5f7b59bff1d9264a52388a5162e6Nick Pelly * limitations under the License. 15590b73bc5b8e5f7b59bff1d9264a52388a5162e6Nick Pelly */ 16590b73bc5b8e5f7b59bff1d9264a52388a5162e6Nick Pelly 174e21e1d21a877cce4db5ec8c5786604cc10f2d7eJeff Hamiltonpackage android.nfc.tech; 18590b73bc5b8e5f7b59bff1d9264a52388a5162e6Nick Pelly 194049f9d00a86f848d42d2429068496b31a6795adMartijn Coenenimport android.nfc.ErrorCodes; 204e21e1d21a877cce4db5ec8c5786604cc10f2d7eJeff Hamiltonimport android.nfc.Tag; 214e21e1d21a877cce4db5ec8c5786604cc10f2d7eJeff Hamiltonimport android.nfc.TransceiveResult; 22590b73bc5b8e5f7b59bff1d9264a52388a5162e6Nick Pellyimport android.os.RemoteException; 23590b73bc5b8e5f7b59bff1d9264a52388a5162e6Nick Pellyimport android.util.Log; 24590b73bc5b8e5f7b59bff1d9264a52388a5162e6Nick Pelly 254e21e1d21a877cce4db5ec8c5786604cc10f2d7eJeff Hamiltonimport java.io.IOException; 264e21e1d21a877cce4db5ec8c5786604cc10f2d7eJeff Hamilton 27590b73bc5b8e5f7b59bff1d9264a52388a5162e6Nick Pelly/** 286be655c768a82716612c00fdd156254d8dc00f42Jeff Hamilton * A base class for tag technologies that are built on top of transceive(). 29590b73bc5b8e5f7b59bff1d9264a52388a5162e6Nick Pelly */ 301f5badc1cb08f10ddf4b09aaaf34060a23999a51Nick Pellyabstract class BasicTagTechnology implements TagTechnology { 313dd6c458530476eccb33bc05c9c9cd83823bcf8dNick Pelly private static final String TAG = "NFC"; 32590b73bc5b8e5f7b59bff1d9264a52388a5162e6Nick Pelly 331f5badc1cb08f10ddf4b09aaaf34060a23999a51Nick Pelly final Tag mTag; 341f5badc1cb08f10ddf4b09aaaf34060a23999a51Nick Pelly 351f5badc1cb08f10ddf4b09aaaf34060a23999a51Nick Pelly boolean mIsConnected; 361f5badc1cb08f10ddf4b09aaaf34060a23999a51Nick Pelly int mSelectedTechnology; 37590b73bc5b8e5f7b59bff1d9264a52388a5162e6Nick Pelly 384e21e1d21a877cce4db5ec8c5786604cc10f2d7eJeff Hamilton BasicTagTechnology(Tag tag, int tech) throws RemoteException { 39590b73bc5b8e5f7b59bff1d9264a52388a5162e6Nick Pelly mTag = tag; 406be655c768a82716612c00fdd156254d8dc00f42Jeff Hamilton mSelectedTechnology = tech; 41a926540d5455a973dd8ca19c00c108620d9c68c2Sylvain Fonteneau } 42a926540d5455a973dd8ca19c00c108620d9c68c2Sylvain Fonteneau 436be655c768a82716612c00fdd156254d8dc00f42Jeff Hamilton @Override 44590b73bc5b8e5f7b59bff1d9264a52388a5162e6Nick Pelly public Tag getTag() { 45590b73bc5b8e5f7b59bff1d9264a52388a5162e6Nick Pelly return mTag; 46590b73bc5b8e5f7b59bff1d9264a52388a5162e6Nick Pelly } 47590b73bc5b8e5f7b59bff1d9264a52388a5162e6Nick Pelly 48ce3224cda51f946871daa1e11e3976e25c59e6faJeff Hamilton /** Internal helper to throw IllegalStateException if the technology isn't connected */ 49ce3224cda51f946871daa1e11e3976e25c59e6faJeff Hamilton void checkConnected() { 50d88e9aa575eb3a9d20cdb0e8918d54993e1ce1e0Jeff Hamilton if ((mTag.getConnectedTechnology() != mSelectedTechnology) || 514049f9d00a86f848d42d2429068496b31a6795adMartijn Coenen (mTag.getConnectedTechnology() == -1)) { 524049f9d00a86f848d42d2429068496b31a6795adMartijn Coenen throw new IllegalStateException("Call connect() first!"); 534049f9d00a86f848d42d2429068496b31a6795adMartijn Coenen } 544049f9d00a86f848d42d2429068496b31a6795adMartijn Coenen } 554049f9d00a86f848d42d2429068496b31a6795adMartijn Coenen 5672f43886fbf439457a79b0a6af247084f92f1197Jean-Baptiste Queru @Override 57590b73bc5b8e5f7b59bff1d9264a52388a5162e6Nick Pelly public boolean isConnected() { 58a71354d76689802152c33af257092d639c03c421Sylvain Fonteneau if (!mIsConnected) { 59a71354d76689802152c33af257092d639c03c421Sylvain Fonteneau return false; 60a71354d76689802152c33af257092d639c03c421Sylvain Fonteneau } 61a71354d76689802152c33af257092d639c03c421Sylvain Fonteneau 62a71354d76689802152c33af257092d639c03c421Sylvain Fonteneau try { 634e21e1d21a877cce4db5ec8c5786604cc10f2d7eJeff Hamilton return mTag.getTagService().isPresent(mTag.getServiceHandle()); 64a71354d76689802152c33af257092d639c03c421Sylvain Fonteneau } catch (RemoteException e) { 653dd6c458530476eccb33bc05c9c9cd83823bcf8dNick Pelly Log.e(TAG, "NFC service dead", e); 66a71354d76689802152c33af257092d639c03c421Sylvain Fonteneau return false; 67a71354d76689802152c33af257092d639c03c421Sylvain Fonteneau } 68590b73bc5b8e5f7b59bff1d9264a52388a5162e6Nick Pelly } 69590b73bc5b8e5f7b59bff1d9264a52388a5162e6Nick Pelly 706be655c768a82716612c00fdd156254d8dc00f42Jeff Hamilton @Override 71590b73bc5b8e5f7b59bff1d9264a52388a5162e6Nick Pelly public void connect() throws IOException { 724049f9d00a86f848d42d2429068496b31a6795adMartijn Coenen try { 73d88e9aa575eb3a9d20cdb0e8918d54993e1ce1e0Jeff Hamilton int errorCode = mTag.getTagService().connect(mTag.getServiceHandle(), 74d88e9aa575eb3a9d20cdb0e8918d54993e1ce1e0Jeff Hamilton mSelectedTechnology); 754049f9d00a86f848d42d2429068496b31a6795adMartijn Coenen 764049f9d00a86f848d42d2429068496b31a6795adMartijn Coenen if (errorCode == ErrorCodes.SUCCESS) { 774049f9d00a86f848d42d2429068496b31a6795adMartijn Coenen // Store this in the tag object 78d88e9aa575eb3a9d20cdb0e8918d54993e1ce1e0Jeff Hamilton mTag.setConnectedTechnology(mSelectedTechnology); 794049f9d00a86f848d42d2429068496b31a6795adMartijn Coenen mIsConnected = true; 80ea51a4275ab7353d537ff94d97e6294e49b50cabMartijn Coenen } else if (errorCode == ErrorCodes.ERROR_NOT_SUPPORTED) { 81ea51a4275ab7353d537ff94d97e6294e49b50cabMartijn Coenen throw new UnsupportedOperationException("Connecting to " + 82ea51a4275ab7353d537ff94d97e6294e49b50cabMartijn Coenen "this technology is not supported by the NFC " + 83ea51a4275ab7353d537ff94d97e6294e49b50cabMartijn Coenen "adapter."); 844049f9d00a86f848d42d2429068496b31a6795adMartijn Coenen } else { 854049f9d00a86f848d42d2429068496b31a6795adMartijn Coenen throw new IOException(); 864049f9d00a86f848d42d2429068496b31a6795adMartijn Coenen } 874049f9d00a86f848d42d2429068496b31a6795adMartijn Coenen } catch (RemoteException e) { 883dd6c458530476eccb33bc05c9c9cd83823bcf8dNick Pelly Log.e(TAG, "NFC service dead", e); 890d27f999f4b1ad51da11946800b40d2978fc6326Martijn Coenen throw new IOException("NFC service died"); 900d27f999f4b1ad51da11946800b40d2978fc6326Martijn Coenen } 910d27f999f4b1ad51da11946800b40d2978fc6326Martijn Coenen } 920d27f999f4b1ad51da11946800b40d2978fc6326Martijn Coenen 9372f43886fbf439457a79b0a6af247084f92f1197Jean-Baptiste Queru /** @hide */ 940d27f999f4b1ad51da11946800b40d2978fc6326Martijn Coenen @Override 950d27f999f4b1ad51da11946800b40d2978fc6326Martijn Coenen public void reconnect() throws IOException { 960d27f999f4b1ad51da11946800b40d2978fc6326Martijn Coenen if (!mIsConnected) { 970d27f999f4b1ad51da11946800b40d2978fc6326Martijn Coenen throw new IllegalStateException("Technology not connected yet"); 983dd6c458530476eccb33bc05c9c9cd83823bcf8dNick Pelly } 993dd6c458530476eccb33bc05c9c9cd83823bcf8dNick Pelly 1003dd6c458530476eccb33bc05c9c9cd83823bcf8dNick Pelly try { 1014e21e1d21a877cce4db5ec8c5786604cc10f2d7eJeff Hamilton int errorCode = mTag.getTagService().reconnect(mTag.getServiceHandle()); 1020d27f999f4b1ad51da11946800b40d2978fc6326Martijn Coenen 1033dd6c458530476eccb33bc05c9c9cd83823bcf8dNick Pelly if (errorCode != ErrorCodes.SUCCESS) { 1040d27f999f4b1ad51da11946800b40d2978fc6326Martijn Coenen mIsConnected = false; 1050d27f999f4b1ad51da11946800b40d2978fc6326Martijn Coenen mTag.setTechnologyDisconnected(); 1063dd6c458530476eccb33bc05c9c9cd83823bcf8dNick Pelly throw new IOException(); 1070d27f999f4b1ad51da11946800b40d2978fc6326Martijn Coenen } 1083dd6c458530476eccb33bc05c9c9cd83823bcf8dNick Pelly } catch (RemoteException e) { 1093dd6c458530476eccb33bc05c9c9cd83823bcf8dNick Pelly mIsConnected = false; 1103dd6c458530476eccb33bc05c9c9cd83823bcf8dNick Pelly mTag.setTechnologyDisconnected(); 1113dd6c458530476eccb33bc05c9c9cd83823bcf8dNick Pelly Log.e(TAG, "NFC service dead", e); 1123dd6c458530476eccb33bc05c9c9cd83823bcf8dNick Pelly throw new IOException("NFC service died"); 1134049f9d00a86f848d42d2429068496b31a6795adMartijn Coenen } 114590b73bc5b8e5f7b59bff1d9264a52388a5162e6Nick Pelly } 115590b73bc5b8e5f7b59bff1d9264a52388a5162e6Nick Pelly 1166be655c768a82716612c00fdd156254d8dc00f42Jeff Hamilton @Override 1173fcedf77286a078ebd7ac8c082365bd80703dfdcNick Pelly public void close() throws IOException { 118590b73bc5b8e5f7b59bff1d9264a52388a5162e6Nick Pelly try { 119b79173f6602359d00a1a89f4d6505a44d461d796Martijn Coenen /* Note that we don't want to physically disconnect the tag, 120b79173f6602359d00a1a89f4d6505a44d461d796Martijn Coenen * but just reconnect to it to reset its state 121b79173f6602359d00a1a89f4d6505a44d461d796Martijn Coenen */ 122a924973f22aedc580708625e4babb6deabc6b4d3Martijn Coenen mTag.getTagService().resetTimeouts(); 1234e21e1d21a877cce4db5ec8c5786604cc10f2d7eJeff Hamilton mTag.getTagService().reconnect(mTag.getServiceHandle()); 124590b73bc5b8e5f7b59bff1d9264a52388a5162e6Nick Pelly } catch (RemoteException e) { 1253dd6c458530476eccb33bc05c9c9cd83823bcf8dNick Pelly Log.e(TAG, "NFC service dead", e); 1264049f9d00a86f848d42d2429068496b31a6795adMartijn Coenen } finally { 1274049f9d00a86f848d42d2429068496b31a6795adMartijn Coenen mIsConnected = false; 1284049f9d00a86f848d42d2429068496b31a6795adMartijn Coenen mTag.setTechnologyDisconnected(); 129590b73bc5b8e5f7b59bff1d9264a52388a5162e6Nick Pelly } 130590b73bc5b8e5f7b59bff1d9264a52388a5162e6Nick Pelly } 131590b73bc5b8e5f7b59bff1d9264a52388a5162e6Nick Pelly 132faca12adc62d148505fadfd286e6a2752c197fa0Martijn Coenen /** Internal getMaxTransceiveLength() */ 133faca12adc62d148505fadfd286e6a2752c197fa0Martijn Coenen int getMaxTransceiveLengthInternal() { 134faca12adc62d148505fadfd286e6a2752c197fa0Martijn Coenen try { 135faca12adc62d148505fadfd286e6a2752c197fa0Martijn Coenen return mTag.getTagService().getMaxTransceiveLength(mSelectedTechnology); 136faca12adc62d148505fadfd286e6a2752c197fa0Martijn Coenen } catch (RemoteException e) { 137faca12adc62d148505fadfd286e6a2752c197fa0Martijn Coenen Log.e(TAG, "NFC service dead", e); 138faca12adc62d148505fadfd286e6a2752c197fa0Martijn Coenen return 0; 139faca12adc62d148505fadfd286e6a2752c197fa0Martijn Coenen } 140faca12adc62d148505fadfd286e6a2752c197fa0Martijn Coenen } 141ce3224cda51f946871daa1e11e3976e25c59e6faJeff Hamilton /** Internal transceive */ 1421f5badc1cb08f10ddf4b09aaaf34060a23999a51Nick Pelly byte[] transceive(byte[] data, boolean raw) throws IOException { 143f54ad8daf6f9dc2b9670ab1abbbfa4308b40bc6aNick Pelly checkConnected(); 144f54ad8daf6f9dc2b9670ab1abbbfa4308b40bc6aNick Pelly 145f54ad8daf6f9dc2b9670ab1abbbfa4308b40bc6aNick Pelly try { 146d88e9aa575eb3a9d20cdb0e8918d54993e1ce1e0Jeff Hamilton TransceiveResult result = mTag.getTagService().transceive(mTag.getServiceHandle(), 147d88e9aa575eb3a9d20cdb0e8918d54993e1ce1e0Jeff Hamilton data, raw); 148bf34061bb4af12aa9efaab653ae413f2bce4a240Martijn Coenen if (result == null) { 149f54ad8daf6f9dc2b9670ab1abbbfa4308b40bc6aNick Pelly throw new IOException("transceive failed"); 150bf34061bb4af12aa9efaab653ae413f2bce4a240Martijn Coenen } else { 151faca12adc62d148505fadfd286e6a2752c197fa0Martijn Coenen return result.getResponseOrThrow(); 152f54ad8daf6f9dc2b9670ab1abbbfa4308b40bc6aNick Pelly } 153f54ad8daf6f9dc2b9670ab1abbbfa4308b40bc6aNick Pelly } catch (RemoteException e) { 1543dd6c458530476eccb33bc05c9c9cd83823bcf8dNick Pelly Log.e(TAG, "NFC service dead", e); 155f54ad8daf6f9dc2b9670ab1abbbfa4308b40bc6aNick Pelly throw new IOException("NFC service died"); 156f54ad8daf6f9dc2b9670ab1abbbfa4308b40bc6aNick Pelly } 157f54ad8daf6f9dc2b9670ab1abbbfa4308b40bc6aNick Pelly } 158590b73bc5b8e5f7b59bff1d9264a52388a5162e6Nick Pelly} 159