Loading core/api/system-current.txt +3 −0 Original line number Diff line number Diff line Loading @@ -10438,6 +10438,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, boolean); method @FlaggedApi("android.nfc.nfc_read_polling_loop") public void addPollingLoopPatternFilter(@NonNull String, boolean); 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[]); method @FlaggedApi("android.nfc.enable_nfc_mainline") public void dumpDebug(@NonNull android.util.proto.ProtoOutputStream); Loading @@ -10449,6 +10450,7 @@ package android.nfc.cardemulation { method @FlaggedApi("android.nfc.enable_nfc_mainline") @NonNull public android.nfc.cardemulation.AidGroup getDynamicAidGroupForCategory(@NonNull String); method @FlaggedApi("android.nfc.enable_nfc_mainline") @Nullable public String getOffHostSecureElement(); method @FlaggedApi("android.nfc.nfc_read_polling_loop") @NonNull public java.util.List<java.lang.String> getPollingLoopFilters(); method @FlaggedApi("android.nfc.nfc_read_polling_loop") @NonNull public java.util.List<java.util.regex.Pattern> getPollingLoopPatternFilters(); method @FlaggedApi("android.nfc.enable_nfc_mainline") @NonNull public java.util.List<java.lang.String> getPrefixAids(); method @FlaggedApi("android.nfc.enable_nfc_mainline") @NonNull public String getSettingsActivityName(); method @FlaggedApi("android.nfc.nfc_read_polling_loop") public boolean getShouldAutoTransact(@NonNull String); Loading @@ -10463,6 +10465,7 @@ package android.nfc.cardemulation { method @FlaggedApi("android.nfc.enable_nfc_mainline") @NonNull public CharSequence loadLabel(@NonNull android.content.pm.PackageManager); method @FlaggedApi("android.nfc.enable_nfc_mainline") @NonNull public boolean removeDynamicAidGroupForCategory(@NonNull String); method @FlaggedApi("android.nfc.nfc_read_polling_loop") public void removePollingLoopFilter(@NonNull String); method @FlaggedApi("android.nfc.nfc_read_polling_loop") public void removePollingLoopPatternFilter(@NonNull String); method @FlaggedApi("android.nfc.enable_nfc_mainline") public boolean requiresScreenOn(); method @FlaggedApi("android.nfc.enable_nfc_mainline") public boolean requiresUnlock(); method @FlaggedApi("android.nfc.enable_nfc_mainline") public void resetOffHostSecureElement(); core/res/res/values/attrs.xml +15 −0 Original line number Diff line number Diff line Loading @@ -4484,6 +4484,21 @@ <attr name="autoTransact" format="boolean"/> </declare-styleable> <!-- Specify one or more <code>polling-loop-pattern-filter</code> elements inside a <code>host-apdu-service</code> to indicate polling loop frames that your service can handle. --> <!-- @FlaggedApi("android.nfc.Flags.FLAG_NFC_READ_POLLING_LOOP") --> <declare-styleable name="PollingLoopPatternFilter"> <!-- The patter to match polling loop frames to, must to be compatible with {@link java.util.regex.Pattern#compile(String)} and only contain hexadecimal numbers and `.`, `?` and `*` operators. This attribute is mandatory. --> <attr name="name" /> <!-- Whether or not the system should automatically start a transaction when this polling loop filter matches. If not set, default value is false. --> <!-- @FlaggedApi("android.nfc.Flags.FLAG_NFC_READ_POLLING_LOOP") --> <attr name="autoTransact" format="boolean"/> </declare-styleable> <!-- Use <code>host-nfcf-service</code> as the root tag of the XML resource that describes an {@link android.nfc.cardemulation.HostNfcFService} service, which is referenced from its {@link android.nfc.cardemulation.HostNfcFService#SERVICE_META_DATA} Loading nfc/api/current.txt +3 −0 Original line number Diff line number Diff line Loading @@ -205,7 +205,10 @@ package android.nfc.cardemulation { 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, boolean); method @FlaggedApi("android.nfc.nfc_read_polling_loop") public boolean registerPollingLoopPatternFilterForService(@NonNull android.content.ComponentName, @NonNull String, boolean); method public boolean removeAidsForService(android.content.ComponentName, String); method @FlaggedApi("android.nfc.nfc_read_polling_loop") public boolean removePollingLoopFilterForService(@NonNull android.content.ComponentName, @NonNull String); method @FlaggedApi("android.nfc.nfc_read_polling_loop") public boolean removePollingLoopPatternFilterForService(@NonNull android.content.ComponentName, @NonNull String); method @NonNull @RequiresPermission(android.Manifest.permission.NFC) public boolean setOffHostForService(@NonNull android.content.ComponentName, @NonNull String); method public boolean setPreferredService(android.app.Activity, android.content.ComponentName); method @FlaggedApi("android.nfc.nfc_observe_mode") public boolean setShouldDefaultToObserveModeForService(@NonNull android.content.ComponentName, boolean); Loading nfc/java/android/nfc/INfcCardEmulation.aidl +3 −0 Original line number Diff line number Diff line Loading @@ -33,10 +33,13 @@ interface INfcCardEmulation boolean setShouldDefaultToObserveModeForService(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 autoTransact); boolean registerPollingLoopPatternFilterForService(int userHandle, in ComponentName service, in String pollingLoopPatternFilter, 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); boolean removeAidGroupForService(int userHandle, in ComponentName service, String category); boolean removePollingLoopFilterForService(int userHandle, in ComponentName service, in String pollingLoopFilter); boolean removePollingLoopPatternFilterForService(int userHandle, in ComponentName service, in String pollingLoopPatternFilter); List<ApduServiceInfo> getServices(int userHandle, in String category); boolean setPreferredService(in ComponentName service); boolean unsetPreferredService(); Loading nfc/java/android/nfc/cardemulation/ApduServiceInfo.java +76 −5 Original line number Diff line number Diff line Loading @@ -108,6 +108,8 @@ public final class ApduServiceInfo implements Parcelable { private final Map<String, Boolean> mAutoTransact; private final Map<Pattern, Boolean> mAutoTransactPatterns; /** * Whether this service should only be started when the device is unlocked. */ Loading Loading @@ -179,7 +181,7 @@ public final class ApduServiceInfo implements Parcelable { this(info, onHost, description, staticAidGroups, dynamicAidGroups, requiresUnlock, requiresScreenOn, bannerResource, uid, settingsActivityName, offHost, staticOffHost, isEnabled, new HashMap<String, Boolean>()); new HashMap<String, Boolean>(), new HashMap<Pattern, Boolean>()); } /** Loading @@ -189,12 +191,13 @@ public final class ApduServiceInfo implements Parcelable { List<AidGroup> staticAidGroups, List<AidGroup> dynamicAidGroups, boolean requiresUnlock, boolean requiresScreenOn, int bannerResource, int uid, String settingsActivityName, String offHost, String staticOffHost, boolean isEnabled, HashMap<String, Boolean> autoTransact) { Map<String, Boolean> autoTransact, Map<Pattern, Boolean> autoTransactPatterns) { this.mService = info; this.mDescription = description; this.mStaticAidGroups = new HashMap<String, AidGroup>(); this.mDynamicAidGroups = new HashMap<String, AidGroup>(); this.mAutoTransact = autoTransact; this.mAutoTransactPatterns = autoTransactPatterns; this.mOffHostName = offHost; this.mStaticOffHostName = staticOffHost; this.mOnHost = onHost; Loading Loading @@ -314,6 +317,7 @@ public final class ApduServiceInfo implements Parcelable { mStaticAidGroups = new HashMap<String, AidGroup>(); mDynamicAidGroups = new HashMap<String, AidGroup>(); mAutoTransact = new HashMap<String, Boolean>(); mAutoTransactPatterns = new HashMap<Pattern, Boolean>(); mOnHost = onHost; final int depth = parser.getDepth(); Loading Loading @@ -408,6 +412,18 @@ public final class ApduServiceInfo implements Parcelable { false); mAutoTransact.put(plf, autoTransact); a.recycle(); } else if (eventType == XmlPullParser.START_TAG && "polling-loop-pattern-filter".equals(tagName) && currentGroup == null) { final TypedArray a = res.obtainAttributes(attrs, com.android.internal.R.styleable.PollingLoopPatternFilter); String plf = a.getString( com.android.internal.R.styleable.PollingLoopPatternFilter_name) .toUpperCase(Locale.ROOT); boolean autoTransact = a.getBoolean( com.android.internal.R.styleable.PollingLoopFilter_autoTransact, false); mAutoTransactPatterns.put(Pattern.compile(plf), autoTransact); a.recycle(); } } } catch (NameNotFoundException e) { Loading Loading @@ -481,7 +497,30 @@ public final class ApduServiceInfo implements Parcelable { */ @FlaggedApi(Flags.FLAG_NFC_READ_POLLING_LOOP) public boolean getShouldAutoTransact(@NonNull String plf) { return mAutoTransact.getOrDefault(plf.toUpperCase(Locale.ROOT), false); if (mAutoTransact.getOrDefault(plf.toUpperCase(Locale.ROOT), false)) { return true; } List<Pattern> patternMatches = mAutoTransactPatterns.keySet().stream() .filter(p -> p.matcher(plf).matches()).toList(); if (patternMatches == null || patternMatches.size() == 0) { return false; } for (Pattern patternMatch : patternMatches) { if (mAutoTransactPatterns.get(patternMatch)) { return true; } } return false; } /** * Returns the current polling loop pattern filters for this service. * @return List of polling loop pattern filters. */ @FlaggedApi(Flags.FLAG_NFC_READ_POLLING_LOOP) @NonNull public List<Pattern> getPollingLoopPatternFilters() { return new ArrayList<>(mAutoTransactPatterns.keySet()); } /** Loading Loading @@ -683,7 +722,7 @@ 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 * 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 * @param pollingLoopFilter the polling loop filter to add, must be a valid hexadecimal string */ @FlaggedApi(Flags.FLAG_NFC_READ_POLLING_LOOP) public void addPollingLoopFilter(@NonNull String pollingLoopFilter, Loading @@ -702,6 +741,31 @@ public final class ApduServiceInfo implements Parcelable { mAutoTransact.remove(pollingLoopFilter.toUpperCase(Locale.ROOT)); } /** * Add a Polling Loop Pattern Filter. Custom NFC polling frames that match this filter will be * delivered to {@link HostApduService#processPollingFrames(List)}. Adding a key with this * multiple times will cause the value to be overwritten each time. * @param pollingLoopPatternFilter the polling loop pattern filter to add, must be a valid * regex to match a hexadecimal string */ @FlaggedApi(Flags.FLAG_NFC_READ_POLLING_LOOP) public void addPollingLoopPatternFilter(@NonNull String pollingLoopPatternFilter, boolean autoTransact) { mAutoTransactPatterns.put(Pattern.compile(pollingLoopPatternFilter), autoTransact); } /** * Remove a Polling Loop Pattern Filter. Custom NFC polling frames that match this filter will * no longer be delivered to {@link HostApduService#processPollingFrames(List)}. * @param pollingLoopPatternFilter this polling loop filter to add. */ @FlaggedApi(Flags.FLAG_NFC_READ_POLLING_LOOP) public void removePollingLoopPatternFilter(@NonNull String pollingLoopPatternFilter) { mAutoTransactPatterns.remove( Pattern.compile(pollingLoopPatternFilter.toUpperCase(Locale.ROOT))); } /** * Sets the off host Secure Element. * @param offHost Secure Element to set. Only accept strings with prefix SIM or prefix eSE. Loading Loading @@ -856,6 +920,8 @@ public final class ApduServiceInfo implements Parcelable { dest.writeInt(mCategoryOtherServiceEnabled ? 1 : 0); dest.writeInt(mAutoTransact.size()); dest.writeMap(mAutoTransact); dest.writeInt(mAutoTransactPatterns.size()); dest.writeMap(mAutoTransactPatterns); }; @FlaggedApi(Flags.FLAG_ENABLE_NFC_MAINLINE) Loading Loading @@ -889,10 +955,15 @@ public final class ApduServiceInfo implements Parcelable { new HashMap<String, Boolean>(autoTransactSize); source.readMap(autoTransact, getClass().getClassLoader(), String.class, Boolean.class); int autoTransactPatternSize = source.readInt(); HashMap<Pattern, Boolean> autoTransactPatterns = new HashMap<Pattern, Boolean>(autoTransactSize); source.readMap(autoTransactPatterns, getClass().getClassLoader(), Pattern.class, Boolean.class); return new ApduServiceInfo(info, onHost, description, staticAidGroups, dynamicAidGroups, requiresUnlock, requiresScreenOn, bannerResource, uid, settingsActivityName, offHostName, staticOffHostName, isEnabled, autoTransact); isEnabled, autoTransact, autoTransactPatterns); } @Override Loading Loading
core/api/system-current.txt +3 −0 Original line number Diff line number Diff line Loading @@ -10438,6 +10438,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, boolean); method @FlaggedApi("android.nfc.nfc_read_polling_loop") public void addPollingLoopPatternFilter(@NonNull String, boolean); 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[]); method @FlaggedApi("android.nfc.enable_nfc_mainline") public void dumpDebug(@NonNull android.util.proto.ProtoOutputStream); Loading @@ -10449,6 +10450,7 @@ package android.nfc.cardemulation { method @FlaggedApi("android.nfc.enable_nfc_mainline") @NonNull public android.nfc.cardemulation.AidGroup getDynamicAidGroupForCategory(@NonNull String); method @FlaggedApi("android.nfc.enable_nfc_mainline") @Nullable public String getOffHostSecureElement(); method @FlaggedApi("android.nfc.nfc_read_polling_loop") @NonNull public java.util.List<java.lang.String> getPollingLoopFilters(); method @FlaggedApi("android.nfc.nfc_read_polling_loop") @NonNull public java.util.List<java.util.regex.Pattern> getPollingLoopPatternFilters(); method @FlaggedApi("android.nfc.enable_nfc_mainline") @NonNull public java.util.List<java.lang.String> getPrefixAids(); method @FlaggedApi("android.nfc.enable_nfc_mainline") @NonNull public String getSettingsActivityName(); method @FlaggedApi("android.nfc.nfc_read_polling_loop") public boolean getShouldAutoTransact(@NonNull String); Loading @@ -10463,6 +10465,7 @@ package android.nfc.cardemulation { method @FlaggedApi("android.nfc.enable_nfc_mainline") @NonNull public CharSequence loadLabel(@NonNull android.content.pm.PackageManager); method @FlaggedApi("android.nfc.enable_nfc_mainline") @NonNull public boolean removeDynamicAidGroupForCategory(@NonNull String); method @FlaggedApi("android.nfc.nfc_read_polling_loop") public void removePollingLoopFilter(@NonNull String); method @FlaggedApi("android.nfc.nfc_read_polling_loop") public void removePollingLoopPatternFilter(@NonNull String); method @FlaggedApi("android.nfc.enable_nfc_mainline") public boolean requiresScreenOn(); method @FlaggedApi("android.nfc.enable_nfc_mainline") public boolean requiresUnlock(); method @FlaggedApi("android.nfc.enable_nfc_mainline") public void resetOffHostSecureElement();
core/res/res/values/attrs.xml +15 −0 Original line number Diff line number Diff line Loading @@ -4484,6 +4484,21 @@ <attr name="autoTransact" format="boolean"/> </declare-styleable> <!-- Specify one or more <code>polling-loop-pattern-filter</code> elements inside a <code>host-apdu-service</code> to indicate polling loop frames that your service can handle. --> <!-- @FlaggedApi("android.nfc.Flags.FLAG_NFC_READ_POLLING_LOOP") --> <declare-styleable name="PollingLoopPatternFilter"> <!-- The patter to match polling loop frames to, must to be compatible with {@link java.util.regex.Pattern#compile(String)} and only contain hexadecimal numbers and `.`, `?` and `*` operators. This attribute is mandatory. --> <attr name="name" /> <!-- Whether or not the system should automatically start a transaction when this polling loop filter matches. If not set, default value is false. --> <!-- @FlaggedApi("android.nfc.Flags.FLAG_NFC_READ_POLLING_LOOP") --> <attr name="autoTransact" format="boolean"/> </declare-styleable> <!-- Use <code>host-nfcf-service</code> as the root tag of the XML resource that describes an {@link android.nfc.cardemulation.HostNfcFService} service, which is referenced from its {@link android.nfc.cardemulation.HostNfcFService#SERVICE_META_DATA} Loading
nfc/api/current.txt +3 −0 Original line number Diff line number Diff line Loading @@ -205,7 +205,10 @@ package android.nfc.cardemulation { 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, boolean); method @FlaggedApi("android.nfc.nfc_read_polling_loop") public boolean registerPollingLoopPatternFilterForService(@NonNull android.content.ComponentName, @NonNull String, boolean); method public boolean removeAidsForService(android.content.ComponentName, String); method @FlaggedApi("android.nfc.nfc_read_polling_loop") public boolean removePollingLoopFilterForService(@NonNull android.content.ComponentName, @NonNull String); method @FlaggedApi("android.nfc.nfc_read_polling_loop") public boolean removePollingLoopPatternFilterForService(@NonNull android.content.ComponentName, @NonNull String); method @NonNull @RequiresPermission(android.Manifest.permission.NFC) public boolean setOffHostForService(@NonNull android.content.ComponentName, @NonNull String); method public boolean setPreferredService(android.app.Activity, android.content.ComponentName); method @FlaggedApi("android.nfc.nfc_observe_mode") public boolean setShouldDefaultToObserveModeForService(@NonNull android.content.ComponentName, boolean); Loading
nfc/java/android/nfc/INfcCardEmulation.aidl +3 −0 Original line number Diff line number Diff line Loading @@ -33,10 +33,13 @@ interface INfcCardEmulation boolean setShouldDefaultToObserveModeForService(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 autoTransact); boolean registerPollingLoopPatternFilterForService(int userHandle, in ComponentName service, in String pollingLoopPatternFilter, 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); boolean removeAidGroupForService(int userHandle, in ComponentName service, String category); boolean removePollingLoopFilterForService(int userHandle, in ComponentName service, in String pollingLoopFilter); boolean removePollingLoopPatternFilterForService(int userHandle, in ComponentName service, in String pollingLoopPatternFilter); List<ApduServiceInfo> getServices(int userHandle, in String category); boolean setPreferredService(in ComponentName service); boolean unsetPreferredService(); Loading
nfc/java/android/nfc/cardemulation/ApduServiceInfo.java +76 −5 Original line number Diff line number Diff line Loading @@ -108,6 +108,8 @@ public final class ApduServiceInfo implements Parcelable { private final Map<String, Boolean> mAutoTransact; private final Map<Pattern, Boolean> mAutoTransactPatterns; /** * Whether this service should only be started when the device is unlocked. */ Loading Loading @@ -179,7 +181,7 @@ public final class ApduServiceInfo implements Parcelable { this(info, onHost, description, staticAidGroups, dynamicAidGroups, requiresUnlock, requiresScreenOn, bannerResource, uid, settingsActivityName, offHost, staticOffHost, isEnabled, new HashMap<String, Boolean>()); new HashMap<String, Boolean>(), new HashMap<Pattern, Boolean>()); } /** Loading @@ -189,12 +191,13 @@ public final class ApduServiceInfo implements Parcelable { List<AidGroup> staticAidGroups, List<AidGroup> dynamicAidGroups, boolean requiresUnlock, boolean requiresScreenOn, int bannerResource, int uid, String settingsActivityName, String offHost, String staticOffHost, boolean isEnabled, HashMap<String, Boolean> autoTransact) { Map<String, Boolean> autoTransact, Map<Pattern, Boolean> autoTransactPatterns) { this.mService = info; this.mDescription = description; this.mStaticAidGroups = new HashMap<String, AidGroup>(); this.mDynamicAidGroups = new HashMap<String, AidGroup>(); this.mAutoTransact = autoTransact; this.mAutoTransactPatterns = autoTransactPatterns; this.mOffHostName = offHost; this.mStaticOffHostName = staticOffHost; this.mOnHost = onHost; Loading Loading @@ -314,6 +317,7 @@ public final class ApduServiceInfo implements Parcelable { mStaticAidGroups = new HashMap<String, AidGroup>(); mDynamicAidGroups = new HashMap<String, AidGroup>(); mAutoTransact = new HashMap<String, Boolean>(); mAutoTransactPatterns = new HashMap<Pattern, Boolean>(); mOnHost = onHost; final int depth = parser.getDepth(); Loading Loading @@ -408,6 +412,18 @@ public final class ApduServiceInfo implements Parcelable { false); mAutoTransact.put(plf, autoTransact); a.recycle(); } else if (eventType == XmlPullParser.START_TAG && "polling-loop-pattern-filter".equals(tagName) && currentGroup == null) { final TypedArray a = res.obtainAttributes(attrs, com.android.internal.R.styleable.PollingLoopPatternFilter); String plf = a.getString( com.android.internal.R.styleable.PollingLoopPatternFilter_name) .toUpperCase(Locale.ROOT); boolean autoTransact = a.getBoolean( com.android.internal.R.styleable.PollingLoopFilter_autoTransact, false); mAutoTransactPatterns.put(Pattern.compile(plf), autoTransact); a.recycle(); } } } catch (NameNotFoundException e) { Loading Loading @@ -481,7 +497,30 @@ public final class ApduServiceInfo implements Parcelable { */ @FlaggedApi(Flags.FLAG_NFC_READ_POLLING_LOOP) public boolean getShouldAutoTransact(@NonNull String plf) { return mAutoTransact.getOrDefault(plf.toUpperCase(Locale.ROOT), false); if (mAutoTransact.getOrDefault(plf.toUpperCase(Locale.ROOT), false)) { return true; } List<Pattern> patternMatches = mAutoTransactPatterns.keySet().stream() .filter(p -> p.matcher(plf).matches()).toList(); if (patternMatches == null || patternMatches.size() == 0) { return false; } for (Pattern patternMatch : patternMatches) { if (mAutoTransactPatterns.get(patternMatch)) { return true; } } return false; } /** * Returns the current polling loop pattern filters for this service. * @return List of polling loop pattern filters. */ @FlaggedApi(Flags.FLAG_NFC_READ_POLLING_LOOP) @NonNull public List<Pattern> getPollingLoopPatternFilters() { return new ArrayList<>(mAutoTransactPatterns.keySet()); } /** Loading Loading @@ -683,7 +722,7 @@ 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 * 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 * @param pollingLoopFilter the polling loop filter to add, must be a valid hexadecimal string */ @FlaggedApi(Flags.FLAG_NFC_READ_POLLING_LOOP) public void addPollingLoopFilter(@NonNull String pollingLoopFilter, Loading @@ -702,6 +741,31 @@ public final class ApduServiceInfo implements Parcelable { mAutoTransact.remove(pollingLoopFilter.toUpperCase(Locale.ROOT)); } /** * Add a Polling Loop Pattern Filter. Custom NFC polling frames that match this filter will be * delivered to {@link HostApduService#processPollingFrames(List)}. Adding a key with this * multiple times will cause the value to be overwritten each time. * @param pollingLoopPatternFilter the polling loop pattern filter to add, must be a valid * regex to match a hexadecimal string */ @FlaggedApi(Flags.FLAG_NFC_READ_POLLING_LOOP) public void addPollingLoopPatternFilter(@NonNull String pollingLoopPatternFilter, boolean autoTransact) { mAutoTransactPatterns.put(Pattern.compile(pollingLoopPatternFilter), autoTransact); } /** * Remove a Polling Loop Pattern Filter. Custom NFC polling frames that match this filter will * no longer be delivered to {@link HostApduService#processPollingFrames(List)}. * @param pollingLoopPatternFilter this polling loop filter to add. */ @FlaggedApi(Flags.FLAG_NFC_READ_POLLING_LOOP) public void removePollingLoopPatternFilter(@NonNull String pollingLoopPatternFilter) { mAutoTransactPatterns.remove( Pattern.compile(pollingLoopPatternFilter.toUpperCase(Locale.ROOT))); } /** * Sets the off host Secure Element. * @param offHost Secure Element to set. Only accept strings with prefix SIM or prefix eSE. Loading Loading @@ -856,6 +920,8 @@ public final class ApduServiceInfo implements Parcelable { dest.writeInt(mCategoryOtherServiceEnabled ? 1 : 0); dest.writeInt(mAutoTransact.size()); dest.writeMap(mAutoTransact); dest.writeInt(mAutoTransactPatterns.size()); dest.writeMap(mAutoTransactPatterns); }; @FlaggedApi(Flags.FLAG_ENABLE_NFC_MAINLINE) Loading Loading @@ -889,10 +955,15 @@ public final class ApduServiceInfo implements Parcelable { new HashMap<String, Boolean>(autoTransactSize); source.readMap(autoTransact, getClass().getClassLoader(), String.class, Boolean.class); int autoTransactPatternSize = source.readInt(); HashMap<Pattern, Boolean> autoTransactPatterns = new HashMap<Pattern, Boolean>(autoTransactSize); source.readMap(autoTransactPatterns, getClass().getClassLoader(), Pattern.class, Boolean.class); return new ApduServiceInfo(info, onHost, description, staticAidGroups, dynamicAidGroups, requiresUnlock, requiresScreenOn, bannerResource, uid, settingsActivityName, offHostName, staticOffHostName, isEnabled, autoTransact); isEnabled, autoTransact, autoTransactPatterns); } @Override Loading