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

Commit 1fafab3b authored by TYM Tsai's avatar TYM Tsai
Browse files

Avoid lambda code to cache computer snapshot

The lambda will automatically retain a reference for use within
the code block. In addition, snapshotComputer() also creates a
new object for the snapshot everytime. If the lambda is called
multiple times and some places keep them for a long time, the
snapshot object becomes huge. It causes OOM in the system_server
process and leads to platform reset.
To avoid the problem, use Supplier instead and then gain snapshot
the supplier.

Bug: 381996338
Flag: EXEMPT bugfix
Test: atest FrameworksMockingServicesTests:com.android.server.pm
Change-Id: I57422392167012905243db0856b6eb5648b56489
parent 8218dda7
Loading
Loading
Loading
Loading
+22 −16
Original line number Diff line number Diff line
@@ -78,6 +78,7 @@ import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.function.BiFunction;
import java.util.function.Supplier;

/**
 * Helper class to send broadcasts for various situations.
@@ -216,7 +217,7 @@ public final class BroadcastHelper {
                filterExtrasForReceiver, bOptions);
    }

    void sendResourcesChangedBroadcast(@NonNull Computer snapshot,
    void sendResourcesChangedBroadcast(@NonNull Supplier<Computer> snapshotSupplier,
                                       boolean mediaStatus,
                                       boolean replacing,
                                       @NonNull String[] pkgNames,
@@ -236,7 +237,7 @@ public final class BroadcastHelper {
                null /* targetPkg */, null /* finishedReceiver */, null /* userIds */,
                null /* instantUserIds */, null /* broadcastAllowList */,
                (callingUid, intentExtras) -> filterExtrasChangedPackageList(
                        snapshot, callingUid, intentExtras),
                        snapshotSupplier, callingUid, intentExtras),
                null /* bOptions */, null /* requiredPermissions */);
    }

@@ -544,7 +545,7 @@ public final class BroadcastHelper {
        });
    }

    void sendPostInstallBroadcasts(@NonNull Computer snapshot,
    void sendPostInstallBroadcasts(@NonNull Supplier<Computer> snapshotSupplier,
                                   @NonNull InstallRequest request,
                                   @NonNull String packageName,
                                   @NonNull String requiredPermissionControllerPackage,
@@ -567,8 +568,8 @@ public final class BroadcastHelper {
                final int[] uids = new int[]{request.getRemovedInfo().mUid};
                notifyResourcesChanged(
                        false /* mediaStatus */, true /* replacing */, pkgNames, uids);
                sendResourcesChangedBroadcast(
                        snapshot, false /* mediaStatus */, true /* replacing */, pkgNames, uids);
                sendResourcesChangedBroadcast(snapshotSupplier,
                        false /* mediaStatus */, true /* replacing */, pkgNames, uids);
            }
            sendPackageRemovedBroadcasts(
                    request.getRemovedInfo(), packageSender, isKillApp, false /*removedBySystem*/,
@@ -608,6 +609,7 @@ public final class BroadcastHelper {
                    null /* broadcastAllowList */, null);
        }

        final Computer snapshot = snapshotSupplier.get();
        // Send installed broadcasts if the package is not a static shared lib.
        if (staticSharedLibraryName == null) {
            // Send PACKAGE_ADDED broadcast for users that see the package for the first time
@@ -732,7 +734,7 @@ public final class BroadcastHelper {
                if (!isArchived) {
                    final String[] pkgNames = new String[]{packageName};
                    final int[] uids = new int[]{request.getPkg().getUid()};
                    sendResourcesChangedBroadcast(snapshot,
                    sendResourcesChangedBroadcast(snapshotSupplier,
                            true /* mediaStatus */, true /* replacing */, pkgNames, uids);
                    notifyResourcesChanged(true /* mediaStatus */,
                            true /* replacing */, pkgNames, uids);
@@ -860,8 +862,8 @@ public final class BroadcastHelper {
     * access all the packages in the extras.
     */
    @Nullable
    private static Bundle filterExtrasChangedPackageList(@NonNull Computer snapshot, int callingUid,
            @NonNull Bundle extras) {
    private static Bundle filterExtrasChangedPackageList(
            @NonNull Supplier<Computer> snapshotSupplier, int callingUid, @NonNull Bundle extras) {
        if (UserHandle.isCore(callingUid)) {
            // see all
            return extras;
@@ -873,6 +875,7 @@ public final class BroadcastHelper {
        final int userId = extras.getInt(
                Intent.EXTRA_USER_HANDLE, UserHandle.getUserId(callingUid));
        final int[] uids = extras.getIntArray(Intent.EXTRA_CHANGED_UID_LIST);
        final Computer snapshot = snapshotSupplier.get();
        final Pair<String[], int[]> filteredPkgs =
                filterPackages(snapshot, pkgs, uids, callingUid, userId);
        if (ArrayUtils.isEmpty(filteredPkgs.first)) {
@@ -952,10 +955,12 @@ public final class BroadcastHelper {
        final int[] instantUserIds = isInstantApp ? new int[] { userId } : EMPTY_INT_ARRAY;
        final SparseArray<int[]> broadcastAllowList =
                isInstantApp ? null : snapshot.getVisibilityAllowLists(packageName, userIds);
        final String[] sharedUserPackages =
                snapshot.getSharedUserPackagesForPackage(packageName, userId);
        mHandler.post(() -> sendPackageChangedBroadcastInternal(
                packageName, dontKillApp, componentNames, packageUid, reason, userIds,
                instantUserIds, broadcastAllowList, setting.getPkg(),
                snapshot.getSharedUserPackagesForPackage(packageName, userId)));
                sharedUserPackages));
        mPackageMonitorCallbackHelper.notifyPackageChanged(packageName, dontKillApp, componentNames,
                packageUid, reason, userIds, instantUserIds, broadcastAllowList, mHandler);
    }
@@ -1120,7 +1125,7 @@ public final class BroadcastHelper {
     * @param uidList The uids of packages which have suspension changes.
     * @param userId The user where packages reside.
     */
    void sendPackagesSuspendedOrUnsuspendedForUser(@NonNull Computer snapshot,
    void sendPackagesSuspendedOrUnsuspendedForUser(@NonNull Supplier<Computer> snapshotSupplier,
                                                   @NonNull String intent,
                                                   @NonNull String[] pkgList,
                                                   @NonNull int[] uidList,
@@ -1138,7 +1143,7 @@ public final class BroadcastHelper {
                .toBundle();
        BiFunction<Integer, Bundle, Bundle> filterExtrasForReceiver =
                (callingUid, intentExtras) -> BroadcastHelper.filterExtrasChangedPackageList(
                        snapshot, callingUid, intentExtras);
                        snapshotSupplier, callingUid, intentExtras);
        mHandler.post(() -> sendPackageBroadcast(intent, null /* pkg */,
                extras, flags, null /* targetPkg */, null /* finishedReceiver */,
                new int[]{userId}, null /* instantUserIds */, null /* broadcastAllowList */,
@@ -1148,7 +1153,7 @@ public final class BroadcastHelper {
                null /* instantUserIds */, null /* broadcastAllowList */, filterExtrasForReceiver);
    }

    void sendMyPackageSuspendedOrUnsuspended(@NonNull Computer snapshot,
    void sendMyPackageSuspendedOrUnsuspended(@NonNull Supplier<Computer> snapshotSupplier,
                                             @NonNull String[] affectedPackages,
                                             boolean suspended,
                                             int userId) {
@@ -1163,6 +1168,7 @@ public final class BroadcastHelper {
                return;
            }
            final int[] targetUserIds = new int[] {userId};
            final Computer snapshot = snapshotSupplier.get();
            for (String packageName : affectedPackages) {
                final Bundle appExtras = suspended
                        ? SuspendPackageHelper.getSuspendedPackageAppExtras(
@@ -1192,7 +1198,7 @@ public final class BroadcastHelper {
     * @param uidList The uids of packages which have suspension changes.
     * @param userId The user where packages reside.
     */
    void sendDistractingPackagesChanged(@NonNull Computer snapshot,
    void sendDistractingPackagesChanged(@NonNull Supplier<Computer> snapshotSupplier,
                                        @NonNull String[] pkgList,
                                        @NonNull int[] uidList,
                                        int userId,
@@ -1208,11 +1214,11 @@ public final class BroadcastHelper {
                null /* finishedReceiver */, new int[]{userId}, null /* instantUserIds */,
                null /* broadcastAllowList */,
                (callingUid, intentExtras) -> filterExtrasChangedPackageList(
                        snapshot, callingUid, intentExtras),
                        snapshotSupplier, callingUid, intentExtras),
                null /* bOptions */, null /* requiredPermissions */));
    }

    void sendResourcesChangedBroadcastAndNotify(@NonNull Computer snapshot,
    void sendResourcesChangedBroadcastAndNotify(@NonNull Supplier<Computer> snapshotSupplier,
                                                boolean mediaStatus,
                                                boolean replacing,
                                                @NonNull ArrayList<AndroidPackage> packages) {
@@ -1224,7 +1230,7 @@ public final class BroadcastHelper {
            packageNames[i] = pkg.getPackageName();
            packageUids[i] = pkg.getUid();
        }
        sendResourcesChangedBroadcast(snapshot, mediaStatus,
        sendResourcesChangedBroadcast(snapshotSupplier, mediaStatus,
                replacing, packageNames, packageUids);
        notifyResourcesChanged(mediaStatus, replacing, packageNames, packageUids);
    }
+2 −2
Original line number Diff line number Diff line
@@ -123,7 +123,7 @@ public final class DistractingPackageHelper {
        if (!changedPackagesList.isEmpty()) {
            final String[] changedPackages = changedPackagesList.toArray(
                    new String[changedPackagesList.size()]);
            mBroadcastHelper.sendDistractingPackagesChanged(mPm.snapshotComputer(),
            mBroadcastHelper.sendDistractingPackagesChanged(mPm::snapshotComputer,
                    changedPackages, changedUids.toArray(), userId, restrictionFlags);
            mPm.scheduleWritePackageRestrictions(userId);
        }
@@ -198,7 +198,7 @@ public final class DistractingPackageHelper {
        if (!changedPackages.isEmpty()) {
            final String[] packageArray = changedPackages.toArray(
                    new String[changedPackages.size()]);
            mBroadcastHelper.sendDistractingPackagesChanged(mPm.snapshotComputer(),
            mBroadcastHelper.sendDistractingPackagesChanged(mPm::snapshotComputer,
                    packageArray, changedUids.toArray(), userId, RESTRICTION_NONE);
            mPm.scheduleWritePackageRestrictions(userId);
        }
+1 −1
Original line number Diff line number Diff line
@@ -3084,7 +3084,7 @@ final class InstallPackageHelper {
                mPm.mProcessLoggingHandler.invalidateBaseApkHash(request.getPkg().getBaseApkPath());
            }

            mBroadcastHelper.sendPostInstallBroadcasts(mPm.snapshotComputer(), request, packageName,
            mBroadcastHelper.sendPostInstallBroadcasts(mPm::snapshotComputer, request, packageName,
                    mPm.mRequiredPermissionControllerPackage, mPm.mRequiredVerifierPackages,
                    mPm.mRequiredInstallerPackage,
                    /* packageSender= */ mPm, launchedForRestore, killApp, update, archived);
+2 −2
Original line number Diff line number Diff line
@@ -227,7 +227,7 @@ public final class StorageEventHelper extends StorageEventListener {
        }

        if (DEBUG_INSTALL) Slog.d(TAG, "Loaded packages " + loaded);
        mBroadcastHelper.sendResourcesChangedBroadcastAndNotify(mPm.snapshotComputer(),
        mBroadcastHelper.sendResourcesChangedBroadcastAndNotify(mPm::snapshotComputer,
                true /* mediaStatus */, false /* replacing */, loaded);
        synchronized (mLoadedVolumes) {
            mLoadedVolumes.add(vol.getId());
@@ -279,7 +279,7 @@ public final class StorageEventHelper extends StorageEventListener {
        }

        if (DEBUG_INSTALL) Slog.d(TAG, "Unloaded packages " + unloaded);
        mBroadcastHelper.sendResourcesChangedBroadcastAndNotify(mPm.snapshotComputer(),
        mBroadcastHelper.sendResourcesChangedBroadcastAndNotify(mPm::snapshotComputer,
                false /* mediaStatus */, false /* replacing */, unloaded);
        synchronized (mLoadedVolumes) {
            mLoadedVolumes.remove(vol.getId());
+7 −9
Original line number Diff line number Diff line
@@ -192,21 +192,20 @@ public final class SuspendPackageHelper {
            }
        });

        final Computer newSnapshot = mPm.snapshotComputer();
        if (!notifyPackagesList.isEmpty()) {
            final String[] changedPackages =
                    notifyPackagesList.toArray(new String[0]);
            mBroadcastHelper.sendPackagesSuspendedOrUnsuspendedForUser(newSnapshot,
            mBroadcastHelper.sendPackagesSuspendedOrUnsuspendedForUser(mPm::snapshotComputer,
                    suspended ? Intent.ACTION_PACKAGES_SUSPENDED
                            : Intent.ACTION_PACKAGES_UNSUSPENDED,
                    changedPackages, notifyUids.toArray(), quarantined, targetUserId);
            mBroadcastHelper.sendMyPackageSuspendedOrUnsuspended(newSnapshot, changedPackages,
                    suspended, targetUserId);
            mBroadcastHelper.sendMyPackageSuspendedOrUnsuspended(mPm::snapshotComputer,
                    changedPackages, suspended, targetUserId);
            mPm.scheduleWritePackageRestrictions(targetUserId);
        }
        // Send the suspension changed broadcast to ensure suspension state is not stale.
        if (!changedPackagesList.isEmpty()) {
            mBroadcastHelper.sendPackagesSuspendedOrUnsuspendedForUser(newSnapshot,
            mBroadcastHelper.sendPackagesSuspendedOrUnsuspendedForUser(mPm::snapshotComputer,
                    Intent.ACTION_PACKAGES_SUSPENSION_CHANGED,
                    changedPackagesList.toArray(new String[0]), changedUids.toArray(), quarantined,
                    targetUserId);
@@ -343,13 +342,12 @@ public final class SuspendPackageHelper {
        });

        mPm.scheduleWritePackageRestrictions(targetUserId);
        final Computer newSnapshot = mPm.snapshotComputer();
        if (!unsuspendedPackages.isEmpty()) {
            final String[] packageArray = unsuspendedPackages.toArray(
                    new String[unsuspendedPackages.size()]);
            mBroadcastHelper.sendMyPackageSuspendedOrUnsuspended(newSnapshot, packageArray,
                    false, targetUserId);
            mBroadcastHelper.sendPackagesSuspendedOrUnsuspendedForUser(newSnapshot,
            mBroadcastHelper.sendMyPackageSuspendedOrUnsuspended(mPm::snapshotComputer,
                    packageArray, false, targetUserId);
            mBroadcastHelper.sendPackagesSuspendedOrUnsuspendedForUser(mPm::snapshotComputer,
                    Intent.ACTION_PACKAGES_UNSUSPENDED,
                    packageArray, unsuspendedUids.toArray(), false, targetUserId);
        }
Loading