Merge "Changes for access control." into ics-mr1

This commit is contained in:
Nick Pelly
2011-11-11 13:06:44 -08:00
committed by Android (Google) Code Review
6 changed files with 107 additions and 73 deletions

View File

@@ -32,7 +32,7 @@ import android.nfc.INfcTag;
interface INfcAdapter
{
INfcTag getNfcTagInterface();
INfcAdapterExtras getNfcAdapterExtrasInterface();
INfcAdapterExtras getNfcAdapterExtrasInterface(in String pkg);
int getState();
boolean disable();

View File

@@ -23,10 +23,10 @@ import android.os.Bundle;
* {@hide}
*/
interface INfcAdapterExtras {
Bundle open(IBinder b);
Bundle close();
Bundle transceive(in byte[] data_in);
int getCardEmulationRoute();
void setCardEmulationRoute(int route);
void authenticate(in byte[] token);
Bundle open(in String pkg, IBinder b);
Bundle close(in String pkg, IBinder b);
Bundle transceive(in String pkg, in byte[] data_in);
int getCardEmulationRoute(in String pkg);
void setCardEmulationRoute(in String pkg, int route);
void authenticate(in String pkg, in byte[] token);
}

View File

@@ -16,6 +16,8 @@
package android.nfc;
import java.util.HashMap;
import android.annotation.SdkConstant;
import android.annotation.SdkConstant.SdkConstantType;
import android.app.Activity;
@@ -197,15 +199,21 @@ public final class NfcAdapter {
static INfcTag sTagService;
/**
* NfcAdapter is currently a singleton, and does not require a context.
* However all the public API's are future-proofed to require a context.
* If we start using that then we'll need to keep a HashMap of
* Context.getApplicationContext() -> NfcAdapter, such that NfcAdapter
* is a singleton within each application context.
* The NfcAdapter object for each application context.
* There is a 1-1 relationship between application context and
* NfcAdapter object.
*/
static NfcAdapter sSingleton; // protected by NfcAdapter.class
static HashMap<Context, NfcAdapter> sNfcAdapters = new HashMap(); //guard by NfcAdapter.class
/**
* NfcAdapter used with a null context. This ctor was deprecated but we have
* to support it for backwards compatibility. New methods that require context
* might throw when called on the null-context NfcAdapter.
*/
static NfcAdapter sNullContextNfcAdapter; // protected by NfcAdapter.class
final NfcActivityManager mNfcActivityManager;
final Context mContext;
/**
* A callback to be invoked when the system successfully delivers your {@link NdefMessage}
@@ -280,12 +288,12 @@ public final class NfcAdapter {
}
/**
* Returns the singleton, or throws if NFC is not available.
* Returns the NfcAdapter for application context,
* or throws if NFC is not available.
* @hide
*/
static synchronized NfcAdapter getSingleton() {
public static synchronized NfcAdapter getNfcAdapter(Context context) {
if (!sIsInitialized) {
sIsInitialized = true;
/* is this device meant to have NFC */
if (!hasNfcFeature()) {
Log.v(TAG, "this device does not have NFC support");
@@ -303,12 +311,21 @@ public final class NfcAdapter {
Log.e(TAG, "could not retrieve NFC Tag service");
throw new UnsupportedOperationException();
}
sSingleton = new NfcAdapter();
sIsInitialized = true;
}
if (sSingleton == null) {
throw new UnsupportedOperationException();
if (context == null) {
if (sNullContextNfcAdapter == null) {
sNullContextNfcAdapter = new NfcAdapter(null);
}
return sNullContextNfcAdapter;
}
return sSingleton;
NfcAdapter adapter = sNfcAdapters.get(context);
if (adapter == null) {
adapter = new NfcAdapter(context);
sNfcAdapters.put(context, adapter);
}
return adapter;
}
/** get handle to NFC service interface */
@@ -336,6 +353,10 @@ public final class NfcAdapter {
* @return the default NFC adapter, or null if no NFC adapter exists
*/
public static NfcAdapter getDefaultAdapter(Context context) {
if (context == null) {
throw new IllegalArgumentException("context cannot be null");
}
context = context.getApplicationContext();
/* use getSystemService() instead of just instantiating to take
* advantage of the context's cached NfcManager & NfcAdapter */
NfcManager manager = (NfcManager) context.getSystemService(Context.NFC_SERVICE);
@@ -343,25 +364,30 @@ public final class NfcAdapter {
}
/**
* Get a handle to the default NFC Adapter on this Android device.
* <p>
* Most Android devices will only have one NFC Adapter (NFC Controller).
*
* @return the default NFC adapter, or null if no NFC adapter exists
* Legacy NfcAdapter getter, always use {@link #getDefaultAdapter(Context)} instead.<p>
* This method was deprecated at API level 10 (Gingerbread MR1) because a context is required
* for many NFC API methods. Those methods will fail when called on an NfcAdapter
* object created from this method.<p>
* @deprecated use {@link #getDefaultAdapter(Context)}
*/
@Deprecated
public static NfcAdapter getDefaultAdapter() {
Log.w(TAG, "WARNING: NfcAdapter.getDefaultAdapter() is deprecated, use " +
"NfcAdapter.getDefaultAdapter(Context) instead", new Exception());
return getSingleton();
return NfcAdapter.getNfcAdapter(null);
}
NfcAdapter(Context context) {
mContext = context;
mNfcActivityManager = new NfcActivityManager(this);
}
/**
* Does not currently need a context.
* @hide
*/
NfcAdapter() {
mNfcActivityManager = new NfcActivityManager(this);
public Context getContext() {
return mContext;
}
/**
@@ -875,8 +901,12 @@ public final class NfcAdapter {
* @hide
*/
public INfcAdapterExtras getNfcAdapterExtrasInterface() {
if (mContext == null) {
throw new UnsupportedOperationException("You need a context on NfcAdapter to use the "
+ " NFC extras APIs");
}
try {
return sService.getNfcAdapterExtrasInterface();
return sService.getNfcAdapterExtrasInterface(mContext.getPackageName());
} catch (RemoteException e) {
attemptDeadServiceRecovery(e);
return null;

View File

@@ -39,8 +39,9 @@ public final class NfcManager {
*/
public NfcManager(Context context) {
NfcAdapter adapter;
context = context.getApplicationContext();
try {
adapter = NfcAdapter.getSingleton();
adapter = NfcAdapter.getNfcAdapter(context);
} catch (UnsupportedOperationException e) {
adapter = null;
}

View File

@@ -16,8 +16,7 @@
package com.android.nfc_extras;
import android.annotation.SdkConstant;
import android.annotation.SdkConstant.SdkConstantType;
import android.content.Context;
import android.nfc.INfcAdapterExtras;
import android.nfc.NfcAdapter;
import android.os.RemoteException;
@@ -60,10 +59,14 @@ public final class NfcAdapterExtras {
// best effort recovery
private static NfcAdapter sAdapter;
private static INfcAdapterExtras sService;
private static NfcAdapterExtras sSingleton;
private static NfcExecutionEnvironment sEmbeddedEe;
private static CardEmulationRoute sRouteOff;
private static CardEmulationRoute sRouteOnWhenScreenOn;
private static final CardEmulationRoute ROUTE_OFF =
new CardEmulationRoute(CardEmulationRoute.ROUTE_OFF, null);
private final NfcExecutionEnvironment mEmbeddedEe;
private final CardEmulationRoute mRouteOnWhenScreenOn;
final Context mContext;
final String mPackageName;
/** get service handles */
private static void initService() {
@@ -84,31 +87,35 @@ public final class NfcAdapterExtras {
* @return the {@link NfcAdapterExtras} object for the given {@link NfcAdapter}
*/
public static NfcAdapterExtras get(NfcAdapter adapter) {
synchronized(NfcAdapterExtras.class) {
if (sSingleton == null) {
Context context = adapter.getContext();
if (context == null) {
throw new UnsupportedOperationException(
"You must pass a context to your NfcAdapter to use the NFC extras APIs");
}
synchronized (NfcAdapterExtras.class) {
if (sService == null) {
try {
sAdapter = adapter;
sSingleton = new NfcAdapterExtras();
sEmbeddedEe = new NfcExecutionEnvironment(sSingleton);
sRouteOff = new CardEmulationRoute(CardEmulationRoute.ROUTE_OFF, null);
sRouteOnWhenScreenOn = new CardEmulationRoute(
CardEmulationRoute.ROUTE_ON_WHEN_SCREEN_ON, sEmbeddedEe);
initService();
} finally {
if (sService == null) {
sRouteOnWhenScreenOn = null;
sRouteOff = null;
sEmbeddedEe = null;
sSingleton = null;
sAdapter = null;
}
}
}
return sSingleton;
}
return new NfcAdapterExtras(context);
}
private NfcAdapterExtras() {}
private NfcAdapterExtras(Context context) {
mContext = context.getApplicationContext();
mPackageName = context.getPackageName();
mEmbeddedEe = new NfcExecutionEnvironment(this);
mRouteOnWhenScreenOn = new CardEmulationRoute(CardEmulationRoute.ROUTE_ON_WHEN_SCREEN_ON,
mEmbeddedEe);
}
/**
* Immutable data class that describes a card emulation route.
@@ -166,18 +173,16 @@ public final class NfcAdapterExtras {
*
* <p class="note">
* Requires the {@link android.Manifest.permission#WRITE_SECURE_SETTINGS} permission.
*
* @return
*/
public CardEmulationRoute getCardEmulationRoute() {
try {
int route = sService.getCardEmulationRoute();
int route = sService.getCardEmulationRoute(mPackageName);
return route == CardEmulationRoute.ROUTE_OFF ?
sRouteOff :
sRouteOnWhenScreenOn;
ROUTE_OFF :
mRouteOnWhenScreenOn;
} catch (RemoteException e) {
attemptDeadServiceRecovery(e);
return sRouteOff;
return ROUTE_OFF;
}
}
@@ -189,11 +194,11 @@ public final class NfcAdapterExtras {
* <p class="note">
* Requires the {@link android.Manifest.permission#WRITE_SECURE_SETTINGS} permission.
*
* @param route a {@link #CardEmulationRoute}
* @param route a {@link CardEmulationRoute}
*/
public void setCardEmulationRoute(CardEmulationRoute route) {
try {
sService.setCardEmulationRoute(route.route);
sService.setCardEmulationRoute(mPackageName, route.route);
} catch (RemoteException e) {
attemptDeadServiceRecovery(e);
}
@@ -201,7 +206,7 @@ public final class NfcAdapterExtras {
/**
* Get the {@link NfcExecutionEnvironment} that is embedded with the
* {@link NFcAdapter}.
* {@link NfcAdapter}.
*
* <p class="note">
* Requires the {@link android.Manifest.permission#WRITE_SECURE_SETTINGS} permission.
@@ -209,7 +214,7 @@ public final class NfcAdapterExtras {
* @return a {@link NfcExecutionEnvironment}, or null if there is no embedded NFC-EE
*/
public NfcExecutionEnvironment getEmbeddedExecutionEnvironment() {
return sEmbeddedEe;
return mEmbeddedEe;
}
/**
@@ -218,12 +223,12 @@ public final class NfcAdapterExtras {
* Some implementations of NFC Adapter Extras may require applications
* to authenticate with a token, before using other methods.
*
* @param a implementation specific token
* @throws a {@link java.lang.SecurityException} if authentication failed
* @param token a implementation specific token
* @throws java.lang.SecurityException if authentication failed
*/
public void authenticate(byte[] token) {
try {
sService.authenticate(token);
sService.authenticate(mPackageName, token);
} catch (RemoteException e) {
attemptDeadServiceRecovery(e);
}

View File

@@ -16,20 +16,17 @@
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;
import java.io.IOException;
public class NfcExecutionEnvironment {
private final NfcAdapterExtras mExtras;
private final Binder mToken;
/**
* Broadcast Action: An ISO-DEP AID was selected.
@@ -115,6 +112,7 @@ public class NfcExecutionEnvironment {
NfcExecutionEnvironment(NfcAdapterExtras extras) {
mExtras = extras;
mToken = new Binder();
}
/**
@@ -133,7 +131,7 @@ public class NfcExecutionEnvironment {
*/
public void open() throws IOException {
try {
Bundle b = mExtras.getService().open(new Binder());
Bundle b = mExtras.getService().open(mExtras.mPackageName, mToken);
throwBundle(b);
} catch (RemoteException e) {
mExtras.attemptDeadServiceRecovery(e);
@@ -151,7 +149,7 @@ public class NfcExecutionEnvironment {
*/
public void close() throws IOException {
try {
throwBundle(mExtras.getService().close());
throwBundle(mExtras.getService().close(mExtras.mPackageName, mToken));
} catch (RemoteException e) {
mExtras.attemptDeadServiceRecovery(e);
throw new IOException("NFC Service was dead");
@@ -169,7 +167,7 @@ public class NfcExecutionEnvironment {
public byte[] transceive(byte[] in) throws IOException {
Bundle b;
try {
b = mExtras.getService().transceive(in);
b = mExtras.getService().transceive(mExtras.mPackageName, in);
} catch (RemoteException e) {
mExtras.attemptDeadServiceRecovery(e);
throw new IOException("NFC Service was dead, need to re-open");