From 1b72904c7a41355b4250b632f43b3f329d400a71 Mon Sep 17 00:00:00 2001 From: Tony Huang Date: Mon, 24 Apr 2023 12:23:29 +0000 Subject: [PATCH] Migrate moveToStage shell transition Bug: 279545938 Test: Using moveToStage command to test Change-Id: If6d5e6ec36ce62d68de906ff4435b1fd02a2c0cd --- .../shell/splitscreen/StageCoordinator.java | 92 ++++++++++++------- .../splitscreen/StageCoordinatorTests.java | 18 ++-- 2 files changed, 71 insertions(+), 39 deletions(-) diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/StageCoordinator.java b/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/StageCoordinator.java index 0ef26fcff2840..222e7db9e903d 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/StageCoordinator.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/StageCoordinator.java @@ -378,40 +378,18 @@ public class StageCoordinator implements SplitLayout.SplitLayoutHandler, boolean moveToStage(ActivityManager.RunningTaskInfo task, @SplitPosition int stagePosition, WindowContainerTransaction wct) { - StageTaskListener targetStage; - int sideStagePosition; - if (isSplitScreenVisible()) { - // If the split screen is foreground, retrieves target stage based on position. - targetStage = stagePosition == mSideStagePosition ? mSideStage : mMainStage; - sideStagePosition = mSideStagePosition; + prepareEnterSplitScreen(wct, task, stagePosition); + if (ENABLE_SHELL_TRANSITIONS) { + mSplitTransitions.startEnterTransition(TRANSIT_TO_FRONT, wct, + null, this, null /* consumedCallback */, null /* finishedCallback */, + isSplitScreenVisible() + ? TRANSIT_SPLIT_SCREEN_OPEN_TO_SIDE : TRANSIT_SPLIT_SCREEN_PAIR_OPEN); } else { - targetStage = mSideStage; - sideStagePosition = stagePosition; - } - - if (!isSplitActive()) { - mSplitLayout.init(); - prepareEnterSplitScreen(wct, task, stagePosition); mSyncQueue.queue(wct); mSyncQueue.runInSync(t -> { updateSurfaceBounds(mSplitLayout, t, false /* applyResizingOffset */); - setDividerVisibility(true, t); }); - } else { - setSideStagePosition(sideStagePosition, wct); - targetStage.addTask(task, wct); - targetStage.evictAllChildren(wct); - if (!isSplitScreenVisible()) { - final StageTaskListener anotherStage = targetStage == mMainStage - ? mSideStage : mMainStage; - anotherStage.reparentTopTask(wct); - anotherStage.evictAllChildren(wct); - wct.reorder(mRootTaskInfo.token, true); - } - setRootForceTranslucent(false, wct); - mSyncQueue.queue(wct); } - // Due to drag already pip task entering split by this method so need to reset flag here. mIsDropEntering = false; return true; @@ -1509,9 +1487,51 @@ public class StageCoordinator implements SplitLayout.SplitLayoutHandler, */ void prepareEnterSplitScreen(WindowContainerTransaction wct, @Nullable ActivityManager.RunningTaskInfo taskInfo, @SplitPosition int startPosition) { - if (mMainStage.isActive()) return; - onSplitScreenEnter(); + if (isSplitActive()) { + prepareBringSplit(wct, taskInfo, startPosition); + } else { + prepareActiveSplit(wct, taskInfo, startPosition); + } + } + + private void prepareBringSplit(WindowContainerTransaction wct, + @Nullable ActivityManager.RunningTaskInfo taskInfo, @SplitPosition int startPosition) { + StageTaskListener targetStage; + if (isSplitScreenVisible()) { + // If the split screen is foreground, retrieves target stage based on position. + targetStage = startPosition == mSideStagePosition ? mSideStage : mMainStage; + } else { + targetStage = mSideStage; + } + + if (taskInfo != null) { + wct.startTask(taskInfo.taskId, + resolveStartStage(STAGE_TYPE_UNDEFINED, startPosition, null, wct)); + targetStage.evictAllChildren(wct); + } + // If running background, we need to reparent current top visible task to another stage + // and evict all tasks current under its. + if (!isSplitScreenVisible()) { + // Recreate so we need to reset position rather than keep position of background split. + mSplitLayout.resetDividerPosition(); + updateWindowBounds(mSplitLayout, wct); + final StageTaskListener anotherStage = targetStage == mMainStage + ? mSideStage : mMainStage; + anotherStage.evictAllChildren(wct); + anotherStage.reparentTopTask(wct); + wct.reorder(mRootTaskInfo.token, true); + setRootForceTranslucent(false, wct); + } + } + + private void prepareActiveSplit(WindowContainerTransaction wct, + @Nullable ActivityManager.RunningTaskInfo taskInfo, @SplitPosition int startPosition) { + if (!ENABLE_SHELL_TRANSITIONS) { + // Legacy transition we need to create divider here, shell transition case we will + // create it on #finishEnterSplitScreen + mSplitLayout.init(); + } if (taskInfo != null) { setSideStagePosition(startPosition, wct); mSideStage.addTask(taskInfo, wct); @@ -2383,7 +2403,17 @@ public class StageCoordinator implements SplitLayout.SplitLayoutHandler, } final ActivityManager.RunningTaskInfo taskInfo = change.getTaskInfo(); - if (taskInfo == null || !taskInfo.hasParentTask()) continue; + if (taskInfo == null) continue; + if (taskInfo.token.equals(mRootTaskInfo.token)) { + if (isOpeningType(change.getMode())) { + // Split is opened by someone so set it as visible. + setSplitsVisible(true); + } else if (isClosingType(change.getMode())) { + // Split is closed by someone so set it as invisible. + setSplitsVisible(false); + } + continue; + } final StageTaskListener stage = getStageOfTask(taskInfo); if (stage == null) continue; if (isOpeningType(change.getMode())) { diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/splitscreen/StageCoordinatorTests.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/splitscreen/StageCoordinatorTests.java index e6219d1aa7921..d27064d1b4dad 100644 --- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/splitscreen/StageCoordinatorTests.java +++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/splitscreen/StageCoordinatorTests.java @@ -152,10 +152,15 @@ public class StageCoordinatorTests extends ShellTestCase { when(mStageCoordinator.isSplitActive()).thenReturn(true); final ActivityManager.RunningTaskInfo task = new TestRunningTaskInfoBuilder().build(); - final WindowContainerTransaction wct = new WindowContainerTransaction(); + final WindowContainerTransaction wct = spy(new WindowContainerTransaction()); mStageCoordinator.moveToStage(task, SPLIT_POSITION_BOTTOM_OR_RIGHT, wct); - verify(mSideStage).addTask(eq(task), eq(wct)); + verify(mStageCoordinator).prepareEnterSplitScreen(eq(wct), eq(task), + eq(SPLIT_POSITION_BOTTOM_OR_RIGHT)); + verify(mMainStage).reparentTopTask(eq(wct)); + verify(mMainStage).evictAllChildren(eq(wct)); + verify(mSideStage).evictAllChildren(eq(wct)); + verify(mSplitLayout).resetDividerPosition(); assertEquals(SPLIT_POSITION_BOTTOM_OR_RIGHT, mStageCoordinator.getSideStagePosition()); assertEquals(SPLIT_POSITION_TOP_OR_LEFT, mStageCoordinator.getMainStagePosition()); } @@ -171,14 +176,11 @@ public class StageCoordinatorTests extends ShellTestCase { final WindowContainerTransaction wct = new WindowContainerTransaction(); mStageCoordinator.moveToStage(task, SPLIT_POSITION_BOTTOM_OR_RIGHT, wct); - verify(mMainStage).addTask(eq(task), eq(wct)); + verify(mStageCoordinator).prepareEnterSplitScreen(eq(wct), eq(task), + eq(SPLIT_POSITION_BOTTOM_OR_RIGHT)); + verify(mMainStage).evictAllChildren(eq(wct)); assertEquals(SPLIT_POSITION_BOTTOM_OR_RIGHT, mStageCoordinator.getMainStagePosition()); assertEquals(SPLIT_POSITION_TOP_OR_LEFT, mStageCoordinator.getSideStagePosition()); - - mStageCoordinator.moveToStage(task, SPLIT_POSITION_TOP_OR_LEFT, wct); - verify(mSideStage).addTask(eq(task), eq(wct)); - assertEquals(SPLIT_POSITION_TOP_OR_LEFT, mStageCoordinator.getSideStagePosition()); - assertEquals(SPLIT_POSITION_BOTTOM_OR_RIGHT, mStageCoordinator.getMainStagePosition()); } @Test