Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 96940dcd authored by Pragya Bajoria's avatar Pragya Bajoria
Browse files

Refactor DesktopTasksLimiter to adapt it to be migrated into DesktopRepository.

Flag: EXEMPT (cosmetic changes only in this CL)
Bug: 367269373
Change-Id: I907bfdbe39b8894a56a3c9f09b3d562ba5c7e0fb
parent 8cf76249
Loading
Loading
Loading
Loading
+1 −1
Original line number Diff line number Diff line
@@ -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? {
+2 −2
Original line number Diff line number Diff line
@@ -262,11 +262,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) }
    }

+12 −12
Original line number Diff line number Diff line
@@ -644,7 +644,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)
@@ -847,7 +847,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 ->
@@ -999,23 +999,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
@@ -1374,7 +1374,7 @@ class DesktopTasksController(
        // 1) Exit immersive if needed.
        immersiveTransitionHandler.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
@@ -1401,7 +1401,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)
                immersiveTransitionHandler.exitImmersiveIfApplicable(
                    transition, wct, task.displayId
@@ -1529,7 +1529,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,
@@ -1558,7 +1558,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
@@ -1566,7 +1566,7 @@ class DesktopTasksController(
        if (!desktopTasksLimiter.isPresent) return null
        return desktopTasksLimiter
            .get()
            .addAndGetMinimizeTaskChangesIfNeeded(displayId, wct, newTaskId)
            .addAndGetMinimizeTaskChanges(displayId, wct, newTaskId)
    }

    private fun addPendingMinimizeTransition(
+57 −86
Original line number Diff line number Diff line
@@ -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
@@ -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(
@@ -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)
        }

@@ -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
        }

@@ -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)
@@ -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) {
@@ -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
@@ -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) {
@@ -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"
    }
}
+2 −2
Original line number Diff line number Diff line
@@ -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())
            )
@@ -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