Loading core/java/com/android/internal/statusbar/IStatusBar.aidl +6 −0 Original line number Diff line number Diff line Loading @@ -376,4 +376,10 @@ oneway interface IStatusBar * @param packageName of the session for which the output switcher is shown. */ void showMediaOutputSwitcher(String packageName); /** Enters desktop mode. * * @param displayId the id of the current display. */ void enterDesktop(int displayId); } libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopMode.java +4 −0 Original line number Diff line number Diff line Loading @@ -47,4 +47,8 @@ public interface DesktopMode { default void addDesktopGestureExclusionRegionListener(Consumer<Region> listener, Executor callbackExecutor) { } /** Called when requested to go to desktop mode from the current focused app. */ void enterDesktop(int displayId); } libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopTasksController.kt +44 −0 Original line number Diff line number Diff line Loading @@ -21,6 +21,7 @@ import android.app.WindowConfiguration.ACTIVITY_TYPE_HOME import android.app.WindowConfiguration.ACTIVITY_TYPE_STANDARD import android.app.WindowConfiguration.WINDOWING_MODE_FREEFORM import android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN import android.app.WindowConfiguration.WINDOWING_MODE_MULTI_WINDOW import android.app.WindowConfiguration.WINDOWING_MODE_UNDEFINED import android.app.WindowConfiguration.WindowingMode import android.content.Context Loading Loading @@ -240,6 +241,43 @@ class DesktopTasksController( return desktopModeTaskRepository.getVisibleTaskCount(displayId) } /** Enter desktop by using the focused task in given `displayId` */ fun enterDesktop(displayId: Int) { val allFocusedTasks = shellTaskOrganizer.getRunningTasks(displayId).filter { taskInfo -> taskInfo.isFocused && (taskInfo.windowingMode == WINDOWING_MODE_FULLSCREEN || taskInfo.windowingMode == WINDOWING_MODE_MULTI_WINDOW) && taskInfo.activityType != ACTIVITY_TYPE_HOME } if (allFocusedTasks.isNotEmpty()) { when (allFocusedTasks.size) { 2 -> { // Split-screen case where there are two focused tasks, then we find the child // task to move to desktop. val splitFocusedTask = findChildFocusedTask(allFocusedTasks) moveToDesktop(splitFocusedTask) } 1 -> { // Fullscreen case where we move the current focused task. moveToDesktop(allFocusedTasks[0].taskId) } else -> { KtProtoLog.v( WM_SHELL_DESKTOP_MODE, "DesktopTasksController: Cannot enter desktop expected less " + "than 3 focused tasks but found " + allFocusedTasks.size ) } } } } private fun findChildFocusedTask(allFocusedTasks: List<RunningTaskInfo>): RunningTaskInfo { if (allFocusedTasks[0].taskId == allFocusedTasks[1].parentTaskId) return allFocusedTasks[1] return allFocusedTasks[0] } /** Move a task with given `taskId` to desktop */ fun moveToDesktop( taskId: Int, Loading Loading @@ -1012,6 +1050,12 @@ class DesktopTasksController( this@DesktopTasksController.setTaskRegionListener(listener, callbackExecutor) } } override fun enterDesktop(displayId: Int) { mainExecutor.execute { this@DesktopTasksController.enterDesktop(displayId) } } } /** The interface for calls from outside the host process. */ Loading libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/desktopmode/DesktopTasksControllerTest.kt +40 −0 Original line number Diff line number Diff line Loading @@ -734,6 +734,46 @@ class DesktopTasksControllerTest : ShellTestCase() { shellExecutor.flushAll() verify(launchAdjacentController).launchAdjacentEnabled = true } @Test fun enterDesktop_fullscreenTaskIsMovedToDesktop() { val task1 = setUpFullscreenTask() val task2 = setUpFullscreenTask() val task3 = setUpFullscreenTask() task1.isFocused = true task2.isFocused = false task3.isFocused = false controller.enterDesktop(DEFAULT_DISPLAY) val wct = getLatestMoveToDesktopWct() assertThat(wct.changes[task1.token.asBinder()]?.windowingMode) .isEqualTo(WINDOWING_MODE_FREEFORM) } @Test fun enterDesktop_splitScreenTaskIsMovedToDesktop() { val task1 = setUpSplitScreenTask() val task2 = setUpFullscreenTask() val task3 = setUpFullscreenTask() val task4 = setUpSplitScreenTask() task1.isFocused = true task2.isFocused = false task3.isFocused = false task4.isFocused = true task4.parentTaskId = task1.taskId controller.enterDesktop(DEFAULT_DISPLAY) val wct = getLatestMoveToDesktopWct() assertThat(wct.changes[task4.token.asBinder()]?.windowingMode) .isEqualTo(WINDOWING_MODE_FREEFORM) verify(splitScreenController).prepareExitSplitScreen(any(), anyInt(), eq(SplitScreenController.EXIT_REASON_DESKTOP_MODE) ) } private fun setUpFreeformTask(displayId: Int = DEFAULT_DISPLAY): RunningTaskInfo { val task = createFreeformTask(displayId) Loading packages/SystemUI/src/com/android/systemui/statusbar/CommandQueue.java +20 −0 Original line number Diff line number Diff line Loading @@ -177,6 +177,7 @@ public class CommandQueue extends IStatusBar.Stub implements private static final int MSG_CONFIRM_IMMERSIVE_PROMPT = 77 << MSG_SHIFT; private static final int MSG_IMMERSIVE_CHANGED = 78 << MSG_SHIFT; private static final int MSG_SET_QS_TILES = 79 << MSG_SHIFT; private static final int MSG_ENTER_DESKTOP = 80 << MSG_SHIFT; public static final int FLAG_EXCLUDE_NONE = 0; public static final int FLAG_EXCLUDE_SEARCH_PANEL = 1 << 0; public static final int FLAG_EXCLUDE_RECENTS_PANEL = 1 << 1; Loading Loading @@ -520,6 +521,11 @@ public class CommandQueue extends IStatusBar.Stub implements * @see IStatusBar#immersiveModeChanged */ default void immersiveModeChanged(int rootDisplayAreaId, boolean isImmersiveMode) {} /** * @see IStatusBar#enterDesktop(int) */ default void enterDesktop(int displayId) {} } @VisibleForTesting Loading Loading @@ -1420,6 +1426,13 @@ public class CommandQueue extends IStatusBar.Stub implements mHandler.obtainMessage(MSG_GO_TO_FULLSCREEN_FROM_SPLIT).sendToTarget(); } @Override public void enterDesktop(int displayId) { SomeArgs args = SomeArgs.obtain(); args.arg1 = displayId; mHandler.obtainMessage(MSG_ENTER_DESKTOP, args).sendToTarget(); } private final class H extends Handler { private H(Looper l) { super(l); Loading Loading @@ -1914,6 +1927,13 @@ public class CommandQueue extends IStatusBar.Stub implements mCallbacks.get(i).immersiveModeChanged(rootDisplayAreaId, isImmersiveMode); } break; case MSG_ENTER_DESKTOP: args = (SomeArgs) msg.obj; int displayId = args.argi1; for (int i = 0; i < mCallbacks.size(); i++) { mCallbacks.get(i).enterDesktop(displayId); } break; } } } Loading Loading
core/java/com/android/internal/statusbar/IStatusBar.aidl +6 −0 Original line number Diff line number Diff line Loading @@ -376,4 +376,10 @@ oneway interface IStatusBar * @param packageName of the session for which the output switcher is shown. */ void showMediaOutputSwitcher(String packageName); /** Enters desktop mode. * * @param displayId the id of the current display. */ void enterDesktop(int displayId); }
libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopMode.java +4 −0 Original line number Diff line number Diff line Loading @@ -47,4 +47,8 @@ public interface DesktopMode { default void addDesktopGestureExclusionRegionListener(Consumer<Region> listener, Executor callbackExecutor) { } /** Called when requested to go to desktop mode from the current focused app. */ void enterDesktop(int displayId); }
libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopTasksController.kt +44 −0 Original line number Diff line number Diff line Loading @@ -21,6 +21,7 @@ import android.app.WindowConfiguration.ACTIVITY_TYPE_HOME import android.app.WindowConfiguration.ACTIVITY_TYPE_STANDARD import android.app.WindowConfiguration.WINDOWING_MODE_FREEFORM import android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN import android.app.WindowConfiguration.WINDOWING_MODE_MULTI_WINDOW import android.app.WindowConfiguration.WINDOWING_MODE_UNDEFINED import android.app.WindowConfiguration.WindowingMode import android.content.Context Loading Loading @@ -240,6 +241,43 @@ class DesktopTasksController( return desktopModeTaskRepository.getVisibleTaskCount(displayId) } /** Enter desktop by using the focused task in given `displayId` */ fun enterDesktop(displayId: Int) { val allFocusedTasks = shellTaskOrganizer.getRunningTasks(displayId).filter { taskInfo -> taskInfo.isFocused && (taskInfo.windowingMode == WINDOWING_MODE_FULLSCREEN || taskInfo.windowingMode == WINDOWING_MODE_MULTI_WINDOW) && taskInfo.activityType != ACTIVITY_TYPE_HOME } if (allFocusedTasks.isNotEmpty()) { when (allFocusedTasks.size) { 2 -> { // Split-screen case where there are two focused tasks, then we find the child // task to move to desktop. val splitFocusedTask = findChildFocusedTask(allFocusedTasks) moveToDesktop(splitFocusedTask) } 1 -> { // Fullscreen case where we move the current focused task. moveToDesktop(allFocusedTasks[0].taskId) } else -> { KtProtoLog.v( WM_SHELL_DESKTOP_MODE, "DesktopTasksController: Cannot enter desktop expected less " + "than 3 focused tasks but found " + allFocusedTasks.size ) } } } } private fun findChildFocusedTask(allFocusedTasks: List<RunningTaskInfo>): RunningTaskInfo { if (allFocusedTasks[0].taskId == allFocusedTasks[1].parentTaskId) return allFocusedTasks[1] return allFocusedTasks[0] } /** Move a task with given `taskId` to desktop */ fun moveToDesktop( taskId: Int, Loading Loading @@ -1012,6 +1050,12 @@ class DesktopTasksController( this@DesktopTasksController.setTaskRegionListener(listener, callbackExecutor) } } override fun enterDesktop(displayId: Int) { mainExecutor.execute { this@DesktopTasksController.enterDesktop(displayId) } } } /** The interface for calls from outside the host process. */ Loading
libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/desktopmode/DesktopTasksControllerTest.kt +40 −0 Original line number Diff line number Diff line Loading @@ -734,6 +734,46 @@ class DesktopTasksControllerTest : ShellTestCase() { shellExecutor.flushAll() verify(launchAdjacentController).launchAdjacentEnabled = true } @Test fun enterDesktop_fullscreenTaskIsMovedToDesktop() { val task1 = setUpFullscreenTask() val task2 = setUpFullscreenTask() val task3 = setUpFullscreenTask() task1.isFocused = true task2.isFocused = false task3.isFocused = false controller.enterDesktop(DEFAULT_DISPLAY) val wct = getLatestMoveToDesktopWct() assertThat(wct.changes[task1.token.asBinder()]?.windowingMode) .isEqualTo(WINDOWING_MODE_FREEFORM) } @Test fun enterDesktop_splitScreenTaskIsMovedToDesktop() { val task1 = setUpSplitScreenTask() val task2 = setUpFullscreenTask() val task3 = setUpFullscreenTask() val task4 = setUpSplitScreenTask() task1.isFocused = true task2.isFocused = false task3.isFocused = false task4.isFocused = true task4.parentTaskId = task1.taskId controller.enterDesktop(DEFAULT_DISPLAY) val wct = getLatestMoveToDesktopWct() assertThat(wct.changes[task4.token.asBinder()]?.windowingMode) .isEqualTo(WINDOWING_MODE_FREEFORM) verify(splitScreenController).prepareExitSplitScreen(any(), anyInt(), eq(SplitScreenController.EXIT_REASON_DESKTOP_MODE) ) } private fun setUpFreeformTask(displayId: Int = DEFAULT_DISPLAY): RunningTaskInfo { val task = createFreeformTask(displayId) Loading
packages/SystemUI/src/com/android/systemui/statusbar/CommandQueue.java +20 −0 Original line number Diff line number Diff line Loading @@ -177,6 +177,7 @@ public class CommandQueue extends IStatusBar.Stub implements private static final int MSG_CONFIRM_IMMERSIVE_PROMPT = 77 << MSG_SHIFT; private static final int MSG_IMMERSIVE_CHANGED = 78 << MSG_SHIFT; private static final int MSG_SET_QS_TILES = 79 << MSG_SHIFT; private static final int MSG_ENTER_DESKTOP = 80 << MSG_SHIFT; public static final int FLAG_EXCLUDE_NONE = 0; public static final int FLAG_EXCLUDE_SEARCH_PANEL = 1 << 0; public static final int FLAG_EXCLUDE_RECENTS_PANEL = 1 << 1; Loading Loading @@ -520,6 +521,11 @@ public class CommandQueue extends IStatusBar.Stub implements * @see IStatusBar#immersiveModeChanged */ default void immersiveModeChanged(int rootDisplayAreaId, boolean isImmersiveMode) {} /** * @see IStatusBar#enterDesktop(int) */ default void enterDesktop(int displayId) {} } @VisibleForTesting Loading Loading @@ -1420,6 +1426,13 @@ public class CommandQueue extends IStatusBar.Stub implements mHandler.obtainMessage(MSG_GO_TO_FULLSCREEN_FROM_SPLIT).sendToTarget(); } @Override public void enterDesktop(int displayId) { SomeArgs args = SomeArgs.obtain(); args.arg1 = displayId; mHandler.obtainMessage(MSG_ENTER_DESKTOP, args).sendToTarget(); } private final class H extends Handler { private H(Looper l) { super(l); Loading Loading @@ -1914,6 +1927,13 @@ public class CommandQueue extends IStatusBar.Stub implements mCallbacks.get(i).immersiveModeChanged(rootDisplayAreaId, isImmersiveMode); } break; case MSG_ENTER_DESKTOP: args = (SomeArgs) msg.obj; int displayId = args.argi1; for (int i = 0; i < mCallbacks.size(); i++) { mCallbacks.get(i).enterDesktop(displayId); } break; } } } Loading