diff options
| author | 2020-09-15 15:36:37 +0100 | |
|---|---|---|
| committer | 2020-10-05 22:56:14 +0100 | |
| commit | 038fd8d035689910230fa4bf32618e726befa13c (patch) | |
| tree | 40236d2456239d1a5574a283e703e7ad8095786c | |
| parent | 2de9c48ee3292d61ad6eea22f92a4a666e669185 (diff) | |
Reverify certain conditions during staged install
There is a delay between when a staged session is verified and when it
gets installed. The device state can mutate within this delay. As such
we need to reverify certain conditions during install phase.
For example, suppose we have a staged session for package X_v1 and it
passes pre-reboot verification. But before we reboot, if install X_v2
using non-staged install flow. On reboot, when installing X_v1 we need
to check for downgrade once again.
Bug: 163037460
Test: atest StagedInstallTest#testInstallMultipleStagedSession_PartialFail_ApkOnly
Change-Id: Ib9dd6eb6787ba8875644fa51919bc9010600509a
| -rw-r--r-- | services/core/java/com/android/server/pm/PackageManagerService.java | 118 |
1 files changed, 68 insertions, 50 deletions
diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java index 6da19df6ff67..8f1576516e07 100644 --- a/services/core/java/com/android/server/pm/PackageManagerService.java +++ b/services/core/java/com/android/server/pm/PackageManagerService.java @@ -14991,6 +14991,7 @@ public class PackageManagerService extends IPackageManager.Stub @Nullable MultiPackageInstallParams mParentInstallParams; final boolean forceQueryableOverride; final int mDataLoaderType; + final long requiredInstalledVersionCode; InstallParams(OriginInfo origin, MoveInfo move, IPackageInstallObserver2 observer, int installFlags, InstallSource installSource, String volumeUuid, @@ -15011,6 +15012,7 @@ public class PackageManagerService extends IPackageManager.Stub this.installReason = PackageManager.INSTALL_REASON_UNKNOWN; this.forceQueryableOverride = false; this.mDataLoaderType = DataLoaderType.NONE; + this.requiredInstalledVersionCode = PackageManager.VERSION_CODE_HIGHEST; } InstallParams(File stagedDir, IPackageInstallObserver2 observer, @@ -15033,6 +15035,7 @@ public class PackageManagerService extends IPackageManager.Stub forceQueryableOverride = sessionParams.forceQueryableOverride; mDataLoaderType = (sessionParams.dataLoaderParams != null) ? sessionParams.dataLoaderParams.getType() : DataLoaderType.NONE; + requiredInstalledVersionCode = sessionParams.requiredInstalledVersionCode; } @Override @@ -15179,6 +15182,18 @@ public class PackageManagerService extends IPackageManager.Stub public void handleStartCopy() { PackageInfoLite pkgLite = PackageManagerServiceUtils.getMinimalPackageInfo(mContext, origin.resolvedPath, installFlags, packageAbiOverride); + + // For staged session, there is a delay between its verification and install. Device + // state can change within this delay and hence we need to re-verify certain conditions. + boolean isStaged = (installFlags & INSTALL_STAGED) != 0; + if (isStaged) { + mRet = verifyReplacingVersionCode( + pkgLite, requiredInstalledVersionCode, installFlags); + if (mRet != INSTALL_SUCCEEDED) { + return; + } + } + mRet = overrideInstallLocation(pkgLite); } @@ -15325,11 +15340,14 @@ public class PackageManagerService extends IPackageManager.Stub PackageInfoLite pkgLite = PackageManagerServiceUtils.getMinimalPackageInfo(mContext, origin.resolvedPath, installFlags, packageAbiOverride); - mRet = verifyReplacingVersionCode(pkgLite); + mRet = verifyReplacingVersionCode(pkgLite, requiredInstalledVersionCode, installFlags); + if (mRet != INSTALL_SUCCEEDED) { + return; + } // Perform package verification and enable rollback (unless we are simply moving the // package). - if (mRet == INSTALL_SUCCEEDED && !origin.existing) { + if (!origin.existing) { sendApkVerificationRequest(pkgLite); if ((installFlags & PackageManager.INSTALL_ENABLE_ROLLBACK) != 0) { sendEnableRollbackRequest(); @@ -15337,54 +15355,6 @@ public class PackageManagerService extends IPackageManager.Stub } } - private int verifyReplacingVersionCode(PackageInfoLite pkgLite) { - String packageName = pkgLite.packageName; - synchronized (mLock) { - // Package which currently owns the data that the new package will own if installed. - // If an app is uninstalled while keeping data (e.g. adb uninstall -k), installedPkg - // will be null whereas dataOwnerPkg will contain information about the package - // which was uninstalled while keeping its data. - AndroidPackage dataOwnerPkg = mPackages.get(packageName); - if (dataOwnerPkg == null) { - PackageSetting ps = mSettings.mPackages.get(packageName); - if (ps != null) { - dataOwnerPkg = ps.pkg; - } - } - - if (requiredInstalledVersionCode != PackageManager.VERSION_CODE_HIGHEST) { - if (dataOwnerPkg == null) { - Slog.w(TAG, "Required installed version code was " - + requiredInstalledVersionCode - + " but package is not installed"); - return PackageManager.INSTALL_FAILED_WRONG_INSTALLED_VERSION; - } - - if (dataOwnerPkg.getLongVersionCode() != requiredInstalledVersionCode) { - Slog.w(TAG, "Required installed version code was " - + requiredInstalledVersionCode - + " but actual installed version is " - + dataOwnerPkg.getLongVersionCode()); - return PackageManager.INSTALL_FAILED_WRONG_INSTALLED_VERSION; - } - } - - if (dataOwnerPkg != null) { - if (!PackageManagerServiceUtils.isDowngradePermitted(installFlags, - dataOwnerPkg.isDebuggable())) { - try { - checkDowngrade(dataOwnerPkg, pkgLite); - } catch (PackageManagerException e) { - Slog.w(TAG, "Downgrade detected: " + e.getMessage()); - return PackageManager.INSTALL_FAILED_VERSION_DOWNGRADE; - } - } - } - } - return PackageManager.INSTALL_SUCCEEDED; - } - - void sendApkVerificationRequest(PackageInfoLite pkgLite) { final int verificationId = mPendingVerificationToken++; @@ -24209,6 +24179,54 @@ public class PackageManagerService extends IPackageManager.Stub } } + private int verifyReplacingVersionCode(PackageInfoLite pkgLite, + long requiredInstalledVersionCode, int installFlags) { + String packageName = pkgLite.packageName; + synchronized (mLock) { + // Package which currently owns the data that the new package will own if installed. + // If an app is uninstalled while keeping data (e.g. adb uninstall -k), installedPkg + // will be null whereas dataOwnerPkg will contain information about the package + // which was uninstalled while keeping its data. + AndroidPackage dataOwnerPkg = mPackages.get(packageName); + if (dataOwnerPkg == null) { + PackageSetting ps = mSettings.mPackages.get(packageName); + if (ps != null) { + dataOwnerPkg = ps.pkg; + } + } + + if (requiredInstalledVersionCode != PackageManager.VERSION_CODE_HIGHEST) { + if (dataOwnerPkg == null) { + Slog.w(TAG, "Required installed version code was " + + requiredInstalledVersionCode + + " but package is not installed"); + return PackageManager.INSTALL_FAILED_WRONG_INSTALLED_VERSION; + } + + if (dataOwnerPkg.getLongVersionCode() != requiredInstalledVersionCode) { + Slog.w(TAG, "Required installed version code was " + + requiredInstalledVersionCode + + " but actual installed version is " + + dataOwnerPkg.getLongVersionCode()); + return PackageManager.INSTALL_FAILED_WRONG_INSTALLED_VERSION; + } + } + + if (dataOwnerPkg != null) { + if (!PackageManagerServiceUtils.isDowngradePermitted(installFlags, + dataOwnerPkg.isDebuggable())) { + try { + checkDowngrade(dataOwnerPkg, pkgLite); + } catch (PackageManagerException e) { + Slog.w(TAG, "Downgrade detected: " + e.getMessage()); + return PackageManager.INSTALL_FAILED_VERSION_DOWNGRADE; + } + } + } + } + return PackageManager.INSTALL_SUCCEEDED; + } + /** * Check and throw if the given before/after packages would be considered a * downgrade. |