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

Commit 4cd3fa43 authored by Jorge Gil's avatar Jorge Gil
Browse files

Exclude opening/move-to-front task from exiting immersive

It's possible for a non-top task to be moved to front and enter
immersive at the same time, so exclude it in move-to-front or opening
WCT from exiting immersive mode, since it doesn't make sense to exit
immersive in those cases.

Flag: com.android.window.flags.enable_fully_immersive_in_desktop
Fix: 374772576
Test: open Candy Crush in desktop, enter immersive, open settings from
notification shade, close settings, put candy crash back in immersive
and verify the app header can't be dragged or double clicked.

Change-Id: I9f614065814dcfbb2bae347ba00c10a53cdae71a
parent 883b4082
Loading
Loading
Loading
Loading
+6 −1
Original line number Diff line number Diff line
@@ -137,14 +137,19 @@ class DesktopFullImmersiveTransitionHandler(
     *
     * @param wct that will apply these changes
     * @param displayId of the display that should exit immersive mode
     * @param excludeTaskId of the task to ignore (not exit) if it is the immersive one
     * @return a function to apply once the transition that will apply these changes is started
     */
    fun exitImmersiveIfApplicable(
        wct: WindowContainerTransaction,
        displayId: Int
        displayId: Int,
        excludeTaskId: Int? = null,
    ): ((IBinder) -> Unit)? {
        if (!Flags.enableFullyImmersiveInDesktop()) return null
        val immersiveTask = desktopRepository.getTaskInFullImmersiveState(displayId) ?: return null
        if (immersiveTask == excludeTaskId) {
            return null
        }
        val taskInfo = shellTaskOrganizer.getRunningTaskInfo(immersiveTask) ?: return null
        logV("Appending immersive exit for task: $immersiveTask in display: $displayId")
        wct.setBounds(taskInfo.token, getExitDestinationBounds(taskInfo))
+24 −8
Original line number Diff line number Diff line
@@ -357,8 +357,11 @@ class DesktopTasksController(
        // TODO(342378842): Instead of using default display, support multiple displays
        val taskToMinimize = bringDesktopAppsToFrontBeforeShowingNewTask(
            DEFAULT_DISPLAY, wct, taskId)
        val runOnTransit = immersiveTransitionHandler
            .exitImmersiveIfApplicable(wct, DEFAULT_DISPLAY)
        val runOnTransit = immersiveTransitionHandler.exitImmersiveIfApplicable(
            wct = wct,
            displayId = DEFAULT_DISPLAY,
            excludeTaskId = taskId,
        )
        wct.startTask(
            taskId,
            ActivityOptions.makeBasic().apply {
@@ -385,7 +388,11 @@ class DesktopTasksController(
        }
        logV("moveRunningTaskToDesktop taskId=%d", task.taskId)
        exitSplitIfApplicable(wct, task)
        val runOnTransit = immersiveTransitionHandler.exitImmersiveIfApplicable(wct, task.displayId)
        val runOnTransit = immersiveTransitionHandler.exitImmersiveIfApplicable(
            wct = wct,
            displayId = task.displayId,
            excludeTaskId = task.taskId,
        )
        // Bring other apps to front first
        val taskToMinimize =
            bringDesktopAppsToFrontBeforeShowingNewTask(task.displayId, wct, task.taskId)
@@ -594,8 +601,11 @@ class DesktopTasksController(
        logV("moveBackgroundTaskToFront taskId=%s", taskId)
        val wct = WindowContainerTransaction()
        // TODO: b/342378842 - Instead of using default display, support multiple displays
        val runOnTransit = immersiveTransitionHandler
            .exitImmersiveIfApplicable(wct, DEFAULT_DISPLAY)
        val runOnTransit = immersiveTransitionHandler.exitImmersiveIfApplicable(
            wct = wct,
            displayId = DEFAULT_DISPLAY,
            excludeTaskId = taskId,
        )
        wct.startTask(
            taskId,
            ActivityOptions.makeBasic().apply {
@@ -618,7 +628,10 @@ class DesktopTasksController(
        val wct = WindowContainerTransaction()
        wct.reorder(taskInfo.token, true /* onTop */, true /* includingParents */)
        val runOnTransit = immersiveTransitionHandler.exitImmersiveIfApplicable(
            wct, taskInfo.displayId)
            wct = wct,
            displayId = taskInfo.displayId,
            excludeTaskId = taskInfo.taskId,
        )
        val transition =
            startLaunchTransition(TRANSIT_TO_FRONT, wct, taskInfo.taskId, remoteTransition)
        runOnTransit?.invoke(transition)
@@ -1218,8 +1231,11 @@ class DesktopTasksController(
            wct.startTask(requestedTaskId, options.toBundle())
            val taskToMinimize = bringDesktopAppsToFrontBeforeShowingNewTask(
                callingTask.displayId, wct, requestedTaskId)
            val runOnTransit = immersiveTransitionHandler
                .exitImmersiveIfApplicable(wct, callingTask.displayId)
            val runOnTransit = immersiveTransitionHandler.exitImmersiveIfApplicable(
                wct = wct,
                displayId = callingTask.displayId,
                excludeTaskId = requestedTaskId,
            )
            val transition = transitions.startTransition(TRANSIT_OPEN, wct, null)
            addPendingMinimizeTransition(transition, taskToMinimize)
            runOnTransit?.invoke(transition)
+25 −0
Original line number Diff line number Diff line
@@ -338,6 +338,31 @@ class DesktopFullImmersiveTransitionHandlerTest : ShellTestCase() {
        assertThat(wct.hasBoundsChange(task.token)).isFalse()
    }

    @Test
    @EnableFlags(Flags.FLAG_ENABLE_FULLY_IMMERSIVE_IN_DESKTOP)
    fun exitImmersiveIfApplicable_byDisplay_withExcludeTask_doesNotExit() {
        val task = createFreeformTask()
        whenever(mockShellTaskOrganizer.getRunningTaskInfo(task.taskId)).thenReturn(task)
        val wct = WindowContainerTransaction()
        val transition = Binder()
        desktopRepository.setTaskInFullImmersiveState(
            displayId = DEFAULT_DISPLAY,
            taskId = task.taskId,
            immersive = true
        )

        immersiveHandler.exitImmersiveIfApplicable(
            wct = wct,
            displayId = DEFAULT_DISPLAY,
            excludeTaskId = task.taskId
        )?.invoke(transition)

        assertThat(immersiveHandler.pendingExternalExitTransitions.any { exit ->
            exit.transition == transition && exit.displayId == DEFAULT_DISPLAY
                    && exit.taskId == task.taskId
        }).isFalse()
    }

    @Test
    @EnableFlags(Flags.FLAG_ENABLE_FULLY_IMMERSIVE_IN_DESKTOP)
    fun exitImmersiveIfApplicable_byTask_inImmersive_changesTaskBounds() {
+15 −10
Original line number Diff line number Diff line
@@ -3060,12 +3060,13 @@ class DesktopTasksControllerTest : ShellTestCase() {
    whenever(transitions.startTransition(eq(TRANSIT_OPEN), any(), anyOrNull()))
      .thenReturn(transition)
    whenever(mockDesktopFullImmersiveTransitionHandler
      .exitImmersiveIfApplicable(any(), eq(immersiveTask.displayId))).thenReturn(runOnStartTransit)
      .exitImmersiveIfApplicable(any(), eq(immersiveTask.displayId), eq(freeformTask.taskId)))
      .thenReturn(runOnStartTransit)

    runOpenInstance(immersiveTask, freeformTask.taskId)

    verify(mockDesktopFullImmersiveTransitionHandler)
      .exitImmersiveIfApplicable(any(), eq(immersiveTask.displayId))
      .exitImmersiveIfApplicable(any(), eq(immersiveTask.displayId), eq(freeformTask.taskId))
    runOnStartTransit.assertOnlyInvocation(transition)
  }

@@ -3370,12 +3371,13 @@ class DesktopTasksControllerTest : ShellTestCase() {
    val runOnStartTransit = RunOnStartTransitionCallback()
    val transition = Binder()
    whenever(mockDesktopFullImmersiveTransitionHandler
      .exitImmersiveIfApplicable(wct, task.displayId)).thenReturn(runOnStartTransit)
      .exitImmersiveIfApplicable(wct, task.displayId, task.taskId)).thenReturn(runOnStartTransit)
    whenever(enterDesktopTransitionHandler.moveToDesktop(wct, UNKNOWN)).thenReturn(transition)

    controller.moveTaskToDesktop(taskId = task.taskId, wct = wct, transitionSource = UNKNOWN)

    verify(mockDesktopFullImmersiveTransitionHandler).exitImmersiveIfApplicable(wct, task.displayId)
    verify(mockDesktopFullImmersiveTransitionHandler)
      .exitImmersiveIfApplicable(wct, task.displayId, task.taskId)
    runOnStartTransit.assertOnlyInvocation(transition)
  }

@@ -3386,12 +3388,13 @@ class DesktopTasksControllerTest : ShellTestCase() {
    val runOnStartTransit = RunOnStartTransitionCallback()
    val transition = Binder()
    whenever(mockDesktopFullImmersiveTransitionHandler
      .exitImmersiveIfApplicable(wct, task.displayId)).thenReturn(runOnStartTransit)
      .exitImmersiveIfApplicable(wct, task.displayId, task.taskId)).thenReturn(runOnStartTransit)
    whenever(enterDesktopTransitionHandler.moveToDesktop(wct, UNKNOWN)).thenReturn(transition)

    controller.moveTaskToDesktop(taskId = task.taskId, wct = wct, transitionSource = UNKNOWN)

    verify(mockDesktopFullImmersiveTransitionHandler).exitImmersiveIfApplicable(wct, task.displayId)
    verify(mockDesktopFullImmersiveTransitionHandler)
      .exitImmersiveIfApplicable(wct, task.displayId, task.taskId)
    runOnStartTransit.assertOnlyInvocation(transition)
  }

@@ -3401,13 +3404,14 @@ class DesktopTasksControllerTest : ShellTestCase() {
    val runOnStartTransit = RunOnStartTransitionCallback()
    val transition = Binder()
    whenever(mockDesktopFullImmersiveTransitionHandler
      .exitImmersiveIfApplicable(any(), eq(task.displayId))).thenReturn(runOnStartTransit)
      .exitImmersiveIfApplicable(any(), eq(task.displayId), eq(task.taskId)))
      .thenReturn(runOnStartTransit)
    whenever(transitions.startTransition(any(), any(), anyOrNull())).thenReturn(transition)

    controller.moveTaskToFront(task.taskId, remoteTransition = null)

    verify(mockDesktopFullImmersiveTransitionHandler)
      .exitImmersiveIfApplicable(any(), eq(task.displayId))
      .exitImmersiveIfApplicable(any(), eq(task.displayId), eq(task.taskId))
    runOnStartTransit.assertOnlyInvocation(transition)
  }

@@ -3417,13 +3421,14 @@ class DesktopTasksControllerTest : ShellTestCase() {
    val runOnStartTransit = RunOnStartTransitionCallback()
    val transition = Binder()
    whenever(mockDesktopFullImmersiveTransitionHandler
      .exitImmersiveIfApplicable(any(), eq(task.displayId))).thenReturn(runOnStartTransit)
      .exitImmersiveIfApplicable(any(), eq(task.displayId), eq(task.taskId)))
      .thenReturn(runOnStartTransit)
    whenever(transitions.startTransition(any(), any(), anyOrNull())).thenReturn(transition)

    controller.moveTaskToFront(task.taskId, remoteTransition = null)

    verify(mockDesktopFullImmersiveTransitionHandler)
      .exitImmersiveIfApplicable(any(), eq(task.displayId))
      .exitImmersiveIfApplicable(any(), eq(task.displayId), eq(task.taskId))
    runOnStartTransit.assertOnlyInvocation(transition)
  }