diff options
author | Jeff Hamilton <jham@android.com> | 2011-11-08 16:55:13 -0600 |
---|---|---|
committer | Nick Pelly <npelly@google.com> | 2011-11-11 08:55:26 -0800 |
commit | bb951c893973691554f49d2e725985125f866b27 (patch) | |
tree | 355d7da2f890359a8b15f07261b2f8415238041d | |
parent | de62d9cbe00d0fcac24af9a3d89ba7a125e56eaa (diff) | |
download | frameworks_base-bb951c893973691554f49d2e725985125f866b27.zip frameworks_base-bb951c893973691554f49d2e725985125f866b27.tar.gz frameworks_base-bb951c893973691554f49d2e725985125f866b27.tar.bz2 |
Changes for access control.
The package name is now required when using the
NFC extras APIs so the context is stored away
and used to derive the package name to be sent
to the NfcService.
Bug: 4515759
Change-Id: I1a3aba3fc026e0090a914b0686fc4b8dec25b927
-rw-r--r-- | core/java/android/nfc/INfcAdapter.aidl | 2 | ||||
-rw-r--r-- | core/java/android/nfc/INfcAdapterExtras.aidl | 12 | ||||
-rw-r--r-- | core/java/android/nfc/NfcAdapter.java | 78 | ||||
-rw-r--r-- | core/java/android/nfc/NfcManager.java | 3 | ||||
-rw-r--r-- | nfc-extras/java/com/android/nfc_extras/NfcAdapterExtras.java | 69 | ||||
-rw-r--r-- | nfc-extras/java/com/android/nfc_extras/NfcExecutionEnvironment.java | 16 |
6 files changed, 107 insertions, 73 deletions
diff --git a/core/java/android/nfc/INfcAdapter.aidl b/core/java/android/nfc/INfcAdapter.aidl index 016af58..0b93ad0 100644 --- a/core/java/android/nfc/INfcAdapter.aidl +++ b/core/java/android/nfc/INfcAdapter.aidl @@ -32,7 +32,7 @@ import android.nfc.INfcTag; interface INfcAdapter { INfcTag getNfcTagInterface(); - INfcAdapterExtras getNfcAdapterExtrasInterface(); + INfcAdapterExtras getNfcAdapterExtrasInterface(in String pkg); int getState(); boolean disable(); diff --git a/core/java/android/nfc/INfcAdapterExtras.aidl b/core/java/android/nfc/INfcAdapterExtras.aidl index 0c2a2fd..2b9d4f0 100644 --- a/core/java/android/nfc/INfcAdapterExtras.aidl +++ b/core/java/android/nfc/INfcAdapterExtras.aidl @@ -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); } diff --git a/core/java/android/nfc/NfcAdapter.java b/core/java/android/nfc/NfcAdapter.java index fe0106d..a9f1685 100644 --- a/core/java/android/nfc/NfcAdapter.java +++ b/core/java/android/nfc/NfcAdapter.java @@ -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 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 sSingleton; // protected by NfcAdapter.class + 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 (context == null) { + if (sNullContextNfcAdapter == null) { + sNullContextNfcAdapter = new NfcAdapter(null); + } + return sNullContextNfcAdapter; } - if (sSingleton == null) { - throw new UnsupportedOperationException(); + NfcAdapter adapter = sNfcAdapters.get(context); + if (adapter == null) { + adapter = new NfcAdapter(context); + sNfcAdapters.put(context, adapter); } - return sSingleton; + 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; diff --git a/core/java/android/nfc/NfcManager.java b/core/java/android/nfc/NfcManager.java index 300ab45..6ec2e21 100644 --- a/core/java/android/nfc/NfcManager.java +++ b/core/java/android/nfc/NfcManager.java @@ -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; } diff --git a/nfc-extras/java/com/android/nfc_extras/NfcAdapterExtras.java b/nfc-extras/java/com/android/nfc_extras/NfcAdapterExtras.java index 99cbb86..62213de 100644 --- a/nfc-extras/java/com/android/nfc_extras/NfcAdapterExtras.java +++ b/nfc-extras/java/com/android/nfc_extras/NfcAdapterExtras.java @@ -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); } diff --git a/nfc-extras/java/com/android/nfc_extras/NfcExecutionEnvironment.java b/nfc-extras/java/com/android/nfc_extras/NfcExecutionEnvironment.java index 63c2de2..f47327a 100644 --- a/nfc-extras/java/com/android/nfc_extras/NfcExecutionEnvironment.java +++ b/nfc-extras/java/com/android/nfc_extras/NfcExecutionEnvironment.java @@ -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"); |