Loading libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipTaskOrganizer.java +11 −4 Original line number Diff line number Diff line Loading @@ -1481,9 +1481,13 @@ public class PipTaskOrganizer implements ShellTaskOrganizer.TaskListener, applyFinishBoundsResize(wct, direction, false); } } else { final boolean isPipTopLeft = direction == TRANSITION_DIRECTION_LEAVE_PIP_TO_SPLIT_SCREEN && isPipToTopLeft(); applyFinishBoundsResize(wct, direction, isPipTopLeft); applyFinishBoundsResize(wct, direction, isPipToTopLeft()); // Use sync transaction to apply finish transaction for enter split case. if (direction == TRANSITION_DIRECTION_LEAVE_PIP_TO_SPLIT_SCREEN) { mSyncTransactionQueue.runInSync(t -> { t.merge(tx); }); } } finishResizeForMenu(destinationBounds); Loading Loading @@ -1520,8 +1524,11 @@ public class PipTaskOrganizer implements ShellTaskOrganizer.TaskListener, mSurfaceTransactionHelper.round(tx, mLeash, isInPip()); wct.setBounds(mToken, taskBounds); // Pip to split should use sync transaction to sync split bounds change. if (direction != TRANSITION_DIRECTION_LEAVE_PIP_TO_SPLIT_SCREEN) { wct.setBoundsChangeTransaction(mToken, tx); } } /** * Applies the window container transaction to finish a bounds resize. Loading libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/SplitScreenController.java +5 −9 Original line number Diff line number Diff line Loading @@ -31,7 +31,6 @@ import static com.android.wm.shell.common.split.SplitScreenConstants.SPLIT_POSIT import static com.android.wm.shell.common.split.SplitScreenUtils.isValidToSplit; import static com.android.wm.shell.common.split.SplitScreenUtils.reverseSplitPosition; import static com.android.wm.shell.common.split.SplitScreenUtils.samePackage; import static com.android.wm.shell.splitscreen.SplitScreen.STAGE_TYPE_SIDE; import static com.android.wm.shell.splitscreen.SplitScreen.STAGE_TYPE_UNDEFINED; import static com.android.wm.shell.sysui.ShellSharedConstants.KEY_EXTRA_SHELL_SPLIT_SCREEN; import static com.android.wm.shell.transition.Transitions.ENABLE_SHELL_TRANSITIONS; Loading Loading @@ -89,7 +88,6 @@ import com.android.wm.shell.draganddrop.DragAndDropController; import com.android.wm.shell.draganddrop.DragAndDropPolicy; import com.android.wm.shell.protolog.ShellProtoLogGroup; import com.android.wm.shell.recents.RecentTasksController; import com.android.wm.shell.splitscreen.SplitScreen.StageType; import com.android.wm.shell.sysui.KeyguardChangeListener; import com.android.wm.shell.sysui.ShellCommandHandler; import com.android.wm.shell.sysui.ShellController; Loading Loading @@ -339,8 +337,7 @@ public class SplitScreenController implements DragAndDropPolicy.Starter, } public boolean moveToSideStage(int taskId, @SplitPosition int sideStagePosition) { return moveToStage(taskId, STAGE_TYPE_SIDE, sideStagePosition, new WindowContainerTransaction()); return moveToStage(taskId, sideStagePosition, new WindowContainerTransaction()); } /** Loading @@ -351,13 +348,13 @@ public class SplitScreenController implements DragAndDropPolicy.Starter, mStageCoordinator.updateSurfaces(transaction); } private boolean moveToStage(int taskId, @StageType int stageType, @SplitPosition int stagePosition, WindowContainerTransaction wct) { private boolean moveToStage(int taskId, @SplitPosition int stagePosition, WindowContainerTransaction wct) { final ActivityManager.RunningTaskInfo task = mTaskOrganizer.getRunningTaskInfo(taskId); if (task == null) { throw new IllegalArgumentException("Unknown taskId" + taskId); } return mStageCoordinator.moveToStage(task, stageType, stagePosition, wct); return mStageCoordinator.moveToStage(task, stagePosition, wct); } public boolean removeFromSideStage(int taskId) { Loading @@ -382,10 +379,9 @@ public class SplitScreenController implements DragAndDropPolicy.Starter, } public void enterSplitScreen(int taskId, boolean leftOrTop, WindowContainerTransaction wct) { final int stageType = isSplitScreenVisible() ? STAGE_TYPE_UNDEFINED : STAGE_TYPE_SIDE; final int stagePosition = leftOrTop ? SPLIT_POSITION_TOP_OR_LEFT : SPLIT_POSITION_BOTTOM_OR_RIGHT; moveToStage(taskId, stageType, stagePosition, wct); moveToStage(taskId, stagePosition, wct); } public void exitSplitScreen(int toTopTaskId, @ExitReason int exitReason) { Loading libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/StageCoordinator.java +28 −41 Original line number Diff line number Diff line Loading @@ -399,56 +399,43 @@ public class StageCoordinator implements SplitLayout.SplitLayoutHandler, return STAGE_TYPE_UNDEFINED; } boolean moveToStage(ActivityManager.RunningTaskInfo task, @StageType int stageType, @SplitPosition int stagePosition, WindowContainerTransaction wct) { boolean moveToStage(ActivityManager.RunningTaskInfo task, @SplitPosition int stagePosition, WindowContainerTransaction wct) { StageTaskListener targetStage; int sideStagePosition; if (stageType == STAGE_TYPE_MAIN) { targetStage = mMainStage; sideStagePosition = reverseSplitPosition(stagePosition); } else if (stageType == STAGE_TYPE_SIDE) { targetStage = mSideStage; sideStagePosition = stagePosition; } else { if (isSplitScreenVisible()) { // If the split screen is activated, retrieves target stage based on position. // If the split screen is foreground, retrieves target stage based on position. targetStage = stagePosition == mSideStagePosition ? mSideStage : mMainStage; sideStagePosition = mSideStagePosition; } else { // Exit split if it running background. exitSplitScreen(null /* childrenToTop */, EXIT_REASON_RECREATE_SPLIT); targetStage = mSideStage; sideStagePosition = stagePosition; } } if (!isSplitActive()) { // prevent the fling divider to center transitioni if split screen didn't active. mIsDropEntering = true; } mSplitLayout.init(); prepareEnterSplitScreen(wct, task, stagePosition); mSyncQueue.queue(wct); mSyncQueue.runInSync(t -> { updateSurfaceBounds(mSplitLayout, t, false /* applyResizingOffset */); }); } else { setSideStagePosition(sideStagePosition, wct); final WindowContainerTransaction evictWct = new WindowContainerTransaction(); targetStage.evictAllChildren(evictWct); // Apply surface bounds before animation start. SurfaceControl.Transaction startT = mTransactionPool.acquire(); if (startT != null) { updateSurfaceBounds(mSplitLayout, startT, false /* applyResizingOffset */); startT.apply(); mTransactionPool.release(startT); } // reparent the task to an invisible split root will make the activity invisible. Reorder // the root task to front to make the entering transition from pip to split smooth. wct.reorder(mRootTaskInfo.token, true); wct.reorder(targetStage.mRootTaskInfo.token, true); targetStage.addTask(task, wct); if (!evictWct.isEmpty()) { wct.merge(evictWct, true /* transfer */); targetStage.evictAllChildren(wct); if (!isSplitScreenVisible()) { final StageTaskListener anotherStage = targetStage == mMainStage ? mSideStage : mMainStage; anotherStage.reparentTopTask(wct); anotherStage.evictAllChildren(wct); wct.reorder(mRootTaskInfo.token, true); } mTaskOrganizer.applyTransaction(wct); 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; } Loading libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/splitscreen/StageCoordinatorTests.java +32 −23 Original line number Diff line number Diff line Loading @@ -144,39 +144,48 @@ public class StageCoordinatorTests extends ShellTestCase { } @Test public void testMoveToStage() { public void testMoveToStage_splitActiveBackground() { when(mStageCoordinator.isSplitActive()).thenReturn(true); final ActivityManager.RunningTaskInfo task = new TestRunningTaskInfoBuilder().build(); final WindowContainerTransaction wct = new WindowContainerTransaction(); mStageCoordinator.moveToStage(task, SPLIT_POSITION_BOTTOM_OR_RIGHT, wct); verify(mSideStage).addTask(eq(task), eq(wct)); assertEquals(SPLIT_POSITION_BOTTOM_OR_RIGHT, mStageCoordinator.getSideStagePosition()); assertEquals(SPLIT_POSITION_TOP_OR_LEFT, mStageCoordinator.getMainStagePosition()); } @Test public void testMoveToStage_splitActiveForeground() { when(mStageCoordinator.isSplitActive()).thenReturn(true); when(mStageCoordinator.isSplitScreenVisible()).thenReturn(true); // Assume current side stage is top or left. mStageCoordinator.setSideStagePosition(SPLIT_POSITION_TOP_OR_LEFT, null); final ActivityManager.RunningTaskInfo task = new TestRunningTaskInfoBuilder().build(); final WindowContainerTransaction wct = new WindowContainerTransaction(); mStageCoordinator.moveToStage(task, STAGE_TYPE_MAIN, SPLIT_POSITION_BOTTOM_OR_RIGHT, new WindowContainerTransaction()); verify(mMainStage).addTask(eq(task), any(WindowContainerTransaction.class)); mStageCoordinator.moveToStage(task, SPLIT_POSITION_BOTTOM_OR_RIGHT, wct); verify(mMainStage).addTask(eq(task), eq(wct)); assertEquals(SPLIT_POSITION_BOTTOM_OR_RIGHT, mStageCoordinator.getMainStagePosition()); assertEquals(SPLIT_POSITION_TOP_OR_LEFT, mStageCoordinator.getSideStagePosition()); mStageCoordinator.moveToStage(task, STAGE_TYPE_SIDE, SPLIT_POSITION_BOTTOM_OR_RIGHT, new WindowContainerTransaction()); verify(mSideStage).addTask(eq(task), any(WindowContainerTransaction.class)); assertEquals(SPLIT_POSITION_BOTTOM_OR_RIGHT, 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 public void testMoveToUndefinedStage() { public void testMoveToStage_splitInctive() { final ActivityManager.RunningTaskInfo task = new TestRunningTaskInfoBuilder().build(); final WindowContainerTransaction wct = new WindowContainerTransaction(); // Verify move to undefined stage while split screen not activated moves task to side stage. when(mStageCoordinator.isSplitScreenVisible()).thenReturn(false); mStageCoordinator.setSideStagePosition(SPLIT_POSITION_TOP_OR_LEFT, null); mStageCoordinator.moveToStage(task, STAGE_TYPE_UNDEFINED, SPLIT_POSITION_BOTTOM_OR_RIGHT, new WindowContainerTransaction()); verify(mSideStage).addTask(eq(task), any(WindowContainerTransaction.class)); mStageCoordinator.moveToStage(task, SPLIT_POSITION_BOTTOM_OR_RIGHT, wct); verify(mStageCoordinator).prepareEnterSplitScreen(eq(wct), eq(task), eq(SPLIT_POSITION_BOTTOM_OR_RIGHT)); assertEquals(SPLIT_POSITION_BOTTOM_OR_RIGHT, mStageCoordinator.getSideStagePosition()); // Verify move to undefined stage after split screen activated moves task based on position. when(mStageCoordinator.isSplitScreenVisible()).thenReturn(true); assertEquals(SPLIT_POSITION_TOP_OR_LEFT, mStageCoordinator.getMainStagePosition()); mStageCoordinator.moveToStage(task, STAGE_TYPE_UNDEFINED, SPLIT_POSITION_TOP_OR_LEFT, new WindowContainerTransaction()); verify(mMainStage).addTask(eq(task), any(WindowContainerTransaction.class)); assertEquals(SPLIT_POSITION_TOP_OR_LEFT, mStageCoordinator.getMainStagePosition()); } @Test Loading Loading
libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipTaskOrganizer.java +11 −4 Original line number Diff line number Diff line Loading @@ -1481,9 +1481,13 @@ public class PipTaskOrganizer implements ShellTaskOrganizer.TaskListener, applyFinishBoundsResize(wct, direction, false); } } else { final boolean isPipTopLeft = direction == TRANSITION_DIRECTION_LEAVE_PIP_TO_SPLIT_SCREEN && isPipToTopLeft(); applyFinishBoundsResize(wct, direction, isPipTopLeft); applyFinishBoundsResize(wct, direction, isPipToTopLeft()); // Use sync transaction to apply finish transaction for enter split case. if (direction == TRANSITION_DIRECTION_LEAVE_PIP_TO_SPLIT_SCREEN) { mSyncTransactionQueue.runInSync(t -> { t.merge(tx); }); } } finishResizeForMenu(destinationBounds); Loading Loading @@ -1520,8 +1524,11 @@ public class PipTaskOrganizer implements ShellTaskOrganizer.TaskListener, mSurfaceTransactionHelper.round(tx, mLeash, isInPip()); wct.setBounds(mToken, taskBounds); // Pip to split should use sync transaction to sync split bounds change. if (direction != TRANSITION_DIRECTION_LEAVE_PIP_TO_SPLIT_SCREEN) { wct.setBoundsChangeTransaction(mToken, tx); } } /** * Applies the window container transaction to finish a bounds resize. Loading
libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/SplitScreenController.java +5 −9 Original line number Diff line number Diff line Loading @@ -31,7 +31,6 @@ import static com.android.wm.shell.common.split.SplitScreenConstants.SPLIT_POSIT import static com.android.wm.shell.common.split.SplitScreenUtils.isValidToSplit; import static com.android.wm.shell.common.split.SplitScreenUtils.reverseSplitPosition; import static com.android.wm.shell.common.split.SplitScreenUtils.samePackage; import static com.android.wm.shell.splitscreen.SplitScreen.STAGE_TYPE_SIDE; import static com.android.wm.shell.splitscreen.SplitScreen.STAGE_TYPE_UNDEFINED; import static com.android.wm.shell.sysui.ShellSharedConstants.KEY_EXTRA_SHELL_SPLIT_SCREEN; import static com.android.wm.shell.transition.Transitions.ENABLE_SHELL_TRANSITIONS; Loading Loading @@ -89,7 +88,6 @@ import com.android.wm.shell.draganddrop.DragAndDropController; import com.android.wm.shell.draganddrop.DragAndDropPolicy; import com.android.wm.shell.protolog.ShellProtoLogGroup; import com.android.wm.shell.recents.RecentTasksController; import com.android.wm.shell.splitscreen.SplitScreen.StageType; import com.android.wm.shell.sysui.KeyguardChangeListener; import com.android.wm.shell.sysui.ShellCommandHandler; import com.android.wm.shell.sysui.ShellController; Loading Loading @@ -339,8 +337,7 @@ public class SplitScreenController implements DragAndDropPolicy.Starter, } public boolean moveToSideStage(int taskId, @SplitPosition int sideStagePosition) { return moveToStage(taskId, STAGE_TYPE_SIDE, sideStagePosition, new WindowContainerTransaction()); return moveToStage(taskId, sideStagePosition, new WindowContainerTransaction()); } /** Loading @@ -351,13 +348,13 @@ public class SplitScreenController implements DragAndDropPolicy.Starter, mStageCoordinator.updateSurfaces(transaction); } private boolean moveToStage(int taskId, @StageType int stageType, @SplitPosition int stagePosition, WindowContainerTransaction wct) { private boolean moveToStage(int taskId, @SplitPosition int stagePosition, WindowContainerTransaction wct) { final ActivityManager.RunningTaskInfo task = mTaskOrganizer.getRunningTaskInfo(taskId); if (task == null) { throw new IllegalArgumentException("Unknown taskId" + taskId); } return mStageCoordinator.moveToStage(task, stageType, stagePosition, wct); return mStageCoordinator.moveToStage(task, stagePosition, wct); } public boolean removeFromSideStage(int taskId) { Loading @@ -382,10 +379,9 @@ public class SplitScreenController implements DragAndDropPolicy.Starter, } public void enterSplitScreen(int taskId, boolean leftOrTop, WindowContainerTransaction wct) { final int stageType = isSplitScreenVisible() ? STAGE_TYPE_UNDEFINED : STAGE_TYPE_SIDE; final int stagePosition = leftOrTop ? SPLIT_POSITION_TOP_OR_LEFT : SPLIT_POSITION_BOTTOM_OR_RIGHT; moveToStage(taskId, stageType, stagePosition, wct); moveToStage(taskId, stagePosition, wct); } public void exitSplitScreen(int toTopTaskId, @ExitReason int exitReason) { Loading
libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/StageCoordinator.java +28 −41 Original line number Diff line number Diff line Loading @@ -399,56 +399,43 @@ public class StageCoordinator implements SplitLayout.SplitLayoutHandler, return STAGE_TYPE_UNDEFINED; } boolean moveToStage(ActivityManager.RunningTaskInfo task, @StageType int stageType, @SplitPosition int stagePosition, WindowContainerTransaction wct) { boolean moveToStage(ActivityManager.RunningTaskInfo task, @SplitPosition int stagePosition, WindowContainerTransaction wct) { StageTaskListener targetStage; int sideStagePosition; if (stageType == STAGE_TYPE_MAIN) { targetStage = mMainStage; sideStagePosition = reverseSplitPosition(stagePosition); } else if (stageType == STAGE_TYPE_SIDE) { targetStage = mSideStage; sideStagePosition = stagePosition; } else { if (isSplitScreenVisible()) { // If the split screen is activated, retrieves target stage based on position. // If the split screen is foreground, retrieves target stage based on position. targetStage = stagePosition == mSideStagePosition ? mSideStage : mMainStage; sideStagePosition = mSideStagePosition; } else { // Exit split if it running background. exitSplitScreen(null /* childrenToTop */, EXIT_REASON_RECREATE_SPLIT); targetStage = mSideStage; sideStagePosition = stagePosition; } } if (!isSplitActive()) { // prevent the fling divider to center transitioni if split screen didn't active. mIsDropEntering = true; } mSplitLayout.init(); prepareEnterSplitScreen(wct, task, stagePosition); mSyncQueue.queue(wct); mSyncQueue.runInSync(t -> { updateSurfaceBounds(mSplitLayout, t, false /* applyResizingOffset */); }); } else { setSideStagePosition(sideStagePosition, wct); final WindowContainerTransaction evictWct = new WindowContainerTransaction(); targetStage.evictAllChildren(evictWct); // Apply surface bounds before animation start. SurfaceControl.Transaction startT = mTransactionPool.acquire(); if (startT != null) { updateSurfaceBounds(mSplitLayout, startT, false /* applyResizingOffset */); startT.apply(); mTransactionPool.release(startT); } // reparent the task to an invisible split root will make the activity invisible. Reorder // the root task to front to make the entering transition from pip to split smooth. wct.reorder(mRootTaskInfo.token, true); wct.reorder(targetStage.mRootTaskInfo.token, true); targetStage.addTask(task, wct); if (!evictWct.isEmpty()) { wct.merge(evictWct, true /* transfer */); targetStage.evictAllChildren(wct); if (!isSplitScreenVisible()) { final StageTaskListener anotherStage = targetStage == mMainStage ? mSideStage : mMainStage; anotherStage.reparentTopTask(wct); anotherStage.evictAllChildren(wct); wct.reorder(mRootTaskInfo.token, true); } mTaskOrganizer.applyTransaction(wct); 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; } Loading
libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/splitscreen/StageCoordinatorTests.java +32 −23 Original line number Diff line number Diff line Loading @@ -144,39 +144,48 @@ public class StageCoordinatorTests extends ShellTestCase { } @Test public void testMoveToStage() { public void testMoveToStage_splitActiveBackground() { when(mStageCoordinator.isSplitActive()).thenReturn(true); final ActivityManager.RunningTaskInfo task = new TestRunningTaskInfoBuilder().build(); final WindowContainerTransaction wct = new WindowContainerTransaction(); mStageCoordinator.moveToStage(task, SPLIT_POSITION_BOTTOM_OR_RIGHT, wct); verify(mSideStage).addTask(eq(task), eq(wct)); assertEquals(SPLIT_POSITION_BOTTOM_OR_RIGHT, mStageCoordinator.getSideStagePosition()); assertEquals(SPLIT_POSITION_TOP_OR_LEFT, mStageCoordinator.getMainStagePosition()); } @Test public void testMoveToStage_splitActiveForeground() { when(mStageCoordinator.isSplitActive()).thenReturn(true); when(mStageCoordinator.isSplitScreenVisible()).thenReturn(true); // Assume current side stage is top or left. mStageCoordinator.setSideStagePosition(SPLIT_POSITION_TOP_OR_LEFT, null); final ActivityManager.RunningTaskInfo task = new TestRunningTaskInfoBuilder().build(); final WindowContainerTransaction wct = new WindowContainerTransaction(); mStageCoordinator.moveToStage(task, STAGE_TYPE_MAIN, SPLIT_POSITION_BOTTOM_OR_RIGHT, new WindowContainerTransaction()); verify(mMainStage).addTask(eq(task), any(WindowContainerTransaction.class)); mStageCoordinator.moveToStage(task, SPLIT_POSITION_BOTTOM_OR_RIGHT, wct); verify(mMainStage).addTask(eq(task), eq(wct)); assertEquals(SPLIT_POSITION_BOTTOM_OR_RIGHT, mStageCoordinator.getMainStagePosition()); assertEquals(SPLIT_POSITION_TOP_OR_LEFT, mStageCoordinator.getSideStagePosition()); mStageCoordinator.moveToStage(task, STAGE_TYPE_SIDE, SPLIT_POSITION_BOTTOM_OR_RIGHT, new WindowContainerTransaction()); verify(mSideStage).addTask(eq(task), any(WindowContainerTransaction.class)); assertEquals(SPLIT_POSITION_BOTTOM_OR_RIGHT, 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 public void testMoveToUndefinedStage() { public void testMoveToStage_splitInctive() { final ActivityManager.RunningTaskInfo task = new TestRunningTaskInfoBuilder().build(); final WindowContainerTransaction wct = new WindowContainerTransaction(); // Verify move to undefined stage while split screen not activated moves task to side stage. when(mStageCoordinator.isSplitScreenVisible()).thenReturn(false); mStageCoordinator.setSideStagePosition(SPLIT_POSITION_TOP_OR_LEFT, null); mStageCoordinator.moveToStage(task, STAGE_TYPE_UNDEFINED, SPLIT_POSITION_BOTTOM_OR_RIGHT, new WindowContainerTransaction()); verify(mSideStage).addTask(eq(task), any(WindowContainerTransaction.class)); mStageCoordinator.moveToStage(task, SPLIT_POSITION_BOTTOM_OR_RIGHT, wct); verify(mStageCoordinator).prepareEnterSplitScreen(eq(wct), eq(task), eq(SPLIT_POSITION_BOTTOM_OR_RIGHT)); assertEquals(SPLIT_POSITION_BOTTOM_OR_RIGHT, mStageCoordinator.getSideStagePosition()); // Verify move to undefined stage after split screen activated moves task based on position. when(mStageCoordinator.isSplitScreenVisible()).thenReturn(true); assertEquals(SPLIT_POSITION_TOP_OR_LEFT, mStageCoordinator.getMainStagePosition()); mStageCoordinator.moveToStage(task, STAGE_TYPE_UNDEFINED, SPLIT_POSITION_TOP_OR_LEFT, new WindowContainerTransaction()); verify(mMainStage).addTask(eq(task), any(WindowContainerTransaction.class)); assertEquals(SPLIT_POSITION_TOP_OR_LEFT, mStageCoordinator.getMainStagePosition()); } @Test Loading