Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 7bdf2dcf authored by Peter Li's avatar Peter Li Committed by Android (Google) Code Review
Browse files

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.
parents d7588243 3ad584f1
Loading
Loading
Loading
Loading
+8 −0
Original line number Diff line number Diff line
@@ -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
}
+12 −0
Original line number Diff line number Diff line
@@ -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. -->
+57 −38
Original line number Diff line number Diff line
@@ -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,7 +291,7 @@ public final class BroadcastHelper {
        return bOptions;
    }

    private void sendPackageChangedBroadcast(@NonNull String packageName,
    private void sendPackageChangedBroadcastInternal(@NonNull String packageName,
            boolean dontKillApp,
            @NonNull ArrayList<String> componentNames,
            int packageUid,
@@ -302,6 +299,21 @@ public final class BroadcastHelper {
            @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,
+13 −12
Original line number Diff line number Diff line
@@ -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 */,
+2 −1
Original line number Diff line number Diff line
@@ -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)