Loading libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopTasksController.kt +38 −18 Original line number Diff line number Diff line Loading @@ -1333,10 +1333,7 @@ class DesktopTasksController( remoteTransition: RemoteTransition? = null, unminimizeReason: UnminimizeReason = UnminimizeReason.UNKNOWN, ) { val deskId = taskRepository.getDeskIdForTask(taskInfo.taskId) ?: getOrCreateDefaultDeskId(taskInfo.displayId) ?: return val deskId = taskRepository.getDeskIdForTask(taskInfo.taskId) logV("moveTaskToFront taskId=%s deskId=%s", taskInfo.taskId, deskId) // If a task is tiled, another task should be brought to foreground with it so let // tiling controller handle the request. Loading @@ -1344,10 +1341,12 @@ class DesktopTasksController( return } val wct = WindowContainerTransaction() if (DesktopExperienceFlags.ENABLE_MULTIPLE_DESKTOPS_BACKEND.isTrue) { desksOrganizer.reorderTaskToFront(wct, deskId, taskInfo) } else { if (deskId == null || !DesktopExperienceFlags.ENABLE_MULTIPLE_DESKTOPS_BACKEND.isTrue) { // Not a desktop task, just move to the front. wct.reorder(taskInfo.token, /* onTop= */ true, /* includingParents= */ true) } else { // A desktop task with multiple desks enabled, reorder it within its desk. desksOrganizer.reorderTaskToFront(wct, deskId, taskInfo) } startLaunchTransition( transitionType = TRANSIT_TO_FRONT, Loading @@ -1360,13 +1359,26 @@ class DesktopTasksController( ) } /** * Starts a launch transition with [transitionType] using [wct]. * * @param transitionType the type of transition to start. * @param wct the wct to use in the transition, which may already container changes. * @param launchingTaskId the id of task launching, may be null if starting the task through an * intent in the [wct]. * @param remoteTransition the remote transition associated with this transition start. * @param deskId may be null if the launching task isn't launching into a desk, such as when * fullscreen or split tasks are just moved to front. * @param displayId the display in which the launch is happening. * @param unminimizeReason the reason to unminimize. */ @VisibleForTesting fun startLaunchTransition( transitionType: Int, wct: WindowContainerTransaction, launchingTaskId: Int?, remoteTransition: RemoteTransition? = null, deskId: Int, deskId: Int?, displayId: Int, unminimizeReason: UnminimizeReason = UnminimizeReason.UNKNOWN, ): IBinder { Loading @@ -1381,12 +1393,14 @@ class DesktopTasksController( var launchTransaction = wct // TODO: b/32994943 - remove dead code when cleaning up task_limit_separate_transition flag val taskIdToMinimize = deskId?.let { addAndGetMinimizeChanges( deskId, launchTransaction, deskId = it, wct = launchTransaction, newTaskId = launchingTaskId, launchingNewIntent = launchingTaskId == null, ) } val exitImmersiveResult = desktopImmersiveController.exitImmersiveIfApplicable( wct = launchTransaction, Loading @@ -1397,11 +1411,11 @@ class DesktopTasksController( var activationRunOnTransitStart: RunOnTransitStart? = null val shouldActivateDesk = when { deskId == null -> false DesktopExperienceFlags.ENABLE_MULTIPLE_DESKTOPS_BACKEND.isTrue -> !taskRepository.isDeskActive(deskId) DesktopExperienceFlags.ENABLE_DISPLAY_WINDOWING_MODE_SWITCHING.isTrue -> { DesktopExperienceFlags.ENABLE_DISPLAY_WINDOWING_MODE_SWITCHING.isTrue -> !isAnyDeskActive(displayId) } else -> false } if (shouldActivateDesk) { Loading @@ -1409,7 +1423,11 @@ class DesktopTasksController( // TODO: b/391485148 - pass in the launching task here to apply task-limit policy, // but make sure to not do it twice since it is also done at the start of this // function. activationRunOnTransitStart = addDeskActivationChanges(deskId, activateDeskWct) activationRunOnTransitStart = addDeskActivationChanges( deskId = checkNotNull(deskId) { "Desk id must be non-null when activating" }, wct = activateDeskWct, ) // Desk activation must be handled before app launch-related transactions. activateDeskWct.merge(launchTransaction, /* transfer= */ true) launchTransaction = activateDeskWct Loading Loading @@ -1447,7 +1465,9 @@ class DesktopTasksController( if (taskIdToMinimize != null) { addPendingMinimizeTransition(t, taskIdToMinimize, MinimizeReason.TASK_LIMIT) } if (deskId != null) { addPendingTaskLimitTransition(t, deskId, launchingTaskId) } if (launchingTaskId != null && taskRepository.isMinimizedTask(launchingTaskId)) { addPendingUnminimizeTransition(t, displayId, launchingTaskId, unminimizeReason) } Loading libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/DesktopModeWindowDecorViewModel.java +6 −0 Original line number Diff line number Diff line Loading @@ -1252,6 +1252,12 @@ public class DesktopModeWindowDecorViewModel implements WindowDecorViewModel, private void moveTaskToFront(RunningTaskInfo taskInfo) { if (!mFocusTransitionObserver.hasGlobalFocus(taskInfo)) { ProtoLog.d(WM_SHELL_DESKTOP_MODE, "%s: task#%d in display#%d does not have global focus, moving to front " + "globallyFocusedTaskId=%d globallyFocusedDisplayId=%d", TAG, taskInfo.taskId, taskInfo.displayId, mFocusTransitionObserver.getGloballyFocusedTaskId(), mFocusTransitionObserver.getGloballyFocusedDisplayId()); mDesktopModeUiEventLogger.log(taskInfo, DesktopUiEventEnum.DESKTOP_WINDOW_HEADER_TAP_TO_REFOCUS); mDesktopTasksController.moveTaskToFront(taskInfo); Loading libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/desktopmode/DesktopTasksControllerTest.kt +57 −5 Original line number Diff line number Diff line Loading @@ -1543,6 +1543,7 @@ class DesktopTasksControllerTest(flags: FlagsParameterization) : ShellTestCase() } @Test @EnableFlags(Flags.FLAG_ENABLE_DISPLAY_WINDOWING_MODE_SWITCHING) fun launchIntent_taskInDesktopMode_onSecondaryDisplay_transitionStarted() { setUpLandscapeDisplay() taskRepository.addDesk(SECOND_DISPLAY, deskId = 2) Loading Loading @@ -2736,7 +2737,7 @@ class DesktopTasksControllerTest(flags: FlagsParameterization) : ShellTestCase() @Test @EnableFlags(Flags.FLAG_ENABLE_MULTIPLE_DESKTOPS_BACKEND) fun moveTaskToFront_reordersToFront() { fun moveTaskToFront_desktopTask_reordersToFront() { val task1 = setUpFreeformTask(displayId = DEFAULT_DISPLAY, deskId = 0) setUpFreeformTask(displayId = DEFAULT_DISPLAY, deskId = 0) whenever( Loading @@ -2755,6 +2756,50 @@ class DesktopTasksControllerTest(flags: FlagsParameterization) : ShellTestCase() verify(desksOrganizer).reorderTaskToFront(any(), eq(0), eq(task1)) } @Test @EnableFlags(Flags.FLAG_ENABLE_MULTIPLE_DESKTOPS_BACKEND) fun moveTaskToFront_nonDesktopTask_reordersToFront() { val task = setUpFullscreenTask(displayId = DEFAULT_DISPLAY) whenever( desktopMixedTransitionHandler.startLaunchTransition( eq(TRANSIT_TO_FRONT), any(), eq(task.taskId), anyOrNull(), anyOrNull(), ) ) .thenReturn(Binder()) controller.moveTaskToFront(task, remoteTransition = null) val wct = getLatestDesktopMixedTaskWct(type = TRANSIT_TO_FRONT) assertNotNull(wct) wct.assertReorder(task = task, toTop = true, includingParents = true) } @Test @EnableFlags(Flags.FLAG_ENABLE_MULTIPLE_DESKTOPS_BACKEND) fun moveTaskToFront_nonDesktopTask_doesNotActivateDesk() { val task = setUpFullscreenTask(displayId = DEFAULT_DISPLAY) whenever( desktopMixedTransitionHandler.startLaunchTransition( eq(TRANSIT_TO_FRONT), any(), eq(task.taskId), anyOrNull(), anyOrNull(), ) ) .thenReturn(Binder()) controller.moveTaskToFront(task, remoteTransition = null) val wct = getLatestDesktopMixedTaskWct(type = TRANSIT_TO_FRONT) assertNotNull(wct) verify(desksOrganizer, never()).activateDesk(eq(wct), any()) } @Test @DisableFlags( Flags.FLAG_ENABLE_MULTIPLE_DESKTOPS_BACKEND, Loading Loading @@ -8544,6 +8589,7 @@ class DesktopTasksControllerTest(flags: FlagsParameterization) : ShellTestCase() @EnableFlags( Flags.FLAG_ENABLE_DESKTOP_WINDOWING_WALLPAPER_ACTIVITY, Flags.FLAG_ENABLE_DESKTOP_WALLPAPER_ACTIVITY_FOR_SYSTEM_USER, Flags.FLAG_ENABLE_DISPLAY_WINDOWING_MODE_SWITCHING, ) fun startLaunchTransition_desktopNotShowing_movesWallpaperToFront() { taskRepository.setDeskInactive(deskId = 0) Loading Loading @@ -9215,11 +9261,15 @@ private fun WindowContainerTransaction.indexOfReorder( return indexOfReorder(task.token, toTop) } private class ReorderPredicate(val token: WindowContainerToken, val toTop: Boolean? = null) : ((WindowContainerTransaction.HierarchyOp) -> Boolean) { private class ReorderPredicate( val token: WindowContainerToken, val toTop: Boolean? = null, val includingParents: Boolean? = null, ) : ((WindowContainerTransaction.HierarchyOp) -> Boolean) { override fun invoke(hop: WindowContainerTransaction.HierarchyOp): Boolean = hop.type == HIERARCHY_OP_TYPE_REORDER && (toTop == null || hop.toTop == toTop) && (includingParents == null || hop.includingParents() == includingParents) && hop.container == token.asBinder() } Loading @@ -9238,15 +9288,17 @@ private class ReparentPredicate( private fun WindowContainerTransaction.assertReorder( task: RunningTaskInfo, toTop: Boolean? = null, includingParents: Boolean? = null, ) { assertReorder(task.token, toTop) assertReorder(task.token, toTop, includingParents) } private fun WindowContainerTransaction.assertReorder( token: WindowContainerToken, toTop: Boolean? = null, includingParents: Boolean? = null, ) { assertHop(ReorderPredicate(token, toTop)) assertHop(ReorderPredicate(token, toTop, includingParents)) } private fun WindowContainerTransaction.assertReorderAt( Loading Loading
libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopTasksController.kt +38 −18 Original line number Diff line number Diff line Loading @@ -1333,10 +1333,7 @@ class DesktopTasksController( remoteTransition: RemoteTransition? = null, unminimizeReason: UnminimizeReason = UnminimizeReason.UNKNOWN, ) { val deskId = taskRepository.getDeskIdForTask(taskInfo.taskId) ?: getOrCreateDefaultDeskId(taskInfo.displayId) ?: return val deskId = taskRepository.getDeskIdForTask(taskInfo.taskId) logV("moveTaskToFront taskId=%s deskId=%s", taskInfo.taskId, deskId) // If a task is tiled, another task should be brought to foreground with it so let // tiling controller handle the request. Loading @@ -1344,10 +1341,12 @@ class DesktopTasksController( return } val wct = WindowContainerTransaction() if (DesktopExperienceFlags.ENABLE_MULTIPLE_DESKTOPS_BACKEND.isTrue) { desksOrganizer.reorderTaskToFront(wct, deskId, taskInfo) } else { if (deskId == null || !DesktopExperienceFlags.ENABLE_MULTIPLE_DESKTOPS_BACKEND.isTrue) { // Not a desktop task, just move to the front. wct.reorder(taskInfo.token, /* onTop= */ true, /* includingParents= */ true) } else { // A desktop task with multiple desks enabled, reorder it within its desk. desksOrganizer.reorderTaskToFront(wct, deskId, taskInfo) } startLaunchTransition( transitionType = TRANSIT_TO_FRONT, Loading @@ -1360,13 +1359,26 @@ class DesktopTasksController( ) } /** * Starts a launch transition with [transitionType] using [wct]. * * @param transitionType the type of transition to start. * @param wct the wct to use in the transition, which may already container changes. * @param launchingTaskId the id of task launching, may be null if starting the task through an * intent in the [wct]. * @param remoteTransition the remote transition associated with this transition start. * @param deskId may be null if the launching task isn't launching into a desk, such as when * fullscreen or split tasks are just moved to front. * @param displayId the display in which the launch is happening. * @param unminimizeReason the reason to unminimize. */ @VisibleForTesting fun startLaunchTransition( transitionType: Int, wct: WindowContainerTransaction, launchingTaskId: Int?, remoteTransition: RemoteTransition? = null, deskId: Int, deskId: Int?, displayId: Int, unminimizeReason: UnminimizeReason = UnminimizeReason.UNKNOWN, ): IBinder { Loading @@ -1381,12 +1393,14 @@ class DesktopTasksController( var launchTransaction = wct // TODO: b/32994943 - remove dead code when cleaning up task_limit_separate_transition flag val taskIdToMinimize = deskId?.let { addAndGetMinimizeChanges( deskId, launchTransaction, deskId = it, wct = launchTransaction, newTaskId = launchingTaskId, launchingNewIntent = launchingTaskId == null, ) } val exitImmersiveResult = desktopImmersiveController.exitImmersiveIfApplicable( wct = launchTransaction, Loading @@ -1397,11 +1411,11 @@ class DesktopTasksController( var activationRunOnTransitStart: RunOnTransitStart? = null val shouldActivateDesk = when { deskId == null -> false DesktopExperienceFlags.ENABLE_MULTIPLE_DESKTOPS_BACKEND.isTrue -> !taskRepository.isDeskActive(deskId) DesktopExperienceFlags.ENABLE_DISPLAY_WINDOWING_MODE_SWITCHING.isTrue -> { DesktopExperienceFlags.ENABLE_DISPLAY_WINDOWING_MODE_SWITCHING.isTrue -> !isAnyDeskActive(displayId) } else -> false } if (shouldActivateDesk) { Loading @@ -1409,7 +1423,11 @@ class DesktopTasksController( // TODO: b/391485148 - pass in the launching task here to apply task-limit policy, // but make sure to not do it twice since it is also done at the start of this // function. activationRunOnTransitStart = addDeskActivationChanges(deskId, activateDeskWct) activationRunOnTransitStart = addDeskActivationChanges( deskId = checkNotNull(deskId) { "Desk id must be non-null when activating" }, wct = activateDeskWct, ) // Desk activation must be handled before app launch-related transactions. activateDeskWct.merge(launchTransaction, /* transfer= */ true) launchTransaction = activateDeskWct Loading Loading @@ -1447,7 +1465,9 @@ class DesktopTasksController( if (taskIdToMinimize != null) { addPendingMinimizeTransition(t, taskIdToMinimize, MinimizeReason.TASK_LIMIT) } if (deskId != null) { addPendingTaskLimitTransition(t, deskId, launchingTaskId) } if (launchingTaskId != null && taskRepository.isMinimizedTask(launchingTaskId)) { addPendingUnminimizeTransition(t, displayId, launchingTaskId, unminimizeReason) } Loading
libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/DesktopModeWindowDecorViewModel.java +6 −0 Original line number Diff line number Diff line Loading @@ -1252,6 +1252,12 @@ public class DesktopModeWindowDecorViewModel implements WindowDecorViewModel, private void moveTaskToFront(RunningTaskInfo taskInfo) { if (!mFocusTransitionObserver.hasGlobalFocus(taskInfo)) { ProtoLog.d(WM_SHELL_DESKTOP_MODE, "%s: task#%d in display#%d does not have global focus, moving to front " + "globallyFocusedTaskId=%d globallyFocusedDisplayId=%d", TAG, taskInfo.taskId, taskInfo.displayId, mFocusTransitionObserver.getGloballyFocusedTaskId(), mFocusTransitionObserver.getGloballyFocusedDisplayId()); mDesktopModeUiEventLogger.log(taskInfo, DesktopUiEventEnum.DESKTOP_WINDOW_HEADER_TAP_TO_REFOCUS); mDesktopTasksController.moveTaskToFront(taskInfo); Loading
libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/desktopmode/DesktopTasksControllerTest.kt +57 −5 Original line number Diff line number Diff line Loading @@ -1543,6 +1543,7 @@ class DesktopTasksControllerTest(flags: FlagsParameterization) : ShellTestCase() } @Test @EnableFlags(Flags.FLAG_ENABLE_DISPLAY_WINDOWING_MODE_SWITCHING) fun launchIntent_taskInDesktopMode_onSecondaryDisplay_transitionStarted() { setUpLandscapeDisplay() taskRepository.addDesk(SECOND_DISPLAY, deskId = 2) Loading Loading @@ -2736,7 +2737,7 @@ class DesktopTasksControllerTest(flags: FlagsParameterization) : ShellTestCase() @Test @EnableFlags(Flags.FLAG_ENABLE_MULTIPLE_DESKTOPS_BACKEND) fun moveTaskToFront_reordersToFront() { fun moveTaskToFront_desktopTask_reordersToFront() { val task1 = setUpFreeformTask(displayId = DEFAULT_DISPLAY, deskId = 0) setUpFreeformTask(displayId = DEFAULT_DISPLAY, deskId = 0) whenever( Loading @@ -2755,6 +2756,50 @@ class DesktopTasksControllerTest(flags: FlagsParameterization) : ShellTestCase() verify(desksOrganizer).reorderTaskToFront(any(), eq(0), eq(task1)) } @Test @EnableFlags(Flags.FLAG_ENABLE_MULTIPLE_DESKTOPS_BACKEND) fun moveTaskToFront_nonDesktopTask_reordersToFront() { val task = setUpFullscreenTask(displayId = DEFAULT_DISPLAY) whenever( desktopMixedTransitionHandler.startLaunchTransition( eq(TRANSIT_TO_FRONT), any(), eq(task.taskId), anyOrNull(), anyOrNull(), ) ) .thenReturn(Binder()) controller.moveTaskToFront(task, remoteTransition = null) val wct = getLatestDesktopMixedTaskWct(type = TRANSIT_TO_FRONT) assertNotNull(wct) wct.assertReorder(task = task, toTop = true, includingParents = true) } @Test @EnableFlags(Flags.FLAG_ENABLE_MULTIPLE_DESKTOPS_BACKEND) fun moveTaskToFront_nonDesktopTask_doesNotActivateDesk() { val task = setUpFullscreenTask(displayId = DEFAULT_DISPLAY) whenever( desktopMixedTransitionHandler.startLaunchTransition( eq(TRANSIT_TO_FRONT), any(), eq(task.taskId), anyOrNull(), anyOrNull(), ) ) .thenReturn(Binder()) controller.moveTaskToFront(task, remoteTransition = null) val wct = getLatestDesktopMixedTaskWct(type = TRANSIT_TO_FRONT) assertNotNull(wct) verify(desksOrganizer, never()).activateDesk(eq(wct), any()) } @Test @DisableFlags( Flags.FLAG_ENABLE_MULTIPLE_DESKTOPS_BACKEND, Loading Loading @@ -8544,6 +8589,7 @@ class DesktopTasksControllerTest(flags: FlagsParameterization) : ShellTestCase() @EnableFlags( Flags.FLAG_ENABLE_DESKTOP_WINDOWING_WALLPAPER_ACTIVITY, Flags.FLAG_ENABLE_DESKTOP_WALLPAPER_ACTIVITY_FOR_SYSTEM_USER, Flags.FLAG_ENABLE_DISPLAY_WINDOWING_MODE_SWITCHING, ) fun startLaunchTransition_desktopNotShowing_movesWallpaperToFront() { taskRepository.setDeskInactive(deskId = 0) Loading Loading @@ -9215,11 +9261,15 @@ private fun WindowContainerTransaction.indexOfReorder( return indexOfReorder(task.token, toTop) } private class ReorderPredicate(val token: WindowContainerToken, val toTop: Boolean? = null) : ((WindowContainerTransaction.HierarchyOp) -> Boolean) { private class ReorderPredicate( val token: WindowContainerToken, val toTop: Boolean? = null, val includingParents: Boolean? = null, ) : ((WindowContainerTransaction.HierarchyOp) -> Boolean) { override fun invoke(hop: WindowContainerTransaction.HierarchyOp): Boolean = hop.type == HIERARCHY_OP_TYPE_REORDER && (toTop == null || hop.toTop == toTop) && (includingParents == null || hop.includingParents() == includingParents) && hop.container == token.asBinder() } Loading @@ -9238,15 +9288,17 @@ private class ReparentPredicate( private fun WindowContainerTransaction.assertReorder( task: RunningTaskInfo, toTop: Boolean? = null, includingParents: Boolean? = null, ) { assertReorder(task.token, toTop) assertReorder(task.token, toTop, includingParents) } private fun WindowContainerTransaction.assertReorder( token: WindowContainerToken, toTop: Boolean? = null, includingParents: Boolean? = null, ) { assertHop(ReorderPredicate(token, toTop)) assertHop(ReorderPredicate(token, toTop, includingParents)) } private fun WindowContainerTransaction.assertReorderAt( Loading