diff options
| author | 2024-10-17 07:18:09 +0000 | |
|---|---|---|
| committer | 2024-10-17 07:18:09 +0000 | |
| commit | 7bdf2dcfa42e0892713f6066cdbde491c8791fea (patch) | |
| tree | 56231bc1d28222f9d483136d3726085f30bbf1dd | |
| parent | d7588243196f80fe78357dafd826976a42702ed8 (diff) | |
| parent | 3ad584f1e6da48cc5971c5fda9c15698f4b0b8c8 (diff) | |
Merge changes from topic "reduce_broadcast_intent" into main
* changes:
Add a new feature flag and a new permission
Refactor BroadcastHelper to pass requiredPermissions parameter.
5 files changed, 92 insertions, 51 deletions
diff --git a/core/java/android/content/pm/flags.aconfig b/core/java/android/content/pm/flags.aconfig index 52d733314eb6..5b38942d468d 100644 --- a/core/java/android/content/pm/flags.aconfig +++ b/core/java/android/content/pm/flags.aconfig @@ -334,3 +334,11 @@ flag { bug: "364771256" is_fixed_read_only: true } + +flag { + name: "reduce_broadcasts_for_component_state_changes" + namespace: "package_manager_service" + description: "Feature flag to limit sending of the PACKAGE_CHANGED broadcast to only the system and the application itself during component state changes." + bug: "292261144" + is_fixed_read_only: true +} diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml index 5693d666adc2..5522aa09a32e 100644 --- a/core/res/AndroidManifest.xml +++ b/core/res/AndroidManifest.xml @@ -8479,6 +8479,18 @@ android:protectionLevel="internal" android:featureFlag="android.content.pm.verification_service" /> + <!-- + This permission allows the system to receive PACKAGE_CHANGED broadcasts when the component + state of a non-exported component has been changed. + <p>Not for use by third-party applications. </p> + <p>Protection level: internal + @hide + --> + <permission + android:name="android.permission.RECEIVE_PACKAGE_CHANGED_BROADCAST_ON_COMPONENT_STATE_CHANGED" + android:protectionLevel="internal" + android:featureFlag="android.content.pm.reduce_broadcasts_for_component_state_changes"/> + <!-- Attribution for Geofencing service. --> <attribution android:tag="GeofencingService" android:label="@string/geofencing_service"/> <!-- Attribution for Country Detector. --> diff --git a/services/core/java/com/android/server/pm/BroadcastHelper.java b/services/core/java/com/android/server/pm/BroadcastHelper.java index 369029adac59..84a5f2b0e8bc 100644 --- a/services/core/java/com/android/server/pm/BroadcastHelper.java +++ b/services/core/java/com/android/server/pm/BroadcastHelper.java @@ -80,11 +80,6 @@ import java.util.function.BiFunction; */ public final class BroadcastHelper { private static final boolean DEBUG_BROADCASTS = false; - /** - * Permissions required in order to receive instant application lifecycle broadcasts. - */ - private static final String[] INSTANT_APP_BROADCAST_PERMISSION = - new String[]{android.Manifest.permission.ACCESS_INSTANT_APPS}; private final UserManagerInternal mUmInternal; private final ActivityManagerInternal mAmInternal; @@ -115,7 +110,7 @@ public final class BroadcastHelper { SparseArray<int[]> broadcastAllowList = new SparseArray<>(); broadcastAllowList.put(userId, visibilityAllowList); broadcastIntent(intent, finishedReceiver, isInstantApp, userId, broadcastAllowList, - filterExtrasForReceiver, bOptions); + filterExtrasForReceiver, bOptions, null /* requiredPermissions */); } void sendPackageBroadcast(final String action, final String pkg, final Bundle extras, @@ -123,7 +118,7 @@ public final class BroadcastHelper { final int[] userIds, int[] instantUserIds, @Nullable SparseArray<int[]> broadcastAllowList, @Nullable BiFunction<Integer, Bundle, Bundle> filterExtrasForReceiver, - @Nullable Bundle bOptions) { + @Nullable Bundle bOptions, @Nullable String[] requiredPermissions) { try { final IActivityManager am = ActivityManager.getService(); if (am == null) return; @@ -137,12 +132,12 @@ public final class BroadcastHelper { if (ArrayUtils.isEmpty(instantUserIds)) { doSendBroadcast(action, pkg, extras, flags, targetPkg, finishedReceiver, resolvedUserIds, false /* isInstantApp */, broadcastAllowList, - filterExtrasForReceiver, bOptions); + filterExtrasForReceiver, bOptions, requiredPermissions); } else { // send restricted broadcasts for instant apps doSendBroadcast(action, pkg, extras, flags, targetPkg, finishedReceiver, - instantUserIds, true /* isInstantApp */, null, - null /* filterExtrasForReceiver */, bOptions); + instantUserIds, true /* isInstantApp */, null /* broadcastAllowList */, + null /* filterExtrasForReceiver */, bOptions, requiredPermissions); } } catch (RemoteException ex) { } @@ -166,7 +161,8 @@ public final class BroadcastHelper { boolean isInstantApp, @Nullable SparseArray<int[]> broadcastAllowList, @Nullable BiFunction<Integer, Bundle, Bundle> filterExtrasForReceiver, - @Nullable Bundle bOptions) { + @Nullable Bundle bOptions, + @Nullable String[] requiredPermissions) { for (int userId : userIds) { final Intent intent = new Intent(action, pkg != null ? Uri.fromParts(PACKAGE_SCHEME, pkg, null) : null); @@ -189,17 +185,18 @@ public final class BroadcastHelper { intent.putExtra(Intent.EXTRA_USER_HANDLE, userId); intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT | flags); broadcastIntent(intent, finishedReceiver, isInstantApp, userId, broadcastAllowList, - filterExtrasForReceiver, bOptions); + filterExtrasForReceiver, bOptions, requiredPermissions); } } - private void broadcastIntent(Intent intent, IIntentReceiver finishedReceiver, boolean isInstantApp, int userId, @Nullable SparseArray<int[]> broadcastAllowList, @Nullable BiFunction<Integer, Bundle, Bundle> filterExtrasForReceiver, - @Nullable Bundle bOptions) { - final String[] requiredPermissions = - isInstantApp ? INSTANT_APP_BROADCAST_PERMISSION : null; + @Nullable Bundle bOptions, @Nullable String[] requiredPermissions) { + if (isInstantApp) { + requiredPermissions = ArrayUtils.appendElement(String.class, requiredPermissions, + android.Manifest.permission.ACCESS_INSTANT_APPS); + } if (DEBUG_BROADCASTS) { RuntimeException here = new RuntimeException("here"); here.fillInStackTrace(); @@ -234,7 +231,7 @@ public final class BroadcastHelper { null /* instantUserIds */, null /* broadcastAllowList */, (callingUid, intentExtras) -> filterExtrasChangedPackageList( snapshot, callingUid, intentExtras), - null /* bOptions */); + null /* bOptions */, null /* requiredPermissions */); } /** @@ -294,14 +291,29 @@ public final class BroadcastHelper { return bOptions; } - private void sendPackageChangedBroadcast(@NonNull String packageName, - boolean dontKillApp, - @NonNull ArrayList<String> componentNames, - int packageUid, - @Nullable String reason, - @Nullable int[] userIds, - @Nullable int[] instantUserIds, - @Nullable SparseArray<int[]> broadcastAllowList) { + private void sendPackageChangedBroadcastInternal(@NonNull String packageName, + boolean dontKillApp, + @NonNull ArrayList<String> componentNames, + int packageUid, + @Nullable String reason, + @Nullable int[] userIds, + @Nullable int[] instantUserIds, + @Nullable SparseArray<int[]> broadcastAllowList) { + sendPackageChangedBroadcastWithPermissions(packageName, dontKillApp, componentNames, + packageUid, reason, userIds, instantUserIds, broadcastAllowList, + null /* targetPackageName */, null /* requiredPermissions */); + } + + private void sendPackageChangedBroadcastWithPermissions(@NonNull String packageName, + boolean dontKillApp, + @NonNull ArrayList<String> componentNames, + int packageUid, + @Nullable String reason, + @Nullable int[] userIds, + @Nullable int[] instantUserIds, + @Nullable SparseArray<int[]> broadcastAllowList, + @Nullable String targetPackageName, + @Nullable String[] requiredPermissions) { if (DEBUG_INSTALL) { Log.v(TAG, "Sending package changed: package=" + packageName + " components=" + componentNames); @@ -321,9 +333,10 @@ public final class BroadcastHelper { // little component state change. final int flags = !componentNames.contains(packageName) ? Intent.FLAG_RECEIVER_REGISTERED_ONLY : 0; - sendPackageBroadcast(Intent.ACTION_PACKAGE_CHANGED, packageName, extras, flags, null, null, - userIds, instantUserIds, broadcastAllowList, null /* filterExtrasForReceiver */, - null /* bOptions */); + sendPackageBroadcast(Intent.ACTION_PACKAGE_CHANGED, packageName, extras, flags, + targetPackageName, null /* finishedReceiver */, userIds, instantUserIds, + broadcastAllowList, null /* filterExtrasForReceiver */, null /* bOptions */, + requiredPermissions); } static void sendDeviceCustomizationReadyBroadcast() { @@ -680,7 +693,8 @@ public final class BroadcastHelper { sendPackageBroadcast(Intent.ACTION_PACKAGE_ADDED, packageName, extras, 0, null, null, userIds, instantUserIds, - broadcastAllowlist, null /* filterExtrasForReceiver */, null); + broadcastAllowlist, null /* filterExtrasForReceiver */, null /* bOptions */, + null /* requiredPermissions */); // Send to PermissionController for all new users, even if it may not be running for some // users if (isPrivacySafetyLabelChangeNotificationsEnabled(mContext)) { @@ -688,7 +702,8 @@ public final class BroadcastHelper { packageName, extras, 0, mContext.getPackageManager().getPermissionControllerPackageName(), null, userIds, instantUserIds, - broadcastAllowlist, null /* filterExtrasForReceiver */, null); + broadcastAllowlist, null /* filterExtrasForReceiver */, null /* bOptions */, + null /* requiredPermissions */); } } @@ -719,7 +734,8 @@ public final class BroadcastHelper { int[] userIds, int[] instantUserIds) { sendPackageBroadcast(Intent.ACTION_PACKAGE_FIRST_LAUNCH, pkgName, null, 0, installerPkg, null, userIds, instantUserIds, null /* broadcastAllowList */, - null /* filterExtrasForReceiver */, null); + null /* filterExtrasForReceiver */, null /* bOptions */, + null /* requiredPermissions */); } /** @@ -824,7 +840,7 @@ public final class BroadcastHelper { final int[] instantUserIds = isInstantApp ? new int[] { userId } : EMPTY_INT_ARRAY; final SparseArray<int[]> broadcastAllowList = isInstantApp ? null : snapshot.getVisibilityAllowLists(packageName, userIds); - mHandler.post(() -> sendPackageChangedBroadcast( + mHandler.post(() -> sendPackageChangedBroadcastInternal( packageName, dontKillApp, componentNames, packageUid, reason, userIds, instantUserIds, broadcastAllowList)); mPackageMonitorCallbackHelper.notifyPackageChanged(packageName, dontKillApp, componentNames, @@ -843,7 +859,7 @@ public final class BroadcastHelper { @Nullable Bundle bOptions) { mHandler.post(() -> sendPackageBroadcast(action, pkg, extras, flags, targetPkg, finishedReceiver, userIds, instantUserIds, broadcastAllowList, - null /* filterExtrasForReceiver */, bOptions)); + null /* filterExtrasForReceiver */, bOptions, null /* requiredPermissions */)); if (targetPkg == null) { // For some broadcast action, e.g. ACTION_PACKAGE_ADDED, this method will be called // many times to different targets, e.g. installer app, permission controller, other @@ -1014,7 +1030,7 @@ public final class BroadcastHelper { extras, flags, null /* targetPkg */, null /* finishedReceiver */, new int[]{userId}, null /* instantUserIds */, null /* broadcastAllowList */, filterExtrasForReceiver, - options)); + options, null /* requiredPermissions */)); notifyPackageMonitor(intent, null /* pkg */, extras, new int[]{userId}, null /* instantUserIds */, null /* broadcastAllowList */, filterExtrasForReceiver); } @@ -1046,9 +1062,12 @@ public final class BroadcastHelper { } else { intentExtras = null; } - doSendBroadcast(action, null, intentExtras, - Intent.FLAG_RECEIVER_INCLUDE_BACKGROUND, packageName, null, - targetUserIds, false, null, null, null); + doSendBroadcast(action, null /* pkg */, intentExtras, + Intent.FLAG_RECEIVER_INCLUDE_BACKGROUND, packageName, + null /* finishedReceiver */, + targetUserIds, false /* isInstantApp */, null /* broadcastAllowList */, + null /* filterExtrasForReceiver */, null /* bOptions */, + null /* requiredPermissions */); } }); } @@ -1077,7 +1096,7 @@ public final class BroadcastHelper { null /* broadcastAllowList */, (callingUid, intentExtras) -> filterExtrasChangedPackageList( snapshot, callingUid, intentExtras), - null /* bOptions */)); + null /* bOptions */, null /* requiredPermissions */)); } void sendResourcesChangedBroadcastAndNotify(@NonNull Computer snapshot, diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java index 455776993c56..d78f12217271 100644 --- a/services/core/java/com/android/server/pm/PackageManagerService.java +++ b/services/core/java/com/android/server/pm/PackageManagerService.java @@ -4709,10 +4709,11 @@ public class PackageManagerService implements PackageSender, TestUtilityService extras.putLong(Intent.EXTRA_TIME, SystemClock.elapsedRealtime()); mHandler.post(() -> { mBroadcastHelper.sendPackageBroadcast(Intent.ACTION_PACKAGE_UNSTOPPED, - packageName, extras, - Intent.FLAG_RECEIVER_REGISTERED_ONLY, null, null, - userIds, null, broadcastAllowList, null, - null); + packageName, extras, Intent.FLAG_RECEIVER_REGISTERED_ONLY, + null /* targetPkg */, null /* finishedReceiver */, userIds, + null /* instantUserIds */, broadcastAllowList, + null /* filterExtrasForReceiver */, null /* bOptions */, + null /* requiredPermissions */); }); mPackageMonitorCallbackHelper.notifyPackageMonitor(Intent.ACTION_PACKAGE_UNSTOPPED, packageName, extras, userIds, null /* instantUserIds */, @@ -7169,17 +7170,17 @@ public class PackageManagerService implements PackageSender, TestUtilityService // Sent async using the PM handler, to maintain ordering with PACKAGE_UNSTOPPED mHandler.post(() -> { mBroadcastHelper.sendPackageBroadcast(Intent.ACTION_PACKAGE_RESTARTED, - packageName, extras, - flags, null, null, - userIds, null, broadcastAllowList, null, - null); + packageName, extras, flags, null /* targetPkg */, + null /* finishedReceiver */, userIds, null /* instantUserIds */, + broadcastAllowList, null /* filterExtrasForReceiver */, + null /* bOptions */, null /* requiredPermissions */); }); } else { mBroadcastHelper.sendPackageBroadcast(Intent.ACTION_PACKAGE_RESTARTED, - packageName, extras, - flags, null, null, - userIds, null, broadcastAllowList, null, - null); + packageName, extras, flags, null /* targetPkg */, + null /* finishedReceiver */, userIds, null /* instantUserIds */, + broadcastAllowList, null /* filterExtrasForReceiver */, null /* bOptions */, + null /* requiredPermissions */); } mPackageMonitorCallbackHelper.notifyPackageMonitor(Intent.ACTION_PACKAGE_RESTARTED, packageName, extras, userIds, null /* instantUserIds */, diff --git a/services/tests/mockingservicestests/src/com/android/server/pm/DistractingPackageHelperTest.kt b/services/tests/mockingservicestests/src/com/android/server/pm/DistractingPackageHelperTest.kt index e131a98b52d0..de029e0d770f 100644 --- a/services/tests/mockingservicestests/src/com/android/server/pm/DistractingPackageHelperTest.kt +++ b/services/tests/mockingservicestests/src/com/android/server/pm/DistractingPackageHelperTest.kt @@ -185,7 +185,8 @@ class DistractingPackageHelperTest : PackageHelperTestBase() { verify(pms, never()).scheduleWritePackageRestrictions(eq(TEST_USER_ID)) verify(broadcastHelper, never()).sendPackageBroadcast(eq( Intent.ACTION_DISTRACTING_PACKAGES_CHANGED), nullable(), nullable(), anyInt(), - nullable(), nullable(), any(), nullable(), nullable(), nullable(), nullable()) + nullable(), nullable(), any(), nullable(), nullable(), nullable(), nullable(), + nullable()) distractingPackageHelper.removeDistractingPackageRestrictions(pms.snapshotComputer(), arrayOfNulls(0), TEST_USER_ID) |