Skip to content

Commit 50b4d8f

Browse files
author
Nick Pelly
committed
Make getSystemService(NFC_SERVICE) the NFC entry point.
This gives NFC service a handle to the application context. Deprecate NfcAdapter.getDefaultAdapter(), it does not provide a context. Using this method will print a warning, and will later throw an exception if a method that requires a context is called. No 2.3 API's will fail, but new API's that do require a context might fail. Also add helper NfcAdapter.getDefaultAdapter(Context). Change-Id: I9a6378de4ef4b61ad922f8d53e64e2a1a1d5d60c
1 parent a218e01 commit 50b4d8f

File tree

9 files changed

+216
-61
lines changed

9 files changed

+216
-61
lines changed

api/current.xml

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35673,6 +35673,17 @@
3567335673
visibility="public"
3567435674
>
3567535675
</field>
35676+
<field name="NFC_SERVICE"
35677+
type="java.lang.String"
35678+
transient="false"
35679+
volatile="false"
35680+
value="&quot;nfc&quot;"
35681+
static="true"
35682+
final="true"
35683+
deprecated="not deprecated"
35684+
visibility="public"
35685+
>
35686+
</field>
3567635687
<field name="NOTIFICATION_SERVICE"
3567735688
type="java.lang.String"
3567835689
transient="false"
@@ -100183,6 +100194,19 @@
100183100194
deprecated="not deprecated"
100184100195
visibility="public"
100185100196
>
100197+
<parameter name="context" type="android.content.Context">
100198+
</parameter>
100199+
</method>
100200+
<method name="getDefaultAdapter"
100201+
return="android.nfc.NfcAdapter"
100202+
abstract="false"
100203+
native="false"
100204+
synchronized="false"
100205+
static="true"
100206+
final="false"
100207+
deprecated="deprecated"
100208+
visibility="public"
100209+
>
100186100210
</method>
100187100211
<method name="isEnabled"
100188100212
return="boolean"
@@ -100229,6 +100253,26 @@
100229100253
>
100230100254
</field>
100231100255
</class>
100256+
<class name="NfcManager"
100257+
extends="java.lang.Object"
100258+
abstract="false"
100259+
static="false"
100260+
final="true"
100261+
deprecated="not deprecated"
100262+
visibility="public"
100263+
>
100264+
<method name="getDefaultAdapter"
100265+
return="android.nfc.NfcAdapter"
100266+
abstract="false"
100267+
native="false"
100268+
synchronized="false"
100269+
static="false"
100270+
final="false"
100271+
deprecated="not deprecated"
100272+
visibility="public"
100273+
>
100274+
</method>
100275+
</class>
100232100276
</package>
100233100277
<package name="android.opengl"
100234100278
>

core/java/android/app/ContextImpl.java

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,7 @@
7272
import android.net.Uri;
7373
import android.net.wifi.IWifiManager;
7474
import android.net.wifi.WifiManager;
75+
import android.nfc.NfcManager;
7576
import android.os.Binder;
7677
import android.os.Bundle;
7778
import android.os.DropBoxManager;
@@ -201,6 +202,7 @@ class ContextImpl extends Context {
201202
private DevicePolicyManager mDevicePolicyManager = null;
202203
private UiModeManager mUiModeManager = null;
203204
private DownloadManager mDownloadManager = null;
205+
private NfcManager mNfcManager = null;
204206

205207
private final Object mSync = new Object();
206208

@@ -977,6 +979,8 @@ public Object getSystemService(String name) {
977979
return getUiModeManager();
978980
} else if (DOWNLOAD_SERVICE.equals(name)) {
979981
return getDownloadManager();
982+
} else if (NFC_SERVICE.equals(name)) {
983+
return getNfcManager();
980984
}
981985

982986
return null;
@@ -1204,6 +1208,15 @@ private DownloadManager getDownloadManager() {
12041208
return mDownloadManager;
12051209
}
12061210

1211+
private NfcManager getNfcManager() {
1212+
synchronized (mSync) {
1213+
if (mNfcManager == null) {
1214+
mNfcManager = new NfcManager(this);
1215+
}
1216+
}
1217+
return mNfcManager;
1218+
}
1219+
12071220
@Override
12081221
public int checkPermission(String permission, int pid, int uid) {
12091222
if (permission == null) {

core/java/android/content/Context.java

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1549,6 +1549,14 @@ public abstract boolean startInstrumentation(ComponentName className,
15491549
*/
15501550
public static final String DOWNLOAD_SERVICE = "download";
15511551

1552+
/**
1553+
* Use with {@link #getSystemService} to retrieve a
1554+
* {@link android.nfc.NfcManager} for using NFC.
1555+
*
1556+
* @see #getSystemService
1557+
*/
1558+
public static final String NFC_SERVICE = "nfc";
1559+
15521560
/**
15531561
* Use with {@link #getSystemService} to retrieve a
15541562
* {@link android.net.sip.SipManager} for accessing the SIP related service.

core/java/android/nfc/NfcAdapter.java

Lines changed: 78 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
import android.annotation.SdkConstant;
2020
import android.annotation.SdkConstant.SdkConstantType;
2121
import android.app.ActivityThread;
22+
import android.content.Context;
2223
import android.content.pm.IPackageManager;
2324
import android.content.pm.PackageManager;
2425
import android.os.IBinder;
@@ -29,11 +30,12 @@
2930
/**
3031
* Represents the device's local NFC adapter.
3132
* <p>
32-
* Use the static {@link #getDefaultAdapter} method to get the default NFC
33-
* Adapter for this Android device. Most Android devices will have only one NFC
34-
* Adapter, and {@link #getDefaultAdapter} returns the singleton object.
33+
* Use the helper {@link #getDefaultAdapter(Context)} to get the default NFC
34+
* adapter for this Android device.
3535
*/
3636
public final class NfcAdapter {
37+
private static final String TAG = "NFC";
38+
3739
/**
3840
* Intent to start an activity when a tag is discovered.
3941
*/
@@ -161,29 +163,17 @@ public final class NfcAdapter {
161163
*/
162164
private static final int DISCOVERY_MODE_CARD_EMULATION = 2;
163165

164-
private static final String TAG = "NFC";
165166

166-
// Both guarded by NfcAdapter.class:
167+
// Guarded by NfcAdapter.class
167168
private static boolean sIsInitialized = false;
168-
private static NfcAdapter sAdapter;
169169

170-
// Final after construction, except for attemptDeadServiceRecovery()
171-
// when NFC crashes.
172-
// Not locked - we accept a best effort attempt when NFC crashes.
173-
/*package*/ INfcAdapter mService;
170+
// Final after first constructor, except for
171+
// attemptDeadServiceRecovery() when NFC crashes - we accept a best effort
172+
// recovery
173+
private static INfcAdapter sService;
174174

175-
private NfcAdapter(INfcAdapter service) {
176-
mService = service;
177-
}
175+
private final Context mContext;
178176

179-
/**
180-
* Returns the binder interface to the service.
181-
* @hide
182-
*/
183-
public INfcAdapter getService() {
184-
return mService;
185-
}
186-
187177
/**
188178
* Helper to check if this device has FEATURE_NFC, but without using
189179
* a context.
@@ -204,8 +194,27 @@ private static boolean hasNfcFeature() {
204194
}
205195
}
206196

197+
private static synchronized INfcAdapter setupService() {
198+
if (!sIsInitialized) {
199+
sIsInitialized = true;
200+
201+
/* is this device meant to have NFC */
202+
if (!hasNfcFeature()) {
203+
Log.v(TAG, "this device does not have NFC support");
204+
return null;
205+
}
206+
207+
sService = getServiceInterface();
208+
if (sService == null) {
209+
Log.e(TAG, "could not retrieve NFC service");
210+
return null;
211+
}
212+
}
213+
return sService;
214+
}
215+
207216
/** get handle to NFC service interface */
208-
private static synchronized INfcAdapter getServiceInterface() {
217+
private static INfcAdapter getServiceInterface() {
209218
/* get a handle to NFC service */
210219
IBinder b = ServiceManager.getService("nfc");
211220
if (b == null) {
@@ -214,35 +223,55 @@ private static synchronized INfcAdapter getServiceInterface() {
214223
return INfcAdapter.Stub.asInterface(b);
215224
}
216225

226+
/**
227+
* Helper to get the default NFC Adapter.
228+
* <p>
229+
* Most Android devices will only have one NFC Adapter (NFC Controller).
230+
* <p>
231+
* This helper is the equivalent of:
232+
* <pre>{@code
233+
* NfcManager manager = (NfcManager) context.getSystemService(Context.NFC_SERVICE);
234+
* NfcAdapter adapter = manager.getDefaultAdapter();
235+
* }</pre>
236+
* @param context the calling application's context
237+
*
238+
* @return the default NFC adapter, or null if no NFC adapter exists
239+
*/
240+
public static NfcAdapter getDefaultAdapter(Context context) {
241+
/* use getSystemService() instead of just instantiating to take
242+
* advantage of the context's cached NfcManager & NfcAdapter */
243+
NfcManager manager = (NfcManager) context.getSystemService(Context.NFC_SERVICE);
244+
return manager.getDefaultAdapter();
245+
}
246+
217247
/**
218248
* Get a handle to the default NFC Adapter on this Android device.
219249
* <p>
220250
* Most Android devices will only have one NFC Adapter (NFC Controller).
221251
*
222252
* @return the default NFC adapter, or null if no NFC adapter exists
253+
* @deprecated use {@link #getDefaultAdapter(Context)}
223254
*/
255+
@Deprecated
224256
public static NfcAdapter getDefaultAdapter() {
225-
synchronized (NfcAdapter.class) {
226-
if (sIsInitialized) {
227-
return sAdapter;
228-
}
229-
sIsInitialized = true;
230-
231-
/* is this device meant to have NFC */
232-
if (!hasNfcFeature()) {
233-
Log.v(TAG, "this device does not have NFC support");
234-
return null;
235-
}
236-
237-
INfcAdapter service = getServiceInterface();
238-
if (service == null) {
239-
Log.e(TAG, "could not retrieve NFC service");
240-
return null;
241-
}
257+
Log.w(TAG, "WARNING: NfcAdapter.getDefaultAdapter() is deprecated, use " +
258+
"NfcAdapter.getDefaultAdapter(Context) instead", new Exception());
259+
return new NfcAdapter(null);
260+
}
242261

243-
sAdapter = new NfcAdapter(service);
244-
return sAdapter;
262+
/*package*/ NfcAdapter(Context context) {
263+
if (setupService() == null) {
264+
throw new UnsupportedOperationException();
245265
}
266+
mContext = context;
267+
}
268+
269+
/**
270+
* Returns the binder interface to the service.
271+
* @hide
272+
*/
273+
public INfcAdapter getService() {
274+
return sService;
246275
}
247276

248277
/**
@@ -256,9 +285,9 @@ public void attemptDeadServiceRecovery(Exception e) {
256285
Log.e(TAG, "could not retrieve NFC service during service recovery");
257286
return;
258287
}
259-
/* assigning to mService is not thread-safe, but this is best-effort code
288+
/* assigning to sService is not thread-safe, but this is best-effort code
260289
* and on a well-behaved system should never happen */
261-
mService = service;
290+
sService = service;
262291
return;
263292
}
264293

@@ -275,7 +304,7 @@ public void attemptDeadServiceRecovery(Exception e) {
275304
*/
276305
public boolean isEnabled() {
277306
try {
278-
return mService.isEnabled();
307+
return sService.isEnabled();
279308
} catch (RemoteException e) {
280309
attemptDeadServiceRecovery(e);
281310
return false;
@@ -292,7 +321,7 @@ public boolean isEnabled() {
292321
*/
293322
public boolean enable() {
294323
try {
295-
return mService.enable();
324+
return sService.enable();
296325
} catch (RemoteException e) {
297326
attemptDeadServiceRecovery(e);
298327
return false;
@@ -311,7 +340,7 @@ public boolean enable() {
311340
*/
312341
public boolean disable() {
313342
try {
314-
return mService.disable();
343+
return sService.disable();
315344
} catch (RemoteException e) {
316345
attemptDeadServiceRecovery(e);
317346
return false;
@@ -338,7 +367,7 @@ public boolean disable() {
338367
*/
339368
public void setLocalNdefMessage(NdefMessage message) {
340369
try {
341-
mService.localSet(message);
370+
sService.localSet(message);
342371
} catch (RemoteException e) {
343372
attemptDeadServiceRecovery(e);
344373
}
@@ -353,7 +382,7 @@ public void setLocalNdefMessage(NdefMessage message) {
353382
*/
354383
public NdefMessage getLocalNdefMessage() {
355384
try {
356-
return mService.localGet();
385+
return sService.localGet();
357386
} catch (RemoteException e) {
358387
attemptDeadServiceRecovery(e);
359388
return null;
@@ -366,7 +395,7 @@ public NdefMessage getLocalNdefMessage() {
366395
*/
367396
public NfcSecureElement createNfcSecureElementConnection() {
368397
try {
369-
return new NfcSecureElement(mService.getNfcSecureElementInterface());
398+
return new NfcSecureElement(sService.getNfcSecureElementInterface());
370399
} catch (RemoteException e) {
371400
Log.e(TAG, "createNfcSecureElementConnection failed", e);
372401
return null;

0 commit comments

Comments
 (0)