summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--core/api/system-current.txt3
-rw-r--r--nfc/api/current.txt2
-rw-r--r--nfc/java/android/nfc/INfcCardEmulation.aidl2
-rw-r--r--nfc/java/android/nfc/cardemulation/ApduServiceInfo.java26
-rw-r--r--nfc/java/android/nfc/cardemulation/CardEmulation.java39
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);
}
/**