blob: 63c2de200224ce0d76bd6332f13c925aed4b976c [file] [log] [blame]
Nick Pelly367f41f2011-03-08 11:43:30 -08001/*
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 java.io.IOException;
20
21import android.annotation.SdkConstant;
22import android.annotation.SdkConstant.SdkConstantType;
23import android.content.Context;
24import android.nfc.INfcAdapterExtras;
25import android.nfc.NfcAdapter;
26import android.os.Binder;
27import android.os.Bundle;
28import android.os.IBinder;
29import android.os.RemoteException;
30
31public class NfcExecutionEnvironment {
Nick Pellycc9ee722011-04-26 16:38:00 -070032 private final NfcAdapterExtras mExtras;
Nick Pelly367f41f2011-03-08 11:43:30 -080033
34 /**
35 * Broadcast Action: An ISO-DEP AID was selected.
36 *
37 * <p>This happens as the result of a 'SELECT AID' command from an
38 * external NFC reader/writer.
39 *
40 * <p>Always contains the extra field {@link #EXTRA_AID}
41 *
42 * <p class="note">
43 * Requires the {@link android.Manifest.permission#WRITE_SECURE_SETTINGS} permission
44 * to receive.
45 */
46 @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
47 public static final String ACTION_AID_SELECTED =
48 "com.android.nfc_extras.action.AID_SELECTED";
49
50 /**
51 * Mandatory byte array extra field in {@link #ACTION_AID_SELECTED}.
52 *
53 * <p>Contains the AID selected.
54 * @hide
55 */
56 public static final String EXTRA_AID = "com.android.nfc_extras.extra.AID";
57
mike wakerly2f9ad8b2011-06-27 17:29:30 -070058 /**
59 * Broadcast action: A filtered APDU was received.
60 *
61 * <p>This happens when an APDU of interest was matched by the Nfc adapter,
62 * for instance as the result of matching an externally-configured filter.
63 *
64 * <p>The filter configuration mechanism is not currently defined.
65 *
66 * <p>Always contains the extra field {@link EXTRA_APDU_BYTES}.
67 *
68 * @hide
69 */
70 public static final String ACTION_APDU_RECEIVED =
71 "com.android.nfc_extras.action.APDU_RECEIVED";
72
73 /**
74 * Mandatory byte array extra field in {@link #ACTION_APDU_RECEIVED}.
75 *
76 * <p>Contains the bytes of the received APDU.
77 *
78 * @hide
79 */
80 public static final String EXTRA_APDU_BYTES =
81 "com.android.nfc_extras.extra.APDU_BYTES";
82
83 /**
84 * Broadcast action: An EMV card removal event was detected.
85 *
86 * @hide
87 */
88 public static final String ACTION_EMV_CARD_REMOVAL =
89 "com.android.nfc_extras.action.EMV_CARD_REMOVAL";
90
91 /**
92 * Broadcast action: An adapter implementing MIFARE Classic via card
93 * emulation detected that a block has been accessed.
94 *
95 * <p>This may only be issued for the first block that the reader
96 * authenticates to.
97 *
98 * <p>May contain the extra field {@link #EXTRA_MIFARE_BLOCK}.
99 *
100 * @hide
101 */
102 public static final String ACTION_MIFARE_ACCESS_DETECTED =
103 "com.android.nfc_extras.action.MIFARE_ACCESS_DETECTED";
104
105 /**
106 * Optional integer extra field in {@link #ACTION_MIFARE_ACCESS_DETECTED}.
107 *
108 * <p>Provides the block number being accessed. If not set, the block
109 * number being accessed is unknown.
110 *
111 * @hide
112 */
113 public static final String EXTRA_MIFARE_BLOCK =
114 "com.android.nfc_extras.extra.MIFARE_BLOCK";
115
Nick Pellycc9ee722011-04-26 16:38:00 -0700116 NfcExecutionEnvironment(NfcAdapterExtras extras) {
117 mExtras = extras;
Nick Pelly367f41f2011-03-08 11:43:30 -0800118 }
119
120 /**
121 * Open the NFC Execution Environment on its contact interface.
122 *
123 * <p>Only one process may open the secure element at a time. If it is
124 * already open, an {@link IOException} is thrown.
125 *
126 * <p>All other NFC functionality is disabled while the NFC-EE is open
127 * on its contact interface, so make sure to call {@link #close} once complete.
128 *
129 * <p class="note">
130 * Requires the {@link android.Manifest.permission#WRITE_SECURE_SETTINGS} permission.
131 *
132 * @throws IOException if the NFC-EE is already open, or some other error occurs
133 */
134 public void open() throws IOException {
135 try {
Nick Pellycc9ee722011-04-26 16:38:00 -0700136 Bundle b = mExtras.getService().open(new Binder());
Nick Pelly367f41f2011-03-08 11:43:30 -0800137 throwBundle(b);
138 } catch (RemoteException e) {
Nick Pellycc9ee722011-04-26 16:38:00 -0700139 mExtras.attemptDeadServiceRecovery(e);
140 throw new IOException("NFC Service was dead, try again");
Nick Pelly367f41f2011-03-08 11:43:30 -0800141 }
142 }
143
144 /**
145 * Close the NFC Execution Environment on its contact interface.
146 *
147 * <p class="note">
148 * Requires the {@link android.Manifest.permission#WRITE_SECURE_SETTINGS} permission.
149 *
150 * @throws IOException if the NFC-EE is already open, or some other error occurs
151 */
152 public void close() throws IOException {
153 try {
Nick Pellycc9ee722011-04-26 16:38:00 -0700154 throwBundle(mExtras.getService().close());
Nick Pelly367f41f2011-03-08 11:43:30 -0800155 } catch (RemoteException e) {
Nick Pellycc9ee722011-04-26 16:38:00 -0700156 mExtras.attemptDeadServiceRecovery(e);
157 throw new IOException("NFC Service was dead");
Nick Pelly367f41f2011-03-08 11:43:30 -0800158 }
159 }
160
161 /**
162 * Send raw commands to the NFC-EE and receive the response.
163 *
164 * <p class="note">
165 * Requires the {@link android.Manifest.permission#WRITE_SECURE_SETTINGS} permission.
166 *
167 * @throws IOException if the NFC-EE is not open, or some other error occurs
168 */
169 public byte[] transceive(byte[] in) throws IOException {
170 Bundle b;
171 try {
Nick Pellycc9ee722011-04-26 16:38:00 -0700172 b = mExtras.getService().transceive(in);
Nick Pelly367f41f2011-03-08 11:43:30 -0800173 } catch (RemoteException e) {
Nick Pellycc9ee722011-04-26 16:38:00 -0700174 mExtras.attemptDeadServiceRecovery(e);
175 throw new IOException("NFC Service was dead, need to re-open");
Nick Pelly367f41f2011-03-08 11:43:30 -0800176 }
177 throwBundle(b);
178 return b.getByteArray("out");
179 }
180
181 private static void throwBundle(Bundle b) throws IOException {
182 if (b.getInt("e") == -1) {
183 throw new IOException(b.getString("m"));
184 }
185 }
186}