Loading services/core/java/com/android/server/pm/AppDataHelper.java +80 −84 Original line number Diff line number Diff line Loading @@ -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; Loading Loading @@ -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; Loading Loading @@ -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; } Loading @@ -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); } }); } Loading @@ -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; Loading @@ -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!"); Loading Loading @@ -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); Loading @@ -292,7 +291,9 @@ public class AppDataHelper { } } if (pkg != null) { prepareAppDataContentsLeafLIF(pkg, ps, userId, flags); } }); } Loading Loading @@ -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 { Loading Loading @@ -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++; } } Loading Loading @@ -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++; } Loading @@ -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)); Loading @@ -597,7 +597,7 @@ public class AppDataHelper { return; } if (DexOptHelper.useArtService()) { destroyAppProfilesWithArtService(pkg); destroyAppProfilesWithArtService(pkg.getPackageName()); } else { try { mArtManagerService.clearAppProfiles(pkg); Loading @@ -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) { Loading @@ -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 Loading @@ -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); Loading services/core/java/com/android/server/pm/ComputerEngine.java +10 −8 Original line number Diff line number Diff line Loading @@ -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(); Loading Loading @@ -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) { Loading services/core/java/com/android/server/pm/InstallPackageHelper.java +13 −10 Original line number Diff line number Diff line Loading @@ -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. Loading Loading @@ -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) { Loading @@ -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. Loading Loading @@ -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() Loading services/core/java/com/android/server/pm/PackageManagerService.java +1 −0 Original line number Diff line number Diff line Loading @@ -1540,6 +1540,7 @@ public class PackageManagerService implements PackageSender, TestUtilityService continue; } pkgSetting .setPkg(null) .modifyUserState(userId) .setInstalled(false) .setArchiveState(archiveState); Loading services/core/java/com/android/server/pm/RemovePackageHelper.java +2 −2 Original line number Diff line number Diff line Loading @@ -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(); Loading Loading @@ -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; } Loading Loading
services/core/java/com/android/server/pm/AppDataHelper.java +80 −84 Original line number Diff line number Diff line Loading @@ -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; Loading Loading @@ -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; Loading Loading @@ -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; } Loading @@ -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); } }); } Loading @@ -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; Loading @@ -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!"); Loading Loading @@ -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); Loading @@ -292,7 +291,9 @@ public class AppDataHelper { } } if (pkg != null) { prepareAppDataContentsLeafLIF(pkg, ps, userId, flags); } }); } Loading Loading @@ -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 { Loading Loading @@ -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++; } } Loading Loading @@ -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++; } Loading @@ -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)); Loading @@ -597,7 +597,7 @@ public class AppDataHelper { return; } if (DexOptHelper.useArtService()) { destroyAppProfilesWithArtService(pkg); destroyAppProfilesWithArtService(pkg.getPackageName()); } else { try { mArtManagerService.clearAppProfiles(pkg); Loading @@ -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) { Loading @@ -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 Loading @@ -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); Loading
services/core/java/com/android/server/pm/ComputerEngine.java +10 −8 Original line number Diff line number Diff line Loading @@ -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(); Loading Loading @@ -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) { Loading
services/core/java/com/android/server/pm/InstallPackageHelper.java +13 −10 Original line number Diff line number Diff line Loading @@ -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. Loading Loading @@ -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) { Loading @@ -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. Loading Loading @@ -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() Loading
services/core/java/com/android/server/pm/PackageManagerService.java +1 −0 Original line number Diff line number Diff line Loading @@ -1540,6 +1540,7 @@ public class PackageManagerService implements PackageSender, TestUtilityService continue; } pkgSetting .setPkg(null) .modifyUserState(userId) .setInstalled(false) .setArchiveState(archiveState); Loading
services/core/java/com/android/server/pm/RemovePackageHelper.java +2 −2 Original line number Diff line number Diff line Loading @@ -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(); Loading Loading @@ -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; } Loading