Loading libs/WindowManager/Shell/src/com/android/wm/shell/common/DisplayController.java +14 −0 Original line number Diff line number Diff line Loading @@ -17,6 +17,7 @@ package com.android.wm.shell.common; import static android.app.WindowConfiguration.ROTATION_UNDEFINED; import static android.view.Display.INVALID_DISPLAY; import android.annotation.NonNull; import android.annotation.Nullable; Loading Loading @@ -125,6 +126,19 @@ public class DisplayController { return r != null ? r.mUniqueId : null; } /** * Gets the displayId associated with the provided uniqueId, if it is associated with one. * Because this calls an IPC, we should only use this in time sensitive cases where we suspect * DisplayManager has more up to date information than mDisplays (i.e., during reboot). For * other cases, use getAllDisplaysByUniqueId below. */ public int getDisplayIdByUniqueIdBlocking(String uniqueId) { for (Display display : mDisplayManager.getDisplays()) { if (uniqueId.equals(display.getUniqueId())) return display.getDisplayId(); } return INVALID_DISPLAY; } /** * Gets a map of all displays by uniqueId from DisplayManager. */ Loading libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopDisplayEventHandler.kt +8 −6 Original line number Diff line number Diff line Loading @@ -126,8 +126,6 @@ class DesktopDisplayEventHandler( // `displayId`. desktopDisplayModeController.updateDefaultDisplayWindowingMode() if (DesktopExperienceFlags.ENABLE_DISPLAY_RECONNECT_INTERACTION.isTrue) { // TODO - b/365873835: Restore a display if a uniqueId match is found in // the desktop repository. displayController.getDisplay(displayId)?.uniqueId?.let { uniqueId -> uniqueIdByDisplayId[displayId] = uniqueId } Loading Loading @@ -209,13 +207,17 @@ class DesktopDisplayEventHandler( return false } if (uniqueDisplayId in displaysMidRestoration) { logV("handlePotentialReconnect: uniqueDisplay=$uniqueDisplayId " + "mid-restoration; aborting.") logV( "handlePotentialReconnect: uniqueDisplay=$uniqueDisplayId " + "mid-restoration; aborting." ) return false } if (!currentUserRepository.hasPreservedDisplayForUniqueDisplayId(uniqueDisplayId)) { logV("handlePotentialReconnect: No preserved display found for " + "uniqueDisplayId=$uniqueDisplayId; aborting.") logV( "handlePotentialReconnect: No preserved display found for " + "uniqueDisplayId=$uniqueDisplayId; aborting." ) } val preservedTasks = currentUserRepository.getPreservedTasks(uniqueDisplayId).toMutableList() Loading libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopTasksController.kt +9 −4 Original line number Diff line number Diff line Loading @@ -797,7 +797,6 @@ class DesktopTasksController( val wct = WindowContainerTransaction() addOnDisplayDisconnectChanges(wct, disconnectedDisplayId, destinationDisplayId) .invoke(transition) try { userRepositories.current.getExpandedTasksOrdered(disconnectedDisplayId).forEach { logD("addOnDisplayDisconnect: taking a snapshot of=$it before disconnect") Loading Loading @@ -878,15 +877,21 @@ class DesktopTasksController( occluded: Boolean, animatingDismiss: Boolean, ) { logD( "onKeyguardVisibilityChanged visible=%b, occluded=%b, animatingDismiss=%b", visible, occluded, animatingDismiss, ) 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, displayId = displayIdByUniqueId.value, uniqueDisplayId = displayIdByUniqueId.key, userId = taskRepository.userId, ) } } Loading libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/data/Desk.kt +2 −0 Original line number Diff line number Diff line Loading @@ -53,6 +53,8 @@ data class Desk( var rightTiledTaskId: Int? = null, // The display's unique id that will remain the same across reboots. var uniqueDisplayId: String? = null, // A desk that will only exist briefly; remove it once it is preserved. Used for persistence. var transientDesk: Boolean = false, ) { // TODO: b/417907552 - Add these variables to persistent repository. // Bounds of tasks in this desk mapped to their respective task ids. Used for reconnect. Loading libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/data/DesktopRepository.kt +91 −19 Original line number Diff line number Diff line Loading @@ -132,15 +132,40 @@ class DesktopRepository( } /** Stores the last state of the given display, along with the bounds of the tasks on it. */ fun preserveDisplay(displayId: Int, uniqueId: String) { logD("preserveDisplay for displayId=%d, uniqueId=%s", displayId, uniqueId) fun preserveDisplay(displayId: Int, uniqueDisplayId: String) { logD("preserveDisplay for displayId=%d, uniqueId=%s", displayId, uniqueDisplayId) if ( preservedDisplaysByUniqueId.containsKey(uniqueDisplayId) && DesktopExperienceFlags.ENABLE_EXTERNAL_DISPLAY_PERSISTENCE_BUGFIX.isTrue ) { // Prevents multiple preserve requests from overwriting the previously // preserved display. Occurs during boot where we see display disabled // + display becoming desktop ineligible both requesting preserve. logD("Display already preserved; aborting.") return } val orderedDesks = desktopData.getOrderedDesks(displayId) // Do not preserve the display if there are no active tasks on it. if (!orderedDesks.any { it.activeTasks.isNotEmpty() }) return val preservedDisplay = DesktopDisplay(displayId) val preservedDisplay = DesktopDisplay(INVALID_DISPLAY) orderedDesks.mapTo(preservedDisplay.orderedDesks) { it.deepCopy() } preservedDisplay.activeDeskId = desktopData.getActiveDesk(displayId)?.deskId preservedDisplaysByUniqueId[uniqueId] = preservedDisplay preservedDisplaysByUniqueId[uniqueDisplayId] = preservedDisplay } /** Stores the last state of a single desk, creating a new PreservedDisplay if needed. */ fun preserveDesk(deskId: Int, uniqueDisplayId: String) { logD("preserveDesk for deskId=%d, uniqueDisplayId=%s", deskId, uniqueDisplayId) val desk = desktopData.getDesk(deskId) ?: return if (desk.activeTasks.isEmpty()) return val preservedDisplay = preservedDisplaysByUniqueId[uniqueDisplayId] ?: DesktopDisplay(INVALID_DISPLAY).also { preservedDisplaysByUniqueId[uniqueDisplayId] = it } preservedDisplay.orderedDesks.add(desk) // The transient desk is preserved and has served its purpose, it can be removed now. if (desk.transientDesk) removeDesk(deskId) } /** Removes the specified preserved display. */ Loading Loading @@ -261,10 +286,19 @@ class DesktopRepository( } /** Adds the given desk under the given display. */ fun addDesk(displayId: Int, deskId: Int, uniqueDisplayId: String? = null) { // TODO: b/441764871 - Extract transientDesk logic into desk-creating vs desk-saving functions. // To avoid ifs in order to dodge listener execution on transient desks, we should create // the desk fully before deciding to either commit it to DesktopData or preserve it. fun addDesk( displayId: Int, deskId: Int, uniqueDisplayId: String? = null, transientDesk: Boolean = false, ) { logD("addDesk for displayId=%d and deskId=%d", displayId, deskId) val couldCreateDesk = canCreateDesks() desktopData.createDesk(displayId, deskId, uniqueDisplayId) desktopData.createDesk(displayId, deskId, uniqueDisplayId, transientDesk) if (transientDesk) return val canCreateDesk = canCreateDesks() deskChangeListeners.forEach { (listener, executor) -> executor.execute { Loading Loading @@ -364,6 +398,7 @@ class DesktopRepository( return } desktopData.setActiveDesk(displayId = displayId, deskId = deskId) if (desktopData.getDesk(deskId)?.transientDesk == true) return deskChangeListeners.forEach { (listener, executor) -> executor.execute { listener.onActiveDeskChanged( Loading Loading @@ -404,7 +439,7 @@ class DesktopRepository( ) val desk = checkNotNull(desktopData.getDesk(deskId)) { "Did not find desk: $deskId" } desk.leftTiledTaskId = taskId if (DesktopModeFlags.ENABLE_DESKTOP_WINDOWING_PERSISTENCE.isTrue) { if (!desk.transientDesk && DesktopModeFlags.ENABLE_DESKTOP_WINDOWING_PERSISTENCE.isTrue) { if (DesktopExperienceFlags.REPOSITORY_BASED_PERSISTENCE.isTrue) { updatePersistentRepository(displayId) } else { Loading @@ -422,7 +457,7 @@ class DesktopRepository( ) val desk = checkNotNull(desktopData.getDesk(deskId)) { "Did not find desk: $deskId" } desk.rightTiledTaskId = taskId if (DesktopModeFlags.ENABLE_DESKTOP_WINDOWING_PERSISTENCE.isTrue) { if (!desk.transientDesk && DesktopModeFlags.ENABLE_DESKTOP_WINDOWING_PERSISTENCE.isTrue) { if (DesktopExperienceFlags.REPOSITORY_BASED_PERSISTENCE.isTrue) { updatePersistentRepository(displayId) } else { Loading Loading @@ -538,8 +573,8 @@ class DesktopRepository( // Removes task if it is active on another desk excluding this desk. removeActiveTask(taskId, excludedDeskId = deskId) if (desk.activeTasks.add(taskId)) { if (desk.transientDesk) return updateActiveTasksListeners(displayId) } else { logD("Active task=%d already added, displayId=%d, deskId=%d", taskId, displayId, deskId) Loading @@ -562,7 +597,7 @@ class DesktopRepository( desk.displayId, desk.deskId, ) affectedDisplays.add(desk.displayId) if (!desk.transientDesk) affectedDisplays.add(desk.displayId) } } affectedDisplays.forEach { displayId -> updateActiveTasksListeners(displayId) } Loading Loading @@ -830,6 +865,7 @@ class DesktopRepository( desk.visibleTasks.remove(taskId) } taskBounds?.let { desk.boundsByTaskId[taskId] = it } if (desk.transientDesk) return val newCount = getVisibleTaskCountInDesk(deskId) if (prevCount != newCount) { logD( Loading Loading @@ -972,6 +1008,7 @@ class DesktopRepository( } desk.freeformTasksInZOrder.add(0, taskId) if (!bounds.isEmpty) desk.boundsByTaskId[taskId] = bounds if (desk.transientDesk) return if (DesktopModeFlags.ENABLE_DESKTOP_WINDOWING_PERSISTENCE.isTrue) { // TODO: can probably just update the desk. updatePersistentRepository(displayId) Loading Loading @@ -1003,9 +1040,11 @@ class DesktopRepository( /** Minimizes the task in its desk. */ fun minimizeTaskInDesk(displayId: Int, deskId: Int, taskId: Int) { logD("MinimizeTaskInDesk: displayId=%d deskId=%d, task=%d", displayId, deskId, taskId) desktopData.getDesk(deskId)?.minimizedTasks?.add(taskId) val desk = desktopData.getDesk(deskId) desk?.minimizedTasks?.add(taskId) ?: logD("Minimize task: No active desk found for task: taskId=%d", taskId) updateTaskInDesk(displayId, deskId, taskId, isVisible = false, taskBounds = null) if (desk?.transientDesk == true) return if (DesktopModeFlags.ENABLE_DESKTOP_WINDOWING_PERSISTENCE.isTrue) { if (DesktopExperienceFlags.REPOSITORY_BASED_PERSISTENCE.isTrue) { updatePersistentRepository(displayId) Loading Loading @@ -1086,7 +1125,7 @@ class DesktopRepository( setTaskInFullImmersiveStateInDesk(deskId = deskId, taskId = taskId, immersive = false) removeActiveTaskFromDesk(deskId = deskId, taskId = taskId) removeVisibleTaskFromDesk(deskId = deskId, taskId = taskId) if (DesktopModeFlags.ENABLE_DESKTOP_WINDOWING_PERSISTENCE.isTrue) { if (!desk.transientDesk && DesktopModeFlags.ENABLE_DESKTOP_WINDOWING_PERSISTENCE.isTrue) { if (DesktopExperienceFlags.REPOSITORY_BASED_PERSISTENCE.isTrue) { updatePersistentRepository(desk.displayId) } else { Loading @@ -1107,6 +1146,10 @@ class DesktopRepository( val wasActive = desktopData.getActiveDesk(desk.displayId)?.deskId == desk.deskId val activeTasks = ArraySet(desk.activeTasks) desktopData.remove(desk.deskId) if (desk.transientDesk) { // No need to inform listeners; just return active tasks. return activeTasks } val canCreateDesks = canCreateDesks() notifyVisibleTaskListeners(desk.displayId, getVisibleTaskCount(displayId = desk.displayId)) deskChangeListeners.forEach { (listener, executor) -> Loading Loading @@ -1220,7 +1263,11 @@ class DesktopRepository( Trace.beginSection("DesktopRepository#UpdateRepoWork") logD("updatePersistentRepository user=%d display=%d", userId, displayId) try { persistentRepository.addOrUpdateRepository(userId, desks) persistentRepository.addOrUpdateRepository( userId, desks, getActiveDeskId(displayId), ) } catch (exception: Exception) { logE( "An exception occurred while updating the persistent repository \n%s", Loading Loading @@ -1374,7 +1421,12 @@ 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, uniqueDisplayId: String?) fun createDesk( displayId: Int, deskId: Int, uniqueDisplayId: String?, transientDesk: Boolean, ) /** Adds an existing desk to a specific display */ fun addDesk(displayId: Int, desk: Desk) Loading Loading @@ -1449,19 +1501,29 @@ class DesktopRepository( private val deskByDisplayId = object : SparseArray<Desk>() { /** Gets [Desk] for existing [displayId] or creates a new one. */ fun getOrCreate(displayId: Int, uniqueDisplayId: String? = null): Desk = fun getOrCreate( displayId: Int, uniqueDisplayId: String? = null, transientDesk: Boolean = false, ): Desk = this[displayId] ?: Desk( deskId = displayId, displayId = displayId, uniqueDisplayId = uniqueDisplayId, transientDesk = transientDesk, ) .also { this[displayId] = it } } override fun createDesk(displayId: Int, deskId: Int, uniqueDisplayId: String?) { override fun createDesk( displayId: Int, deskId: Int, uniqueDisplayId: String?, transientDesk: Boolean, ) { check(displayId == deskId) { "Display and desk ids must match" } deskByDisplayId.getOrCreate(displayId, uniqueDisplayId) deskByDisplayId.getOrCreate(displayId, uniqueDisplayId, transientDesk) } override fun addDesk(displayId: Int, desk: Desk) { Loading Loading @@ -1537,7 +1599,12 @@ class DesktopRepository( private class MultiDesktopData : DesktopData { private val desktopDisplays = SparseArray<DesktopDisplay>() override fun createDesk(displayId: Int, deskId: Int, uniqueDisplayId: String?) { override fun createDesk( displayId: Int, deskId: Int, uniqueDisplayId: String?, transientDesk: Boolean, ) { val display = desktopDisplays[displayId] ?: DesktopDisplay(displayId).also { desktopDisplays[displayId] = it } Loading @@ -1545,7 +1612,12 @@ class DesktopRepository( "Attempting to create desk#$deskId that already exists in display#$displayId" } display.orderedDesks.add( Desk(deskId = deskId, displayId = displayId, uniqueDisplayId = uniqueDisplayId) Desk( deskId = deskId, displayId = displayId, uniqueDisplayId = uniqueDisplayId, transientDesk = transientDesk, ) ) } Loading Loading
libs/WindowManager/Shell/src/com/android/wm/shell/common/DisplayController.java +14 −0 Original line number Diff line number Diff line Loading @@ -17,6 +17,7 @@ package com.android.wm.shell.common; import static android.app.WindowConfiguration.ROTATION_UNDEFINED; import static android.view.Display.INVALID_DISPLAY; import android.annotation.NonNull; import android.annotation.Nullable; Loading Loading @@ -125,6 +126,19 @@ public class DisplayController { return r != null ? r.mUniqueId : null; } /** * Gets the displayId associated with the provided uniqueId, if it is associated with one. * Because this calls an IPC, we should only use this in time sensitive cases where we suspect * DisplayManager has more up to date information than mDisplays (i.e., during reboot). For * other cases, use getAllDisplaysByUniqueId below. */ public int getDisplayIdByUniqueIdBlocking(String uniqueId) { for (Display display : mDisplayManager.getDisplays()) { if (uniqueId.equals(display.getUniqueId())) return display.getDisplayId(); } return INVALID_DISPLAY; } /** * Gets a map of all displays by uniqueId from DisplayManager. */ Loading
libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopDisplayEventHandler.kt +8 −6 Original line number Diff line number Diff line Loading @@ -126,8 +126,6 @@ class DesktopDisplayEventHandler( // `displayId`. desktopDisplayModeController.updateDefaultDisplayWindowingMode() if (DesktopExperienceFlags.ENABLE_DISPLAY_RECONNECT_INTERACTION.isTrue) { // TODO - b/365873835: Restore a display if a uniqueId match is found in // the desktop repository. displayController.getDisplay(displayId)?.uniqueId?.let { uniqueId -> uniqueIdByDisplayId[displayId] = uniqueId } Loading Loading @@ -209,13 +207,17 @@ class DesktopDisplayEventHandler( return false } if (uniqueDisplayId in displaysMidRestoration) { logV("handlePotentialReconnect: uniqueDisplay=$uniqueDisplayId " + "mid-restoration; aborting.") logV( "handlePotentialReconnect: uniqueDisplay=$uniqueDisplayId " + "mid-restoration; aborting." ) return false } if (!currentUserRepository.hasPreservedDisplayForUniqueDisplayId(uniqueDisplayId)) { logV("handlePotentialReconnect: No preserved display found for " + "uniqueDisplayId=$uniqueDisplayId; aborting.") logV( "handlePotentialReconnect: No preserved display found for " + "uniqueDisplayId=$uniqueDisplayId; aborting." ) } val preservedTasks = currentUserRepository.getPreservedTasks(uniqueDisplayId).toMutableList() Loading
libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopTasksController.kt +9 −4 Original line number Diff line number Diff line Loading @@ -797,7 +797,6 @@ class DesktopTasksController( val wct = WindowContainerTransaction() addOnDisplayDisconnectChanges(wct, disconnectedDisplayId, destinationDisplayId) .invoke(transition) try { userRepositories.current.getExpandedTasksOrdered(disconnectedDisplayId).forEach { logD("addOnDisplayDisconnect: taking a snapshot of=$it before disconnect") Loading Loading @@ -878,15 +877,21 @@ class DesktopTasksController( occluded: Boolean, animatingDismiss: Boolean, ) { logD( "onKeyguardVisibilityChanged visible=%b, occluded=%b, animatingDismiss=%b", visible, occluded, animatingDismiss, ) 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, displayId = displayIdByUniqueId.value, uniqueDisplayId = displayIdByUniqueId.key, userId = taskRepository.userId, ) } } Loading
libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/data/Desk.kt +2 −0 Original line number Diff line number Diff line Loading @@ -53,6 +53,8 @@ data class Desk( var rightTiledTaskId: Int? = null, // The display's unique id that will remain the same across reboots. var uniqueDisplayId: String? = null, // A desk that will only exist briefly; remove it once it is preserved. Used for persistence. var transientDesk: Boolean = false, ) { // TODO: b/417907552 - Add these variables to persistent repository. // Bounds of tasks in this desk mapped to their respective task ids. Used for reconnect. Loading
libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/data/DesktopRepository.kt +91 −19 Original line number Diff line number Diff line Loading @@ -132,15 +132,40 @@ class DesktopRepository( } /** Stores the last state of the given display, along with the bounds of the tasks on it. */ fun preserveDisplay(displayId: Int, uniqueId: String) { logD("preserveDisplay for displayId=%d, uniqueId=%s", displayId, uniqueId) fun preserveDisplay(displayId: Int, uniqueDisplayId: String) { logD("preserveDisplay for displayId=%d, uniqueId=%s", displayId, uniqueDisplayId) if ( preservedDisplaysByUniqueId.containsKey(uniqueDisplayId) && DesktopExperienceFlags.ENABLE_EXTERNAL_DISPLAY_PERSISTENCE_BUGFIX.isTrue ) { // Prevents multiple preserve requests from overwriting the previously // preserved display. Occurs during boot where we see display disabled // + display becoming desktop ineligible both requesting preserve. logD("Display already preserved; aborting.") return } val orderedDesks = desktopData.getOrderedDesks(displayId) // Do not preserve the display if there are no active tasks on it. if (!orderedDesks.any { it.activeTasks.isNotEmpty() }) return val preservedDisplay = DesktopDisplay(displayId) val preservedDisplay = DesktopDisplay(INVALID_DISPLAY) orderedDesks.mapTo(preservedDisplay.orderedDesks) { it.deepCopy() } preservedDisplay.activeDeskId = desktopData.getActiveDesk(displayId)?.deskId preservedDisplaysByUniqueId[uniqueId] = preservedDisplay preservedDisplaysByUniqueId[uniqueDisplayId] = preservedDisplay } /** Stores the last state of a single desk, creating a new PreservedDisplay if needed. */ fun preserveDesk(deskId: Int, uniqueDisplayId: String) { logD("preserveDesk for deskId=%d, uniqueDisplayId=%s", deskId, uniqueDisplayId) val desk = desktopData.getDesk(deskId) ?: return if (desk.activeTasks.isEmpty()) return val preservedDisplay = preservedDisplaysByUniqueId[uniqueDisplayId] ?: DesktopDisplay(INVALID_DISPLAY).also { preservedDisplaysByUniqueId[uniqueDisplayId] = it } preservedDisplay.orderedDesks.add(desk) // The transient desk is preserved and has served its purpose, it can be removed now. if (desk.transientDesk) removeDesk(deskId) } /** Removes the specified preserved display. */ Loading Loading @@ -261,10 +286,19 @@ class DesktopRepository( } /** Adds the given desk under the given display. */ fun addDesk(displayId: Int, deskId: Int, uniqueDisplayId: String? = null) { // TODO: b/441764871 - Extract transientDesk logic into desk-creating vs desk-saving functions. // To avoid ifs in order to dodge listener execution on transient desks, we should create // the desk fully before deciding to either commit it to DesktopData or preserve it. fun addDesk( displayId: Int, deskId: Int, uniqueDisplayId: String? = null, transientDesk: Boolean = false, ) { logD("addDesk for displayId=%d and deskId=%d", displayId, deskId) val couldCreateDesk = canCreateDesks() desktopData.createDesk(displayId, deskId, uniqueDisplayId) desktopData.createDesk(displayId, deskId, uniqueDisplayId, transientDesk) if (transientDesk) return val canCreateDesk = canCreateDesks() deskChangeListeners.forEach { (listener, executor) -> executor.execute { Loading Loading @@ -364,6 +398,7 @@ class DesktopRepository( return } desktopData.setActiveDesk(displayId = displayId, deskId = deskId) if (desktopData.getDesk(deskId)?.transientDesk == true) return deskChangeListeners.forEach { (listener, executor) -> executor.execute { listener.onActiveDeskChanged( Loading Loading @@ -404,7 +439,7 @@ class DesktopRepository( ) val desk = checkNotNull(desktopData.getDesk(deskId)) { "Did not find desk: $deskId" } desk.leftTiledTaskId = taskId if (DesktopModeFlags.ENABLE_DESKTOP_WINDOWING_PERSISTENCE.isTrue) { if (!desk.transientDesk && DesktopModeFlags.ENABLE_DESKTOP_WINDOWING_PERSISTENCE.isTrue) { if (DesktopExperienceFlags.REPOSITORY_BASED_PERSISTENCE.isTrue) { updatePersistentRepository(displayId) } else { Loading @@ -422,7 +457,7 @@ class DesktopRepository( ) val desk = checkNotNull(desktopData.getDesk(deskId)) { "Did not find desk: $deskId" } desk.rightTiledTaskId = taskId if (DesktopModeFlags.ENABLE_DESKTOP_WINDOWING_PERSISTENCE.isTrue) { if (!desk.transientDesk && DesktopModeFlags.ENABLE_DESKTOP_WINDOWING_PERSISTENCE.isTrue) { if (DesktopExperienceFlags.REPOSITORY_BASED_PERSISTENCE.isTrue) { updatePersistentRepository(displayId) } else { Loading Loading @@ -538,8 +573,8 @@ class DesktopRepository( // Removes task if it is active on another desk excluding this desk. removeActiveTask(taskId, excludedDeskId = deskId) if (desk.activeTasks.add(taskId)) { if (desk.transientDesk) return updateActiveTasksListeners(displayId) } else { logD("Active task=%d already added, displayId=%d, deskId=%d", taskId, displayId, deskId) Loading @@ -562,7 +597,7 @@ class DesktopRepository( desk.displayId, desk.deskId, ) affectedDisplays.add(desk.displayId) if (!desk.transientDesk) affectedDisplays.add(desk.displayId) } } affectedDisplays.forEach { displayId -> updateActiveTasksListeners(displayId) } Loading Loading @@ -830,6 +865,7 @@ class DesktopRepository( desk.visibleTasks.remove(taskId) } taskBounds?.let { desk.boundsByTaskId[taskId] = it } if (desk.transientDesk) return val newCount = getVisibleTaskCountInDesk(deskId) if (prevCount != newCount) { logD( Loading Loading @@ -972,6 +1008,7 @@ class DesktopRepository( } desk.freeformTasksInZOrder.add(0, taskId) if (!bounds.isEmpty) desk.boundsByTaskId[taskId] = bounds if (desk.transientDesk) return if (DesktopModeFlags.ENABLE_DESKTOP_WINDOWING_PERSISTENCE.isTrue) { // TODO: can probably just update the desk. updatePersistentRepository(displayId) Loading Loading @@ -1003,9 +1040,11 @@ class DesktopRepository( /** Minimizes the task in its desk. */ fun minimizeTaskInDesk(displayId: Int, deskId: Int, taskId: Int) { logD("MinimizeTaskInDesk: displayId=%d deskId=%d, task=%d", displayId, deskId, taskId) desktopData.getDesk(deskId)?.minimizedTasks?.add(taskId) val desk = desktopData.getDesk(deskId) desk?.minimizedTasks?.add(taskId) ?: logD("Minimize task: No active desk found for task: taskId=%d", taskId) updateTaskInDesk(displayId, deskId, taskId, isVisible = false, taskBounds = null) if (desk?.transientDesk == true) return if (DesktopModeFlags.ENABLE_DESKTOP_WINDOWING_PERSISTENCE.isTrue) { if (DesktopExperienceFlags.REPOSITORY_BASED_PERSISTENCE.isTrue) { updatePersistentRepository(displayId) Loading Loading @@ -1086,7 +1125,7 @@ class DesktopRepository( setTaskInFullImmersiveStateInDesk(deskId = deskId, taskId = taskId, immersive = false) removeActiveTaskFromDesk(deskId = deskId, taskId = taskId) removeVisibleTaskFromDesk(deskId = deskId, taskId = taskId) if (DesktopModeFlags.ENABLE_DESKTOP_WINDOWING_PERSISTENCE.isTrue) { if (!desk.transientDesk && DesktopModeFlags.ENABLE_DESKTOP_WINDOWING_PERSISTENCE.isTrue) { if (DesktopExperienceFlags.REPOSITORY_BASED_PERSISTENCE.isTrue) { updatePersistentRepository(desk.displayId) } else { Loading @@ -1107,6 +1146,10 @@ class DesktopRepository( val wasActive = desktopData.getActiveDesk(desk.displayId)?.deskId == desk.deskId val activeTasks = ArraySet(desk.activeTasks) desktopData.remove(desk.deskId) if (desk.transientDesk) { // No need to inform listeners; just return active tasks. return activeTasks } val canCreateDesks = canCreateDesks() notifyVisibleTaskListeners(desk.displayId, getVisibleTaskCount(displayId = desk.displayId)) deskChangeListeners.forEach { (listener, executor) -> Loading Loading @@ -1220,7 +1263,11 @@ class DesktopRepository( Trace.beginSection("DesktopRepository#UpdateRepoWork") logD("updatePersistentRepository user=%d display=%d", userId, displayId) try { persistentRepository.addOrUpdateRepository(userId, desks) persistentRepository.addOrUpdateRepository( userId, desks, getActiveDeskId(displayId), ) } catch (exception: Exception) { logE( "An exception occurred while updating the persistent repository \n%s", Loading Loading @@ -1374,7 +1421,12 @@ 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, uniqueDisplayId: String?) fun createDesk( displayId: Int, deskId: Int, uniqueDisplayId: String?, transientDesk: Boolean, ) /** Adds an existing desk to a specific display */ fun addDesk(displayId: Int, desk: Desk) Loading Loading @@ -1449,19 +1501,29 @@ class DesktopRepository( private val deskByDisplayId = object : SparseArray<Desk>() { /** Gets [Desk] for existing [displayId] or creates a new one. */ fun getOrCreate(displayId: Int, uniqueDisplayId: String? = null): Desk = fun getOrCreate( displayId: Int, uniqueDisplayId: String? = null, transientDesk: Boolean = false, ): Desk = this[displayId] ?: Desk( deskId = displayId, displayId = displayId, uniqueDisplayId = uniqueDisplayId, transientDesk = transientDesk, ) .also { this[displayId] = it } } override fun createDesk(displayId: Int, deskId: Int, uniqueDisplayId: String?) { override fun createDesk( displayId: Int, deskId: Int, uniqueDisplayId: String?, transientDesk: Boolean, ) { check(displayId == deskId) { "Display and desk ids must match" } deskByDisplayId.getOrCreate(displayId, uniqueDisplayId) deskByDisplayId.getOrCreate(displayId, uniqueDisplayId, transientDesk) } override fun addDesk(displayId: Int, desk: Desk) { Loading Loading @@ -1537,7 +1599,12 @@ class DesktopRepository( private class MultiDesktopData : DesktopData { private val desktopDisplays = SparseArray<DesktopDisplay>() override fun createDesk(displayId: Int, deskId: Int, uniqueDisplayId: String?) { override fun createDesk( displayId: Int, deskId: Int, uniqueDisplayId: String?, transientDesk: Boolean, ) { val display = desktopDisplays[displayId] ?: DesktopDisplay(displayId).also { desktopDisplays[displayId] = it } Loading @@ -1545,7 +1612,12 @@ class DesktopRepository( "Attempting to create desk#$deskId that already exists in display#$displayId" } display.orderedDesks.add( Desk(deskId = deskId, displayId = displayId, uniqueDisplayId = uniqueDisplayId) Desk( deskId = deskId, displayId = displayId, uniqueDisplayId = uniqueDisplayId, transientDesk = transientDesk, ) ) } Loading