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

Commit 08335ccd authored by mattsziklay's avatar mattsziklay Committed by Matt Sziklay
Browse files

Persist desktops on external displays.

Stores uniqueDisplayId in DesktopPersistentRepository so when the
repository is initialized, the restored desks can be added to
repositories on displays other than the default.

Adds a method to DisplayController to search for a Display by uniqueId
to accomplish this.

Additionally updates instances of wct.launchTask to add appropriate
displayId to the ActivityOptions to ensure background tasks are not
launched on default display.

Bug: 427777565
Test: Manual; make desks on multiple displays and reboot; confirm desks
appear in correct display in overview.
Flag: com.android.window.flags.enable_display_reconnect_interaction
Change-Id: I638453b4ba0bf42781676c1e3d172d0dbbbe327d

Change-Id: Ib0d9cc090e8b3dbda1bf5c8164775c3d8815ad3f
parent 6f932682
Loading
Loading
Loading
Loading
+35 −0
Original line number Diff line number Diff line
@@ -46,7 +46,9 @@ import com.android.wm.shell.shared.desktopmode.DesktopState;
import com.android.wm.shell.sysui.ShellInit;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;

/**
@@ -114,6 +116,30 @@ public class DisplayController {
        return mDisplayManager.getDisplay(displayId);
    }

    /**
     * Gets the uniqueId associated with the provided displayId, if it is associated with one.
     */
    @Nullable
    public String getDisplayUniqueId(int displayId) {
        final DisplayRecord r = mDisplays.get(displayId);
        return r != null ? r.mUniqueId : null;
    }

    /**
     * Gets a map of all displays by uniqueId from DisplayManager.
     */
    @Nullable
    public Map<String, Integer> getAllDisplaysByUniqueId() {
        HashMap<String, Integer> map = new HashMap<>();
        for (int i = 0; i < mDisplays.size(); i++) {
            final String uniqueId = mDisplays.valueAt(i).mUniqueId;
            if (uniqueId != null) {
                map.put(uniqueId, mDisplays.keyAt(i));
            }
        }
        return map;
    }

    /**
     * Returns true if the display with the given displayId is part of the topology.
     */
@@ -218,6 +244,10 @@ public class DisplayController {
            final DisplayRecord record = new DisplayRecord(displayId, hasStatusAndNavBars);
            DisplayLayout displayLayout = record.createLayout(context, display);
            record.setDisplayLayout(context, displayLayout);
            final String uniqueId = display.getUniqueId();
            if (uniqueId != null) {
                record.setUniqueId(uniqueId);
            }
            mDisplays.put(displayId, record);
            for (int i = 0; i < mDisplayChangedListeners.size(); ++i) {
                mDisplayChangedListeners.get(i).onDisplayAdded(displayId);
@@ -383,6 +413,7 @@ public class DisplayController {

    private class DisplayRecord {
        private final int mDisplayId;
        private String mUniqueId;
        private Context mContext;
        private DisplayLayout mDisplayLayout;
        private InsetsState mInsetsState = new InsetsState();
@@ -428,6 +459,10 @@ public class DisplayController {
            mDisplayLayout.setInsets(mContext.getResources(), mInsetsState);
        }

        private void setUniqueId(String uniqueId) {
            mUniqueId = uniqueId;
        }

        private void setInsets(InsetsState state) {
            mInsetsState = state;
            mDisplayLayout.setInsets(mContext.getResources(), state);
+3 −2
Original line number Diff line number Diff line
@@ -1781,9 +1781,10 @@ public abstract class WMShellModule {
            DesktopPersistentRepository desktopPersistentRepository,
            @ShellMainThread CoroutineScope mainScope,
            DesktopConfig desktopConfig,
            DesktopState desktopState) {
            DesktopState desktopState,
            DisplayController displayController) {
        return new DesktopRepositoryInitializerImpl(context, desktopPersistentRepository,
                mainScope, desktopConfig, desktopState);
                mainScope, desktopConfig, desktopState, displayController);
    }

    @WMSingleton
+24 −7
Original line number Diff line number Diff line
@@ -620,7 +620,11 @@ class DesktopTasksController(
            if (deskId == null) {
                logW("Failed to add desk in displayId=%d for userId=%d", displayId, userId)
            } else {
                repository.addDesk(displayId = displayId, deskId = deskId)
                repository.addDesk(
                    displayId = displayId,
                    deskId = deskId,
                    uniqueDisplayId = displayController.getDisplayUniqueId(displayId),
                )
                onResult(deskId)
                if (activateDesk) {
                    activateDesk(deskId = deskId, userId = userId, enterReason = enterReason)
@@ -638,7 +642,11 @@ class DesktopTasksController(
            logW("Failed to add desk in displayId=%d for userId=%d", displayId, userId)
            return null
        }
        repository.addDesk(displayId = displayId, deskId = deskId)
        repository.addDesk(
            displayId = displayId,
            deskId = deskId,
            uniqueDisplayId = displayController.getDisplayUniqueId(displayId),
        )
        return deskId
    }

@@ -748,7 +756,7 @@ class DesktopTasksController(
        destinationDisplayId: Int,
    ): RunOnTransitStart {
        logD(
            "onDisplayDisconnect: disconnectedDisplayId=$disconnectedDisplayId, " +
            "addOnDisplayDisconnectChanges: disconnectedDisplayId=$disconnectedDisplayId, " +
                "destinationDisplayId=$destinationDisplayId"
        )
        val runOnTransitStartList = mutableListOf<RunOnTransitStart>()
@@ -762,7 +770,7 @@ class DesktopTasksController(
        val destDisplayLayout = displayController.getDisplayLayout(destinationDisplayId)
        if (destDisplayLayout == null) {
            logE(
                "onDisplayDisconnect: no display layout found for " +
                "addOnDisplayDisconnectChanges: no display layout found for " +
                    "destinationDisplayId=$destinationDisplayId"
            )
        }
@@ -818,7 +826,11 @@ class DesktopTasksController(
            val deskTasks = desktopRepository.getActiveTaskIdsInDesk(deskId)
            // Remove desk if it's empty.
            if (deskTasks.isEmpty()) {
                logD("onDisplayDisconnect: removing empty desk=%d of user=%d", deskId, userId)
                logD(
                    "handleExtendedModeDisconnect: removing empty desk=%d of user=%d",
                    deskId,
                    userId,
                )
                desksOrganizer.removeDesk(wct, deskId, userId)
                runOnTransitStartList.add { transition ->
                    desksTransitionObserver.addPendingTransition(
@@ -836,7 +848,8 @@ class DesktopTasksController(
                }
            } else {
                logD(
                    "onDisplayDisconnect: reparenting desk=%d to display=%d for user=%d",
                    "handleExtendedModeDisconnect: " +
                        "reparenting desk=%d to display=%d for user=%d",
                    deskId,
                    destinationDisplayId,
                    userId,
@@ -857,6 +870,8 @@ class DesktopTasksController(
                            userId = userId,
                            deskId = deskId,
                            displayId = destinationDisplayId,
                            uniqueDisplayId =
                                displayController.getDisplayUniqueId(destinationDisplayId),
                        )
                    )
                }
@@ -1280,6 +1295,7 @@ class DesktopTasksController(
                .apply {
                    launchWindowingMode = WINDOWING_MODE_FREEFORM
                    launchBounds = getInitialBounds(displayLayout, task, deskId)
                    launchDisplayId = targetDisplayId
                }
                .toBundle(),
        )
@@ -2912,7 +2928,8 @@ class DesktopTasksController(
                    wct.reorder(runningTaskInfo.token, /* onTop= */ true)
                } else if (DesktopModeFlags.ENABLE_DESKTOP_WINDOWING_PERSISTENCE.isTrue()) {
                    // Task is not running, start it
                    wct.startTask(taskId, createActivityOptionsForStartTask().toBundle())
                    val startDesk = repository.getDefaultDeskId(displayId) ?: INVALID_DESK_ID
                    wct.startTask(taskId, createActivityOptionsForStartTask(startDesk).toBundle())
                }
            }

+2 −2
Original line number Diff line number Diff line
@@ -51,10 +51,10 @@ data class Desk(
    var topTransparentFullscreenTaskData: TopTransparentFullscreenTaskData? = null,
    var leftTiledTaskId: Int? = null,
    var rightTiledTaskId: Int? = null,
    // The display's unique id that will remain the same across reboots.
    var uniqueDisplayId: String? = null,
) {
    // TODO: b/417907552 - Add these variables to persistent repository.
    // The display's unique id that will remain the same across reboots.
    var uniqueDisplayId: String? = null
    // Bounds of tasks in this desk mapped to their respective task ids. Used for reconnect.
    var boundsByTaskId: MutableMap<Int, Rect> = mutableMapOf()

+20 −13
Original line number Diff line number Diff line
@@ -254,10 +254,10 @@ class DesktopRepository(
    }

    /** Adds the given desk under the given display. */
    fun addDesk(displayId: Int, deskId: Int) {
    fun addDesk(displayId: Int, deskId: Int, uniqueDisplayId: String? = null) {
        logD("addDesk for displayId=%d and deskId=%d", displayId, deskId)
        val couldCreateDesk = canCreateDesks()
        desktopData.createDesk(displayId, deskId)
        desktopData.createDesk(displayId, deskId, uniqueDisplayId)
        val canCreateDesk = canCreateDesks()
        deskChangeListeners.forEach { (listener, executor) ->
            executor.execute {
@@ -270,12 +270,13 @@ class DesktopRepository(
    }

    /** Update the data to reflect a desk changing displays. */
    fun onDeskDisplayChanged(deskId: Int, newDisplayId: Int) {
    fun onDeskDisplayChanged(deskId: Int, newDisplayId: Int, newUniqueDisplayId: String?) {
        val couldCreateDesk = canCreateDesks()
        val desk =
            desktopData.getDesk(deskId)?.deepCopy()
                ?: error("Expected to find desk with id: $deskId")
        desk.displayId = newDisplayId
        desk.uniqueDisplayId = newUniqueDisplayId
        // TODO: b/412484513 - consider de-duping unnecessary updates to listeners, such as the one
        //  made here by |removeDesk| that will be reverted at the end of this method.
        removeDesk(deskId)
@@ -1231,12 +1232,13 @@ class DesktopRepository(
        "Use updatePersistentRepository() instead.",
        ReplaceWith("updatePersistentRepository()"),
    )
    private suspend fun updatePersistentRepositoryForDesk(desk: Desk) =
    private suspend fun updatePersistentRepositoryForDesk(desk: Desk): Unit =
        traceSection("DesktopRepository#updatePersistentRepositoryForDesk") {
            try {
                persistentRepository.addOrUpdateDesktop(
                    userId = userId,
                    desktopId = desk.deskId,
                    uniqueDisplayId = desk.uniqueDisplayId,
                    visibleTasks = desk.visibleTasks,
                    minimizedTasks = desk.minimizedTasks,
                    freeformTasksInZOrder = desk.freeformTasksInZOrder,
@@ -1353,7 +1355,7 @@ class DesktopRepository(
    /** An interface for the desktop hierarchy's data managed by this repository. */
    private interface DesktopData {
        /** Creates a desk record. */
        fun createDesk(displayId: Int, deskId: Int)
        fun createDesk(displayId: Int, deskId: Int, uniqueDisplayId: String?)

        /** Adds an existing desk to a specific display */
        fun addDesk(displayId: Int, desk: Desk)
@@ -1428,16 +1430,19 @@ class DesktopRepository(
        private val deskByDisplayId =
            object : SparseArray<Desk>() {
                /** Gets [Desk] for existing [displayId] or creates a new one. */
                fun getOrCreate(displayId: Int): Desk =
                fun getOrCreate(displayId: Int, uniqueDisplayId: String? = null): Desk =
                    this[displayId]
                        ?: Desk(deskId = displayId, displayId = displayId).also {
                            this[displayId] = it
                        }
                        ?: Desk(
                                deskId = displayId,
                                displayId = displayId,
                                uniqueDisplayId = uniqueDisplayId,
                            )
                            .also { this[displayId] = it }
            }

        override fun createDesk(displayId: Int, deskId: Int) {
        override fun createDesk(displayId: Int, deskId: Int, uniqueDisplayId: String?) {
            check(displayId == deskId) { "Display and desk ids must match" }
            deskByDisplayId.getOrCreate(displayId)
            deskByDisplayId.getOrCreate(displayId, uniqueDisplayId)
        }

        override fun addDesk(displayId: Int, desk: Desk) {
@@ -1513,14 +1518,16 @@ class DesktopRepository(
    private class MultiDesktopData : DesktopData {
        private val desktopDisplays = SparseArray<DesktopDisplay>()

        override fun createDesk(displayId: Int, deskId: Int) {
        override fun createDesk(displayId: Int, deskId: Int, uniqueDisplayId: String?) {
            val display =
                desktopDisplays[displayId]
                    ?: DesktopDisplay(displayId).also { desktopDisplays[displayId] = it }
            check(display.orderedDesks.none { desk -> desk.deskId == deskId }) {
                "Attempting to create desk#$deskId that already exists in display#$displayId"
            }
            display.orderedDesks.add(Desk(deskId = deskId, displayId = displayId))
            display.orderedDesks.add(
                Desk(deskId = deskId, displayId = displayId, uniqueDisplayId = uniqueDisplayId)
            )
        }

        override fun addDesk(displayId: Int, desk: Desk) {
Loading