Merge "decouple HCE from FEATURE_NFC" into nyc-mr1-dev

This commit is contained in:
Steve Elliott
2016-05-10 19:48:59 +00:00
committed by Android (Google) Code Review

View File

@@ -290,6 +290,7 @@ public final class NfcAdapter {
// Guarded by NfcAdapter.class // Guarded by NfcAdapter.class
static boolean sIsInitialized = false; static boolean sIsInitialized = false;
static boolean sHasNfcFeature;
// Final after first constructor, except for // Final after first constructor, except for
// attemptDeadServiceRecovery() when NFC crashes - we accept a best effort // attemptDeadServiceRecovery() when NFC crashes - we accept a best effort
@@ -433,6 +434,26 @@ public final class NfcAdapter {
} }
} }
/**
* Helper to check if this device is NFC HCE capable, by checking for
* FEATURE_NFC_HOST_CARD_EMULATION and/or FEATURE_NFC_HOST_CARD_EMULATION_NFCF,
* but without using a context.
*/
private static boolean hasNfcHceFeature() {
IPackageManager pm = ActivityThread.getPackageManager();
if (pm == null) {
Log.e(TAG, "Cannot get package manager, assuming no NFC feature");
return false;
}
try {
return pm.hasSystemFeature(PackageManager.FEATURE_NFC_HOST_CARD_EMULATION, 0)
|| pm.hasSystemFeature(PackageManager.FEATURE_NFC_HOST_CARD_EMULATION_NFCF, 0);
} catch (RemoteException e) {
Log.e(TAG, "Package manager query failed, assuming no NFC feature", e);
return false;
}
}
/** /**
* Returns the NfcAdapter for application context, * Returns the NfcAdapter for application context,
* or throws if NFC is not available. * or throws if NFC is not available.
@@ -440,36 +461,39 @@ public final class NfcAdapter {
*/ */
public static synchronized NfcAdapter getNfcAdapter(Context context) { public static synchronized NfcAdapter getNfcAdapter(Context context) {
if (!sIsInitialized) { if (!sIsInitialized) {
sHasNfcFeature = hasNfcFeature();
boolean hasHceFeature = hasNfcHceFeature();
/* is this device meant to have NFC */ /* is this device meant to have NFC */
if (!hasNfcFeature()) { if (!sHasNfcFeature && !hasHceFeature) {
Log.v(TAG, "this device does not have NFC support"); Log.v(TAG, "this device does not have NFC support");
throw new UnsupportedOperationException(); throw new UnsupportedOperationException();
} }
sService = getServiceInterface(); sService = getServiceInterface();
if (sService == null) { if (sService == null) {
Log.e(TAG, "could not retrieve NFC service"); Log.e(TAG, "could not retrieve NFC service");
throw new UnsupportedOperationException(); throw new UnsupportedOperationException();
} }
try { if (sHasNfcFeature) {
sTagService = sService.getNfcTagInterface(); try {
} catch (RemoteException e) { sTagService = sService.getNfcTagInterface();
Log.e(TAG, "could not retrieve NFC Tag service"); } catch (RemoteException e) {
throw new UnsupportedOperationException(); Log.e(TAG, "could not retrieve NFC Tag service");
throw new UnsupportedOperationException();
}
} }
if (hasHceFeature) {
try { try {
sCardEmulationService = sService.getNfcCardEmulationInterface(); sNfcFCardEmulationService = sService.getNfcFCardEmulationInterface();
} catch (RemoteException e) { } catch (RemoteException e) {
Log.e(TAG, "could not retrieve card emulation service"); Log.e(TAG, "could not retrieve NFC-F card emulation service");
throw new UnsupportedOperationException(); throw new UnsupportedOperationException();
} }
try {
try { sCardEmulationService = sService.getNfcCardEmulationInterface();
sNfcFCardEmulationService = sService.getNfcFCardEmulationInterface(); } catch (RemoteException e) {
} catch (RemoteException e) { Log.e(TAG, "could not retrieve card emulation service");
Log.e(TAG, "could not retrieve NFC-F card emulation service"); throw new UnsupportedOperationException();
throw new UnsupportedOperationException(); }
} }
sIsInitialized = true; sIsInitialized = true;
@@ -837,8 +861,14 @@ public final class NfcAdapter {
* *
* @param uris an array of Uri(s) to push over Android Beam * @param uris an array of Uri(s) to push over Android Beam
* @param activity activity for which the Uri(s) will be pushed * @param activity activity for which the Uri(s) will be pushed
* @throws UnsupportedOperationException if FEATURE_NFC is unavailable.
*/ */
public void setBeamPushUris(Uri[] uris, Activity activity) { public void setBeamPushUris(Uri[] uris, Activity activity) {
synchronized (NfcAdapter.class) {
if (!sHasNfcFeature) {
throw new UnsupportedOperationException();
}
}
if (activity == null) { if (activity == null) {
throw new NullPointerException("activity cannot be null"); throw new NullPointerException("activity cannot be null");
} }
@@ -913,8 +943,14 @@ public final class NfcAdapter {
* *
* @param callback callback, or null to disable * @param callback callback, or null to disable
* @param activity activity for which the Uri(s) will be pushed * @param activity activity for which the Uri(s) will be pushed
* @throws UnsupportedOperationException if FEATURE_NFC is unavailable.
*/ */
public void setBeamPushUrisCallback(CreateBeamUrisCallback callback, Activity activity) { public void setBeamPushUrisCallback(CreateBeamUrisCallback callback, Activity activity) {
synchronized (NfcAdapter.class) {
if (!sHasNfcFeature) {
throw new UnsupportedOperationException();
}
}
if (activity == null) { if (activity == null) {
throw new NullPointerException("activity cannot be null"); throw new NullPointerException("activity cannot be null");
} }
@@ -991,9 +1027,15 @@ public final class NfcAdapter {
* @param activities optional additional activities, however we strongly recommend * @param activities optional additional activities, however we strongly recommend
* to only register one at a time, and to do so in that activity's * to only register one at a time, and to do so in that activity's
* {@link Activity#onCreate} * {@link Activity#onCreate}
* @throws UnsupportedOperationException if FEATURE_NFC is unavailable.
*/ */
public void setNdefPushMessage(NdefMessage message, Activity activity, public void setNdefPushMessage(NdefMessage message, Activity activity,
Activity ... activities) { Activity ... activities) {
synchronized (NfcAdapter.class) {
if (!sHasNfcFeature) {
throw new UnsupportedOperationException();
}
}
int targetSdkVersion = getSdkVersion(); int targetSdkVersion = getSdkVersion();
try { try {
if (activity == null) { if (activity == null) {
@@ -1023,6 +1065,11 @@ public final class NfcAdapter {
*/ */
@SystemApi @SystemApi
public void setNdefPushMessage(NdefMessage message, Activity activity, int flags) { public void setNdefPushMessage(NdefMessage message, Activity activity, int flags) {
synchronized (NfcAdapter.class) {
if (!sHasNfcFeature) {
throw new UnsupportedOperationException();
}
}
if (activity == null) { if (activity == null) {
throw new NullPointerException("activity cannot be null"); throw new NullPointerException("activity cannot be null");
} }
@@ -1093,9 +1140,15 @@ public final class NfcAdapter {
* @param activities optional additional activities, however we strongly recommend * @param activities optional additional activities, however we strongly recommend
* to only register one at a time, and to do so in that activity's * to only register one at a time, and to do so in that activity's
* {@link Activity#onCreate} * {@link Activity#onCreate}
* @throws UnsupportedOperationException if FEATURE_NFC is unavailable.
*/ */
public void setNdefPushMessageCallback(CreateNdefMessageCallback callback, Activity activity, public void setNdefPushMessageCallback(CreateNdefMessageCallback callback, Activity activity,
Activity ... activities) { Activity ... activities) {
synchronized (NfcAdapter.class) {
if (!sHasNfcFeature) {
throw new UnsupportedOperationException();
}
}
int targetSdkVersion = getSdkVersion(); int targetSdkVersion = getSdkVersion();
try { try {
if (activity == null) { if (activity == null) {
@@ -1167,9 +1220,15 @@ public final class NfcAdapter {
* @param activities optional additional activities, however we strongly recommend * @param activities optional additional activities, however we strongly recommend
* to only register one at a time, and to do so in that activity's * to only register one at a time, and to do so in that activity's
* {@link Activity#onCreate} * {@link Activity#onCreate}
* @throws UnsupportedOperationException if FEATURE_NFC is unavailable.
*/ */
public void setOnNdefPushCompleteCallback(OnNdefPushCompleteCallback callback, public void setOnNdefPushCompleteCallback(OnNdefPushCompleteCallback callback,
Activity activity, Activity ... activities) { Activity activity, Activity ... activities) {
synchronized (NfcAdapter.class) {
if (!sHasNfcFeature) {
throw new UnsupportedOperationException();
}
}
int targetSdkVersion = getSdkVersion(); int targetSdkVersion = getSdkVersion();
try { try {
if (activity == null) { if (activity == null) {
@@ -1226,9 +1285,15 @@ public final class NfcAdapter {
* @param techLists the tech lists used to perform matching for dispatching of the * @param techLists the tech lists used to perform matching for dispatching of the
* {@link NfcAdapter#ACTION_TECH_DISCOVERED} intent * {@link NfcAdapter#ACTION_TECH_DISCOVERED} intent
* @throws IllegalStateException if the Activity is not currently in the foreground * @throws IllegalStateException if the Activity is not currently in the foreground
* @throws UnsupportedOperationException if FEATURE_NFC is unavailable.
*/ */
public void enableForegroundDispatch(Activity activity, PendingIntent intent, public void enableForegroundDispatch(Activity activity, PendingIntent intent,
IntentFilter[] filters, String[][] techLists) { IntentFilter[] filters, String[][] techLists) {
synchronized (NfcAdapter.class) {
if (!sHasNfcFeature) {
throw new UnsupportedOperationException();
}
}
if (activity == null || intent == null) { if (activity == null || intent == null) {
throw new NullPointerException(); throw new NullPointerException();
} }
@@ -1262,8 +1327,14 @@ public final class NfcAdapter {
* *
* @param activity the Activity to disable dispatch to * @param activity the Activity to disable dispatch to
* @throws IllegalStateException if the Activity has already been paused * @throws IllegalStateException if the Activity has already been paused
* @throws UnsupportedOperationException if FEATURE_NFC is unavailable.
*/ */
public void disableForegroundDispatch(Activity activity) { public void disableForegroundDispatch(Activity activity) {
synchronized (NfcAdapter.class) {
if (!sHasNfcFeature) {
throw new UnsupportedOperationException();
}
}
ActivityThread.currentActivityThread().unregisterOnActivityPausedListener(activity, ActivityThread.currentActivityThread().unregisterOnActivityPausedListener(activity,
mForegroundDispatchListener); mForegroundDispatchListener);
disableForegroundDispatchInternal(activity, false); disableForegroundDispatchInternal(activity, false);
@@ -1308,9 +1379,15 @@ public final class NfcAdapter {
* @param callback the callback to be called when a tag is discovered * @param callback the callback to be called when a tag is discovered
* @param flags Flags indicating poll technologies and other optional parameters * @param flags Flags indicating poll technologies and other optional parameters
* @param extras Additional extras for configuring reader mode. * @param extras Additional extras for configuring reader mode.
* @throws UnsupportedOperationException if FEATURE_NFC is unavailable.
*/ */
public void enableReaderMode(Activity activity, ReaderCallback callback, int flags, public void enableReaderMode(Activity activity, ReaderCallback callback, int flags,
Bundle extras) { Bundle extras) {
synchronized (NfcAdapter.class) {
if (!sHasNfcFeature) {
throw new UnsupportedOperationException();
}
}
mNfcActivityManager.enableReaderMode(activity, callback, flags, extras); mNfcActivityManager.enableReaderMode(activity, callback, flags, extras);
} }
@@ -1320,8 +1397,14 @@ public final class NfcAdapter {
* all supported tag technologies. * all supported tag technologies.
* *
* @param activity the Activity that currently has reader mode enabled * @param activity the Activity that currently has reader mode enabled
* @throws UnsupportedOperationException if FEATURE_NFC is unavailable.
*/ */
public void disableReaderMode(Activity activity) { public void disableReaderMode(Activity activity) {
synchronized (NfcAdapter.class) {
if (!sHasNfcFeature) {
throw new UnsupportedOperationException();
}
}
mNfcActivityManager.disableReaderMode(activity); mNfcActivityManager.disableReaderMode(activity);
} }
@@ -1348,8 +1431,14 @@ public final class NfcAdapter {
* *
* @param activity the current foreground Activity that has registered data to share * @param activity the current foreground Activity that has registered data to share
* @return whether the Beam animation was successfully invoked * @return whether the Beam animation was successfully invoked
* @throws UnsupportedOperationException if FEATURE_NFC is unavailable.
*/ */
public boolean invokeBeam(Activity activity) { public boolean invokeBeam(Activity activity) {
synchronized (NfcAdapter.class) {
if (!sHasNfcFeature) {
throw new UnsupportedOperationException();
}
}
if (activity == null) { if (activity == null) {
throw new NullPointerException("activity may not be null."); throw new NullPointerException("activity may not be null.");
} }
@@ -1403,10 +1492,16 @@ public final class NfcAdapter {
* @param activity foreground activity * @param activity foreground activity
* @param message a NDEF Message to push over NFC * @param message a NDEF Message to push over NFC
* @throws IllegalStateException if the activity is not currently in the foreground * @throws IllegalStateException if the activity is not currently in the foreground
* @throws UnsupportedOperationException if FEATURE_NFC is unavailable.
* @deprecated use {@link #setNdefPushMessage} instead * @deprecated use {@link #setNdefPushMessage} instead
*/ */
@Deprecated @Deprecated
public void enableForegroundNdefPush(Activity activity, NdefMessage message) { public void enableForegroundNdefPush(Activity activity, NdefMessage message) {
synchronized (NfcAdapter.class) {
if (!sHasNfcFeature) {
throw new UnsupportedOperationException();
}
}
if (activity == null || message == null) { if (activity == null || message == null) {
throw new NullPointerException(); throw new NullPointerException();
} }
@@ -1431,10 +1526,16 @@ public final class NfcAdapter {
* *
* @param activity the Foreground activity * @param activity the Foreground activity
* @throws IllegalStateException if the Activity has already been paused * @throws IllegalStateException if the Activity has already been paused
* @throws UnsupportedOperationException if FEATURE_NFC is unavailable.
* @deprecated use {@link #setNdefPushMessage} instead * @deprecated use {@link #setNdefPushMessage} instead
*/ */
@Deprecated @Deprecated
public void disableForegroundNdefPush(Activity activity) { public void disableForegroundNdefPush(Activity activity) {
synchronized (NfcAdapter.class) {
if (!sHasNfcFeature) {
throw new UnsupportedOperationException();
}
}
if (activity == null) { if (activity == null) {
throw new NullPointerException(); throw new NullPointerException();
} }
@@ -1451,6 +1552,9 @@ public final class NfcAdapter {
*/ */
@SystemApi @SystemApi
public boolean enableNdefPush() { public boolean enableNdefPush() {
if (!sHasNfcFeature) {
throw new UnsupportedOperationException();
}
try { try {
return sService.enableNdefPush(); return sService.enableNdefPush();
} catch (RemoteException e) { } catch (RemoteException e) {
@@ -1466,6 +1570,11 @@ public final class NfcAdapter {
*/ */
@SystemApi @SystemApi
public boolean disableNdefPush() { public boolean disableNdefPush() {
synchronized (NfcAdapter.class) {
if (!sHasNfcFeature) {
throw new UnsupportedOperationException();
}
}
try { try {
return sService.disableNdefPush(); return sService.disableNdefPush();
} catch (RemoteException e) { } catch (RemoteException e) {
@@ -1496,8 +1605,14 @@ public final class NfcAdapter {
* *
* @see android.provider.Settings#ACTION_NFCSHARING_SETTINGS * @see android.provider.Settings#ACTION_NFCSHARING_SETTINGS
* @return true if NDEF Push feature is enabled * @return true if NDEF Push feature is enabled
* @throws UnsupportedOperationException if FEATURE_NFC is unavailable.
*/ */
public boolean isNdefPushEnabled() { public boolean isNdefPushEnabled() {
synchronized (NfcAdapter.class) {
if (!sHasNfcFeature) {
throw new UnsupportedOperationException();
}
}
try { try {
return sService.isNdefPushEnabled(); return sService.isNdefPushEnabled();
} catch (RemoteException e) { } catch (RemoteException e) {
@@ -1622,6 +1737,11 @@ public final class NfcAdapter {
@SystemApi @SystemApi
public boolean addNfcUnlockHandler(final NfcUnlockHandler unlockHandler, public boolean addNfcUnlockHandler(final NfcUnlockHandler unlockHandler,
String[] tagTechnologies) { String[] tagTechnologies) {
synchronized (NfcAdapter.class) {
if (!sHasNfcFeature) {
throw new UnsupportedOperationException();
}
}
// If there are no tag technologies, don't bother adding unlock handler // If there are no tag technologies, don't bother adding unlock handler
if (tagTechnologies.length == 0) { if (tagTechnologies.length == 0) {
return false; return false;
@@ -1665,6 +1785,11 @@ public final class NfcAdapter {
*/ */
@SystemApi @SystemApi
public boolean removeNfcUnlockHandler(NfcUnlockHandler unlockHandler) { public boolean removeNfcUnlockHandler(NfcUnlockHandler unlockHandler) {
synchronized (NfcAdapter.class) {
if (!sHasNfcFeature) {
throw new UnsupportedOperationException();
}
}
try { try {
synchronized (mLock) { synchronized (mLock) {
if (mNfcUnlockHandlers.containsKey(unlockHandler)) { if (mNfcUnlockHandlers.containsKey(unlockHandler)) {