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

Commit 4dfa9616 authored by Alex Buynytskyy's avatar Alex Buynytskyy Committed by Android (Google) Code Review
Browse files

Merge "Set AndroidPackage to null for archived installs." into main

parents e5127ca4 d0db470f
Loading
Loading
Loading
Loading
+80 −84
Original line number Diff line number Diff line
@@ -17,6 +17,7 @@
package com.android.server.pm;

import static android.os.Trace.TRACE_TAG_PACKAGE_MANAGER;

import static com.android.server.pm.PackageManagerService.TAG;
import static com.android.server.pm.PackageManagerServiceUtils.getPackageManagerLocal;
import static com.android.server.pm.PackageManagerServiceUtils.logCriticalInfo;
@@ -49,7 +50,6 @@ import com.android.server.pm.Installer.LegacyDexoptDisabledException;
import com.android.server.pm.dex.ArtManagerService;
import com.android.server.pm.parsing.pkg.AndroidPackageUtils;
import com.android.server.pm.pkg.AndroidPackage;
import com.android.server.pm.pkg.PackageState;
import com.android.server.pm.pkg.PackageStateInternal;
import com.android.server.pm.pkg.SELinuxUtil;

@@ -93,25 +93,27 @@ public class AppDataHelper {
     */
    @GuardedBy("mPm.mInstallLock")
    public void prepareAppDataAfterInstallLIF(AndroidPackage pkg) {
        prepareAppDataPostCommitLIF(pkg, 0 /* previousAppId */);
        final PackageSetting ps;
        synchronized (mPm.mLock) {
            ps = mPm.mSettings.getPackageLPr(pkg.getPackageName());
        }
        prepareAppDataPostCommitLIF(ps, 0 /* previousAppId */);
    }

    /**
     * For more details about data verification and previousAppId, check
     * {@link #prepareAppData(Installer.Batch, AndroidPackage, int, int, int)}
     * @see #prepareAppDataAfterInstallLIF(AndroidPackage)
     * {@link #prepareAppData}
     * @see #prepareAppDataAfterInstallLIF
     */
    @GuardedBy("mPm.mInstallLock")
    public void prepareAppDataPostCommitLIF(AndroidPackage pkg, int previousAppId) {
        final PackageSetting ps;
    public void prepareAppDataPostCommitLIF(PackageSetting ps, int previousAppId) {
        synchronized (mPm.mLock) {
            ps = mPm.mSettings.getPackageLPr(pkg.getPackageName());
            mPm.mSettings.writeKernelMappingLPr(ps);
        }

        // TODO(b/211761016): should we still create the profile dirs?
        if (!shouldHaveAppStorage(pkg)) {
            Slog.w(TAG, "Skipping preparing app data for " + pkg.getPackageName());
        if (ps.getPkg() != null && !shouldHaveAppStorage(ps.getPkg())) {
            Slog.w(TAG, "Skipping preparing app data for " + ps.getPackageName());
            return;
        }

@@ -132,15 +134,15 @@ public class AppDataHelper {

            if (ps.getInstalled(user.id)) {
                // TODO: when user data is locked, mark that we're still dirty
                prepareAppData(batch, pkg, previousAppId, user.id, flags).thenRun(() -> {
                prepareAppData(batch, ps, previousAppId, user.id, flags).thenRun(() -> {
                    // Note: this code block is executed with the Installer lock
                    // already held, since it's invoked as a side-effect of
                    // executeBatchLI()
                    if (umInternal.isUserUnlockingOrUnlocked(user.id)) {
                        // Prepare app data on external storage; currently this is used to
                        // setup any OBB dirs that were created by the installer correctly.
                        int uid = UserHandle.getUid(user.id, UserHandle.getAppId(pkg.getUid()));
                        smInternal.prepareAppDataAfterInstall(pkg.getPackageName(), uid);
                        int uid = UserHandle.getUid(user.id, ps.getAppId());
                        smInternal.prepareAppDataAfterInstall(ps.getPackageName(), uid);
                    }
                });
            }
@@ -156,73 +158,70 @@ public class AppDataHelper {
        }
    }

    /**
     * Prepare app data for the given app.
     * <p>
     * Verifies that directories exist and that ownership and labeling is
     * correct for all installed apps. If there is an ownership mismatch:
     * <ul>
     * <li>If previousAppId < 0, app data will be migrated to the new app ID
     * <li>If previousAppId == 0, no migration will happen and data will be wiped and recreated
     * <li>If previousAppId > 0, app data owned by previousAppId will be migrated to the new app ID
     * </ul>
     */
    private @NonNull CompletableFuture<?> prepareAppData(@NonNull Installer.Batch batch,
            @Nullable AndroidPackage pkg, int previousAppId, int userId,
            @StorageManager.StorageFlags int flags) {
    private void prepareAppDataAndMigrate(@NonNull Installer.Batch batch,
            @NonNull AndroidPackage pkg, @UserIdInt int userId,
            @StorageManager.StorageFlags int flags, boolean maybeMigrateAppData) {
        if (pkg == null) {
            Slog.wtf(TAG, "Package was null!", new Throwable());
            return CompletableFuture.completedFuture(null);
            return;
        }
        if (!shouldHaveAppStorage(pkg)) {
            Slog.w(TAG, "Skipping preparing app data for " + pkg.getPackageName());
            return CompletableFuture.completedFuture(null);
            return;
        }
        return prepareAppDataLeaf(batch, pkg, previousAppId, userId, flags);
        final PackageSetting ps;
        synchronized (mPm.mLock) {
            ps = mPm.mSettings.getPackageLPr(pkg.getPackageName());
        }

    private void prepareAppDataAndMigrate(@NonNull Installer.Batch batch,
            @NonNull PackageState packageState, @NonNull AndroidPackage pkg, @UserIdInt int userId,
            @StorageManager.StorageFlags int flags, boolean maybeMigrateAppData) {
        prepareAppData(batch, pkg, Process.INVALID_UID, userId, flags).thenRun(() -> {
        prepareAppData(batch, ps, Process.INVALID_UID, userId, flags).thenRun(() -> {
            // Note: this code block is executed with the Installer lock
            // already held, since it's invoked as a side-effect of
            // executeBatchLI()
            if (maybeMigrateAppData && maybeMigrateAppDataLIF(packageState, pkg, userId)) {
            if (maybeMigrateAppData && maybeMigrateAppDataLIF(ps, userId)) {
                // We may have just shuffled around app data directories, so
                // prepare them one more time
                final Installer.Batch batchInner = new Installer.Batch();
                prepareAppData(batchInner, pkg, Process.INVALID_UID, userId, flags);
                prepareAppData(batchInner, ps, Process.INVALID_UID, userId, flags);
                executeBatchLI(batchInner);
            }
        });
    }

    private @NonNull CompletableFuture<?> prepareAppDataLeaf(@NonNull Installer.Batch batch,
            @NonNull AndroidPackage pkg, int previousAppId, int userId, int flags) {
    /**
     * Prepare app data for the given app.
     * <p>
     * Verifies that directories exist and that ownership and labeling is
     * correct for all installed apps. If there is an ownership mismatch:
     * <ul>
     * <li>If previousAppId < 0, app data will be migrated to the new app ID
     * <li>If previousAppId == 0, no migration will happen and data will be wiped and recreated
     * <li>If previousAppId > 0, app data owned by previousAppId will be migrated to the new app ID
     * </ul>
     */
    private @NonNull CompletableFuture<?> prepareAppData(@NonNull Installer.Batch batch,
            @NonNull PackageSetting ps, int previousAppId, int userId, int flags) {
        final String packageName = ps.getPackageName();

        if (DEBUG_APP_DATA) {
            Slog.v(TAG, "prepareAppData for " + pkg.getPackageName() + " u" + userId + " 0x"
            Slog.v(TAG, "prepareAppData for " + packageName + " u" + userId + " 0x"
                    + Integer.toHexString(flags));
        }

        final PackageSetting ps;
        final String seInfoUser;
        synchronized (mPm.mLock) {
            ps = mPm.mSettings.getPackageLPr(pkg.getPackageName());
            seInfoUser = SELinuxUtil.getSeinfoUser(ps.readUserState(userId));
        }
        final String volumeUuid = pkg.getVolumeUuid();
        final String packageName = pkg.getPackageName();

        final int appId = UserHandle.getAppId(pkg.getUid());
        final AndroidPackage pkg = ps.getPkg();
        final String volumeUuid = ps.getVolumeUuid();
        final int appId = ps.getAppId();

        String pkgSeInfo = ps.getSeInfo();

        Preconditions.checkNotNull(pkgSeInfo);

        final String seInfo = pkgSeInfo + seInfoUser;
        final int targetSdkVersion = pkg.getTargetSdkVersion();
        final boolean usesSdk = !pkg.getUsesSdkLibraries().isEmpty();
        final int targetSdkVersion = ps.getTargetSdkVersion();
        final boolean usesSdk = ps.getUsesSdkLibraries().length > 0;
        final CreateAppDataArgs args = Installer.buildCreateAppDataArgs(volumeUuid, packageName,
                userId, flags, appId, seInfo, targetSdkVersion, usesSdk);
        args.previousAppId = previousAppId;
@@ -234,7 +233,7 @@ public class AppDataHelper {
            if (e != null) {
                logCriticalInfo(Log.WARN, "Failed to create app data for " + packageName
                        + ", but trying to recover: " + e);
                destroyAppDataLeafLIF(pkg, userId, flags);
                destroyAppDataLeafLIF(packageName, volumeUuid, userId, flags);
                try {
                    createAppDataResult = mInstaller.createAppData(args);
                    logCriticalInfo(Log.DEBUG, "Recovery succeeded!");
@@ -267,8 +266,8 @@ public class AppDataHelper {
                // #performDexOptUpgrade. When we do that we should have a
                // more granular check here and only update the existing
                // profiles.
                if (mPm.isDeviceUpgrading() || mPm.isFirstBoot()
                        || (userId != UserHandle.USER_SYSTEM)) {
                if (pkg != null && (mPm.isDeviceUpgrading() || mPm.isFirstBoot()
                        || (userId != UserHandle.USER_SYSTEM))) {
                    try {
                        mArtManagerService.prepareAppProfiles(pkg, userId,
                                /* updateReferenceProfileContent= */ false);
@@ -292,7 +291,9 @@ public class AppDataHelper {
                }
            }

            if (pkg != null) {
                prepareAppDataContentsLeafLIF(pkg, ps, userId, flags);
            }
        });
    }

@@ -336,18 +337,17 @@ public class AppDataHelper {
     * CE/DE data to match the {@code defaultToDeviceProtectedStorage} flag
     * requested by the app.
     */
    private boolean maybeMigrateAppDataLIF(@NonNull PackageState packageState,
            @NonNull AndroidPackage pkg, @UserIdInt int userId) {
        if (packageState.isSystem() && !StorageManager.isFileEncrypted()
    private boolean maybeMigrateAppDataLIF(@NonNull PackageSetting ps, @UserIdInt int userId) {
        if (ps.isSystem() && !StorageManager.isFileEncrypted()
                && PackageManager.APPLY_DEFAULT_TO_DEVICE_PROTECTED_STORAGE) {
            final int storageTarget = pkg.isDefaultToDeviceProtectedStorage()
            final int storageTarget = ps.isDefaultToDeviceProtectedStorage()
                    ? StorageManager.FLAG_STORAGE_DE : StorageManager.FLAG_STORAGE_CE;
            try {
                mInstaller.migrateAppData(pkg.getVolumeUuid(), pkg.getPackageName(), userId,
                mInstaller.migrateAppData(ps.getVolumeUuid(), ps.getPackageName(), userId,
                        storageTarget);
            } catch (Installer.InstallerException e) {
                logCriticalInfo(Log.WARN,
                        "Failed to migrate " + pkg.getPackageName() + ": " + e.getMessage());
                        "Failed to migrate " + ps.getPackageName() + ": " + e.getMessage());
            }
            return true;
        } else {
@@ -471,7 +471,7 @@ public class AppDataHelper {
            }

            if (ps.getUserStateOrDefault(userId).isInstalled()) {
                prepareAppDataAndMigrate(batch, ps, ps.getPkg(), userId, flags, migrateAppData);
                prepareAppDataAndMigrate(batch, ps.getPkg(), userId, flags, migrateAppData);
                preparedCount++;
            }
        }
@@ -550,7 +550,7 @@ public class AppDataHelper {
                        && packageStateInternal.getUserStateOrDefault(
                                UserHandle.USER_SYSTEM).isInstalled()) {
                    AndroidPackage pkg = packageStateInternal.getPkg();
                    prepareAppDataAndMigrate(batch, packageStateInternal, pkg,
                    prepareAppDataAndMigrate(batch, pkg,
                            UserHandle.USER_SYSTEM, storageFlags, true /* maybeMigrateAppData */);
                    count++;
                }
@@ -568,22 +568,22 @@ public class AppDataHelper {
        if (pkg == null) {
            return;
        }
        clearAppDataLeafLIF(pkg, userId, flags);
        clearAppDataLeafLIF(pkg.getPackageName(), pkg.getVolumeUuid(), userId, flags);

        if ((flags & Installer.FLAG_CLEAR_APP_DATA_KEEP_ART_PROFILES) == 0) {
            clearAppProfilesLIF(pkg);
        }
    }

    private void clearAppDataLeafLIF(AndroidPackage pkg, int userId, int flags) {
    void clearAppDataLeafLIF(String packageName, String volumeUuid, int userId, int flags) {
        final Computer snapshot = mPm.snapshotComputer();
        final PackageStateInternal packageStateInternal =
                snapshot.getPackageStateInternal(pkg.getPackageName());
                snapshot.getPackageStateInternal(packageName);
        for (int realUserId : mPm.resolveUserIds(userId)) {
            final long ceDataInode = (packageStateInternal != null)
                    ? packageStateInternal.getUserStateOrDefault(realUserId).getCeDataInode() : 0;
            try {
                mInstaller.clearAppData(pkg.getVolumeUuid(), pkg.getPackageName(), realUserId,
                mInstaller.clearAppData(volumeUuid, packageName, realUserId,
                        flags, ceDataInode);
            } catch (Installer.InstallerException e) {
                Slog.w(TAG, String.valueOf(e));
@@ -597,7 +597,7 @@ public class AppDataHelper {
            return;
        }
        if (DexOptHelper.useArtService()) {
            destroyAppProfilesWithArtService(pkg);
            destroyAppProfilesWithArtService(pkg.getPackageName());
        } else {
            try {
                mArtManagerService.clearAppProfiles(pkg);
@@ -612,41 +612,37 @@ public class AppDataHelper {
            Slog.wtf(TAG, "Package was null!", new Throwable());
            return;
        }
        destroyAppDataLeafLIF(pkg, userId, flags);
        destroyAppDataLeafLIF(pkg.getPackageName(), pkg.getVolumeUuid(), userId, flags);
    }

    private void destroyAppDataLeafLIF(AndroidPackage pkg, int userId, int flags) {
    private void destroyAppDataLeafLIF(
            String packageName, String volumeUuid, int userId, int flags) {
        final Computer snapshot = mPm.snapshotComputer();
        final PackageStateInternal packageStateInternal =
                snapshot.getPackageStateInternal(pkg.getPackageName());
                snapshot.getPackageStateInternal(packageName);
        for (int realUserId : mPm.resolveUserIds(userId)) {
            final long ceDataInode = (packageStateInternal != null)
                    ? packageStateInternal.getUserStateOrDefault(realUserId).getCeDataInode() : 0;
            try {
                mInstaller.destroyAppData(pkg.getVolumeUuid(), pkg.getPackageName(), realUserId,
                mInstaller.destroyAppData(volumeUuid, packageName, realUserId,
                        flags, ceDataInode);
            } catch (Installer.InstallerException e) {
                Slog.w(TAG, String.valueOf(e));
            }
            mPm.getDexManager().notifyPackageDataDestroyed(pkg.getPackageName(), userId);
            mPm.getDynamicCodeLogger().notifyPackageDataDestroyed(pkg.getPackageName(), userId);
        }
            mPm.getDexManager().notifyPackageDataDestroyed(packageName, userId);
            mPm.getDynamicCodeLogger().notifyPackageDataDestroyed(packageName, userId);
        }

    public void destroyAppProfilesLIF(AndroidPackage pkg) {
        if (pkg == null) {
            Slog.wtf(TAG, "Package was null!", new Throwable());
            return;
        }
        destroyAppProfilesLeafLIF(pkg);
    }

    private void destroyAppProfilesLeafLIF(AndroidPackage pkg) {
    /**
     * Destroy ART app profiles for the package.
     */
    void destroyAppProfilesLIF(String packageName) {
        if (DexOptHelper.useArtService()) {
            destroyAppProfilesWithArtService(pkg);
            destroyAppProfilesWithArtService(packageName);
        } else {
            try {
                mInstaller.destroyAppProfiles(pkg.getPackageName());
                mInstaller.destroyAppProfiles(packageName);
            } catch (LegacyDexoptDisabledException e) {
                throw new RuntimeException(e);
            } catch (Installer.InstallerException e) {
@@ -655,7 +651,7 @@ public class AppDataHelper {
        }
    }

    private void destroyAppProfilesWithArtService(AndroidPackage pkg) {
    private void destroyAppProfilesWithArtService(String packageName) {
        if (!DexOptHelper.artManagerLocalIsInitialized()) {
            // This function may get called while PackageManagerService is constructed (via e.g.
            // InitAppsHelper.initSystemApps), and ART Service hasn't yet been started then (it
@@ -668,7 +664,7 @@ public class AppDataHelper {
        try (PackageManagerLocal.FilteredSnapshot snapshot =
                        getPackageManagerLocal().withFilteredSnapshot()) {
            try {
                DexOptHelper.getArtManagerLocal().clearAppProfiles(snapshot, pkg.getPackageName());
                DexOptHelper.getArtManagerLocal().clearAppProfiles(snapshot, packageName);
            } catch (IllegalArgumentException e) {
                // Package isn't found, but that should only happen due to race.
                Slog.w(TAG, e);
+10 −8
Original line number Diff line number Diff line
@@ -1500,14 +1500,15 @@ public class ComputerEngine implements Computer {
                    state.getFirstInstallTimeMillis(), ps.getLastUpdateTime(), installedPermissions,
                    grantedPermissions, state, userId, ps);

            if (packageInfo != null) {
            if (packageInfo == null) {
                return null;
            }

            packageInfo.packageName = packageInfo.applicationInfo.packageName =
                    resolveExternalPackageName(p);

            return packageInfo;
            }
        }
        // TODO(b/314808978): Set ps.setPkg to null during install-archived.
        if ((flags & (MATCH_UNINSTALLED_PACKAGES | MATCH_ARCHIVED_PACKAGES)) != 0
        } else if ((flags & (MATCH_UNINSTALLED_PACKAGES | MATCH_ARCHIVED_PACKAGES)) != 0
                && PackageUserStateUtils.isAvailable(state, flags)) {
            PackageInfo pi = new PackageInfo();
            pi.packageName = ps.getPackageName();
@@ -1541,9 +1542,10 @@ public class ComputerEngine implements Computer {
                        + ps.getPackageName() + "]. Provides a minimum info.");
            }
            return pi;
        }
        } else {
            return null;
        }
    }

    public final PackageInfo getPackageInfo(String packageName,
            @PackageManager.PackageInfoFlagsBits long flags, int userId) {
+13 −10
Original line number Diff line number Diff line
@@ -731,7 +731,8 @@ final class InstallPackageHelper {

                    synchronized (mPm.mInstallLock) {
                        // We don't need to freeze for a brand new install
                        mAppDataHelper.prepareAppDataAfterInstallLIF(pkgSetting.getPkg());
                        mAppDataHelper.prepareAppDataPostCommitLIF(
                                pkgSetting, /* previousAppId= */0);
                    }
                }
                // TODO(b/278553670) Store archive state for the user.
@@ -2432,9 +2433,9 @@ final class InstallPackageHelper {
            final boolean instantApp = ((installRequest.getScanFlags() & SCAN_AS_INSTANT_APP) != 0);
            final boolean isApex = ((installRequest.getScanFlags() & SCAN_AS_APEX) != 0);
            final PackageSetting ps = installRequest.getScannedPackageSetting();
            final String packageName = ps.getPackageName();
            final String codePath = ps.getPathString();
            final AndroidPackage pkg = ps.getPkg();
            final String packageName = pkg.getPackageName();
            final String codePath = pkg.getPath();
            final boolean onIncremental = mIncrementalManager != null
                    && isIncrementalPath(codePath);
            if (onIncremental) {
@@ -2447,18 +2448,19 @@ final class InstallPackageHelper {
            }

            // Hardcode previousAppId to 0 to disable any data migration (http://b/221088088)
            mAppDataHelper.prepareAppDataPostCommitLIF(pkg, 0);
            mAppDataHelper.prepareAppDataPostCommitLIF(ps, 0);
            if (installRequest.isClearCodeCache()) {
                mAppDataHelper.clearAppDataLIF(pkg, UserHandle.USER_ALL,
                        FLAG_STORAGE_DE | FLAG_STORAGE_CE | FLAG_STORAGE_EXTERNAL
                                | Installer.FLAG_CLEAR_CODE_CACHE_ONLY);
                mAppDataHelper.clearAppDataLeafLIF(packageName, ps.getVolumeUuid(),
                        UserHandle.USER_ALL, FLAG_STORAGE_DE | FLAG_STORAGE_CE
                        | FLAG_STORAGE_EXTERNAL | Installer.FLAG_CLEAR_CODE_CACHE_ONLY);
            }
            if (installRequest.isInstallReplace()) {
                mDexManager.notifyPackageUpdated(pkg.getPackageName(),
            if (installRequest.isInstallReplace() && pkg != null) {
                mDexManager.notifyPackageUpdated(packageName,
                        pkg.getBaseApkPath(), pkg.getSplitCodePaths());
            }

            if (!useArtService()) { // ART Service handles this on demand instead.
            // ART Service handles this on demand instead.
            if (!useArtService() && pkg != null) {
                // Prepare the application profiles for the new code paths.
                // This needs to be done before invoking dexopt so that any install-time profile
                // can be used for optimizations.
@@ -2523,6 +2525,7 @@ final class InstallPackageHelper {
                    (!instantApp || android.provider.Settings.Global.getInt(
                            mContext.getContentResolver(),
                            android.provider.Settings.Global.INSTANT_APP_DEXOPT_ENABLED, 0) != 0)
                            && pkg != null
                            && !pkg.isDebuggable()
                            && (!onIncremental)
                            && dexoptOptions.isCompilationEnabled()
+1 −0
Original line number Diff line number Diff line
@@ -1540,6 +1540,7 @@ public class PackageManagerService implements PackageSender, TestUtilityService
                continue;
            }
            pkgSetting
                    .setPkg(null)
                    .modifyUserState(userId)
                    .setInstalled(false)
                    .setArchiveState(archiveState);
+2 −2
Original line number Diff line number Diff line
@@ -261,7 +261,7 @@ final class RemovePackageHelper {
            sus = mPm.mSettings.getSharedUserSettingLPr(ps);
        }

        mAppDataHelper.destroyAppProfilesLIF(pkg);
        mAppDataHelper.destroyAppProfilesLIF(ps.getPackageName());

        final List<AndroidPackage> sharedUserPkgs =
                sus != null ? sus.getPackages() : Collections.emptyList();
@@ -354,7 +354,7 @@ final class RemovePackageHelper {
            }
            mAppDataHelper.destroyAppDataLIF(resolvedPkg, UserHandle.USER_ALL,
                    FLAG_STORAGE_DE | FLAG_STORAGE_CE | FLAG_STORAGE_EXTERNAL);
            mAppDataHelper.destroyAppProfilesLIF(resolvedPkg);
            mAppDataHelper.destroyAppProfilesLIF(resolvedPkg.getPackageName());
            if (outInfo != null) {
                outInfo.mDataRemoved = true;
            }