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

Commit 038fd8d0 authored by Mohammad Samiul Islam's avatar Mohammad Samiul Islam
Browse files

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
parent 2de9c48e
Loading
Loading
Loading
Loading
+68 −50
Original line number Diff line number Diff line
@@ -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.