Loading libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopTasksController.kt +74 −24 Original line number Diff line number Diff line Loading @@ -127,6 +127,10 @@ import java.util.Optional import java.util.concurrent.Executor import java.util.function.Consumer import com.android.wm.shell.desktopmode.DesktopModeEventLogger.Companion.ResizeTrigger import com.android.wm.shell.desktopmode.DragToDesktopTransitionHandler.Companion.DRAG_TO_DESKTOP_FINISH_ANIM_DURATION_MS import com.android.wm.shell.desktopmode.EnterDesktopTaskTransitionHandler.FREEFORM_ANIMATION_DURATION import com.android.wm.shell.desktopmode.ExitDesktopTaskTransitionHandler.FULLSCREEN_ANIMATION_DURATION /** Handles moving tasks in and out of desktop */ class DesktopTasksController( private val context: Context, Loading Loading @@ -195,6 +199,9 @@ class DesktopTasksController( @VisibleForTesting var taskbarDesktopTaskListener: TaskbarDesktopTaskListener? = null @VisibleForTesting var desktopModeEnterExitTransitionListener: DesktopModeEntryExitTransitionListener? = null /** Task id of the task currently being dragged from fullscreen/split. */ val draggingTaskId get() = dragToDesktopTransitionHandler.draggingTaskId Loading Loading @@ -380,6 +387,7 @@ class DesktopTasksController( ) // TODO(343149901): Add DPI changes for task launch val transition = enterDesktopTaskTransitionHandler.moveToDesktop(wct, transitionSource) desktopModeEnterExitTransitionListener?.onEnterDesktopModeTransitionStarted(FREEFORM_ANIMATION_DURATION) taskIdToMinimize?.let { addPendingMinimizeTransition(transition, it) } exitResult.asExit()?.runOnTransitionStart?.invoke(transition) return true Loading Loading @@ -409,6 +417,7 @@ class DesktopTasksController( addMoveToDesktopChanges(wct, task) val transition = enterDesktopTaskTransitionHandler.moveToDesktop(wct, transitionSource) desktopModeEnterExitTransitionListener?.onEnterDesktopModeTransitionStarted(FREEFORM_ANIMATION_DURATION) taskIdToMinimize?.let { addPendingMinimizeTransition(transition, it) } exitResult.asExit()?.runOnTransitionStart?.invoke(transition) } Loading Loading @@ -450,6 +459,9 @@ class DesktopTasksController( val exitResult = desktopImmersiveController.exitImmersiveIfApplicable( wct, taskInfo.displayId) val transition = dragToDesktopTransitionHandler.finishDragToDesktopTransition(wct) desktopModeEnterExitTransitionListener?.onEnterDesktopModeTransitionStarted( DRAG_TO_DESKTOP_FINISH_ANIM_DURATION_MS.toInt() ) transition?.let { taskIdToMinimize?.let { taskId -> addPendingMinimizeTransition(it, taskId) } exitResult.asExit()?.runOnTransitionStart?.invoke(transition) Loading Loading @@ -485,9 +497,7 @@ class DesktopTasksController( ): ((IBinder) -> Unit)? { val taskId = taskInfo.taskId desktopTilingDecorViewModel.removeTaskIfTiled(displayId, taskId) if (taskRepository.isOnlyVisibleNonClosingTask(taskId)) { removeWallpaperActivity(wct) } performDesktopExitCleanupIfNeeded(taskId, wct) taskRepository.addClosingTask(displayId, taskId) taskbarDesktopTaskListener?.onTaskbarCornerRoundingUpdate( doesAnyTaskRequireTaskbarRounding( Loading @@ -503,11 +513,7 @@ class DesktopTasksController( val taskId = taskInfo.taskId val displayId = taskInfo.displayId val wct = WindowContainerTransaction() if (taskRepository.isOnlyVisibleNonClosingTask(taskId)) { // Perform clean up of the desktop wallpaper activity if the minimized window task is // the last active task. removeWallpaperActivity(wct) } performDesktopExitCleanupIfNeeded(taskId, wct) // Notify immersive handler as it might need to exit immersive state. val exitResult = desktopImmersiveController.exitImmersiveIfApplicable(wct, taskInfo) Loading Loading @@ -576,6 +582,11 @@ class DesktopTasksController( position, mOnAnimationFinishedCallback ) // handles case where we are moving to full screen without closing all DW tasks. if (!taskRepository.isOnlyVisibleNonClosingTask(task.taskId)) { desktopModeEnterExitTransitionListener?.onExitDesktopModeTransitionStarted(FULLSCREEN_ANIMATION_DURATION) } } /** Loading Loading @@ -1226,6 +1237,21 @@ class DesktopTasksController( } } /** * Remove wallpaper activity if task provided is last task and wallpaper activity token is not * null */ private fun performDesktopExitCleanupIfNeeded(taskId: Int, wct: WindowContainerTransaction) { if (!taskRepository.isOnlyVisibleNonClosingTask(taskId)) { return } desktopModeEnterExitTransitionListener?.onExitDesktopModeTransitionStarted(FULLSCREEN_ANIMATION_DURATION) if (taskRepository.wallpaperActivityToken != null) { removeWallpaperActivity(wct) } } fun releaseVisualIndicator() { val t = SurfaceControl.Transaction() visualIndicator?.releaseVisualIndicator(t) Loading Loading @@ -1662,12 +1688,7 @@ class DesktopTasksController( return null val wct = WindowContainerTransaction() if (taskRepository.isOnlyVisibleNonClosingTask(task.taskId) && taskRepository.wallpaperActivityToken != null ) { // Remove wallpaper activity when the last active task is removed removeWallpaperActivity(wct) } performDesktopExitCleanupIfNeeded(task.taskId, wct) if (!DesktopModeFlags.ENABLE_DESKTOP_WINDOWING_BACK_NAVIGATION.isTrue()) { taskRepository.addClosingTask(task.displayId, task.taskId) Loading Loading @@ -1758,10 +1779,8 @@ class DesktopTasksController( if (useDesktopOverrideDensity()) { wct.setDensityDpi(taskInfo.token, getDefaultDensityDpi()) } if (taskRepository.isOnlyVisibleNonClosingTask(taskInfo.taskId)) { // Remove wallpaper activity when leaving desktop mode removeWallpaperActivity(wct) } performDesktopExitCleanupIfNeeded(taskInfo.taskId, wct) } private fun cascadeWindow(bounds: Rect, displayLayout: DisplayLayout, displayId: Int) { Loading Loading @@ -1790,10 +1809,8 @@ class DesktopTasksController( // The task's density may have been overridden in freeform; revert it here as we don't // want it overridden in multi-window. wct.setDensityDpi(taskInfo.token, getDefaultDensityDpi()) if (taskRepository.isOnlyVisibleNonClosingTask(taskInfo.taskId)) { // Remove wallpaper activity when leaving desktop mode removeWallpaperActivity(wct) } performDesktopExitCleanupIfNeeded(taskInfo.taskId, wct) } /** Returns the ID of the Task that will be minimized, or null if no task will be minimized. */ Loading Loading @@ -2331,7 +2348,7 @@ class DesktopTasksController( } } private val mTaskbarDesktopTaskListener: TaskbarDesktopTaskListener = private val taskbarDesktopTaskListener: TaskbarDesktopTaskListener = object : TaskbarDesktopTaskListener { override fun onTaskbarCornerRoundingUpdate( hasTasksRequiringTaskbarRounding: Boolean) { Loading @@ -2348,6 +2365,27 @@ class DesktopTasksController( } } private val desktopModeEntryExitTransitionListener: DesktopModeEntryExitTransitionListener = object : DesktopModeEntryExitTransitionListener { override fun onEnterDesktopModeTransitionStarted(transitionDuration: Int) { ProtoLog.v( WM_SHELL_DESKTOP_MODE, "IDesktopModeImpl: onEnterDesktopModeTransitionStarted transitionTime=%s", transitionDuration ) remoteListener.call { l -> l.onEnterDesktopModeTransitionStarted(transitionDuration) } } override fun onExitDesktopModeTransitionStarted(transitionDuration: Int) { ProtoLog.v( WM_SHELL_DESKTOP_MODE, "IDesktopModeImpl: onExitDesktopModeTransitionStarted transitionTime=%s", transitionDuration ) remoteListener.call { l -> l.onExitDesktopModeTransitionStarted(transitionDuration) } } } init { remoteListener = SingleInstanceRemoteListener<DesktopTasksController, IDesktopTaskListener>( Loading @@ -2355,13 +2393,16 @@ class DesktopTasksController( { c -> run { c.taskRepository.addVisibleTasksListener(listener, c.mainExecutor) c.taskbarDesktopTaskListener = mTaskbarDesktopTaskListener c.taskbarDesktopTaskListener = taskbarDesktopTaskListener c.desktopModeEnterExitTransitionListener = desktopModeEntryExitTransitionListener } }, { c -> run { c.taskRepository.removeVisibleTasksListener(listener) c.taskbarDesktopTaskListener = null c.desktopModeEnterExitTransitionListener = null } } ) Loading Loading @@ -2468,6 +2509,15 @@ class DesktopTasksController( fun onTaskbarCornerRoundingUpdate(hasTasksRequiringTaskbarRounding: Boolean) } /** Defines interface for entering and exiting desktop windowing mode. */ interface DesktopModeEntryExitTransitionListener { /** [transitionDuration] time it takes to run enter desktop mode transition */ fun onEnterDesktopModeTransitionStarted(transitionDuration: Int) /** [transitionDuration] time it takes to run exit desktop mode transition */ fun onExitDesktopModeTransitionStarted(transitionDuration: Int) } /** The positions on a screen that a task can snap to. */ enum class SnapPosition { RIGHT, Loading libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/ExitDesktopTaskTransitionHandler.java +1 −2 Original line number Diff line number Diff line Loading @@ -60,8 +60,7 @@ import java.util.function.Supplier; * entering and exiting freeform. */ public class ExitDesktopTaskTransitionHandler implements Transitions.TransitionHandler { @VisibleForTesting static final int FULLSCREEN_ANIMATION_DURATION = 336; public static final int FULLSCREEN_ANIMATION_DURATION = 336; private final Context mContext; private final Transitions mTransitions; Loading libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/IDesktopTaskListener.aidl +6 −0 Original line number Diff line number Diff line Loading @@ -33,4 +33,10 @@ interface IDesktopTaskListener { * [hasTasksRequiringTaskbarRounding] is true. */ oneway void onTaskbarCornerRoundingUpdate(boolean hasTasksRequiringTaskbarRounding); /** Entering desktop mode transition is started, send the signal with transition duration. */ oneway void onEnterDesktopModeTransitionStarted(int transitionDuration); /** Exiting desktop mode transition is started, send the signal with transition duration. */ oneway void onExitDesktopModeTransitionStarted(int transitionDuration); } No newline at end of file libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/desktopmode/DesktopTasksControllerTest.kt +27 −2 Original line number Diff line number Diff line Loading @@ -95,12 +95,15 @@ import com.android.wm.shell.common.ShellExecutor import com.android.wm.shell.common.SyncTransactionQueue import com.android.wm.shell.desktopmode.DesktopImmersiveController.ExitResult import com.android.wm.shell.desktopmode.DesktopModeEventLogger.Companion.ResizeTrigger import com.android.wm.shell.desktopmode.DesktopTasksController.DesktopModeEntryExitTransitionListener import com.android.wm.shell.desktopmode.DesktopTasksController.SnapPosition import com.android.wm.shell.desktopmode.DesktopTasksController.TaskbarDesktopTaskListener import com.android.wm.shell.desktopmode.DesktopTestHelpers.Companion.createFreeformTask import com.android.wm.shell.desktopmode.DesktopTestHelpers.Companion.createFullscreenTask import com.android.wm.shell.desktopmode.DesktopTestHelpers.Companion.createHomeTask import com.android.wm.shell.desktopmode.DesktopTestHelpers.Companion.createSplitScreenTask import com.android.wm.shell.desktopmode.EnterDesktopTaskTransitionHandler.FREEFORM_ANIMATION_DURATION import com.android.wm.shell.desktopmode.ExitDesktopTaskTransitionHandler.FULLSCREEN_ANIMATION_DURATION import com.android.wm.shell.desktopmode.minimize.DesktopWindowLimitRemoteHandler import com.android.wm.shell.desktopmode.persistence.Desktop import com.android.wm.shell.desktopmode.persistence.DesktopPersistentRepository Loading Loading @@ -223,6 +226,8 @@ class DesktopTasksControllerTest : ShellTestCase() { @Mock private lateinit var desktopWindowDecoration: DesktopModeWindowDecoration @Mock private lateinit var resources: Resources @Mock lateinit var desktopModeEnterExitTransitionListener: DesktopModeEntryExitTransitionListener private lateinit var controller: DesktopTasksController private lateinit var shellInit: ShellInit private lateinit var taskRepository: DesktopRepository Loading Loading @@ -294,6 +299,7 @@ class DesktopTasksControllerTest : ShellTestCase() { controller = createController() controller.setSplitScreenController(splitScreenController) controller.freeformTaskTransitionStarter = freeformTaskTransitionStarter controller.desktopModeEnterExitTransitionListener = desktopModeEnterExitTransitionListener shellInit.init() Loading Loading @@ -1054,6 +1060,7 @@ class DesktopTasksControllerTest : ShellTestCase() { controller.moveRunningTaskToDesktop(task, transitionSource = UNKNOWN) val wct = getLatestEnterDesktopWct() assertThat(wct.changes[task.token.asBinder()]?.windowingMode).isEqualTo(WINDOWING_MODE_FREEFORM) verify(desktopModeEnterExitTransitionListener).onEnterDesktopModeTransitionStarted(FREEFORM_ANIMATION_DURATION) } @Test Loading @@ -1065,12 +1072,14 @@ class DesktopTasksControllerTest : ShellTestCase() { val wct = getLatestEnterDesktopWct() assertThat(wct.changes[task.token.asBinder()]?.windowingMode) .isEqualTo(WINDOWING_MODE_UNDEFINED) verify(desktopModeEnterExitTransitionListener).onEnterDesktopModeTransitionStarted(FREEFORM_ANIMATION_DURATION) } @Test fun moveTaskToDesktop_nonExistentTask_doesNothing() { controller.moveTaskToDesktop(999, transitionSource = UNKNOWN) verifyEnterDesktopWCTNotExecuted() verify(desktopModeEnterExitTransitionListener, times(0)).onEnterDesktopModeTransitionStarted(anyInt()) } @Test Loading Loading @@ -1115,9 +1124,9 @@ class DesktopTasksControllerTest : ShellTestCase() { } controller.moveRunningTaskToDesktop(task, transitionSource = UNKNOWN) val wct = getLatestEnterDesktopWct() assertThat(wct.changes[task.token.asBinder()]?.windowingMode).isEqualTo(WINDOWING_MODE_FREEFORM) verify(desktopModeEnterExitTransitionListener).onEnterDesktopModeTransitionStarted(FREEFORM_ANIMATION_DURATION) } @Test Loading @@ -1132,6 +1141,9 @@ class DesktopTasksControllerTest : ShellTestCase() { controller.moveRunningTaskToDesktop(task, transitionSource = UNKNOWN) verifyEnterDesktopWCTNotExecuted() verify(desktopModeEnterExitTransitionListener, times(0)).onEnterDesktopModeTransitionStarted( FREEFORM_ANIMATION_DURATION ) } @Test Loading Loading @@ -1178,6 +1190,7 @@ class DesktopTasksControllerTest : ShellTestCase() { val wct = getLatestEnterDesktopWct() assertThat(wct.changes[task.token.asBinder()]?.windowingMode).isEqualTo(WINDOWING_MODE_FREEFORM) verify(desktopModeEnterExitTransitionListener).onEnterDesktopModeTransitionStarted(FREEFORM_ANIMATION_DURATION) } @Test Loading @@ -1197,6 +1210,7 @@ class DesktopTasksControllerTest : ShellTestCase() { assertThat(changes[fullscreenTask.token.asBinder()]?.windowingMode) .isEqualTo(WINDOWING_MODE_FREEFORM) } verify(desktopModeEnterExitTransitionListener).onEnterDesktopModeTransitionStarted(FREEFORM_ANIMATION_DURATION) } @Test Loading @@ -1217,6 +1231,7 @@ class DesktopTasksControllerTest : ShellTestCase() { assertThat(changes[fullscreenTask.token.asBinder()]?.windowingMode) .isEqualTo(WINDOWING_MODE_FREEFORM) } verify(desktopModeEnterExitTransitionListener).onEnterDesktopModeTransitionStarted(FREEFORM_ANIMATION_DURATION) } @Test Loading @@ -1238,6 +1253,7 @@ class DesktopTasksControllerTest : ShellTestCase() { assertThat(hierarchyOps.map { it.container }) .doesNotContain(freeformTaskSecond.token.asBinder()) } verify(desktopModeEnterExitTransitionListener).onEnterDesktopModeTransitionStarted(FREEFORM_ANIMATION_DURATION) } @Test Loading @@ -1246,6 +1262,7 @@ class DesktopTasksControllerTest : ShellTestCase() { controller.moveRunningTaskToDesktop(task, transitionSource = UNKNOWN) val wct = getLatestEnterDesktopWct() assertThat(wct.changes[task.token.asBinder()]?.windowingMode).isEqualTo(WINDOWING_MODE_FREEFORM) verify(desktopModeEnterExitTransitionListener).onEnterDesktopModeTransitionStarted(FREEFORM_ANIMATION_DURATION) verify(splitScreenController) .prepareExitSplitScreen(any(), anyInt(), eq(SplitScreenController.EXIT_REASON_DESKTOP_MODE)) } Loading @@ -1256,6 +1273,7 @@ class DesktopTasksControllerTest : ShellTestCase() { controller.moveRunningTaskToDesktop(task, transitionSource = UNKNOWN) val wct = getLatestEnterDesktopWct() assertThat(wct.changes[task.token.asBinder()]?.windowingMode).isEqualTo(WINDOWING_MODE_FREEFORM) verify(desktopModeEnterExitTransitionListener).onEnterDesktopModeTransitionStarted(FREEFORM_ANIMATION_DURATION) verify(splitScreenController, never()) .prepareExitSplitScreen(any(), anyInt(), eq(SplitScreenController.EXIT_REASON_DESKTOP_MODE)) } Loading @@ -1270,6 +1288,7 @@ class DesktopTasksControllerTest : ShellTestCase() { controller.moveRunningTaskToDesktop(newTask, transitionSource = UNKNOWN) val wct = getLatestEnterDesktopWct() verify(desktopModeEnterExitTransitionListener).onEnterDesktopModeTransitionStarted(FREEFORM_ANIMATION_DURATION) assertThat(wct.hierarchyOps.size).isEqualTo(MAX_TASK_LIMIT + 1) // visible tasks + home wct.assertReorderAt(0, homeTask) wct.assertReorderSequenceInRange( Loading @@ -1288,6 +1307,7 @@ class DesktopTasksControllerTest : ShellTestCase() { controller.moveRunningTaskToDesktop(newTask, transitionSource = UNKNOWN) val wct = getLatestEnterDesktopWct() verify(desktopModeEnterExitTransitionListener).onEnterDesktopModeTransitionStarted(FREEFORM_ANIMATION_DURATION) assertThat(wct.hierarchyOps.size).isEqualTo(MAX_TASK_LIMIT + 2) // tasks + home + wallpaper // Move home to front wct.assertReorderAt(0, homeTask) Loading @@ -1307,6 +1327,7 @@ class DesktopTasksControllerTest : ShellTestCase() { tda.configuration.windowConfiguration.windowingMode = WINDOWING_MODE_FULLSCREEN controller.moveToFullscreen(task.taskId, transitionSource = UNKNOWN) val wct = getLatestExitDesktopWct() verify(desktopModeEnterExitTransitionListener, times(1)).onExitDesktopModeTransitionStarted(FULLSCREEN_ANIMATION_DURATION) assertThat(wct.changes[task.token.asBinder()]?.windowingMode) .isEqualTo(WINDOWING_MODE_UNDEFINED) } Loading @@ -1324,6 +1345,7 @@ class DesktopTasksControllerTest : ShellTestCase() { val wct = getLatestExitDesktopWct() val taskChange = assertNotNull(wct.changes[task.token.asBinder()]) verify(desktopModeEnterExitTransitionListener).onExitDesktopModeTransitionStarted(FULLSCREEN_ANIMATION_DURATION) assertThat(taskChange.windowingMode).isEqualTo(WINDOWING_MODE_UNDEFINED) // Removes wallpaper activity when leaving desktop wct.assertRemoveAt(index = 0, wallpaperToken) Loading @@ -1338,6 +1360,7 @@ class DesktopTasksControllerTest : ShellTestCase() { val wct = getLatestExitDesktopWct() assertThat(wct.changes[task.token.asBinder()]?.windowingMode) .isEqualTo(WINDOWING_MODE_FULLSCREEN) verify(desktopModeEnterExitTransitionListener).onExitDesktopModeTransitionStarted(FULLSCREEN_ANIMATION_DURATION) } @Test Loading @@ -1354,6 +1377,7 @@ class DesktopTasksControllerTest : ShellTestCase() { val wct = getLatestExitDesktopWct() val taskChange = assertNotNull(wct.changes[task.token.asBinder()]) assertThat(taskChange.windowingMode).isEqualTo(WINDOWING_MODE_FULLSCREEN) verify(desktopModeEnterExitTransitionListener).onExitDesktopModeTransitionStarted(FULLSCREEN_ANIMATION_DURATION) // Removes wallpaper activity when leaving desktop wct.assertRemoveAt(index = 0, wallpaperToken) } Loading @@ -1374,6 +1398,7 @@ class DesktopTasksControllerTest : ShellTestCase() { val wct = getLatestExitDesktopWct() val task1Change = assertNotNull(wct.changes[task1.token.asBinder()]) assertThat(task1Change.windowingMode).isEqualTo(WINDOWING_MODE_UNDEFINED) verify(desktopModeEnterExitTransitionListener).onExitDesktopModeTransitionStarted(FULLSCREEN_ANIMATION_DURATION) // Does not remove wallpaper activity, as desktop still has a visible desktop task assertThat(wct.hierarchyOps).isEmpty() } Loading @@ -1388,13 +1413,13 @@ class DesktopTasksControllerTest : ShellTestCase() { fun moveToFullscreen_secondDisplayTaskHasFreeform_secondDisplayNotAffected() { val taskDefaultDisplay = setUpFreeformTask(displayId = DEFAULT_DISPLAY) val taskSecondDisplay = setUpFreeformTask(displayId = SECOND_DISPLAY) controller.moveToFullscreen(taskDefaultDisplay.taskId, transitionSource = UNKNOWN) with(getLatestExitDesktopWct()) { assertThat(changes.keys).contains(taskDefaultDisplay.token.asBinder()) assertThat(changes.keys).doesNotContain(taskSecondDisplay.token.asBinder()) } verify(desktopModeEnterExitTransitionListener).onExitDesktopModeTransitionStarted(FULLSCREEN_ANIMATION_DURATION) } @Test Loading Loading
libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopTasksController.kt +74 −24 Original line number Diff line number Diff line Loading @@ -127,6 +127,10 @@ import java.util.Optional import java.util.concurrent.Executor import java.util.function.Consumer import com.android.wm.shell.desktopmode.DesktopModeEventLogger.Companion.ResizeTrigger import com.android.wm.shell.desktopmode.DragToDesktopTransitionHandler.Companion.DRAG_TO_DESKTOP_FINISH_ANIM_DURATION_MS import com.android.wm.shell.desktopmode.EnterDesktopTaskTransitionHandler.FREEFORM_ANIMATION_DURATION import com.android.wm.shell.desktopmode.ExitDesktopTaskTransitionHandler.FULLSCREEN_ANIMATION_DURATION /** Handles moving tasks in and out of desktop */ class DesktopTasksController( private val context: Context, Loading Loading @@ -195,6 +199,9 @@ class DesktopTasksController( @VisibleForTesting var taskbarDesktopTaskListener: TaskbarDesktopTaskListener? = null @VisibleForTesting var desktopModeEnterExitTransitionListener: DesktopModeEntryExitTransitionListener? = null /** Task id of the task currently being dragged from fullscreen/split. */ val draggingTaskId get() = dragToDesktopTransitionHandler.draggingTaskId Loading Loading @@ -380,6 +387,7 @@ class DesktopTasksController( ) // TODO(343149901): Add DPI changes for task launch val transition = enterDesktopTaskTransitionHandler.moveToDesktop(wct, transitionSource) desktopModeEnterExitTransitionListener?.onEnterDesktopModeTransitionStarted(FREEFORM_ANIMATION_DURATION) taskIdToMinimize?.let { addPendingMinimizeTransition(transition, it) } exitResult.asExit()?.runOnTransitionStart?.invoke(transition) return true Loading Loading @@ -409,6 +417,7 @@ class DesktopTasksController( addMoveToDesktopChanges(wct, task) val transition = enterDesktopTaskTransitionHandler.moveToDesktop(wct, transitionSource) desktopModeEnterExitTransitionListener?.onEnterDesktopModeTransitionStarted(FREEFORM_ANIMATION_DURATION) taskIdToMinimize?.let { addPendingMinimizeTransition(transition, it) } exitResult.asExit()?.runOnTransitionStart?.invoke(transition) } Loading Loading @@ -450,6 +459,9 @@ class DesktopTasksController( val exitResult = desktopImmersiveController.exitImmersiveIfApplicable( wct, taskInfo.displayId) val transition = dragToDesktopTransitionHandler.finishDragToDesktopTransition(wct) desktopModeEnterExitTransitionListener?.onEnterDesktopModeTransitionStarted( DRAG_TO_DESKTOP_FINISH_ANIM_DURATION_MS.toInt() ) transition?.let { taskIdToMinimize?.let { taskId -> addPendingMinimizeTransition(it, taskId) } exitResult.asExit()?.runOnTransitionStart?.invoke(transition) Loading Loading @@ -485,9 +497,7 @@ class DesktopTasksController( ): ((IBinder) -> Unit)? { val taskId = taskInfo.taskId desktopTilingDecorViewModel.removeTaskIfTiled(displayId, taskId) if (taskRepository.isOnlyVisibleNonClosingTask(taskId)) { removeWallpaperActivity(wct) } performDesktopExitCleanupIfNeeded(taskId, wct) taskRepository.addClosingTask(displayId, taskId) taskbarDesktopTaskListener?.onTaskbarCornerRoundingUpdate( doesAnyTaskRequireTaskbarRounding( Loading @@ -503,11 +513,7 @@ class DesktopTasksController( val taskId = taskInfo.taskId val displayId = taskInfo.displayId val wct = WindowContainerTransaction() if (taskRepository.isOnlyVisibleNonClosingTask(taskId)) { // Perform clean up of the desktop wallpaper activity if the minimized window task is // the last active task. removeWallpaperActivity(wct) } performDesktopExitCleanupIfNeeded(taskId, wct) // Notify immersive handler as it might need to exit immersive state. val exitResult = desktopImmersiveController.exitImmersiveIfApplicable(wct, taskInfo) Loading Loading @@ -576,6 +582,11 @@ class DesktopTasksController( position, mOnAnimationFinishedCallback ) // handles case where we are moving to full screen without closing all DW tasks. if (!taskRepository.isOnlyVisibleNonClosingTask(task.taskId)) { desktopModeEnterExitTransitionListener?.onExitDesktopModeTransitionStarted(FULLSCREEN_ANIMATION_DURATION) } } /** Loading Loading @@ -1226,6 +1237,21 @@ class DesktopTasksController( } } /** * Remove wallpaper activity if task provided is last task and wallpaper activity token is not * null */ private fun performDesktopExitCleanupIfNeeded(taskId: Int, wct: WindowContainerTransaction) { if (!taskRepository.isOnlyVisibleNonClosingTask(taskId)) { return } desktopModeEnterExitTransitionListener?.onExitDesktopModeTransitionStarted(FULLSCREEN_ANIMATION_DURATION) if (taskRepository.wallpaperActivityToken != null) { removeWallpaperActivity(wct) } } fun releaseVisualIndicator() { val t = SurfaceControl.Transaction() visualIndicator?.releaseVisualIndicator(t) Loading Loading @@ -1662,12 +1688,7 @@ class DesktopTasksController( return null val wct = WindowContainerTransaction() if (taskRepository.isOnlyVisibleNonClosingTask(task.taskId) && taskRepository.wallpaperActivityToken != null ) { // Remove wallpaper activity when the last active task is removed removeWallpaperActivity(wct) } performDesktopExitCleanupIfNeeded(task.taskId, wct) if (!DesktopModeFlags.ENABLE_DESKTOP_WINDOWING_BACK_NAVIGATION.isTrue()) { taskRepository.addClosingTask(task.displayId, task.taskId) Loading Loading @@ -1758,10 +1779,8 @@ class DesktopTasksController( if (useDesktopOverrideDensity()) { wct.setDensityDpi(taskInfo.token, getDefaultDensityDpi()) } if (taskRepository.isOnlyVisibleNonClosingTask(taskInfo.taskId)) { // Remove wallpaper activity when leaving desktop mode removeWallpaperActivity(wct) } performDesktopExitCleanupIfNeeded(taskInfo.taskId, wct) } private fun cascadeWindow(bounds: Rect, displayLayout: DisplayLayout, displayId: Int) { Loading Loading @@ -1790,10 +1809,8 @@ class DesktopTasksController( // The task's density may have been overridden in freeform; revert it here as we don't // want it overridden in multi-window. wct.setDensityDpi(taskInfo.token, getDefaultDensityDpi()) if (taskRepository.isOnlyVisibleNonClosingTask(taskInfo.taskId)) { // Remove wallpaper activity when leaving desktop mode removeWallpaperActivity(wct) } performDesktopExitCleanupIfNeeded(taskInfo.taskId, wct) } /** Returns the ID of the Task that will be minimized, or null if no task will be minimized. */ Loading Loading @@ -2331,7 +2348,7 @@ class DesktopTasksController( } } private val mTaskbarDesktopTaskListener: TaskbarDesktopTaskListener = private val taskbarDesktopTaskListener: TaskbarDesktopTaskListener = object : TaskbarDesktopTaskListener { override fun onTaskbarCornerRoundingUpdate( hasTasksRequiringTaskbarRounding: Boolean) { Loading @@ -2348,6 +2365,27 @@ class DesktopTasksController( } } private val desktopModeEntryExitTransitionListener: DesktopModeEntryExitTransitionListener = object : DesktopModeEntryExitTransitionListener { override fun onEnterDesktopModeTransitionStarted(transitionDuration: Int) { ProtoLog.v( WM_SHELL_DESKTOP_MODE, "IDesktopModeImpl: onEnterDesktopModeTransitionStarted transitionTime=%s", transitionDuration ) remoteListener.call { l -> l.onEnterDesktopModeTransitionStarted(transitionDuration) } } override fun onExitDesktopModeTransitionStarted(transitionDuration: Int) { ProtoLog.v( WM_SHELL_DESKTOP_MODE, "IDesktopModeImpl: onExitDesktopModeTransitionStarted transitionTime=%s", transitionDuration ) remoteListener.call { l -> l.onExitDesktopModeTransitionStarted(transitionDuration) } } } init { remoteListener = SingleInstanceRemoteListener<DesktopTasksController, IDesktopTaskListener>( Loading @@ -2355,13 +2393,16 @@ class DesktopTasksController( { c -> run { c.taskRepository.addVisibleTasksListener(listener, c.mainExecutor) c.taskbarDesktopTaskListener = mTaskbarDesktopTaskListener c.taskbarDesktopTaskListener = taskbarDesktopTaskListener c.desktopModeEnterExitTransitionListener = desktopModeEntryExitTransitionListener } }, { c -> run { c.taskRepository.removeVisibleTasksListener(listener) c.taskbarDesktopTaskListener = null c.desktopModeEnterExitTransitionListener = null } } ) Loading Loading @@ -2468,6 +2509,15 @@ class DesktopTasksController( fun onTaskbarCornerRoundingUpdate(hasTasksRequiringTaskbarRounding: Boolean) } /** Defines interface for entering and exiting desktop windowing mode. */ interface DesktopModeEntryExitTransitionListener { /** [transitionDuration] time it takes to run enter desktop mode transition */ fun onEnterDesktopModeTransitionStarted(transitionDuration: Int) /** [transitionDuration] time it takes to run exit desktop mode transition */ fun onExitDesktopModeTransitionStarted(transitionDuration: Int) } /** The positions on a screen that a task can snap to. */ enum class SnapPosition { RIGHT, Loading
libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/ExitDesktopTaskTransitionHandler.java +1 −2 Original line number Diff line number Diff line Loading @@ -60,8 +60,7 @@ import java.util.function.Supplier; * entering and exiting freeform. */ public class ExitDesktopTaskTransitionHandler implements Transitions.TransitionHandler { @VisibleForTesting static final int FULLSCREEN_ANIMATION_DURATION = 336; public static final int FULLSCREEN_ANIMATION_DURATION = 336; private final Context mContext; private final Transitions mTransitions; Loading
libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/IDesktopTaskListener.aidl +6 −0 Original line number Diff line number Diff line Loading @@ -33,4 +33,10 @@ interface IDesktopTaskListener { * [hasTasksRequiringTaskbarRounding] is true. */ oneway void onTaskbarCornerRoundingUpdate(boolean hasTasksRequiringTaskbarRounding); /** Entering desktop mode transition is started, send the signal with transition duration. */ oneway void onEnterDesktopModeTransitionStarted(int transitionDuration); /** Exiting desktop mode transition is started, send the signal with transition duration. */ oneway void onExitDesktopModeTransitionStarted(int transitionDuration); } No newline at end of file
libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/desktopmode/DesktopTasksControllerTest.kt +27 −2 Original line number Diff line number Diff line Loading @@ -95,12 +95,15 @@ import com.android.wm.shell.common.ShellExecutor import com.android.wm.shell.common.SyncTransactionQueue import com.android.wm.shell.desktopmode.DesktopImmersiveController.ExitResult import com.android.wm.shell.desktopmode.DesktopModeEventLogger.Companion.ResizeTrigger import com.android.wm.shell.desktopmode.DesktopTasksController.DesktopModeEntryExitTransitionListener import com.android.wm.shell.desktopmode.DesktopTasksController.SnapPosition import com.android.wm.shell.desktopmode.DesktopTasksController.TaskbarDesktopTaskListener import com.android.wm.shell.desktopmode.DesktopTestHelpers.Companion.createFreeformTask import com.android.wm.shell.desktopmode.DesktopTestHelpers.Companion.createFullscreenTask import com.android.wm.shell.desktopmode.DesktopTestHelpers.Companion.createHomeTask import com.android.wm.shell.desktopmode.DesktopTestHelpers.Companion.createSplitScreenTask import com.android.wm.shell.desktopmode.EnterDesktopTaskTransitionHandler.FREEFORM_ANIMATION_DURATION import com.android.wm.shell.desktopmode.ExitDesktopTaskTransitionHandler.FULLSCREEN_ANIMATION_DURATION import com.android.wm.shell.desktopmode.minimize.DesktopWindowLimitRemoteHandler import com.android.wm.shell.desktopmode.persistence.Desktop import com.android.wm.shell.desktopmode.persistence.DesktopPersistentRepository Loading Loading @@ -223,6 +226,8 @@ class DesktopTasksControllerTest : ShellTestCase() { @Mock private lateinit var desktopWindowDecoration: DesktopModeWindowDecoration @Mock private lateinit var resources: Resources @Mock lateinit var desktopModeEnterExitTransitionListener: DesktopModeEntryExitTransitionListener private lateinit var controller: DesktopTasksController private lateinit var shellInit: ShellInit private lateinit var taskRepository: DesktopRepository Loading Loading @@ -294,6 +299,7 @@ class DesktopTasksControllerTest : ShellTestCase() { controller = createController() controller.setSplitScreenController(splitScreenController) controller.freeformTaskTransitionStarter = freeformTaskTransitionStarter controller.desktopModeEnterExitTransitionListener = desktopModeEnterExitTransitionListener shellInit.init() Loading Loading @@ -1054,6 +1060,7 @@ class DesktopTasksControllerTest : ShellTestCase() { controller.moveRunningTaskToDesktop(task, transitionSource = UNKNOWN) val wct = getLatestEnterDesktopWct() assertThat(wct.changes[task.token.asBinder()]?.windowingMode).isEqualTo(WINDOWING_MODE_FREEFORM) verify(desktopModeEnterExitTransitionListener).onEnterDesktopModeTransitionStarted(FREEFORM_ANIMATION_DURATION) } @Test Loading @@ -1065,12 +1072,14 @@ class DesktopTasksControllerTest : ShellTestCase() { val wct = getLatestEnterDesktopWct() assertThat(wct.changes[task.token.asBinder()]?.windowingMode) .isEqualTo(WINDOWING_MODE_UNDEFINED) verify(desktopModeEnterExitTransitionListener).onEnterDesktopModeTransitionStarted(FREEFORM_ANIMATION_DURATION) } @Test fun moveTaskToDesktop_nonExistentTask_doesNothing() { controller.moveTaskToDesktop(999, transitionSource = UNKNOWN) verifyEnterDesktopWCTNotExecuted() verify(desktopModeEnterExitTransitionListener, times(0)).onEnterDesktopModeTransitionStarted(anyInt()) } @Test Loading Loading @@ -1115,9 +1124,9 @@ class DesktopTasksControllerTest : ShellTestCase() { } controller.moveRunningTaskToDesktop(task, transitionSource = UNKNOWN) val wct = getLatestEnterDesktopWct() assertThat(wct.changes[task.token.asBinder()]?.windowingMode).isEqualTo(WINDOWING_MODE_FREEFORM) verify(desktopModeEnterExitTransitionListener).onEnterDesktopModeTransitionStarted(FREEFORM_ANIMATION_DURATION) } @Test Loading @@ -1132,6 +1141,9 @@ class DesktopTasksControllerTest : ShellTestCase() { controller.moveRunningTaskToDesktop(task, transitionSource = UNKNOWN) verifyEnterDesktopWCTNotExecuted() verify(desktopModeEnterExitTransitionListener, times(0)).onEnterDesktopModeTransitionStarted( FREEFORM_ANIMATION_DURATION ) } @Test Loading Loading @@ -1178,6 +1190,7 @@ class DesktopTasksControllerTest : ShellTestCase() { val wct = getLatestEnterDesktopWct() assertThat(wct.changes[task.token.asBinder()]?.windowingMode).isEqualTo(WINDOWING_MODE_FREEFORM) verify(desktopModeEnterExitTransitionListener).onEnterDesktopModeTransitionStarted(FREEFORM_ANIMATION_DURATION) } @Test Loading @@ -1197,6 +1210,7 @@ class DesktopTasksControllerTest : ShellTestCase() { assertThat(changes[fullscreenTask.token.asBinder()]?.windowingMode) .isEqualTo(WINDOWING_MODE_FREEFORM) } verify(desktopModeEnterExitTransitionListener).onEnterDesktopModeTransitionStarted(FREEFORM_ANIMATION_DURATION) } @Test Loading @@ -1217,6 +1231,7 @@ class DesktopTasksControllerTest : ShellTestCase() { assertThat(changes[fullscreenTask.token.asBinder()]?.windowingMode) .isEqualTo(WINDOWING_MODE_FREEFORM) } verify(desktopModeEnterExitTransitionListener).onEnterDesktopModeTransitionStarted(FREEFORM_ANIMATION_DURATION) } @Test Loading @@ -1238,6 +1253,7 @@ class DesktopTasksControllerTest : ShellTestCase() { assertThat(hierarchyOps.map { it.container }) .doesNotContain(freeformTaskSecond.token.asBinder()) } verify(desktopModeEnterExitTransitionListener).onEnterDesktopModeTransitionStarted(FREEFORM_ANIMATION_DURATION) } @Test Loading @@ -1246,6 +1262,7 @@ class DesktopTasksControllerTest : ShellTestCase() { controller.moveRunningTaskToDesktop(task, transitionSource = UNKNOWN) val wct = getLatestEnterDesktopWct() assertThat(wct.changes[task.token.asBinder()]?.windowingMode).isEqualTo(WINDOWING_MODE_FREEFORM) verify(desktopModeEnterExitTransitionListener).onEnterDesktopModeTransitionStarted(FREEFORM_ANIMATION_DURATION) verify(splitScreenController) .prepareExitSplitScreen(any(), anyInt(), eq(SplitScreenController.EXIT_REASON_DESKTOP_MODE)) } Loading @@ -1256,6 +1273,7 @@ class DesktopTasksControllerTest : ShellTestCase() { controller.moveRunningTaskToDesktop(task, transitionSource = UNKNOWN) val wct = getLatestEnterDesktopWct() assertThat(wct.changes[task.token.asBinder()]?.windowingMode).isEqualTo(WINDOWING_MODE_FREEFORM) verify(desktopModeEnterExitTransitionListener).onEnterDesktopModeTransitionStarted(FREEFORM_ANIMATION_DURATION) verify(splitScreenController, never()) .prepareExitSplitScreen(any(), anyInt(), eq(SplitScreenController.EXIT_REASON_DESKTOP_MODE)) } Loading @@ -1270,6 +1288,7 @@ class DesktopTasksControllerTest : ShellTestCase() { controller.moveRunningTaskToDesktop(newTask, transitionSource = UNKNOWN) val wct = getLatestEnterDesktopWct() verify(desktopModeEnterExitTransitionListener).onEnterDesktopModeTransitionStarted(FREEFORM_ANIMATION_DURATION) assertThat(wct.hierarchyOps.size).isEqualTo(MAX_TASK_LIMIT + 1) // visible tasks + home wct.assertReorderAt(0, homeTask) wct.assertReorderSequenceInRange( Loading @@ -1288,6 +1307,7 @@ class DesktopTasksControllerTest : ShellTestCase() { controller.moveRunningTaskToDesktop(newTask, transitionSource = UNKNOWN) val wct = getLatestEnterDesktopWct() verify(desktopModeEnterExitTransitionListener).onEnterDesktopModeTransitionStarted(FREEFORM_ANIMATION_DURATION) assertThat(wct.hierarchyOps.size).isEqualTo(MAX_TASK_LIMIT + 2) // tasks + home + wallpaper // Move home to front wct.assertReorderAt(0, homeTask) Loading @@ -1307,6 +1327,7 @@ class DesktopTasksControllerTest : ShellTestCase() { tda.configuration.windowConfiguration.windowingMode = WINDOWING_MODE_FULLSCREEN controller.moveToFullscreen(task.taskId, transitionSource = UNKNOWN) val wct = getLatestExitDesktopWct() verify(desktopModeEnterExitTransitionListener, times(1)).onExitDesktopModeTransitionStarted(FULLSCREEN_ANIMATION_DURATION) assertThat(wct.changes[task.token.asBinder()]?.windowingMode) .isEqualTo(WINDOWING_MODE_UNDEFINED) } Loading @@ -1324,6 +1345,7 @@ class DesktopTasksControllerTest : ShellTestCase() { val wct = getLatestExitDesktopWct() val taskChange = assertNotNull(wct.changes[task.token.asBinder()]) verify(desktopModeEnterExitTransitionListener).onExitDesktopModeTransitionStarted(FULLSCREEN_ANIMATION_DURATION) assertThat(taskChange.windowingMode).isEqualTo(WINDOWING_MODE_UNDEFINED) // Removes wallpaper activity when leaving desktop wct.assertRemoveAt(index = 0, wallpaperToken) Loading @@ -1338,6 +1360,7 @@ class DesktopTasksControllerTest : ShellTestCase() { val wct = getLatestExitDesktopWct() assertThat(wct.changes[task.token.asBinder()]?.windowingMode) .isEqualTo(WINDOWING_MODE_FULLSCREEN) verify(desktopModeEnterExitTransitionListener).onExitDesktopModeTransitionStarted(FULLSCREEN_ANIMATION_DURATION) } @Test Loading @@ -1354,6 +1377,7 @@ class DesktopTasksControllerTest : ShellTestCase() { val wct = getLatestExitDesktopWct() val taskChange = assertNotNull(wct.changes[task.token.asBinder()]) assertThat(taskChange.windowingMode).isEqualTo(WINDOWING_MODE_FULLSCREEN) verify(desktopModeEnterExitTransitionListener).onExitDesktopModeTransitionStarted(FULLSCREEN_ANIMATION_DURATION) // Removes wallpaper activity when leaving desktop wct.assertRemoveAt(index = 0, wallpaperToken) } Loading @@ -1374,6 +1398,7 @@ class DesktopTasksControllerTest : ShellTestCase() { val wct = getLatestExitDesktopWct() val task1Change = assertNotNull(wct.changes[task1.token.asBinder()]) assertThat(task1Change.windowingMode).isEqualTo(WINDOWING_MODE_UNDEFINED) verify(desktopModeEnterExitTransitionListener).onExitDesktopModeTransitionStarted(FULLSCREEN_ANIMATION_DURATION) // Does not remove wallpaper activity, as desktop still has a visible desktop task assertThat(wct.hierarchyOps).isEmpty() } Loading @@ -1388,13 +1413,13 @@ class DesktopTasksControllerTest : ShellTestCase() { fun moveToFullscreen_secondDisplayTaskHasFreeform_secondDisplayNotAffected() { val taskDefaultDisplay = setUpFreeformTask(displayId = DEFAULT_DISPLAY) val taskSecondDisplay = setUpFreeformTask(displayId = SECOND_DISPLAY) controller.moveToFullscreen(taskDefaultDisplay.taskId, transitionSource = UNKNOWN) with(getLatestExitDesktopWct()) { assertThat(changes.keys).contains(taskDefaultDisplay.token.asBinder()) assertThat(changes.keys).doesNotContain(taskSecondDisplay.token.asBinder()) } verify(desktopModeEnterExitTransitionListener).onExitDesktopModeTransitionStarted(FULLSCREEN_ANIMATION_DURATION) } @Test Loading