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