Loading libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopTasksController.kt +56 −13 Original line number Diff line number Diff line Loading @@ -1079,7 +1079,8 @@ class DesktopTasksController( ) } private fun startLaunchTransition( @VisibleForTesting fun startLaunchTransition( transitionType: Int, wct: WindowContainerTransaction, launchingTaskId: Int?, Loading @@ -1087,34 +1088,52 @@ class DesktopTasksController( displayId: Int = DEFAULT_DISPLAY, unminimizeReason: UnminimizeReason = UnminimizeReason.UNKNOWN, ): IBinder { // TODO: b/397619806 - Consolidate sharable logic with [handleFreeformTaskLaunch]. var launchTransaction = wct val taskIdToMinimize = addAndGetMinimizeChanges( displayId, wct, launchTransaction, newTaskId = launchingTaskId, launchingNewIntent = launchingTaskId == null, ) val exitImmersiveResult = desktopImmersiveController.exitImmersiveIfApplicable( wct = wct, wct = launchTransaction, displayId = displayId, excludeTaskId = launchingTaskId, reason = DesktopImmersiveController.ExitReason.TASK_LAUNCH, ) var deskIdToActivate: Int? = null if ( DesktopExperienceFlags.ENABLE_DISPLAY_WINDOWING_MODE_SWITCHING.isTrue && !isDesktopModeShowing(displayId) ) { deskIdToActivate = checkNotNull( launchingTaskId?.let { taskRepository.getDeskIdForTask(it) } ?: getDefaultDeskId(displayId) ) val activateDeskWct = WindowContainerTransaction() addDeskActivationChanges(deskIdToActivate, activateDeskWct) // Desk activation must be handled before app launch-related transactions. activateDeskWct.merge(launchTransaction, /* transfer= */ true) launchTransaction = activateDeskWct } val t = if (remoteTransition == null) { desktopMixedTransitionHandler.startLaunchTransition( transitionType = transitionType, wct = wct, wct = launchTransaction, taskId = launchingTaskId, minimizingTaskId = taskIdToMinimize, exitingImmersiveTask = exitImmersiveResult.asExit()?.exitingTask, ) } else if (taskIdToMinimize == null) { val remoteTransitionHandler = OneShotRemoteHandler(mainExecutor, remoteTransition) transitions.startTransition(transitionType, wct, remoteTransitionHandler).also { remoteTransitionHandler.setTransition(it) } transitions .startTransition(transitionType, launchTransaction, remoteTransitionHandler) .also { remoteTransitionHandler.setTransition(it) } } else { val remoteTransitionHandler = DesktopWindowLimitRemoteHandler( Loading @@ -1123,9 +1142,9 @@ class DesktopTasksController( remoteTransition, taskIdToMinimize, ) transitions.startTransition(transitionType, wct, remoteTransitionHandler).also { remoteTransitionHandler.setTransition(it) } transitions .startTransition(transitionType, launchTransaction, remoteTransitionHandler) .also { remoteTransitionHandler.setTransition(it) } } if (taskIdToMinimize != null) { addPendingMinimizeTransition(t, taskIdToMinimize, MinimizeReason.TASK_LIMIT) Loading @@ -1133,6 +1152,24 @@ class DesktopTasksController( if (launchingTaskId != null && taskRepository.isMinimizedTask(launchingTaskId)) { addPendingUnminimizeTransition(t, displayId, launchingTaskId, unminimizeReason) } if ( DesktopExperienceFlags.ENABLE_MULTIPLE_DESKTOPS_BACKEND.isTrue && deskIdToActivate != null ) { if (DesktopExperienceFlags.ENABLE_DISPLAY_WINDOWING_MODE_SWITCHING.isTrue) { desksTransitionObserver.addPendingTransition( DeskTransition.ActivateDesk( token = t, displayId = displayId, deskId = deskIdToActivate, ) ) } desktopModeEnterExitTransitionListener?.onEnterDesktopModeTransitionStarted( FREEFORM_ANIMATION_DURATION ) } exitImmersiveResult.asExit()?.runOnTransitionStart?.invoke(t) return t } Loading Loading @@ -2704,10 +2741,9 @@ class DesktopTasksController( activateDesk(deskId, remoteTransition) } /** Activates the given desk. */ fun activateDesk(deskId: Int, remoteTransition: RemoteTransition? = null) { /** Activates the given desk but without starting a transition. */ fun addDeskActivationChanges(deskId: Int, wct: WindowContainerTransaction) { val displayId = taskRepository.getDisplayForDesk(deskId) val wct = WindowContainerTransaction() if (DesktopExperienceFlags.ENABLE_MULTIPLE_DESKTOPS_BACKEND.isTrue) { prepareForDeskActivation(displayId, wct) desksOrganizer.activateDesk(wct, deskId) Loading @@ -2720,6 +2756,13 @@ class DesktopTasksController( } else { bringDesktopAppsToFront(displayId, wct) } } /** Activates the given desk. */ fun activateDesk(deskId: Int, remoteTransition: RemoteTransition? = null) { val displayId = taskRepository.getDisplayForDesk(deskId) val wct = WindowContainerTransaction() addDeskActivationChanges(deskId, wct) val transitionType = transitionType(remoteTransition) val handler = Loading libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/desktopmode/DesktopTasksControllerTest.kt +76 −4 Original line number Diff line number Diff line Loading @@ -2477,8 +2477,7 @@ class DesktopTasksControllerTest(flags: FlagsParameterization) : ShellTestCase() controller.moveTaskToFront(task.taskId, unminimizeReason = UnminimizeReason.UNKNOWN) val wct = getLatestDesktopMixedTaskWct(type = TRANSIT_OPEN) assertThat(wct.hierarchyOps).hasSize(1) wct.assertLaunchTaskAt(0, task.taskId, WINDOWING_MODE_FREEFORM) wct.assertLaunchTask(task.taskId, WINDOWING_MODE_FREEFORM) } @Test Loading Loading @@ -6306,6 +6305,61 @@ class DesktopTasksControllerTest(flags: FlagsParameterization) : ShellTestCase() assertThat(taskRepository.getNumberOfDesks(DEFAULT_DISPLAY)).isEqualTo(currentDeskCount + 1) } @Test @EnableFlags( Flags.FLAG_ENABLE_DESKTOP_WINDOWING_WALLPAPER_ACTIVITY, Flags.FLAG_ENABLE_DESKTOP_WALLPAPER_ACTIVITY_FOR_SYSTEM_USER, ) fun startLaunchTransition_desktopNotShowing_movesWallpaperToFront() { val launchingTask = createFreeformTask() val wct = WindowContainerTransaction() wct.reorder(launchingTask.token, /* onTop= */ true) whenever( desktopMixedTransitionHandler.startLaunchTransition( eq(TRANSIT_OPEN), any(), anyOrNull(), anyOrNull(), anyOrNull(), ) ) .thenReturn(Binder()) controller.startLaunchTransition(TRANSIT_OPEN, wct, launchingTaskId = null) val latestWct = getLatestDesktopMixedTaskWct(type = TRANSIT_OPEN) val launchingTaskReorderIndex = latestWct.indexOfReorder(launchingTask, toTop = true) val wallpaperReorderIndex = latestWct.indexOfReorder(wallpaperToken, toTop = true) assertThat(launchingTaskReorderIndex).isNotEqualTo(-1) assertThat(wallpaperReorderIndex).isNotEqualTo(-1) assertThat(launchingTaskReorderIndex).isGreaterThan(wallpaperReorderIndex) } @Test @EnableFlags( Flags.FLAG_ENABLE_DESKTOP_WINDOWING_WALLPAPER_ACTIVITY, Flags.FLAG_ENABLE_DESKTOP_WALLPAPER_ACTIVITY_FOR_SYSTEM_USER, ) fun startLaunchTransition_desktopShowing_doesNotReorderWallpaper() { val wct = WindowContainerTransaction() whenever( desktopMixedTransitionHandler.startLaunchTransition( eq(TRANSIT_OPEN), any(), anyOrNull(), anyOrNull(), anyOrNull(), ) ) .thenReturn(Binder()) setUpFreeformTask() controller.startLaunchTransition(TRANSIT_OPEN, wct, launchingTaskId = null) val latestWct = getLatestDesktopMixedTaskWct(type = TRANSIT_OPEN) assertNull(latestWct.hierarchyOps.find { op -> op.container == wallpaperToken.asBinder() }) } private class RunOnStartTransitionCallback : ((IBinder) -> Unit) { var invocations = 0 private set Loading Loading @@ -6692,13 +6746,20 @@ private fun WindowContainerTransaction.assertWithoutHop( } private fun WindowContainerTransaction.indexOfReorder( task: RunningTaskInfo, token: WindowContainerToken, toTop: Boolean? = null, ): Int { val hop = hierarchyOps.singleOrNull(ReorderPredicate(task.token, toTop)) ?: return -1 val hop = hierarchyOps.singleOrNull(ReorderPredicate(token, toTop)) ?: return -1 return hierarchyOps.indexOf(hop) } private fun WindowContainerTransaction.indexOfReorder( task: RunningTaskInfo, toTop: Boolean? = null, ): Int { return indexOfReorder(task.token, toTop) } private class ReorderPredicate(val token: WindowContainerToken, val toTop: Boolean? = null) : ((WindowContainerTransaction.HierarchyOp) -> Boolean) { override fun invoke(hop: WindowContainerTransaction.HierarchyOp): Boolean = Loading Loading @@ -6816,6 +6877,17 @@ private fun WindowContainerTransaction.assertPendingIntentAt(index: Int, intent: assertThat(op.pendingIntent?.intent?.categories).isEqualTo(intent.categories) } private fun WindowContainerTransaction.assertLaunchTask(taskId: Int, windowingMode: Int) { val keyLaunchWindowingMode = "android.activity.windowingMode" assertHop { hop -> hop.type == HIERARCHY_OP_TYPE_LAUNCH_TASK && hop.launchOptions?.getInt(LAUNCH_KEY_TASK_ID) == taskId && hop.launchOptions?.getInt(keyLaunchWindowingMode, WINDOWING_MODE_UNDEFINED) == windowingMode } } private fun WindowContainerTransaction.assertLaunchTaskAt( index: Int, taskId: Int, Loading Loading
libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopTasksController.kt +56 −13 Original line number Diff line number Diff line Loading @@ -1079,7 +1079,8 @@ class DesktopTasksController( ) } private fun startLaunchTransition( @VisibleForTesting fun startLaunchTransition( transitionType: Int, wct: WindowContainerTransaction, launchingTaskId: Int?, Loading @@ -1087,34 +1088,52 @@ class DesktopTasksController( displayId: Int = DEFAULT_DISPLAY, unminimizeReason: UnminimizeReason = UnminimizeReason.UNKNOWN, ): IBinder { // TODO: b/397619806 - Consolidate sharable logic with [handleFreeformTaskLaunch]. var launchTransaction = wct val taskIdToMinimize = addAndGetMinimizeChanges( displayId, wct, launchTransaction, newTaskId = launchingTaskId, launchingNewIntent = launchingTaskId == null, ) val exitImmersiveResult = desktopImmersiveController.exitImmersiveIfApplicable( wct = wct, wct = launchTransaction, displayId = displayId, excludeTaskId = launchingTaskId, reason = DesktopImmersiveController.ExitReason.TASK_LAUNCH, ) var deskIdToActivate: Int? = null if ( DesktopExperienceFlags.ENABLE_DISPLAY_WINDOWING_MODE_SWITCHING.isTrue && !isDesktopModeShowing(displayId) ) { deskIdToActivate = checkNotNull( launchingTaskId?.let { taskRepository.getDeskIdForTask(it) } ?: getDefaultDeskId(displayId) ) val activateDeskWct = WindowContainerTransaction() addDeskActivationChanges(deskIdToActivate, activateDeskWct) // Desk activation must be handled before app launch-related transactions. activateDeskWct.merge(launchTransaction, /* transfer= */ true) launchTransaction = activateDeskWct } val t = if (remoteTransition == null) { desktopMixedTransitionHandler.startLaunchTransition( transitionType = transitionType, wct = wct, wct = launchTransaction, taskId = launchingTaskId, minimizingTaskId = taskIdToMinimize, exitingImmersiveTask = exitImmersiveResult.asExit()?.exitingTask, ) } else if (taskIdToMinimize == null) { val remoteTransitionHandler = OneShotRemoteHandler(mainExecutor, remoteTransition) transitions.startTransition(transitionType, wct, remoteTransitionHandler).also { remoteTransitionHandler.setTransition(it) } transitions .startTransition(transitionType, launchTransaction, remoteTransitionHandler) .also { remoteTransitionHandler.setTransition(it) } } else { val remoteTransitionHandler = DesktopWindowLimitRemoteHandler( Loading @@ -1123,9 +1142,9 @@ class DesktopTasksController( remoteTransition, taskIdToMinimize, ) transitions.startTransition(transitionType, wct, remoteTransitionHandler).also { remoteTransitionHandler.setTransition(it) } transitions .startTransition(transitionType, launchTransaction, remoteTransitionHandler) .also { remoteTransitionHandler.setTransition(it) } } if (taskIdToMinimize != null) { addPendingMinimizeTransition(t, taskIdToMinimize, MinimizeReason.TASK_LIMIT) Loading @@ -1133,6 +1152,24 @@ class DesktopTasksController( if (launchingTaskId != null && taskRepository.isMinimizedTask(launchingTaskId)) { addPendingUnminimizeTransition(t, displayId, launchingTaskId, unminimizeReason) } if ( DesktopExperienceFlags.ENABLE_MULTIPLE_DESKTOPS_BACKEND.isTrue && deskIdToActivate != null ) { if (DesktopExperienceFlags.ENABLE_DISPLAY_WINDOWING_MODE_SWITCHING.isTrue) { desksTransitionObserver.addPendingTransition( DeskTransition.ActivateDesk( token = t, displayId = displayId, deskId = deskIdToActivate, ) ) } desktopModeEnterExitTransitionListener?.onEnterDesktopModeTransitionStarted( FREEFORM_ANIMATION_DURATION ) } exitImmersiveResult.asExit()?.runOnTransitionStart?.invoke(t) return t } Loading Loading @@ -2704,10 +2741,9 @@ class DesktopTasksController( activateDesk(deskId, remoteTransition) } /** Activates the given desk. */ fun activateDesk(deskId: Int, remoteTransition: RemoteTransition? = null) { /** Activates the given desk but without starting a transition. */ fun addDeskActivationChanges(deskId: Int, wct: WindowContainerTransaction) { val displayId = taskRepository.getDisplayForDesk(deskId) val wct = WindowContainerTransaction() if (DesktopExperienceFlags.ENABLE_MULTIPLE_DESKTOPS_BACKEND.isTrue) { prepareForDeskActivation(displayId, wct) desksOrganizer.activateDesk(wct, deskId) Loading @@ -2720,6 +2756,13 @@ class DesktopTasksController( } else { bringDesktopAppsToFront(displayId, wct) } } /** Activates the given desk. */ fun activateDesk(deskId: Int, remoteTransition: RemoteTransition? = null) { val displayId = taskRepository.getDisplayForDesk(deskId) val wct = WindowContainerTransaction() addDeskActivationChanges(deskId, wct) val transitionType = transitionType(remoteTransition) val handler = Loading
libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/desktopmode/DesktopTasksControllerTest.kt +76 −4 Original line number Diff line number Diff line Loading @@ -2477,8 +2477,7 @@ class DesktopTasksControllerTest(flags: FlagsParameterization) : ShellTestCase() controller.moveTaskToFront(task.taskId, unminimizeReason = UnminimizeReason.UNKNOWN) val wct = getLatestDesktopMixedTaskWct(type = TRANSIT_OPEN) assertThat(wct.hierarchyOps).hasSize(1) wct.assertLaunchTaskAt(0, task.taskId, WINDOWING_MODE_FREEFORM) wct.assertLaunchTask(task.taskId, WINDOWING_MODE_FREEFORM) } @Test Loading Loading @@ -6306,6 +6305,61 @@ class DesktopTasksControllerTest(flags: FlagsParameterization) : ShellTestCase() assertThat(taskRepository.getNumberOfDesks(DEFAULT_DISPLAY)).isEqualTo(currentDeskCount + 1) } @Test @EnableFlags( Flags.FLAG_ENABLE_DESKTOP_WINDOWING_WALLPAPER_ACTIVITY, Flags.FLAG_ENABLE_DESKTOP_WALLPAPER_ACTIVITY_FOR_SYSTEM_USER, ) fun startLaunchTransition_desktopNotShowing_movesWallpaperToFront() { val launchingTask = createFreeformTask() val wct = WindowContainerTransaction() wct.reorder(launchingTask.token, /* onTop= */ true) whenever( desktopMixedTransitionHandler.startLaunchTransition( eq(TRANSIT_OPEN), any(), anyOrNull(), anyOrNull(), anyOrNull(), ) ) .thenReturn(Binder()) controller.startLaunchTransition(TRANSIT_OPEN, wct, launchingTaskId = null) val latestWct = getLatestDesktopMixedTaskWct(type = TRANSIT_OPEN) val launchingTaskReorderIndex = latestWct.indexOfReorder(launchingTask, toTop = true) val wallpaperReorderIndex = latestWct.indexOfReorder(wallpaperToken, toTop = true) assertThat(launchingTaskReorderIndex).isNotEqualTo(-1) assertThat(wallpaperReorderIndex).isNotEqualTo(-1) assertThat(launchingTaskReorderIndex).isGreaterThan(wallpaperReorderIndex) } @Test @EnableFlags( Flags.FLAG_ENABLE_DESKTOP_WINDOWING_WALLPAPER_ACTIVITY, Flags.FLAG_ENABLE_DESKTOP_WALLPAPER_ACTIVITY_FOR_SYSTEM_USER, ) fun startLaunchTransition_desktopShowing_doesNotReorderWallpaper() { val wct = WindowContainerTransaction() whenever( desktopMixedTransitionHandler.startLaunchTransition( eq(TRANSIT_OPEN), any(), anyOrNull(), anyOrNull(), anyOrNull(), ) ) .thenReturn(Binder()) setUpFreeformTask() controller.startLaunchTransition(TRANSIT_OPEN, wct, launchingTaskId = null) val latestWct = getLatestDesktopMixedTaskWct(type = TRANSIT_OPEN) assertNull(latestWct.hierarchyOps.find { op -> op.container == wallpaperToken.asBinder() }) } private class RunOnStartTransitionCallback : ((IBinder) -> Unit) { var invocations = 0 private set Loading Loading @@ -6692,13 +6746,20 @@ private fun WindowContainerTransaction.assertWithoutHop( } private fun WindowContainerTransaction.indexOfReorder( task: RunningTaskInfo, token: WindowContainerToken, toTop: Boolean? = null, ): Int { val hop = hierarchyOps.singleOrNull(ReorderPredicate(task.token, toTop)) ?: return -1 val hop = hierarchyOps.singleOrNull(ReorderPredicate(token, toTop)) ?: return -1 return hierarchyOps.indexOf(hop) } private fun WindowContainerTransaction.indexOfReorder( task: RunningTaskInfo, toTop: Boolean? = null, ): Int { return indexOfReorder(task.token, toTop) } private class ReorderPredicate(val token: WindowContainerToken, val toTop: Boolean? = null) : ((WindowContainerTransaction.HierarchyOp) -> Boolean) { override fun invoke(hop: WindowContainerTransaction.HierarchyOp): Boolean = Loading Loading @@ -6816,6 +6877,17 @@ private fun WindowContainerTransaction.assertPendingIntentAt(index: Int, intent: assertThat(op.pendingIntent?.intent?.categories).isEqualTo(intent.categories) } private fun WindowContainerTransaction.assertLaunchTask(taskId: Int, windowingMode: Int) { val keyLaunchWindowingMode = "android.activity.windowingMode" assertHop { hop -> hop.type == HIERARCHY_OP_TYPE_LAUNCH_TASK && hop.launchOptions?.getInt(LAUNCH_KEY_TASK_ID) == taskId && hop.launchOptions?.getInt(keyLaunchWindowingMode, WINDOWING_MODE_UNDEFINED) == windowingMode } } private fun WindowContainerTransaction.assertLaunchTaskAt( index: Int, taskId: Int, Loading