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

Commit 5019ad22 authored by Jorge Gil's avatar Jorge Gil Committed by Android (Google) Code Review
Browse files

Merge changes I05ef9baf,Idf38fef3 into main

* changes:
  [40/N] Desks: Fix failing WMShellUnitTests
  [39/N] Desks: Restore persisted desks on reboot
parents 7e668500 a8792453
Loading
Loading
Loading
Loading
+7 −1
Original line number Diff line number Diff line
@@ -759,6 +759,7 @@ public abstract class WMShellModule {
            ToggleResizeDesktopTaskTransitionHandler toggleResizeDesktopTaskTransitionHandler,
            DragToDesktopTransitionHandler dragToDesktopTransitionHandler,
            @DynamicOverride DesktopUserRepositories desktopUserRepositories,
            DesktopRepositoryInitializer desktopRepositoryInitializer,
            Optional<DesktopImmersiveController> desktopImmersiveController,
            DesktopModeLoggerTransitionObserver desktopModeLoggerTransitionObserver,
            LaunchAdjacentController launchAdjacentController,
@@ -805,6 +806,7 @@ public abstract class WMShellModule {
                dragToDesktopTransitionHandler,
                desktopImmersiveController.get(),
                desktopUserRepositories,
                desktopRepositoryInitializer,
                recentsTransitionHandler,
                multiInstanceHelper,
                mainExecutor,
@@ -1313,10 +1315,12 @@ public abstract class WMShellModule {
    static Optional<DesktopDisplayEventHandler> provideDesktopDisplayEventHandler(
            Context context,
            ShellInit shellInit,
            @ShellMainThread CoroutineScope mainScope,
            DisplayController displayController,
            Optional<DesktopUserRepositories> desktopUserRepositories,
            Optional<DesktopTasksController> desktopTasksController,
            Optional<DesktopDisplayModeController> desktopDisplayModeController
            Optional<DesktopDisplayModeController> desktopDisplayModeController,
            DesktopRepositoryInitializer desktopRepositoryInitializer
    ) {
        if (!DesktopModeStatus.canEnterDesktopMode(context)) {
            return Optional.empty();
@@ -1325,7 +1329,9 @@ public abstract class WMShellModule {
                new DesktopDisplayEventHandler(
                        context,
                        shellInit,
                        mainScope,
                        displayController,
                        desktopRepositoryInitializer,
                        desktopUserRepositories.get(),
                        desktopTasksController.get(),
                        desktopDisplayModeController.get()));
+19 −9
Original line number Diff line number Diff line
@@ -23,15 +23,21 @@ import com.android.internal.protolog.ProtoLog
import com.android.wm.shell.common.DisplayController
import com.android.wm.shell.common.DisplayController.OnDisplaysChangedListener
import com.android.wm.shell.desktopmode.multidesks.OnDeskRemovedListener
import com.android.wm.shell.desktopmode.persistence.DesktopRepositoryInitializer
import com.android.wm.shell.protolog.ShellProtoLogGroup.WM_SHELL_DESKTOP_MODE
import com.android.wm.shell.shared.desktopmode.DesktopModeStatus
import com.android.wm.shell.sysui.ShellInit
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.cancel
import kotlinx.coroutines.launch

/** Handles display events in desktop mode */
class DesktopDisplayEventHandler(
    private val context: Context,
    shellInit: ShellInit,
    private val mainScope: CoroutineScope,
    private val displayController: DisplayController,
    private val desktopRepositoryInitializer: DesktopRepositoryInitializer,
    private val desktopUserRepositories: DesktopUserRepositories,
    private val desktopTasksController: DesktopTasksController,
    private val desktopDisplayModeController: DesktopDisplayModeController,
@@ -61,15 +67,19 @@ class DesktopDisplayEventHandler(
            logV("Display #$displayId does not support desks")
            return
        }

        mainScope.launch {
            desktopRepositoryInitializer.isInitialized.collect { initialized ->
                if (!initialized) return@collect
                if (desktopRepository.getNumberOfDesks(displayId) == 0) {
                    logV("Creating new desk in new display#$displayId")
        // TODO: b/362720497 - when SystemUI crashes with a freeform task open for any reason, the
        //  task is recreated and received in [FreeformTaskListener] before this display callback
        //  is invoked, which results in the repository trying to add the task to a desk before the
        //  desk has been recreated here, which may result in a crash-loop if the repository is
        //  checking that the desk exists before adding a task to it. See b/391984373.
                    // TODO: b/393978539 - consider activating the desk on creation when
                    //  applicable, such as for connected displays.
                    desktopTasksController.createDesk(displayId)
        // TODO: b/393978539 - consider activating the desk on creation when applicable, such as
        //  for connected displays.
                }
                cancel()
            }
        }
    }

    override fun onDisplayRemoved(displayId: Int) {
+30 −3
Original line number Diff line number Diff line
@@ -716,12 +716,15 @@ class DesktopRepository(
    }

    /**
     * Returns the top transparent fullscreen task id for a given display's active desk, or null.
     * Returns the top transparent fullscreen task id for a given display, or null.
     *
     * TODO: b/389960283 - add explicit [deskId] argument.
     */
    fun getTopTransparentFullscreenTaskId(displayId: Int): Int? =
        desktopData.getActiveDesk(displayId)?.topTransparentFullscreenTaskId
        desktopData
            .desksSequence(displayId)
            .mapNotNull { it.topTransparentFullscreenTaskId }
            .firstOrNull()

    /**
     * Clears the top transparent fullscreen task id info for a given display's active desk.
@@ -818,7 +821,6 @@ class DesktopRepository(
    }

    /** Minimizes the task in its desk. */
    @VisibleForTesting
    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)
@@ -933,6 +935,12 @@ class DesktopRepository(
                listener.onDeskRemoved(displayId = desk.displayId, deskId = desk.deskId)
            }
        }
        if (
            DesktopModeFlags.ENABLE_DESKTOP_WINDOWING_PERSISTENCE.isTrue &&
                DesktopExperienceFlags.ENABLE_MULTIPLE_DESKTOPS_BACKEND.isTrue
        ) {
            removeDeskFromPersistentRepository(desk)
        }
        return activeTasks
    }

@@ -1031,6 +1039,24 @@ class DesktopRepository(
        }
    }

    private fun removeDeskFromPersistentRepository(desk: Desk) {
        mainCoroutineScope.launch {
            try {
                logD(
                    "updatePersistentRepositoryForRemovedDesk user=%d desk=%d",
                    userId,
                    desk.deskId,
                )
                persistentRepository.removeDesktop(userId = userId, desktopId = desk.deskId)
            } catch (throwable: Throwable) {
                logE(
                    "An exception occurred while updating the persistent repository \n%s",
                    throwable.stackTrace,
                )
            }
        }
    }

    internal fun dump(pw: PrintWriter, prefix: String) {
        val innerPrefix = "$prefix  "
        pw.println("${prefix}DesktopRepository")
@@ -1049,6 +1075,7 @@ class DesktopRepository(
            }
            .forEach { (displayId, activeDeskId, desks) ->
                pw.println("${prefix}Display #$displayId:")
                pw.println("${innerPrefix}numOfDesks=${desks.size}")
                pw.println("${innerPrefix}activeDesk=$activeDeskId")
                pw.println("${innerPrefix}desks:")
                val desksPrefix = "$innerPrefix  "
+38 −12
Original line number Diff line number Diff line
@@ -115,6 +115,9 @@ import com.android.wm.shell.desktopmode.multidesks.DeskTransition
import com.android.wm.shell.desktopmode.multidesks.DesksOrganizer
import com.android.wm.shell.desktopmode.multidesks.DesksTransitionObserver
import com.android.wm.shell.desktopmode.multidesks.OnDeskRemovedListener
import com.android.wm.shell.desktopmode.multidesks.createDesk
import com.android.wm.shell.desktopmode.persistence.DesktopRepositoryInitializer
import com.android.wm.shell.desktopmode.persistence.DesktopRepositoryInitializer.DeskRecreationFactory
import com.android.wm.shell.draganddrop.DragAndDropController
import com.android.wm.shell.freeform.FreeformTaskTransitionStarter
import com.android.wm.shell.protolog.ShellProtoLogGroup.WM_SHELL_DESKTOP_MODE
@@ -194,6 +197,7 @@ class DesktopTasksController(
    private val dragToDesktopTransitionHandler: DragToDesktopTransitionHandler,
    private val desktopImmersiveController: DesktopImmersiveController,
    private val userRepositories: DesktopUserRepositories,
    desktopRepositoryInitializer: DesktopRepositoryInitializer,
    private val recentsTransitionHandler: RecentsTransitionHandler,
    private val multiInstanceHelper: MultiInstanceHelper,
    @ShellMainThread private val mainExecutor: ShellExecutor,
@@ -276,6 +280,19 @@ class DesktopTasksController(
        }
        userId = ActivityManager.getCurrentUser()
        taskRepository = userRepositories.getProfile(userId)

        if (DesktopExperienceFlags.ENABLE_MULTIPLE_DESKTOPS_BACKEND.isTrue) {
            desktopRepositoryInitializer.deskRecreationFactory =
                DeskRecreationFactory { deskUserId, destinationDisplayId, deskId ->
                    if (deskUserId != userId) {
                        // TODO: b/400984250 - add multi-user support for multi-desk restoration.
                        logW("Tried to recreated desk of another user.")
                        deskId
                    } else {
                        desksOrganizer.createDesk(destinationDisplayId)
                    }
                }
        }
    }

    private fun onInit() {
@@ -1718,15 +1735,7 @@ 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,
                        ActivityOptions.makeBasic()
                            .apply {
                                launchWindowingMode = WINDOWING_MODE_FREEFORM
                                splashScreenStyle = SPLASH_SCREEN_STYLE_ICON
                            }
                            .toBundle(),
                    )
                    wct.startTask(taskId, createActivityOptionsForStartTask().toBundle())
                }
            }

@@ -2826,9 +2835,6 @@ class DesktopTasksController(
        }
        prepareForDeskActivation(displayId, wct)
        desksOrganizer.activateDesk(wct, deskId)
        if (DesktopModeFlags.ENABLE_DESKTOP_WINDOWING_PERSISTENCE.isTrue()) {
            // TODO: 362720497 - do non-running tasks need to be restarted with |wct#startTask|?
        }
        taskbarDesktopTaskListener?.onTaskbarCornerRoundingUpdate(
            doesAnyTaskRequireTaskbarRounding(displayId)
        )
@@ -2846,6 +2852,19 @@ class DesktopTasksController(
                desksOrganizer.minimizeTask(wct, deskId, taskToMinimize)
            }
        }
        if (DesktopModeFlags.ENABLE_DESKTOP_WINDOWING_PERSISTENCE.isTrue) {
            expandedTasksOrderedFrontToBack
                .filter { taskId -> taskId != taskIdToMinimize }
                .reversed()
                .forEach { taskId ->
                    val runningTaskInfo = shellTaskOrganizer.getRunningTaskInfo(taskId)
                    if (runningTaskInfo == null) {
                        wct.startTask(taskId, createActivityOptionsForStartTask().toBundle())
                    } else {
                        desksOrganizer.reorderTaskToFront(wct, deskId, runningTaskInfo)
                    }
                }
        }
        return { transition ->
            val activateDeskTransition =
                if (newTaskIdInFront != null) {
@@ -3497,6 +3516,13 @@ class DesktopTasksController(
        }
    }

    private fun createActivityOptionsForStartTask(): ActivityOptions {
        return ActivityOptions.makeBasic().apply {
            launchWindowingMode = WINDOWING_MODE_FREEFORM
            splashScreenStyle = SPLASH_SCREEN_STYLE_ICON
        }
    }

    private fun dump(pw: PrintWriter, prefix: String) {
        val innerPrefix = "$prefix  "
        pw.println("${prefix}DesktopTasksController")
+8 −0
Original line number Diff line number Diff line
@@ -18,6 +18,8 @@ package com.android.wm.shell.desktopmode.multidesks
import android.app.ActivityManager
import android.window.TransitionInfo
import android.window.WindowContainerTransaction
import com.android.wm.shell.desktopmode.multidesks.DesksOrganizer.OnCreateCallback
import kotlin.coroutines.suspendCoroutine

/** An organizer of desk containers in which to host child desktop windows. */
interface DesksOrganizer {
@@ -82,3 +84,9 @@ interface DesksOrganizer {
        fun onCreated(deskId: Int)
    }
}

/** Creates a new desk container in the given display. */
suspend fun DesksOrganizer.createDesk(displayId: Int): Int = suspendCoroutine { cont ->
    val onCreateCallback = OnCreateCallback { deskId -> cont.resumeWith(Result.success(deskId)) }
    createDesk(displayId, onCreateCallback)
}
Loading