Loading core/java/android/content/IntentFilter.java +32 −9 Original line number Diff line number Diff line Loading @@ -17,6 +17,7 @@ package android.content; import android.annotation.IntDef; import android.annotation.Nullable; import android.annotation.SystemApi; import android.compat.annotation.UnsupportedAppUsage; import android.net.Uri; Loading @@ -40,6 +41,7 @@ import java.io.IOException; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.util.ArrayList; import java.util.Collection; import java.util.Iterator; import java.util.List; import java.util.Set; Loading Loading @@ -766,17 +768,31 @@ public class IntentFilter implements Parcelable { * @return True if the action is listed in the filter. */ public final boolean matchAction(String action) { return matchAction(action, false); return matchAction(action, false /*wildcardSupported*/, null /*ignoreActions*/); } /** * Variant of {@link #matchAction(String)} that allows a wildcard for the provided action. * @param wildcardSupported if true, will allow action to use wildcards * @param ignoreActions if not null, the set of actions to should not be considered valid while * calculating the match */ private boolean matchAction(String action, boolean wildcardSupported) { if (wildcardSupported && !mActions.isEmpty() && WILDCARD.equals(action)) { private boolean matchAction(String action, boolean wildcardSupported, @Nullable Collection<String> ignoreActions) { if (wildcardSupported && WILDCARD.equals(action)) { if (ignoreActions == null) { return !mActions.isEmpty(); } for (int i = mActions.size() - 1; i >= 0; i--) { if (!ignoreActions.contains(mActions.get(i))) { return true; } } return false; } if (ignoreActions != null && ignoreActions.contains(action)) { return false; } return hasAction(action); } Loading Loading @@ -1779,17 +1795,24 @@ public class IntentFilter implements Parcelable { */ public final int match(String action, String type, String scheme, Uri data, Set<String> categories, String logTag) { return match(action, type, scheme, data, categories, logTag, false /*supportWildcards*/); return match(action, type, scheme, data, categories, logTag, false /*supportWildcards*/, null /*ignoreActions*/); } /** * Variant of {@link #match(ContentResolver, Intent, boolean, String)} that supports wildcards * in the action, type, scheme, host and path. * @hide if true, will allow supported parameters to use wildcards to match this filter * @param supportWildcards if true, will allow supported parameters to use wildcards to match * this filter * @param ignoreActions a collection of actions that, if not null should be ignored and not used * if provided as the matching action or the set of actions defined by this * filter * @hide */ public final int match(String action, String type, String scheme, Uri data, Set<String> categories, String logTag, boolean supportWildcards) { if (action != null && !matchAction(action, supportWildcards)) { Uri data, Set<String> categories, String logTag, boolean supportWildcards, @Nullable Collection<String> ignoreActions) { if (action != null && !matchAction(action, supportWildcards, ignoreActions)) { if (false) Log.v( logTag, "No matching action " + action + " for " + this); return NO_MATCH_ACTION; Loading services/core/java/com/android/server/pm/AppsFilter.java +74 −13 Original line number Diff line number Diff line Loading @@ -113,6 +113,7 @@ public class AppsFilter { private final OverlayReferenceMapper mOverlayReferenceMapper; private PackageParser.SigningDetails mSystemSigningDetails; private Set<String> mProtectedBroadcasts = new ArraySet<>(); AppsFilter(FeatureConfig featureConfig, String[] forceQueryableWhitelist, boolean systemAppsQueryable, Loading Loading @@ -298,10 +299,10 @@ public class AppsFilter { /** Returns true if the querying package may query for the potential target package */ private static boolean canQueryViaComponents(AndroidPackage querying, AndroidPackage potentialTarget) { AndroidPackage potentialTarget, Set<String> protectedBroadcasts) { if (!querying.getQueriesIntents().isEmpty()) { for (Intent intent : querying.getQueriesIntents()) { if (matchesIntentFilters(intent, potentialTarget)) { if (matchesIntentFilters(intent, potentialTarget, protectedBroadcasts)) { return true; } } Loading Loading @@ -353,13 +354,14 @@ public class AppsFilter { return false; } private static boolean matchesIntentFilters(Intent intent, AndroidPackage potentialTarget) { private static boolean matchesIntentFilters(Intent intent, AndroidPackage potentialTarget, Set<String> protectedBroadcasts) { for (int s = ArrayUtils.size(potentialTarget.getServices()) - 1; s >= 0; s--) { ParsedService service = potentialTarget.getServices().get(s); if (!service.isExported()) { continue; } if (matchesAnyFilter(intent, service)) { if (matchesAnyFilter(intent, service, null /*protectedBroadcasts*/)) { return true; } } Loading @@ -368,7 +370,8 @@ public class AppsFilter { if (!activity.isExported()) { continue; } if (matchesAnyFilter(intent, activity)) { if (matchesAnyFilter(intent, activity, null /*protectedBroadcasts*/)) { return true; } } Loading @@ -377,25 +380,32 @@ public class AppsFilter { if (!receiver.isExported()) { continue; } if (matchesAnyFilter(intent, receiver)) { if (matchesAnyFilter(intent, receiver, protectedBroadcasts)) { return true; } } return false; } private static boolean matchesAnyFilter(Intent intent, ParsedComponent component) { private static boolean matchesAnyFilter(Intent intent, ParsedComponent component, Set<String> protectedBroadcasts) { List<ParsedIntentInfo> intents = component.getIntents(); for (int i = ArrayUtils.size(intents) - 1; i >= 0; i--) { IntentFilter intentFilter = intents.get(i); if (intentFilter.match(intent.getAction(), intent.getType(), intent.getScheme(), intent.getData(), intent.getCategories(), "AppsFilter", true) > 0) { if (matchesIntentFilter(intent, intentFilter, protectedBroadcasts)) { return true; } } return false; } private static boolean matchesIntentFilter(Intent intent, IntentFilter intentFilter, @Nullable Set<String> protectedBroadcasts) { return intentFilter.match(intent.getAction(), intent.getType(), intent.getScheme(), intent.getData(), intent.getCategories(), "AppsFilter", true, protectedBroadcasts) > 0; } /** * Grants access based on an interaction between a calling and target package, granting * visibility of the caller from the target. Loading Loading @@ -434,6 +444,12 @@ public class AppsFilter { } } } if (!newPkgSetting.pkg.getProtectedBroadcasts().isEmpty()) { mProtectedBroadcasts.addAll(newPkgSetting.pkg.getProtectedBroadcasts()); recomputeComponentVisibility(existingSettings, newPkgSetting.pkg.getPackageName()); } Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "filter.addPackage"); try { final AndroidPackage newPkg = newPkgSetting.pkg; Loading Loading @@ -464,7 +480,7 @@ public class AppsFilter { final AndroidPackage existingPkg = existingSetting.pkg; // let's evaluate the ability of already added packages to see this new package if (!newIsForceQueryable) { if (canQueryViaComponents(existingPkg, newPkg)) { if (canQueryViaComponents(existingPkg, newPkg, mProtectedBroadcasts)) { mQueriesViaComponent.add(existingSetting.appId, newPkgSetting.appId); } if (canQueryViaPackage(existingPkg, newPkg) Loading @@ -474,7 +490,7 @@ public class AppsFilter { } // now we'll evaluate our new package's ability to see existing packages if (!mForceQueryable.contains(existingSetting.appId)) { if (canQueryViaComponents(newPkg, existingPkg)) { if (canQueryViaComponents(newPkg, existingPkg, mProtectedBroadcasts)) { mQueriesViaComponent.add(newPkgSetting.appId, existingSetting.appId); } if (canQueryViaPackage(newPkg, existingPkg) Loading Loading @@ -511,10 +527,47 @@ public class AppsFilter { && pkgSetting.signatures.mSigningDetails.signaturesMatchExactly(sysSigningDetails); } private static void sort(int[] uids, int nextUidIndex) { Arrays.sort(uids, 0, nextUidIndex); private ArraySet<String> collectProtectedBroadcasts( ArrayMap<String, PackageSetting> existingSettings, @Nullable String excludePackage) { ArraySet<String> ret = new ArraySet<>(); for (int i = existingSettings.size() - 1; i >= 0; i--) { PackageSetting setting = existingSettings.valueAt(i); if (setting.pkg == null || setting.pkg.getPackageName().equals(excludePackage)) { continue; } final List<String> protectedBroadcasts = setting.pkg.getProtectedBroadcasts(); if (!protectedBroadcasts.isEmpty()) { ret.addAll(protectedBroadcasts); } } return ret; } private void recomputeComponentVisibility(ArrayMap<String, PackageSetting> existingSettings, @Nullable String excludePackage) { mQueriesViaComponent.clear(); for (int i = existingSettings.size() - 1; i >= 0; i--) { PackageSetting setting = existingSettings.valueAt(i); if (setting.pkg == null || setting.pkg.getPackageName().equals(excludePackage) || mForceQueryable.contains(setting.appId)) { continue; } for (int j = existingSettings.size() - 1; j >= 0; j--) { if (i == j) { continue; } final PackageSetting otherSetting = existingSettings.valueAt(j); if (otherSetting.pkg == null || otherSetting.pkg.getPackageName().equals(excludePackage)) { continue; } if (canQueryViaComponents(setting.pkg, otherSetting.pkg, mProtectedBroadcasts)) { mQueriesViaComponent.add(setting.appId, otherSetting.appId); } } } } /** * Fetches all app Ids that a given setting is currently visible to, per provided user. This * only includes UIDs >= {@link Process#FIRST_APPLICATION_UID} as all other UIDs can already see Loading Loading @@ -608,6 +661,14 @@ public class AppsFilter { } } if (!setting.pkg.getProtectedBroadcasts().isEmpty()) { final String removingPackageName = setting.pkg.getPackageName(); mProtectedBroadcasts.clear(); mProtectedBroadcasts.addAll( collectProtectedBroadcasts(existingSettings, removingPackageName)); recomputeComponentVisibility(existingSettings, removingPackageName); } mOverlayReferenceMapper.removePkg(setting.name); mFeatureConfig.updatePackageState(setting, true /*removed*/); } Loading services/tests/servicestests/src/com/android/server/pm/AppsFilterTest.java +103 −26 File changed.Preview size limit exceeded, changes collapsed. Show changes Loading
core/java/android/content/IntentFilter.java +32 −9 Original line number Diff line number Diff line Loading @@ -17,6 +17,7 @@ package android.content; import android.annotation.IntDef; import android.annotation.Nullable; import android.annotation.SystemApi; import android.compat.annotation.UnsupportedAppUsage; import android.net.Uri; Loading @@ -40,6 +41,7 @@ import java.io.IOException; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.util.ArrayList; import java.util.Collection; import java.util.Iterator; import java.util.List; import java.util.Set; Loading Loading @@ -766,17 +768,31 @@ public class IntentFilter implements Parcelable { * @return True if the action is listed in the filter. */ public final boolean matchAction(String action) { return matchAction(action, false); return matchAction(action, false /*wildcardSupported*/, null /*ignoreActions*/); } /** * Variant of {@link #matchAction(String)} that allows a wildcard for the provided action. * @param wildcardSupported if true, will allow action to use wildcards * @param ignoreActions if not null, the set of actions to should not be considered valid while * calculating the match */ private boolean matchAction(String action, boolean wildcardSupported) { if (wildcardSupported && !mActions.isEmpty() && WILDCARD.equals(action)) { private boolean matchAction(String action, boolean wildcardSupported, @Nullable Collection<String> ignoreActions) { if (wildcardSupported && WILDCARD.equals(action)) { if (ignoreActions == null) { return !mActions.isEmpty(); } for (int i = mActions.size() - 1; i >= 0; i--) { if (!ignoreActions.contains(mActions.get(i))) { return true; } } return false; } if (ignoreActions != null && ignoreActions.contains(action)) { return false; } return hasAction(action); } Loading Loading @@ -1779,17 +1795,24 @@ public class IntentFilter implements Parcelable { */ public final int match(String action, String type, String scheme, Uri data, Set<String> categories, String logTag) { return match(action, type, scheme, data, categories, logTag, false /*supportWildcards*/); return match(action, type, scheme, data, categories, logTag, false /*supportWildcards*/, null /*ignoreActions*/); } /** * Variant of {@link #match(ContentResolver, Intent, boolean, String)} that supports wildcards * in the action, type, scheme, host and path. * @hide if true, will allow supported parameters to use wildcards to match this filter * @param supportWildcards if true, will allow supported parameters to use wildcards to match * this filter * @param ignoreActions a collection of actions that, if not null should be ignored and not used * if provided as the matching action or the set of actions defined by this * filter * @hide */ public final int match(String action, String type, String scheme, Uri data, Set<String> categories, String logTag, boolean supportWildcards) { if (action != null && !matchAction(action, supportWildcards)) { Uri data, Set<String> categories, String logTag, boolean supportWildcards, @Nullable Collection<String> ignoreActions) { if (action != null && !matchAction(action, supportWildcards, ignoreActions)) { if (false) Log.v( logTag, "No matching action " + action + " for " + this); return NO_MATCH_ACTION; Loading
services/core/java/com/android/server/pm/AppsFilter.java +74 −13 Original line number Diff line number Diff line Loading @@ -113,6 +113,7 @@ public class AppsFilter { private final OverlayReferenceMapper mOverlayReferenceMapper; private PackageParser.SigningDetails mSystemSigningDetails; private Set<String> mProtectedBroadcasts = new ArraySet<>(); AppsFilter(FeatureConfig featureConfig, String[] forceQueryableWhitelist, boolean systemAppsQueryable, Loading Loading @@ -298,10 +299,10 @@ public class AppsFilter { /** Returns true if the querying package may query for the potential target package */ private static boolean canQueryViaComponents(AndroidPackage querying, AndroidPackage potentialTarget) { AndroidPackage potentialTarget, Set<String> protectedBroadcasts) { if (!querying.getQueriesIntents().isEmpty()) { for (Intent intent : querying.getQueriesIntents()) { if (matchesIntentFilters(intent, potentialTarget)) { if (matchesIntentFilters(intent, potentialTarget, protectedBroadcasts)) { return true; } } Loading Loading @@ -353,13 +354,14 @@ public class AppsFilter { return false; } private static boolean matchesIntentFilters(Intent intent, AndroidPackage potentialTarget) { private static boolean matchesIntentFilters(Intent intent, AndroidPackage potentialTarget, Set<String> protectedBroadcasts) { for (int s = ArrayUtils.size(potentialTarget.getServices()) - 1; s >= 0; s--) { ParsedService service = potentialTarget.getServices().get(s); if (!service.isExported()) { continue; } if (matchesAnyFilter(intent, service)) { if (matchesAnyFilter(intent, service, null /*protectedBroadcasts*/)) { return true; } } Loading @@ -368,7 +370,8 @@ public class AppsFilter { if (!activity.isExported()) { continue; } if (matchesAnyFilter(intent, activity)) { if (matchesAnyFilter(intent, activity, null /*protectedBroadcasts*/)) { return true; } } Loading @@ -377,25 +380,32 @@ public class AppsFilter { if (!receiver.isExported()) { continue; } if (matchesAnyFilter(intent, receiver)) { if (matchesAnyFilter(intent, receiver, protectedBroadcasts)) { return true; } } return false; } private static boolean matchesAnyFilter(Intent intent, ParsedComponent component) { private static boolean matchesAnyFilter(Intent intent, ParsedComponent component, Set<String> protectedBroadcasts) { List<ParsedIntentInfo> intents = component.getIntents(); for (int i = ArrayUtils.size(intents) - 1; i >= 0; i--) { IntentFilter intentFilter = intents.get(i); if (intentFilter.match(intent.getAction(), intent.getType(), intent.getScheme(), intent.getData(), intent.getCategories(), "AppsFilter", true) > 0) { if (matchesIntentFilter(intent, intentFilter, protectedBroadcasts)) { return true; } } return false; } private static boolean matchesIntentFilter(Intent intent, IntentFilter intentFilter, @Nullable Set<String> protectedBroadcasts) { return intentFilter.match(intent.getAction(), intent.getType(), intent.getScheme(), intent.getData(), intent.getCategories(), "AppsFilter", true, protectedBroadcasts) > 0; } /** * Grants access based on an interaction between a calling and target package, granting * visibility of the caller from the target. Loading Loading @@ -434,6 +444,12 @@ public class AppsFilter { } } } if (!newPkgSetting.pkg.getProtectedBroadcasts().isEmpty()) { mProtectedBroadcasts.addAll(newPkgSetting.pkg.getProtectedBroadcasts()); recomputeComponentVisibility(existingSettings, newPkgSetting.pkg.getPackageName()); } Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "filter.addPackage"); try { final AndroidPackage newPkg = newPkgSetting.pkg; Loading Loading @@ -464,7 +480,7 @@ public class AppsFilter { final AndroidPackage existingPkg = existingSetting.pkg; // let's evaluate the ability of already added packages to see this new package if (!newIsForceQueryable) { if (canQueryViaComponents(existingPkg, newPkg)) { if (canQueryViaComponents(existingPkg, newPkg, mProtectedBroadcasts)) { mQueriesViaComponent.add(existingSetting.appId, newPkgSetting.appId); } if (canQueryViaPackage(existingPkg, newPkg) Loading @@ -474,7 +490,7 @@ public class AppsFilter { } // now we'll evaluate our new package's ability to see existing packages if (!mForceQueryable.contains(existingSetting.appId)) { if (canQueryViaComponents(newPkg, existingPkg)) { if (canQueryViaComponents(newPkg, existingPkg, mProtectedBroadcasts)) { mQueriesViaComponent.add(newPkgSetting.appId, existingSetting.appId); } if (canQueryViaPackage(newPkg, existingPkg) Loading Loading @@ -511,10 +527,47 @@ public class AppsFilter { && pkgSetting.signatures.mSigningDetails.signaturesMatchExactly(sysSigningDetails); } private static void sort(int[] uids, int nextUidIndex) { Arrays.sort(uids, 0, nextUidIndex); private ArraySet<String> collectProtectedBroadcasts( ArrayMap<String, PackageSetting> existingSettings, @Nullable String excludePackage) { ArraySet<String> ret = new ArraySet<>(); for (int i = existingSettings.size() - 1; i >= 0; i--) { PackageSetting setting = existingSettings.valueAt(i); if (setting.pkg == null || setting.pkg.getPackageName().equals(excludePackage)) { continue; } final List<String> protectedBroadcasts = setting.pkg.getProtectedBroadcasts(); if (!protectedBroadcasts.isEmpty()) { ret.addAll(protectedBroadcasts); } } return ret; } private void recomputeComponentVisibility(ArrayMap<String, PackageSetting> existingSettings, @Nullable String excludePackage) { mQueriesViaComponent.clear(); for (int i = existingSettings.size() - 1; i >= 0; i--) { PackageSetting setting = existingSettings.valueAt(i); if (setting.pkg == null || setting.pkg.getPackageName().equals(excludePackage) || mForceQueryable.contains(setting.appId)) { continue; } for (int j = existingSettings.size() - 1; j >= 0; j--) { if (i == j) { continue; } final PackageSetting otherSetting = existingSettings.valueAt(j); if (otherSetting.pkg == null || otherSetting.pkg.getPackageName().equals(excludePackage)) { continue; } if (canQueryViaComponents(setting.pkg, otherSetting.pkg, mProtectedBroadcasts)) { mQueriesViaComponent.add(setting.appId, otherSetting.appId); } } } } /** * Fetches all app Ids that a given setting is currently visible to, per provided user. This * only includes UIDs >= {@link Process#FIRST_APPLICATION_UID} as all other UIDs can already see Loading Loading @@ -608,6 +661,14 @@ public class AppsFilter { } } if (!setting.pkg.getProtectedBroadcasts().isEmpty()) { final String removingPackageName = setting.pkg.getPackageName(); mProtectedBroadcasts.clear(); mProtectedBroadcasts.addAll( collectProtectedBroadcasts(existingSettings, removingPackageName)); recomputeComponentVisibility(existingSettings, removingPackageName); } mOverlayReferenceMapper.removePkg(setting.name); mFeatureConfig.updatePackageState(setting, true /*removed*/); } Loading
services/tests/servicestests/src/com/android/server/pm/AppsFilterTest.java +103 −26 File changed.Preview size limit exceeded, changes collapsed. Show changes