From 0129eb9d410345bcffb2a44dabeb433e7651ad7b Mon Sep 17 00:00:00 2001 From: Gustav Sennton Date: Tue, 2 Jul 2024 17:06:27 +0000 Subject: Remove minimized tasks when there are only minimized Tasks left. Remove leftover minimized tasks when the last visible desktop task is removed to avoid keeping minimized tasks around for the next desktop session. Flag: com.android.window.flags.enable_desktop_windowing_task_limit Bug: 349542123 Test: add 5 tasks, remove all visible ones -> minimized task removed Test: DesktopTasksLimiterTest Change-Id: If8a3759370e881b36c2d7e17206c73c8de4e62b8 --- .../shell/desktopmode/DesktopModeTaskRepository.kt | 4 +++ .../wm/shell/desktopmode/DesktopTasksLimiter.kt | 32 +++++++++++++++++ .../shell/desktopmode/DesktopTasksLimiterTest.kt | 41 ++++++++++++++++++++++ 3 files changed, 77 insertions(+) diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopModeTaskRepository.kt b/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopModeTaskRepository.kt index 81891ce91e04..df79b1575894 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopModeTaskRepository.kt +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopModeTaskRepository.kt @@ -250,6 +250,10 @@ class DesktopModeTaskRepository { return ArraySet(displayData[displayId]?.activeTasks) } + /** Returns the minimized tasks for the given [displayId]. */ + fun getMinimizedTasks(displayId: Int): ArraySet = + ArraySet(displayData[displayId]?.minimizedTasks) + /** * Returns whether Desktop Mode is currently showing any tasks, i.e. whether any Desktop Tasks * are visible. diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopTasksLimiter.kt b/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopTasksLimiter.kt index 0f88384ec2ac..c85f76de33a7 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopTasksLimiter.kt +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopTasksLimiter.kt @@ -42,9 +42,12 @@ class DesktopTasksLimiter ( private val shellTaskOrganizer: ShellTaskOrganizer, ) { private val minimizeTransitionObserver = MinimizeTransitionObserver() + @VisibleForTesting + val leftoverMinimizedTasksRemover = LeftoverMinimizedTasksRemover() init { transitions.registerObserver(minimizeTransitionObserver) + taskRepository.addActiveTaskListener(leftoverMinimizedTasksRemover) } private data class TaskDetails (val displayId: Int, val taskId: Int) @@ -113,6 +116,35 @@ class DesktopTasksLimiter ( } } + @VisibleForTesting + inner class LeftoverMinimizedTasksRemover : DesktopModeTaskRepository.ActiveTasksListener { + override fun onActiveTasksChanged(displayId: Int) { + val wct = WindowContainerTransaction() + removeLeftoverMinimizedTasks(displayId, wct) + shellTaskOrganizer.applyTransaction(wct) + } + + fun removeLeftoverMinimizedTasks(displayId: Int, wct: WindowContainerTransaction) { + if (taskRepository + .getActiveNonMinimizedTasksOrderedFrontToBack(displayId).isNotEmpty()) { + return + } + val remainingMinimizedTasks = taskRepository.getMinimizedTasks(displayId) + if (remainingMinimizedTasks.isEmpty()) { + return + } + KtProtoLog.v( + ShellProtoLogGroup.WM_SHELL_DESKTOP_MODE, + "DesktopTasksLimiter: removing leftover minimized tasks: $remainingMinimizedTasks") + remainingMinimizedTasks.forEach { taskIdToRemove -> + val taskToRemove = shellTaskOrganizer.getRunningTaskInfo(taskIdToRemove) + if (taskToRemove != null) { + wct.removeTask(taskToRemove.token) + } + } + } + } + /** * Mark a task as minimized, this should only be done after the corresponding transition has * finished so we don't minimize the task if the transition fails. diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/desktopmode/DesktopTasksLimiterTest.kt b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/desktopmode/DesktopTasksLimiterTest.kt index 77f917cc28d8..4bfa96a7b6ce 100644 --- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/desktopmode/DesktopTasksLimiterTest.kt +++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/desktopmode/DesktopTasksLimiterTest.kt @@ -24,6 +24,7 @@ import android.view.Display.DEFAULT_DISPLAY import android.view.WindowManager.TRANSIT_OPEN import android.view.WindowManager.TRANSIT_TO_BACK import android.window.WindowContainerTransaction +import android.window.WindowContainerTransaction.HierarchyOp.HIERARCHY_OP_TYPE_REMOVE_TASK import android.window.WindowContainerTransaction.HierarchyOp.HIERARCHY_OP_TYPE_REORDER import androidx.test.filters.SmallTest import com.android.dx.mockito.inline.extended.ExtendedMockito @@ -204,6 +205,46 @@ class DesktopTasksLimiterTest : ShellTestCase() { assertThat(desktopTaskRepo.isMinimizedTask(taskId = task.taskId)).isTrue() } + @Test + fun removeLeftoverMinimizedTasks_activeNonMinimizedTasksStillAround_doesNothing() { + desktopTaskRepo.addActiveTask(displayId = DEFAULT_DISPLAY, taskId = 1) + desktopTaskRepo.addActiveTask(displayId = DEFAULT_DISPLAY, taskId = 2) + desktopTaskRepo.minimizeTask(displayId = DEFAULT_DISPLAY, taskId = 2) + + val wct = WindowContainerTransaction() + desktopTasksLimiter.leftoverMinimizedTasksRemover.removeLeftoverMinimizedTasks( + DEFAULT_DISPLAY, wct) + + assertThat(wct.isEmpty).isTrue() + } + + @Test + fun removeLeftoverMinimizedTasks_noMinimizedTasks_doesNothing() { + val wct = WindowContainerTransaction() + desktopTasksLimiter.leftoverMinimizedTasksRemover.removeLeftoverMinimizedTasks( + DEFAULT_DISPLAY, wct) + + assertThat(wct.isEmpty).isTrue() + } + + @Test + fun removeLeftoverMinimizedTasks_onlyMinimizedTasksLeft_removesAllMinimizedTasks() { + val task1 = setUpFreeformTask(displayId = DEFAULT_DISPLAY) + val task2 = setUpFreeformTask(displayId = DEFAULT_DISPLAY) + desktopTaskRepo.minimizeTask(displayId = DEFAULT_DISPLAY, taskId = task1.taskId) + desktopTaskRepo.minimizeTask(displayId = DEFAULT_DISPLAY, taskId = task2.taskId) + + val wct = WindowContainerTransaction() + desktopTasksLimiter.leftoverMinimizedTasksRemover.removeLeftoverMinimizedTasks( + DEFAULT_DISPLAY, wct) + + assertThat(wct.hierarchyOps).hasSize(2) + assertThat(wct.hierarchyOps[0].type).isEqualTo(HIERARCHY_OP_TYPE_REMOVE_TASK) + assertThat(wct.hierarchyOps[0].container).isEqualTo(task1.token.asBinder()) + assertThat(wct.hierarchyOps[1].type).isEqualTo(HIERARCHY_OP_TYPE_REMOVE_TASK) + assertThat(wct.hierarchyOps[1].container).isEqualTo(task2.token.asBinder()) + } + @Test fun addAndGetMinimizeTaskChangesIfNeeded_tasksWithinLimit_noTaskMinimized() { val taskLimit = desktopTasksLimiter.getMaxTaskLimit() -- cgit v1.2.3-59-g8ed1b