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

Commit fe05a0b3 authored by Toshiki Kikuchi's avatar Toshiki Kikuchi
Browse files

Setup desktop when entering desktop by app-initiated transition

This CL setup the desktop env (e.g., bring up DesktopWallpaper) when an
app is launched (or moved to top) into the desktop by app-initiated
transition when the desktop session is not activated.
We probably want to consolidate the logic with handleFreeformTaskLaunch
but this CL is the hot fix.

Flag: com.android.window.flags.enable_display_windowing_mode_switching
Bug: 397249847
Test: DesktopTasksControllerTest
Change-Id: Ia778bff76eaccadb1adb9558c4b529a145d48ea3
parent 6b3d33e2
Loading
Loading
Loading
Loading
+56 −13
Original line number Diff line number Diff line
@@ -1055,7 +1055,8 @@ class DesktopTasksController(
        )
    }

    private fun startLaunchTransition(
    @VisibleForTesting
    fun startLaunchTransition(
        transitionType: Int,
        wct: WindowContainerTransaction,
        launchingTaskId: Int?,
@@ -1063,34 +1064,52 @@ class DesktopTasksController(
        displayId: Int = DEFAULT_DISPLAY,
        unminimizeReason: UnminimizeReason = UnminimizeReason.UNKNOWN,
    ): IBinder {
        // TODO: b/397619806 - Consolidate sharable logic with [handleFreeformTaskLaunch].
        var launchTransaction = wct
        val taskIdToMinimize =
            addAndGetMinimizeChanges(
                displayId,
                wct,
                launchTransaction,
                newTaskId = launchingTaskId,
                launchingNewIntent = launchingTaskId == null,
            )
        val exitImmersiveResult =
            desktopImmersiveController.exitImmersiveIfApplicable(
                wct = wct,
                wct = launchTransaction,
                displayId = displayId,
                excludeTaskId = launchingTaskId,
                reason = DesktopImmersiveController.ExitReason.TASK_LAUNCH,
            )
        var deskIdToActivate: Int? = null
        if (
            DesktopExperienceFlags.ENABLE_DISPLAY_WINDOWING_MODE_SWITCHING.isTrue &&
                !isDesktopModeShowing(displayId)
        ) {
            deskIdToActivate =
                checkNotNull(
                    launchingTaskId?.let { taskRepository.getDeskIdForTask(it) }
                        ?: getDefaultDeskId(displayId)
                )
            val activateDeskWct = WindowContainerTransaction()
            addDeskActivationChanges(deskIdToActivate, activateDeskWct)
            // Desk activation must be handled before app launch-related transactions.
            activateDeskWct.merge(launchTransaction, /* transfer= */ true)
            launchTransaction = activateDeskWct
        }
        val t =
            if (remoteTransition == null) {
                desktopMixedTransitionHandler.startLaunchTransition(
                    transitionType = transitionType,
                    wct = wct,
                    wct = launchTransaction,
                    taskId = launchingTaskId,
                    minimizingTaskId = taskIdToMinimize,
                    exitingImmersiveTask = exitImmersiveResult.asExit()?.exitingTask,
                )
            } else if (taskIdToMinimize == null) {
                val remoteTransitionHandler = OneShotRemoteHandler(mainExecutor, remoteTransition)
                transitions.startTransition(transitionType, wct, remoteTransitionHandler).also {
                    remoteTransitionHandler.setTransition(it)
                }
                transitions
                    .startTransition(transitionType, launchTransaction, remoteTransitionHandler)
                    .also { remoteTransitionHandler.setTransition(it) }
            } else {
                val remoteTransitionHandler =
                    DesktopWindowLimitRemoteHandler(
@@ -1099,9 +1118,9 @@ class DesktopTasksController(
                        remoteTransition,
                        taskIdToMinimize,
                    )
                transitions.startTransition(transitionType, wct, remoteTransitionHandler).also {
                    remoteTransitionHandler.setTransition(it)
                }
                transitions
                    .startTransition(transitionType, launchTransaction, remoteTransitionHandler)
                    .also { remoteTransitionHandler.setTransition(it) }
            }
        if (taskIdToMinimize != null) {
            addPendingMinimizeTransition(t, taskIdToMinimize, MinimizeReason.TASK_LIMIT)
@@ -1109,6 +1128,24 @@ class DesktopTasksController(
        if (launchingTaskId != null && taskRepository.isMinimizedTask(launchingTaskId)) {
            addPendingUnminimizeTransition(t, displayId, launchingTaskId, unminimizeReason)
        }
        if (
            DesktopExperienceFlags.ENABLE_MULTIPLE_DESKTOPS_BACKEND.isTrue &&
                deskIdToActivate != null
        ) {
            if (DesktopExperienceFlags.ENABLE_DISPLAY_WINDOWING_MODE_SWITCHING.isTrue) {
                desksTransitionObserver.addPendingTransition(
                    DeskTransition.ActivateDesk(
                        token = t,
                        displayId = displayId,
                        deskId = deskIdToActivate,
                    )
                )
            }

            desktopModeEnterExitTransitionListener?.onEnterDesktopModeTransitionStarted(
                FREEFORM_ANIMATION_DURATION
            )
        }
        exitImmersiveResult.asExit()?.runOnTransitionStart?.invoke(t)
        return t
    }
@@ -2665,10 +2702,9 @@ class DesktopTasksController(
        activateDesk(deskId, remoteTransition)
    }

    /** Activates the given desk. */
    fun activateDesk(deskId: Int, remoteTransition: RemoteTransition? = null) {
    /** Activates the given desk but without starting a transition. */
    fun addDeskActivationChanges(deskId: Int, wct: WindowContainerTransaction) {
        val displayId = taskRepository.getDisplayForDesk(deskId)
        val wct = WindowContainerTransaction()
        if (DesktopExperienceFlags.ENABLE_MULTIPLE_DESKTOPS_BACKEND.isTrue) {
            prepareForDeskActivation(displayId, wct)
            desksOrganizer.activateDesk(wct, deskId)
@@ -2681,6 +2717,13 @@ class DesktopTasksController(
        } else {
            bringDesktopAppsToFront(displayId, wct)
        }
    }

    /** Activates the given desk. */
    fun activateDesk(deskId: Int, remoteTransition: RemoteTransition? = null) {
        val displayId = taskRepository.getDisplayForDesk(deskId)
        val wct = WindowContainerTransaction()
        addDeskActivationChanges(deskId, wct)

        val transitionType = transitionType(remoteTransition)
        val handler =
+76 −4
Original line number Diff line number Diff line
@@ -2477,8 +2477,7 @@ class DesktopTasksControllerTest(flags: FlagsParameterization) : ShellTestCase()
        controller.moveTaskToFront(task.taskId, unminimizeReason = UnminimizeReason.UNKNOWN)

        val wct = getLatestDesktopMixedTaskWct(type = TRANSIT_OPEN)
        assertThat(wct.hierarchyOps).hasSize(1)
        wct.assertLaunchTaskAt(0, task.taskId, WINDOWING_MODE_FREEFORM)
        wct.assertLaunchTask(task.taskId, WINDOWING_MODE_FREEFORM)
    }

    @Test
@@ -6240,6 +6239,61 @@ class DesktopTasksControllerTest(flags: FlagsParameterization) : ShellTestCase()
        assertThat(taskRepository.getNumberOfDesks(DEFAULT_DISPLAY)).isEqualTo(currentDeskCount + 1)
    }

    @Test
    @EnableFlags(
        Flags.FLAG_ENABLE_DESKTOP_WINDOWING_WALLPAPER_ACTIVITY,
        Flags.FLAG_ENABLE_DESKTOP_WALLPAPER_ACTIVITY_FOR_SYSTEM_USER,
    )
    fun startLaunchTransition_desktopNotShowing_movesWallpaperToFront() {
        val launchingTask = createFreeformTask()
        val wct = WindowContainerTransaction()
        wct.reorder(launchingTask.token, /* onTop= */ true)
        whenever(
                desktopMixedTransitionHandler.startLaunchTransition(
                    eq(TRANSIT_OPEN),
                    any(),
                    anyOrNull(),
                    anyOrNull(),
                    anyOrNull(),
                )
            )
            .thenReturn(Binder())

        controller.startLaunchTransition(TRANSIT_OPEN, wct, launchingTaskId = null)

        val latestWct = getLatestDesktopMixedTaskWct(type = TRANSIT_OPEN)
        val launchingTaskReorderIndex = latestWct.indexOfReorder(launchingTask, toTop = true)
        val wallpaperReorderIndex = latestWct.indexOfReorder(wallpaperToken, toTop = true)
        assertThat(launchingTaskReorderIndex).isNotEqualTo(-1)
        assertThat(wallpaperReorderIndex).isNotEqualTo(-1)
        assertThat(launchingTaskReorderIndex).isGreaterThan(wallpaperReorderIndex)
    }

    @Test
    @EnableFlags(
        Flags.FLAG_ENABLE_DESKTOP_WINDOWING_WALLPAPER_ACTIVITY,
        Flags.FLAG_ENABLE_DESKTOP_WALLPAPER_ACTIVITY_FOR_SYSTEM_USER,
    )
    fun startLaunchTransition_desktopShowing_doesNotReorderWallpaper() {
        val wct = WindowContainerTransaction()
        whenever(
                desktopMixedTransitionHandler.startLaunchTransition(
                    eq(TRANSIT_OPEN),
                    any(),
                    anyOrNull(),
                    anyOrNull(),
                    anyOrNull(),
                )
            )
            .thenReturn(Binder())

        setUpFreeformTask()
        controller.startLaunchTransition(TRANSIT_OPEN, wct, launchingTaskId = null)

        val latestWct = getLatestDesktopMixedTaskWct(type = TRANSIT_OPEN)
        assertNull(latestWct.hierarchyOps.find { op -> op.container == wallpaperToken.asBinder() })
    }

    private class RunOnStartTransitionCallback : ((IBinder) -> Unit) {
        var invocations = 0
            private set
@@ -6626,13 +6680,20 @@ private fun WindowContainerTransaction.assertWithoutHop(
}

private fun WindowContainerTransaction.indexOfReorder(
    task: RunningTaskInfo,
    token: WindowContainerToken,
    toTop: Boolean? = null,
): Int {
    val hop = hierarchyOps.singleOrNull(ReorderPredicate(task.token, toTop)) ?: return -1
    val hop = hierarchyOps.singleOrNull(ReorderPredicate(token, toTop)) ?: return -1
    return hierarchyOps.indexOf(hop)
}

private fun WindowContainerTransaction.indexOfReorder(
    task: RunningTaskInfo,
    toTop: Boolean? = null,
): Int {
    return indexOfReorder(task.token, toTop)
}

private class ReorderPredicate(val token: WindowContainerToken, val toTop: Boolean? = null) :
    ((WindowContainerTransaction.HierarchyOp) -> Boolean) {
    override fun invoke(hop: WindowContainerTransaction.HierarchyOp): Boolean =
@@ -6750,6 +6811,17 @@ private fun WindowContainerTransaction.assertPendingIntentAt(index: Int, intent:
    assertThat(op.pendingIntent?.intent?.categories).isEqualTo(intent.categories)
}

private fun WindowContainerTransaction.assertLaunchTask(taskId: Int, windowingMode: Int) {
    val keyLaunchWindowingMode = "android.activity.windowingMode"

    assertHop { hop ->
        hop.type == HIERARCHY_OP_TYPE_LAUNCH_TASK &&
            hop.launchOptions?.getInt(LAUNCH_KEY_TASK_ID) == taskId &&
            hop.launchOptions?.getInt(keyLaunchWindowingMode, WINDOWING_MODE_UNDEFINED) ==
                windowingMode
    }
}

private fun WindowContainerTransaction.assertLaunchTaskAt(
    index: Int,
    taskId: Int,