Implement new NFC-EE API's as shared library (frameworks/base).

Change-Id: I45c4eaf59ec78167fc236fdd59676465a5e1bcb7
This commit is contained in:
Nick Pelly
2011-03-08 11:43:30 -08:00
parent dfcb8c5116
commit 367f41f8f6
11 changed files with 357 additions and 218 deletions

View File

@@ -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 \

View File

@@ -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

View File

@@ -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);
}
}

View File

@@ -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);
}
interface INfcAdapterExtras {
Bundle open(IBinder b);
Bundle close();
Bundle transceive(in byte[] data_in);
int getCardEmulationRoute();
void setCardEmulationRoute(int route);
}

View File

@@ -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.
* <p>
* 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}.
* <p>
* 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);
}
}
}
}

View File

@@ -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;
}
}
}

View File

@@ -87,7 +87,9 @@
<protected-broadcast android:name="android.hardware.usb.action.USB_ACCESSORY_ATTACHED" />
<protected-broadcast android:name="android.nfc.action.LLCP_LINK_STATE_CHANGED" />
<protected-broadcast android:name="android.nfc.action.TRANSACTION_DETECTED" />
<protected-broadcast android:name="com.android.nfc_extras.action.RF_FIELD_ON_DETECTED" />
<protected-broadcast android:name="com.android.nfc_extras.action.RF_FIELD_OFF_DETECTED" />
<protected-broadcast android:name="com.android.nfc_extras.action.AID_SELECTED" />
<!-- ====================================== -->
<!-- Permissions for things that cost money -->

11
nfc-extras/Android.mk Normal file
View File

@@ -0,0 +1,11 @@
LOCAL_PATH:= $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE_TAGS := optional
LOCAL_SRC_FILES := $(call all-subdir-java-files)
LOCAL_MODULE:= com.android.nfc_extras
include $(BUILD_JAVA_LIBRARY)

View File

@@ -0,0 +1,20 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- 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.
-->
<permissions>
<library name="com.android.nfc_extras"
file="/system/framework/com.android.nfc_extras.jar" />
</permissions>

View File

@@ -0,0 +1,180 @@
/*
* 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 android.annotation.SdkConstant;
import android.annotation.SdkConstant.SdkConstantType;
import android.nfc.INfcAdapterExtras;
import android.nfc.NfcAdapter;
import android.os.RemoteException;
import android.util.Log;
/**
* Provides additional methods on an {@link NfcAdapter} for Card Emulation
* and management of {@link NfcExecutionEnvironment}'s.
*
* There is a 1-1 relationship between an {@link NfcAdapterExtras} object and
* a {@link NfcAdapter} object.
*/
public final class NfcAdapterExtras {
private static final String TAG = "NfcAdapterExtras";
/**
* Broadcast Action: an RF field ON has been detected.
*
* <p class="note">This is an unreliable signal, and will be removed.
* <p class="note">
* 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.
*
* <p class="note">This is an unreliable signal, and will be removed.
* <p class="note">
* 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}.
*
* <p class="note">
* 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.
* <p>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.
* <p>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.
*
* <p class="note">
* 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.
*
* <p>This routing state is not persisted across reboot.
*
* <p class="note">
* 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}.
*
* <p class="note">
* 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;
}
}

View File

@@ -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.
*
* <p>This happens as the result of a 'SELECT AID' command from an
* external NFC reader/writer.
*
* <p>Always contains the extra field {@link #EXTRA_AID}
*
* <p class="note">
* 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}.
*
* <p>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.
*
* <p>Only one process may open the secure element at a time. If it is
* already open, an {@link IOException} is thrown.
*
* <p>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.
*
* <p class="note">
* 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.
*
* <p class="note">
* 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.
*
* <p class="note">
* 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"));
}
}
}