Skip to content

Commit 48b651c

Browse files
Nick PellyAndroid (Google) Code Review
authored andcommitted
Merge "Changes for access control." into ics-mr1
2 parents a303f0e + bb951c8 commit 48b651c

File tree

6 files changed

+107
-73
lines changed

6 files changed

+107
-73
lines changed

core/java/android/nfc/INfcAdapter.aidl

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ import android.nfc.INfcTag;
3232
interface INfcAdapter
3333
{
3434
INfcTag getNfcTagInterface();
35-
INfcAdapterExtras getNfcAdapterExtrasInterface();
35+
INfcAdapterExtras getNfcAdapterExtrasInterface(in String pkg);
3636

3737
int getState();
3838
boolean disable();

core/java/android/nfc/INfcAdapterExtras.aidl

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -23,10 +23,10 @@ import android.os.Bundle;
2323
* {@hide}
2424
*/
2525
interface INfcAdapterExtras {
26-
Bundle open(IBinder b);
27-
Bundle close();
28-
Bundle transceive(in byte[] data_in);
29-
int getCardEmulationRoute();
30-
void setCardEmulationRoute(int route);
31-
void authenticate(in byte[] token);
26+
Bundle open(in String pkg, IBinder b);
27+
Bundle close(in String pkg, IBinder b);
28+
Bundle transceive(in String pkg, in byte[] data_in);
29+
int getCardEmulationRoute(in String pkg);
30+
void setCardEmulationRoute(in String pkg, int route);
31+
void authenticate(in String pkg, in byte[] token);
3232
}

core/java/android/nfc/NfcAdapter.java

Lines changed: 54 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,8 @@
1616

1717
package android.nfc;
1818

19+
import java.util.HashMap;
20+
1921
import android.annotation.SdkConstant;
2022
import android.annotation.SdkConstant.SdkConstantType;
2123
import android.app.Activity;
@@ -197,15 +199,21 @@ public final class NfcAdapter {
197199
static INfcTag sTagService;
198200

199201
/**
200-
* NfcAdapter is currently a singleton, and does not require a context.
201-
* However all the public API's are future-proofed to require a context.
202-
* If we start using that then we'll need to keep a HashMap of
203-
* Context.getApplicationContext() -> NfcAdapter, such that NfcAdapter
204-
* is a singleton within each application context.
202+
* The NfcAdapter object for each application context.
203+
* There is a 1-1 relationship between application context and
204+
* NfcAdapter object.
205+
*/
206+
static HashMap<Context, NfcAdapter> sNfcAdapters = new HashMap(); //guard by NfcAdapter.class
207+
208+
/**
209+
* NfcAdapter used with a null context. This ctor was deprecated but we have
210+
* to support it for backwards compatibility. New methods that require context
211+
* might throw when called on the null-context NfcAdapter.
205212
*/
206-
static NfcAdapter sSingleton; // protected by NfcAdapter.class
213+
static NfcAdapter sNullContextNfcAdapter; // protected by NfcAdapter.class
207214

208215
final NfcActivityManager mNfcActivityManager;
216+
final Context mContext;
209217

210218
/**
211219
* A callback to be invoked when the system successfully delivers your {@link NdefMessage}
@@ -280,12 +288,12 @@ private static boolean hasNfcFeature() {
280288
}
281289

282290
/**
283-
* Returns the singleton, or throws if NFC is not available.
291+
* Returns the NfcAdapter for application context,
292+
* or throws if NFC is not available.
293+
* @hide
284294
*/
285-
static synchronized NfcAdapter getSingleton() {
295+
public static synchronized NfcAdapter getNfcAdapter(Context context) {
286296
if (!sIsInitialized) {
287-
sIsInitialized = true;
288-
289297
/* is this device meant to have NFC */
290298
if (!hasNfcFeature()) {
291299
Log.v(TAG, "this device does not have NFC support");
@@ -303,12 +311,21 @@ static synchronized NfcAdapter getSingleton() {
303311
Log.e(TAG, "could not retrieve NFC Tag service");
304312
throw new UnsupportedOperationException();
305313
}
306-
sSingleton = new NfcAdapter();
314+
315+
sIsInitialized = true;
316+
}
317+
if (context == null) {
318+
if (sNullContextNfcAdapter == null) {
319+
sNullContextNfcAdapter = new NfcAdapter(null);
320+
}
321+
return sNullContextNfcAdapter;
307322
}
308-
if (sSingleton == null) {
309-
throw new UnsupportedOperationException();
323+
NfcAdapter adapter = sNfcAdapters.get(context);
324+
if (adapter == null) {
325+
adapter = new NfcAdapter(context);
326+
sNfcAdapters.put(context, adapter);
310327
}
311-
return sSingleton;
328+
return adapter;
312329
}
313330

314331
/** get handle to NFC service interface */
@@ -336,32 +353,41 @@ private static INfcAdapter getServiceInterface() {
336353
* @return the default NFC adapter, or null if no NFC adapter exists
337354
*/
338355
public static NfcAdapter getDefaultAdapter(Context context) {
356+
if (context == null) {
357+
throw new IllegalArgumentException("context cannot be null");
358+
}
359+
context = context.getApplicationContext();
339360
/* use getSystemService() instead of just instantiating to take
340361
* advantage of the context's cached NfcManager & NfcAdapter */
341362
NfcManager manager = (NfcManager) context.getSystemService(Context.NFC_SERVICE);
342363
return manager.getDefaultAdapter();
343364
}
344365

345366
/**
346-
* Get a handle to the default NFC Adapter on this Android device.
347-
* <p>
348-
* Most Android devices will only have one NFC Adapter (NFC Controller).
349-
*
350-
* @return the default NFC adapter, or null if no NFC adapter exists
367+
* Legacy NfcAdapter getter, always use {@link #getDefaultAdapter(Context)} instead.<p>
368+
* This method was deprecated at API level 10 (Gingerbread MR1) because a context is required
369+
* for many NFC API methods. Those methods will fail when called on an NfcAdapter
370+
* object created from this method.<p>
351371
* @deprecated use {@link #getDefaultAdapter(Context)}
352372
*/
353373
@Deprecated
354374
public static NfcAdapter getDefaultAdapter() {
355375
Log.w(TAG, "WARNING: NfcAdapter.getDefaultAdapter() is deprecated, use " +
356376
"NfcAdapter.getDefaultAdapter(Context) instead", new Exception());
357-
return getSingleton();
377+
378+
return NfcAdapter.getNfcAdapter(null);
379+
}
380+
381+
NfcAdapter(Context context) {
382+
mContext = context;
383+
mNfcActivityManager = new NfcActivityManager(this);
358384
}
359385

360386
/**
361-
* Does not currently need a context.
387+
* @hide
362388
*/
363-
NfcAdapter() {
364-
mNfcActivityManager = new NfcActivityManager(this);
389+
public Context getContext() {
390+
return mContext;
365391
}
366392

367393
/**
@@ -875,8 +901,12 @@ public boolean isNdefPushEnabled() {
875901
* @hide
876902
*/
877903
public INfcAdapterExtras getNfcAdapterExtrasInterface() {
904+
if (mContext == null) {
905+
throw new UnsupportedOperationException("You need a context on NfcAdapter to use the "
906+
+ " NFC extras APIs");
907+
}
878908
try {
879-
return sService.getNfcAdapterExtrasInterface();
909+
return sService.getNfcAdapterExtrasInterface(mContext.getPackageName());
880910
} catch (RemoteException e) {
881911
attemptDeadServiceRecovery(e);
882912
return null;

core/java/android/nfc/NfcManager.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,8 +39,9 @@ public final class NfcManager {
3939
*/
4040
public NfcManager(Context context) {
4141
NfcAdapter adapter;
42+
context = context.getApplicationContext();
4243
try {
43-
adapter = NfcAdapter.getSingleton();
44+
adapter = NfcAdapter.getNfcAdapter(context);
4445
} catch (UnsupportedOperationException e) {
4546
adapter = null;
4647
}

nfc-extras/java/com/android/nfc_extras/NfcAdapterExtras.java

Lines changed: 37 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -16,8 +16,7 @@
1616

1717
package com.android.nfc_extras;
1818

19-
import android.annotation.SdkConstant;
20-
import android.annotation.SdkConstant.SdkConstantType;
19+
import android.content.Context;
2120
import android.nfc.INfcAdapterExtras;
2221
import android.nfc.NfcAdapter;
2322
import android.os.RemoteException;
@@ -60,10 +59,14 @@ public final class NfcAdapterExtras {
6059
// best effort recovery
6160
private static NfcAdapter sAdapter;
6261
private static INfcAdapterExtras sService;
63-
private static NfcAdapterExtras sSingleton;
64-
private static NfcExecutionEnvironment sEmbeddedEe;
65-
private static CardEmulationRoute sRouteOff;
66-
private static CardEmulationRoute sRouteOnWhenScreenOn;
62+
private static final CardEmulationRoute ROUTE_OFF =
63+
new CardEmulationRoute(CardEmulationRoute.ROUTE_OFF, null);
64+
65+
private final NfcExecutionEnvironment mEmbeddedEe;
66+
private final CardEmulationRoute mRouteOnWhenScreenOn;
67+
68+
final Context mContext;
69+
final String mPackageName;
6770

6871
/** get service handles */
6972
private static void initService() {
@@ -84,31 +87,35 @@ private static void initService() {
8487
* @return the {@link NfcAdapterExtras} object for the given {@link NfcAdapter}
8588
*/
8689
public static NfcAdapterExtras get(NfcAdapter adapter) {
87-
synchronized(NfcAdapterExtras.class) {
88-
if (sSingleton == null) {
90+
Context context = adapter.getContext();
91+
if (context == null) {
92+
throw new UnsupportedOperationException(
93+
"You must pass a context to your NfcAdapter to use the NFC extras APIs");
94+
}
95+
96+
synchronized (NfcAdapterExtras.class) {
97+
if (sService == null) {
8998
try {
9099
sAdapter = adapter;
91-
sSingleton = new NfcAdapterExtras();
92-
sEmbeddedEe = new NfcExecutionEnvironment(sSingleton);
93-
sRouteOff = new CardEmulationRoute(CardEmulationRoute.ROUTE_OFF, null);
94-
sRouteOnWhenScreenOn = new CardEmulationRoute(
95-
CardEmulationRoute.ROUTE_ON_WHEN_SCREEN_ON, sEmbeddedEe);
96100
initService();
97101
} finally {
98102
if (sService == null) {
99-
sRouteOnWhenScreenOn = null;
100-
sRouteOff = null;
101-
sEmbeddedEe = null;
102-
sSingleton = null;
103103
sAdapter = null;
104104
}
105105
}
106106
}
107-
return sSingleton;
108107
}
108+
109+
return new NfcAdapterExtras(context);
109110
}
110111

111-
private NfcAdapterExtras() {}
112+
private NfcAdapterExtras(Context context) {
113+
mContext = context.getApplicationContext();
114+
mPackageName = context.getPackageName();
115+
mEmbeddedEe = new NfcExecutionEnvironment(this);
116+
mRouteOnWhenScreenOn = new CardEmulationRoute(CardEmulationRoute.ROUTE_ON_WHEN_SCREEN_ON,
117+
mEmbeddedEe);
118+
}
112119

113120
/**
114121
* Immutable data class that describes a card emulation route.
@@ -166,18 +173,16 @@ INfcAdapterExtras getService() {
166173
*
167174
* <p class="note">
168175
* Requires the {@link android.Manifest.permission#WRITE_SECURE_SETTINGS} permission.
169-
*
170-
* @return
171176
*/
172177
public CardEmulationRoute getCardEmulationRoute() {
173178
try {
174-
int route = sService.getCardEmulationRoute();
179+
int route = sService.getCardEmulationRoute(mPackageName);
175180
return route == CardEmulationRoute.ROUTE_OFF ?
176-
sRouteOff :
177-
sRouteOnWhenScreenOn;
181+
ROUTE_OFF :
182+
mRouteOnWhenScreenOn;
178183
} catch (RemoteException e) {
179184
attemptDeadServiceRecovery(e);
180-
return sRouteOff;
185+
return ROUTE_OFF;
181186
}
182187
}
183188

@@ -189,27 +194,27 @@ public CardEmulationRoute getCardEmulationRoute() {
189194
* <p class="note">
190195
* Requires the {@link android.Manifest.permission#WRITE_SECURE_SETTINGS} permission.
191196
*
192-
* @param route a {@link #CardEmulationRoute}
197+
* @param route a {@link CardEmulationRoute}
193198
*/
194199
public void setCardEmulationRoute(CardEmulationRoute route) {
195200
try {
196-
sService.setCardEmulationRoute(route.route);
201+
sService.setCardEmulationRoute(mPackageName, route.route);
197202
} catch (RemoteException e) {
198203
attemptDeadServiceRecovery(e);
199204
}
200205
}
201206

202207
/**
203208
* Get the {@link NfcExecutionEnvironment} that is embedded with the
204-
* {@link NFcAdapter}.
209+
* {@link NfcAdapter}.
205210
*
206211
* <p class="note">
207212
* Requires the {@link android.Manifest.permission#WRITE_SECURE_SETTINGS} permission.
208213
*
209214
* @return a {@link NfcExecutionEnvironment}, or null if there is no embedded NFC-EE
210215
*/
211216
public NfcExecutionEnvironment getEmbeddedExecutionEnvironment() {
212-
return sEmbeddedEe;
217+
return mEmbeddedEe;
213218
}
214219

215220
/**
@@ -218,12 +223,12 @@ public NfcExecutionEnvironment getEmbeddedExecutionEnvironment() {
218223
* Some implementations of NFC Adapter Extras may require applications
219224
* to authenticate with a token, before using other methods.
220225
*
221-
* @param a implementation specific token
222-
* @throws a {@link java.lang.SecurityException} if authentication failed
226+
* @param token a implementation specific token
227+
* @throws java.lang.SecurityException if authentication failed
223228
*/
224229
public void authenticate(byte[] token) {
225230
try {
226-
sService.authenticate(token);
231+
sService.authenticate(mPackageName, token);
227232
} catch (RemoteException e) {
228233
attemptDeadServiceRecovery(e);
229234
}

nfc-extras/java/com/android/nfc_extras/NfcExecutionEnvironment.java

Lines changed: 7 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -16,20 +16,17 @@
1616

1717
package com.android.nfc_extras;
1818

19-
import java.io.IOException;
20-
2119
import android.annotation.SdkConstant;
2220
import android.annotation.SdkConstant.SdkConstantType;
23-
import android.content.Context;
24-
import android.nfc.INfcAdapterExtras;
25-
import android.nfc.NfcAdapter;
2621
import android.os.Binder;
2722
import android.os.Bundle;
28-
import android.os.IBinder;
2923
import android.os.RemoteException;
3024

25+
import java.io.IOException;
26+
3127
public class NfcExecutionEnvironment {
3228
private final NfcAdapterExtras mExtras;
29+
private final Binder mToken;
3330

3431
/**
3532
* Broadcast Action: An ISO-DEP AID was selected.
@@ -115,6 +112,7 @@ public class NfcExecutionEnvironment {
115112

116113
NfcExecutionEnvironment(NfcAdapterExtras extras) {
117114
mExtras = extras;
115+
mToken = new Binder();
118116
}
119117

120118
/**
@@ -133,7 +131,7 @@ public class NfcExecutionEnvironment {
133131
*/
134132
public void open() throws IOException {
135133
try {
136-
Bundle b = mExtras.getService().open(new Binder());
134+
Bundle b = mExtras.getService().open(mExtras.mPackageName, mToken);
137135
throwBundle(b);
138136
} catch (RemoteException e) {
139137
mExtras.attemptDeadServiceRecovery(e);
@@ -151,7 +149,7 @@ public void open() throws IOException {
151149
*/
152150
public void close() throws IOException {
153151
try {
154-
throwBundle(mExtras.getService().close());
152+
throwBundle(mExtras.getService().close(mExtras.mPackageName, mToken));
155153
} catch (RemoteException e) {
156154
mExtras.attemptDeadServiceRecovery(e);
157155
throw new IOException("NFC Service was dead");
@@ -169,7 +167,7 @@ public void close() throws IOException {
169167
public byte[] transceive(byte[] in) throws IOException {
170168
Bundle b;
171169
try {
172-
b = mExtras.getService().transceive(in);
170+
b = mExtras.getService().transceive(mExtras.mPackageName, in);
173171
} catch (RemoteException e) {
174172
mExtras.attemptDeadServiceRecovery(e);
175173
throw new IOException("NFC Service was dead, need to re-open");

0 commit comments

Comments
 (0)