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

Commit 21f6c3bb authored by Jorge Gil's avatar Jorge Gil
Browse files

Desks: Use supported display when moving task to front

When moving a background desktop task to front and the desk it belonged
to prior to being in the background has already been removed, it is
possible that the display id used to find a default desk for it was a
display that does not support desktop mode.

Instead, try to find a suitable display in this order:
1. The display the task is associated with (via its TaskInfo)
2. The display in focus
3. Any display that supports desktop
4. DEFAULT_DISPLAY

It's still possible that (4) does not support desktop, but that is left
to callsites to handle as an error.

Bug: 417944041
Flag: EXEMPT bug fix
Test: Open Gmail in CD, use adb command to remove its desk and then
moveTaskToFront

Change-Id: I0009aa1b77c12403beef38b8626ea26fec047dea
parent 038937b1
Loading
Loading
Loading
Loading
+42 −11
Original line number Diff line number Diff line
@@ -797,13 +797,34 @@ class DesktopTasksController(
        return runOnTransitStart
    }

    private fun getDisplayIdForTaskOrDefault(task: TaskInfo): Int {
        return when {
            task.displayId != INVALID_DISPLAY -> task.displayId
            focusTransitionObserver.globallyFocusedDisplayId != INVALID_DISPLAY ->
                focusTransitionObserver.globallyFocusedDisplayId
            else -> DEFAULT_DISPLAY
    private fun getDisplayIdForTaskOrDefault(task: TaskInfo?): Int {
        // First, try to get the display already associated with the task.
        if (
            task != null &&
                task.displayId != INVALID_DISPLAY &&
                desktopState.isDesktopModeSupportedOnDisplay(displayId = task.displayId)
        ) {
            return task.displayId
        }
        // Second, try to use the globally focused display.
        val globallyFocusedDisplayId = focusTransitionObserver.globallyFocusedDisplayId
        if (
            globallyFocusedDisplayId != INVALID_DISPLAY &&
                desktopState.isDesktopModeSupportedOnDisplay(displayId = globallyFocusedDisplayId)
        ) {
            return globallyFocusedDisplayId
        }
        // Fallback to any display that supports desktop.
        val supportedDisplayId =
            rootTaskDisplayAreaOrganizer.displayIds.firstOrNull { displayId ->
                desktopState.isDesktopModeSupportedOnDisplay(displayId)
            }
        if (supportedDisplayId != null) {
            return supportedDisplayId
        }
        // Use the default display as the last option even if it does not support desktop. Callers
        // should handle this case.
        return DEFAULT_DISPLAY
    }

    /** Moves task to desktop mode if task is running, else launches it in desktop mode. */
@@ -1466,13 +1487,23 @@ class DesktopTasksController(
        remoteTransition: RemoteTransition?,
        unminimizeReason: UnminimizeReason,
    ) {
        logV("moveBackgroundTaskToFront taskId=%s", taskId)
        logV("moveBackgroundTaskToFront taskId=%s unminimizeReason=%s", taskId, unminimizeReason)
        val wct = WindowContainerTransaction()

        val deskIdForTask = taskRepository.getDeskIdForTask(taskId)
        val deskId =
            taskRepository.getDeskIdForTask(taskId)
                ?: getOrCreateDefaultDeskId(DEFAULT_DISPLAY)
                ?: return
            if (deskIdForTask != null) {
                deskIdForTask
            } else {
                val task = recentTasksController?.findTaskInBackground(taskId)
                val displayId = getDisplayIdForTaskOrDefault(task)
                logV(
                    "background taskId=%s did not have desk associated, " +
                        "using default desk of displayId=%d",
                    taskId,
                    displayId,
                )
                getOrCreateDefaultDeskId(displayId) ?: return
            }
        val displayId =
            if (ENABLE_BUG_FIXES_FOR_SECONDARY_DISPLAY.isTrue)
                taskRepository.getDisplayForDesk(deskId)
+110 −0
Original line number Diff line number Diff line
@@ -417,6 +417,7 @@ 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))

        controller = createController()
        controller.setSplitScreenController(splitScreenController)
@@ -3195,6 +3196,115 @@ class DesktopTasksControllerTest(flags: FlagsParameterization) : ShellTestCase()
        wct.assertLaunchTaskOnDisplay(SECOND_DISPLAY)
    }

    @Test
    @EnableFlags(
        Flags.FLAG_ENABLE_MULTIPLE_DESKTOPS_BACKEND,
        Flags.FLAG_ENABLE_BUG_FIXES_FOR_SECONDARY_DISPLAY,
    )
    fun moveTaskToFront_backgroundTask_notInDesk_launchesInAssociatedDisplay() {
        val deskId = 2
        val taskId = 1
        val task = createRecentTaskInfo(taskId, displayId = SECOND_DISPLAY)
        taskRepository.addDesk(displayId = SECOND_DISPLAY, deskId = deskId)
        whenever(shellTaskOrganizer.getRunningTaskInfo(taskId)).thenReturn(null)
        whenever(recentTasksController.findTaskInBackground(taskId)).thenReturn(task)
        whenever(
                desktopMixedTransitionHandler.startLaunchTransition(
                    eq(TRANSIT_OPEN),
                    any(),
                    anyOrNull(),
                    anyOrNull(),
                    anyOrNull(),
                    anyOrNull(),
                    anyOrNull(),
                )
            )
            .thenReturn(Binder())
        desktopState.overrideDesktopModeSupportPerDisplay[SECOND_DISPLAY] = true

        controller.moveTaskToFront(task.taskId, unminimizeReason = UnminimizeReason.UNKNOWN)

        val wct = getLatestDesktopMixedTaskWct(type = TRANSIT_OPEN)
        wct.assertLaunchTaskOnDisplay(SECOND_DISPLAY)
    }

    @Test
    @EnableFlags(
        Flags.FLAG_ENABLE_MULTIPLE_DESKTOPS_BACKEND,
        Flags.FLAG_ENABLE_BUG_FIXES_FOR_SECONDARY_DISPLAY,
    )
    fun moveTaskToFront_backgroundTask_notInDesk_unsupportedAssociatedDisplay_launchesInFocused() {
        val focusedDisplayId = 10
        val deskId = 2
        val taskId = 1
        val task = createRecentTaskInfo(taskId, displayId = SECOND_DISPLAY)
        taskRepository.addDesk(displayId = SECOND_DISPLAY, deskId = deskId)
        taskRepository.addDesk(displayId = focusedDisplayId, deskId = focusedDisplayId)
        whenever(shellTaskOrganizer.getRunningTaskInfo(taskId)).thenReturn(null)
        whenever(recentTasksController.findTaskInBackground(taskId)).thenReturn(task)
        whenever(focusTransitionObserver.globallyFocusedDisplayId).thenReturn(focusedDisplayId)
        whenever(
                desktopMixedTransitionHandler.startLaunchTransition(
                    eq(TRANSIT_OPEN),
                    any(),
                    anyOrNull(),
                    anyOrNull(),
                    anyOrNull(),
                    anyOrNull(),
                    anyOrNull(),
                )
            )
            .thenReturn(Binder())
        desktopState.overrideDesktopModeSupportPerDisplay[SECOND_DISPLAY] = false
        desktopState.overrideDesktopModeSupportPerDisplay[focusedDisplayId] = true

        controller.moveTaskToFront(task.taskId, unminimizeReason = UnminimizeReason.UNKNOWN)

        val wct = getLatestDesktopMixedTaskWct(type = TRANSIT_OPEN)
        wct.assertLaunchTaskOnDisplay(focusedDisplayId)
    }

    @Test
    @EnableFlags(
        Flags.FLAG_ENABLE_MULTIPLE_DESKTOPS_BACKEND,
        Flags.FLAG_ENABLE_BUG_FIXES_FOR_SECONDARY_DISPLAY,
    )
    fun moveTaskToFront_backgroundTask_notInDesk_unsupportedAssociatedAndFocusedDisplay_launchesInSupported() {
        val supportedDisplayId = 11
        val focusedDisplayId = 10
        val deskId = 2
        val taskId = 1
        val task = createRecentTaskInfo(taskId, displayId = SECOND_DISPLAY)
        taskRepository.addDesk(displayId = SECOND_DISPLAY, deskId = deskId)
        taskRepository.addDesk(displayId = focusedDisplayId, deskId = focusedDisplayId)
        taskRepository.addDesk(displayId = supportedDisplayId, deskId = supportedDisplayId)
        whenever(shellTaskOrganizer.getRunningTaskInfo(taskId)).thenReturn(null)
        whenever(recentTasksController.findTaskInBackground(taskId)).thenReturn(task)
        whenever(focusTransitionObserver.globallyFocusedDisplayId).thenReturn(focusedDisplayId)
        whenever(rootTaskDisplayAreaOrganizer.displayIds)
            .thenReturn(intArrayOf(SECOND_DISPLAY, focusedDisplayId, supportedDisplayId))
        whenever(
                desktopMixedTransitionHandler.startLaunchTransition(
                    eq(TRANSIT_OPEN),
                    any(),
                    anyOrNull(),
                    anyOrNull(),
                    anyOrNull(),
                    anyOrNull(),
                    anyOrNull(),
                )
            )
            .thenReturn(Binder())
        desktopState.overrideDesktopModeSupportPerDisplay[SECOND_DISPLAY] = false
        desktopState.overrideDesktopModeSupportPerDisplay[focusedDisplayId] = false
        desktopState.overrideDesktopModeSupportPerDisplay[supportedDisplayId] = true

        controller.moveTaskToFront(task.taskId, unminimizeReason = UnminimizeReason.UNKNOWN)

        val wct = getLatestDesktopMixedTaskWct(type = TRANSIT_OPEN)
        wct.assertLaunchTaskOnDisplay(supportedDisplayId)
    }

    @Test
    @DisableFlags(
        Flags.FLAG_ENABLE_MULTIPLE_DESKTOPS_BACKEND,