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

Commit 7079ba9a authored by Riddle Hsu's avatar Riddle Hsu
Browse files

Allow to collect moving back task in open transition

Simulation:
 Task A starts(NEW_TASK) Task B, finishes
 Task B starts(NEW_TASK) Task C
   Task B calls moveTaskToBack in onPause
 Task C (declare as translucent and sleep 200ms in
         onCreate to delay transition)
   starts(NEW_TASK) Task B -> attempt to move task B to front
   finishes

Because the initial open transition may be done until the last
step, then moveTaskToBack for B will run after the last step.
Then expect B should be on top but the result is on home screen
because A and C are finished, and B is moved to back.

This change is kinda a workaround to mitigate the case of
deferred move-to-back. Because it is regular to have closing
targets in an open transition, the moving task can run with
the collecting transition directly.

Fix: 325645759
Test: atest TransitionTests#testDeferredMoveTaskToBack
Change-Id: I46d8e26110ebefea74e5dd06c85c003b12693416
parent 642bdb48
Loading
Loading
Loading
Loading
+12 −4
Original line number Diff line number Diff line
@@ -5787,7 +5787,7 @@ class Task extends TaskFragment {
        // If we have a watcher, preflight the move before committing to it.  First check
        // for *other* available tasks, but if none are available, then try again allowing the
        // current task to be selected.
        if (isTopRootTaskInDisplayArea() && mAtmService.mController != null) {
        if (mAtmService.mController != null && isTopRootTaskInDisplayArea()) {
            ActivityRecord next = topRunningActivity(null, task.mTaskId);
            if (next == null) {
                next = topRunningActivity(null, INVALID_TASK_ID);
@@ -5831,6 +5831,15 @@ class Task extends TaskFragment {
                + tr.mTaskId);

        if (mTransitionController.isShellTransitionsEnabled()) {
            // TODO(b/277838915): Consider to make it concurrent to eliminate the special case.
            final Transition collecting = mTransitionController.getCollectingTransition();
            if (collecting != null && collecting.mType == TRANSIT_OPEN) {
                // It can be a CLOSING participate of an OPEN transition. This avoids the deferred
                // transition from moving task to back after the task was moved to front.
                collecting.collect(tr);
                moveTaskToBackInner(tr, collecting);
                return true;
            }
            final Transition transition = new Transition(TRANSIT_TO_BACK, 0 /* flags */,
                    mTransitionController, mWmService.mSyncEngine);
            // Guarantee that this gets its own transition by queueing on SyncEngine
@@ -5859,7 +5868,7 @@ class Task extends TaskFragment {
        return true;
    }

    private boolean moveTaskToBackInner(@NonNull Task task, @Nullable Transition transition) {
    private void moveTaskToBackInner(@NonNull Task task, @Nullable Transition transition) {
        final Transition.ReadyCondition movedToBack =
                new Transition.ReadyCondition("moved-to-back", task);
        if (transition != null) {
@@ -5874,7 +5883,7 @@ class Task extends TaskFragment {

            if (inPinnedWindowingMode()) {
                mTaskSupervisor.removeRootTask(this);
                return true;
                return;
            }

            mRootWindowContainer.ensureVisibilityAndConfig(null /* starting */,
@@ -5897,7 +5906,6 @@ class Task extends TaskFragment {
        } else {
            mRootWindowContainer.resumeFocusedTasksTopActivities();
        }
        return true;
    }

    boolean willActivityBeVisible(IBinder token) {
+42 −12
Original line number Diff line number Diff line
@@ -64,8 +64,10 @@ import static org.mockito.ArgumentMatchers.anyBoolean;
import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.ArgumentMatchers.anyString;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.clearInvocations;
import static org.mockito.Mockito.doAnswer;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
@@ -2368,9 +2370,7 @@ public class TransitionTests extends WindowTestsBase {
        assertTrue(transitA.isCollecting());

        // finish collecting A
        transitA.start();
        transitA.setAllReady();
        mSyncEngine.tryFinishForTest(transitA.getSyncId());
        tryFinishTransitionSyncSet(transitA);
        waitUntilHandlersIdle();

        assertTrue(transitA.isPlaying());
@@ -2475,6 +2475,36 @@ public class TransitionTests extends WindowTestsBase {
        assertFalse(controller.isCollecting());
    }

    @Test
    public void testDeferredMoveTaskToBack() {
        final ActivityRecord activity = new ActivityBuilder(mAtm).setCreateTask(true).build();
        final Task task = activity.getTask();
        registerTestTransitionPlayer();
        final TransitionController controller = mWm.mRoot.mTransitionController;
        mSyncEngine = createTestBLASTSyncEngine();
        controller.setSyncEngine(mSyncEngine);
        final Transition transition = createTestTransition(TRANSIT_CHANGE, controller);
        controller.moveToCollecting(transition);
        task.moveTaskToBack(task);
        // Actual action will be deferred by current transition.
        verify(task, never()).moveToBack(any(), any());

        tryFinishTransitionSyncSet(transition);
        waitUntilHandlersIdle();
        // Continue to move task to back after the transition is done.
        verify(task).moveToBack(any(), any());
        final Transition moveBackTransition = controller.getCollectingTransition();
        assertNotNull(moveBackTransition);
        moveBackTransition.abort();

        // The move-to-back can be collected in to a collecting OPEN transition.
        clearInvocations(task);
        final Transition transition2 = createTestTransition(TRANSIT_OPEN, controller);
        controller.moveToCollecting(transition2);
        task.moveTaskToBack(task);
        verify(task).moveToBack(any(), any());
    }

    @Test
    public void testNoSyncFlagIfOneTrack() {
        final TransitionController controller = mAtm.getTransitionController();
@@ -2492,17 +2522,11 @@ public class TransitionTests extends WindowTestsBase {
        controller.startCollectOrQueue(transitC, (deferred) -> {});

        // Verify that, as-long as there is <= 1 track, we won't get a SYNC flag
        transitA.start();
        transitA.setAllReady();
        mSyncEngine.tryFinishForTest(transitA.getSyncId());
        tryFinishTransitionSyncSet(transitA);
        assertTrue((player.mLastReady.getFlags() & FLAG_SYNC) == 0);
        transitB.start();
        transitB.setAllReady();
        mSyncEngine.tryFinishForTest(transitB.getSyncId());
        tryFinishTransitionSyncSet(transitB);
        assertTrue((player.mLastReady.getFlags() & FLAG_SYNC) == 0);
        transitC.start();
        transitC.setAllReady();
        mSyncEngine.tryFinishForTest(transitC.getSyncId());
        tryFinishTransitionSyncSet(transitC);
        assertTrue((player.mLastReady.getFlags() & FLAG_SYNC) == 0);
    }

@@ -2642,6 +2666,12 @@ public class TransitionTests extends WindowTestsBase {
        assertEquals("reason1", condition1.mAlternate);
    }

    private void tryFinishTransitionSyncSet(Transition transition) {
        transition.setAllReady();
        transition.start();
        mSyncEngine.tryFinishForTest(transition.getSyncId());
    }

    private static void makeTaskOrganized(Task... tasks) {
        final ITaskOrganizer organizer = mock(ITaskOrganizer.class);
        for (Task t : tasks) {