Loading services/core/java/com/android/server/wm/Task.java +12 −4 Original line number Diff line number Diff line Loading @@ -5793,7 +5793,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); Loading Loading @@ -5837,6 +5837,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 Loading Loading @@ -5865,7 +5874,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) { Loading @@ -5880,7 +5889,7 @@ class Task extends TaskFragment { if (inPinnedWindowingMode()) { mTaskSupervisor.removeRootTask(this); return true; return; } mRootWindowContainer.ensureVisibilityAndConfig(null /* starting */, Loading @@ -5903,7 +5912,6 @@ class Task extends TaskFragment { } else { mRootWindowContainer.resumeFocusedTasksTopActivities(); } return true; } boolean willActivityBeVisible(IBinder token) { Loading services/tests/wmtests/src/com/android/server/wm/TransitionTests.java +42 −12 Original line number Diff line number Diff line Loading @@ -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; Loading Loading @@ -2373,9 +2375,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()); Loading Loading @@ -2480,6 +2480,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(); Loading @@ -2497,17 +2527,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); } Loading Loading @@ -2616,6 +2640,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) { Loading Loading
services/core/java/com/android/server/wm/Task.java +12 −4 Original line number Diff line number Diff line Loading @@ -5793,7 +5793,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); Loading Loading @@ -5837,6 +5837,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 Loading Loading @@ -5865,7 +5874,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) { Loading @@ -5880,7 +5889,7 @@ class Task extends TaskFragment { if (inPinnedWindowingMode()) { mTaskSupervisor.removeRootTask(this); return true; return; } mRootWindowContainer.ensureVisibilityAndConfig(null /* starting */, Loading @@ -5903,7 +5912,6 @@ class Task extends TaskFragment { } else { mRootWindowContainer.resumeFocusedTasksTopActivities(); } return true; } boolean willActivityBeVisible(IBinder token) { Loading
services/tests/wmtests/src/com/android/server/wm/TransitionTests.java +42 −12 Original line number Diff line number Diff line Loading @@ -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; Loading Loading @@ -2373,9 +2375,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()); Loading Loading @@ -2480,6 +2480,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(); Loading @@ -2497,17 +2527,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); } Loading Loading @@ -2616,6 +2640,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) { Loading