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

Commit 35b7d8f5 authored by Nikita Ioffe's avatar Nikita Ioffe Committed by Android (Google) Code Review
Browse files

Merge "Fail committing new staged session if another one is already in progress"

parents 309eb41a da998cfa
Loading
Loading
Loading
Loading
+8 −0
Original line number Diff line number Diff line
@@ -1389,6 +1389,14 @@ public abstract class PackageManager {
     */
    public static final int INSTALL_FAILED_BAD_SIGNATURE = -118;

    /**
     * Installation failed return code: a new staged session was attempted to be committed while
     * there is already one in-progress.
     *
     * @hide
     */
    public static final int INSTALL_FAILED_OTHER_STAGED_SESSION_IN_PROGRESS = -119;

    /** @hide */
    @IntDef(flag = true, prefix = { "DELETE_" }, value = {
            DELETE_KEEP_DATA,
+14 −1
Original line number Diff line number Diff line
@@ -510,6 +510,13 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub {
        }
    }

    /** {@hide} */
    boolean isCommitted() {
        synchronized (mLock) {
            return mCommitted;
        }
    }

    @GuardedBy("mLock")
    private void assertPreparedAndNotSealedLocked(String cookie) {
        assertPreparedAndNotCommittedOrDestroyedLocked(cookie);
@@ -1064,7 +1071,13 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub {

    private void handleCommit() {
        if (params.isStaged) {
            try {
                mStagingManager.commitSession(this);
            } catch (StagingManager.AlreadyInProgressStagedSessionException e) {
                dispatchSessionFinished(
                        PackageManager.INSTALL_FAILED_OTHER_STAGED_SESSION_IN_PROGRESS,
                        e.getMessage(), null);
            }
            destroyInternal();
            dispatchSessionFinished(PackageManager.INSTALL_SUCCEEDED, "Session staged", null);
            return;
+43 −3
Original line number Diff line number Diff line
@@ -17,6 +17,7 @@
package com.android.server.pm;

import android.annotation.NonNull;
import android.annotation.Nullable;
import android.apex.ApexInfo;
import android.apex.ApexInfoList;
import android.apex.ApexSessionInfo;
@@ -479,11 +480,42 @@ public class StagingManager {
        return true;
    }

    void commitSession(@NonNull PackageInstallerSession session) {
    void commitSession(@NonNull PackageInstallerSession session)
            throws AlreadyInProgressStagedSessionException {
        PackageInstallerSession activeSession = getActiveSession();
        boolean anotherSessionAlreadyInProgress =
                activeSession != null && session.sessionId != activeSession.sessionId;
        updateStoredSession(session);
        if (anotherSessionAlreadyInProgress) {
            session.setStagedSessionFailed(SessionInfo.STAGED_SESSION_VERIFICATION_FAILED,
                    "There is already in-progress committed staged session "
                            + activeSession.sessionId);
            throw new AlreadyInProgressStagedSessionException(activeSession.sessionId);
        }
        mBgHandler.post(() -> preRebootVerification(session));
    }

    @Nullable
    private PackageInstallerSession getActiveSession() {
        synchronized (mStagedSessions) {
            for (int i = 0; i < mStagedSessions.size(); i++) {
                final PackageInstallerSession session = mStagedSessions.valueAt(i);
                if (!session.isCommitted()) {
                    continue;
                }
                if (session.hasParentSessionId()) {
                    // Staging manager will finalize only parent session. Ignore child sessions
                    // picking the active.
                    continue;
                }
                if (!session.isStagedSessionApplied() && !session.isStagedSessionFailed()) {
                    return session;
                }
            }
        }
        return null;
    }

    void createSession(@NonNull PackageInstallerSession sessionInfo) {
        synchronized (mStagedSessions) {
            mStagedSessions.append(sessionInfo.sessionId, sessionInfo);
@@ -497,8 +529,8 @@ public class StagingManager {
    }

    void abortCommittedSession(@NonNull PackageInstallerSession session) {
        if (session.isStagedSessionApplied()) {
            Slog.w(TAG, "Cannot abort applied session!");
        if (session.isStagedSessionApplied() || session.isStagedSessionFailed()) {
            Slog.w(TAG, "Cannot abort already finalized session : " + session.sessionId);
            return;
        }
        abortSession(session);
@@ -618,4 +650,12 @@ public class StagingManager {
            }
        }
    }

    static final class AlreadyInProgressStagedSessionException extends Exception {

        AlreadyInProgressStagedSessionException(int sessionId) {
            super("There is already in-progress committed staged session "
                    + sessionId);
        }
    }
}