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

Commit 8836b3c5 authored by Jorge Gil's avatar Jorge Gil
Browse files

Fix |displayId| argument for desktop clean up from alt+tab..

..and other to-fullscreen changes when the task being moved is a
recent (non-running task).

Instead of using |TaskInfo.displayId| which may be invalid, use the
displayId associated with the deactivating desk.

Also no-ops and logs a warning from HomeIntentProvider.

Flag: EXEMPT BUGFIX
Fix: 441678801
Test: atest WMShellUnitTests
Change-Id: I40669d64bdeee05558cdfeea6214b6296b466c19
parent 9c9c7234
Loading
Loading
Loading
Loading
+10 −0
Original line number Diff line number Diff line
@@ -23,9 +23,12 @@ import android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN
import android.content.Context
import android.content.Intent
import android.os.UserHandle
import android.view.Display
import android.view.Display.DEFAULT_DISPLAY
import android.window.DesktopExperienceFlags.ENABLE_PER_DISPLAY_DESKTOP_WALLPAPER_ACTIVITY
import android.window.WindowContainerTransaction
import com.android.internal.protolog.ProtoLog
import com.android.wm.shell.protolog.ShellProtoLogGroup

/** Creates home intent **/
class HomeIntentProvider(
@@ -34,6 +37,13 @@ class HomeIntentProvider(
    fun addLaunchHomePendingIntent(
        wct: WindowContainerTransaction, displayId: Int, userId: Int? = null
    ) {
        if (displayId == Display.INVALID_DISPLAY) {
            ProtoLog.w(
                ShellProtoLogGroup.WM_SHELL,
                "HomeIntentProvider: attempted to add launch home intent for invalid display",
            )
            return
        }
        val userHandle =
            if (userId != null) UserHandle.of(userId) else UserHandle.of(ActivityManager.getCurrentUser())

+40 −19
Original line number Diff line number Diff line
@@ -1967,6 +1967,7 @@ class DesktopTasksController(
    ) {
        val displayId =
            when {
                // May be invalid when the task info of a recent (non-running task).
                task.displayId != INVALID_DISPLAY -> task.displayId
                focusTransitionObserver.globallyFocusedDisplayId != INVALID_DISPLAY ->
                    focusTransitionObserver.globallyFocusedDisplayId
@@ -4699,23 +4700,36 @@ class DesktopTasksController(
        return bounds
    }

    /** Applies the changes needed to enter fullscreen and clean up the desktop if needed. */
    /**
     * Applies the changes needed to enter fullscreen and clean up the desktop if needed.
     *
     * @param destinationDisplayId the destination display id for the task, which may be different
     *   from the task info's displayId when the task is also being moved across displays or when
     *   the task is a recents (non-running) task that was previously in [destinationDisplayId] but
     *   its info reports INVALID_DISPLAY.
     */
    fun addMoveToFullscreenChanges(
        wct: WindowContainerTransaction,
        taskInfo: TaskInfo,
        willExitDesktop: Boolean,
        displayId: Int = taskInfo.displayId,
        destinationDisplayId: Int = taskInfo.displayId,
    ): RunOnTransitStart? {
        val sourceDisplayId = taskInfo.displayId
        val sourceDisplayId =
            if (taskInfo.displayId != INVALID_DISPLAY) {
                taskInfo.displayId
            } else {
                // This is possible when the task is a recent (non-running) task.
                destinationDisplayId
            }
        logV(
            "addMoveToFullscreenChanges taskId=%d sourceDisplayId=%d destDisplayId=%d " +
            "addMoveToFullscreenChanges taskId=%d sourceDisplayId=%d destinationDisplayId=%d " +
                "willExitDesktop=%b",
            taskInfo.taskId,
            sourceDisplayId,
            displayId,
            destinationDisplayId,
            willExitDesktop,
        )
        val tdaInfo = rootTaskDisplayAreaOrganizer.getDisplayAreaInfo(displayId)!!
        val tdaInfo = rootTaskDisplayAreaOrganizer.getDisplayAreaInfo(destinationDisplayId)!!
        val tdaWindowingMode = tdaInfo.configuration.windowConfiguration.windowingMode
        val targetWindowingMode =
            if (tdaWindowingMode == WINDOWING_MODE_FULLSCREEN) {
@@ -4736,7 +4750,7 @@ class DesktopTasksController(
        }
        if (
            DesktopExperienceFlags.ENABLE_MULTIPLE_DESKTOPS_BACKEND.isTrue ||
                taskInfo.displayId != displayId
                taskInfo.displayId != destinationDisplayId
        ) {
            wct.reparent(taskInfo.token, tdaInfo.token, /* onTop= */ true)
        } else if (enableAltTabKqsFlatenning.isTrue) {
@@ -4746,21 +4760,22 @@ class DesktopTasksController(
        }
        val userId = taskInfo.userId
        val repository = userRepositories.getProfile(userId)
        val deskId =
        val sourceDeskId =
            // If the task moving to fullscreen was in a desk, then that's the desk to deactivate.
            repository.getDeskIdForTask(taskInfo.taskId)
                ?: if (enableAltTabKqsFlatenning.isTrue) {
                    repository.getActiveDeskId(displayId)
                    // The task we're moving to might not be in a desk (for example, we might be
                    // refocusing an already fullscreen task with Alt+Tab), so check if there's a
                    // desk active and deactivate that one.
                    repository.getActiveDeskId(destinationDisplayId)
                } else {
                    null
                }
        if (willExitDesktop) {
            val isLastTask =
                deskId?.let { repository.isOnlyTaskInDesk(taskInfo.taskId, it) } ?: false
            return performDesktopExitCleanUp(
                wct = wct,
                deskId = deskId,
                displayId =
                    if (
            val cleanupDisplayId =
                // A desk is getting deactivated, so use that desk's display id.
                sourceDeskId?.let { repository.getDisplayForDesk(it) }
                    ?: if (
                        DesktopExperienceFlags.MOVE_TO_NEXT_DISPLAY_SHORTCUT_WITH_PROJECTED_MODE
                            .isTrue
                    ) {
@@ -4768,8 +4783,14 @@ class DesktopTasksController(
                        sourceDisplayId
                    } else {
                        // Before the bug fix, display move is not considered.
                        displayId
                    },
                        destinationDisplayId
                    }
            val isLastTask =
                sourceDeskId?.let { repository.isOnlyTaskInDesk(taskInfo.taskId, it) } ?: false
            return performDesktopExitCleanUp(
                wct = wct,
                deskId = sourceDeskId,
                displayId = cleanupDisplayId,
                userId = userId,
                willExitDesktop = true,
                removingLastTaskId = if (isLastTask) taskInfo.taskId else null,
@@ -4779,7 +4800,7 @@ class DesktopTasksController(
                            .isTrue
                    ) {
                        // If the last task is moved from the display, it should go to home.
                        displayId != taskInfo.displayId
                        destinationDisplayId != taskInfo.displayId
                    } else {
                        // Before the bug fix, display move is not considered.
                        false
+51 −2
Original line number Diff line number Diff line
@@ -3072,6 +3072,48 @@ class DesktopTasksControllerTest(flags: FlagsParameterization) : ShellTestCase()
        verifyExitDesktopWCTNotExecuted()
    }
    @Test
    @EnableFlags(
        Flags.FLAG_ENABLE_MULTIPLE_DESKTOPS_BACKEND,
        com.android.launcher3.Flags.FLAG_ENABLE_ALT_TAB_KQS_FLATENNING,
        FLAG_MOVE_TO_NEXT_DISPLAY_SHORTCUT_WITH_PROJECTED_MODE,
    )
    fun moveToFullscreen_fullscreenNonRunningTask_deskActive_cleansUpSourceDisplay() {
        whenever(focusTransitionObserver.globallyFocusedDisplayId).thenReturn(SECOND_DISPLAY)
        taskRepository.addDesk(displayId = SECOND_DISPLAY, deskId = 9)
        taskRepository.setActiveDesk(displayId = SECOND_DISPLAY, deskId = 9)
        val task = setUpFullscreenTask(displayId = INVALID_TASK_ID, background = true)
        controller.moveToFullscreen(task.taskId, transitionSource = UNKNOWN)
        val wct = getLatestExitDesktopWct()
        // Verify that cleanup (e.g. resetting the launcher) is performed on the source display
        // where the task originated from.
        wct.assertPendingIntent(launchHomeIntent(SECOND_DISPLAY))
        wct.assertPendingIntentActivityOptionsLaunchDisplayId(SECOND_DISPLAY)
    }
    @Test
    @EnableFlags(
        Flags.FLAG_ENABLE_MULTIPLE_DESKTOPS_BACKEND,
        com.android.launcher3.Flags.FLAG_ENABLE_ALT_TAB_KQS_FLATENNING,
        FLAG_MOVE_TO_NEXT_DISPLAY_SHORTCUT_WITH_PROJECTED_MODE,
    )
    fun moveToFullscreen_fullscreenNonRunningTask_noDeskActive_cleansUpSourceDisplay() {
        whenever(focusTransitionObserver.globallyFocusedDisplayId).thenReturn(SECOND_DISPLAY)
        taskRepository.addDesk(displayId = SECOND_DISPLAY, deskId = 9)
        taskRepository.setDeskInactive(deskId = 9)
        val task = setUpFullscreenTask(displayId = INVALID_TASK_ID, background = true)
        controller.moveToFullscreen(task.taskId, transitionSource = UNKNOWN)
        val wct = getLatestExitDesktopWct()
        // Verify that cleanup (e.g. resetting the launcher) is performed on the source display
        // where the task originated from.
        wct.assertPendingIntent(launchHomeIntent(SECOND_DISPLAY))
        wct.assertPendingIntentActivityOptionsLaunchDisplayId(SECOND_DISPLAY)
    }
    @Test
    @EnableFlags(Flags.FLAG_ENABLE_MULTIPLE_DESKTOPS_BACKEND)
    fun moveToFullscreen_secondDisplayTaskHasFreeform_secondDisplayNotAffected() {
@@ -12625,6 +12667,7 @@ class DesktopTasksControllerTest(flags: FlagsParameterization) : ShellTestCase()
        enableSystemFullscreenOverride: Boolean = false,
        aspectRatioOverrideApplied: Boolean = false,
        visible: Boolean = true,
        background: Boolean = false,
    ): RunningTaskInfo {
        val task = createFullscreenTask(displayId)
        val activityInfo = ActivityInfo()
@@ -12675,8 +12718,14 @@ class DesktopTasksControllerTest(flags: FlagsParameterization) : ShellTestCase()
            }
            isVisible = visible
        }
        if (background) {
            whenever(shellTaskOrganizer.getRunningTaskInfo(task.taskId)).thenReturn(null)
            whenever(recentTasksController.findTaskInBackground(task.taskId))
                .thenReturn(createRecentTaskInfo(taskId = task.taskId, displayId = INVALID_DISPLAY))
        } else {
            whenever(shellTaskOrganizer.getRunningTaskInfo(task.taskId)).thenReturn(task)
            runningTasks.add(task)
        }
        return task
    }