Loading libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopMixedTransitionHandler.kt +1 −1 Original line number Diff line number Diff line Loading @@ -138,7 +138,7 @@ class DesktopMixedTransitionHandler( private fun isLastDesktopTask(change: TransitionInfo.Change): Boolean = change.taskInfo?.let { desktopRepository.getActiveNonMinimizedTaskCount(it.displayId) == 1 desktopRepository.getExpandedTaskCount(it.displayId) == 1 } ?: false private fun findCloseDesktopTaskChange(info: TransitionInfo): TransitionInfo.Change? { Loading libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopRepository.kt +2 −2 Original line number Diff line number Diff line Loading @@ -260,11 +260,11 @@ class DesktopRepository ( ArraySet(desktopTaskDataByDisplayId[displayId]?.minimizedTasks) /** Returns all active non-minimized tasks for [displayId] ordered from top to bottom. */ fun getActiveNonMinimizedOrderedTasks(displayId: Int): List<Int> = fun getExpandedTasksOrdered(displayId: Int): List<Int> = getFreeformTasksInZOrder(displayId).filter { !isMinimizedTask(it) } /** Returns the count of active non-minimized tasks for [displayId]. */ fun getActiveNonMinimizedTaskCount(displayId: Int): Int { fun getExpandedTaskCount(displayId: Int): Int { return getActiveTasks(displayId).count { !isMinimizedTask(it) } } Loading libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopTasksController.kt +12 −12 Original line number Diff line number Diff line Loading @@ -662,7 +662,7 @@ class DesktopTasksController( remoteTransition: RemoteTransition?, ): IBinder { val taskToMinimize: RunningTaskInfo? = addAndGetMinimizeChangesIfNeeded(DEFAULT_DISPLAY, wct, taskId) addAndGetMinimizeChanges(DEFAULT_DISPLAY, wct, taskId) if (remoteTransition == null) { val t = transitions.startTransition(transitionType, wct, null /* handler */) addPendingMinimizeTransition(t, taskToMinimize) Loading Loading @@ -872,7 +872,7 @@ class DesktopTasksController( excludeTaskId: Int? = null, ): Boolean { val doesAnyTaskRequireTaskbarRounding = taskRepository.getActiveNonMinimizedOrderedTasks(displayId) taskRepository.getExpandedTasksOrdered(displayId) // exclude current task since maximize/restore transition has not taken place yet. .filterNot { taskId -> taskId == excludeTaskId } .any { taskId -> Loading Loading @@ -1050,23 +1050,23 @@ class DesktopTasksController( addWallpaperActivity(wct) } val nonMinimizedTasksOrderedFrontToBack = taskRepository.getActiveNonMinimizedOrderedTasks(displayId) val expandedTasksOrderedFrontToBack = taskRepository.getExpandedTasksOrdered(displayId) // If we're adding a new Task we might need to minimize an old one // TODO(b/365725441): Handle non running task minimization val taskToMinimize: RunningTaskInfo? = if (newTaskIdInFront != null && desktopTasksLimiter.isPresent) { desktopTasksLimiter .get() .getTaskToMinimizeIfNeeded( nonMinimizedTasksOrderedFrontToBack, .getTaskToMinimize( expandedTasksOrderedFrontToBack, newTaskIdInFront ) } else { null } nonMinimizedTasksOrderedFrontToBack expandedTasksOrderedFrontToBack // If there is a Task to minimize, let it stay behind the Home Task .filter { taskId -> taskId != taskToMinimize?.taskId } .reversed() // Start from the back so the front task is brought forward last Loading Loading @@ -1489,7 +1489,7 @@ class DesktopTasksController( // 1) Exit immersive if needed. desktopImmersiveController.exitImmersiveIfApplicable(transition, wct, task.displayId) // 2) minimize a Task if needed. val taskToMinimize = addAndGetMinimizeChangesIfNeeded(task.displayId, wct, task.taskId) val taskToMinimize = addAndGetMinimizeChanges(task.displayId, wct, task.taskId) if (taskToMinimize != null) { addPendingMinimizeTransition(transition, taskToMinimize) return wct Loading @@ -1516,7 +1516,7 @@ class DesktopTasksController( // Desktop Mode is already showing and we're launching a new Task - we might need to // minimize another Task. val taskToMinimize = addAndGetMinimizeChangesIfNeeded(task.displayId, wct, task.taskId) addAndGetMinimizeChanges(task.displayId, wct, task.taskId) addPendingMinimizeTransition(transition, taskToMinimize) desktopImmersiveController.exitImmersiveIfApplicable( transition, wct, task.displayId Loading Loading @@ -1650,7 +1650,7 @@ class DesktopTasksController( val stableBounds = Rect() displayLayout.getStableBoundsForDesktopMode(stableBounds) val activeTasks = taskRepository.getActiveNonMinimizedOrderedTasks(displayId) val activeTasks = taskRepository.getExpandedTasksOrdered(displayId) activeTasks.firstOrNull()?.let { activeTask -> shellTaskOrganizer.getRunningTaskInfo(activeTask)?.let { cascadeWindow(context.resources, stableBounds, Loading Loading @@ -1679,7 +1679,7 @@ class DesktopTasksController( } /** Returns the ID of the Task that will be minimized, or null if no task will be minimized. */ private fun addAndGetMinimizeChangesIfNeeded( private fun addAndGetMinimizeChanges( displayId: Int, wct: WindowContainerTransaction, newTaskId: Int Loading @@ -1687,7 +1687,7 @@ class DesktopTasksController( if (!desktopTasksLimiter.isPresent) return null return desktopTasksLimiter .get() .addAndGetMinimizeTaskChangesIfNeeded(displayId, wct, newTaskId) .addAndGetMinimizeTaskChanges(displayId, wct, newTaskId) } private fun addPendingMinimizeTransition( Loading libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopTasksLimiter.kt +57 −86 Original line number Diff line number Diff line Loading @@ -30,7 +30,7 @@ import com.android.internal.jank.Cuj.CUJ_DESKTOP_MODE_MINIMIZE_WINDOW import com.android.internal.jank.InteractionJankMonitor import com.android.internal.protolog.ProtoLog import com.android.wm.shell.ShellTaskOrganizer import com.android.wm.shell.protolog.ShellProtoLogGroup import com.android.wm.shell.protolog.ShellProtoLogGroup.WM_SHELL_DESKTOP_MODE import com.android.wm.shell.shared.annotations.ShellMainThread import com.android.wm.shell.transition.Transitions import com.android.wm.shell.transition.Transitions.TransitionObserver Loading @@ -57,13 +57,11 @@ class DesktopTasksLimiter ( init { require(maxTasksLimit > 0) { "DesktopTasksLimiter should not be created with a maxTasksLimit at 0 or less. " + "Current value: $maxTasksLimit." "DesktopTasksLimiter: maxTasksLimit should be greater than 0. Current value: $maxTasksLimit." } transitions.registerObserver(minimizeTransitionObserver) taskRepository.addActiveTaskListener(leftoverMinimizedTasksRemover) ProtoLog.v(ShellProtoLogGroup.WM_SHELL_DESKTOP_MODE, "DesktopTasksLimiter: starting limiter with a maximum of %d tasks", maxTasksLimit) logV("Starting limiter with a maximum of %d tasks", maxTasksLimit) } private data class TaskDetails( Loading @@ -88,20 +86,14 @@ class DesktopTasksLimiter ( finishTransaction: SurfaceControl.Transaction ) { val taskToMinimize = pendingTransitionTokensAndTasks.remove(transition) ?: return if (!taskRepository.isActiveTask(taskToMinimize.taskId)) return if (!isTaskReorderedToBackOrInvisible(info, taskToMinimize)) { ProtoLog.v( ShellProtoLogGroup.WM_SHELL_DESKTOP_MODE, "DesktopTasksLimiter: task %d is not reordered to back nor invis", taskToMinimize.taskId) if (!isTaskReadyForMinimize(info, taskToMinimize)) { logV("task %d is not reordered to back nor invis", taskToMinimize.taskId) return } taskToMinimize.transitionInfo = info activeTransitionTokensAndTasks[transition] = taskToMinimize this@DesktopTasksLimiter.markTaskMinimized( this@DesktopTasksLimiter.minimizeTask( taskToMinimize.displayId, taskToMinimize.taskId) } Loading @@ -109,18 +101,15 @@ class DesktopTasksLimiter ( * Returns whether the Task [taskDetails] is being reordered to the back in the transition * [info], or is already invisible. * * This check can be used to double-check that a task was indeed minimized before * marking it as such. * This check confirms a task should be minimized before minimizing it. */ private fun isTaskReorderedToBackOrInvisible( private fun isTaskReadyForMinimize( info: TransitionInfo, taskDetails: TaskDetails ): Boolean { val taskChange = info.changes.find { change -> change.taskInfo?.taskId == taskDetails.taskId } if (taskChange == null) { return !taskRepository.isVisibleTask(taskDetails.taskId) } if (taskChange == null) return !taskRepository.isVisibleTask(taskDetails.taskId) return taskChange.mode == TRANSIT_TO_BACK } Loading @@ -145,9 +134,7 @@ class DesktopTasksLimiter ( } override fun onTransitionFinished(transition: IBinder, aborted: Boolean) { ProtoLog.v( ShellProtoLogGroup.WM_SHELL_DESKTOP_MODE, "DesktopTasksLimiter: transition %s finished", transition) logV("transition %s finished", transition) if (activeTransitionTokensAndTasks.remove(transition) != null) { if (aborted) { interactionJankMonitor.cancel(CUJ_DESKTOP_MODE_MINIMIZE_WINDOW) Loading @@ -170,18 +157,11 @@ class DesktopTasksLimiter ( } fun removeLeftoverMinimizedTasks(displayId: Int, wct: WindowContainerTransaction) { if (taskRepository.getActiveNonMinimizedOrderedTasks(displayId).isNotEmpty()) { return } if (taskRepository.getExpandedTasksOrdered(displayId).isNotEmpty()) return val remainingMinimizedTasks = taskRepository.getMinimizedTasks(displayId) if (remainingMinimizedTasks.isEmpty()) { return } ProtoLog.v( ShellProtoLogGroup.WM_SHELL_DESKTOP_MODE, "DesktopTasksLimiter: removing leftover minimized tasks: %s", remainingMinimizedTasks, ) if (remainingMinimizedTasks.isEmpty()) return logV("Removing leftover minimized tasks: %s", remainingMinimizedTasks) remainingMinimizedTasks.forEach { taskIdToRemove -> val taskToRemove = shellTaskOrganizer.getRunningTaskInfo(taskIdToRemove) if (taskToRemove != null) { Loading @@ -192,35 +172,30 @@ class DesktopTasksLimiter ( } /** * Mark [taskId], which must be on [displayId], as minimized, this should only be done after the * corresponding transition has finished so we don't minimize the task if the transition fails. * Mark task with [taskId] on [displayId] as minimized. * * This should be after the corresponding transition has finished so we don't * minimize the task if the transition fails. */ private fun markTaskMinimized(displayId: Int, taskId: Int) { ProtoLog.v( ShellProtoLogGroup.WM_SHELL_DESKTOP_MODE, "DesktopTasksLimiter: marking %d as minimized", taskId) private fun minimizeTask(displayId: Int, taskId: Int) { logV("Minimize taskId=%d, displayId=%d", taskId, displayId) taskRepository.minimizeTask(displayId, taskId) } /** * Add a minimize-transition to [wct] if adding [newFrontTaskInfo] brings us over the task * Adds a minimize-transition to [wct] if adding [newFrontTaskInfo] crosses task * limit, returning the task to minimize. * * The task must be on [displayId]. */ fun addAndGetMinimizeTaskChangesIfNeeded( fun addAndGetMinimizeTaskChanges( displayId: Int, wct: WindowContainerTransaction, newFrontTaskId: Int, ): RunningTaskInfo? { ProtoLog.v( ShellProtoLogGroup.WM_SHELL_DESKTOP_MODE, "DesktopTasksLimiter: addMinimizeBackTaskChangesIfNeeded, newFrontTask=%d", newFrontTaskId) val newTaskListOrderedFrontToBack = createOrderedTaskListWithGivenTaskInFront( taskRepository.getActiveNonMinimizedOrderedTasks(displayId), newFrontTaskId) val taskToMinimize = getTaskToMinimizeIfNeeded(newTaskListOrderedFrontToBack) logV("addAndGetMinimizeTaskChanges, newFrontTask=%d", newFrontTaskId) // This list is ordered from front to back. val newTaskOrderedList = createOrderedTaskListWithNewTask( taskRepository.getExpandedTasksOrdered(displayId), newFrontTaskId) val taskToMinimize = getTaskToMinimize(newTaskOrderedList) if (taskToMinimize != null) { wct.reorder(taskToMinimize.token, false /* onTop */) return taskToMinimize Loading @@ -229,7 +204,7 @@ class DesktopTasksLimiter ( } /** * Add a pending minimize transition change, to update the list of minimized apps once the * Add a pending minimize transition change to update the list of minimized apps once the * transition goes through. */ fun addPendingMinimizeChange(transition: IBinder, displayId: Int, taskId: Int) { Loading @@ -238,51 +213,47 @@ class DesktopTasksLimiter ( } /** * Returns the Task to minimize given 1. a list of visible tasks ordered from front to back and * 2. a new task placed in front of all the others. * Returns the minimized task from the list of visible tasks ordered from front to back with * the new task placed in front of other tasks. */ fun getTaskToMinimizeIfNeeded( visibleFreeformTaskIdsOrderedFrontToBack: List<Int>, fun getTaskToMinimize( visibleOrderedTasks: List<Int>, newTaskIdInFront: Int ): RunningTaskInfo? { return getTaskToMinimizeIfNeeded( createOrderedTaskListWithGivenTaskInFront( visibleFreeformTaskIdsOrderedFrontToBack, newTaskIdInFront)) } ): RunningTaskInfo? = getTaskToMinimize(createOrderedTaskListWithNewTask(visibleOrderedTasks, newTaskIdInFront)) /** Returns the Task to minimize given a list of visible tasks ordered from front to back. */ fun getTaskToMinimizeIfNeeded( visibleFreeformTaskIdsOrderedFrontToBack: List<Int> ): RunningTaskInfo? { if (visibleFreeformTaskIdsOrderedFrontToBack.size <= maxTasksLimit) { ProtoLog.v( ShellProtoLogGroup.WM_SHELL_DESKTOP_MODE, "DesktopTasksLimiter: no need to minimize; tasks below limit") // No need to minimize anything fun getTaskToMinimize(visibleOrderedTasks: List<Int>): RunningTaskInfo? { if (visibleOrderedTasks.size <= maxTasksLimit) { logV("No need to minimize; tasks below limit") return null } val taskIdToMinimize = visibleFreeformTaskIdsOrderedFrontToBack.last() val taskIdToMinimize = visibleOrderedTasks.last() val taskToMinimize = shellTaskOrganizer.getRunningTaskInfo(taskIdToMinimize) if (taskToMinimize == null) { ProtoLog.e( ShellProtoLogGroup.WM_SHELL_DESKTOP_MODE, "DesktopTasksLimiter: taskToMinimize(taskId = %d) == null", taskIdToMinimize, ) logE("taskToMinimize(taskId = %d) == null", taskIdToMinimize) return null } return taskToMinimize } private fun createOrderedTaskListWithGivenTaskInFront( existingTaskIdsOrderedFrontToBack: List<Int>, newTaskId: Int ): List<Int> { return listOf(newTaskId) + existingTaskIdsOrderedFrontToBack.filter { taskId -> taskId != newTaskId } } private fun createOrderedTaskListWithNewTask( orderedTaskIds: List<Int>, newTaskId: Int): List<Int> = listOf(newTaskId) + orderedTaskIds.filter { taskId -> taskId != newTaskId } @VisibleForTesting fun getTransitionObserver(): TransitionObserver = minimizeTransitionObserver private fun logV(msg: String, vararg arguments: Any?) { ProtoLog.v(WM_SHELL_DESKTOP_MODE, "%s: $msg", TAG, *arguments) } private fun logE(msg: String, vararg arguments: Any?) { ProtoLog.e(WM_SHELL_DESKTOP_MODE, "%s: $msg", TAG, *arguments) } private companion object { const val TAG = "DesktopTasksLimiter" } } libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/desktopmode/DesktopMixedTransitionHandlerTest.kt +2 −2 Original line number Diff line number Diff line Loading @@ -147,7 +147,7 @@ class DesktopMixedTransitionHandlerTest : ShellTestCase() { fun startAnimation_withClosingDesktopTask_callsCloseTaskHandler() { val transition = mock<IBinder>() val transitionInfo = createTransitionInfo(task = createTask(WINDOWING_MODE_FREEFORM)) whenever(desktopRepository.getActiveNonMinimizedTaskCount(any())).thenReturn(2) whenever(desktopRepository.getExpandedTaskCount(any())).thenReturn(2) whenever( closeDesktopTaskTransitionHandler.startAnimation(any(), any(), any(), any(), any()) ) Loading @@ -170,7 +170,7 @@ class DesktopMixedTransitionHandlerTest : ShellTestCase() { fun startAnimation_withClosingLastDesktopTask_dispatchesTransition() { val transition = mock<IBinder>() val transitionInfo = createTransitionInfo(task = createTask(WINDOWING_MODE_FREEFORM)) whenever(desktopRepository.getActiveNonMinimizedTaskCount(any())).thenReturn(1) whenever(desktopRepository.getExpandedTaskCount(any())).thenReturn(1) whenever(transitions.dispatchTransition(any(), any(), any(), any(), any(), any())) .thenReturn(mock()) Loading Loading
libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopMixedTransitionHandler.kt +1 −1 Original line number Diff line number Diff line Loading @@ -138,7 +138,7 @@ class DesktopMixedTransitionHandler( private fun isLastDesktopTask(change: TransitionInfo.Change): Boolean = change.taskInfo?.let { desktopRepository.getActiveNonMinimizedTaskCount(it.displayId) == 1 desktopRepository.getExpandedTaskCount(it.displayId) == 1 } ?: false private fun findCloseDesktopTaskChange(info: TransitionInfo): TransitionInfo.Change? { Loading
libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopRepository.kt +2 −2 Original line number Diff line number Diff line Loading @@ -260,11 +260,11 @@ class DesktopRepository ( ArraySet(desktopTaskDataByDisplayId[displayId]?.minimizedTasks) /** Returns all active non-minimized tasks for [displayId] ordered from top to bottom. */ fun getActiveNonMinimizedOrderedTasks(displayId: Int): List<Int> = fun getExpandedTasksOrdered(displayId: Int): List<Int> = getFreeformTasksInZOrder(displayId).filter { !isMinimizedTask(it) } /** Returns the count of active non-minimized tasks for [displayId]. */ fun getActiveNonMinimizedTaskCount(displayId: Int): Int { fun getExpandedTaskCount(displayId: Int): Int { return getActiveTasks(displayId).count { !isMinimizedTask(it) } } Loading
libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopTasksController.kt +12 −12 Original line number Diff line number Diff line Loading @@ -662,7 +662,7 @@ class DesktopTasksController( remoteTransition: RemoteTransition?, ): IBinder { val taskToMinimize: RunningTaskInfo? = addAndGetMinimizeChangesIfNeeded(DEFAULT_DISPLAY, wct, taskId) addAndGetMinimizeChanges(DEFAULT_DISPLAY, wct, taskId) if (remoteTransition == null) { val t = transitions.startTransition(transitionType, wct, null /* handler */) addPendingMinimizeTransition(t, taskToMinimize) Loading Loading @@ -872,7 +872,7 @@ class DesktopTasksController( excludeTaskId: Int? = null, ): Boolean { val doesAnyTaskRequireTaskbarRounding = taskRepository.getActiveNonMinimizedOrderedTasks(displayId) taskRepository.getExpandedTasksOrdered(displayId) // exclude current task since maximize/restore transition has not taken place yet. .filterNot { taskId -> taskId == excludeTaskId } .any { taskId -> Loading Loading @@ -1050,23 +1050,23 @@ class DesktopTasksController( addWallpaperActivity(wct) } val nonMinimizedTasksOrderedFrontToBack = taskRepository.getActiveNonMinimizedOrderedTasks(displayId) val expandedTasksOrderedFrontToBack = taskRepository.getExpandedTasksOrdered(displayId) // If we're adding a new Task we might need to minimize an old one // TODO(b/365725441): Handle non running task minimization val taskToMinimize: RunningTaskInfo? = if (newTaskIdInFront != null && desktopTasksLimiter.isPresent) { desktopTasksLimiter .get() .getTaskToMinimizeIfNeeded( nonMinimizedTasksOrderedFrontToBack, .getTaskToMinimize( expandedTasksOrderedFrontToBack, newTaskIdInFront ) } else { null } nonMinimizedTasksOrderedFrontToBack expandedTasksOrderedFrontToBack // If there is a Task to minimize, let it stay behind the Home Task .filter { taskId -> taskId != taskToMinimize?.taskId } .reversed() // Start from the back so the front task is brought forward last Loading Loading @@ -1489,7 +1489,7 @@ class DesktopTasksController( // 1) Exit immersive if needed. desktopImmersiveController.exitImmersiveIfApplicable(transition, wct, task.displayId) // 2) minimize a Task if needed. val taskToMinimize = addAndGetMinimizeChangesIfNeeded(task.displayId, wct, task.taskId) val taskToMinimize = addAndGetMinimizeChanges(task.displayId, wct, task.taskId) if (taskToMinimize != null) { addPendingMinimizeTransition(transition, taskToMinimize) return wct Loading @@ -1516,7 +1516,7 @@ class DesktopTasksController( // Desktop Mode is already showing and we're launching a new Task - we might need to // minimize another Task. val taskToMinimize = addAndGetMinimizeChangesIfNeeded(task.displayId, wct, task.taskId) addAndGetMinimizeChanges(task.displayId, wct, task.taskId) addPendingMinimizeTransition(transition, taskToMinimize) desktopImmersiveController.exitImmersiveIfApplicable( transition, wct, task.displayId Loading Loading @@ -1650,7 +1650,7 @@ class DesktopTasksController( val stableBounds = Rect() displayLayout.getStableBoundsForDesktopMode(stableBounds) val activeTasks = taskRepository.getActiveNonMinimizedOrderedTasks(displayId) val activeTasks = taskRepository.getExpandedTasksOrdered(displayId) activeTasks.firstOrNull()?.let { activeTask -> shellTaskOrganizer.getRunningTaskInfo(activeTask)?.let { cascadeWindow(context.resources, stableBounds, Loading Loading @@ -1679,7 +1679,7 @@ class DesktopTasksController( } /** Returns the ID of the Task that will be minimized, or null if no task will be minimized. */ private fun addAndGetMinimizeChangesIfNeeded( private fun addAndGetMinimizeChanges( displayId: Int, wct: WindowContainerTransaction, newTaskId: Int Loading @@ -1687,7 +1687,7 @@ class DesktopTasksController( if (!desktopTasksLimiter.isPresent) return null return desktopTasksLimiter .get() .addAndGetMinimizeTaskChangesIfNeeded(displayId, wct, newTaskId) .addAndGetMinimizeTaskChanges(displayId, wct, newTaskId) } private fun addPendingMinimizeTransition( Loading
libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopTasksLimiter.kt +57 −86 Original line number Diff line number Diff line Loading @@ -30,7 +30,7 @@ import com.android.internal.jank.Cuj.CUJ_DESKTOP_MODE_MINIMIZE_WINDOW import com.android.internal.jank.InteractionJankMonitor import com.android.internal.protolog.ProtoLog import com.android.wm.shell.ShellTaskOrganizer import com.android.wm.shell.protolog.ShellProtoLogGroup import com.android.wm.shell.protolog.ShellProtoLogGroup.WM_SHELL_DESKTOP_MODE import com.android.wm.shell.shared.annotations.ShellMainThread import com.android.wm.shell.transition.Transitions import com.android.wm.shell.transition.Transitions.TransitionObserver Loading @@ -57,13 +57,11 @@ class DesktopTasksLimiter ( init { require(maxTasksLimit > 0) { "DesktopTasksLimiter should not be created with a maxTasksLimit at 0 or less. " + "Current value: $maxTasksLimit." "DesktopTasksLimiter: maxTasksLimit should be greater than 0. Current value: $maxTasksLimit." } transitions.registerObserver(minimizeTransitionObserver) taskRepository.addActiveTaskListener(leftoverMinimizedTasksRemover) ProtoLog.v(ShellProtoLogGroup.WM_SHELL_DESKTOP_MODE, "DesktopTasksLimiter: starting limiter with a maximum of %d tasks", maxTasksLimit) logV("Starting limiter with a maximum of %d tasks", maxTasksLimit) } private data class TaskDetails( Loading @@ -88,20 +86,14 @@ class DesktopTasksLimiter ( finishTransaction: SurfaceControl.Transaction ) { val taskToMinimize = pendingTransitionTokensAndTasks.remove(transition) ?: return if (!taskRepository.isActiveTask(taskToMinimize.taskId)) return if (!isTaskReorderedToBackOrInvisible(info, taskToMinimize)) { ProtoLog.v( ShellProtoLogGroup.WM_SHELL_DESKTOP_MODE, "DesktopTasksLimiter: task %d is not reordered to back nor invis", taskToMinimize.taskId) if (!isTaskReadyForMinimize(info, taskToMinimize)) { logV("task %d is not reordered to back nor invis", taskToMinimize.taskId) return } taskToMinimize.transitionInfo = info activeTransitionTokensAndTasks[transition] = taskToMinimize this@DesktopTasksLimiter.markTaskMinimized( this@DesktopTasksLimiter.minimizeTask( taskToMinimize.displayId, taskToMinimize.taskId) } Loading @@ -109,18 +101,15 @@ class DesktopTasksLimiter ( * Returns whether the Task [taskDetails] is being reordered to the back in the transition * [info], or is already invisible. * * This check can be used to double-check that a task was indeed minimized before * marking it as such. * This check confirms a task should be minimized before minimizing it. */ private fun isTaskReorderedToBackOrInvisible( private fun isTaskReadyForMinimize( info: TransitionInfo, taskDetails: TaskDetails ): Boolean { val taskChange = info.changes.find { change -> change.taskInfo?.taskId == taskDetails.taskId } if (taskChange == null) { return !taskRepository.isVisibleTask(taskDetails.taskId) } if (taskChange == null) return !taskRepository.isVisibleTask(taskDetails.taskId) return taskChange.mode == TRANSIT_TO_BACK } Loading @@ -145,9 +134,7 @@ class DesktopTasksLimiter ( } override fun onTransitionFinished(transition: IBinder, aborted: Boolean) { ProtoLog.v( ShellProtoLogGroup.WM_SHELL_DESKTOP_MODE, "DesktopTasksLimiter: transition %s finished", transition) logV("transition %s finished", transition) if (activeTransitionTokensAndTasks.remove(transition) != null) { if (aborted) { interactionJankMonitor.cancel(CUJ_DESKTOP_MODE_MINIMIZE_WINDOW) Loading @@ -170,18 +157,11 @@ class DesktopTasksLimiter ( } fun removeLeftoverMinimizedTasks(displayId: Int, wct: WindowContainerTransaction) { if (taskRepository.getActiveNonMinimizedOrderedTasks(displayId).isNotEmpty()) { return } if (taskRepository.getExpandedTasksOrdered(displayId).isNotEmpty()) return val remainingMinimizedTasks = taskRepository.getMinimizedTasks(displayId) if (remainingMinimizedTasks.isEmpty()) { return } ProtoLog.v( ShellProtoLogGroup.WM_SHELL_DESKTOP_MODE, "DesktopTasksLimiter: removing leftover minimized tasks: %s", remainingMinimizedTasks, ) if (remainingMinimizedTasks.isEmpty()) return logV("Removing leftover minimized tasks: %s", remainingMinimizedTasks) remainingMinimizedTasks.forEach { taskIdToRemove -> val taskToRemove = shellTaskOrganizer.getRunningTaskInfo(taskIdToRemove) if (taskToRemove != null) { Loading @@ -192,35 +172,30 @@ class DesktopTasksLimiter ( } /** * Mark [taskId], which must be on [displayId], as minimized, this should only be done after the * corresponding transition has finished so we don't minimize the task if the transition fails. * Mark task with [taskId] on [displayId] as minimized. * * This should be after the corresponding transition has finished so we don't * minimize the task if the transition fails. */ private fun markTaskMinimized(displayId: Int, taskId: Int) { ProtoLog.v( ShellProtoLogGroup.WM_SHELL_DESKTOP_MODE, "DesktopTasksLimiter: marking %d as minimized", taskId) private fun minimizeTask(displayId: Int, taskId: Int) { logV("Minimize taskId=%d, displayId=%d", taskId, displayId) taskRepository.minimizeTask(displayId, taskId) } /** * Add a minimize-transition to [wct] if adding [newFrontTaskInfo] brings us over the task * Adds a minimize-transition to [wct] if adding [newFrontTaskInfo] crosses task * limit, returning the task to minimize. * * The task must be on [displayId]. */ fun addAndGetMinimizeTaskChangesIfNeeded( fun addAndGetMinimizeTaskChanges( displayId: Int, wct: WindowContainerTransaction, newFrontTaskId: Int, ): RunningTaskInfo? { ProtoLog.v( ShellProtoLogGroup.WM_SHELL_DESKTOP_MODE, "DesktopTasksLimiter: addMinimizeBackTaskChangesIfNeeded, newFrontTask=%d", newFrontTaskId) val newTaskListOrderedFrontToBack = createOrderedTaskListWithGivenTaskInFront( taskRepository.getActiveNonMinimizedOrderedTasks(displayId), newFrontTaskId) val taskToMinimize = getTaskToMinimizeIfNeeded(newTaskListOrderedFrontToBack) logV("addAndGetMinimizeTaskChanges, newFrontTask=%d", newFrontTaskId) // This list is ordered from front to back. val newTaskOrderedList = createOrderedTaskListWithNewTask( taskRepository.getExpandedTasksOrdered(displayId), newFrontTaskId) val taskToMinimize = getTaskToMinimize(newTaskOrderedList) if (taskToMinimize != null) { wct.reorder(taskToMinimize.token, false /* onTop */) return taskToMinimize Loading @@ -229,7 +204,7 @@ class DesktopTasksLimiter ( } /** * Add a pending minimize transition change, to update the list of minimized apps once the * Add a pending minimize transition change to update the list of minimized apps once the * transition goes through. */ fun addPendingMinimizeChange(transition: IBinder, displayId: Int, taskId: Int) { Loading @@ -238,51 +213,47 @@ class DesktopTasksLimiter ( } /** * Returns the Task to minimize given 1. a list of visible tasks ordered from front to back and * 2. a new task placed in front of all the others. * Returns the minimized task from the list of visible tasks ordered from front to back with * the new task placed in front of other tasks. */ fun getTaskToMinimizeIfNeeded( visibleFreeformTaskIdsOrderedFrontToBack: List<Int>, fun getTaskToMinimize( visibleOrderedTasks: List<Int>, newTaskIdInFront: Int ): RunningTaskInfo? { return getTaskToMinimizeIfNeeded( createOrderedTaskListWithGivenTaskInFront( visibleFreeformTaskIdsOrderedFrontToBack, newTaskIdInFront)) } ): RunningTaskInfo? = getTaskToMinimize(createOrderedTaskListWithNewTask(visibleOrderedTasks, newTaskIdInFront)) /** Returns the Task to minimize given a list of visible tasks ordered from front to back. */ fun getTaskToMinimizeIfNeeded( visibleFreeformTaskIdsOrderedFrontToBack: List<Int> ): RunningTaskInfo? { if (visibleFreeformTaskIdsOrderedFrontToBack.size <= maxTasksLimit) { ProtoLog.v( ShellProtoLogGroup.WM_SHELL_DESKTOP_MODE, "DesktopTasksLimiter: no need to minimize; tasks below limit") // No need to minimize anything fun getTaskToMinimize(visibleOrderedTasks: List<Int>): RunningTaskInfo? { if (visibleOrderedTasks.size <= maxTasksLimit) { logV("No need to minimize; tasks below limit") return null } val taskIdToMinimize = visibleFreeformTaskIdsOrderedFrontToBack.last() val taskIdToMinimize = visibleOrderedTasks.last() val taskToMinimize = shellTaskOrganizer.getRunningTaskInfo(taskIdToMinimize) if (taskToMinimize == null) { ProtoLog.e( ShellProtoLogGroup.WM_SHELL_DESKTOP_MODE, "DesktopTasksLimiter: taskToMinimize(taskId = %d) == null", taskIdToMinimize, ) logE("taskToMinimize(taskId = %d) == null", taskIdToMinimize) return null } return taskToMinimize } private fun createOrderedTaskListWithGivenTaskInFront( existingTaskIdsOrderedFrontToBack: List<Int>, newTaskId: Int ): List<Int> { return listOf(newTaskId) + existingTaskIdsOrderedFrontToBack.filter { taskId -> taskId != newTaskId } } private fun createOrderedTaskListWithNewTask( orderedTaskIds: List<Int>, newTaskId: Int): List<Int> = listOf(newTaskId) + orderedTaskIds.filter { taskId -> taskId != newTaskId } @VisibleForTesting fun getTransitionObserver(): TransitionObserver = minimizeTransitionObserver private fun logV(msg: String, vararg arguments: Any?) { ProtoLog.v(WM_SHELL_DESKTOP_MODE, "%s: $msg", TAG, *arguments) } private fun logE(msg: String, vararg arguments: Any?) { ProtoLog.e(WM_SHELL_DESKTOP_MODE, "%s: $msg", TAG, *arguments) } private companion object { const val TAG = "DesktopTasksLimiter" } }
libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/desktopmode/DesktopMixedTransitionHandlerTest.kt +2 −2 Original line number Diff line number Diff line Loading @@ -147,7 +147,7 @@ class DesktopMixedTransitionHandlerTest : ShellTestCase() { fun startAnimation_withClosingDesktopTask_callsCloseTaskHandler() { val transition = mock<IBinder>() val transitionInfo = createTransitionInfo(task = createTask(WINDOWING_MODE_FREEFORM)) whenever(desktopRepository.getActiveNonMinimizedTaskCount(any())).thenReturn(2) whenever(desktopRepository.getExpandedTaskCount(any())).thenReturn(2) whenever( closeDesktopTaskTransitionHandler.startAnimation(any(), any(), any(), any(), any()) ) Loading @@ -170,7 +170,7 @@ class DesktopMixedTransitionHandlerTest : ShellTestCase() { fun startAnimation_withClosingLastDesktopTask_dispatchesTransition() { val transition = mock<IBinder>() val transitionInfo = createTransitionInfo(task = createTask(WINDOWING_MODE_FREEFORM)) whenever(desktopRepository.getActiveNonMinimizedTaskCount(any())).thenReturn(1) whenever(desktopRepository.getExpandedTaskCount(any())).thenReturn(1) whenever(transitions.dispatchTransition(any(), any(), any(), any(), any(), any())) .thenReturn(mock()) Loading