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

Commit b0ed62e4 authored by Jorge Gil's avatar Jorge Gil
Browse files

Desks: Incompatible Tasks (1/2) - Merge isDesktopModeShowing()/isAnyDeskActive()

isDesktopModeShowing() is the same as isAnyDeskActive() but with extra
considerations for top-transparent-fullscreen tasks. This extra
information is available in the repository, so it can be made part of
isAnyDeskActive() there.

For multiple desks, top-transparent-fullscreen checks aren't needed
anymore because a desk's active state is not tied to freeform task
visibility or top-transparent-fullscreen task existence, and is instead
set/unset explicitly.

Flag: com.android.window.flags.enable_multiple_desktops_backend
Bug: 398295550
Test: launch incompatible tasks in desktop, verify they remain
fullscreen and activate/deactivate the desktop based on transparency

Change-Id: I49fd8edc2c03242ce80b3cfcc140b93d3438708b
parent d9a023d1
Loading
Loading
Loading
Loading
+10 −1
Original line number Diff line number Diff line
@@ -805,7 +805,16 @@ class DesktopRepository(
                logE("Could not find default desk for display: $displayId")
                return false
            }
            return desk.visibleTasks.isNotEmpty()
            val hasVisibleTasks = desk.visibleTasks.isNotEmpty()
            val hasTopTransparentFullscreenTask =
                getTopTransparentFullscreenTaskId(displayId) != null
            if (
                DesktopModeFlags.INCLUDE_TOP_TRANSPARENT_FULLSCREEN_TASK_IN_DESKTOP_HEURISTIC
                    .isTrue && DesktopModeFlags.ENABLE_DESKTOP_WINDOWING_MODALS_POLICY.isTrue
            ) {
                return hasVisibleTasks || hasTopTransparentFullscreenTask
            }
            return hasVisibleTasks
        }
        return desktopData.getActiveDesk(displayId) != null
    }
+8 −36
Original line number Diff line number Diff line
@@ -367,34 +367,6 @@ class DesktopTasksController(
    /** Returns whether the given display has an active desk. */
    fun isAnyDeskActive(displayId: Int): Boolean = taskRepository.isAnyDeskActive(displayId)

    /**
     * Returns true if any freeform tasks are visible or if a transparent fullscreen task exists on
     * top in Desktop Mode.
     *
     * TODO: b/362720497 - consolidate with [isAnyDeskActive].
     *     - top-transparent-fullscreen case: should not be needed if we allow it to launch inside
     *       the desk in fullscreen instead of force-exiting desktop and having to trick this method
     *       into thinking it is in desktop mode when a task in this state exists.
     */
    fun isDesktopModeShowing(displayId: Int): Boolean {
        val hasVisibleTasks = taskRepository.isAnyDeskActive(displayId)
        val hasTopTransparentFullscreenTask =
            taskRepository.getTopTransparentFullscreenTaskId(displayId) != null
        if (
            DesktopModeFlags.INCLUDE_TOP_TRANSPARENT_FULLSCREEN_TASK_IN_DESKTOP_HEURISTIC
                .isTrue() && DesktopModeFlags.ENABLE_DESKTOP_WINDOWING_MODALS_POLICY.isTrue()
        ) {
            logV(
                "isDesktopModeShowing: hasVisibleTasks=%s hasTopTransparentFullscreenTask=%s",
                hasVisibleTasks,
                hasTopTransparentFullscreenTask,
            )
            return hasVisibleTasks || hasTopTransparentFullscreenTask
        }
        logV("isDesktopModeShowing: hasVisibleTasks=%s", hasVisibleTasks)
        return hasVisibleTasks
    }

    /** Moves focused task to desktop mode for given [displayId]. */
    fun moveFocusedTaskToDesktop(displayId: Int, transitionSource: DesktopModeTransitionSource) {
        val allFocusedTasks = getAllFocusedTasks(displayId)
@@ -1150,7 +1122,7 @@ class DesktopTasksController(
                DesktopExperienceFlags.ENABLE_MULTIPLE_DESKTOPS_BACKEND.isTrue ->
                    !taskRepository.isDeskActive(deskId)
                DesktopExperienceFlags.ENABLE_DISPLAY_WINDOWING_MODE_SWITCHING.isTrue -> {
                    !isDesktopModeShowing(displayId)
                    !isAnyDeskActive(displayId)
                }
                else -> false
            }
@@ -2103,7 +2075,7 @@ class DesktopTasksController(
        // Only immersive mixed transition are currently supported.
        if (!DesktopModeFlags.ENABLE_FULLY_IMMERSIVE_IN_DESKTOP.isTrue) return false
        val triggerTask = info.triggerTask ?: return false
        if (!isDesktopModeShowing(triggerTask.displayId)) {
        if (!isAnyDeskActive(triggerTask.displayId)) {
            return false
        }
        if (!TransitionUtil.isOpeningType(info.type)) {
@@ -2449,7 +2421,7 @@ class DesktopTasksController(
                val runOnTransitStart: RunOnTransitStart? =
                    if (
                        task.baseIntent.flags.and(Intent.FLAG_ACTIVITY_TASK_ON_HOME) != 0 ||
                            !isDesktopModeShowing(task.displayId)
                            !isAnyDeskActive(task.displayId)
                    ) {
                        // In some launches home task is moved behind new task being launched. Make
                        // sure that's not the case for launches in desktop. Also, if this launch is
@@ -2512,10 +2484,10 @@ class DesktopTasksController(
    }

    private fun shouldFreeformTaskLaunchSwitchToFullscreen(task: RunningTaskInfo): Boolean =
        !isDesktopModeShowing(task.displayId)
        !isAnyDeskActive(task.displayId)

    private fun shouldFullscreenTaskLaunchSwitchToDesktop(task: RunningTaskInfo): Boolean =
        isDesktopModeShowing(task.displayId) || forceEnterDesktop(task.displayId)
        isAnyDeskActive(task.displayId) || forceEnterDesktop(task.displayId)

    /**
     * If a task is not compatible with desktop mode freeform, it should always be launched in
@@ -2526,7 +2498,7 @@ class DesktopTasksController(
        transition: IBinder,
    ): WindowContainerTransaction? {
        logV("handleIncompatibleTaskLaunch")
        if (!isDesktopModeShowing(task.displayId) && !forceEnterDesktop(task.displayId)) return null
        if (!isAnyDeskActive(task.displayId) && !forceEnterDesktop(task.displayId)) return null
        // Only update task repository for transparent task.
        if (
            DesktopModeFlags.INCLUDE_TOP_TRANSPARENT_FULLSCREEN_TASK_IN_DESKTOP_HEURISTIC
@@ -2563,7 +2535,7 @@ class DesktopTasksController(
        requestType: Int,
    ): WindowContainerTransaction? {
        logV("handleTaskClosing")
        if (!isDesktopModeShowing(task.displayId)) return null
        if (!isAnyDeskActive(task.displayId)) return null
        val deskId = taskRepository.getDeskIdForTask(task.taskId)
        if (deskId == null && DesktopExperienceFlags.ENABLE_MULTIPLE_DESKTOPS_BACKEND.isTrue) {
            return null
@@ -3478,7 +3450,7 @@ class DesktopTasksController(
        onFinishCallback: Consumer<Boolean>,
    ): Boolean {
        // TODO(b/320797628): Pass through which display we are dropping onto
        if (!isDesktopModeShowing(DEFAULT_DISPLAY)) {
        if (!isAnyDeskActive(DEFAULT_DISPLAY)) {
            // Not currently in desktop mode, ignore the drop
            return false
        }
+1 −1
Original line number Diff line number Diff line
@@ -2882,7 +2882,7 @@ public class StageCoordinator implements SplitLayout.SplitLayoutHandler,
        final boolean isOpening = isOpeningType(type);
        final boolean inFullscreen = triggerTask.getWindowingMode() == WINDOWING_MODE_FULLSCREEN;
        final boolean inDesktopMode = mDesktopTasksController.isPresent()
                && mDesktopTasksController.get().isDesktopModeShowing(mDisplayId);
                && mDesktopTasksController.get().isAnyDeskActive(mDisplayId);
        final boolean isLaunchingDesktopTask = isOpening && DesktopModeStatus.canEnterDesktopMode(
                mContext) && triggerTask.getWindowingMode() == WINDOWING_MODE_FREEFORM;
        final StageTaskListener stage = getStageOfTask(triggerTask);
+11 −58
Original line number Diff line number Diff line
@@ -639,38 +639,24 @@ class DesktopTasksControllerTest(flags: FlagsParameterization) : ShellTestCase()

    @Test
    @DisableFlags(Flags.FLAG_ENABLE_MULTIPLE_DESKTOPS_BACKEND)
    fun isDesktopModeShowing_noTasks_returnsFalse() {
        assertThat(controller.isDesktopModeShowing(displayId = 0)).isFalse()
    }

    @Test
    @DisableFlags(Flags.FLAG_ENABLE_MULTIPLE_DESKTOPS_BACKEND)
    fun isDesktopModeShowing_noTasksVisible_returnsFalse() {
    fun isAnyDeskActive_noTasksVisible_returnsFalse() {
        val task1 = setUpFreeformTask()
        val task2 = setUpFreeformTask()
        markTaskHidden(task1)
        markTaskHidden(task2)

        assertThat(controller.isDesktopModeShowing(displayId = 0)).isFalse()
    }

    @Test
    @EnableFlags(Flags.FLAG_ENABLE_MULTIPLE_DESKTOPS_BACKEND)
    fun isDesktopModeShowing_noActiveDesk_returnsFalse() {
        taskRepository.setDeskInactive(deskId = 0)

        assertThat(controller.isDesktopModeShowing(displayId = 0)).isFalse()
        assertThat(controller.isAnyDeskActive(displayId = 0)).isFalse()
    }

    @Test
    @DisableFlags(Flags.FLAG_ENABLE_MULTIPLE_DESKTOPS_BACKEND)
    fun isDesktopModeShowing_tasksActiveAndVisible_returnsTrue() {
    fun isAnyDeskActive_tasksActiveAndVisible_returnsTrue() {
        val task1 = setUpFreeformTask()
        val task2 = setUpFreeformTask()
        markTaskVisible(task1)
        markTaskHidden(task2)

        assertThat(controller.isDesktopModeShowing(displayId = 0)).isTrue()
        assertThat(controller.isAnyDeskActive(displayId = 0)).isTrue()
    }

    @Test
@@ -679,25 +665,11 @@ class DesktopTasksControllerTest(flags: FlagsParameterization) : ShellTestCase()
        Flags.FLAG_INCLUDE_TOP_TRANSPARENT_FULLSCREEN_TASK_IN_DESKTOP_HEURISTIC,
    )
    @DisableFlags(Flags.FLAG_ENABLE_MULTIPLE_DESKTOPS_BACKEND)
    fun isDesktopModeShowing_topTransparentFullscreenTask_returnsTrue() {
    fun isAnyDeskActive_topTransparentFullscreenTask_returnsTrue() {
        val topTransparentTask = setUpFullscreenTask(displayId = DEFAULT_DISPLAY)
        taskRepository.setTopTransparentFullscreenTaskId(DEFAULT_DISPLAY, topTransparentTask.taskId)

        assertThat(controller.isDesktopModeShowing(displayId = DEFAULT_DISPLAY)).isTrue()
    }

    @Test
    @EnableFlags(
        Flags.FLAG_ENABLE_DESKTOP_WINDOWING_MODALS_POLICY,
        Flags.FLAG_INCLUDE_TOP_TRANSPARENT_FULLSCREEN_TASK_IN_DESKTOP_HEURISTIC,
        Flags.FLAG_ENABLE_MULTIPLE_DESKTOPS_BACKEND,
    )
    fun isDesktopModeShowing_deskInactive_topTransparentFullscreenTask_returnsTrue() {
        val topTransparentTask = setUpFullscreenTask(displayId = DEFAULT_DISPLAY)
        taskRepository.setTopTransparentFullscreenTaskId(DEFAULT_DISPLAY, topTransparentTask.taskId)
        taskRepository.setDeskInactive(deskId = 0)

        assertThat(controller.isDesktopModeShowing(displayId = DEFAULT_DISPLAY)).isTrue()
        assertThat(controller.isAnyDeskActive(displayId = DEFAULT_DISPLAY)).isTrue()
    }

    @Test
@@ -4783,25 +4755,6 @@ class DesktopTasksControllerTest(flags: FlagsParameterization) : ShellTestCase()
            .isEqualTo(WINDOWING_MODE_FREEFORM)
    }

    @Test
    @EnableFlags(
        Flags.FLAG_ENABLE_DESKTOP_WINDOWING_MODALS_POLICY,
        Flags.FLAG_INCLUDE_TOP_TRANSPARENT_FULLSCREEN_TASK_IN_DESKTOP_HEURISTIC,
        Flags.FLAG_ENABLE_MULTIPLE_DESKTOPS_BACKEND,
    )
    fun handleRequest_onlyTopTransparentFullscreenTask_multiDesksEnabled_movesToDesktop() {
        val deskId = 0
        val topTransparentTask = setUpFullscreenTask(displayId = DEFAULT_DISPLAY)
        taskRepository.setTopTransparentFullscreenTaskId(DEFAULT_DISPLAY, topTransparentTask.taskId)
        taskRepository.setDeskInactive(deskId = deskId)

        val task = setUpFullscreenTask(displayId = DEFAULT_DISPLAY)

        val wct = controller.handleRequest(Binder(), createTransition(task))
        assertNotNull(wct)
        verify(desksOrganizer).moveTaskToDesk(wct, deskId, task)
    }

    @Test
    @EnableFlags(Flags.FLAG_ENABLE_DESKTOP_WINDOWING_MODALS_POLICY)
    fun handleRequest_desktopNotShowing_topTransparentFullscreenTask_returnNull() {
@@ -4961,7 +4914,7 @@ class DesktopTasksControllerTest(flags: FlagsParameterization) : ShellTestCase()
                isTopActivityNoDisplay = false
            }

        assertThat(controller.isDesktopModeShowing(DEFAULT_DISPLAY)).isFalse()
        assertThat(controller.isAnyDeskActive(DEFAULT_DISPLAY)).isFalse()
        val result = controller.handleRequest(Binder(), createTransition(task))
        assertThat(result?.changes?.get(task.token.asBinder())?.windowingMode)
            .isEqualTo(WINDOWING_MODE_FULLSCREEN)
@@ -7483,7 +7436,7 @@ class DesktopTasksControllerTest(flags: FlagsParameterization) : ShellTestCase()
        // At least one freeform task to be in a desktop.
        val existingTask = setUpFreeformTask(displayId = DEFAULT_DISPLAY)
        val triggerTask = setUpFullscreenTask(displayId = DEFAULT_DISPLAY)
        assertThat(controller.isDesktopModeShowing(triggerTask.displayId)).isTrue()
        assertThat(controller.isAnyDeskActive(triggerTask.displayId)).isTrue()
        taskRepository.setTaskInFullImmersiveState(
            displayId = existingTask.displayId,
            taskId = existingTask.taskId,
@@ -7503,7 +7456,7 @@ class DesktopTasksControllerTest(flags: FlagsParameterization) : ShellTestCase()
    fun shouldPlayDesktopAnimation_fullscreenStaysFullscreen_doesNotPlay() {
        val triggerTask = setUpFullscreenTask(displayId = DEFAULT_DISPLAY)
        taskRepository.setDeskInactive(deskId = 0)
        assertThat(controller.isDesktopModeShowing(triggerTask.displayId)).isFalse()
        assertThat(controller.isAnyDeskActive(triggerTask.displayId)).isFalse()

        assertThat(
                controller.shouldPlayDesktopAnimation(
@@ -7519,7 +7472,7 @@ class DesktopTasksControllerTest(flags: FlagsParameterization) : ShellTestCase()
        // At least one freeform task to be in a desktop.
        val existingTask = setUpFreeformTask(displayId = DEFAULT_DISPLAY)
        val triggerTask = setUpFreeformTask(displayId = DEFAULT_DISPLAY, active = false)
        assertThat(controller.isDesktopModeShowing(triggerTask.displayId)).isTrue()
        assertThat(controller.isAnyDeskActive(triggerTask.displayId)).isTrue()
        taskRepository.setTaskInFullImmersiveState(
            displayId = existingTask.displayId,
            taskId = existingTask.taskId,
@@ -7539,7 +7492,7 @@ class DesktopTasksControllerTest(flags: FlagsParameterization) : ShellTestCase()
    fun shouldPlayDesktopAnimation_freeformExitsDesktop_doesNotPlay() {
        val triggerTask = setUpFreeformTask(displayId = DEFAULT_DISPLAY, active = false)
        taskRepository.setDeskInactive(deskId = 0)
        assertThat(controller.isDesktopModeShowing(triggerTask.displayId)).isFalse()
        assertThat(controller.isAnyDeskActive(triggerTask.displayId)).isFalse()

        assertThat(
                controller.shouldPlayDesktopAnimation(