diff options
3 files changed, 133 insertions, 16 deletions
diff --git a/services/core/java/com/android/server/pm/DexOptHelper.java b/services/core/java/com/android/server/pm/DexOptHelper.java index 9ecc7b9a805d..2bc7eeb9f448 100644 --- a/services/core/java/com/android/server/pm/DexOptHelper.java +++ b/services/core/java/com/android/server/pm/DexOptHelper.java @@ -80,6 +80,7 @@ import com.android.server.art.model.DexoptResult; import com.android.server.pm.PackageDexOptimizer.DexOptResult; import com.android.server.pm.dex.DexManager; import com.android.server.pm.dex.DexoptOptions; +import com.android.server.pm.local.PackageManagerLocalImpl; import com.android.server.pm.pkg.AndroidPackage; import com.android.server.pm.pkg.PackageState; import com.android.server.pm.pkg.PackageStateInternal; @@ -819,10 +820,16 @@ public final class DexOptHelper { final PackageSetting ps = installRequest.getScannedPackageSetting(); final String packageName = ps.getPackageName(); + PackageSetting uncommittedPs = null; + if (Flags.improveInstallFreeze()) { + uncommittedPs = ps; + } + PackageManagerLocal packageManagerLocal = LocalManagerRegistry.getManager(PackageManagerLocal.class); try (PackageManagerLocal.FilteredSnapshot snapshot = - packageManagerLocal.withFilteredSnapshot()) { + PackageManagerLocalImpl.withFilteredSnapshot(packageManagerLocal, + uncommittedPs)) { boolean ignoreDexoptProfile = (installRequest.getInstallFlags() & PackageManager.INSTALL_IGNORE_DEXOPT_PROFILE) diff --git a/services/core/java/com/android/server/pm/InstallPackageHelper.java b/services/core/java/com/android/server/pm/InstallPackageHelper.java index aca65bfd561c..83292b775ddc 100644 --- a/services/core/java/com/android/server/pm/InstallPackageHelper.java +++ b/services/core/java/com/android/server/pm/InstallPackageHelper.java @@ -148,6 +148,7 @@ import android.util.ArrayMap; import android.util.ArraySet; import android.util.EventLog; import android.util.ExceptionUtils; +import android.util.IntArray; import android.util.Log; import android.util.Pair; import android.util.Slog; @@ -1014,13 +1015,17 @@ final class InstallPackageHelper { final Map<String, Settings.VersionInfo> versionInfos = new ArrayMap<>(requests.size()); try { CriticalEventLog.getInstance().logInstallPackagesStarted(); - if (prepareInstallPackages(requests) && scanInstallPackages(requests, createdAppId, versionInfos)) { List<ReconciledPackage> reconciledPackages = reconcileInstallPackages(requests, versionInfos); - if (reconciledPackages != null - && renameAndUpdatePaths(requests) + if (reconciledPackages == null) { + return; + } + if (Flags.improveInstallFreeze()) { + prepPerformDexoptIfNeeded(reconciledPackages); + } + if (renameAndUpdatePaths(requests) && commitInstallPackages(reconciledPackages)) { success = true; } @@ -1031,6 +1036,75 @@ final class InstallPackageHelper { } } + private int[] getNewUsers(InstallRequest installRequest, int[] allUsers) + throws PackageManagerException { + final int userId = installRequest.getUserId(); + if (userId != UserHandle.USER_ALL && userId != UserHandle.USER_CURRENT + && !mPm.mUserManager.exists(userId)) { + throw new PackageManagerException(PackageManagerException.INTERNAL_ERROR_MISSING_USER, + "User " + userId + " doesn't exist or has been removed"); + } + + final IntArray newUserIds = new IntArray(); + if (userId != UserHandle.USER_ALL) { + newUserIds.add(userId); + } else if (allUsers != null) { + final int[] installedForUsers = installRequest.getOriginUsers(); + for (int currentUserId : allUsers) { + final boolean installedForCurrentUser = ArrayUtils.contains( + installedForUsers, currentUserId); + final boolean restrictedByPolicy = + mPm.isUserRestricted(currentUserId, + UserManager.DISALLOW_INSTALL_APPS) + || mPm.isUserRestricted(currentUserId, + UserManager.DISALLOW_DEBUGGING_FEATURES); + if (installedForCurrentUser || !restrictedByPolicy) { + newUserIds.add(currentUserId); + } + } + } + + if (newUserIds.size() == 0) { + throw new PackageManagerException(PackageManagerException.INTERNAL_ERROR_MISSING_USER, + "User " + userId + " doesn't exist or has been removed"); + } else { + return newUserIds.toArray(); + } + } + + private void prepPerformDexoptIfNeeded(List<ReconciledPackage> reconciledPackages) { + for (ReconciledPackage reconciledPkg : reconciledPackages) { + final InstallRequest request = reconciledPkg.mInstallRequest; + // prepare profiles + final PackageSetting ps = request.getScannedPackageSetting(); + final PackageSetting oldPkgSetting = request.getScanRequestOldPackageSetting(); + final int[] allUsers = mPm.mUserManager.getUserIds(); + if (reconciledPkg.mCollectedSharedLibraryInfos != null + || (oldPkgSetting != null + && !oldPkgSetting.getSharedLibraryDependencies().isEmpty())) { + // Reconcile if the new package or the old package uses shared libraries. + // It is possible that the old package uses shared libraries but the new + // one doesn't. + mSharedLibraries.executeSharedLibrariesUpdate(request.getParsedPackage(), ps, + null, null, reconciledPkg.mCollectedSharedLibraryInfos, allUsers); + } + try (PackageManagerTracedLock installLock = mPm.mInstallLock.acquireLock()) { + final int[] newUsers = getNewUsers(request, allUsers); + // Hardcode previousAppId to 0 to disable any data migration (http://b/221088088) + mAppDataHelper.prepareAppDataPostCommitLIF(ps, 0, newUsers); + if (request.isClearCodeCache()) { + mAppDataHelper.clearAppDataLIF(ps.getPkg(), UserHandle.USER_ALL, + FLAG_STORAGE_DE | FLAG_STORAGE_CE | FLAG_STORAGE_EXTERNAL + | Installer.FLAG_CLEAR_CODE_CACHE_ONLY); + } + } catch (PackageManagerException e) { + request.setError(e.error, e.getMessage()); + return; + } + DexOptHelper.performDexoptIfNeeded(request, mDexManager, mContext, null); + } + } + private boolean renameAndUpdatePaths(List<InstallRequest> requests) { try (PackageManagerTracedLock installLock = mPm.mInstallLock.acquireLock()) { for (InstallRequest request : requests) { @@ -2655,20 +2729,22 @@ final class InstallPackageHelper { incrementalStorages.add(storage); } - // Hardcode previousAppId to 0 to disable any data migration (http://b/221088088) - mAppDataHelper.prepareAppDataPostCommitLIF(ps, 0, installRequest.getNewUsers()); - if (installRequest.isClearCodeCache()) { - mAppDataHelper.clearAppDataLIF(ps.getPkg(), UserHandle.USER_ALL, - FLAG_STORAGE_DE | FLAG_STORAGE_CE | FLAG_STORAGE_EXTERNAL - | Installer.FLAG_CLEAR_CODE_CACHE_ONLY); - } if (installRequest.isInstallReplace() && pkg != null) { mDexManager.notifyPackageUpdated(packageName, pkg.getBaseApkPath(), pkg.getSplitCodePaths()); } + if (!Flags.improveInstallFreeze()) { + // Hardcode previousAppId to 0 to disable any data migration (http://b/221088088) + mAppDataHelper.prepareAppDataPostCommitLIF(ps, 0, installRequest.getNewUsers()); + if (installRequest.isClearCodeCache()) { + mAppDataHelper.clearAppDataLIF(ps.getPkg(), UserHandle.USER_ALL, + FLAG_STORAGE_DE | FLAG_STORAGE_CE | FLAG_STORAGE_EXTERNAL + | Installer.FLAG_CLEAR_CODE_CACHE_ONLY); + } - DexOptHelper.performDexoptIfNeeded(installRequest, mDexManager, mContext, - mPm.mInstallLock.getRawLock()); + DexOptHelper.performDexoptIfNeeded(installRequest, mDexManager, mContext, + mPm.mInstallLock.getRawLock()); + } } PackageManagerServiceUtils.waitForNativeBinariesExtractionForIncremental( incrementalStorages); diff --git a/services/core/java/com/android/server/pm/local/PackageManagerLocalImpl.java b/services/core/java/com/android/server/pm/local/PackageManagerLocalImpl.java index 55afb17614af..c22e382682a7 100644 --- a/services/core/java/com/android/server/pm/local/PackageManagerLocalImpl.java +++ b/services/core/java/com/android/server/pm/local/PackageManagerLocalImpl.java @@ -31,6 +31,7 @@ import com.android.server.pm.Computer; import com.android.server.pm.PackageManagerLocal; import com.android.server.pm.PackageManagerService; import com.android.server.pm.pkg.PackageState; +import com.android.server.pm.pkg.PackageStateInternal; import com.android.server.pm.pkg.SharedUserApi; import com.android.server.pm.snapshot.PackageDataSnapshot; @@ -71,8 +72,26 @@ public class PackageManagerLocalImpl implements PackageManagerLocal { @NonNull @Override public FilteredSnapshotImpl withFilteredSnapshot(int callingUid, @NonNull UserHandle user) { + return withFilteredSnapshot(callingUid, user, /* uncommittedPs= */ null); + } + + /** + * Creates a {@link FilteredSnapshot} with a uncommitted {@link PackageState} that is used for + * dexopt in the art service to get the correct package state before the package is committed. + */ + @NonNull + public static FilteredSnapshotImpl withFilteredSnapshot(PackageManagerLocal pm, + @NonNull PackageState uncommittedPs) { + return ((PackageManagerLocalImpl) pm).withFilteredSnapshot(Binder.getCallingUid(), + Binder.getCallingUserHandle(), uncommittedPs); + } + + @NonNull + private FilteredSnapshotImpl withFilteredSnapshot(int callingUid, @NonNull UserHandle user, + @Nullable PackageState uncommittedPs) { return new FilteredSnapshotImpl(callingUid, user, - mService.snapshotComputer(false /*allowLiveComputer*/), null); + mService.snapshotComputer(/* allowLiveComputer= */ false), + /* parentSnapshot= */ null, uncommittedPs); } @Override @@ -145,7 +164,8 @@ public class PackageManagerLocalImpl implements PackageManagerLocal { @Override public FilteredSnapshot filtered(int callingUid, @NonNull UserHandle user) { - return new FilteredSnapshotImpl(callingUid, user, mSnapshot, this); + return new FilteredSnapshotImpl(callingUid, user, mSnapshot, this, + /* uncommittedPs= */ null); } @SuppressWarnings("RedundantSuppression") @@ -209,13 +229,18 @@ public class PackageManagerLocalImpl implements PackageManagerLocal { @Nullable private final UnfilteredSnapshotImpl mParentSnapshot; + @Nullable + private final PackageState mUncommitPackageState; + private FilteredSnapshotImpl(int callingUid, @NonNull UserHandle user, @NonNull PackageDataSnapshot snapshot, - @Nullable UnfilteredSnapshotImpl parentSnapshot) { + @Nullable UnfilteredSnapshotImpl parentSnapshot, + @Nullable PackageState uncommittedPs) { super(snapshot); mCallingUid = callingUid; mUserId = user.getIdentifier(); mParentSnapshot = parentSnapshot; + mUncommitPackageState = uncommittedPs; } @Override @@ -237,6 +262,10 @@ public class PackageManagerLocalImpl implements PackageManagerLocal { @Override public PackageState getPackageState(@NonNull String packageName) { checkClosed(); + if (mUncommitPackageState != null + && packageName.equals(mUncommitPackageState.getPackageName())) { + return mUncommitPackageState; + } return mSnapshot.getPackageStateFiltered(packageName, mCallingUid, mUserId); } @@ -250,6 +279,11 @@ public class PackageManagerLocalImpl implements PackageManagerLocal { var filteredPackageStates = new ArrayMap<String, PackageState>(); for (int index = 0, size = packageStates.size(); index < size; index++) { var packageState = packageStates.valueAt(index); + if (mUncommitPackageState != null + && packageState.getPackageName().equals( + mUncommitPackageState.getPackageName())) { + packageState = (PackageStateInternal) mUncommitPackageState; + } if (!mSnapshot.shouldFilterApplication(packageState, mCallingUid, mUserId)) { filteredPackageStates.put(packageStates.keyAt(index), packageState); } |