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