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

Commit c1630144 authored by Riddle Hsu's avatar Riddle Hsu Committed by Automerger Merge Worker
Browse files

Merge "Pause transient hide activities before resuming next" into udc-qpr-dev am: b73baea1

parents f14f41b7 b73baea1
Loading
Loading
Loading
Loading
+1 −1
Original line number Diff line number Diff line
@@ -1020,7 +1020,7 @@ class TaskFragment extends WindowContainer<WindowContainer> {
        final WindowContainer<?> parent = getParent();
        final Task thisTask = asTask();
        if (thisTask != null && parent.asTask() == null
                && mTransitionController.isTransientHide(thisTask)) {
                && mTransitionController.isTransientVisible(thisTask)) {
            // Keep transient-hide root tasks visible. Non-root tasks still follow standard rule.
            return TASK_FRAGMENT_VISIBILITY_VISIBLE;
        }
+30 −0
Original line number Diff line number Diff line
@@ -407,6 +407,36 @@ class Transition implements BLASTSyncEngine.TransactionReadyListener {
        return false;
    }

    /** Returns {@code true} if the task should keep visible if this is a transient transition. */
    boolean isTransientVisible(@NonNull Task task) {
        if (mTransientLaunches == null) return false;
        int occludedCount = 0;
        final int numTransient = mTransientLaunches.size();
        for (int i = numTransient - 1; i >= 0; --i) {
            final Task transientRoot = mTransientLaunches.keyAt(i).getRootTask();
            if (transientRoot == null) continue;
            final WindowContainer<?> rootParent = transientRoot.getParent();
            if (rootParent == null || rootParent.getTopChild() == transientRoot) continue;
            final ActivityRecord topOpaque = mController.mAtm.mTaskSupervisor
                    .mOpaqueActivityHelper.getOpaqueActivity(rootParent);
            if (transientRoot.compareTo(topOpaque.getRootTask()) < 0) {
                occludedCount++;
            }
        }
        if (occludedCount == numTransient) {
            for (int i = mTransientLaunches.size() - 1; i >= 0; --i) {
                if (mTransientLaunches.keyAt(i).isDescendantOf(task)) {
                    // Keep transient activity visible until transition finished, so it won't pause
                    // with transient-hide tasks that may delay resuming the next top.
                    return true;
                }
            }
            // Let transient-hide activities pause before transition is finished.
            return false;
        }
        return isInTransientHide(task);
    }

    boolean canApplyDim(@NonNull Task task) {
        if (mTransientLaunches == null) return true;
        final Dimmer dimmer = task.getDimmer();
+10 −3
Original line number Diff line number Diff line
@@ -477,15 +477,22 @@ class TransitionController {
        if (mCollectingTransition != null && mCollectingTransition.isInTransientHide(task)) {
            return true;
        }
        for (int i = mWaitingTransitions.size() - 1; i >= 0; --i) {
            if (mWaitingTransitions.get(i).isInTransientHide(task)) return true;
        }
        for (int i = mPlayingTransitions.size() - 1; i >= 0; --i) {
            if (mPlayingTransitions.get(i).isInTransientHide(task)) return true;
        }
        return false;
    }

    boolean isTransientVisible(@NonNull Task task) {
        if (mCollectingTransition != null && mCollectingTransition.isTransientVisible(task)) {
            return true;
        }
        for (int i = mPlayingTransitions.size() - 1; i >= 0; --i) {
            if (mPlayingTransitions.get(i).isTransientVisible(task)) return true;
        }
        return false;
    }

    boolean canApplyDim(@Nullable Task task) {
        if (task == null) {
            // Always allow non-activity window.
+1 −1
Original line number Diff line number Diff line
@@ -656,7 +656,7 @@ public class RootTaskTests extends WindowTestsBase {
                topSplitPrimary.getVisibility(null /* starting */));
        // Make primary split root transient-hide.
        spyOn(splitPrimary.mTransitionController);
        doReturn(true).when(splitPrimary.mTransitionController).isTransientHide(
        doReturn(true).when(splitPrimary.mTransitionController).isTransientVisible(
                organizer.mPrimary);
        // The split root and its top become visible.
        assertEquals(TASK_FRAGMENT_VISIBILITY_VISIBLE,
+41 −0
Original line number Diff line number Diff line
@@ -1483,6 +1483,47 @@ public class TransitionTests extends WindowTestsBase {
        assertTrue(enteringAnimReports.contains(activity2));
    }

    @Test
    public void testIsTransientVisible() {
        final ActivityRecord appB = new ActivityBuilder(mAtm).setCreateTask(true)
                .setVisible(false).build();
        final ActivityRecord recent = new ActivityBuilder(mAtm).setCreateTask(true)
                .setVisible(false).build();
        final ActivityRecord appA = new ActivityBuilder(mAtm).setCreateTask(true).build();
        final Task taskA = appA.getTask();
        final Task taskB = appB.getTask();
        final Task taskRecent = recent.getTask();
        registerTestTransitionPlayer();
        final TransitionController controller = mRootWindowContainer.mTransitionController;
        final Transition transition = createTestTransition(TRANSIT_OPEN, controller);
        controller.moveToCollecting(transition);
        transition.collect(recent);
        transition.collect(taskA);
        transition.setTransientLaunch(recent, taskA);
        taskRecent.moveToFront("move-recent-to-front");

        // During collecting and playing, the recent is on top so it is visible naturally.
        // While B needs isTransientVisible to keep visibility because it is occluded by recents.
        assertFalse(controller.isTransientVisible(taskB));
        assertTrue(controller.isTransientVisible(taskA));
        assertFalse(controller.isTransientVisible(taskRecent));
        // Switch to playing state.
        transition.onTransactionReady(transition.getSyncId(), mMockT);
        assertTrue(controller.isTransientVisible(taskA));

        // Switch to another task. For example, use gesture navigation to switch tasks.
        taskB.moveToFront("move-b-to-front");
        // The previous app (taskA) should be paused first so it loses transient visible. Because
        // visually it is taskA -> taskB, the pause -> resume order should be the same.
        assertFalse(controller.isTransientVisible(taskA));
        // Keep the recent visible so there won't be 2 activities pausing at the same time. It is
        // to avoid the latency to resume the current top, i.e. appB.
        assertTrue(controller.isTransientVisible(taskRecent));
        // The recent is paused after the transient transition is finished.
        controller.finishTransition(transition);
        assertFalse(controller.isTransientVisible(taskRecent));
    }

    @Test
    public void testNotReadyPushPop() {
        final TransitionController controller = new TestTransitionController(mAtm);