From 8802f871ecee4d59af94059714b7ee7de4691360 Mon Sep 17 00:00:00 2001 From: Alisher Alikhodjaev <alisher@google.com> Date: Tue, 28 Nov 2023 14:52:44 -0800 Subject: [PATCH] Implementation of Dedicated card mode APIs changes (Discovery tech and Change Routing) Bug: 300351519 Bug: 319156577 Test: n/a Merged-In: If664910d00fc673c0329e0cd4489174260eb4f1e Merged-In: I3035f8b4fac331d827afa8e7bda6109d91ee510a Change-Id: If664910d00fc673c0329e0cd4489174260eb4f1e --- core/api/current.txt | 9 + core/java/android/nfc/INfcAdapter.aidl | 1 + core/java/android/nfc/INfcCardEmulation.aidl | 3 + core/java/android/nfc/NfcActivityManager.java | 74 +++++++ core/java/android/nfc/NfcAdapter.java | 195 ++++++++++++++++-- .../nfc/cardemulation/CardEmulation.java | 81 ++++++++ core/java/android/nfc/flags.aconfig | 7 + 7 files changed, 352 insertions(+), 18 deletions(-) diff --git a/core/api/current.txt b/core/api/current.txt index c600df19a379..48f58c09871d 100644 --- a/core/api/current.txt +++ b/core/api/current.txt @@ -29120,6 +29120,8 @@ package android.nfc { method @FlaggedApi("android.nfc.enable_nfc_reader_option") public boolean isReaderOptionSupported(); method public boolean isSecureNfcEnabled(); method public boolean isSecureNfcSupported(); + 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"; @@ -29135,6 +29137,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 f6beec179d57..85879ac56194 100644 --- a/core/java/android/nfc/INfcAdapter.aidl +++ b/core/java/android/nfc/INfcAdapter.aidl @@ -86,4 +86,5 @@ interface INfcAdapter boolean enableReaderOption(boolean enable); boolean isObserveModeSupported(); boolean setObserveMode(boolean enabled); + 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 f407fb73534f..979855e5e25c 100644 --- a/core/java/android/nfc/NfcAdapter.java +++ b/core/java/android/nfc/NfcAdapter.java @@ -332,6 +332,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> @@ -358,6 +371,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 @@ -436,11 +519,13 @@ 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 Object sLock = new Object(); + // Final after first constructor, except for // attemptDeadServiceRecovery() when NFC crashes - we accept a best effort // recovery @@ -1230,7 +1315,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(); } @@ -1300,7 +1385,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(); } @@ -1385,7 +1470,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(); } @@ -1399,7 +1484,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(); } @@ -1478,7 +1563,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(); } @@ -1529,7 +1614,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(); } @@ -1572,7 +1657,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(); } @@ -1607,7 +1692,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(); } @@ -1643,7 +1728,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(); } @@ -1660,7 +1745,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(); } @@ -1688,7 +1773,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(); } @@ -1702,6 +1787,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 pollTechnology, listenTechnology 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 pollTechnology Flags indicating poll technologies. + * @param listenTechnology 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 pollTechnology, @ListenTechnology int listenTechnology) { + if (listenTechnology == FLAG_LISTEN_DISABLE) { + synchronized (sLock) { + if (!sHasNfcFeature) { + throw new UnsupportedOperationException(); + } + } + mNfcActivityManager.enableReaderMode(activity, null, pollTechnology, null); + return; + } + if (pollTechnology == FLAG_READER_DISABLE) { + synchronized (sLock) { + if (!sHasCeFeature) { + throw new UnsupportedOperationException(); + } + } + } else { + synchronized (sLock) { + if (!sHasNfcFeature || !sHasCeFeature) { + throw new UnsupportedOperationException(); + } + } + } + mNfcActivityManager.setDiscoveryTech(activity, pollTechnology, listenTechnology); + } + + /** + * 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. * @@ -1732,7 +1891,7 @@ public final class NfcAdapter { @java.lang.Deprecated @UnsupportedAppUsage public boolean invokeBeam(Activity activity) { - synchronized (NfcAdapter.class) { + synchronized (sLock) { if (!sHasNfcFeature) { throw new UnsupportedOperationException(); } @@ -1770,7 +1929,7 @@ public final class NfcAdapter { @Deprecated @UnsupportedAppUsage public void enableForegroundNdefPush(Activity activity, NdefMessage message) { - synchronized (NfcAdapter.class) { + synchronized (sLock) { if (!sHasNfcFeature) { throw new UnsupportedOperationException(); } @@ -1800,7 +1959,7 @@ public final class NfcAdapter { @Deprecated @UnsupportedAppUsage public void disableForegroundNdefPush(Activity activity) { - synchronized (NfcAdapter.class) { + synchronized (sLock) { if (!sHasNfcFeature) { throw new UnsupportedOperationException(); } @@ -2080,7 +2239,7 @@ public final class NfcAdapter { @java.lang.Deprecated @UnsupportedAppUsage public boolean isNdefPushEnabled() { - synchronized (NfcAdapter.class) { + synchronized (sLock) { if (!sHasNfcFeature) { throw new UnsupportedOperationException(); } @@ -2194,7 +2353,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(); } @@ -2243,7 +2402,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 0d073cc6c819..11be905c41ca 100644 --- a/core/java/android/nfc/flags.aconfig +++ b/core/java/android/nfc/flags.aconfig @@ -55,3 +55,10 @@ flag { description: "Enable sending broadcasts to Wallet role holder when a tag enters/leaves the field." bug: "306203494" } + +flag { + name: "enable_nfc_set_discovery_tech" + namespace: "nfc" + description: "Flag for NFC set discovery tech API" + bug: "300351519" +} -- GitLab