diff --git a/Android.mk b/Android.mk index 009c80c1f035e..09e471f34fb6e 100644 --- a/Android.mk +++ b/Android.mk @@ -121,10 +121,10 @@ LOCAL_SRC_FILES += \ core/java/android/nfc/ILlcpServiceSocket.aidl \ core/java/android/nfc/ILlcpSocket.aidl \ core/java/android/nfc/INfcAdapter.aidl \ + core/java/android/nfc/INfcAdapterExtras.aidl \ core/java/android/nfc/INfcTag.aidl \ core/java/android/nfc/IP2pInitiator.aidl \ core/java/android/nfc/IP2pTarget.aidl \ - core/java/android/nfc/INfcSecureElement.aidl \ core/java/android/os/IHardwareService.aidl \ core/java/android/os/IMessenger.aidl \ core/java/android/os/INetworkManagementService.aidl \ diff --git a/CleanSpec.mk b/CleanSpec.mk index 2ee8f3122ec2e..8c3b17e2fa5f4 100644 --- a/CleanSpec.mk +++ b/CleanSpec.mk @@ -73,6 +73,7 @@ $(call add-clean-step, rm -rf $(OUT_DIR)/target/common/obj/JAVA_LIBRARIES/androi $(call add-clean-step, rm -rf $(OUT_DIR)/target/common/obj/JAVA_LIBRARIES/framework_intermediates/src/core/java/com/trustedlogic) $(call add-clean-step, rm -rf $(OUT_DIR)/target/common/obj/JAVA_LIBRARIES/android_stubs_current_intermediates/src/com/trustedlogic) $(call add-clean-step, rm -rf $(OUT_DIR)/target/common/obj/JAVA_LIBRARIES/framework_intermediates/src/core/java/android/nfc/INdefTag.java) +$(call add-clean-step, rm -rf $(OUT_DIR)/target/common/obj/JAVA_LIBRARIES/framework_intermediates/src/core/java/android/nfc) # ************************************************ # NEWER CLEAN STEPS MUST BE AT THE END OF THE LIST diff --git a/core/java/android/nfc/INfcAdapter.aidl b/core/java/android/nfc/INfcAdapter.aidl index d439a48b8ce17..870127c72e143 100644 --- a/core/java/android/nfc/INfcAdapter.aidl +++ b/core/java/android/nfc/INfcAdapter.aidl @@ -28,7 +28,7 @@ import android.nfc.ILlcpConnectionlessSocket; import android.nfc.INfcTag; import android.nfc.IP2pTarget; import android.nfc.IP2pInitiator; -import android.nfc.INfcSecureElement; +import android.nfc.INfcAdapterExtras; /** * @hide @@ -41,13 +41,12 @@ interface INfcAdapter INfcTag getNfcTagInterface(); IP2pTarget getP2pTargetInterface(); IP2pInitiator getP2pInitiatorInterface(); - INfcSecureElement getNfcSecureElementInterface(); + INfcAdapterExtras getNfcAdapterExtrasInterface(); // NfcAdapter-class related methods boolean isEnabled(); NdefMessage localGet(); void localSet(in NdefMessage message); - void openTagConnection(in Tag tag); void enableForegroundDispatch(in ComponentName activity, in PendingIntent intent, in IntentFilter[] filters, in TechListParcel techLists); void disableForegroundDispatch(in ComponentName activity); @@ -59,12 +58,8 @@ interface INfcAdapter int createLlcpConnectionlessSocket(int sap); int createLlcpServiceSocket(int sap, String sn, int miu, int rw, int linearBufferLength); int createLlcpSocket(int sap, int miu, int rw, int linearBufferLength); - int deselectSecureElement(); boolean disable(); boolean enable(); String getProperties(String param); - int[] getSecureElementList(); - int getSelectedSecureElement(); - int selectSecureElement(int seId); int setProperties(String param, String value); -} \ No newline at end of file +} diff --git a/core/java/android/nfc/INfcSecureElement.aidl b/core/java/android/nfc/INfcAdapterExtras.aidl similarity index 63% rename from core/java/android/nfc/INfcSecureElement.aidl rename to core/java/android/nfc/INfcAdapterExtras.aidl index aa98dd26f8f68..ab5c1a656bba9 100755 --- a/core/java/android/nfc/INfcSecureElement.aidl +++ b/core/java/android/nfc/INfcAdapterExtras.aidl @@ -1,5 +1,5 @@ /* - * Copyright (C) 2010 The Android Open Source Project + * Copyright (C) 2011 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -16,13 +16,15 @@ package android.nfc; +import android.os.Bundle; + /** * {@hide} */ -interface INfcSecureElement { - int openSecureElementConnection(); - int closeSecureElementConnection(int nativeHandle); - byte[] exchangeAPDU(int nativeHandle, in byte[] data); - int[] getSecureElementTechList(int nativeHandle); - byte[] getSecureElementUid(int nativeHandle); -} \ No newline at end of file +interface INfcAdapterExtras { + Bundle open(IBinder b); + Bundle close(); + Bundle transceive(in byte[] data_in); + int getCardEmulationRoute(); + void setCardEmulationRoute(int route); +} diff --git a/core/java/android/nfc/NfcAdapter.java b/core/java/android/nfc/NfcAdapter.java index 8c56fda7a53a6..4689804fbfb49 100644 --- a/core/java/android/nfc/NfcAdapter.java +++ b/core/java/android/nfc/NfcAdapter.java @@ -156,31 +156,6 @@ public final class NfcAdapter { */ public static final String EXTRA_ID = "android.nfc.extra.ID"; - /** - * Broadcast Action: a transaction with a secure element has been detected. - *
- * Always contains the extra field - * {@link android.nfc.NfcAdapter#EXTRA_AID} - * @hide - */ - @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION) - public static final String ACTION_TRANSACTION_DETECTED = - "android.nfc.action.TRANSACTION_DETECTED"; - - /** - * Broadcast Action: an RF field ON has been detected. - * @hide - */ - public static final String ACTION_RF_FIELD_ON_DETECTED = - "android.nfc.action.RF_FIELD_ON_DETECTED"; - - /** - * Broadcast Action: an RF Field OFF has been detected. - * @hide - */ - public static final String ACTION_RF_FIELD_OFF_DETECTED = - "android.nfc.action.RF_FIELD_OFF_DETECTED"; - /** * Broadcast Action: an adapter's state changed between enabled and disabled. * @@ -200,15 +175,6 @@ public final class NfcAdapter { */ public static final String EXTRA_NEW_BOOLEAN_STATE = "android.nfc.isEnabled"; - /** - * Mandatory byte array extra field in - * {@link android.nfc.NfcAdapter#ACTION_TRANSACTION_DETECTED}. - *
- * Contains the AID of the applet involved in the transaction.
- * @hide
- */
- public static final String EXTRA_AID = "android.nfc.extra.AID";
-
/**
* LLCP link status: The LLCP link is activated.
* @hide
@@ -691,39 +657,14 @@ public final class NfcAdapter {
}
/**
- * Create an Nfc Secure Element Connection
* @hide
*/
- public NfcSecureElement createNfcSecureElementConnection() {
+ public INfcAdapterExtras getNfcAdapterExtrasInterface() {
try {
- return new NfcSecureElement(sService.getNfcSecureElementInterface());
+ return sService.getNfcAdapterExtrasInterface();
} catch (RemoteException e) {
- Log.e(TAG, "createNfcSecureElementConnection failed", e);
+ attemptDeadServiceRecovery(e);
return null;
}
}
-
- /**
- * To change the Secure Element Card Emulation state (ON/OFF)
- * @hide
- */
- public void changeNfcSecureElementCardEmulationState(boolean state)
- {
- int seId = 11259375;
- if(state){
- /* Enable card emulation */
- try {
- sService.selectSecureElement(seId);
- } catch (RemoteException e) {
- Log.e(TAG, "Enable card emulation failed", e);
- }
- }else{
- /* Disable card emulation */
- try {
- sService.deselectSecureElement();
- } catch (RemoteException e) {
- Log.e(TAG, " card emulation failed", e);
- }
- }
- }
}
diff --git a/core/java/android/nfc/NfcSecureElement.java b/core/java/android/nfc/NfcSecureElement.java
deleted file mode 100755
index 3b5f39eaac8a9..0000000000000
--- a/core/java/android/nfc/NfcSecureElement.java
+++ /dev/null
@@ -1,138 +0,0 @@
-/*
- * Copyright (C) 2010 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.nfc;
-
-import android.nfc.tech.TagTechnology;
-import android.os.RemoteException;
-import android.util.Log;
-
-import java.io.IOException;
-
-//import android.util.Log;
-
-/**
- * This class provides the primary API for managing all aspects Secure Element.
- * Get an instance of this class by calling
- * Context.getSystemService(Context.NFC_SERVICE).
- * @hide
- */
-public final class NfcSecureElement {
-
- private static final String TAG = "NfcSecureElement";
-
- private INfcSecureElement mService;
-
-
- /**
- * @hide
- */
- public NfcSecureElement(INfcSecureElement mSecureElementService) {
- mService = mSecureElementService;
- }
-
- public int openSecureElementConnection(String seType) throws IOException {
- if (seType.equals("SmartMX")) {
- try {
- int handle = mService.openSecureElementConnection();
- // Handle potential errors
- if (handle != 0) {
- return handle;
- } else {
- throw new IOException("SmartMX connection not allowed");
- }
- } catch (RemoteException e) {
- Log.e(TAG, "RemoteException in openSecureElementConnection(): ", e);
- return 0;
- }
-
- } else if (seType.equals("UICC")) {
- return 0;
- } else {
- throw new IOException("Wrong Secure Element type");
- }
- }
-
-
- public byte [] exchangeAPDU(int handle,byte [] data) throws IOException {
-
-
- // Perform exchange APDU
- try {
- byte[] response = mService.exchangeAPDU(handle, data);
- // Handle potential errors
- if (response == null) {
- throw new IOException("Exchange APDU failed");
- }
- return response;
- } catch (RemoteException e) {
- Log.e(TAG, "RemoteException in exchangeAPDU(): ", e);
- return null;
- }
- }
-
- public void closeSecureElementConnection(int handle) throws IOException {
-
- try {
- int status = mService.closeSecureElementConnection(handle);
- // Handle potential errors
- if (ErrorCodes.isError(status)) {
- throw new IOException("Error during the conection close");
- };
- } catch (RemoteException e) {
- Log.e(TAG, "RemoteException in closeSecureElement(): ", e);
- }
- }
-
-
- /**
- * Returns target type. constants.
- *
- * @return Secure Element technology type. The possible values are defined in
- * {@link TagTechnology}
- *
- */
- public int[] getSecureElementTechList(int handle) throws IOException {
- try {
- return mService.getSecureElementTechList(handle);
- } catch (RemoteException e) {
- Log.e(TAG, "RemoteException in getType(): ", e);
- return null;
- }
- }
-
- /**
- * Returns Secure Element UID.
- *
- * @return Secure Element UID.
- */
- public byte[] getSecureElementUid(int handle) throws IOException {
-
- byte[] uid = null;
- try {
- uid = mService.getSecureElementUid(handle);
- // Handle potential errors
- if (uid == null) {
- throw new IOException("Get Secure Element UID failed");
- }
- return uid;
- } catch (RemoteException e) {
- Log.e(TAG, "RemoteException in getType(): ", e);
- return null;
- }
- }
-
-}
diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml
index 56ca05765f388..c8295d7d7d8f4 100644
--- a/core/res/AndroidManifest.xml
+++ b/core/res/AndroidManifest.xml
@@ -87,7 +87,9 @@
This is an unreliable signal, and will be removed. + *
+ * Requires the {@link android.Manifest.permission#WRITE_SECURE_SETTINGS} permission + * to receive. + */ + public static final String ACTION_RF_FIELD_ON_DETECTED = + "com.android.nfc_extras.action.RF_FIELD_ON_DETECTED"; + + /** + * Broadcast Action: an RF field OFF has been detected. + * + *
This is an unreliable signal, and will be removed. + *
+ * Requires the {@link android.Manifest.permission#WRITE_SECURE_SETTINGS} permission + * to receive. + */ + public static final String ACTION_RF_FIELD_OFF_DETECTED = + "com.android.nfc_extras.action.RF_FIELD_OFF_DETECTED"; + + // protected by NfcAdapterExtras.class, and final after first construction + private static INfcAdapterExtras sService; + private static boolean sIsInitialized = false; + private static NfcAdapterExtras sSingleton; + private static NfcExecutionEnvironment sEmbeddedEe; + private static CardEmulationRoute sRouteOff; + private static CardEmulationRoute sRouteOnWhenScreenOn; + + /** + * Get the {@link NfcAdapterExtras} for the given {@link NfcAdapter}. + * + *
+ * Requires the {@link android.Manifest.permission#WRITE_SECURE_SETTINGS} permission. + * + * @param adapter a {@link NfcAdapter}, must not be null + * @return the {@link NfcAdapterExtras} object for the given {@link NfcAdapter} + */ + public static NfcAdapterExtras get(NfcAdapter adapter) { + synchronized(NfcAdapterExtras.class) { + if (!sIsInitialized) { + sIsInitialized = true; + sService = adapter.getNfcAdapterExtrasInterface(); + sEmbeddedEe = new NfcExecutionEnvironment(sService); + sRouteOff = new CardEmulationRoute(CardEmulationRoute.ROUTE_OFF, null); + sRouteOnWhenScreenOn = new CardEmulationRoute( + CardEmulationRoute.ROUTE_ON_WHEN_SCREEN_ON, sEmbeddedEe); + sSingleton = new NfcAdapterExtras(); + } + return sSingleton; + } + } + + private NfcAdapterExtras() {} + + /** + * Immutable data class that describes a card emulation route. + */ + public final static class CardEmulationRoute { + /** + * Card Emulation is turned off on this NfcAdapter. + *
This is the default routing state after boot. + */ + public static final int ROUTE_OFF = 1; + + /** + * Card Emulation is routed to {@link #nfcEe} only when the screen is on, + * otherwise it is turned off. + */ + public static final int ROUTE_ON_WHEN_SCREEN_ON = 2; + + /** + * A route such as {@link #ROUTE_OFF} or {@link #ROUTE_ON_WHEN_SCREEN_ON}. + */ + public final int route; + + /** + * The {@link NFcExecutionEnvironment} that is Card Emulation is routed to. + *
null if {@link #route} is {@link #ROUTE_OFF}, otherwise not null. + */ + public final NfcExecutionEnvironment nfcEe; + + public CardEmulationRoute(int route, NfcExecutionEnvironment nfcEe) { + if (route == ROUTE_OFF && nfcEe != null) { + throw new IllegalArgumentException("must not specifiy a NFC-EE with ROUTE_OFF"); + } else if (route != ROUTE_OFF && nfcEe == null) { + throw new IllegalArgumentException("must specifiy a NFC-EE for this route"); + } + this.route = route; + this.nfcEe = nfcEe; + } + } + + /** + * Get the routing state of this NFC EE. + * + *
+ * Requires the {@link android.Manifest.permission#WRITE_SECURE_SETTINGS} permission. + * + * @return + */ + public CardEmulationRoute getCardEmulationRoute() { + try { + int route = sService.getCardEmulationRoute(); + return route == CardEmulationRoute.ROUTE_OFF ? + sRouteOff : + sRouteOnWhenScreenOn; + } catch (RemoteException e) { + Log.e(TAG, "", e); + return sRouteOff; + } + } + + /** + * Set the routing state of this NFC EE. + * + *
This routing state is not persisted across reboot. + * + *
+ * Requires the {@link android.Manifest.permission#WRITE_SECURE_SETTINGS} permission. + * + * @param route a {@link #CardEmulationRoute} + */ + public void setCardEmulationRoute(CardEmulationRoute route) { + try { + sService.setCardEmulationRoute(route.route); + } catch (RemoteException e) { + Log.e(TAG, "", e); + } + } + + /** + * Get the {@link NfcExecutionEnvironment} that is embedded with the + * {@link NFcAdapter}. + * + *
+ * Requires the {@link android.Manifest.permission#WRITE_SECURE_SETTINGS} permission. + * + * @return a {@link NfcExecutionEnvironment}, or null if there is no embedded NFC-EE + */ + public NfcExecutionEnvironment getEmbeddedExecutionEnvironment() { + return sEmbeddedEe; + } +} diff --git a/nfc-extras/java/com/android/nfc_extras/NfcExecutionEnvironment.java b/nfc-extras/java/com/android/nfc_extras/NfcExecutionEnvironment.java new file mode 100644 index 0000000000000..3efe49236de91 --- /dev/null +++ b/nfc-extras/java/com/android/nfc_extras/NfcExecutionEnvironment.java @@ -0,0 +1,125 @@ +/* + * Copyright (C) 2011 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.nfc_extras; + +import java.io.IOException; + +import android.annotation.SdkConstant; +import android.annotation.SdkConstant.SdkConstantType; +import android.content.Context; +import android.nfc.INfcAdapterExtras; +import android.nfc.NfcAdapter; +import android.os.Binder; +import android.os.Bundle; +import android.os.IBinder; +import android.os.RemoteException; + +public class NfcExecutionEnvironment { + private final INfcAdapterExtras mService; + + /** + * Broadcast Action: An ISO-DEP AID was selected. + * + *
This happens as the result of a 'SELECT AID' command from an + * external NFC reader/writer. + * + *
Always contains the extra field {@link #EXTRA_AID} + * + *
+ * Requires the {@link android.Manifest.permission#WRITE_SECURE_SETTINGS} permission + * to receive. + */ + @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION) + public static final String ACTION_AID_SELECTED = + "com.android.nfc_extras.action.AID_SELECTED"; + + /** + * Mandatory byte array extra field in {@link #ACTION_AID_SELECTED}. + * + *
Contains the AID selected. + * @hide + */ + public static final String EXTRA_AID = "com.android.nfc_extras.extra.AID"; + + NfcExecutionEnvironment(INfcAdapterExtras service) { + mService = service; + } + + /** + * Open the NFC Execution Environment on its contact interface. + * + *
Only one process may open the secure element at a time. If it is + * already open, an {@link IOException} is thrown. + * + *
All other NFC functionality is disabled while the NFC-EE is open + * on its contact interface, so make sure to call {@link #close} once complete. + * + *
+ * Requires the {@link android.Manifest.permission#WRITE_SECURE_SETTINGS} permission. + * + * @throws IOException if the NFC-EE is already open, or some other error occurs + */ + public void open() throws IOException { + try { + Bundle b = mService.open(new Binder()); + throwBundle(b); + } catch (RemoteException e) { + return; + } + } + + /** + * Close the NFC Execution Environment on its contact interface. + * + *
+ * Requires the {@link android.Manifest.permission#WRITE_SECURE_SETTINGS} permission. + * + * @throws IOException if the NFC-EE is already open, or some other error occurs + */ + public void close() throws IOException { + try { + throwBundle(mService.close()); + } catch (RemoteException e) { + return; + } + } + + /** + * Send raw commands to the NFC-EE and receive the response. + * + *
+ * Requires the {@link android.Manifest.permission#WRITE_SECURE_SETTINGS} permission. + * + * @throws IOException if the NFC-EE is not open, or some other error occurs + */ + public byte[] transceive(byte[] in) throws IOException { + Bundle b; + try { + b = mService.transceive(in); + } catch (RemoteException e) { + throw new IOException(e.getMessage()); + } + throwBundle(b); + return b.getByteArray("out"); + } + + private static void throwBundle(Bundle b) throws IOException { + if (b.getInt("e") == -1) { + throw new IOException(b.getString("m")); + } + } +}