Loading core/java/android/app/BroadcastOptions.java +34 −0 Original line number Diff line number Diff line Loading @@ -40,6 +40,8 @@ import android.os.PowerExemptionManager.ReasonCode; import android.os.PowerExemptionManager.TempAllowListType; import android.os.Process; import com.android.internal.util.ArrayUtils; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.util.Objects; Loading Loading @@ -68,6 +70,7 @@ public class BroadcastOptions extends ComponentOptions { private @Nullable BundleMerger mDeliveryGroupExtrasMerger; private @Nullable IntentFilter mDeliveryGroupMatchingFilter; private @DeferralPolicy int mDeferralPolicy; private @Nullable String[] mIncludedPackages; /** @hide */ @IntDef(flag = true, prefix = { "FLAG_" }, value = { Loading Loading @@ -230,6 +233,12 @@ public class BroadcastOptions extends ComponentOptions { private static final String KEY_DEFERRAL_POLICY = "android:broadcast.deferralPolicy"; /** * Corresponds to {@link #setIncludedPackages(String[])} */ private static final String KEY_INCLUDED_PACKAGES = "android:broadcast.includedPackageNames"; /** * The list of delivery group policies which specify how multiple broadcasts belonging to * the same delivery group has to be handled. Loading Loading @@ -355,6 +364,7 @@ public class BroadcastOptions extends ComponentOptions { mDeliveryGroupMatchingFilter = opts.getParcelable(KEY_DELIVERY_GROUP_MATCHING_FILTER, IntentFilter.class); mDeferralPolicy = opts.getInt(KEY_DEFERRAL_POLICY, DEFERRAL_POLICY_DEFAULT); mIncludedPackages = opts.getStringArray(KEY_INCLUDED_PACKAGES); } /** @hide */ Loading Loading @@ -1112,6 +1122,27 @@ public class BroadcastOptions extends ComponentOptions { return (mFlags & FLAG_DEBUG_LOG) != 0; } /** * Set the list of packages to send the broadcast to. * * @hide */ public BroadcastOptions setIncludedPackages(@Nullable String[] packageNames) { mIncludedPackages = packageNames; return this; } /** * Get the list of packages to send the broadcast to, that was previously set using * {@link #setIncludedPackages(String[])}. * * @hide */ @Nullable public String[] getIncludedPackages() { return mIncludedPackages; } /** * Returns the created options as a Bundle, which can be passed to * {@link android.content.Context#sendBroadcast(android.content.Intent) Loading Loading @@ -1178,6 +1209,9 @@ public class BroadcastOptions extends ComponentOptions { if (mDeferralPolicy != DEFERRAL_POLICY_DEFAULT) { b.putInt(KEY_DEFERRAL_POLICY, mDeferralPolicy); } if (!ArrayUtils.isEmpty(mIncludedPackages)) { b.putStringArray(KEY_INCLUDED_PACKAGES, mIncludedPackages); } return b; } Loading services/core/java/android/content/pm/PackageManagerInternal.java +5 −1 Original line number Diff line number Diff line Loading @@ -382,10 +382,14 @@ public abstract class PackageManagerInternal { * of the calling UID. * @param forSend true if the invocation is intended for sending broadcasts. The value * of this parameter affects how packages are filtered. * @param includedPackages An optional array of package names. If provided, the results * will be limited to receivers from these packages only. * If {@code null}, receivers from all packages can be included. */ public abstract List<ResolveInfo> queryIntentReceivers( Intent intent, String resolvedType, @PackageManager.ResolveInfoFlagsBits long flags, int filterCallingUid, int callingPid, int userId, boolean forSend); int filterCallingUid, int callingPid, int userId, boolean forSend, @Nullable String[] includedPackages); /** * Retrieve all services that can be performed for the given intent. Loading services/core/java/com/android/server/am/ActivityManagerService.java +2 −1 Original line number Diff line number Diff line Loading @@ -5841,7 +5841,8 @@ public class ActivityManagerService extends IActivityManager.Stub intent, matchFlags, uid, userId)); case ActivityManager.INTENT_SENDER_BROADCAST: return new ParceledListSlice<>(mPackageManagerInt.queryIntentReceivers( intent, resolvedType, matchFlags, uid, Process.INVALID_PID, userId, false)); intent, resolvedType, matchFlags, uid, Process.INVALID_PID, userId, false /* forSend */, null /* includedPackages */)); default: // ActivityManager.INTENT_SENDER_ACTIVITY_RESULT throw new IllegalStateException("Unsupported intent sender type: " + res.key.type); } Loading services/core/java/com/android/server/am/BroadcastController.java +26 −8 Original line number Diff line number Diff line Loading @@ -111,6 +111,7 @@ import android.util.proto.ProtoOutputStream; import com.android.internal.annotations.GuardedBy; import com.android.internal.annotations.VisibleForTesting; import com.android.internal.util.ArrayUtils; import com.android.server.IntentResolver; import com.android.server.LocalManagerRegistry; import com.android.server.LocalServices; Loading Loading @@ -207,8 +208,7 @@ class BroadcastController { * Resolver for broadcast intents to registered receivers. * Holds BroadcastFilter (subclass of IntentFilter). */ final IntentResolver<BroadcastFilter, BroadcastFilter> mReceiverResolver = new IntentResolver<>() { final class BroadcastIntentResolver extends IntentResolver<BroadcastFilter, BroadcastFilter> { @Override protected boolean allowFilterResult( BroadcastFilter filter, List<BroadcastFilter> dest) { Loading Loading @@ -245,7 +245,21 @@ class BroadcastController { protected boolean isPackageForFilter(String packageName, BroadcastFilter filter) { return packageName.equals(filter.packageName); } public List<BroadcastFilter> queryIntent(@NonNull PackageDataSnapshot snapshot, Intent intent, String resolvedType, boolean defaultOnly, @UserIdInt int userId, @Nullable String[] includedPackages) { final List<BroadcastFilter> infos = super.queryIntent(snapshot, intent, resolvedType, defaultOnly, userId); // TODO: b/428262517 - filter out packages that are not in includedPackages close to // intent resolution. if (includedPackages != null) { infos.removeIf(info -> !ArrayUtils.contains(includedPackages, info.packageName)); } return infos; } }; private final BroadcastIntentResolver mReceiverResolver = new BroadcastIntentResolver(); BroadcastController(Context context, ActivityManagerService service, BroadcastQueue queue) { mContext = context; Loading Loading @@ -1509,10 +1523,13 @@ class BroadcastController { // Need to resolve the intent to interested receivers... if ((intent.getFlags() & Intent.FLAG_RECEIVER_REGISTERED_ONLY) == 0) { receivers = collectReceiverComponents( intent, resolvedType, callingUid, callingPid, users, broadcastAllowList); intent, resolvedType, callingUid, callingPid, users, broadcastAllowList, brOptions == null ? null : brOptions.getIncludedPackages()); } if (intent.getComponent() == null) { final PackageDataSnapshot snapshot = mService.getPackageManagerInternal().snapshot(); final String[] includedPackages = brOptions != null ? brOptions.getIncludedPackages() : null; if (userId == UserHandle.USER_ALL && callingUid == SHELL_UID) { // Query one target user at a time, excluding shell-restricted users for (int i = 0; i < users.length; i++) { Loading @@ -1521,8 +1538,8 @@ class BroadcastController { continue; } List<BroadcastFilter> registeredReceiversForUser = mReceiverResolver.queryIntent(snapshot, intent, resolvedType, false /*defaultOnly*/, users[i]); mReceiverResolver.queryIntent(snapshot, intent, resolvedType, false /*defaultOnly*/, users[i], includedPackages); if (registeredReceivers == null) { registeredReceivers = registeredReceiversForUser; } else if (registeredReceiversForUser != null) { Loading @@ -1531,7 +1548,7 @@ class BroadcastController { } } else { registeredReceivers = mReceiverResolver.queryIntent(snapshot, intent, resolvedType, false /*defaultOnly*/, userId); resolvedType, false /*defaultOnly*/, userId, includedPackages); } if (registeredReceivers != null) { SaferIntentUtils.blockNullAction(args, registeredReceivers); Loading Loading @@ -1959,7 +1976,7 @@ class BroadcastController { private List<ResolveInfo> collectReceiverComponents( Intent intent, String resolvedType, int callingUid, int callingPid, int[] users, int[] broadcastAllowList) { int[] users, int[] broadcastAllowList, String[] includedPackages) { // TODO: come back and remove this assumption to triage all broadcasts long pmFlags = STOCK_PM_FLAGS | MATCH_DEBUG_TRIAGED_MISSING; Loading @@ -1974,7 +1991,8 @@ class BroadcastController { continue; } List<ResolveInfo> newReceivers = mService.mPackageManagerInt.queryIntentReceivers( intent, resolvedType, pmFlags, callingUid, callingPid, user, /* forSend */true); intent, resolvedType, pmFlags, callingUid, callingPid, user, /* forSend */ true, includedPackages); if (user != UserHandle.USER_SYSTEM && newReceivers != null) { // If this is not the system user, we need to check for // any receivers that should be filtered out. Loading services/core/java/com/android/server/am/ComponentAliasResolver.java +2 −1 Original line number Diff line number Diff line Loading @@ -481,7 +481,8 @@ public class ComponentAliasResolver { i.setComponent(resolution.getTarget()); List<ResolveInfo> resolved = pmi.queryIntentReceivers( i, resolvedType, packageFlags, callingUid, callingPid, userId, /*forSend*/ true); i, resolvedType, packageFlags, callingUid, callingPid, userId, /* forSend */ true, /* includedPackages */ null); if (resolved == null || resolved.size() == 0) { // Target component not found. Slog.w(TAG, "Alias target " + target.flattenToShortString() + " not found"); Loading Loading
core/java/android/app/BroadcastOptions.java +34 −0 Original line number Diff line number Diff line Loading @@ -40,6 +40,8 @@ import android.os.PowerExemptionManager.ReasonCode; import android.os.PowerExemptionManager.TempAllowListType; import android.os.Process; import com.android.internal.util.ArrayUtils; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.util.Objects; Loading Loading @@ -68,6 +70,7 @@ public class BroadcastOptions extends ComponentOptions { private @Nullable BundleMerger mDeliveryGroupExtrasMerger; private @Nullable IntentFilter mDeliveryGroupMatchingFilter; private @DeferralPolicy int mDeferralPolicy; private @Nullable String[] mIncludedPackages; /** @hide */ @IntDef(flag = true, prefix = { "FLAG_" }, value = { Loading Loading @@ -230,6 +233,12 @@ public class BroadcastOptions extends ComponentOptions { private static final String KEY_DEFERRAL_POLICY = "android:broadcast.deferralPolicy"; /** * Corresponds to {@link #setIncludedPackages(String[])} */ private static final String KEY_INCLUDED_PACKAGES = "android:broadcast.includedPackageNames"; /** * The list of delivery group policies which specify how multiple broadcasts belonging to * the same delivery group has to be handled. Loading Loading @@ -355,6 +364,7 @@ public class BroadcastOptions extends ComponentOptions { mDeliveryGroupMatchingFilter = opts.getParcelable(KEY_DELIVERY_GROUP_MATCHING_FILTER, IntentFilter.class); mDeferralPolicy = opts.getInt(KEY_DEFERRAL_POLICY, DEFERRAL_POLICY_DEFAULT); mIncludedPackages = opts.getStringArray(KEY_INCLUDED_PACKAGES); } /** @hide */ Loading Loading @@ -1112,6 +1122,27 @@ public class BroadcastOptions extends ComponentOptions { return (mFlags & FLAG_DEBUG_LOG) != 0; } /** * Set the list of packages to send the broadcast to. * * @hide */ public BroadcastOptions setIncludedPackages(@Nullable String[] packageNames) { mIncludedPackages = packageNames; return this; } /** * Get the list of packages to send the broadcast to, that was previously set using * {@link #setIncludedPackages(String[])}. * * @hide */ @Nullable public String[] getIncludedPackages() { return mIncludedPackages; } /** * Returns the created options as a Bundle, which can be passed to * {@link android.content.Context#sendBroadcast(android.content.Intent) Loading Loading @@ -1178,6 +1209,9 @@ public class BroadcastOptions extends ComponentOptions { if (mDeferralPolicy != DEFERRAL_POLICY_DEFAULT) { b.putInt(KEY_DEFERRAL_POLICY, mDeferralPolicy); } if (!ArrayUtils.isEmpty(mIncludedPackages)) { b.putStringArray(KEY_INCLUDED_PACKAGES, mIncludedPackages); } return b; } Loading
services/core/java/android/content/pm/PackageManagerInternal.java +5 −1 Original line number Diff line number Diff line Loading @@ -382,10 +382,14 @@ public abstract class PackageManagerInternal { * of the calling UID. * @param forSend true if the invocation is intended for sending broadcasts. The value * of this parameter affects how packages are filtered. * @param includedPackages An optional array of package names. If provided, the results * will be limited to receivers from these packages only. * If {@code null}, receivers from all packages can be included. */ public abstract List<ResolveInfo> queryIntentReceivers( Intent intent, String resolvedType, @PackageManager.ResolveInfoFlagsBits long flags, int filterCallingUid, int callingPid, int userId, boolean forSend); int filterCallingUid, int callingPid, int userId, boolean forSend, @Nullable String[] includedPackages); /** * Retrieve all services that can be performed for the given intent. Loading
services/core/java/com/android/server/am/ActivityManagerService.java +2 −1 Original line number Diff line number Diff line Loading @@ -5841,7 +5841,8 @@ public class ActivityManagerService extends IActivityManager.Stub intent, matchFlags, uid, userId)); case ActivityManager.INTENT_SENDER_BROADCAST: return new ParceledListSlice<>(mPackageManagerInt.queryIntentReceivers( intent, resolvedType, matchFlags, uid, Process.INVALID_PID, userId, false)); intent, resolvedType, matchFlags, uid, Process.INVALID_PID, userId, false /* forSend */, null /* includedPackages */)); default: // ActivityManager.INTENT_SENDER_ACTIVITY_RESULT throw new IllegalStateException("Unsupported intent sender type: " + res.key.type); } Loading
services/core/java/com/android/server/am/BroadcastController.java +26 −8 Original line number Diff line number Diff line Loading @@ -111,6 +111,7 @@ import android.util.proto.ProtoOutputStream; import com.android.internal.annotations.GuardedBy; import com.android.internal.annotations.VisibleForTesting; import com.android.internal.util.ArrayUtils; import com.android.server.IntentResolver; import com.android.server.LocalManagerRegistry; import com.android.server.LocalServices; Loading Loading @@ -207,8 +208,7 @@ class BroadcastController { * Resolver for broadcast intents to registered receivers. * Holds BroadcastFilter (subclass of IntentFilter). */ final IntentResolver<BroadcastFilter, BroadcastFilter> mReceiverResolver = new IntentResolver<>() { final class BroadcastIntentResolver extends IntentResolver<BroadcastFilter, BroadcastFilter> { @Override protected boolean allowFilterResult( BroadcastFilter filter, List<BroadcastFilter> dest) { Loading Loading @@ -245,7 +245,21 @@ class BroadcastController { protected boolean isPackageForFilter(String packageName, BroadcastFilter filter) { return packageName.equals(filter.packageName); } public List<BroadcastFilter> queryIntent(@NonNull PackageDataSnapshot snapshot, Intent intent, String resolvedType, boolean defaultOnly, @UserIdInt int userId, @Nullable String[] includedPackages) { final List<BroadcastFilter> infos = super.queryIntent(snapshot, intent, resolvedType, defaultOnly, userId); // TODO: b/428262517 - filter out packages that are not in includedPackages close to // intent resolution. if (includedPackages != null) { infos.removeIf(info -> !ArrayUtils.contains(includedPackages, info.packageName)); } return infos; } }; private final BroadcastIntentResolver mReceiverResolver = new BroadcastIntentResolver(); BroadcastController(Context context, ActivityManagerService service, BroadcastQueue queue) { mContext = context; Loading Loading @@ -1509,10 +1523,13 @@ class BroadcastController { // Need to resolve the intent to interested receivers... if ((intent.getFlags() & Intent.FLAG_RECEIVER_REGISTERED_ONLY) == 0) { receivers = collectReceiverComponents( intent, resolvedType, callingUid, callingPid, users, broadcastAllowList); intent, resolvedType, callingUid, callingPid, users, broadcastAllowList, brOptions == null ? null : brOptions.getIncludedPackages()); } if (intent.getComponent() == null) { final PackageDataSnapshot snapshot = mService.getPackageManagerInternal().snapshot(); final String[] includedPackages = brOptions != null ? brOptions.getIncludedPackages() : null; if (userId == UserHandle.USER_ALL && callingUid == SHELL_UID) { // Query one target user at a time, excluding shell-restricted users for (int i = 0; i < users.length; i++) { Loading @@ -1521,8 +1538,8 @@ class BroadcastController { continue; } List<BroadcastFilter> registeredReceiversForUser = mReceiverResolver.queryIntent(snapshot, intent, resolvedType, false /*defaultOnly*/, users[i]); mReceiverResolver.queryIntent(snapshot, intent, resolvedType, false /*defaultOnly*/, users[i], includedPackages); if (registeredReceivers == null) { registeredReceivers = registeredReceiversForUser; } else if (registeredReceiversForUser != null) { Loading @@ -1531,7 +1548,7 @@ class BroadcastController { } } else { registeredReceivers = mReceiverResolver.queryIntent(snapshot, intent, resolvedType, false /*defaultOnly*/, userId); resolvedType, false /*defaultOnly*/, userId, includedPackages); } if (registeredReceivers != null) { SaferIntentUtils.blockNullAction(args, registeredReceivers); Loading Loading @@ -1959,7 +1976,7 @@ class BroadcastController { private List<ResolveInfo> collectReceiverComponents( Intent intent, String resolvedType, int callingUid, int callingPid, int[] users, int[] broadcastAllowList) { int[] users, int[] broadcastAllowList, String[] includedPackages) { // TODO: come back and remove this assumption to triage all broadcasts long pmFlags = STOCK_PM_FLAGS | MATCH_DEBUG_TRIAGED_MISSING; Loading @@ -1974,7 +1991,8 @@ class BroadcastController { continue; } List<ResolveInfo> newReceivers = mService.mPackageManagerInt.queryIntentReceivers( intent, resolvedType, pmFlags, callingUid, callingPid, user, /* forSend */true); intent, resolvedType, pmFlags, callingUid, callingPid, user, /* forSend */ true, includedPackages); if (user != UserHandle.USER_SYSTEM && newReceivers != null) { // If this is not the system user, we need to check for // any receivers that should be filtered out. Loading
services/core/java/com/android/server/am/ComponentAliasResolver.java +2 −1 Original line number Diff line number Diff line Loading @@ -481,7 +481,8 @@ public class ComponentAliasResolver { i.setComponent(resolution.getTarget()); List<ResolveInfo> resolved = pmi.queryIntentReceivers( i, resolvedType, packageFlags, callingUid, callingPid, userId, /*forSend*/ true); i, resolvedType, packageFlags, callingUid, callingPid, userId, /* forSend */ true, /* includedPackages */ null); if (resolved == null || resolved.size() == 0) { // Target component not found. Slog.w(TAG, "Alias target " + target.flattenToShortString() + " not found"); Loading