NfcAdapterExtras.java revision ab8f48c2ee524f67e5c3cab5846119e6c8a645b5
1/*
2 * Copyright (C) 2011 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 com.android.nfc_extras;
18
19import android.annotation.SdkConstant;
20import android.annotation.SdkConstant.SdkConstantType;
21import android.nfc.ApduList;
22import android.nfc.INfcAdapterExtras;
23import android.nfc.NfcAdapter;
24import android.os.RemoteException;
25import android.util.Log;
26
27/**
28 * Provides additional methods on an {@link NfcAdapter} for Card Emulation
29 * and management of {@link NfcExecutionEnvironment}'s.
30 *
31 * There is a 1-1 relationship between an {@link NfcAdapterExtras} object and
32 * a {@link NfcAdapter} object.
33 */
34public final class NfcAdapterExtras {
35    private static final String TAG = "NfcAdapterExtras";
36
37    /**
38     * Broadcast Action: an RF field ON has been detected.
39     *
40     * <p class="note">This is an unreliable signal, and will be removed.
41     * <p class="note">
42     * Requires the {@link android.Manifest.permission#WRITE_SECURE_SETTINGS} permission
43     * to receive.
44     */
45    public static final String ACTION_RF_FIELD_ON_DETECTED =
46            "com.android.nfc_extras.action.RF_FIELD_ON_DETECTED";
47
48    /**
49     * Broadcast Action: an RF field OFF has been detected.
50     *
51     * <p class="note">This is an unreliable signal, and will be removed.
52     * <p class="note">
53     * Requires the {@link android.Manifest.permission#WRITE_SECURE_SETTINGS} permission
54     * to receive.
55     */
56    public static final String ACTION_RF_FIELD_OFF_DETECTED =
57            "com.android.nfc_extras.action.RF_FIELD_OFF_DETECTED";
58
59    // protected by NfcAdapterExtras.class, and final after first construction
60    private static INfcAdapterExtras sService;
61    private static NfcAdapterExtras sSingleton;
62    private static NfcExecutionEnvironment sEmbeddedEe;
63    private static CardEmulationRoute sRouteOff;
64    private static CardEmulationRoute sRouteOnWhenScreenOn;
65
66    /**
67     * Get the {@link NfcAdapterExtras} for the given {@link NfcAdapter}.
68     *
69     * <p class="note">
70     * Requires the {@link android.Manifest.permission#WRITE_SECURE_SETTINGS} permission.
71     *
72     * @param adapter a {@link NfcAdapter}, must not be null
73     * @return the {@link NfcAdapterExtras} object for the given {@link NfcAdapter}
74     */
75    public static NfcAdapterExtras get(NfcAdapter adapter) {
76        synchronized(NfcAdapterExtras.class) {
77            if (sSingleton == null) {
78                try {
79                    sService = adapter.getNfcAdapterExtrasInterface();
80                    sEmbeddedEe = new NfcExecutionEnvironment(sService);
81                    sRouteOff = new CardEmulationRoute(CardEmulationRoute.ROUTE_OFF, null);
82                    sRouteOnWhenScreenOn = new CardEmulationRoute(
83                            CardEmulationRoute.ROUTE_ON_WHEN_SCREEN_ON, sEmbeddedEe);
84                    sSingleton = new NfcAdapterExtras();
85                } finally {
86                    if (sSingleton == null) {
87                        sService = null;
88                        sEmbeddedEe = null;
89                        sRouteOff = null;
90                        sRouteOnWhenScreenOn = null;
91                    }
92                }
93            }
94            return sSingleton;
95        }
96    }
97
98    private NfcAdapterExtras() {}
99
100    /**
101     * Immutable data class that describes a card emulation route.
102     */
103    public final static class CardEmulationRoute {
104        /**
105         * Card Emulation is turned off on this NfcAdapter.
106         * <p>This is the default routing state after boot.
107         */
108        public static final int ROUTE_OFF = 1;
109
110        /**
111         * Card Emulation is routed to {@link #nfcEe} only when the screen is on,
112         * otherwise it is turned off.
113         */
114        public static final int ROUTE_ON_WHEN_SCREEN_ON = 2;
115
116        /**
117         * A route such as {@link #ROUTE_OFF} or {@link #ROUTE_ON_WHEN_SCREEN_ON}.
118         */
119        public final int route;
120
121        /**
122         * The {@link NFcExecutionEnvironment} that is Card Emulation is routed to.
123         * <p>null if {@link #route} is {@link #ROUTE_OFF}, otherwise not null.
124         */
125        public final NfcExecutionEnvironment nfcEe;
126
127        public CardEmulationRoute(int route, NfcExecutionEnvironment nfcEe) {
128            if (route == ROUTE_OFF && nfcEe != null) {
129                throw new IllegalArgumentException("must not specifiy a NFC-EE with ROUTE_OFF");
130            } else if (route != ROUTE_OFF && nfcEe == null) {
131                throw new IllegalArgumentException("must specifiy a NFC-EE for this route");
132            }
133            this.route = route;
134            this.nfcEe = nfcEe;
135        }
136    }
137
138    /**
139     * Get the routing state of this NFC EE.
140     *
141     * <p class="note">
142     * Requires the {@link android.Manifest.permission#WRITE_SECURE_SETTINGS} permission.
143     *
144     * @return
145     */
146    public CardEmulationRoute getCardEmulationRoute() {
147        try {
148            int route = sService.getCardEmulationRoute();
149            return route == CardEmulationRoute.ROUTE_OFF ?
150                    sRouteOff :
151                    sRouteOnWhenScreenOn;
152        } catch (RemoteException e) {
153            Log.e(TAG, "", e);
154            return sRouteOff;
155        }
156    }
157
158    /**
159     * Set the routing state of this NFC EE.
160     *
161     * <p>This routing state is not persisted across reboot.
162     *
163     * <p class="note">
164     * Requires the {@link android.Manifest.permission#WRITE_SECURE_SETTINGS} permission.
165     *
166     * @param route a {@link #CardEmulationRoute}
167     */
168    public void setCardEmulationRoute(CardEmulationRoute route) {
169        try {
170            sService.setCardEmulationRoute(route.route);
171        } catch (RemoteException e) {
172            Log.e(TAG, "", e);
173        }
174    }
175
176    /**
177     * Get the {@link NfcExecutionEnvironment} that is embedded with the
178     * {@link NFcAdapter}.
179     *
180     * <p class="note">
181     * Requires the {@link android.Manifest.permission#WRITE_SECURE_SETTINGS} permission.
182     *
183     * @return a {@link NfcExecutionEnvironment}, or null if there is no embedded NFC-EE
184     */
185    public NfcExecutionEnvironment getEmbeddedExecutionEnvironment() {
186        return sEmbeddedEe;
187    }
188
189    public void registerTearDownApdus(String packageName, ApduList apdus) {
190        try {
191            sService.registerTearDownApdus(packageName, apdus);
192        } catch (RemoteException e) {
193            Log.e(TAG, "", e);
194        }
195    }
196
197    public void unregisterTearDownApdus(String packageName) {
198        try {
199            sService.unregisterTearDownApdus(packageName);
200        } catch (RemoteException e) {
201            Log.e(TAG, "", e);
202        }
203    }
204}
205