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

Commit 9056fc3a authored by Matt Sziklay's avatar Matt Sziklay
Browse files

Update view model when desk organizer updates tasks.

When an onTaskInfoChanged event reaches DesksOrganizer, it does not ultimately reach DesktopModeWindowDecorViewModel, meaning window decorations end up with outdated taskInfo. This CL fixes this by calling view model's onTaskInfoChanged during RootTaskDesksOrganizer#onTaskInfoChanged

Bug: 404292560
Test: Manual, logging
Flag: com.android.window.flags.enable_multiple_desktops_backend
Change-Id: Iac6f0afdfe3c4aff871886a650fc0b142c72dd2d
parent 13c9658e
Loading
Loading
Loading
Loading
+4 −2
Original line number Original line Diff line number Diff line
@@ -1047,7 +1047,8 @@ public abstract class WMShellModule {
            DesktopModeCompatPolicy desktopModeCompatPolicy,
            DesktopModeCompatPolicy desktopModeCompatPolicy,
            DesktopTilingDecorViewModel desktopTilingDecorViewModel,
            DesktopTilingDecorViewModel desktopTilingDecorViewModel,
            MultiDisplayDragMoveIndicatorController multiDisplayDragMoveIndicatorController,
            MultiDisplayDragMoveIndicatorController multiDisplayDragMoveIndicatorController,
            Optional<CompatUIHandler> compatUI
            Optional<CompatUIHandler> compatUI,
            DesksOrganizer desksOrganizer
    ) {
    ) {
        if (!DesktopModeStatus.canEnterDesktopModeOrShowAppHandle(context)) {
        if (!DesktopModeStatus.canEnterDesktopModeOrShowAppHandle(context)) {
            return Optional.empty();
            return Optional.empty();
@@ -1065,7 +1066,8 @@ public abstract class WMShellModule {
                activityOrientationChangeHandler, focusTransitionObserver, desktopModeEventLogger,
                activityOrientationChangeHandler, focusTransitionObserver, desktopModeEventLogger,
                desktopModeUiEventLogger, taskResourceLoader, recentsTransitionHandler,
                desktopModeUiEventLogger, taskResourceLoader, recentsTransitionHandler,
                desktopModeCompatPolicy, desktopTilingDecorViewModel,
                desktopModeCompatPolicy, desktopTilingDecorViewModel,
                multiDisplayDragMoveIndicatorController, compatUI.orElse(null)));
                multiDisplayDragMoveIndicatorController, compatUI.orElse(null),
                desksOrganizer));
    }
    }


    @WMSingleton
    @WMSingleton
+3 −0
Original line number Original line Diff line number Diff line
@@ -78,6 +78,9 @@ interface DesksOrganizer {
    /** Whether the desk is activate according to the given change at the end of a transition. */
    /** Whether the desk is activate according to the given change at the end of a transition. */
    fun isDeskActiveAtEnd(change: TransitionInfo.Change, deskId: Int): Boolean
    fun isDeskActiveAtEnd(change: TransitionInfo.Change, deskId: Int): Boolean


    /** Allows for other classes to respond to task changes this organizer receives. */
    fun setOnDesktopTaskInfoChangedListener(listener: (ActivityManager.RunningTaskInfo) -> Unit)

    /** A callback that is invoked when the desk container is created. */
    /** A callback that is invoked when the desk container is created. */
    fun interface OnCreateCallback {
    fun interface OnCreateCallback {
        /** Calls back when the [deskId] has been created. */
        /** Calls back when the [deskId] has been created. */
+11 −0
Original line number Original line Diff line number Diff line
@@ -54,6 +54,7 @@ class RootTaskDesksOrganizer(
        mutableListOf<CreateDeskMinimizationRootRequest>()
        mutableListOf<CreateDeskMinimizationRootRequest>()
    @VisibleForTesting
    @VisibleForTesting
    val deskMinimizationRootsByDeskId: MutableMap<Int, DeskMinimizationRoot> = mutableMapOf()
    val deskMinimizationRootsByDeskId: MutableMap<Int, DeskMinimizationRoot> = mutableMapOf()
    private var onTaskInfoChangedListener: ((RunningTaskInfo) -> Unit)? = null


    init {
    init {
        if (DesktopExperienceFlags.ENABLE_MULTIPLE_DESKTOPS_BACKEND.isTrue) {
        if (DesktopExperienceFlags.ENABLE_MULTIPLE_DESKTOPS_BACKEND.isTrue) {
@@ -213,6 +214,10 @@ class RootTaskDesksOrganizer(
            change.taskInfo?.isVisibleRequested == true &&
            change.taskInfo?.isVisibleRequested == true &&
            change.mode == TRANSIT_TO_FRONT
            change.mode == TRANSIT_TO_FRONT


    override fun setOnDesktopTaskInfoChangedListener(listener: (RunningTaskInfo) -> Unit) {
        onTaskInfoChangedListener = listener
    }

    override fun onTaskAppeared(taskInfo: RunningTaskInfo, leash: SurfaceControl) {
    override fun onTaskAppeared(taskInfo: RunningTaskInfo, leash: SurfaceControl) {
        handleTaskAppeared(taskInfo, leash)
        handleTaskAppeared(taskInfo, leash)
        updateLaunchAdjacentController()
        updateLaunchAdjacentController()
@@ -220,6 +225,12 @@ class RootTaskDesksOrganizer(


    override fun onTaskInfoChanged(taskInfo: RunningTaskInfo) {
    override fun onTaskInfoChanged(taskInfo: RunningTaskInfo) {
        handleTaskInfoChanged(taskInfo)
        handleTaskInfoChanged(taskInfo)
        if (
            taskInfo.taskId !in deskRootsByDeskId &&
                deskMinimizationRootsByDeskId.values.none { it.rootId == taskInfo.taskId }
        ) {
            onTaskInfoChangedListener?.invoke(taskInfo)
        }
        updateLaunchAdjacentController()
        updateLaunchAdjacentController()
    }
    }


+13 −3
Original line number Original line Diff line number Diff line
@@ -127,6 +127,7 @@ import com.android.wm.shell.desktopmode.common.ToggleTaskSizeInteraction;
import com.android.wm.shell.desktopmode.common.ToggleTaskSizeUtilsKt;
import com.android.wm.shell.desktopmode.common.ToggleTaskSizeUtilsKt;
import com.android.wm.shell.desktopmode.education.AppHandleEducationController;
import com.android.wm.shell.desktopmode.education.AppHandleEducationController;
import com.android.wm.shell.desktopmode.education.AppToWebEducationController;
import com.android.wm.shell.desktopmode.education.AppToWebEducationController;
import com.android.wm.shell.desktopmode.multidesks.DesksOrganizer;
import com.android.wm.shell.freeform.FreeformTaskTransitionStarter;
import com.android.wm.shell.freeform.FreeformTaskTransitionStarter;
import com.android.wm.shell.recents.RecentsTransitionHandler;
import com.android.wm.shell.recents.RecentsTransitionHandler;
import com.android.wm.shell.recents.RecentsTransitionStateListener;
import com.android.wm.shell.recents.RecentsTransitionStateListener;
@@ -212,6 +213,7 @@ public class DesktopModeWindowDecorViewModel implements WindowDecorViewModel,
    private final AppHandleAndHeaderVisibilityHelper mAppHandleAndHeaderVisibilityHelper;
    private final AppHandleAndHeaderVisibilityHelper mAppHandleAndHeaderVisibilityHelper;
    private final AppHeaderViewHolder.Factory mAppHeaderViewHolderFactory;
    private final AppHeaderViewHolder.Factory mAppHeaderViewHolderFactory;
    private final AppHandleViewHolder.Factory mAppHandleViewHolderFactory;
    private final AppHandleViewHolder.Factory mAppHandleViewHolderFactory;
    private final DesksOrganizer mDesksOrganizer;
    private boolean mTransitionDragActive;
    private boolean mTransitionDragActive;


    private SparseArray<EventReceiver> mEventReceiversByDisplay = new SparseArray<>();
    private SparseArray<EventReceiver> mEventReceiversByDisplay = new SparseArray<>();
@@ -310,7 +312,8 @@ public class DesktopModeWindowDecorViewModel implements WindowDecorViewModel,
            DesktopModeCompatPolicy desktopModeCompatPolicy,
            DesktopModeCompatPolicy desktopModeCompatPolicy,
            DesktopTilingDecorViewModel desktopTilingDecorViewModel,
            DesktopTilingDecorViewModel desktopTilingDecorViewModel,
            MultiDisplayDragMoveIndicatorController multiDisplayDragMoveIndicatorController,
            MultiDisplayDragMoveIndicatorController multiDisplayDragMoveIndicatorController,
            CompatUIHandler compatUI) {
            CompatUIHandler compatUI,
            DesksOrganizer desksOrganizer) {
        this(
        this(
                context,
                context,
                shellExecutor,
                shellExecutor,
@@ -358,7 +361,8 @@ public class DesktopModeWindowDecorViewModel implements WindowDecorViewModel,
                desktopModeCompatPolicy,
                desktopModeCompatPolicy,
                desktopTilingDecorViewModel,
                desktopTilingDecorViewModel,
                multiDisplayDragMoveIndicatorController,
                multiDisplayDragMoveIndicatorController,
                compatUI);
                compatUI,
                desksOrganizer);
    }
    }


    @VisibleForTesting
    @VisibleForTesting
@@ -409,7 +413,8 @@ public class DesktopModeWindowDecorViewModel implements WindowDecorViewModel,
            DesktopModeCompatPolicy desktopModeCompatPolicy,
            DesktopModeCompatPolicy desktopModeCompatPolicy,
            DesktopTilingDecorViewModel desktopTilingDecorViewModel,
            DesktopTilingDecorViewModel desktopTilingDecorViewModel,
            MultiDisplayDragMoveIndicatorController multiDisplayDragMoveIndicatorController,
            MultiDisplayDragMoveIndicatorController multiDisplayDragMoveIndicatorController,
            CompatUIHandler compatUI) {
            CompatUIHandler compatUI,
            DesksOrganizer desksOrganizer) {
        mContext = context;
        mContext = context;
        mMainExecutor = shellExecutor;
        mMainExecutor = shellExecutor;
        mMainHandler = mainHandler;
        mMainHandler = mainHandler;
@@ -487,6 +492,7 @@ public class DesktopModeWindowDecorViewModel implements WindowDecorViewModel,
        mDesktopTasksController.setSnapEventHandler(this);
        mDesktopTasksController.setSnapEventHandler(this);
        mMultiDisplayDragMoveIndicatorController = multiDisplayDragMoveIndicatorController;
        mMultiDisplayDragMoveIndicatorController = multiDisplayDragMoveIndicatorController;
        mLatencyTracker = LatencyTracker.getInstance(mContext);
        mLatencyTracker = LatencyTracker.getInstance(mContext);
        mDesksOrganizer = desksOrganizer;
        shellInit.addInitCallback(this::onInit, this);
        shellInit.addInitCallback(this::onInit, this);
    }
    }


@@ -525,6 +531,10 @@ public class DesktopModeWindowDecorViewModel implements WindowDecorViewModel,
                    });
                    });
        }
        }
        mFocusTransitionObserver.setLocalFocusTransitionListener(this, mMainExecutor);
        mFocusTransitionObserver.setLocalFocusTransitionListener(this, mMainExecutor);
        mDesksOrganizer.setOnDesktopTaskInfoChangedListener((taskInfo) -> {
            onTaskInfoChanged(taskInfo);
            return Unit.INSTANCE;
        });
    }
    }


    @Override
    @Override
+37 −0
Original line number Original line Diff line number Diff line
@@ -15,6 +15,7 @@
 */
 */
package com.android.wm.shell.desktopmode.multidesks
package com.android.wm.shell.desktopmode.multidesks


import android.app.ActivityManager
import android.app.WindowConfiguration.WINDOWING_MODE_FREEFORM
import android.app.WindowConfiguration.WINDOWING_MODE_FREEFORM
import android.app.WindowConfiguration.WINDOWING_MODE_UNDEFINED
import android.app.WindowConfiguration.WINDOWING_MODE_UNDEFINED
import android.testing.AndroidTestingRunner
import android.testing.AndroidTestingRunner
@@ -48,7 +49,9 @@ import org.junit.Before
import org.junit.Test
import org.junit.Test
import org.junit.runner.RunWith
import org.junit.runner.RunWith
import org.mockito.Mockito
import org.mockito.Mockito
import org.mockito.Mockito.never
import org.mockito.Mockito.verify
import org.mockito.Mockito.verify
import org.mockito.kotlin.any
import org.mockito.kotlin.argThat
import org.mockito.kotlin.argThat
import org.mockito.kotlin.mock
import org.mockito.kotlin.mock
import org.mockito.kotlin.whenever
import org.mockito.kotlin.whenever
@@ -67,6 +70,7 @@ class RootTaskDesksOrganizerTest : ShellTestCase() {
    private val mockShellCommandHandler = mock<ShellCommandHandler>()
    private val mockShellCommandHandler = mock<ShellCommandHandler>()
    private val mockShellTaskOrganizer = mock<ShellTaskOrganizer>()
    private val mockShellTaskOrganizer = mock<ShellTaskOrganizer>()
    private val launchAdjacentController = LaunchAdjacentController(mock())
    private val launchAdjacentController = LaunchAdjacentController(mock())
    private val taskInfoChangedListener = mock<(ActivityManager.RunningTaskInfo) -> Unit>()


    private lateinit var organizer: RootTaskDesksOrganizer
    private lateinit var organizer: RootTaskDesksOrganizer


@@ -79,6 +83,7 @@ class RootTaskDesksOrganizerTest : ShellTestCase() {
                mockShellTaskOrganizer,
                mockShellTaskOrganizer,
                launchAdjacentController,
                launchAdjacentController,
            )
            )
        organizer.setOnDesktopTaskInfoChangedListener(taskInfoChangedListener)
    }
    }


    @Test fun testCreateDesk_createsDeskAndMinimizationRoots() = runTest { createDesk() }
    @Test fun testCreateDesk_createsDeskAndMinimizationRoots() = runTest { createDesk() }
@@ -652,6 +657,34 @@ class RootTaskDesksOrganizerTest : ShellTestCase() {
        assertThat(launchAdjacentController.launchAdjacentEnabled).isFalse()
        assertThat(launchAdjacentController.launchAdjacentEnabled).isFalse()
    }
    }


    @Test
    fun onTaskInfoChanged_taskNotRoot_invokesListener() = runTest {
        createDesk()
        val task = createFreeformTask().apply { taskId = TEST_CHILD_TASK_ID }

        organizer.onTaskInfoChanged(task)

        verify(taskInfoChangedListener).invoke(task)
    }

    @Test
    fun onTaskInfoChanged_isDeskRoot_doesNotInvokeListener() = runTest {
        val deskRoot = createDesk().deskRoot

        organizer.onTaskInfoChanged(deskRoot.taskInfo)

        verify(taskInfoChangedListener, never()).invoke(any())
    }

    @Test
    fun onTaskInfoChanged_isMinimizationRoot_doesNotInvokeListener() = runTest {
        val minimizationRoot = createDesk().minimizationRoot

        organizer.onTaskInfoChanged(minimizationRoot.taskInfo)

        verify(taskInfoChangedListener, never()).invoke(any())
    }

    private data class DeskRoots(
    private data class DeskRoots(
        val deskRoot: DeskRoot,
        val deskRoot: DeskRoot,
        val minimizationRoot: DeskMinimizationRoot,
        val minimizationRoot: DeskMinimizationRoot,
@@ -712,4 +745,8 @@ class RootTaskDesksOrganizerTest : ShellTestCase() {
                hop.newParent == desk.deskRoot.token.asBinder() &&
                hop.newParent == desk.deskRoot.token.asBinder() &&
                hop.toTop
                hop.toTop
        }
        }

    companion object {
        private const val TEST_CHILD_TASK_ID = 100
    }
}
}
Loading