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

Commit 4839d295 authored by Jorge Gil's avatar Jorge Gil
Browse files

[35/N] Desks: Add DesksOrganizer#unminimizeTask

Unminimizes a task from a desk if it was minimized. Internally, it means
the task is reparented from the minimization root to the desk root.

To a DesksOrganizer, unminimization does not imply desk activation, so
activating an inactive desk by unminimizing one of its tasks will still
need to be explicitly done by DesktopTasksController in a separate CL.

Flag: com.android.window.flags.enable_multiple_desktops_backend
Bug: 393978427
Test: atest WMShellUnitTests
Change-Id: Ic6d9c4b2c1731c4edcdd184dabaf34d17d155253
parent 08000947
Loading
Loading
Loading
Loading
+7 −0
Original line number Diff line number Diff line
@@ -47,6 +47,13 @@ interface DesksOrganizer {
        task: ActivityManager.RunningTaskInfo,
    )

    /** Unminimize the given task of the given desk. */
    fun unminimizeTask(
        wct: WindowContainerTransaction,
        deskId: Int,
        task: ActivityManager.RunningTaskInfo,
    )

    /** Whether the change is for the given desk id. */
    fun isDeskChange(change: TransitionInfo.Change, deskId: Int): Boolean

+25 −0
Original line number Diff line number Diff line
@@ -111,6 +111,7 @@ class RootTaskDesksOrganizer(
    }

    override fun minimizeTask(wct: WindowContainerTransaction, deskId: Int, task: RunningTaskInfo) {
        logV("minimizeTask task=${task.taskId} desk=$deskId")
        val deskRoot =
            checkNotNull(deskRootsByDeskId[deskId]) { "Root not found for desk: $deskId" }
        val minimizationRoot =
@@ -129,6 +130,30 @@ class RootTaskDesksOrganizer(
        wct.reparent(task.token, minimizationRoot.token, /* onTop= */ true)
    }

    override fun unminimizeTask(
        wct: WindowContainerTransaction,
        deskId: Int,
        task: RunningTaskInfo,
    ) {
        val taskId = task.taskId
        logV("unminimizeTask task=$taskId desk=$deskId")
        val deskRoot =
            checkNotNull(deskRootsByDeskId[deskId]) { "Root not found for desk: $deskId" }
        val minimizationRoot =
            checkNotNull(deskMinimizationRootsByDeskId[deskId]) {
                "Minimization root not found for desk: $deskId"
            }
        if (taskId in deskRoot.children) {
            logV("Task #$taskId is already unminimized in desk=$deskId")
            return
        }
        if (taskId !in minimizationRoot.children) {
            logE("Attempted to unminimize task=$taskId in desk=$deskId but it was not a child")
            return
        }
        wct.reparent(task.token, deskRoot.token, /* onTop= */ true)
    }

    override fun isDeskChange(change: TransitionInfo.Change, deskId: Int): Boolean =
        (isDeskRootChange(change) && change.taskId == deskId) ||
            (getDeskMinimizationRootInChange(change)?.deskId == deskId)
+65 −8
Original line number Diff line number Diff line
@@ -21,6 +21,7 @@ import android.view.Display
import android.view.SurfaceControl
import android.view.WindowManager.TRANSIT_TO_FRONT
import android.window.TransitionInfo
import android.window.WindowContainerToken
import android.window.WindowContainerTransaction
import android.window.WindowContainerTransaction.Change
import android.window.WindowContainerTransaction.HierarchyOp
@@ -473,14 +474,7 @@ class RootTaskDesksOrganizerTest : ShellTestCase() {

        organizer.minimizeTask(wct, deskId = desk.deskRoot.deskId, task)

        assertThat(
                wct.hierarchyOps.any { hop ->
                    hop.isReparent &&
                        hop.container == task.token.asBinder() &&
                        hop.newParent == desk.minimizationRoot.token.asBinder()
                }
            )
            .isTrue()
        assertThat(wct.hasMinimizationHops(desk, task.token)).isTrue()
    }

    @Test
@@ -508,6 +502,48 @@ class RootTaskDesksOrganizerTest : ShellTestCase() {
        assertThat(wct.isEmpty).isTrue()
    }

    @Test
    fun unminimizeTask() {
        val desk = createDesk()
        val task = createFreeformTask().apply { parentTaskId = desk.deskRoot.deskId }
        val wct = WindowContainerTransaction()
        organizer.moveTaskToDesk(wct, desk.deskRoot.deskId, task)
        organizer.onTaskAppeared(task, SurfaceControl())
        organizer.minimizeTask(wct, deskId = desk.deskRoot.deskId, task)
        task.parentTaskId = desk.minimizationRoot.rootId
        organizer.onTaskInfoChanged(task)

        wct.clear()
        organizer.unminimizeTask(wct, deskId = desk.deskRoot.deskId, task)

        assertThat(wct.hasUnminimizationHops(desk, task.token)).isTrue()
    }

    @Test
    fun unminimizeTask_alreadyUnminimized_noOp() {
        val desk = createDesk()
        val task = createFreeformTask().apply { parentTaskId = desk.deskRoot.deskId }
        val wct = WindowContainerTransaction()
        organizer.moveTaskToDesk(wct, desk.deskRoot.deskId, task)
        organizer.onTaskAppeared(task, SurfaceControl())

        wct.clear()
        organizer.unminimizeTask(wct, deskId = desk.deskRoot.deskId, task)

        assertThat(wct.hasUnminimizationHops(desk, task.token)).isFalse()
    }

    @Test
    fun unminimizeTask_notInDesk_noOp() {
        val desk = createDesk()
        val task = createFreeformTask()
        val wct = WindowContainerTransaction()

        organizer.unminimizeTask(wct, deskId = desk.deskRoot.deskId, task)

        assertThat(wct.hasUnminimizationHops(desk, task.token)).isFalse()
    }

    private data class DeskRoots(
        val deskRoot: DeskRoot,
        val minimizationRoot: DeskMinimizationRoot,
@@ -525,6 +561,27 @@ class RootTaskDesksOrganizerTest : ShellTestCase() {
        )
    }

    private fun WindowContainerTransaction.hasMinimizationHops(
        desk: DeskRoots,
        task: WindowContainerToken,
    ): Boolean =
        hierarchyOps.any { hop ->
            hop.isReparent &&
                hop.container == task.asBinder() &&
                hop.newParent == desk.minimizationRoot.token.asBinder()
        }

    private fun WindowContainerTransaction.hasUnminimizationHops(
        desk: DeskRoots,
        task: WindowContainerToken,
    ): Boolean =
        hierarchyOps.any { hop ->
            hop.isReparent &&
                hop.container == task.asBinder() &&
                hop.newParent == desk.deskRoot.token.asBinder() &&
                hop.toTop
        }

    private class FakeOnCreateCallback : DesksOrganizer.OnCreateCallback {
        var deskId: Int? = null
        val created: Boolean