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

Commit 0129eb9d authored by Gustav Sennton's avatar Gustav Sennton
Browse files

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
parent 4988ed31
Loading
Loading
Loading
Loading
+4 −0
Original line number Original line Diff line number Diff line
@@ -250,6 +250,10 @@ class DesktopModeTaskRepository {
        return ArraySet(displayData[displayId]?.activeTasks)
        return ArraySet(displayData[displayId]?.activeTasks)
    }
    }


    /** Returns the minimized tasks for the given [displayId]. */
    fun getMinimizedTasks(displayId: Int): ArraySet<Int> =
        ArraySet(displayData[displayId]?.minimizedTasks)

    /**
    /**
     * Returns whether Desktop Mode is currently showing any tasks, i.e. whether any Desktop Tasks
     * Returns whether Desktop Mode is currently showing any tasks, i.e. whether any Desktop Tasks
     * are visible.
     * are visible.
+32 −0
Original line number Original line Diff line number Diff line
@@ -42,9 +42,12 @@ class DesktopTasksLimiter (
        private val shellTaskOrganizer: ShellTaskOrganizer,
        private val shellTaskOrganizer: ShellTaskOrganizer,
) {
) {
    private val minimizeTransitionObserver = MinimizeTransitionObserver()
    private val minimizeTransitionObserver = MinimizeTransitionObserver()
    @VisibleForTesting
    val leftoverMinimizedTasksRemover = LeftoverMinimizedTasksRemover()


    init {
    init {
        transitions.registerObserver(minimizeTransitionObserver)
        transitions.registerObserver(minimizeTransitionObserver)
        taskRepository.addActiveTaskListener(leftoverMinimizedTasksRemover)
    }
    }


    private data class TaskDetails (val displayId: Int, val taskId: Int)
    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
     * 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.
     * finished so we don't minimize the task if the transition fails.
+41 −0
Original line number Original line Diff line number Diff line
@@ -24,6 +24,7 @@ import android.view.Display.DEFAULT_DISPLAY
import android.view.WindowManager.TRANSIT_OPEN
import android.view.WindowManager.TRANSIT_OPEN
import android.view.WindowManager.TRANSIT_TO_BACK
import android.view.WindowManager.TRANSIT_TO_BACK
import android.window.WindowContainerTransaction
import android.window.WindowContainerTransaction
import android.window.WindowContainerTransaction.HierarchyOp.HIERARCHY_OP_TYPE_REMOVE_TASK
import android.window.WindowContainerTransaction.HierarchyOp.HIERARCHY_OP_TYPE_REORDER
import android.window.WindowContainerTransaction.HierarchyOp.HIERARCHY_OP_TYPE_REORDER
import androidx.test.filters.SmallTest
import androidx.test.filters.SmallTest
import com.android.dx.mockito.inline.extended.ExtendedMockito
import com.android.dx.mockito.inline.extended.ExtendedMockito
@@ -204,6 +205,46 @@ class DesktopTasksLimiterTest : ShellTestCase() {
        assertThat(desktopTaskRepo.isMinimizedTask(taskId = task.taskId)).isTrue()
        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
    @Test
    fun addAndGetMinimizeTaskChangesIfNeeded_tasksWithinLimit_noTaskMinimized() {
    fun addAndGetMinimizeTaskChangesIfNeeded_tasksWithinLimit_noTaskMinimized() {
        val taskLimit = desktopTasksLimiter.getMaxTaskLimit()
        val taskLimit = desktopTasksLimiter.getMaxTaskLimit()