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

Commit c2c2fb8a authored by Matt Sziklay's avatar Matt Sziklay Committed by Android (Google) Code Review
Browse files

Merge changes Ie32fdf44,Ibc39040c,I5eb80a0a into main

* changes:
  Fixes for restoring minimized tasks on reconnect.
  Reconnect: Prevent multiple restoreDisplay calls for the same display.
  Prevent restored display tasks from showing on keyguard.
parents fce2b2a2 bf5549ea
Loading
Loading
Loading
Loading
+39 −11
Original line number Diff line number Diff line
@@ -20,6 +20,7 @@ import android.content.Context
import android.os.Trace
import android.os.UserHandle
import android.os.UserManager
import android.util.ArraySet
import android.view.Display
import android.view.Display.DEFAULT_DISPLAY
import android.window.DesktopExperienceFlags
@@ -27,6 +28,7 @@ import android.window.DesktopExperienceFlags.ENABLE_MULTIPLE_DESKTOPS_ACTIVATION
import android.window.DesktopModeFlags
import android.window.DisplayAreaInfo
import com.android.app.tracing.traceSection
import com.android.internal.annotations.VisibleForTesting
import com.android.internal.protolog.ProtoLog
import com.android.wm.shell.RootTaskDisplayAreaOrganizer
import com.android.wm.shell.RootTaskDisplayAreaOrganizer.RootTaskDisplayAreaListener
@@ -77,6 +79,10 @@ class DesktopDisplayEventHandler(
    // displayId to its uniqueId since we will not be able to fetch it after disconnect.
    private val uniqueIdByDisplayId = mutableMapOf<Int, String>()

    // All uniqueDisplayIds that are currently being restored; any further requests
    // to restore them will no-op.
    @VisibleForTesting val displaysMidRestoration = ArraySet<String>()

    init {
        shellInit.addInitCallback({ onInit() }, this)
    }
@@ -141,6 +147,14 @@ class DesktopDisplayEventHandler(
            if (displayId != DEFAULT_DISPLAY) {
                desktopDisplayModeController.updateDefaultDisplayWindowingMode()
            }
            val uniqueDisplayId = uniqueIdByDisplayId[displayId]
            if (uniqueDisplayId != null && uniqueDisplayId in displaysMidRestoration) {
                logW(
                    "onDisplayRemoved: Found display mid-restoration that did not finish: " +
                        "displayId=$displayId, uniqueDisplayId=$uniqueDisplayId"
                )
                displaysMidRestoration.remove(uniqueDisplayId)
            }
            uniqueIdByDisplayId.remove(displayId)
        }

@@ -189,20 +203,28 @@ class DesktopDisplayEventHandler(
        val uniqueDisplayId = displayController.getDisplay(displayId)?.uniqueId ?: return false
        uniqueIdByDisplayId[displayId] = uniqueDisplayId
        val currentUserRepository = desktopUserRepositories.current
        if (
            !DesktopExperienceFlags.ENABLE_DISPLAY_RECONNECT_INTERACTION.isTrue ||
                !currentUserRepository.hasPreservedDisplayForUniqueDisplayId(uniqueDisplayId)
        ) {
        if (!DesktopExperienceFlags.ENABLE_DISPLAY_RECONNECT_INTERACTION.isTrue) {
            logV("handlePotentialReconnect: Reconnect not supported; aborting.")
            return false
        }
        val preservedTasks = currentUserRepository.getPreservedTasks(uniqueDisplayId)
        if (uniqueDisplayId in displaysMidRestoration) {
            logV("handlePotentialReconnect: uniqueDisplay=$uniqueDisplayId " +
                "mid-restoration; aborting.")
            return false
        }
        if (!currentUserRepository.hasPreservedDisplayForUniqueDisplayId(uniqueDisplayId)) {
            logV("handlePotentialReconnect: No preserved display found for " +
                "uniqueDisplayId=$uniqueDisplayId; aborting.")
        }
        val preservedTasks =
            currentUserRepository.getPreservedTasks(uniqueDisplayId).toMutableList()
        // Projected mode: Do not move anything focused on the internal display.
        if (!desktopState.isDesktopModeSupportedOnDisplay(DEFAULT_DISPLAY)) {
            val focusedDefaultDisplayTaskIds =
                desktopTasksController
                    .getFocusedNonDesktopTasks(DEFAULT_DISPLAY, currentUserRepository.userId)
                    .map { task -> task.taskId }
            preservedTasks.filterNot { taskId -> focusedDefaultDisplayTaskIds.contains(taskId) }
            preservedTasks.removeAll { taskId -> focusedDefaultDisplayTaskIds.contains(taskId) }
        }
        if (preservedTasks.isEmpty()) {
            // The preserved display is normally removed at the end of restoreDisplay.
@@ -210,11 +232,17 @@ class DesktopDisplayEventHandler(
            currentUserRepository.removePreservedDisplay(uniqueDisplayId)
            return false
        }
        displaysMidRestoration.add(uniqueDisplayId)
        mainScope.launch {
            // If the display has been removed by the time this executes, restore nothing.
            if (uniqueDisplayId !in displaysMidRestoration) return@launch
            desktopTasksController.restoreDisplay(
                displayId = displayId,
                uniqueDisplayId = uniqueDisplayId,
                userId = desktopUserRepositories.current.userId,
            )
            displaysMidRestoration.remove(uniqueDisplayId)
        }
        return true
    }

+55 −14
Original line number Diff line number Diff line
@@ -165,6 +165,7 @@ import com.android.wm.shell.shared.split.SplitScreenConstants.SPLIT_POSITION_BOT
import com.android.wm.shell.shared.split.SplitScreenConstants.SPLIT_POSITION_TOP_OR_LEFT
import com.android.wm.shell.splitscreen.SplitScreenController
import com.android.wm.shell.splitscreen.SplitScreenController.EXIT_REASON_DESKTOP_MODE
import com.android.wm.shell.sysui.KeyguardChangeListener
import com.android.wm.shell.sysui.ShellCommandHandler
import com.android.wm.shell.sysui.ShellController
import com.android.wm.shell.sysui.ShellInit
@@ -256,7 +257,8 @@ class DesktopTasksController(
    RemoteCallable<DesktopTasksController>,
    Transitions.TransitionHandler,
    DragAndDropController.DragAndDropListener,
    UserChangeListener {
    UserChangeListener,
    KeyguardChangeListener {

    private val desktopMode: DesktopModeImpl
    private var visualIndicator: DesktopModeVisualIndicator? = null
@@ -354,6 +356,7 @@ class DesktopTasksController(
            }
        )
        dragAndDropController.addListener(this)
        shellController.addKeyguardChangeListener(this)
    }

    @VisibleForTesting
@@ -810,6 +813,25 @@ class DesktopTasksController(
        }
    }

    override fun onKeyguardVisibilityChanged(
        visible: Boolean,
        occluded: Boolean,
        animatingDismiss: Boolean,
    ) {
        if (visible) return
        val displaysByUniqueId = displayController.allDisplaysByUniqueId ?: return
        for (displayIdByUniqueId in displaysByUniqueId) {
            val taskRepository = userRepositories.current
            if (taskRepository.hasPreservedDisplayForUniqueDisplayId(displayIdByUniqueId.key)) {
                restoreDisplay(
                    displayIdByUniqueId.value,
                    displayIdByUniqueId.key,
                    taskRepository.userId,
                )
            }
        }
    }

    private fun handleExtendedModeDisconnect(
        desktopRepository: DesktopRepository,
        wct: WindowContainerTransaction,
@@ -948,12 +970,14 @@ class DesktopTasksController(
        )
        // TODO: b/365873835 - Utilize DesktopTask data class once it is
        //  implemented in DesktopRepository.
        // Do not handle restoration while locked; it will be handled when keyguard is gone.
        if (keyguardManager.isKeyguardLocked) return
        val repository = userRepositories.getProfile(userId)
        val preservedTaskIdsByDeskId = repository.getPreservedTasksByDeskIdInZOrder(uniqueDisplayId)
        val boundsByTaskId = repository.getPreservedTaskBounds(uniqueDisplayId)
        val activeDeskId = repository.getPreservedActiveDesk(uniqueDisplayId)
        val wct = WindowContainerTransaction()
        var runOnTransitStart: RunOnTransitStart? = null
        var runOnTransitStartList = mutableListOf<RunOnTransitStart>()
        val destDisplayLayout = displayController.getDisplayLayout(displayId) ?: return
        val tilingReconnectHandler =
            TilingDisplayReconnectEventHandler(repository, snapEventHandler, transitions, displayId)
@@ -973,13 +997,14 @@ class DesktopTasksController(
                )
                val isActiveDesk = preservedDeskId == activeDeskId
                if (isActiveDesk) {
                    runOnTransitStart =
                    runOnTransitStartList.add(
                        addDeskActivationChanges(
                            deskId = newDeskId,
                            wct = wct,
                            userId = userId,
                            enterReason = EnterReason.DISPLAY_CONNECT,
                        )
                    )
                }

                preservedTaskIds.asReversed().forEach { taskId ->
@@ -990,9 +1015,11 @@ class DesktopTasksController(
                                deskId = newDeskId,
                                taskId = taskId,
                                userId = userId,
                                displayId = displayId,
                                uniqueDisplayId = uniqueDisplayId,
                                taskBounds = boundsByTaskId[taskId],
                            )
                            ?.let { runOnTransitStartList.add(it) }
                    }
                }

@@ -1011,7 +1038,7 @@ class DesktopTasksController(
            }
            val transition = transitions.startTransition(TRANSIT_CHANGE, wct, null)
            tilingReconnectHandler.activationBinder = transition
            runOnTransitStart?.invoke(transition)
            runOnTransitStartList.forEach { it.invoke(transition) }
            repository.removePreservedDisplay(uniqueDisplayId)
        }
    }
@@ -1022,9 +1049,10 @@ class DesktopTasksController(
        deskId: Int,
        taskId: Int,
        userId: Int,
        displayId: Int,
        uniqueDisplayId: String,
        taskBounds: Rect?,
    ) {
    ): RunOnTransitStart? {
        logD(
            "addRestoreTaskToDeskChanges: taskId=$taskId; deskId=$deskId; userId=$userId; " +
                "taskBounds=$taskBounds; uniqueDisplayId=$uniqueDisplayId"
@@ -1034,7 +1062,7 @@ class DesktopTasksController(
        val task = shellTaskOrganizer.getRunningTaskInfo(taskId)
        if (task == null) {
            logE("restoreDisplay: Could not find running task info for taskId=$taskId.")
            return
            return null
        }
        desksOrganizer.moveTaskToDesk(wct, deskId, task, minimized = minimized)
        wct.setDensityDpi(task.token, destinationDisplayLayout.densityDpi())
@@ -1044,6 +1072,19 @@ class DesktopTasksController(
            // Bring display to front if task is not minimized to ensure display focus.
            wct.reorder(task.token, /* onTop= */ true, /* includingParents= */ true)
        }
        return { transition ->
            desksTransitionObserver.addPendingTransition(
                DeskTransition.AddTaskToDesk(
                    token = transition,
                    userId = userId,
                    displayId = displayId,
                    deskId = deskId,
                    taskId = taskId,
                    taskBounds = taskBounds,
                    minimized = minimized,
                )
            )
        }
    }

    private fun handleUserChangeTransitionRequest(
+14 −0
Original line number Diff line number Diff line
@@ -15,6 +15,7 @@
 */
package com.android.wm.shell.desktopmode.multidesks

import android.graphics.Rect
import android.os.IBinder
import com.android.wm.shell.desktopmode.DesktopModeEventLogger

@@ -152,4 +153,17 @@ sealed interface DeskTransition {
    ) : DeskTransition {
        override fun copyWithToken(token: IBinder): DeskTransition = copy(token)
    }

    /** A transition to add a task to a desk, including bounds and minimize state */
    data class AddTaskToDesk(
        override val token: IBinder,
        override val userId: Int,
        val displayId: Int,
        val deskId: Int,
        val taskId: Int,
        val taskBounds: Rect?,
        val minimized: Boolean,
    ) : DeskTransition {
        override fun copyWithToken(token: IBinder): DeskTransition = copy(token)
    }
}
+20 −0
Original line number Diff line number Diff line
@@ -199,6 +199,7 @@ class DesksTransitionObserver(
            is DeskTransition.DeactivateDesk -> handleDeactivateDeskTransition(info, deskTransition)
            is DeskTransition.ChangeDeskDisplay -> handleChangeDeskDisplay(info, deskTransition)
            is DeskTransition.RemoveDisplay -> handleRemoveDisplay(deskTransition)
            is DeskTransition.AddTaskToDesk -> handleAddTaskToDesk(deskTransition)
        }
    }

@@ -258,6 +259,25 @@ class DesksTransitionObserver(
        }
    }

    private fun handleAddTaskToDesk(deskTransition: DeskTransition.AddTaskToDesk) {
        logD("handleAddTaskToDesk: %s", deskTransition)
        val taskRepository = desktopUserRepositories.getProfile(deskTransition.userId)
        taskRepository.addTaskToDesk(
            deskTransition.displayId,
            deskTransition.deskId,
            deskTransition.taskId,
            !deskTransition.minimized,
            deskTransition.taskBounds,
        )
        if (deskTransition.minimized) {
            taskRepository.minimizeTaskInDesk(
                deskTransition.displayId,
                deskTransition.deskId,
                deskTransition.taskId,
            )
        }
    }

    private fun handleIndependentDeskTransitionIfNeeded(info: TransitionInfo) {
        val deskChanges = info.deskChanges()
        val desktopWallpaperChanges = info.desktopWallpaperChanges()
+21 −5
Original line number Diff line number Diff line
@@ -520,8 +520,11 @@ class RootTaskDesksOrganizer(
                        },
                )
            createDeskRootRequests.remove(deskRequest)
            deskRequest.onCreateCallback.onCreated(deskId)
            createDeskMinimizationRoot(displayId = appearingInDisplayId, deskId = deskId)
            createDeskMinimizationRoot(
                displayId = appearingInDisplayId,
                deskId = deskId,
                callback = deskRequest.onCreateCallback,
            )
            return
        }
        // Check if there's any pending minimization container creation requests under this display.
@@ -532,6 +535,7 @@ class RootTaskDesksOrganizer(
        val deskMinimizationRoot = DeskMinimizationRoot(deskId, taskInfo, leash)
        deskMinimizationRootsByDeskId[deskId] = deskMinimizationRoot
        createDeskMinimizationRootRequests.remove(deskMinimizationRootRequest)
        deskMinimizationRootRequest.callback.onCreated(deskId)
        hideMinimizationRoot(deskMinimizationRoot)
    }

@@ -630,9 +634,17 @@ class RootTaskDesksOrganizer(
        }
    }

    private fun createDeskMinimizationRoot(displayId: Int, deskId: Int) {
    private fun createDeskMinimizationRoot(
        displayId: Int,
        deskId: Int,
        callback: OnCreateCallback,
    ) {
        createDeskMinimizationRootRequests +=
            CreateDeskMinimizationRootRequest(displayId = displayId, deskId = deskId)
            CreateDeskMinimizationRootRequest(
                displayId = displayId,
                deskId = deskId,
                callback = callback,
            )
        shellTaskOrganizer.createRootTask(
            TaskOrganizer.CreateRootTaskRequest()
                .setName("MinimizedDesk_$deskId")
@@ -723,7 +735,11 @@ class RootTaskDesksOrganizer(
        val onCreateCallback: OnCreateCallback,
    )

    private data class CreateDeskMinimizationRootRequest(val displayId: Int, val deskId: Int)
    private data class CreateDeskMinimizationRootRequest(
        val displayId: Int,
        val deskId: Int,
        val callback: OnCreateCallback,
    )

    private fun logD(msg: String, vararg arguments: Any?) {
        ProtoLog.d(WM_SHELL_DESKTOP_MODE, "%s: $msg", TAG, *arguments)
Loading