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

Commit fd042f14 authored by Pragya Bajoria's avatar Pragya Bajoria Committed by Android (Google) Code Review
Browse files

Merge "Refactor DesktopTasksLimiter to adapt it to be migrated into DesktopRepository." into main

parents 58613adc 96940dcd
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
@@ -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) }
    }

+12 −12
Original line number Diff line number Diff line
@@ -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)
@@ -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 ->
@@ -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
@@ -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
@@ -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
@@ -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,
@@ -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
@@ -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(
+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