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

Commit c0836c88 authored by JW Wang's avatar JW Wang
Browse files

Check package overlaps for rebootless APEX (5/n)

Move the code to PackageSessionVerifier.

Note now the error is treated as a verification error instead of
a validation error. This will help debugging as the error message
is recorded.

Bug: 161121612
Test: atest StagedInstallInternalTest#testRebootlessUpdate_hasStagedSessionWithSameApex_fails

Change-Id: I8a206034cdf64a39c47ad105a4045a8098ad4386
parent 041a4ee8
Loading
Loading
Loading
Loading
+0 −15
Original line number Diff line number Diff line
@@ -2351,21 +2351,6 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub {
                    return;
                }
            }

            if (!params.isStaged) {
                // For non-staged APEX installs also check if there is a staged session that
                // contains the same APEX. If that's the case, we should fail this session.
                synchronized (mLock) {
                    int sessionId = mStagingManager.getSessionIdByPackageName(mPackageName);
                    if (sessionId != -1) {
                        onSessionValidationFailure(
                                PackageManager.INSTALL_FAILED_VERIFICATION_FAILURE,
                                "Staged session " + sessionId + " already contains "
                                        + mPackageName);
                        return;
                    }
                }
            }
        }

        if (params.isStaged) {
+39 −2
Original line number Diff line number Diff line
@@ -86,6 +86,14 @@ final class PackageSessionVerifier {
    public void verifyNonStaged(PackageInstallerSession session, Callback callback) {
        mHandler.post(() -> {
            try {
                storeSession(session.mStagedSession);
                if (session.isMultiPackage()) {
                    for (PackageInstallerSession child : session.getChildSessions()) {
                        checkRebootlessApex(child);
                    }
                } else {
                    checkRebootlessApex(session);
                }
                verifyAPK(session, callback);
            } catch (PackageManagerException e) {
                callback.onResult(e.error, e.getMessage());
@@ -154,7 +162,6 @@ final class PackageSessionVerifier {
        Slog.d(TAG, "Starting preRebootVerification for session " + session.sessionId());
        mHandler.post(() -> {
            try {
                storeSession(session);
                checkActiveSessions();
                checkRollbacks(session);
                if (session.isMultiPackage()) {
@@ -175,8 +182,10 @@ final class PackageSessionVerifier {
     * Stores staged-sessions for checking package overlapping and rollback conflicts.
     */
    private void storeSession(StagingManager.StagedSession session) {
        if (session != null) {
            mStagedSessions.add(session);
        }
    }

    private void onVerificationSuccess(StagingManager.StagedSession session, Callback callback) {
        callback.onResult(SessionInfo.STAGED_SESSION_NO_ERROR, null);
@@ -441,6 +450,34 @@ final class PackageSessionVerifier {
        return mApexManager.abortStagedSession(sessionId);
    }

    /**
     * Fails this rebootless APEX session if the same package name found in any staged sessions.
     */
    private void checkRebootlessApex(PackageInstallerSession session)
            throws PackageManagerException {
        if (session.isStaged() || !session.isApexSession()) {
            return;
        }
        String packageName = session.getPackageName();
        if (packageName == null) {
            throw new PackageManagerException(
                    PackageManager.INSTALL_FAILED_VERIFICATION_FAILURE,
                    "Invalid session " + session.sessionId + " with package name null");
        }
        for (StagingManager.StagedSession stagedSession : mStagedSessions) {
            if (stagedSession.isDestroyed() || stagedSession.isInTerminalState()) {
                continue;
            }
            if (stagedSession.sessionContains(s -> packageName.equals(s.getPackageName()))) {
                // Staged-sessions take priority over rebootless APEX
                throw new PackageManagerException(
                        PackageManager.INSTALL_FAILED_VERIFICATION_FAILURE,
                        "Staged session " + stagedSession.sessionId() + " already contains "
                                + packageName);
            }
        }
    }

    /**
     * Checks if multiple staged-sessions are supported. It is supported only when the system
     * supports checkpoint.