Loading core/java/android/content/pm/PackageParser.java +36 −14 Original line number Diff line number Diff line Loading @@ -4070,32 +4070,54 @@ public class PackageParser { intentInfo, outError)) { return false; } Intent intent = new Intent(); if (intentInfo.countActions() != 1) { outError[0] = "intent tags must contain exactly one action."; Uri data = null; String dataType = null; String host = ""; final int numActions = intentInfo.countActions(); final int numSchemes = intentInfo.countDataSchemes(); final int numTypes = intentInfo.countDataTypes(); final int numHosts = intentInfo.getHosts().length; if ((numSchemes == 0 && numTypes == 0 && numActions == 0)) { outError[0] = "intent tags must contain either an action or data."; return false; } intent.setAction(intentInfo.getAction(0)); for (int i = 0, max = intentInfo.countCategories(); i < max; i++) { intent.addCategory(intentInfo.getCategory(i)); if (numActions > 1) { outError[0] = "intent tag may have at most one action."; return false; } Uri data = null; String dataType = null; if (intentInfo.countDataTypes() > 1) { if (numTypes > 1) { outError[0] = "intent tag may have at most one data type."; return false; } if (intentInfo.countDataSchemes() > 1) { if (numSchemes > 1) { outError[0] = "intent tag may have at most one data scheme."; return false; } if (intentInfo.countDataTypes() == 1) { data = Uri.fromParts(intentInfo.getDataType(0), "", null); if (numHosts > 1) { outError[0] = "intent tag may have at most one data host."; return false; } Intent intent = new Intent(); for (int i = 0, max = intentInfo.countCategories(); i < max; i++) { intent.addCategory(intentInfo.getCategory(i)); } if (intentInfo.countDataSchemes() == 1) { dataType = intentInfo.getDataScheme(0); if (numHosts == 1) { host = intentInfo.getHosts()[0]; } if (numSchemes == 1) { data = new Uri.Builder() .scheme(intentInfo.getDataScheme(0)) .authority(host) .build(); } if (numTypes == 1) { dataType = intentInfo.getDataType(0); } intent.setDataAndType(data, dataType); if (numActions == 1) { intent.setAction(intentInfo.getAction(0)); } owner.mQueriesIntents = ArrayUtils.add(owner.mQueriesIntents, intent); } else if (parser.getName().equals("package")) { final TypedArray sa = res.obtainAttributes(parser, Loading services/core/java/com/android/server/pm/AppsFilter.java +86 −18 Original line number Diff line number Diff line Loading @@ -16,13 +16,18 @@ package com.android.server.pm; import static android.content.pm.PackageParser.Component; import static android.content.pm.PackageParser.IntentInfo; import static android.provider.DeviceConfig.NAMESPACE_PACKAGE_MANAGER_SERVICE; import android.Manifest; import android.annotation.Nullable; import android.content.Intent; import android.content.IntentFilter; import android.content.pm.PackageManager; import android.content.pm.PackageParser; import android.content.pm.ProviderInfo; import android.net.Uri; import android.os.Build; import android.os.Process; import android.os.RemoteException; Loading @@ -38,6 +43,7 @@ import com.android.server.FgThread; import com.android.server.compat.PlatformCompat; import java.io.PrintWriter; import java.util.ArrayList; import java.util.Collections; import java.util.HashMap; import java.util.HashSet; Loading @@ -55,13 +61,13 @@ class AppsFilter { // Forces filtering logic to run for debug purposes. // STOPSHIP (b/136675067): should be false after development is complete private static final boolean DEBUG_RUN_WHEN_DISABLED = true; private static final boolean DEBUG_RUN_WHEN_DISABLED = false; // Logs all filtering instead of enforcing private static final boolean DEBUG_ALLOW_ALL = false; @SuppressWarnings("ConstantExpression") private static final boolean DEBUG_LOGGING = false | DEBUG_RUN_WHEN_DISABLED | DEBUG_ALLOW_ALL; private static final boolean DEBUG_LOGGING = false | DEBUG_ALLOW_ALL; /** * This contains a list of packages that are implicitly queryable because another app explicitly Loading Loading @@ -200,23 +206,43 @@ class AppsFilter { return false; } for (Intent intent : querying.mQueriesIntents) { for (PackageParser.Activity activity : potentialTarget.activities) { if (activity.intents != null) { for (PackageParser.ActivityIntentInfo filter : activity.intents) { if (matches(intent, filter)) { if (matches(intent, potentialTarget.providers, potentialTarget.activities, potentialTarget.services, potentialTarget.receivers)) { return true; } } return false; } private static boolean matches(Intent intent, ArrayList<PackageParser.Provider> providerList, ArrayList<? extends Component<? extends IntentInfo>>... componentLists) { for (int p = providerList.size() - 1; p >= 0; p--) { PackageParser.Provider provider = providerList.get(p); final ProviderInfo providerInfo = provider.info; final Uri data = intent.getData(); if ("content".equalsIgnoreCase(intent.getScheme()) && data != null && providerInfo.authority.equalsIgnoreCase(data.getAuthority())) { return true; } } return false; } /** Returns true if the given intent matches the given filter. */ private static boolean matches(Intent intent, PackageParser.ActivityIntentInfo filter) { return filter.match(intent.getAction(), intent.getType(), intent.getScheme(), intent.getData(), intent.getCategories(), "AppsFilter") > 0; for (int l = componentLists.length - 1; l >= 0; l--) { ArrayList<? extends Component<? extends IntentInfo>> components = componentLists[l]; for (int c = components.size() - 1; c >= 0; c--) { Component<? extends IntentInfo> component = components.get(c); ArrayList<? extends IntentInfo> intents = component.intents; for (int i = intents.size() - 1; i >= 0; i--) { IntentFilter intentFilter = intents.get(i); if (intentFilter.match(intent.getAction(), intent.getType(), intent.getScheme(), intent.getData(), intent.getCategories(), "AppsFilter") > 0) { return true; } } } } return false; } /** Loading Loading @@ -328,9 +354,15 @@ class AppsFilter { PackageSetting targetPkgSetting, int userId) { final boolean featureEnabled = mFeatureConfig.isGloballyEnabled(); if (!featureEnabled && !DEBUG_RUN_WHEN_DISABLED) { if (DEBUG_LOGGING) { Slog.d(TAG, "filtering disabled; skipped"); } return false; } if (callingUid < Process.FIRST_APPLICATION_UID) { if (DEBUG_LOGGING) { Slog.d(TAG, "filtering skipped; " + callingUid + " is system"); } return false; } if (callingSetting == null) { Loading Loading @@ -376,14 +408,13 @@ class AppsFilter { } if (mFeatureConfig.packageIsEnabled(callingPkgSetting.pkg)) { if (DEBUG_LOGGING) { Slog.d(TAG, "interaction: " + callingPkgSetting.name + " -> " + targetPkgSetting.name + (DEBUG_ALLOW_ALL ? " ALLOWED" : "BLOCKED")); log(callingPkgSetting, targetPkgSetting, DEBUG_ALLOW_ALL ? "ALLOWED" : "BLOCKED"); } return !DEBUG_ALLOW_ALL; } else { if (DEBUG_LOGGING) { Slog.d(TAG, "interaction: " + callingPkgSetting.name + " -> " + targetPkgSetting.name + " DISABLED"); log(callingPkgSetting, targetPkgSetting, "DISABLED"); } return false; } Loading @@ -397,38 +428,65 @@ class AppsFilter { // This package isn't technically installed and won't be written to settings, so we can // treat it as filtered until it's available again. if (targetPkg == null) { if (DEBUG_LOGGING) { Slog.wtf(TAG, "shouldFilterApplication: " + "targetPkg is null"); } return true; } final String targetName = targetPkg.packageName; if (callingPkgSetting.pkg.applicationInfo.targetSdkVersion < Build.VERSION_CODES.R) { if (DEBUG_LOGGING) { log(callingPkgSetting, targetPkgSetting, "caller pre-R"); } return false; } if (isImplicitlyQueryableSystemApp(targetPkgSetting)) { if (DEBUG_LOGGING) { log(callingPkgSetting, targetPkgSetting, "implicitly queryable sys"); } return false; } if (targetPkg.mForceQueryable) { if (DEBUG_LOGGING) { log(callingPkgSetting, targetPkgSetting, "manifest forceQueryable"); } return false; } if (mForceQueryable.contains(targetName)) { if (DEBUG_LOGGING) { log(callingPkgSetting, targetPkgSetting, "whitelist forceQueryable"); } return false; } if (mQueriesViaPackage.containsKey(callingName) && mQueriesViaPackage.get(callingName).contains( targetName)) { // the calling package has explicitly declared the target package; allow if (DEBUG_LOGGING) { log(callingPkgSetting, targetPkgSetting, "queries package"); } return false; } else if (mQueriesViaIntent.containsKey(callingName) && mQueriesViaIntent.get(callingName).contains(targetName)) { if (DEBUG_LOGGING) { log(callingPkgSetting, targetPkgSetting, "queries intent"); } return false; } if (mImplicitlyQueryable.get(userId) != null && mImplicitlyQueryable.get(userId).containsKey(callingName) && mImplicitlyQueryable.get(userId).get(callingName).contains(targetName)) { if (DEBUG_LOGGING) { log(callingPkgSetting, targetPkgSetting, "implicitly queryable for user"); } return false; } if (callingPkgSetting.pkg.instrumentation.size() > 0) { for (int i = 0, max = callingPkgSetting.pkg.instrumentation.size(); i < max; i++) { if (callingPkgSetting.pkg.instrumentation.get(i).info.targetPackage == targetName) { if (DEBUG_LOGGING) { log(callingPkgSetting, targetPkgSetting, "instrumentation"); } return false; } } Loading @@ -437,6 +495,9 @@ class AppsFilter { if (mPermissionManager.checkPermission( Manifest.permission.QUERY_ALL_PACKAGES, callingName, userId) == PackageManager.PERMISSION_GRANTED) { if (DEBUG_LOGGING) { log(callingPkgSetting, targetPkgSetting, "permission"); } return false; } } catch (RemoteException e) { Loading @@ -445,6 +506,13 @@ class AppsFilter { return true; } private static void log(PackageSetting callingPkgSetting, PackageSetting targetPkgSetting, String description) { Slog.wtf(TAG, "interaction: " + callingPkgSetting.name + " -> " + targetPkgSetting.name + " " + description); } private boolean isImplicitlyQueryableSystemApp(PackageSetting targetPkgSetting) { return targetPkgSetting.isSystem() && (mSystemAppsQueryable || mForceQueryableByDevice.contains(targetPkgSetting.pkg.packageName)); Loading Loading
core/java/android/content/pm/PackageParser.java +36 −14 Original line number Diff line number Diff line Loading @@ -4070,32 +4070,54 @@ public class PackageParser { intentInfo, outError)) { return false; } Intent intent = new Intent(); if (intentInfo.countActions() != 1) { outError[0] = "intent tags must contain exactly one action."; Uri data = null; String dataType = null; String host = ""; final int numActions = intentInfo.countActions(); final int numSchemes = intentInfo.countDataSchemes(); final int numTypes = intentInfo.countDataTypes(); final int numHosts = intentInfo.getHosts().length; if ((numSchemes == 0 && numTypes == 0 && numActions == 0)) { outError[0] = "intent tags must contain either an action or data."; return false; } intent.setAction(intentInfo.getAction(0)); for (int i = 0, max = intentInfo.countCategories(); i < max; i++) { intent.addCategory(intentInfo.getCategory(i)); if (numActions > 1) { outError[0] = "intent tag may have at most one action."; return false; } Uri data = null; String dataType = null; if (intentInfo.countDataTypes() > 1) { if (numTypes > 1) { outError[0] = "intent tag may have at most one data type."; return false; } if (intentInfo.countDataSchemes() > 1) { if (numSchemes > 1) { outError[0] = "intent tag may have at most one data scheme."; return false; } if (intentInfo.countDataTypes() == 1) { data = Uri.fromParts(intentInfo.getDataType(0), "", null); if (numHosts > 1) { outError[0] = "intent tag may have at most one data host."; return false; } Intent intent = new Intent(); for (int i = 0, max = intentInfo.countCategories(); i < max; i++) { intent.addCategory(intentInfo.getCategory(i)); } if (intentInfo.countDataSchemes() == 1) { dataType = intentInfo.getDataScheme(0); if (numHosts == 1) { host = intentInfo.getHosts()[0]; } if (numSchemes == 1) { data = new Uri.Builder() .scheme(intentInfo.getDataScheme(0)) .authority(host) .build(); } if (numTypes == 1) { dataType = intentInfo.getDataType(0); } intent.setDataAndType(data, dataType); if (numActions == 1) { intent.setAction(intentInfo.getAction(0)); } owner.mQueriesIntents = ArrayUtils.add(owner.mQueriesIntents, intent); } else if (parser.getName().equals("package")) { final TypedArray sa = res.obtainAttributes(parser, Loading
services/core/java/com/android/server/pm/AppsFilter.java +86 −18 Original line number Diff line number Diff line Loading @@ -16,13 +16,18 @@ package com.android.server.pm; import static android.content.pm.PackageParser.Component; import static android.content.pm.PackageParser.IntentInfo; import static android.provider.DeviceConfig.NAMESPACE_PACKAGE_MANAGER_SERVICE; import android.Manifest; import android.annotation.Nullable; import android.content.Intent; import android.content.IntentFilter; import android.content.pm.PackageManager; import android.content.pm.PackageParser; import android.content.pm.ProviderInfo; import android.net.Uri; import android.os.Build; import android.os.Process; import android.os.RemoteException; Loading @@ -38,6 +43,7 @@ import com.android.server.FgThread; import com.android.server.compat.PlatformCompat; import java.io.PrintWriter; import java.util.ArrayList; import java.util.Collections; import java.util.HashMap; import java.util.HashSet; Loading @@ -55,13 +61,13 @@ class AppsFilter { // Forces filtering logic to run for debug purposes. // STOPSHIP (b/136675067): should be false after development is complete private static final boolean DEBUG_RUN_WHEN_DISABLED = true; private static final boolean DEBUG_RUN_WHEN_DISABLED = false; // Logs all filtering instead of enforcing private static final boolean DEBUG_ALLOW_ALL = false; @SuppressWarnings("ConstantExpression") private static final boolean DEBUG_LOGGING = false | DEBUG_RUN_WHEN_DISABLED | DEBUG_ALLOW_ALL; private static final boolean DEBUG_LOGGING = false | DEBUG_ALLOW_ALL; /** * This contains a list of packages that are implicitly queryable because another app explicitly Loading Loading @@ -200,23 +206,43 @@ class AppsFilter { return false; } for (Intent intent : querying.mQueriesIntents) { for (PackageParser.Activity activity : potentialTarget.activities) { if (activity.intents != null) { for (PackageParser.ActivityIntentInfo filter : activity.intents) { if (matches(intent, filter)) { if (matches(intent, potentialTarget.providers, potentialTarget.activities, potentialTarget.services, potentialTarget.receivers)) { return true; } } return false; } private static boolean matches(Intent intent, ArrayList<PackageParser.Provider> providerList, ArrayList<? extends Component<? extends IntentInfo>>... componentLists) { for (int p = providerList.size() - 1; p >= 0; p--) { PackageParser.Provider provider = providerList.get(p); final ProviderInfo providerInfo = provider.info; final Uri data = intent.getData(); if ("content".equalsIgnoreCase(intent.getScheme()) && data != null && providerInfo.authority.equalsIgnoreCase(data.getAuthority())) { return true; } } return false; } /** Returns true if the given intent matches the given filter. */ private static boolean matches(Intent intent, PackageParser.ActivityIntentInfo filter) { return filter.match(intent.getAction(), intent.getType(), intent.getScheme(), intent.getData(), intent.getCategories(), "AppsFilter") > 0; for (int l = componentLists.length - 1; l >= 0; l--) { ArrayList<? extends Component<? extends IntentInfo>> components = componentLists[l]; for (int c = components.size() - 1; c >= 0; c--) { Component<? extends IntentInfo> component = components.get(c); ArrayList<? extends IntentInfo> intents = component.intents; for (int i = intents.size() - 1; i >= 0; i--) { IntentFilter intentFilter = intents.get(i); if (intentFilter.match(intent.getAction(), intent.getType(), intent.getScheme(), intent.getData(), intent.getCategories(), "AppsFilter") > 0) { return true; } } } } return false; } /** Loading Loading @@ -328,9 +354,15 @@ class AppsFilter { PackageSetting targetPkgSetting, int userId) { final boolean featureEnabled = mFeatureConfig.isGloballyEnabled(); if (!featureEnabled && !DEBUG_RUN_WHEN_DISABLED) { if (DEBUG_LOGGING) { Slog.d(TAG, "filtering disabled; skipped"); } return false; } if (callingUid < Process.FIRST_APPLICATION_UID) { if (DEBUG_LOGGING) { Slog.d(TAG, "filtering skipped; " + callingUid + " is system"); } return false; } if (callingSetting == null) { Loading Loading @@ -376,14 +408,13 @@ class AppsFilter { } if (mFeatureConfig.packageIsEnabled(callingPkgSetting.pkg)) { if (DEBUG_LOGGING) { Slog.d(TAG, "interaction: " + callingPkgSetting.name + " -> " + targetPkgSetting.name + (DEBUG_ALLOW_ALL ? " ALLOWED" : "BLOCKED")); log(callingPkgSetting, targetPkgSetting, DEBUG_ALLOW_ALL ? "ALLOWED" : "BLOCKED"); } return !DEBUG_ALLOW_ALL; } else { if (DEBUG_LOGGING) { Slog.d(TAG, "interaction: " + callingPkgSetting.name + " -> " + targetPkgSetting.name + " DISABLED"); log(callingPkgSetting, targetPkgSetting, "DISABLED"); } return false; } Loading @@ -397,38 +428,65 @@ class AppsFilter { // This package isn't technically installed and won't be written to settings, so we can // treat it as filtered until it's available again. if (targetPkg == null) { if (DEBUG_LOGGING) { Slog.wtf(TAG, "shouldFilterApplication: " + "targetPkg is null"); } return true; } final String targetName = targetPkg.packageName; if (callingPkgSetting.pkg.applicationInfo.targetSdkVersion < Build.VERSION_CODES.R) { if (DEBUG_LOGGING) { log(callingPkgSetting, targetPkgSetting, "caller pre-R"); } return false; } if (isImplicitlyQueryableSystemApp(targetPkgSetting)) { if (DEBUG_LOGGING) { log(callingPkgSetting, targetPkgSetting, "implicitly queryable sys"); } return false; } if (targetPkg.mForceQueryable) { if (DEBUG_LOGGING) { log(callingPkgSetting, targetPkgSetting, "manifest forceQueryable"); } return false; } if (mForceQueryable.contains(targetName)) { if (DEBUG_LOGGING) { log(callingPkgSetting, targetPkgSetting, "whitelist forceQueryable"); } return false; } if (mQueriesViaPackage.containsKey(callingName) && mQueriesViaPackage.get(callingName).contains( targetName)) { // the calling package has explicitly declared the target package; allow if (DEBUG_LOGGING) { log(callingPkgSetting, targetPkgSetting, "queries package"); } return false; } else if (mQueriesViaIntent.containsKey(callingName) && mQueriesViaIntent.get(callingName).contains(targetName)) { if (DEBUG_LOGGING) { log(callingPkgSetting, targetPkgSetting, "queries intent"); } return false; } if (mImplicitlyQueryable.get(userId) != null && mImplicitlyQueryable.get(userId).containsKey(callingName) && mImplicitlyQueryable.get(userId).get(callingName).contains(targetName)) { if (DEBUG_LOGGING) { log(callingPkgSetting, targetPkgSetting, "implicitly queryable for user"); } return false; } if (callingPkgSetting.pkg.instrumentation.size() > 0) { for (int i = 0, max = callingPkgSetting.pkg.instrumentation.size(); i < max; i++) { if (callingPkgSetting.pkg.instrumentation.get(i).info.targetPackage == targetName) { if (DEBUG_LOGGING) { log(callingPkgSetting, targetPkgSetting, "instrumentation"); } return false; } } Loading @@ -437,6 +495,9 @@ class AppsFilter { if (mPermissionManager.checkPermission( Manifest.permission.QUERY_ALL_PACKAGES, callingName, userId) == PackageManager.PERMISSION_GRANTED) { if (DEBUG_LOGGING) { log(callingPkgSetting, targetPkgSetting, "permission"); } return false; } } catch (RemoteException e) { Loading @@ -445,6 +506,13 @@ class AppsFilter { return true; } private static void log(PackageSetting callingPkgSetting, PackageSetting targetPkgSetting, String description) { Slog.wtf(TAG, "interaction: " + callingPkgSetting.name + " -> " + targetPkgSetting.name + " " + description); } private boolean isImplicitlyQueryableSystemApp(PackageSetting targetPkgSetting) { return targetPkgSetting.isSystem() && (mSystemAppsQueryable || mForceQueryableByDevice.contains(targetPkgSetting.pkg.packageName)); Loading