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

Commit 707587ed authored by Jorge Gil's avatar Jorge Gil
Browse files

Desks: Apply activation changes on user switch from Shell

Handle transition requests for user switches to deactivate desks of the
outgoing user and activate desks of the new user if applicable.

This also makes changes in DesksTransitionObserver: user-switches are
no longer an "independent" desk transition, so this flags off a lot of
the user-switch detection that was needed before.

Flag: com.android.window.flags.apply_desk_activation_on_user_switch
Bug: 420858253
Bug: 430988310
Fix: 415381304
Test: switch users:
- from empty desk to empty desk
- empty desk to non-empty desk (and viceversa)
- empty desk to Home (and viceversa)
- non-empty desk to Home (and viceversa)
verify tasks are restored as expected

Change-Id: I99a8a243e69d1a4c53606f72fcdc5e511722cbc1
parent c98ea903
Loading
Loading
Loading
Loading
+90 −17
Original line number Diff line number Diff line
@@ -767,6 +767,7 @@ class DesktopTasksController(
        removeWallpaperTask(wct, disconnectedDisplayId)
        removeHomeTask(wct, disconnectedDisplayId)
        userRepositories.forAllRepositories { desktopRepository ->
            val userId = desktopRepository.userId
            val deskIds = desktopRepository.getDeskIds(disconnectedDisplayId).toList()
            if (desktopModeSupportedOnDisplay) {
                // Desktop supported on display; reparent desks, focused desk on top.
@@ -774,12 +775,17 @@ class DesktopTasksController(
                    val deskTasks = desktopRepository.getActiveTaskIdsInDesk(deskId)
                    // Remove desk if it's empty.
                    if (deskTasks.isEmpty()) {
                        logD("onDisplayDisconnect: removing empty desk=$deskId")
                        desksOrganizer.removeDesk(wct, deskId, desktopRepository.userId)
                        logD(
                            "onDisplayDisconnect: removing empty desk=%d of user=%d",
                            deskId,
                            userId,
                        )
                        desksOrganizer.removeDesk(wct, deskId, userId)
                        runOnTransitStartSet.add { transition ->
                            desksTransitionObserver.addPendingTransition(
                                DeskTransition.RemoveDesk(
                                    token = transition,
                                    userId = userId,
                                    displayId = disconnectedDisplayId,
                                    deskId = deskId,
                                    tasks = emptySet(),
@@ -791,8 +797,10 @@ class DesktopTasksController(
                        }
                    } else {
                        logD(
                            "onDisplayDisconnect: reparenting desk=$deskId to " +
                                "display=$destinationDisplayId"
                            "onDisplayDisconnect: reparenting desk=%d to display=%d for user=%d",
                            deskId,
                            destinationDisplayId,
                            userId,
                        )
                        // Otherwise, reparent it to the destination display.
                        val toTop =
@@ -809,16 +817,17 @@ class DesktopTasksController(
                        runOnTransitStartSet.add { transition ->
                            desksTransitionObserver.addPendingTransition(
                                DeskTransition.ChangeDeskDisplay(
                                    transition,
                                    deskId,
                                    destinationDisplayId,
                                    token = transition,
                                    userId = userId,
                                    deskId = deskId,
                                    displayId = destinationDisplayId,
                                )
                            )
                        }
                        updateDesksActivationOnDisconnection(
                                disconnectedDisplayActiveDesk = deskId,
                                destinationDisplayId = destinationDisplayId,
                                userId = desktopRepository.userId,
                                userId = userId,
                                wct = wct,
                                toTop = toTop,
                            )
@@ -845,11 +854,12 @@ class DesktopTasksController(
                        )
                        destDisplayLayout?.densityDpi()?.let { wct.setDensityDpi(task.token, it) }
                    }
                    desksOrganizer.removeDesk(wct, deskId, desktopRepository.userId)
                    desksOrganizer.removeDesk(wct, deskId, userId)
                    runOnTransitStartSet.add { transition ->
                        desksTransitionObserver.addPendingTransition(
                            DeskTransition.RemoveDesk(
                                token = transition,
                                userId = userId,
                                displayId = disconnectedDisplayId,
                                deskId = deskId,
                                tasks = emptySet(),
@@ -859,7 +869,11 @@ class DesktopTasksController(
                            )
                        )
                        desksTransitionObserver.addPendingTransition(
                            DeskTransition.RemoveDisplay(transition, disconnectedDisplayId)
                            DeskTransition.RemoveDisplay(
                                token = transition,
                                userId = userId,
                                displayId = disconnectedDisplayId,
                            )
                        )
                    }
                }
@@ -980,6 +994,46 @@ class DesktopTasksController(
        }
    }

    private fun handleUserChangeTransitionRequest(
        transition: IBinder,
        request: TransitionRequestInfo,
    ): WindowContainerTransaction? {
        val userChange = request.userChange ?: return null
        val previousRepo = userRepositories.getProfile(userChange.previousUserId)
        val newRepo = userRepositories.getProfile(userChange.newUserId)
        val wct = WindowContainerTransaction()
        // Deactivate desks of old user.
        rootTaskDisplayAreaOrganizer.displayIds
            .toList()
            .mapNotNull { displayId -> previousRepo.getActiveDeskId(displayId) }
            .mapNotNull { deskId ->
                addDeskDeactivationChanges(
                    wct = wct,
                    deskId = deskId,
                    userId = userChange.previousUserId,
                    switchingUser = true,
                    exitReason = ExitReason.UNKNOWN_EXIT,
                )
            }
            .forEach { runOnTransitStart -> runOnTransitStart(transition) }
        // Activate desks of new user.
        rootTaskDisplayAreaOrganizer.displayIds
            .toList()
            .mapNotNull { displayId -> newRepo.getActiveDeskId(displayId) }
            .map { deskId ->
                addDeskActivationChanges(
                    deskId = deskId,
                    wct = wct,
                    userId = userChange.newUserId,
                    switchingUser = true,
                    enterReason = EnterReason.UNKNOWN_ENTER,
                )
            }
            .forEach { runOnTransitStart -> runOnTransitStart(transition) }

        return wct
    }

    /**
     * Handle desk operations when disconnecting a display and all desks on that display are moving
     * to a display that supports desks. The previously focused display will determine which desk
@@ -1011,9 +1065,10 @@ class DesktopTasksController(
                // The disconnected display's active desk was reparented to the back, ensure it is
                // no longer an active launch root.
                addDeskDeactivationChanges(
                    wct,
                    disconnectedDisplayActiveDesk,
                    ExitReason.DISPLAY_DISCONNECTED,
                    wct = wct,
                    deskId = disconnectedDisplayActiveDesk,
                    userId = userId,
                    exitReason = ExitReason.DISPLAY_DISCONNECTED,
                )
            }
        return runOnTransitStart
@@ -3051,7 +3106,12 @@ class DesktopTasksController(
                exitReason = exitReason,
            )
        } else {
            addDeskDeactivationChanges(wct, deskId, exitReason)
            addDeskDeactivationChanges(
                wct = wct,
                deskId = deskId,
                userId = userId,
                exitReason = exitReason,
            )
        }
    }

@@ -3101,8 +3161,7 @@ class DesktopTasksController(
            DesktopExperienceFlags.ENABLE_APPLY_DESK_ACTIVATION_ON_USER_SWITCH.isTrue &&
                userChange != null
        ) {
            // TODO: b/420858253 - deactivate the outgoing user's active desks and reactivate the
            //  active desks of the incoming user.
            return handleUserChangeTransitionRequest(transition, request)
        }
        // Check if we should skip handling this transition
        var reason = ""
@@ -4532,6 +4591,7 @@ class DesktopTasksController(
        //  without having to specify the value?
        addPendingLaunchTransition: Boolean = false,
        userId: Int,
        switchingUser: Boolean = false,
        displayId: Int = userRepositories.getProfile(userId).getDisplayForDesk(deskId),
        enterReason: EnterReason,
    ): RunOnTransitStart {
@@ -4608,12 +4668,19 @@ class DesktopTasksController(
        }
        val deactivatingDesk = repository.getActiveDeskId(displayId)?.takeIf { it != deskId }
        val deactivationRunnable =
            addDeskDeactivationChanges(wct, deactivatingDesk, ExitReason.RETURN_HOME_OR_OVERVIEW)
            addDeskDeactivationChanges(
                wct = wct,
                deskId = deactivatingDesk,
                userId = userId,
                switchingUser = switchingUser,
                ExitReason.RETURN_HOME_OR_OVERVIEW,
            )
        return { transition ->
            val activateDeskTransition =
                if (newTaskIdInFront != null) {
                    DeskTransition.ActivateDeskWithTask(
                        token = transition,
                        userId = userId,
                        displayId = displayId,
                        deskId = deskId,
                        enterTaskId = newTaskIdInFront,
@@ -4623,6 +4690,7 @@ class DesktopTasksController(
                } else {
                    DeskTransition.ActivateDesk(
                        token = transition,
                        userId = userId,
                        displayId = displayId,
                        deskId = deskId,
                        enterReason = enterReason,
@@ -4859,6 +4927,7 @@ class DesktopTasksController(
                desksTransitionObserver.addPendingTransition(
                    DeskTransition.RemoveDesk(
                        token = transition,
                        userId = userId,
                        displayId = displayId,
                        deskId = deskId,
                        tasks = tasksToRemove,
@@ -4878,6 +4947,8 @@ class DesktopTasksController(
    private fun addDeskDeactivationChanges(
        wct: WindowContainerTransaction,
        deskId: Int?,
        userId: Int,
        switchingUser: Boolean = false,
        exitReason: ExitReason,
    ): RunOnTransitStart? {
        if (!DesktopExperienceFlags.ENABLE_MULTIPLE_DESKTOPS_BACKEND.isTrue) return null
@@ -4887,7 +4958,9 @@ class DesktopTasksController(
            desksTransitionObserver.addPendingTransition(
                DeskTransition.DeactivateDesk(
                    token = transition,
                    userId = userId,
                    deskId = deskId,
                    switchingUser = switchingUser,
                    exitReason = exitReason,
                    runOnTransitEnd = { snapEventHandler.onDeskDeactivated(deskId) },
                )
+27 −7
Original line number Diff line number Diff line
@@ -22,6 +22,8 @@ import com.android.wm.shell.desktopmode.DesktopModeEventLogger
sealed interface DeskTransition {
    /** The transition token. */
    val token: IBinder
    /** The user associated with this transition. */
    val userId: Int

    /** Returns a copy of this desk transition with a new transition token. */
    fun copyWithToken(token: IBinder): DeskTransition
@@ -29,6 +31,7 @@ sealed interface DeskTransition {
    /** A transition to remove a desk and its tasks from a display. */
    data class RemoveDesk(
        override val token: IBinder,
        override val userId: Int,
        val displayId: Int,
        val deskId: Int,
        val tasks: Set<Int>,
@@ -37,6 +40,7 @@ sealed interface DeskTransition {
    ) : DeskTransition {
        constructor(
            token: IBinder,
            userId: Int,
            displayId: Int,
            deskId: Int,
            tasks: Set<Int>,
@@ -46,7 +50,7 @@ sealed interface DeskTransition {
            // after verifying that the call order before and after repository does not matter
            // for [DesktopDisplayEventHandler].
            runOnTransitEnd: (() -> Unit)?,
        ) : this(token, displayId, deskId, tasks, onDeskRemovedListener, exitReason) {
        ) : this(token, userId, displayId, deskId, tasks, onDeskRemovedListener, exitReason) {
            this.runOnTransitEnd = runOnTransitEnd
        }

@@ -58,17 +62,19 @@ sealed interface DeskTransition {
    /** A transition to activate a desk in its display. */
    data class ActivateDesk(
        override val token: IBinder,
        override val userId: Int,
        val displayId: Int,
        val deskId: Int,
        val enterReason: DesktopModeEventLogger.Companion.EnterReason,
    ) : DeskTransition {
        constructor(
            token: IBinder,
            userId: Int,
            displayId: Int,
            deskId: Int,
            enterReason: DesktopModeEventLogger.Companion.EnterReason,
            runOnTransitEnd: (() -> Unit)?,
        ) : this(token, displayId, deskId, enterReason) {
        ) : this(token, userId, displayId, deskId, enterReason) {
            this.runOnTransitEnd = runOnTransitEnd
        }

@@ -80,6 +86,7 @@ sealed interface DeskTransition {
    /** A transition to activate a desk by moving an outside task to it. */
    data class ActivateDeskWithTask(
        override val token: IBinder,
        override val userId: Int,
        val displayId: Int,
        val deskId: Int,
        val enterTaskId: Int,
@@ -87,12 +94,13 @@ sealed interface DeskTransition {
    ) : DeskTransition {
        constructor(
            token: IBinder,
            userId: Int,
            displayId: Int,
            deskId: Int,
            enterTaskId: Int,
            enterReason: DesktopModeEventLogger.Companion.EnterReason,
            runOnTransitEnd: (() -> Unit)?,
        ) : this(token, displayId, deskId, enterTaskId, enterReason) {
        ) : this(token, userId, displayId, deskId, enterTaskId, enterReason) {
            this.runOnTransitEnd = runOnTransitEnd
        }

@@ -104,15 +112,19 @@ sealed interface DeskTransition {
    /** A transition to deactivate a desk. */
    data class DeactivateDesk(
        override val token: IBinder,
        override val userId: Int,
        val deskId: Int,
        val switchingUser: Boolean,
        val exitReason: DesktopModeEventLogger.Companion.ExitReason,
    ) : DeskTransition {
        constructor(
            token: IBinder,
            userId: Int,
            deskId: Int,
            switchingUser: Boolean,
            exitReason: DesktopModeEventLogger.Companion.ExitReason,
            runOnTransitEnd: (() -> Unit)?,
        ) : this(token, deskId, exitReason) {
        ) : this(token, userId, deskId, switchingUser, exitReason) {
            this.runOnTransitEnd = runOnTransitEnd
        }

@@ -122,13 +134,21 @@ sealed interface DeskTransition {
    }

    /** A transition to move a desk to a new display */
    data class ChangeDeskDisplay(override val token: IBinder, val deskId: Int, val displayId: Int) :
        DeskTransition {
    data class ChangeDeskDisplay(
        override val token: IBinder,
        override val userId: Int,
        val deskId: Int,
        val displayId: Int,
    ) : DeskTransition {
        override fun copyWithToken(token: IBinder): DeskTransition = copy(token)
    }

    /** A transition to remove a display and any desks on it. */
    data class RemoveDisplay(override val token: IBinder, val displayId: Int) : DeskTransition {
    data class RemoveDisplay(
        override val token: IBinder,
        override val userId: Int,
        val displayId: Int,
    ) : DeskTransition {
        override fun copyWithToken(token: IBinder): DeskTransition = copy(token)
    }
}
+65 −42

File changed.

Preview size limit exceeded, changes collapsed.

+124 −2
Original line number Diff line number Diff line
@@ -219,6 +219,7 @@ import org.mockito.kotlin.argThat
import org.mockito.kotlin.argumentCaptor
import org.mockito.kotlin.atLeastOnce
import org.mockito.kotlin.eq
import org.mockito.kotlin.inOrder
import org.mockito.kotlin.verifyNoInteractions
import org.mockito.kotlin.whenever
import org.mockito.quality.Strictness
@@ -319,6 +320,7 @@ class DesktopTasksControllerTest(flags: FlagsParameterization) : ShellTestCase()

    private val DEFAULT_USER_ID = 0
    private val DEFAULT_USER_WORK_PROFILE_ID = 100
    private val SECONDARY_USER_ID = 11

    private val SECONDARY_DISPLAY_ID = 1
    private val DISPLAY_DIMENSION_SHORT = 1600
@@ -448,7 +450,8 @@ class DesktopTasksControllerTest(flags: FlagsParameterization) : ShellTestCase()
        whenever(userProfileContexts[anyInt()]).thenReturn(context)
        whenever(userProfileContexts.getOrCreate(anyInt())).thenReturn(context)
        whenever(freeformTaskTransitionStarter.startPipTransition(any())).thenReturn(Binder())
        whenever(rootTaskDisplayAreaOrganizer.displayIds).thenReturn(intArrayOf(DEFAULT_DISPLAY))
        whenever(rootTaskDisplayAreaOrganizer.displayIds)
            .thenReturn(intArrayOf(DEFAULT_DISPLAY, SECONDARY_DISPLAY_ID))

        controller = createController()
        controller.setSplitScreenController(splitScreenController)
@@ -2071,6 +2074,7 @@ class DesktopTasksControllerTest(flags: FlagsParameterization) : ShellTestCase()
    fun moveToDesktop_displayNotSupported_doesNothing() {
        val spyController = spy(controller)
        desktopState.overrideDesktopModeSupportPerDisplay[DEFAULT_DISPLAY] = false
        desktopState.overrideDesktopModeSupportPerDisplay[SECONDARY_DISPLAY_ID] = false
        val task = setUpFullscreenTask()
        spyController.moveTaskToDefaultDeskAndActivate(task.taskId, transitionSource = UNKNOWN)
        verify(spyController, times(0))
@@ -4183,6 +4187,7 @@ class DesktopTasksControllerTest(flags: FlagsParameterization) : ShellTestCase()
            .addPendingTransition(
                DeskTransition.ActivateDeskWithTask(
                    token = transition,
                    userId = taskRepository.userId,
                    displayId = SECOND_DISPLAY,
                    deskId = targetDeskId,
                    enterTaskId = task.taskId,
@@ -4221,7 +4226,9 @@ class DesktopTasksControllerTest(flags: FlagsParameterization) : ShellTestCase()
            .addPendingTransition(
                DeskTransition.DeactivateDesk(
                    token = transition,
                    userId = taskRepository.userId,
                    deskId = sourceDeskId,
                    switchingUser = false,
                    exitReason = ExitReason.TASK_MOVED_FROM_DESK,
                )
            )
@@ -4652,7 +4659,9 @@ class DesktopTasksControllerTest(flags: FlagsParameterization) : ShellTestCase()
            .addPendingTransition(
                DeskTransition.DeactivateDesk(
                    transition,
                    userId = taskRepository.userId,
                    deskId = 0,
                    switchingUser = false,
                    exitReason = ExitReason.TASK_FINISHED,
                )
            )
@@ -4780,7 +4789,9 @@ class DesktopTasksControllerTest(flags: FlagsParameterization) : ShellTestCase()
            .addPendingTransition(
                DeskTransition.DeactivateDesk(
                    token = transition,
                    userId = taskRepository.userId,
                    deskId = 0,
                    switchingUser = false,
                    exitReason = ExitReason.TASK_MINIMIZED,
                )
            )
@@ -4917,7 +4928,9 @@ class DesktopTasksControllerTest(flags: FlagsParameterization) : ShellTestCase()
            .addPendingTransition(
                DeskTransition.DeactivateDesk(
                    transition,
                    userId = taskRepository.userId,
                    deskId,
                    switchingUser = false,
                    exitReason = ExitReason.TASK_MINIMIZED,
                )
            )
@@ -5333,7 +5346,9 @@ class DesktopTasksControllerTest(flags: FlagsParameterization) : ShellTestCase()
            .addPendingTransition(
                DeskTransition.DeactivateDesk(
                    transition,
                    userId = taskRepository.userId,
                    deskId = 0,
                    switchingUser = false,
                    exitReason = ExitReason.FULLSCREEN_LAUNCH,
                )
            )
@@ -5729,6 +5744,7 @@ class DesktopTasksControllerTest(flags: FlagsParameterization) : ShellTestCase()
            .addPendingTransition(
                DeskTransition.ActivateDeskWithTask(
                    token = transition,
                    userId = taskRepository.userId,
                    displayId = DEFAULT_DISPLAY,
                    deskId = deskId,
                    enterTaskId = fullscreenTask.taskId,
@@ -6308,7 +6324,9 @@ class DesktopTasksControllerTest(flags: FlagsParameterization) : ShellTestCase()
        desksTransitionsObserver.addPendingTransition(
            DeskTransition.DeactivateDesk(
                transition,
                userId = taskRepository.userId,
                deskId = 0,
                switchingUser = false,
                exitReason = ExitReason.UNKNOWN_EXIT,
            )
        )
@@ -6551,7 +6569,9 @@ class DesktopTasksControllerTest(flags: FlagsParameterization) : ShellTestCase()
            .addPendingTransition(
                DeskTransition.DeactivateDesk(
                    transition,
                    userId = taskRepository.userId,
                    deskId,
                    switchingUser = false,
                    exitReason = ExitReason.FULLSCREEN_LAUNCH,
                )
            )
@@ -7150,7 +7170,9 @@ class DesktopTasksControllerTest(flags: FlagsParameterization) : ShellTestCase()
            .addPendingTransition(
                DeskTransition.DeactivateDesk(
                    token = transition,
                    userId = taskRepository.userId,
                    deskId = 0,
                    switchingUser = false,
                    exitReason = ExitReason.TASK_FINISHED,
                )
            )
@@ -7354,7 +7376,9 @@ class DesktopTasksControllerTest(flags: FlagsParameterization) : ShellTestCase()
            .addPendingTransition(
                DeskTransition.DeactivateDesk(
                    token = transition,
                    userId = taskRepository.userId,
                    deskId = 0,
                    switchingUser = false,
                    exitReason = ExitReason.TASK_FINISHED,
                )
            )
@@ -10448,7 +10472,9 @@ class DesktopTasksControllerTest(flags: FlagsParameterization) : ShellTestCase()
            .addPendingTransition(
                DeskTransition.DeactivateDesk(
                    token = transition,
                    userId = taskRepository.userId,
                    deskId = 0,
                    switchingUser = false,
                    exitReason = ExitReason.RETURN_HOME_OR_OVERVIEW,
                )
            )
@@ -11108,6 +11134,7 @@ class DesktopTasksControllerTest(flags: FlagsParameterization) : ShellTestCase()
            .addPendingTransition(
                DeskTransition.ActivateDesk(
                    token = transition,
                    userId = taskRepository.userId,
                    displayId = DEFAULT_DISPLAY,
                    deskId = inactiveDesk,
                    enterReason = EnterReason.APP_FREEFORM_INTENT,
@@ -11251,7 +11278,9 @@ class DesktopTasksControllerTest(flags: FlagsParameterization) : ShellTestCase()
            .addPendingTransition(
                DeskTransition.DeactivateDesk(
                    transition,
                    userId = taskRepository.userId,
                    deskId,
                    switchingUser = false,
                    exitReason = ExitReason.RETURN_HOME_OR_OVERVIEW,
                )
            )
@@ -11532,6 +11561,96 @@ class DesktopTasksControllerTest(flags: FlagsParameterization) : ShellTestCase()
        verify(desksOrganizer).activateDesk(wct, targetDeskId)
    }

    @Test
    @EnableFlags(
        Flags.FLAG_ENABLE_MULTIPLE_DESKTOPS_BACKEND,
        Flags.FLAG_APPLY_DESK_ACTIVATION_ON_USER_SWITCH,
    )
    fun handleRequest_userSwitch() {
        val previousUser = DEFAULT_USER_ID
        val newUser = SECONDARY_USER_ID
        userRepositories.getProfile(DEFAULT_USER_ID).apply {
            addDesk(displayId = DEFAULT_DISPLAY, deskId = 5)
            setActiveDesk(displayId = DEFAULT_DISPLAY, deskId = 5)
        }
        userRepositories.getProfile(SECONDARY_USER_ID).apply {
            addDesk(displayId = DEFAULT_DISPLAY, deskId = 110005)
            setActiveDesk(displayId = DEFAULT_DISPLAY, deskId = 110005)
        }

        val wct =
            controller.handleRequest(
                Binder(),
                createTransition(
                    task = null,
                    userChange =
                        TransitionRequestInfo.UserChange(
                            /* previousUserId = */ previousUser,
                            /* newUserId = */ newUser,
                        ),
                ),
            )

        assertNotNull(wct, "should handle request")
        val inOrder = inOrder(desksOrganizer)
        inOrder
            .verify(desksOrganizer)
            .deactivateDesk(wct = eq(wct), deskId = eq(5), skipReorder = any())
        inOrder
            .verify(desksOrganizer)
            .activateDesk(wct = eq(wct), deskId = eq(110005), skipReorder = any())
    }

    @Test
    @EnableFlags(
        Flags.FLAG_ENABLE_MULTIPLE_DESKTOPS_BACKEND,
        Flags.FLAG_APPLY_DESK_ACTIVATION_ON_USER_SWITCH,
    )
    fun handleRequest_userSwitch_multipleDisplays() {
        val previousUser = DEFAULT_USER_ID
        val newUser = SECONDARY_USER_ID
        userRepositories.getProfile(DEFAULT_USER_ID).apply {
            addDesk(displayId = DEFAULT_DISPLAY, deskId = 5)
            setActiveDesk(displayId = DEFAULT_DISPLAY, deskId = 5)
            addDesk(displayId = SECONDARY_DISPLAY_ID, deskId = 6)
            setActiveDesk(displayId = SECONDARY_DISPLAY_ID, deskId = 6)
        }
        userRepositories.getProfile(SECONDARY_USER_ID).apply {
            addDesk(displayId = DEFAULT_DISPLAY, deskId = 110005)
            setActiveDesk(displayId = DEFAULT_DISPLAY, deskId = 110005)
            addDesk(displayId = SECONDARY_DISPLAY_ID, deskId = 110006)
            setActiveDesk(displayId = SECONDARY_DISPLAY_ID, deskId = 110006)
        }

        val wct =
            controller.handleRequest(
                Binder(),
                createTransition(
                    task = null,
                    userChange =
                        TransitionRequestInfo.UserChange(
                            /* previousUserId = */ previousUser,
                            /* newUserId = */ newUser,
                        ),
                ),
            )

        assertNotNull(wct, "should handle request")
        val inOrder = inOrder(desksOrganizer)
        inOrder
            .verify(desksOrganizer)
            .deactivateDesk(wct = eq(wct), deskId = eq(5), skipReorder = any())
        inOrder
            .verify(desksOrganizer)
            .deactivateDesk(wct = eq(wct), deskId = eq(6), skipReorder = any())
        inOrder
            .verify(desksOrganizer)
            .activateDesk(wct = eq(wct), deskId = eq(110005), skipReorder = any())
        inOrder
            .verify(desksOrganizer)
            .activateDesk(wct = eq(wct), deskId = eq(110006), skipReorder = any())
    }

    private class RunOnStartTransitionCallback : ((IBinder) -> Unit) {
        var invocations = 0
            private set
@@ -11923,8 +12042,11 @@ class DesktopTasksControllerTest(flags: FlagsParameterization) : ShellTestCase()
    private fun createTransition(
        task: RunningTaskInfo?,
        @WindowManager.TransitionType type: Int = TRANSIT_OPEN,
        userChange: TransitionRequestInfo.UserChange? = null,
    ): TransitionRequestInfo {
        return TransitionRequestInfo(type, task, /* remoteTransition= */ null)
        return TransitionRequestInfo(type, task, /* remoteTransition= */ null).apply {
            userChange?.let { setUserChange(it) }
        }
    }

    private fun createTaskMoveTransition(
+120 −15

File changed.

Preview size limit exceeded, changes collapsed.