diff options
| -rw-r--r-- | core/api/system-current.txt | 3 | ||||
| -rw-r--r-- | nfc/api/current.txt | 2 | ||||
| -rw-r--r-- | nfc/java/android/nfc/INfcCardEmulation.aidl | 2 | ||||
| -rw-r--r-- | nfc/java/android/nfc/cardemulation/ApduServiceInfo.java | 26 | ||||
| -rw-r--r-- | nfc/java/android/nfc/cardemulation/CardEmulation.java | 39 |
5 files changed, 31 insertions, 41 deletions
diff --git a/core/api/system-current.txt b/core/api/system-current.txt index 062bdaad9f7f..d9b5d56544d6 100644 --- a/core/api/system-current.txt +++ b/core/api/system-current.txt @@ -10421,8 +10421,7 @@ package android.nfc.cardemulation { @FlaggedApi("android.nfc.enable_nfc_mainline") public final class ApduServiceInfo implements android.os.Parcelable { ctor @FlaggedApi("android.nfc.enable_nfc_mainline") public ApduServiceInfo(@NonNull android.content.pm.PackageManager, @NonNull android.content.pm.ResolveInfo, boolean) throws java.io.IOException, org.xmlpull.v1.XmlPullParserException; - method @FlaggedApi("android.nfc.nfc_read_polling_loop") public void addPollingLoopFilter(@NonNull String); - method @FlaggedApi("android.nfc.nfc_read_polling_loop") public void addPollingLoopFilterToAutoTransact(@NonNull String); + method @FlaggedApi("android.nfc.nfc_read_polling_loop") public void addPollingLoopFilter(@NonNull String, boolean); method @FlaggedApi("android.nfc.nfc_observe_mode") public boolean defaultToObserveMode(); method @FlaggedApi("android.nfc.enable_nfc_mainline") public int describeContents(); method @FlaggedApi("android.nfc.enable_nfc_mainline") public void dump(@NonNull android.os.ParcelFileDescriptor, @NonNull java.io.PrintWriter, @NonNull String[]); diff --git a/nfc/api/current.txt b/nfc/api/current.txt index 7b53ca6ea7e9..0fb7c95e3680 100644 --- a/nfc/api/current.txt +++ b/nfc/api/current.txt @@ -204,7 +204,7 @@ package android.nfc.cardemulation { method public boolean isDefaultServiceForAid(android.content.ComponentName, String); method public boolean isDefaultServiceForCategory(android.content.ComponentName, String); method public boolean registerAidsForService(android.content.ComponentName, String, java.util.List<java.lang.String>); - method @FlaggedApi("android.nfc.nfc_read_polling_loop") public boolean registerPollingLoopFilterForService(@NonNull android.content.ComponentName, @NonNull String); + method @FlaggedApi("android.nfc.nfc_read_polling_loop") public boolean registerPollingLoopFilterForService(@NonNull android.content.ComponentName, @NonNull String, boolean); method public boolean removeAidsForService(android.content.ComponentName, String); method @FlaggedApi("android.nfc.nfc_observe_mode") public boolean setDefaultToObserveModeForService(@NonNull android.content.ComponentName, boolean); method @NonNull @RequiresPermission(android.Manifest.permission.NFC) public boolean setOffHostForService(@NonNull android.content.ComponentName, @NonNull String); diff --git a/nfc/java/android/nfc/INfcCardEmulation.aidl b/nfc/java/android/nfc/INfcCardEmulation.aidl index 65d0625f251e..64f7fa44c12f 100644 --- a/nfc/java/android/nfc/INfcCardEmulation.aidl +++ b/nfc/java/android/nfc/INfcCardEmulation.aidl @@ -32,7 +32,7 @@ interface INfcCardEmulation boolean setDefaultForNextTap(int userHandle, in ComponentName service); boolean setDefaultToObserveModeForService(int userId, in android.content.ComponentName service, boolean enable); boolean registerAidGroupForService(int userHandle, in ComponentName service, in AidGroup aidGroup); - boolean registerPollingLoopFilterForService(int userHandle, in ComponentName service, in String pollingLoopFilter); + boolean registerPollingLoopFilterForService(int userHandle, in ComponentName service, in String pollingLoopFilter, boolean autoTransact); boolean setOffHostForService(int userHandle, in ComponentName service, in String offHostSecureElement); boolean unsetOffHostForService(int userHandle, in ComponentName service); AidGroup getAidGroupForService(int userHandle, in ComponentName service, String category); diff --git a/nfc/java/android/nfc/cardemulation/ApduServiceInfo.java b/nfc/java/android/nfc/cardemulation/ApduServiceInfo.java index c81b95b7c81b..e62e37bd4ca0 100644 --- a/nfc/java/android/nfc/cardemulation/ApduServiceInfo.java +++ b/nfc/java/android/nfc/cardemulation/ApduServiceInfo.java @@ -681,34 +681,18 @@ public final class ApduServiceInfo implements Parcelable { /** * Add a Polling Loop Filter. Custom NFC polling frames that match this filter will be - * delivered to {@link HostApduService#processPollingFrames(List)}. Adding a key with this or - * {@link ApduServiceInfo#addPollingLoopFilterToAutoTransact(String)} multiple times will - * cause the value to be overwritten each time. + * delivered to {@link HostApduService#processPollingFrames(List)}. Adding a key with this + * multiple times will cause the value to be overwritten each time. * @param pollingLoopFilter the polling loop filter to add, must be a valide hexadecimal string */ @FlaggedApi(Flags.FLAG_NFC_READ_POLLING_LOOP) - public void addPollingLoopFilter(@NonNull String pollingLoopFilter) { - mAutoTransact.put(pollingLoopFilter.toUpperCase(Locale.ROOT), false); + public void addPollingLoopFilter(@NonNull String pollingLoopFilter, + boolean autoTransact) { + mAutoTransact.put(pollingLoopFilter, autoTransact); } /** - * Add a Polling Loop Filter. Custom NFC polling frames that match this filter will cause the - * device to exit observe mode, just as if - * {@link android.nfc.NfcAdapter#setObserveModeEnabled(boolean)} had been called with true, - * allowing transactions to proceed. The matching frame will also be delivered to - * {@link HostApduService#processPollingFrames(List)}. Adding a key with this or - * {@link ApduServiceInfo#addPollingLoopFilter(String)} multiple times will - * cause the value to be overwritten each time. - * - * @param pollingLoopFilter the polling loop filter to add, must be a valide hexadecimal string - */ - @FlaggedApi(Flags.FLAG_NFC_READ_POLLING_LOOP) - public void addPollingLoopFilterToAutoTransact(@NonNull String pollingLoopFilter) { - mAutoTransact.put(pollingLoopFilter.toUpperCase(Locale.ROOT), true); - } - - /** * Remove a Polling Loop Filter. Custom NFC polling frames that match this filter will no * longer be delivered to {@link HostApduService#processPollingFrames(List)}. * @param pollingLoopFilter this polling loop filter to add. diff --git a/nfc/java/android/nfc/cardemulation/CardEmulation.java b/nfc/java/android/nfc/cardemulation/CardEmulation.java index e681a8568300..47ddd9de224f 100644 --- a/nfc/java/android/nfc/cardemulation/CardEmulation.java +++ b/nfc/java/android/nfc/cardemulation/CardEmulation.java @@ -42,6 +42,7 @@ import android.provider.Settings.SettingNotFoundException; import android.util.Log; import java.util.HashMap; +import java.util.HexFormat; import java.util.List; import java.util.regex.Pattern; @@ -59,7 +60,6 @@ import java.util.regex.Pattern; */ public final class CardEmulation { private static final Pattern AID_PATTERN = Pattern.compile("[0-9A-Fa-f]{10,32}\\*?\\#?"); - private static final Pattern PLF_PATTERN = Pattern.compile("[0-9A-Fa-f]{1,32}"); static final String TAG = "CardEmulation"; @@ -360,21 +360,28 @@ public final class CardEmulation { } /** - * Register a polling loop filter (PLF) for a HostApduService. The PLF can be sequence of an - * even number of hexadecimal numbers (0-9, A-F or a-f). When non-standard polling loop frame - * matches this sequence exactly, it may be delivered to - * {@link HostApduService#processPollingFrames(List)} if this service is currently - * preferred or there are no other services registered for this filter. + * Register a polling loop filter (PLF) for a HostApduService and indicate whether it should + * auto-transact or not. The PLF can be sequence of an + * even number of at least 2 hexadecimal numbers (0-9, A-F or a-f), representing a series of + * bytes. When non-standard polling loop frame matches this sequence exactly, it may be + * delivered to {@link HostApduService#processPollingFrames(List)}. If auto-transact is set to + * true, then observe mode will also be disabled. if this service is currently preferred or + * there are no other services registered for this filter. * @param service The HostApduService to register the filter for * @param pollingLoopFilter The filter to register + * @param autoTransact true to have the NFC stack automatically disable observe mode and allow + * transactions to proceed when this filter matches, false otherwise * @return true if the filter was registered, false otherwise + * @throws IllegalArgumentException if the passed in string doesn't parse to at least one byte */ @FlaggedApi(Flags.FLAG_NFC_READ_POLLING_LOOP) public boolean registerPollingLoopFilterForService(@NonNull ComponentName service, - @NonNull String pollingLoopFilter) { + @NonNull String pollingLoopFilter, boolean autoTransact) { + pollingLoopFilter = validatePollingLoopFilter(pollingLoopFilter); + try { return sService.registerPollingLoopFilterForService(mContext.getUser().getIdentifier(), - service, pollingLoopFilter); + service, pollingLoopFilter, autoTransact); } catch (RemoteException e) { // Try one more time recoverService(); @@ -384,7 +391,8 @@ public final class CardEmulation { } try { return sService.registerPollingLoopFilterForService( - mContext.getUser().getIdentifier(), service, pollingLoopFilter); + mContext.getUser().getIdentifier(), service, + pollingLoopFilter, autoTransact); } catch (RemoteException ee) { Log.e(TAG, "Failed to reach CardEmulationService."); return false; @@ -979,15 +987,14 @@ public final class CardEmulation { * @hide */ @FlaggedApi(Flags.FLAG_NFC_READ_POLLING_LOOP) - public static boolean isValidPollingLoopFilter(@NonNull String pollingLoopFilter) { + public static @NonNull String validatePollingLoopFilter(@NonNull String pollingLoopFilter) { // Verify hex characters - if (!PLF_PATTERN.matcher(pollingLoopFilter).matches()) { - Log.e(TAG, "Polling Loop Filter " + pollingLoopFilter - + " is not a valid Polling Loop Filter."); - return false; + byte[] plfBytes = HexFormat.of().parseHex(pollingLoopFilter); + if (plfBytes.length == 0) { + throw new IllegalArgumentException( + "Polling loop filter must contain at least one byte."); } - - return true; + return HexFormat.of().withUpperCase().formatHex(plfBytes); } /** |