am 48b651cb: Merge "Changes for access control." into ics-mr1

* commit '48b651cb2a3afab979c2a46185fd7edfa5424387':
  Changes for access control.
This commit is contained in:
Nick Pelly
2011-11-11 13:08:37 -08:00
committed by Android Git Automerger
6 changed files with 107 additions and 73 deletions

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -16,20 +16,17 @@
package com.android.nfc_extras; package com.android.nfc_extras;
import java.io.IOException;
import android.annotation.SdkConstant; import android.annotation.SdkConstant;
import android.annotation.SdkConstant.SdkConstantType; import android.annotation.SdkConstant.SdkConstantType;
import android.content.Context;
import android.nfc.INfcAdapterExtras;
import android.nfc.NfcAdapter;
import android.os.Binder; import android.os.Binder;
import android.os.Bundle; import android.os.Bundle;
import android.os.IBinder;
import android.os.RemoteException; import android.os.RemoteException;
import java.io.IOException;
public class NfcExecutionEnvironment { public class NfcExecutionEnvironment {
private final NfcAdapterExtras mExtras; private final NfcAdapterExtras mExtras;
private final Binder mToken;
/** /**
* Broadcast Action: An ISO-DEP AID was selected. * Broadcast Action: An ISO-DEP AID was selected.
@@ -115,6 +112,7 @@ public class NfcExecutionEnvironment {
NfcExecutionEnvironment(NfcAdapterExtras extras) { NfcExecutionEnvironment(NfcAdapterExtras extras) {
mExtras = extras; mExtras = extras;
mToken = new Binder();
} }
/** /**
@@ -133,7 +131,7 @@ public class NfcExecutionEnvironment {
*/ */
public void open() throws IOException { public void open() throws IOException {
try { try {
Bundle b = mExtras.getService().open(new Binder()); Bundle b = mExtras.getService().open(mExtras.mPackageName, mToken);
throwBundle(b); throwBundle(b);
} catch (RemoteException e) { } catch (RemoteException e) {
mExtras.attemptDeadServiceRecovery(e); mExtras.attemptDeadServiceRecovery(e);
@@ -151,7 +149,7 @@ public class NfcExecutionEnvironment {
*/ */
public void close() throws IOException { public void close() throws IOException {
try { try {
throwBundle(mExtras.getService().close()); throwBundle(mExtras.getService().close(mExtras.mPackageName, mToken));
} catch (RemoteException e) { } catch (RemoteException e) {
mExtras.attemptDeadServiceRecovery(e); mExtras.attemptDeadServiceRecovery(e);
throw new IOException("NFC Service was dead"); throw new IOException("NFC Service was dead");
@@ -169,7 +167,7 @@ public class NfcExecutionEnvironment {
public byte[] transceive(byte[] in) throws IOException { public byte[] transceive(byte[] in) throws IOException {
Bundle b; Bundle b;
try { try {
b = mExtras.getService().transceive(in); b = mExtras.getService().transceive(mExtras.mPackageName, in);
} catch (RemoteException e) { } catch (RemoteException e) {
mExtras.attemptDeadServiceRecovery(e); mExtras.attemptDeadServiceRecovery(e);
throw new IOException("NFC Service was dead, need to re-open"); throw new IOException("NFC Service was dead, need to re-open");