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

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

Fail a staged session when a rollback is already staged (1/n)

1. A rollback session gets the priority. Non-rollback sessions should
   fail no matter they are staged earlier or later.
2. Move checks for commit timestamps into the if block for overlap
   checking. So it will not interfere with rollback checks.
3. Fix StagingManagerTest caused by the change in
   checkNonOverlappingWithStagedSessions().

Bug: 192625695
Test: atest CtsRollbackManagerHostTestCases StagingManagerTest
Change-Id: Id3a0cfaef52d0f8b7b311b28c7bc2bd99e8b0a53
parent 86922cea
Loading
Loading
Loading
Loading
+21 −14
Original line number Diff line number Diff line
@@ -652,6 +652,7 @@ public class StagingManager {
     * </ul>
     * @throws PackageManagerException if session fails the check
     */
    // TODO(b/192625695): Rename this method which checks rollbacks in addition to overlapping
    @VisibleForTesting
    void checkNonOverlappingWithStagedSessions(@NonNull StagedSession session)
            throws PackageManagerException {
@@ -685,13 +686,6 @@ public class StagingManager {
                    continue;
                }

                if (stagedSession.getCommittedMillis() > session.getCommittedMillis()) {
                    // Ignore sessions that are committed after the provided session. When there are
                    // overlaps between sessions, we will fail the one committed later instead of
                    // the earlier one.
                    continue;
                }

                // From here on, stagedSession is a parent active staged session

                // Check if session is one of the active sessions
@@ -716,15 +710,28 @@ public class StagingManager {
                            "Session was failed by rollback session: " + session.sessionId());
                    Slog.i(TAG, "Session " + root.sessionId() + " is marked failed due to "
                            + "rollback session: " + session.sessionId());
                } else if (!isRollback && isRollback(stagedSession)) {
                    throw new PackageManagerException(
                            SessionInfo.STAGED_SESSION_CONFLICT,
                            "Session was failed by rollback session: " + stagedSession.sessionId());
                } else if (stagedSession.sessionContains(
                        s -> s.getPackageName().equals(packageName))) {
                    // New session cannot have same package name as one of the active sessions
                    // Fail the session committed later when there are overlapping packages
                    if (stagedSession.getCommittedMillis() < session.getCommittedMillis()) {
                        throw new PackageManagerException(
                                SessionInfo.STAGED_SESSION_VERIFICATION_FAILED,
                                "Package: " + session.getPackageName() + " in session: "
                                        + session.sessionId()
                                        + " has been staged already by session: "
                                        + stagedSession.sessionId(), null);
                    } else {
                        stagedSession.setSessionFailed(
                                SessionInfo.STAGED_SESSION_VERIFICATION_FAILED,
                                "Package: " + packageName + " in session: "
                                        + stagedSession.sessionId()
                                        + " has been staged already by session: "
                                        + session.sessionId());
                    }
                }

                // Staging multiple root sessions is not allowed if device doesn't support
+11 −2
Original line number Diff line number Diff line
@@ -19,9 +19,11 @@ package com.android.server.pm;
import static com.google.common.truth.Truth.assertThat;

import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.ArgumentMatchers.anyString;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.doAnswer;
import static org.mockito.Mockito.doNothing;
import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.spy;
@@ -123,9 +125,15 @@ public class StagingManagerTest {
        mStagingManager.createSession(session2);
        // Session1 should not fail in spite of the overlapping packages
        mStagingManager.checkNonOverlappingWithStagedSessions(session1);
        // Session2 should fail due to overlapping packages
        // setSessionFailed() should've been called when doing overlapping checks on session1
        verify(session2, times(1)).setSessionFailed(anyInt(), anyString());

        // Yet another session with overlapping packages
        StagingManager.StagedSession session3 = createSession(333, "com.foo", 3);
        mStagingManager.createSession(session3);
        assertThrows(PackageManagerException.class,
                () -> mStagingManager.checkNonOverlappingWithStagedSessions(session2));
                () -> mStagingManager.checkNonOverlappingWithStagedSessions(session3));
        verify(session3, never()).setSessionFailed(anyInt(), anyString());
    }

    @Test
@@ -505,6 +513,7 @@ public class StagingManagerTest {
            Predicate<StagingManager.StagedSession> filter = invocation.getArgument(0);
            return filter.test(stagedSession);
        }).when(stagedSession).sessionContains(any());
        doNothing().when(stagedSession).setSessionFailed(anyInt(), anyString());
        return stagedSession;
    }