summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
author Alisher Alikhodjaev <alisher@google.com> 2023-11-28 14:52:44 -0800
committer Alisher Alikhodjaev <alisher@google.com> 2024-01-04 13:44:20 -0800
commita0de319f68205f4afb2005aed4d4fbfe13db7210 (patch)
tree44a302d1b7958ac4cdb5def965eb013fdecf9887
parent2d1d2ccee4085ec7571711639bcaafc3fde84473 (diff)
Implementation of Dedicated card mode APIs changes
(Discovery tech and Change Routing) Bug: 300351519 Test: n/a Change-Id: If664910d00fc673c0329e0cd4489174260eb4f1e (cherry picked from commit 04a371696f7d882f151d1b0ae4dd262fda9e4452)
-rw-r--r--core/api/current.txt9
-rw-r--r--core/java/android/nfc/INfcAdapter.aidl2
-rw-r--r--core/java/android/nfc/INfcCardEmulation.aidl3
-rw-r--r--core/java/android/nfc/NfcActivityManager.java74
-rw-r--r--core/java/android/nfc/NfcAdapter.java195
-rw-r--r--core/java/android/nfc/cardemulation/CardEmulation.java81
-rw-r--r--core/java/android/nfc/flags.aconfig7
7 files changed, 353 insertions, 18 deletions
diff --git a/core/api/current.txt b/core/api/current.txt
index df073dda254a..f92a3af99e96 100644
--- a/core/api/current.txt
+++ b/core/api/current.txt
@@ -28823,6 +28823,8 @@ package android.nfc {
method public boolean isSecureNfcEnabled();
method public boolean isSecureNfcSupported();
method @FlaggedApi("android.nfc.enable_nfc_charging") public boolean isWlcEnabled();
+ method @FlaggedApi("android.nfc.enable_nfc_set_discovery_tech") public void resetDiscoveryTechnology(@NonNull android.app.Activity);
+ method @FlaggedApi("android.nfc.enable_nfc_set_discovery_tech") public void setDiscoveryTechnology(@NonNull android.app.Activity, int, int);
field public static final String ACTION_ADAPTER_STATE_CHANGED = "android.nfc.action.ADAPTER_STATE_CHANGED";
field public static final String ACTION_NDEF_DISCOVERED = "android.nfc.action.NDEF_DISCOVERED";
field @RequiresPermission(android.Manifest.permission.NFC_PREFERRED_PAYMENT_INFO) public static final String ACTION_PREFERRED_PAYMENT_CHANGED = "android.nfc.action.PREFERRED_PAYMENT_CHANGED";
@@ -28838,6 +28840,13 @@ package android.nfc {
field public static final String EXTRA_READER_PRESENCE_CHECK_DELAY = "presence";
field public static final String EXTRA_SECURE_ELEMENT_NAME = "android.nfc.extra.SECURE_ELEMENT_NAME";
field public static final String EXTRA_TAG = "android.nfc.extra.TAG";
+ field @FlaggedApi("android.nfc.enable_nfc_set_discovery_tech") public static final int FLAG_LISTEN_DISABLE = 0; // 0x0
+ field @FlaggedApi("android.nfc.enable_nfc_set_discovery_tech") public static final int FLAG_LISTEN_KEEP = -1; // 0xffffffff
+ field @FlaggedApi("android.nfc.enable_nfc_set_discovery_tech") public static final int FLAG_LISTEN_NFC_PASSIVE_A = 1; // 0x1
+ field @FlaggedApi("android.nfc.enable_nfc_set_discovery_tech") public static final int FLAG_LISTEN_NFC_PASSIVE_B = 2; // 0x2
+ field @FlaggedApi("android.nfc.enable_nfc_set_discovery_tech") public static final int FLAG_LISTEN_NFC_PASSIVE_F = 4; // 0x4
+ field @FlaggedApi("android.nfc.enable_nfc_set_discovery_tech") public static final int FLAG_READER_DISABLE = 0; // 0x0
+ field @FlaggedApi("android.nfc.enable_nfc_set_discovery_tech") public static final int FLAG_READER_KEEP = -1; // 0xffffffff
field public static final int FLAG_READER_NFC_A = 1; // 0x1
field public static final int FLAG_READER_NFC_B = 2; // 0x2
field public static final int FLAG_READER_NFC_BARCODE = 16; // 0x10
diff --git a/core/java/android/nfc/INfcAdapter.aidl b/core/java/android/nfc/INfcAdapter.aidl
index 967a0cc92ef5..286cf2890eea 100644
--- a/core/java/android/nfc/INfcAdapter.aidl
+++ b/core/java/android/nfc/INfcAdapter.aidl
@@ -95,4 +95,6 @@ interface INfcAdapter
void registerWlcStateListener(in INfcWlcStateListener listener);
void unregisterWlcStateListener(in INfcWlcStateListener listener);
WlcLDeviceInfo getWlcLDeviceInfo();
+
+ void updateDiscoveryTechnology(IBinder b, int pollFlags, int listenFlags);
}
diff --git a/core/java/android/nfc/INfcCardEmulation.aidl b/core/java/android/nfc/INfcCardEmulation.aidl
index 191385a3c13d..f4b46046bc3e 100644
--- a/core/java/android/nfc/INfcCardEmulation.aidl
+++ b/core/java/android/nfc/INfcCardEmulation.aidl
@@ -43,4 +43,7 @@ interface INfcCardEmulation
ApduServiceInfo getPreferredPaymentService(int userHandle);
boolean setServiceEnabledForCategoryOther(int userHandle, in ComponentName app, boolean status);
boolean isDefaultPaymentRegistered();
+
+ boolean overrideRoutingTable(int userHandle, String protocol, String technology);
+ boolean recoverRoutingTable(int userHandle);
}
diff --git a/core/java/android/nfc/NfcActivityManager.java b/core/java/android/nfc/NfcActivityManager.java
index 8d75cac531fb..f03fc0af86b3 100644
--- a/core/java/android/nfc/NfcActivityManager.java
+++ b/core/java/android/nfc/NfcActivityManager.java
@@ -112,6 +112,9 @@ public final class NfcActivityManager extends IAppCallback.Stub
Bundle readerModeExtras = null;
Binder token;
+ int mPollTech = NfcAdapter.FLAG_USE_ALL_TECH;
+ int mListenTech = NfcAdapter.FLAG_USE_ALL_TECH;
+
public NfcActivityState(Activity activity) {
if (activity.isDestroyed()) {
throw new IllegalStateException("activity is already destroyed");
@@ -132,6 +135,9 @@ public final class NfcActivityManager extends IAppCallback.Stub
readerModeFlags = 0;
readerModeExtras = null;
token = null;
+
+ mPollTech = NfcAdapter.FLAG_USE_ALL_TECH;
+ mListenTech = NfcAdapter.FLAG_USE_ALL_TECH;
}
@Override
public String toString() {
@@ -278,6 +284,9 @@ public final class NfcActivityManager extends IAppCallback.Stub
int readerModeFlags = 0;
Bundle readerModeExtras = null;
Binder token;
+ int pollTech;
+ int listenTech;
+
synchronized (NfcActivityManager.this) {
NfcActivityState state = findActivityState(activity);
if (DBG) Log.d(TAG, "onResume() for " + activity + " " + state);
@@ -286,9 +295,15 @@ public final class NfcActivityManager extends IAppCallback.Stub
token = state.token;
readerModeFlags = state.readerModeFlags;
readerModeExtras = state.readerModeExtras;
+
+ pollTech = state.mPollTech;
+ listenTech = state.mListenTech;
}
if (readerModeFlags != 0) {
setReaderMode(token, readerModeFlags, readerModeExtras);
+ } else if (listenTech != NfcAdapter.FLAG_USE_ALL_TECH
+ || pollTech != NfcAdapter.FLAG_USE_ALL_TECH) {
+ changeDiscoveryTech(token, pollTech, listenTech);
}
requestNfcServiceCallback();
}
@@ -298,6 +313,9 @@ public final class NfcActivityManager extends IAppCallback.Stub
public void onActivityPaused(Activity activity) {
boolean readerModeFlagsSet;
Binder token;
+ int pollTech;
+ int listenTech;
+
synchronized (NfcActivityManager.this) {
NfcActivityState state = findActivityState(activity);
if (DBG) Log.d(TAG, "onPause() for " + activity + " " + state);
@@ -305,10 +323,17 @@ public final class NfcActivityManager extends IAppCallback.Stub
state.resumed = false;
token = state.token;
readerModeFlagsSet = state.readerModeFlags != 0;
+
+ pollTech = state.mPollTech;
+ listenTech = state.mListenTech;
}
if (readerModeFlagsSet) {
// Restore default p2p modes
setReaderMode(token, 0, null);
+ } else if (listenTech != NfcAdapter.FLAG_USE_ALL_TECH
+ || pollTech != NfcAdapter.FLAG_USE_ALL_TECH) {
+ changeDiscoveryTech(token,
+ NfcAdapter.FLAG_USE_ALL_TECH, NfcAdapter.FLAG_USE_ALL_TECH);
}
}
@@ -333,4 +358,53 @@ public final class NfcActivityManager extends IAppCallback.Stub
}
}
+ /** setDiscoveryTechnology() implementation */
+ public void setDiscoveryTech(Activity activity, int pollTech, int listenTech) {
+ boolean isResumed;
+ Binder token;
+ boolean readerModeFlagsSet;
+ synchronized (NfcActivityManager.this) {
+ NfcActivityState state = getActivityState(activity);
+ readerModeFlagsSet = state.readerModeFlags != 0;
+ state.mListenTech = listenTech;
+ state.mPollTech = pollTech;
+ token = state.token;
+ isResumed = state.resumed;
+ }
+ if (!readerModeFlagsSet && isResumed) {
+ changeDiscoveryTech(token, pollTech, listenTech);
+ } else if (readerModeFlagsSet) {
+ throw new IllegalStateException("Cannot be used when the Reader Mode is enabled");
+ }
+ }
+
+ /** resetDiscoveryTechnology() implementation */
+ public void resetDiscoveryTech(Activity activity) {
+ boolean isResumed;
+ Binder token;
+ boolean readerModeFlagsSet;
+ synchronized (NfcActivityManager.this) {
+ NfcActivityState state = getActivityState(activity);
+ readerModeFlagsSet = state.readerModeFlags != 0;
+ state.mListenTech = NfcAdapter.FLAG_USE_ALL_TECH;
+ state.mPollTech = NfcAdapter.FLAG_USE_ALL_TECH;
+ token = state.token;
+ isResumed = state.resumed;
+ }
+ if (readerModeFlagsSet) {
+ disableReaderMode(activity);
+ } else if (isResumed) {
+ changeDiscoveryTech(token, NfcAdapter.FLAG_USE_ALL_TECH, NfcAdapter.FLAG_USE_ALL_TECH);
+ }
+
+ }
+
+ private void changeDiscoveryTech(Binder token, int pollTech, int listenTech) {
+ try {
+ NfcAdapter.sService.updateDiscoveryTechnology(token, pollTech, listenTech);
+ } catch (RemoteException e) {
+ mAdapter.attemptDeadServiceRecovery(e);
+ }
+ }
+
}
diff --git a/core/java/android/nfc/NfcAdapter.java b/core/java/android/nfc/NfcAdapter.java
index 21e23ae53979..5a40e424ea91 100644
--- a/core/java/android/nfc/NfcAdapter.java
+++ b/core/java/android/nfc/NfcAdapter.java
@@ -333,6 +333,19 @@ public final class NfcAdapter {
*/
public static final int FLAG_READER_NFC_BARCODE = 0x10;
+ /** @hide */
+ @IntDef(flag = true, prefix = {"FLAG_READER_"}, value = {
+ FLAG_READER_KEEP,
+ FLAG_READER_DISABLE,
+ FLAG_READER_NFC_A,
+ FLAG_READER_NFC_B,
+ FLAG_READER_NFC_F,
+ FLAG_READER_NFC_V,
+ FLAG_READER_NFC_BARCODE
+ })
+ @Retention(RetentionPolicy.SOURCE)
+ public @interface PollTechnology {}
+
/**
* Flag for use with {@link #enableReaderMode(Activity, ReaderCallback, int, Bundle)}.
* <p>
@@ -360,6 +373,76 @@ public final class NfcAdapter {
public static final String EXTRA_READER_PRESENCE_CHECK_DELAY = "presence";
/**
+ * Flag for use with {@link #setDiscoveryTechnology(Activity, int, int)}.
+ * <p>
+ * Setting this flag enables listening for Nfc-A technology.
+ */
+ @FlaggedApi(Flags.FLAG_ENABLE_NFC_SET_DISCOVERY_TECH)
+ public static final int FLAG_LISTEN_NFC_PASSIVE_A = 0x1;
+
+ /**
+ * Flag for use with {@link #setDiscoveryTechnology(Activity, int, int)}.
+ * <p>
+ * Setting this flag enables listening for Nfc-B technology.
+ */
+ @FlaggedApi(Flags.FLAG_ENABLE_NFC_SET_DISCOVERY_TECH)
+ public static final int FLAG_LISTEN_NFC_PASSIVE_B = 1 << 1;
+
+ /**
+ * Flag for use with {@link #setDiscoveryTechnology(Activity, int, int)}.
+ * <p>
+ * Setting this flag enables listening for Nfc-F technology.
+ */
+ @FlaggedApi(Flags.FLAG_ENABLE_NFC_SET_DISCOVERY_TECH)
+ public static final int FLAG_LISTEN_NFC_PASSIVE_F = 1 << 2;
+
+ /**
+ * Flags for use with {@link #setDiscoveryTechnology(Activity, int, int)}.
+ * <p>
+ * Setting this flag disables listening.
+ */
+ @FlaggedApi(Flags.FLAG_ENABLE_NFC_SET_DISCOVERY_TECH)
+ public static final int FLAG_LISTEN_DISABLE = 0x0;
+
+ /**
+ * Flags for use with {@link #setDiscoveryTechnology(Activity, int, int)}.
+ * <p>
+ * Setting this flag disables polling.
+ */
+ @FlaggedApi(Flags.FLAG_ENABLE_NFC_SET_DISCOVERY_TECH)
+ public static final int FLAG_READER_DISABLE = 0x0;
+
+ /**
+ * Flags for use with {@link #setDiscoveryTechnology(Activity, int, int)}.
+ * <p>
+ * Setting this flag makes listening to use current flags.
+ */
+ @FlaggedApi(Flags.FLAG_ENABLE_NFC_SET_DISCOVERY_TECH)
+ public static final int FLAG_LISTEN_KEEP = -1;
+
+ /**
+ * Flags for use with {@link #setDiscoveryTechnology(Activity, int, int)}.
+ * <p>
+ * Setting this flag makes polling to use current flags.
+ */
+ @FlaggedApi(Flags.FLAG_ENABLE_NFC_SET_DISCOVERY_TECH)
+ public static final int FLAG_READER_KEEP = -1;
+
+ /** @hide */
+ public static final int FLAG_USE_ALL_TECH = 0xff;
+
+ /** @hide */
+ @IntDef(flag = true, prefix = {"FLAG_LISTEN_"}, value = {
+ FLAG_LISTEN_KEEP,
+ FLAG_LISTEN_DISABLE,
+ FLAG_LISTEN_NFC_PASSIVE_A,
+ FLAG_LISTEN_NFC_PASSIVE_B,
+ FLAG_LISTEN_NFC_PASSIVE_F
+ })
+ @Retention(RetentionPolicy.SOURCE)
+ public @interface ListenTechnology {}
+
+ /**
* @hide
* @removed
*/
@@ -437,12 +520,14 @@ public final class NfcAdapter {
@Retention(RetentionPolicy.SOURCE)
public @interface TagIntentAppPreferenceResult {}
- // Guarded by NfcAdapter.class
+ // Guarded by sLock
static boolean sIsInitialized = false;
static boolean sHasNfcFeature;
static boolean sHasCeFeature;
static boolean sHasNfcWlcFeature;
+ static Object sLock = new Object();
+
// Final after first constructor, except for
// attemptDeadServiceRecovery() when NFC crashes - we accept a best effort
// recovery
@@ -1235,7 +1320,7 @@ public final class NfcAdapter {
@java.lang.Deprecated
@UnsupportedAppUsage
public void setBeamPushUris(Uri[] uris, Activity activity) {
- synchronized (NfcAdapter.class) {
+ synchronized (sLock) {
if (!sHasNfcFeature) {
throw new UnsupportedOperationException();
}
@@ -1305,7 +1390,7 @@ public final class NfcAdapter {
@java.lang.Deprecated
@UnsupportedAppUsage
public void setBeamPushUrisCallback(CreateBeamUrisCallback callback, Activity activity) {
- synchronized (NfcAdapter.class) {
+ synchronized (sLock) {
if (!sHasNfcFeature) {
throw new UnsupportedOperationException();
}
@@ -1390,7 +1475,7 @@ public final class NfcAdapter {
@UnsupportedAppUsage
public void setNdefPushMessage(NdefMessage message, Activity activity,
Activity ... activities) {
- synchronized (NfcAdapter.class) {
+ synchronized (sLock) {
if (!sHasNfcFeature) {
throw new UnsupportedOperationException();
}
@@ -1404,7 +1489,7 @@ public final class NfcAdapter {
@SystemApi
@UnsupportedAppUsage
public void setNdefPushMessage(NdefMessage message, Activity activity, int flags) {
- synchronized (NfcAdapter.class) {
+ synchronized (sLock) {
if (!sHasNfcFeature) {
throw new UnsupportedOperationException();
}
@@ -1483,7 +1568,7 @@ public final class NfcAdapter {
@UnsupportedAppUsage
public void setNdefPushMessageCallback(CreateNdefMessageCallback callback, Activity activity,
Activity ... activities) {
- synchronized (NfcAdapter.class) {
+ synchronized (sLock) {
if (!sHasNfcFeature) {
throw new UnsupportedOperationException();
}
@@ -1534,7 +1619,7 @@ public final class NfcAdapter {
@UnsupportedAppUsage
public void setOnNdefPushCompleteCallback(OnNdefPushCompleteCallback callback,
Activity activity, Activity ... activities) {
- synchronized (NfcAdapter.class) {
+ synchronized (sLock) {
if (!sHasNfcFeature) {
throw new UnsupportedOperationException();
}
@@ -1577,7 +1662,7 @@ public final class NfcAdapter {
*/
public void enableForegroundDispatch(Activity activity, PendingIntent intent,
IntentFilter[] filters, String[][] techLists) {
- synchronized (NfcAdapter.class) {
+ synchronized (sLock) {
if (!sHasNfcFeature) {
throw new UnsupportedOperationException();
}
@@ -1612,7 +1697,7 @@ public final class NfcAdapter {
* @throws UnsupportedOperationException if FEATURE_NFC is unavailable.
*/
public void disableForegroundDispatch(Activity activity) {
- synchronized (NfcAdapter.class) {
+ synchronized (sLock) {
if (!sHasNfcFeature) {
throw new UnsupportedOperationException();
}
@@ -1648,7 +1733,7 @@ public final class NfcAdapter {
*/
public void enableReaderMode(Activity activity, ReaderCallback callback, int flags,
Bundle extras) {
- synchronized (NfcAdapter.class) {
+ synchronized (sLock) {
if (!sHasNfcFeature) {
throw new UnsupportedOperationException();
}
@@ -1665,7 +1750,7 @@ public final class NfcAdapter {
* @throws UnsupportedOperationException if FEATURE_NFC is unavailable.
*/
public void disableReaderMode(Activity activity) {
- synchronized (NfcAdapter.class) {
+ synchronized (sLock) {
if (!sHasNfcFeature) {
throw new UnsupportedOperationException();
}
@@ -1693,7 +1778,7 @@ public final class NfcAdapter {
@FlaggedApi(Flags.FLAG_ENABLE_NFC_MAINLINE)
@SuppressLint("VisiblySynchronized")
public void setReaderMode(boolean enablePolling) {
- synchronized (NfcAdapter.class) {
+ synchronized (sLock) {
if (!sHasNfcFeature) {
throw new UnsupportedOperationException();
}
@@ -1708,6 +1793,80 @@ public final class NfcAdapter {
}
/**
+ * Set the NFC controller to enable specific poll/listen technologies,
+ * as specified in parameters, while this Activity is in the foreground.
+ *
+ * Use {@link #FLAG_READER_KEEP} to keep current polling technology.
+ * Use {@link #FLAG_LISTEN_KEEP} to keep current listenig technology.
+ * Use {@link #FLAG_READER_DISABLE} to disable polling.
+ * Use {@link #FLAG_LISTEN_DISABLE} to disable listening.
+ * Also refer to {@link #resetDiscoveryTechnology(Activity)} to restore these changes.
+ * </p>
+ * The pollTech, listenTech parameters can be one or several of below list.
+ * <pre>
+ * Poll Listen
+ * Passive A 0x01 (NFC_A) 0x01 (NFC_PASSIVE_A)
+ * Passive B 0x02 (NFC_B) 0x02 (NFC_PASSIVE_B)
+ * Passive F 0x04 (NFC_F) 0x04 (NFC_PASSIVE_F)
+ * ISO 15693 0x08 (NFC_V) -
+ * Kovio 0x10 (NFC_BARCODE) -
+ * </pre>
+ * <p>Example usage in an Activity that requires to disable poll,
+ * keep current listen technologies:
+ * <pre>
+ * protected void onResume() {
+ * mNfcAdapter = NfcAdapter.getDefaultAdapter(getApplicationContext());
+ * mNfcAdapter.setDiscoveryTechnology(this,
+ * NfcAdapter.FLAG_READER_DISABLE, NfcAdapter.FLAG_LISTEN_KEEP);
+ * }</pre></p>
+ * @param activity The Activity that requests NFC controller to enable specific technologies.
+ * @param pollTech Flags indicating poll technologies.
+ * @param listenTech Flags indicating listen technologies.
+ * @throws UnsupportedOperationException if FEATURE_NFC,
+ * FEATURE_NFC_HOST_CARD_EMULATION, FEATURE_NFC_HOST_CARD_EMULATION_NFCF are unavailable.
+ */
+
+ @FlaggedApi(Flags.FLAG_ENABLE_NFC_SET_DISCOVERY_TECH)
+ public void setDiscoveryTechnology(@NonNull Activity activity,
+ @PollTechnology int pollTech, @ListenTechnology int listenTech) {
+ if (listenTech == FLAG_LISTEN_DISABLE) {
+ synchronized (sLock) {
+ if (!sHasNfcFeature) {
+ throw new UnsupportedOperationException();
+ }
+ }
+ mNfcActivityManager.enableReaderMode(activity, null, pollTech, null);
+ return;
+ }
+ if (pollTech == FLAG_READER_DISABLE) {
+ synchronized (sLock) {
+ if (!sHasCeFeature) {
+ throw new UnsupportedOperationException();
+ }
+ }
+ } else {
+ synchronized (sLock) {
+ if (!sHasNfcFeature || !sHasCeFeature) {
+ throw new UnsupportedOperationException();
+ }
+ }
+ }
+ mNfcActivityManager.setDiscoveryTech(activity, pollTech, listenTech);
+ }
+
+ /**
+ * Restore the poll/listen technologies of NFC controller,
+ * which were changed by {@link #setDiscoveryTechnology(Activity , int , int)}
+ *
+ * @param activity The Activity that requests to changed technologies.
+ */
+
+ @FlaggedApi(Flags.FLAG_ENABLE_NFC_SET_DISCOVERY_TECH)
+ public void resetDiscoveryTechnology(@NonNull Activity activity) {
+ mNfcActivityManager.resetDiscoveryTech(activity);
+ }
+
+ /**
* Manually invoke Android Beam to share data.
*
* <p>The Android Beam animation is normally only shown when two NFC-capable
@@ -1737,7 +1896,7 @@ public final class NfcAdapter {
@java.lang.Deprecated
@UnsupportedAppUsage
public boolean invokeBeam(Activity activity) {
- synchronized (NfcAdapter.class) {
+ synchronized (sLock) {
if (!sHasNfcFeature) {
throw new UnsupportedOperationException();
}
@@ -1775,7 +1934,7 @@ public final class NfcAdapter {
@Deprecated
@UnsupportedAppUsage
public void enableForegroundNdefPush(Activity activity, NdefMessage message) {
- synchronized (NfcAdapter.class) {
+ synchronized (sLock) {
if (!sHasNfcFeature) {
throw new UnsupportedOperationException();
}
@@ -1805,7 +1964,7 @@ public final class NfcAdapter {
@Deprecated
@UnsupportedAppUsage
public void disableForegroundNdefPush(Activity activity) {
- synchronized (NfcAdapter.class) {
+ synchronized (sLock) {
if (!sHasNfcFeature) {
throw new UnsupportedOperationException();
}
@@ -2085,7 +2244,7 @@ public final class NfcAdapter {
@java.lang.Deprecated
@UnsupportedAppUsage
public boolean isNdefPushEnabled() {
- synchronized (NfcAdapter.class) {
+ synchronized (sLock) {
if (!sHasNfcFeature) {
throw new UnsupportedOperationException();
}
@@ -2199,7 +2358,7 @@ public final class NfcAdapter {
@RequiresPermission(android.Manifest.permission.WRITE_SECURE_SETTINGS)
public boolean addNfcUnlockHandler(final NfcUnlockHandler unlockHandler,
String[] tagTechnologies) {
- synchronized (NfcAdapter.class) {
+ synchronized (sLock) {
if (!sHasNfcFeature) {
throw new UnsupportedOperationException();
}
@@ -2248,7 +2407,7 @@ public final class NfcAdapter {
@SystemApi
@RequiresPermission(android.Manifest.permission.WRITE_SECURE_SETTINGS)
public boolean removeNfcUnlockHandler(NfcUnlockHandler unlockHandler) {
- synchronized (NfcAdapter.class) {
+ synchronized (sLock) {
if (!sHasNfcFeature) {
throw new UnsupportedOperationException();
}
diff --git a/core/java/android/nfc/cardemulation/CardEmulation.java b/core/java/android/nfc/cardemulation/CardEmulation.java
index 58b6179691e9..ad86d70db967 100644
--- a/core/java/android/nfc/cardemulation/CardEmulation.java
+++ b/core/java/android/nfc/cardemulation/CardEmulation.java
@@ -998,6 +998,87 @@ public final class CardEmulation {
}
}
+ /**
+ * Setting NFC controller routing table, which includes Protocol Route and Technology Route,
+ * while this Activity is in the foreground.
+ *
+ * The parameter set to null can be used to keep current values for that entry.
+ * <p>
+ * Example usage in an Activity that requires to set proto route to "ESE" and keep tech route:
+ * <pre>
+ * protected void onResume() {
+ * mNfcAdapter.overrideRoutingTable(this , "ESE" , null);
+ * }</pre>
+ * </p>
+ * Also activities must call this method when it goes to the background,
+ * with all parameters set to null.
+ * @param activity The Activity that requests NFC controller routing table to be changed.
+ * @param protocol ISO-DEP route destination, which can be "DH" or "UICC" or "ESE".
+ * @param technology Tech-A, Tech-B route destination, which can be "DH" or "UICC" or "ESE".
+ * @return true if operation is successful and false otherwise
+ *
+ * This is a high risk API and only included to support mainline effort
+ * @hide
+ */
+ public boolean overrideRoutingTable(Activity activity, String protocol, String technology) {
+ if (activity == null) {
+ throw new NullPointerException("activity or service or category is null");
+ }
+ if (!activity.isResumed()) {
+ throw new IllegalArgumentException("Activity must be resumed.");
+ }
+ try {
+ return sService.overrideRoutingTable(UserHandle.myUserId(), protocol, technology);
+ } catch (RemoteException e) {
+ // Try one more time
+ recoverService();
+ if (sService == null) {
+ Log.e(TAG, "Failed to recover CardEmulationService.");
+ return false;
+ }
+ try {
+ return sService.overrideRoutingTable(UserHandle.myUserId(), protocol, technology);
+ } catch (RemoteException ee) {
+ Log.e(TAG, "Failed to reach CardEmulationService.");
+ return false;
+ }
+ }
+ }
+
+ /**
+ * Restore the NFC controller routing table,
+ * which was changed by {@link #overrideRoutingTable(Activity, String, String)}
+ *
+ * @param activity The Activity that requested NFC controller routing table to be changed.
+ * @return true if operation is successful and false otherwise
+ *
+ * @hide
+ */
+ public boolean recoverRoutingTable(Activity activity) {
+ if (activity == null) {
+ throw new NullPointerException("activity is null");
+ }
+ if (!activity.isResumed()) {
+ throw new IllegalArgumentException("Activity must be resumed.");
+ }
+ try {
+ return sService.recoverRoutingTable(UserHandle.myUserId());
+ } catch (RemoteException e) {
+ // Try one more time
+ recoverService();
+ if (sService == null) {
+ Log.e(TAG, "Failed to recover CardEmulationService.");
+ return false;
+ }
+ try {
+ return sService.recoverRoutingTable(UserHandle.myUserId());
+ } catch (RemoteException ee) {
+ Log.e(TAG, "Failed to reach CardEmulationService.");
+ return false;
+ }
+ }
+ }
+
void recoverService() {
NfcAdapter adapter = NfcAdapter.getDefaultAdapter(mContext);
sService = adapter.getCardEmulationService();
diff --git a/core/java/android/nfc/flags.aconfig b/core/java/android/nfc/flags.aconfig
index ce4f77725ef1..01a45708fddf 100644
--- a/core/java/android/nfc/flags.aconfig
+++ b/core/java/android/nfc/flags.aconfig
@@ -62,3 +62,10 @@ flag {
description: "Flag for NFC charging changes"
bug: "292143899"
}
+
+flag {
+ name: "enable_nfc_set_discovery_tech"
+ namespace: "nfc"
+ description: "Flag for NFC set discovery tech API"
+ bug: "300351519"
+}