Loading libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopTasksController.kt +22 −12 Original line number Diff line number Diff line Loading @@ -2701,10 +2701,12 @@ class DesktopTasksController( /** * Adds split screen changes to a transaction. Note that bounds are not reset here due to * animation; see {@link onDesktopSplitSelectAnimComplete} * * TODO: b/394268248 - desk needs to be deactivated. */ private fun addMoveToSplitChanges(wct: WindowContainerTransaction, taskInfo: RunningTaskInfo) { private fun addMoveToSplitChanges( wct: WindowContainerTransaction, taskInfo: RunningTaskInfo, deskId: Int?, ): RunOnTransitStart? { // This windowing mode is to get the transition animation started; once we complete // split select, we will change windowing mode to undefined and inherit from split stage. // Going to undefined here causes task to flicker to the top left. Loading @@ -2714,11 +2716,12 @@ class DesktopTasksController( // want it overridden in multi-window. wct.setDensityDpi(taskInfo.token, getDefaultDensityDpi()) performDesktopExitCleanupIfNeeded( return performDesktopExitCleanupIfNeeded( taskId = taskInfo.taskId, displayId = taskInfo.displayId, deskId = deskId, wct = wct, forceToFullscreen = false, forceToFullscreen = true, shouldEndUpAtHome = false, ) } Loading Loading @@ -2950,14 +2953,21 @@ class DesktopTasksController( } dragToDesktopTransitionHandler.cancelDragToDesktopTransition(cancelState) } else { val deskId = taskRepository.getDeskIdForTask(taskInfo.taskId) logV("Split requested for task=%d in desk=%d", taskInfo.taskId, deskId) val wct = WindowContainerTransaction() addMoveToSplitChanges(wct, taskInfo) val runOnTransitStart = addMoveToSplitChanges(wct, taskInfo, deskId) val transition = splitScreenController.requestEnterSplitSelect( taskInfo, wct, if (leftOrTop) SPLIT_POSITION_TOP_OR_LEFT else SPLIT_POSITION_BOTTOM_OR_RIGHT, if (leftOrTop) SPLIT_POSITION_TOP_OR_LEFT else SPLIT_POSITION_BOTTOM_OR_RIGHT, taskInfo.configuration.windowConfiguration.bounds, ) if (transition != null) { runOnTransitStart?.invoke(transition) } } } } Loading libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/SplitScreenController.java +6 −2 Original line number Diff line number Diff line Loading @@ -54,6 +54,7 @@ import android.content.pm.ShortcutInfo; import android.graphics.Rect; import android.os.Bundle; import android.os.Handler; import android.os.IBinder; import android.os.RemoteException; import android.os.UserHandle; import android.util.ArrayMap; Loading Loading @@ -580,10 +581,13 @@ public class SplitScreenController implements SplitDragPolicy.Starter, * @param wct transaction to apply if this is a valid request * @param splitPosition the split position this task should move to * @param taskBounds current freeform bounds of the task entering split * * @return the token of the transition that started as a result of entering split select. */ public void requestEnterSplitSelect(ActivityManager.RunningTaskInfo taskInfo, @Nullable public IBinder requestEnterSplitSelect(ActivityManager.RunningTaskInfo taskInfo, WindowContainerTransaction wct, int splitPosition, Rect taskBounds) { mStageCoordinator.requestEnterSplitSelect(taskInfo, wct, splitPosition, taskBounds); return mStageCoordinator.requestEnterSplitSelect(taskInfo, wct, splitPosition, taskBounds); } /** Loading libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/StageCoordinator.java +12 −2 Original line number Diff line number Diff line Loading @@ -122,6 +122,7 @@ import android.view.RemoteAnimationTarget; import android.view.SurfaceControl; import android.view.WindowManager; import android.widget.Toast; import android.window.DesktopExperienceFlags; import android.window.DisplayAreaInfo; import android.window.RemoteTransition; import android.window.TransitionInfo; Loading Loading @@ -219,6 +220,7 @@ public class StageCoordinator implements SplitLayout.SplitLayoutHandler, private final Context mContext; private final List<SplitScreen.SplitScreenListener> mListeners = new ArrayList<>(); private final Set<SplitScreen.SplitSelectListener> mSelectListeners = new HashSet<>(); private final Transitions mTransitions; private final DisplayController mDisplayController; private final DisplayImeController mDisplayImeController; private final DisplayInsetsController mDisplayInsetsController; Loading Loading @@ -419,6 +421,7 @@ public class StageCoordinator implements SplitLayout.SplitLayoutHandler, iconProvider, mWindowDecorViewModel, STAGE_TYPE_SIDE); } mTransitions = transitions; mDisplayController = displayController; mDisplayImeController = displayImeController; mDisplayInsetsController = displayInsetsController; Loading Loading @@ -455,6 +458,7 @@ public class StageCoordinator implements SplitLayout.SplitLayoutHandler, mTaskOrganizer = taskOrganizer; mMainStage = mainStage; mSideStage = sideStage; mTransitions = transitions; mDisplayController = displayController; mDisplayImeController = displayImeController; mDisplayInsetsController = displayInsetsController; Loading Loading @@ -660,16 +664,22 @@ public class StageCoordinator implements SplitLayout.SplitLayoutHandler, return mLogger; } void requestEnterSplitSelect(ActivityManager.RunningTaskInfo taskInfo, @Nullable IBinder requestEnterSplitSelect(ActivityManager.RunningTaskInfo taskInfo, WindowContainerTransaction wct, int splitPosition, Rect taskBounds) { boolean enteredSplitSelect = false; for (SplitScreen.SplitSelectListener listener : mSelectListeners) { enteredSplitSelect |= listener.onRequestEnterSplitSelect(taskInfo, splitPosition, taskBounds); } if (enteredSplitSelect) { if (!enteredSplitSelect) { return null; } if (!DesktopExperienceFlags.ENABLE_MULTIPLE_DESKTOPS_BACKEND.isTrue()) { mTaskOrganizer.applyTransaction(wct); return null; } return mTransitions.startTransition(TRANSIT_CHANGE, wct, /* handler= */ null); } void startShortcut(String packageName, String shortcutId, @SplitPosition int position, Loading libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/desktopmode/DesktopTasksControllerTest.kt +24 −1 Original line number Diff line number Diff line Loading @@ -5248,6 +5248,24 @@ class DesktopTasksControllerTest(flags: FlagsParameterization) : ShellTestCase() assertThat(wctArgument.firstValue.hierarchyOps).isEmpty() } @Test @EnableFlags(Flags.FLAG_ENABLE_MULTIPLE_DESKTOPS_BACKEND) fun enterSplit_wasInDesk_deactivatesDesk() { val deskId = 5 taskRepository.addDesk(displayId = DEFAULT_DISPLAY, deskId = deskId) taskRepository.setActiveDesk(displayId = DEFAULT_DISPLAY, deskId = deskId) val task = setUpFreeformTask(displayId = DEFAULT_DISPLAY, deskId = deskId) val transition = Binder() whenever(splitScreenController.requestEnterSplitSelect(eq(task), any(), any(), any())) .thenReturn(transition) controller.requestSplit(task, leftOrTop = false) verify(desksOrganizer).deactivateDesk(any(), eq(deskId)) verify(desksTransitionsObserver) .addPendingTransition(DeskTransition.DeactivateDesk(transition, deskId)) } @Test @EnableFlags(Flags.FLAG_ENABLE_DESKTOP_WINDOWING_MULTI_INSTANCE_FEATURES) fun newWindow_fromFullscreenOpensInSplit() { Loading Loading @@ -6601,6 +6619,7 @@ class DesktopTasksControllerTest(flags: FlagsParameterization) : ShellTestCase() bounds: Rect? = null, active: Boolean = true, background: Boolean = false, deskId: Int? = null, ): RunningTaskInfo { val task = createFreeformTask(displayId, bounds) val activityInfo = ActivityInfo() Loading @@ -6613,7 +6632,11 @@ class DesktopTasksControllerTest(flags: FlagsParameterization) : ShellTestCase() } else { whenever(shellTaskOrganizer.getRunningTaskInfo(task.taskId)).thenReturn(task) } if (deskId != null) { taskRepository.addTaskToDesk(displayId, deskId, task.taskId, isVisible = active) } else { taskRepository.addTask(displayId, task.taskId, isVisible = active) } if (!background) { runningTasks.add(task) } Loading libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/splitscreen/StageCoordinatorTests.java +73 −0 Original line number Diff line number Diff line Loading @@ -38,6 +38,8 @@ import static com.google.common.truth.Truth.assertThat; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertNull; import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.anyBoolean; import static org.mockito.ArgumentMatchers.anyInt; Loading @@ -48,6 +50,7 @@ import static org.mockito.Mockito.clearInvocations; import static org.mockito.Mockito.doAnswer; import static org.mockito.Mockito.doReturn; 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 @@ -58,6 +61,7 @@ import android.app.ActivityOptions; import android.app.PendingIntent; import android.content.res.Configuration; import android.graphics.Rect; import android.os.Binder; import android.os.Bundle; import android.os.Handler; import android.os.IBinder; Loading Loading @@ -196,6 +200,7 @@ public class StageCoordinatorTests extends ShellTestCase { when(token.asBinder()).thenReturn(mBinder); when(mRunningTaskInfo.getToken()).thenReturn(token); when(mTaskOrganizer.getRunningTaskInfo(mTaskId)).thenReturn(mRunningTaskInfo); when(mTaskOrganizer.startNewTransition(anyInt(), any())).thenReturn(new Binder()); when(mRootTDAOrganizer.getDisplayAreaInfo(DEFAULT_DISPLAY)).thenReturn(mDisplayAreaInfo); when(mSplitLayout.getTopLeftBounds()).thenReturn(mBounds1); Loading Loading @@ -557,6 +562,60 @@ public class StageCoordinatorTests extends ShellTestCase { assertFalse(c != null && c.getWindowingMode() == WINDOWING_MODE_FULLSCREEN); } @Test @DisableFlags(Flags.FLAG_ENABLE_MULTIPLE_DESKTOPS_BACKEND) public void testRequestEnterSplit_didNotEnterSplitSelect_doesNotApplyTransaction() { final WindowContainerTransaction wct = new WindowContainerTransaction(); mStageCoordinator.registerSplitSelectListener( new TestSplitSelectListener(/* alwaysEnter = */ false)); final IBinder transition = mStageCoordinator.requestEnterSplitSelect(mRunningTaskInfo, wct, SPLIT_POSITION_TOP_OR_LEFT, new Rect(0, 0, 100, 100)); assertNull(transition); verify(mTaskOrganizer, never()).applyTransaction(wct); } @Test @DisableFlags(Flags.FLAG_ENABLE_MULTIPLE_DESKTOPS_BACKEND) public void testRequestEnterSplit_enteredSplitSelect_appliesTransaction() { final WindowContainerTransaction wct = new WindowContainerTransaction(); mStageCoordinator.registerSplitSelectListener( new TestSplitSelectListener(/* alwaysEnter = */ true)); final IBinder transition = mStageCoordinator.requestEnterSplitSelect(mRunningTaskInfo, wct, SPLIT_POSITION_TOP_OR_LEFT, new Rect(0, 0, 100, 100)); assertNull(transition); verify(mTaskOrganizer).applyTransaction(wct); } @Test @EnableFlags(Flags.FLAG_ENABLE_MULTIPLE_DESKTOPS_BACKEND) public void testRequestEnterSplit_didNotEnterSplitSelect_doesNotStartTransition() { final WindowContainerTransaction wct = new WindowContainerTransaction(); mStageCoordinator.registerSplitSelectListener( new TestSplitSelectListener(/* alwaysEnter = */ false)); final IBinder transition = mStageCoordinator.requestEnterSplitSelect(mRunningTaskInfo, wct, SPLIT_POSITION_TOP_OR_LEFT, new Rect(0, 0, 100, 100)); assertNull(transition); } @Test @EnableFlags(Flags.FLAG_ENABLE_MULTIPLE_DESKTOPS_BACKEND) public void testRequestEnterSplit_enteredSplitSelect_startsTransition() { final WindowContainerTransaction wct = new WindowContainerTransaction(); mStageCoordinator.registerSplitSelectListener( new TestSplitSelectListener(/* alwaysEnter = */ true)); final IBinder transition = mStageCoordinator.requestEnterSplitSelect(mRunningTaskInfo, wct, SPLIT_POSITION_TOP_OR_LEFT, new Rect(0, 0, 100, 100)); assertNotNull(transition); } private Transitions createTestTransitions() { ShellInit shellInit = new ShellInit(mMainExecutor); final Transitions t = new Transitions(mContext, shellInit, mock(ShellController.class), Loading @@ -566,4 +625,18 @@ public class StageCoordinatorTests extends ShellTestCase { shellInit.init(); return t; } private static class TestSplitSelectListener implements SplitScreen.SplitSelectListener { private final boolean mAlwaysEnter; TestSplitSelectListener(boolean alwaysEnter) { mAlwaysEnter = alwaysEnter; } @Override public boolean onRequestEnterSplitSelect(ActivityManager.RunningTaskInfo taskInfo, int splitPosition, Rect taskBounds) { return mAlwaysEnter; } } } Loading
libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopTasksController.kt +22 −12 Original line number Diff line number Diff line Loading @@ -2701,10 +2701,12 @@ class DesktopTasksController( /** * Adds split screen changes to a transaction. Note that bounds are not reset here due to * animation; see {@link onDesktopSplitSelectAnimComplete} * * TODO: b/394268248 - desk needs to be deactivated. */ private fun addMoveToSplitChanges(wct: WindowContainerTransaction, taskInfo: RunningTaskInfo) { private fun addMoveToSplitChanges( wct: WindowContainerTransaction, taskInfo: RunningTaskInfo, deskId: Int?, ): RunOnTransitStart? { // This windowing mode is to get the transition animation started; once we complete // split select, we will change windowing mode to undefined and inherit from split stage. // Going to undefined here causes task to flicker to the top left. Loading @@ -2714,11 +2716,12 @@ class DesktopTasksController( // want it overridden in multi-window. wct.setDensityDpi(taskInfo.token, getDefaultDensityDpi()) performDesktopExitCleanupIfNeeded( return performDesktopExitCleanupIfNeeded( taskId = taskInfo.taskId, displayId = taskInfo.displayId, deskId = deskId, wct = wct, forceToFullscreen = false, forceToFullscreen = true, shouldEndUpAtHome = false, ) } Loading Loading @@ -2950,14 +2953,21 @@ class DesktopTasksController( } dragToDesktopTransitionHandler.cancelDragToDesktopTransition(cancelState) } else { val deskId = taskRepository.getDeskIdForTask(taskInfo.taskId) logV("Split requested for task=%d in desk=%d", taskInfo.taskId, deskId) val wct = WindowContainerTransaction() addMoveToSplitChanges(wct, taskInfo) val runOnTransitStart = addMoveToSplitChanges(wct, taskInfo, deskId) val transition = splitScreenController.requestEnterSplitSelect( taskInfo, wct, if (leftOrTop) SPLIT_POSITION_TOP_OR_LEFT else SPLIT_POSITION_BOTTOM_OR_RIGHT, if (leftOrTop) SPLIT_POSITION_TOP_OR_LEFT else SPLIT_POSITION_BOTTOM_OR_RIGHT, taskInfo.configuration.windowConfiguration.bounds, ) if (transition != null) { runOnTransitStart?.invoke(transition) } } } } Loading
libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/SplitScreenController.java +6 −2 Original line number Diff line number Diff line Loading @@ -54,6 +54,7 @@ import android.content.pm.ShortcutInfo; import android.graphics.Rect; import android.os.Bundle; import android.os.Handler; import android.os.IBinder; import android.os.RemoteException; import android.os.UserHandle; import android.util.ArrayMap; Loading Loading @@ -580,10 +581,13 @@ public class SplitScreenController implements SplitDragPolicy.Starter, * @param wct transaction to apply if this is a valid request * @param splitPosition the split position this task should move to * @param taskBounds current freeform bounds of the task entering split * * @return the token of the transition that started as a result of entering split select. */ public void requestEnterSplitSelect(ActivityManager.RunningTaskInfo taskInfo, @Nullable public IBinder requestEnterSplitSelect(ActivityManager.RunningTaskInfo taskInfo, WindowContainerTransaction wct, int splitPosition, Rect taskBounds) { mStageCoordinator.requestEnterSplitSelect(taskInfo, wct, splitPosition, taskBounds); return mStageCoordinator.requestEnterSplitSelect(taskInfo, wct, splitPosition, taskBounds); } /** Loading
libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/StageCoordinator.java +12 −2 Original line number Diff line number Diff line Loading @@ -122,6 +122,7 @@ import android.view.RemoteAnimationTarget; import android.view.SurfaceControl; import android.view.WindowManager; import android.widget.Toast; import android.window.DesktopExperienceFlags; import android.window.DisplayAreaInfo; import android.window.RemoteTransition; import android.window.TransitionInfo; Loading Loading @@ -219,6 +220,7 @@ public class StageCoordinator implements SplitLayout.SplitLayoutHandler, private final Context mContext; private final List<SplitScreen.SplitScreenListener> mListeners = new ArrayList<>(); private final Set<SplitScreen.SplitSelectListener> mSelectListeners = new HashSet<>(); private final Transitions mTransitions; private final DisplayController mDisplayController; private final DisplayImeController mDisplayImeController; private final DisplayInsetsController mDisplayInsetsController; Loading Loading @@ -419,6 +421,7 @@ public class StageCoordinator implements SplitLayout.SplitLayoutHandler, iconProvider, mWindowDecorViewModel, STAGE_TYPE_SIDE); } mTransitions = transitions; mDisplayController = displayController; mDisplayImeController = displayImeController; mDisplayInsetsController = displayInsetsController; Loading Loading @@ -455,6 +458,7 @@ public class StageCoordinator implements SplitLayout.SplitLayoutHandler, mTaskOrganizer = taskOrganizer; mMainStage = mainStage; mSideStage = sideStage; mTransitions = transitions; mDisplayController = displayController; mDisplayImeController = displayImeController; mDisplayInsetsController = displayInsetsController; Loading Loading @@ -660,16 +664,22 @@ public class StageCoordinator implements SplitLayout.SplitLayoutHandler, return mLogger; } void requestEnterSplitSelect(ActivityManager.RunningTaskInfo taskInfo, @Nullable IBinder requestEnterSplitSelect(ActivityManager.RunningTaskInfo taskInfo, WindowContainerTransaction wct, int splitPosition, Rect taskBounds) { boolean enteredSplitSelect = false; for (SplitScreen.SplitSelectListener listener : mSelectListeners) { enteredSplitSelect |= listener.onRequestEnterSplitSelect(taskInfo, splitPosition, taskBounds); } if (enteredSplitSelect) { if (!enteredSplitSelect) { return null; } if (!DesktopExperienceFlags.ENABLE_MULTIPLE_DESKTOPS_BACKEND.isTrue()) { mTaskOrganizer.applyTransaction(wct); return null; } return mTransitions.startTransition(TRANSIT_CHANGE, wct, /* handler= */ null); } void startShortcut(String packageName, String shortcutId, @SplitPosition int position, Loading
libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/desktopmode/DesktopTasksControllerTest.kt +24 −1 Original line number Diff line number Diff line Loading @@ -5248,6 +5248,24 @@ class DesktopTasksControllerTest(flags: FlagsParameterization) : ShellTestCase() assertThat(wctArgument.firstValue.hierarchyOps).isEmpty() } @Test @EnableFlags(Flags.FLAG_ENABLE_MULTIPLE_DESKTOPS_BACKEND) fun enterSplit_wasInDesk_deactivatesDesk() { val deskId = 5 taskRepository.addDesk(displayId = DEFAULT_DISPLAY, deskId = deskId) taskRepository.setActiveDesk(displayId = DEFAULT_DISPLAY, deskId = deskId) val task = setUpFreeformTask(displayId = DEFAULT_DISPLAY, deskId = deskId) val transition = Binder() whenever(splitScreenController.requestEnterSplitSelect(eq(task), any(), any(), any())) .thenReturn(transition) controller.requestSplit(task, leftOrTop = false) verify(desksOrganizer).deactivateDesk(any(), eq(deskId)) verify(desksTransitionsObserver) .addPendingTransition(DeskTransition.DeactivateDesk(transition, deskId)) } @Test @EnableFlags(Flags.FLAG_ENABLE_DESKTOP_WINDOWING_MULTI_INSTANCE_FEATURES) fun newWindow_fromFullscreenOpensInSplit() { Loading Loading @@ -6601,6 +6619,7 @@ class DesktopTasksControllerTest(flags: FlagsParameterization) : ShellTestCase() bounds: Rect? = null, active: Boolean = true, background: Boolean = false, deskId: Int? = null, ): RunningTaskInfo { val task = createFreeformTask(displayId, bounds) val activityInfo = ActivityInfo() Loading @@ -6613,7 +6632,11 @@ class DesktopTasksControllerTest(flags: FlagsParameterization) : ShellTestCase() } else { whenever(shellTaskOrganizer.getRunningTaskInfo(task.taskId)).thenReturn(task) } if (deskId != null) { taskRepository.addTaskToDesk(displayId, deskId, task.taskId, isVisible = active) } else { taskRepository.addTask(displayId, task.taskId, isVisible = active) } if (!background) { runningTasks.add(task) } Loading
libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/splitscreen/StageCoordinatorTests.java +73 −0 Original line number Diff line number Diff line Loading @@ -38,6 +38,8 @@ import static com.google.common.truth.Truth.assertThat; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertNull; import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.anyBoolean; import static org.mockito.ArgumentMatchers.anyInt; Loading @@ -48,6 +50,7 @@ import static org.mockito.Mockito.clearInvocations; import static org.mockito.Mockito.doAnswer; import static org.mockito.Mockito.doReturn; 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 @@ -58,6 +61,7 @@ import android.app.ActivityOptions; import android.app.PendingIntent; import android.content.res.Configuration; import android.graphics.Rect; import android.os.Binder; import android.os.Bundle; import android.os.Handler; import android.os.IBinder; Loading Loading @@ -196,6 +200,7 @@ public class StageCoordinatorTests extends ShellTestCase { when(token.asBinder()).thenReturn(mBinder); when(mRunningTaskInfo.getToken()).thenReturn(token); when(mTaskOrganizer.getRunningTaskInfo(mTaskId)).thenReturn(mRunningTaskInfo); when(mTaskOrganizer.startNewTransition(anyInt(), any())).thenReturn(new Binder()); when(mRootTDAOrganizer.getDisplayAreaInfo(DEFAULT_DISPLAY)).thenReturn(mDisplayAreaInfo); when(mSplitLayout.getTopLeftBounds()).thenReturn(mBounds1); Loading Loading @@ -557,6 +562,60 @@ public class StageCoordinatorTests extends ShellTestCase { assertFalse(c != null && c.getWindowingMode() == WINDOWING_MODE_FULLSCREEN); } @Test @DisableFlags(Flags.FLAG_ENABLE_MULTIPLE_DESKTOPS_BACKEND) public void testRequestEnterSplit_didNotEnterSplitSelect_doesNotApplyTransaction() { final WindowContainerTransaction wct = new WindowContainerTransaction(); mStageCoordinator.registerSplitSelectListener( new TestSplitSelectListener(/* alwaysEnter = */ false)); final IBinder transition = mStageCoordinator.requestEnterSplitSelect(mRunningTaskInfo, wct, SPLIT_POSITION_TOP_OR_LEFT, new Rect(0, 0, 100, 100)); assertNull(transition); verify(mTaskOrganizer, never()).applyTransaction(wct); } @Test @DisableFlags(Flags.FLAG_ENABLE_MULTIPLE_DESKTOPS_BACKEND) public void testRequestEnterSplit_enteredSplitSelect_appliesTransaction() { final WindowContainerTransaction wct = new WindowContainerTransaction(); mStageCoordinator.registerSplitSelectListener( new TestSplitSelectListener(/* alwaysEnter = */ true)); final IBinder transition = mStageCoordinator.requestEnterSplitSelect(mRunningTaskInfo, wct, SPLIT_POSITION_TOP_OR_LEFT, new Rect(0, 0, 100, 100)); assertNull(transition); verify(mTaskOrganizer).applyTransaction(wct); } @Test @EnableFlags(Flags.FLAG_ENABLE_MULTIPLE_DESKTOPS_BACKEND) public void testRequestEnterSplit_didNotEnterSplitSelect_doesNotStartTransition() { final WindowContainerTransaction wct = new WindowContainerTransaction(); mStageCoordinator.registerSplitSelectListener( new TestSplitSelectListener(/* alwaysEnter = */ false)); final IBinder transition = mStageCoordinator.requestEnterSplitSelect(mRunningTaskInfo, wct, SPLIT_POSITION_TOP_OR_LEFT, new Rect(0, 0, 100, 100)); assertNull(transition); } @Test @EnableFlags(Flags.FLAG_ENABLE_MULTIPLE_DESKTOPS_BACKEND) public void testRequestEnterSplit_enteredSplitSelect_startsTransition() { final WindowContainerTransaction wct = new WindowContainerTransaction(); mStageCoordinator.registerSplitSelectListener( new TestSplitSelectListener(/* alwaysEnter = */ true)); final IBinder transition = mStageCoordinator.requestEnterSplitSelect(mRunningTaskInfo, wct, SPLIT_POSITION_TOP_OR_LEFT, new Rect(0, 0, 100, 100)); assertNotNull(transition); } private Transitions createTestTransitions() { ShellInit shellInit = new ShellInit(mMainExecutor); final Transitions t = new Transitions(mContext, shellInit, mock(ShellController.class), Loading @@ -566,4 +625,18 @@ public class StageCoordinatorTests extends ShellTestCase { shellInit.init(); return t; } private static class TestSplitSelectListener implements SplitScreen.SplitSelectListener { private final boolean mAlwaysEnter; TestSplitSelectListener(boolean alwaysEnter) { mAlwaysEnter = alwaysEnter; } @Override public boolean onRequestEnterSplitSelect(ActivityManager.RunningTaskInfo taskInfo, int splitPosition, Rect taskBounds) { return mAlwaysEnter; } } }