summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
author Mohammad Samiul Islam <samiul@google.com> 2020-09-15 15:36:37 +0100
committer Mohammad Samiul Islam <samiul@google.com> 2020-10-05 22:56:14 +0100
commit038fd8d035689910230fa4bf32618e726befa13c (patch)
tree40236d2456239d1a5574a283e703e7ad8095786c
parent2de9c48ee3292d61ad6eea22f92a4a666e669185 (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.java118
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.