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

Commit 8a620569 authored by Eghosa Ewansiha-Vlachavas's avatar Eghosa Ewansiha-Vlachavas Committed by Android (Google) Code Review
Browse files

Merge "[1/n] Remove top transparent fullscreen task on new task opening" into main

parents b04ee502 b0cd6828
Loading
Loading
Loading
Loading
+2 −0
Original line number Diff line number Diff line
@@ -1404,6 +1404,7 @@ public abstract class WMShellModule {
            Optional<DesktopImmersiveController> desktopImmersiveController,
            DesktopMinimizationTransitionHandler desktopMinimizationTransitionHandler,
            DesktopModeDragAndDropTransitionHandler desktopModeDragAndDropTransitionHandler,
            Optional<SystemModalsTransitionHandler> systemModalsTransitionHandler,
            InteractionJankMonitor interactionJankMonitor,
            @ShellMainThread Handler handler,
            ShellInit shellInit,
@@ -1424,6 +1425,7 @@ public abstract class WMShellModule {
                        desktopImmersiveController.get(),
                        desktopMinimizationTransitionHandler,
                        desktopModeDragAndDropTransitionHandler,
                        systemModalsTransitionHandler,
                        interactionJankMonitor,
                        handler,
                        shellInit,
+34 −3
Original line number Diff line number Diff line
@@ -36,6 +36,7 @@ import com.android.internal.jank.InteractionJankMonitor
import com.android.internal.protolog.ProtoLog
import com.android.wm.shell.RootTaskDisplayAreaOrganizer
import com.android.wm.shell.desktopmode.DesktopModeTransitionTypes.TRANSIT_DESKTOP_MODE_TASK_LIMIT_MINIMIZE
import com.android.wm.shell.desktopmode.compatui.SystemModalsTransitionHandler
import com.android.wm.shell.freeform.FreeformTaskTransitionHandler
import com.android.wm.shell.freeform.FreeformTaskTransitionStarter
import com.android.wm.shell.protolog.ShellProtoLogGroup.WM_SHELL_DESKTOP_MODE
@@ -45,6 +46,7 @@ import com.android.wm.shell.sysui.ShellInit
import com.android.wm.shell.transition.MixedTransitionHandler
import com.android.wm.shell.transition.Transitions
import com.android.wm.shell.transition.Transitions.TransitionFinishCallback
import java.util.Optional

/** The [Transitions.TransitionHandler] coordinates transition handlers in desktop windowing. */
class DesktopMixedTransitionHandler(
@@ -56,6 +58,7 @@ class DesktopMixedTransitionHandler(
    private val desktopImmersiveController: DesktopImmersiveController,
    private val desktopMinimizationTransitionHandler: DesktopMinimizationTransitionHandler,
    private val desktopModeDragAndDropTransitionHandler: DesktopModeDragAndDropTransitionHandler,
    private val systemModalsTransitionHandler: Optional<SystemModalsTransitionHandler>,
    private val interactionJankMonitor: InteractionJankMonitor,
    @ShellMainThread private val handler: Handler,
    shellInit: ShellInit,
@@ -137,6 +140,7 @@ class DesktopMixedTransitionHandler(
        wct: WindowContainerTransaction,
        taskId: Int?,
        minimizingTaskId: Int? = null,
        closingTopTransparentTaskId: Int? = null,
        exitingImmersiveTask: Int? = null,
        dragEvent: DragEvent? = null,
    ): IBinder {
@@ -163,6 +167,7 @@ class DesktopMixedTransitionHandler(
                    transition = transition,
                    launchingTask = taskId,
                    minimizingTask = minimizingTaskId,
                    closingTopTransparentTask = closingTopTransparentTaskId,
                    exitingImmersiveTask = exitingImmersiveTask,
                    dragEvent = dragEvent,
                )
@@ -274,6 +279,10 @@ class DesktopMixedTransitionHandler(
            pending.exitingImmersiveTask?.let { exitingTask -> findTaskChange(info, exitingTask) }
        val minimizeChange =
            pending.minimizingTask?.let { minimizingTask -> findTaskChange(info, minimizingTask) }
        val closeTopTransparentFullscreenTaskChange =
            pending.closingTopTransparentTask?.let { closingTopTransparentTask ->
                findTaskChange(info, closingTopTransparentTask)
            }
        val launchChange = findDesktopTaskLaunchChange(info, pending.launchingTask)
        if (launchChange == null) {
            check(immersiveExitChange == null)
@@ -281,6 +290,7 @@ class DesktopMixedTransitionHandler(
            return false
        }

        var topTransparentAnimationCount = 0
        var subAnimationCount = -1
        var combinedWct: WindowContainerTransaction? = null
        val finishCb = TransitionFinishCallback { wct ->
@@ -291,9 +301,11 @@ class DesktopMixedTransitionHandler(
        }

        logV(
            "Animating mixed launch transition task#%d, minimizingTask#%s immersiveExitTask#%s",
            "Animating mixed launch transition task#%d, minimizingTask#%s " +
                "closingTopTransparentTask#%s immersiveExitTask#%s",
            launchChange.taskInfo!!.taskId,
            minimizeChange?.taskInfo?.taskId,
            closeTopTransparentFullscreenTaskChange?.taskInfo?.taskId,
            immersiveExitChange?.taskInfo?.taskId,
        )
        if (DesktopModeFlags.ENABLE_DESKTOP_APP_LAUNCH_TRANSITIONS_BUGFIX.isTrue) {
@@ -314,8 +326,26 @@ class DesktopMixedTransitionHandler(
                finishCallback,
            )
        }
        if (closeTopTransparentFullscreenTaskChange != null) {
            systemModalsTransitionHandler.ifPresent { handler ->
                logV(
                    "Animating system modal close: taskId=%d",
                    closeTopTransparentFullscreenTaskChange.taskInfo?.taskId,
                )
                topTransparentAnimationCount = 1
                // Animate the modal closure separately.
                info.changes.remove(closeTopTransparentFullscreenTaskChange)
                handler.animateSystemModal(
                    closeTopTransparentFullscreenTaskChange.leash,
                    startTransaction,
                    finishTransaction,
                    finishCb,
                    /* toShow= */ false,
                )
            }
        }
        if (immersiveExitChange != null) {
            subAnimationCount = 2
            subAnimationCount = 2 + topTransparentAnimationCount
            // Animate the immersive exit change separately.
            info.changes.remove(immersiveExitChange)
            desktopImmersiveController.animateResizeChange(
@@ -335,7 +365,7 @@ class DesktopMixedTransitionHandler(
        }
        // There's nothing to animate separately, so let the left over handler animate
        // the entire transition.
        subAnimationCount = 1
        subAnimationCount = 1 + topTransparentAnimationCount
        return dispatchToLeftoverHandler(
            transition,
            info,
@@ -536,6 +566,7 @@ class DesktopMixedTransitionHandler(
            override val transition: IBinder,
            val launchingTask: Int?,
            val minimizingTask: Int?,
            val closingTopTransparentTask: Int?,
            val exitingImmersiveTask: Int?,
            val dragEvent: DragEvent? = null,
        ) : PendingMixedTransition()
+28 −30
Original line number Diff line number Diff line
@@ -16,6 +16,7 @@

package com.android.wm.shell.desktopmode

import android.app.ActivityManager
import android.graphics.Rect
import android.graphics.Region
import android.util.ArrayMap
@@ -25,6 +26,7 @@ import android.util.SparseArray
import android.view.Display.INVALID_DISPLAY
import android.window.DesktopExperienceFlags
import android.window.DesktopModeFlags
import android.window.WindowContainerToken
import androidx.core.util.forEach
import androidx.core.util.valueIterator
import com.android.internal.annotations.VisibleForTesting
@@ -56,6 +58,9 @@ class DesktopRepository(
        var activeDeskId: Int? = null
    }

    /** Specific [TaskInfo] data related to top transparent fullscreen task handling. */
    data class TopTransparentFullscreenTaskData(val taskId: Int, val token: WindowContainerToken)

    /**
     * Task data tracked per desk.
     *
@@ -83,7 +88,7 @@ class DesktopRepository(
        val closingTasks: ArraySet<Int> = ArraySet(),
        val freeformTasksInZOrder: ArrayList<Int> = ArrayList(),
        var fullImmersiveTaskId: Int? = null,
        var topTransparentFullscreenTaskId: Int? = null,
        var topTransparentFullscreenTaskData: TopTransparentFullscreenTaskData? = null,
        var leftTiledTaskId: Int? = null,
        var rightTiledTaskId: Int? = null,
    ) {
@@ -97,7 +102,7 @@ class DesktopRepository(
                closingTasks = ArraySet(closingTasks),
                freeformTasksInZOrder = ArrayList(freeformTasksInZOrder),
                fullImmersiveTaskId = fullImmersiveTaskId,
                topTransparentFullscreenTaskId = topTransparentFullscreenTaskId,
                topTransparentFullscreenTaskData = topTransparentFullscreenTaskData,
                leftTiledTaskId = leftTiledTaskId,
                rightTiledTaskId = rightTiledTaskId,
            )
@@ -111,7 +116,7 @@ class DesktopRepository(
            closingTasks.clear()
            freeformTasksInZOrder.clear()
            fullImmersiveTaskId = null
            topTransparentFullscreenTaskId = null
            topTransparentFullscreenTaskData = null
            leftTiledTaskId = null
            rightTiledTaskId = null
        }
@@ -793,36 +798,29 @@ class DesktopRepository(
    fun getTaskInFullImmersiveState(displayId: Int): Int? =
        desktopData.getActiveDesk(displayId)?.fullImmersiveTaskId

    /** Sets the top transparent fullscreen task id for a given display's active desk. */
    @Deprecated("Deprecated with multiple desks")
    fun setTopTransparentFullscreenTaskId(displayId: Int, taskId: Int) {
        if (DesktopExperienceFlags.ENABLE_MULTIPLE_DESKTOPS_BACKEND.isTrue) return
    /** Sets the top transparent fullscreen task data for a given desk. */
    fun setTopTransparentFullscreenTaskData(deskId: Int, task: ActivityManager.RunningTaskInfo) {
        logD(
            "Top transparent fullscreen task set for display: taskId=%d, displayId=%d",
            taskId,
            displayId,
            "Top transparent fullscreen task set for desk: taskId=%d, deskId=%d",
            task.taskId,
            deskId,
        )
        desktopData.getActiveDesk(displayId)?.topTransparentFullscreenTaskId = taskId
        desktopData.getDesk(deskId)?.topTransparentFullscreenTaskData =
            TopTransparentFullscreenTaskData(task.taskId, task.token)
    }

    /** Returns the top transparent fullscreen task id for a given display, or null. */
    @Deprecated("Deprecated with multiple desks")
    fun getTopTransparentFullscreenTaskId(displayId: Int): Int? =
        desktopData
            .desksSequence(displayId)
            .mapNotNull { it.topTransparentFullscreenTaskId }
            .firstOrNull()

    /** Clears the top transparent fullscreen task id info for a given display's active desk. */
    @Deprecated("Deprecated with multiple desks")
    fun clearTopTransparentFullscreenTaskId(displayId: Int) {
        if (DesktopExperienceFlags.ENABLE_MULTIPLE_DESKTOPS_BACKEND.isTrue) return
    /** Returns the top transparent fullscreen task data for a given desk, or null. */
    fun getTopTransparentFullscreenTaskData(deskId: Int): TopTransparentFullscreenTaskData? =
        desktopData.getDesk(deskId)?.topTransparentFullscreenTaskData

    /** Clears the top transparent fullscreen task data for a given desk. */
    fun clearTopTransparentFullscreenTaskData(deskId: Int) {
        logD(
            "Top transparent fullscreen task cleared for display: taskId=%d, displayId=%d",
            desktopData.getActiveDesk(displayId)?.topTransparentFullscreenTaskId,
            displayId,
            "Top transparent fullscreen task cleared for desk: taskId=%d, deskId=%d",
            desktopData.getDesk(deskId)?.topTransparentFullscreenTaskData?.taskId,
            deskId,
        )
        desktopData.getActiveDesk(displayId)?.topTransparentFullscreenTaskId = null
        desktopData.getDesk(deskId)?.topTransparentFullscreenTaskData = null
    }

    @VisibleForTesting
@@ -842,7 +840,7 @@ class DesktopRepository(
            }
            val hasVisibleTasks = desk.visibleTasks.isNotEmpty()
            val hasTopTransparentFullscreenTask =
                getTopTransparentFullscreenTaskId(displayId) != null
                getTopTransparentFullscreenTaskData(desk.deskId) != null
            if (
                DesktopModeFlags.INCLUDE_TOP_TRANSPARENT_FULLSCREEN_TASK_IN_DESKTOP_HEURISTIC
                    .isTrue && DesktopModeFlags.ENABLE_DESKTOP_WINDOWING_MODALS_POLICY.isTrue
@@ -1188,8 +1186,8 @@ class DesktopRepository(
                    pw.println(desk.minimizedTasks.toDumpString())
                    pw.print("$desksPrefix  fullImmersiveTaskId=")
                    pw.println(desk.fullImmersiveTaskId)
                    pw.print("$desksPrefix  topTransparentFullscreenTaskId=")
                    pw.println(desk.topTransparentFullscreenTaskId)
                    pw.print("$desksPrefix  topTransparentFullscreenTaskData=")
                    pw.println(desk.topTransparentFullscreenTaskData)
                }
            }
    }
+65 −6
Original line number Diff line number Diff line
@@ -1506,6 +1506,8 @@ class DesktopTasksController(
                    launchingNewIntent = launchingTaskId == null,
                )
            }
        val closingTopTransparentTaskId =
            deskId?.let { taskRepository.getTopTransparentFullscreenTaskData(it)?.taskId }
        val exitImmersiveResult =
            desktopImmersiveController.exitImmersiveIfApplicable(
                wct = launchTransaction,
@@ -1543,6 +1545,8 @@ class DesktopTasksController(
                )
            }
        }
        // Remove top transparent fullscreen task if needed.
        deskId?.let { closeTopTransparentFullscreenTask(launchTransaction, it) }
        val t =
            if (remoteTransition == null) {
                logV("startLaunchTransition -- no remoteTransition -- wct = $launchTransaction")
@@ -1551,10 +1555,13 @@ class DesktopTasksController(
                    wct = launchTransaction,
                    taskId = launchingTaskId,
                    minimizingTaskId = taskIdToMinimize,
                    closingTopTransparentTaskId = closingTopTransparentTaskId,
                    exitingImmersiveTask = exitImmersiveResult.asExit()?.exitingTask,
                    dragEvent = dragEvent,
                )
            } else if (taskIdToMinimize == null) {
                // TODO(b/412761429): Move OneShotRemoteHandler call to within
                //  DesktopMixedTransitionHandler.
                val remoteTransitionHandler = OneShotRemoteHandler(mainExecutor, remoteTransition)
                transitions
                    .startTransition(transitionType, launchTransaction, remoteTransitionHandler)
@@ -2938,7 +2945,16 @@ class DesktopTasksController(
        // 2) minimize a Task if needed.
        // TODO: b/32994943 - remove dead code when cleaning up task_limit_separate_transition flag
        val taskIdToMinimize = addAndGetMinimizeChanges(deskId, wct, task.taskId)
        addPendingAppLaunchTransition(transition, task.taskId, taskIdToMinimize)
        // 3) Remove top transparent fullscreen task if needed.
        val closingTopTransparentTaskId =
            taskRepository.getTopTransparentFullscreenTaskData(deskId)?.taskId
        closeTopTransparentFullscreenTask(wct, deskId)
        addPendingAppLaunchTransition(
            transition,
            task.taskId,
            taskIdToMinimize,
            closingTopTransparentTaskId,
        )
        if (taskIdToMinimize != null) {
            addPendingMinimizeTransition(transition, taskIdToMinimize, MinimizeReason.TASK_LIMIT)
            return wct
@@ -2995,8 +3011,17 @@ class DesktopTasksController(
                                )
                            }
                            addPendingTaskLimitTransition(transition, deskId, task.taskId)
                            // Remove top transparent fullscreen task if needed.
                            val closingTopTransparentTaskId =
                                taskRepository.getTopTransparentFullscreenTaskData(deskId)?.taskId
                            closeTopTransparentFullscreenTask(wct, deskId)
                            // Also track the pending launching task.
                            addPendingAppLaunchTransition(transition, task.taskId, taskIdToMinimize)
                            addPendingAppLaunchTransition(
                                transition,
                                task.taskId,
                                taskIdToMinimize,
                                closingTopTransparentTaskId,
                            )
                        }
                    }
                runOnTransitStart?.invoke(transition)
@@ -3060,11 +3085,15 @@ class DesktopTasksController(
        if (!DesktopExperienceFlags.ENABLE_MULTIPLE_DESKTOPS_BACKEND.isTrue) {
            if (!inDesktop && !forceEnterDesktop(displayId)) return null
            if (
                DesktopModeFlags.INCLUDE_TOP_TRANSPARENT_FULLSCREEN_TASK_IN_DESKTOP_HEURISTIC
                    .isTrue && isTransparentTask
                isTransparentTask &&
                    (DesktopModeFlags.FORCE_CLOSE_TOP_TRANSPARENT_FULLSCREEN_TASK.isTrue ||
                        DesktopModeFlags
                            .INCLUDE_TOP_TRANSPARENT_FULLSCREEN_TASK_IN_DESKTOP_HEURISTIC
                            .isTrue)
            ) {
                // Only update task repository for transparent task.
                taskRepository.setTopTransparentFullscreenTaskId(displayId, taskId)
                val deskId = taskRepository.getActiveDeskId(displayId)
                deskId?.let { taskRepository.setTopTransparentFullscreenTaskData(it, task) }
            }
            // Already fullscreen, no-op.
            if (task.isFullscreen) return null
@@ -3087,6 +3116,16 @@ class DesktopTasksController(
            logD("handleIncompatibleTaskLaunch not in desktop, not a freeform task, nothing to do")
            return null
        }
        if (
            isTransparentTask &&
                (DesktopModeFlags.FORCE_CLOSE_TOP_TRANSPARENT_FULLSCREEN_TASK.isTrue ||
                    DesktopModeFlags.INCLUDE_TOP_TRANSPARENT_FULLSCREEN_TASK_IN_DESKTOP_HEURISTIC
                        .isTrue)
        ) {
            // Only update task repository for transparent task.
            val deskId = taskRepository.getActiveDeskId(displayId)
            deskId?.let { taskRepository.setTopTransparentFullscreenTaskData(it, task) }
        }
        // Both opaque and transparent incompatible tasks need to be forced to fullscreen, but
        // opaque ones force-exit the desktop while transparent ones are just shown on top of the
        // desktop while keeping it active.
@@ -3448,6 +3487,7 @@ class DesktopTasksController(
        transition: IBinder,
        launchTaskId: Int,
        minimizeTaskId: Int?,
        closingTopTransparentTaskId: Int?,
    ) {
        if (!DesktopModeFlags.ENABLE_DESKTOP_APP_LAUNCH_TRANSITIONS_BUGFIX.isTrue) {
            return
@@ -3458,6 +3498,7 @@ class DesktopTasksController(
                transition,
                launchTaskId,
                minimizeTaskId,
                closingTopTransparentTaskId,
                /* exitingImmersiveTask= */ null,
            )
        )
@@ -3512,7 +3553,16 @@ class DesktopTasksController(
                    launchTaskId = newTask?.taskId,
                )
                if (newTask != null && addPendingLaunchTransition) {
                    addPendingAppLaunchTransition(transition, newTask.taskId, taskIdToMinimize)
                    // Remove top transparent fullscreen task if needed.
                    val closingTopTransparentTaskId =
                        taskRepository.getTopTransparentFullscreenTaskData(deskId)?.taskId
                    closeTopTransparentFullscreenTask(wct, deskId)
                    addPendingAppLaunchTransition(
                        transition,
                        newTask.taskId,
                        taskIdToMinimize,
                        closingTopTransparentTaskId,
                    )
                }
            }
        }
@@ -3574,6 +3624,15 @@ class DesktopTasksController(
        }
    }

    private fun closeTopTransparentFullscreenTask(wct: WindowContainerTransaction, deskId: Int) {
        if (!DesktopModeFlags.FORCE_CLOSE_TOP_TRANSPARENT_FULLSCREEN_TASK.isTrue) return
        val data = taskRepository.getTopTransparentFullscreenTaskData(deskId)
        if (data != null) {
            logD("closeTopTransparentFullscreenTask: taskId=%d, deskId=%d", data.taskId, deskId)
            wct.removeTask(data.token)
        }
    }

    /** Activates the desk at the given index if it exists. */
    fun activatePreviousDesk(displayId: Int) {
        if (
+6 −5
Original line number Diff line number Diff line
@@ -79,9 +79,9 @@ class DesktopTasksTransitionObserver(
    ) {
        // TODO: b/332682201 Update repository state
        if (
            DesktopModeFlags.INCLUDE_TOP_TRANSPARENT_FULLSCREEN_TASK_IN_DESKTOP_HEURISTIC.isTrue &&
            DesktopModeFlags.ENABLE_DESKTOP_WINDOWING_MODALS_POLICY.isTrue &&
                !DesktopExperienceFlags.ENABLE_MULTIPLE_DESKTOPS_BACKEND.isTrue
                (DesktopModeFlags.INCLUDE_TOP_TRANSPARENT_FULLSCREEN_TASK_IN_DESKTOP_HEURISTIC
                    .isTrue || DesktopModeFlags.FORCE_CLOSE_TOP_TRANSPARENT_FULLSCREEN_TASK.isTrue)
        ) {
            updateTopTransparentFullscreenTaskId(info)
        }
@@ -213,8 +213,9 @@ class DesktopTasksTransitionObserver(
                change.taskInfo?.let { task ->
                    val desktopRepository = desktopUserRepositories.getProfile(task.userId)
                    val displayId = task.displayId
                    val deskId = desktopRepository.getActiveDeskId(displayId) ?: return@forEachLoop
                    val transparentTaskId =
                        desktopRepository.getTopTransparentFullscreenTaskId(displayId)
                        desktopRepository.getTopTransparentFullscreenTaskData(deskId)?.taskId
                    if (transparentTaskId == null) return@forEachLoop
                    val changeMode = change.mode
                    val taskId = task.taskId
@@ -228,7 +229,7 @@ class DesktopTasksTransitionObserver(
                        isTopTransparentFullscreenTaskClosing ||
                            isNonTopTransparentFullscreenTaskOpening
                    ) {
                        desktopRepository.clearTopTransparentFullscreenTaskId(displayId)
                        desktopRepository.clearTopTransparentFullscreenTaskData(deskId)
                        return@forEachLoop
                    }
                }
Loading