Merge "remove aflag declaration OEM_ENABLED_SATELLITE_FLAG" into main
diff --git a/core/java/com/android/internal/util/LatencyTracker.java b/core/java/com/android/internal/util/LatencyTracker.java
index c120e67d..33794a5 100644
--- a/core/java/com/android/internal/util/LatencyTracker.java
+++ b/core/java/com/android/internal/util/LatencyTracker.java
@@ -23,6 +23,7 @@
 import static com.android.internal.util.FrameworkStatsLog.UIACTION_LATENCY_REPORTED__ACTION__ACTION_CHECK_CREDENTIAL;
 import static com.android.internal.util.FrameworkStatsLog.UIACTION_LATENCY_REPORTED__ACTION__ACTION_CHECK_CREDENTIAL_UNLOCKED;
 import static com.android.internal.util.FrameworkStatsLog.UIACTION_LATENCY_REPORTED__ACTION__ACTION_DESKTOP_MODE_ENTER_APP_HANDLE_DRAG;
+import static com.android.internal.util.FrameworkStatsLog.UIACTION_LATENCY_REPORTED__ACTION__ACTION_DESKTOP_MODE_ENTER_APP_HANDLE_MENU;
 import static com.android.internal.util.FrameworkStatsLog.UIACTION_LATENCY_REPORTED__ACTION__ACTION_EXPAND_PANEL;
 import static com.android.internal.util.FrameworkStatsLog.UIACTION_LATENCY_REPORTED__ACTION__ACTION_FACE_WAKE_AND_UNLOCK;
 import static com.android.internal.util.FrameworkStatsLog.UIACTION_LATENCY_REPORTED__ACTION__ACTION_FINGERPRINT_WAKE_AND_UNLOCK;
@@ -268,14 +269,27 @@
     public static final int ACTION_SHADE_WINDOW_DISPLAY_CHANGE = 29;
 
     /**
-     * Applicable when the user drags a full screen app's handle into the desktop drop zone to enter
-     * desktop mode. This measure the time from when the user releases their finger in the drop zone
-     * to when the animation for entering desktop mode visually begins. During this period, the
-     * home task and app headers for each window are initialized. Both have historically been
-     * expensive. See b/381396057 and b/360452034 respectively.
+     * Time it takes for the "enter desktop" mode animation to begin when initiated by dragging the
+     * app's handle into the desktop drop zone.
+     * <p>
+     * This measure the time from when the user releases their finger in the drop zone to when the
+     * animation for entering desktop mode visually begins. During this period, the home task and
+     * app headers for each window are initialized. Both have historically been expensive. See
+     * b/381396057 and b/360452034 respectively.
      */
     public static final int ACTION_DESKTOP_MODE_ENTER_APP_HANDLE_DRAG = 30;
 
+    /**
+     * Time it takes for the "enter desktop" mode animation to begin when initiated via the app
+     * handle's menu.
+     * <p>
+     * This measures the time from when the menu option is clicked/tapped to when the animation for
+     * entering desktop mode visually begins. During this period, the home task and app headers for
+     * each window are initialized. Both have historically been expensive. See b/381396057 and
+     * b/360452034 respectively.
+     */
+    public static final int ACTION_DESKTOP_MODE_ENTER_APP_HANDLE_MENU = 31;
+
     private static final int[] ACTIONS_ALL = {
         ACTION_EXPAND_PANEL,
         ACTION_TOGGLE_RECENTS,
@@ -308,6 +322,7 @@
         ACTION_KEYGUARD_FACE_UNLOCK_TO_HOME,
         ACTION_SHADE_WINDOW_DISPLAY_CHANGE,
         ACTION_DESKTOP_MODE_ENTER_APP_HANDLE_DRAG,
+        ACTION_DESKTOP_MODE_ENTER_APP_HANDLE_MENU,
     };
 
     /** @hide */
@@ -343,6 +358,7 @@
         ACTION_KEYGUARD_FACE_UNLOCK_TO_HOME,
         ACTION_SHADE_WINDOW_DISPLAY_CHANGE,
         ACTION_DESKTOP_MODE_ENTER_APP_HANDLE_DRAG,
+        ACTION_DESKTOP_MODE_ENTER_APP_HANDLE_MENU,
     })
     @Retention(RetentionPolicy.SOURCE)
     public @interface Action {}
@@ -380,6 +396,7 @@
             UIACTION_LATENCY_REPORTED__ACTION__ACTION_KEYGUARD_FACE_UNLOCK_TO_HOME,
             UIACTION_LATENCY_REPORTED__ACTION__ACTION_SHADE_WINDOW_DISPLAY_CHANGE,
             UIACTION_LATENCY_REPORTED__ACTION__ACTION_DESKTOP_MODE_ENTER_APP_HANDLE_DRAG,
+            UIACTION_LATENCY_REPORTED__ACTION__ACTION_DESKTOP_MODE_ENTER_APP_HANDLE_MENU,
     };
 
     private final Object mLock = new Object();
@@ -582,6 +599,8 @@
                 return "ACTION_SHADE_WINDOW_DISPLAY_CHANGE";
             case UIACTION_LATENCY_REPORTED__ACTION__ACTION_DESKTOP_MODE_ENTER_APP_HANDLE_DRAG:
                 return "ACTION_DESKTOP_MODE_ENTER_APP_HANDLE_DRAG";
+            case UIACTION_LATENCY_REPORTED__ACTION__ACTION_DESKTOP_MODE_ENTER_APP_HANDLE_MENU:
+                return "ACTION_DESKTOP_MODE_ENTER_APP_HANDLE_MENU";
             default:
                 throw new IllegalArgumentException("Invalid action");
         }
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/dagger/WMShellModule.java b/libs/WindowManager/Shell/src/com/android/wm/shell/dagger/WMShellModule.java
index 5d5e4d3..59acdc5 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/dagger/WMShellModule.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/dagger/WMShellModule.java
@@ -44,6 +44,7 @@
 import com.android.internal.jank.InteractionJankMonitor;
 import com.android.internal.logging.UiEventLogger;
 import com.android.internal.statusbar.IStatusBarService;
+import com.android.internal.util.LatencyTracker;
 import com.android.launcher3.icons.IconProvider;
 import com.android.window.flags.Flags;
 import com.android.wm.shell.RootTaskDisplayAreaOrganizer;
@@ -1074,8 +1075,10 @@
     static EnterDesktopTaskTransitionHandler provideEnterDesktopModeTaskTransitionHandler(
             Transitions transitions,
             Optional<DesktopTasksLimiter> desktopTasksLimiter,
-            InteractionJankMonitor interactionJankMonitor) {
-        return new EnterDesktopTaskTransitionHandler(transitions, interactionJankMonitor);
+            InteractionJankMonitor interactionJankMonitor,
+            LatencyTracker latencyTracker) {
+        return new EnterDesktopTaskTransitionHandler(
+                transitions, interactionJankMonitor, latencyTracker);
     }
 
     @WMSingleton
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopDisplayEventHandler.kt b/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopDisplayEventHandler.kt
index 946e795..afc48ac 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopDisplayEventHandler.kt
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopDisplayEventHandler.kt
@@ -68,6 +68,8 @@
         //  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.
         desktopTasksController.createDesk(displayId)
+        // TODO: b/393978539 - consider activating the desk on creation when applicable, such as
+        //  for connected displays.
     }
 
     override fun onDisplayRemoved(displayId: Int) {
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopRepository.kt b/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopRepository.kt
index 926e0f2..3c694ae 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopRepository.kt
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopRepository.kt
@@ -238,7 +238,6 @@
     }
 
     /** Returns the id of the active desk in the given display, if any. */
-    @VisibleForTesting
     fun getActiveDeskId(displayId: Int): Int? = desktopData.getActiveDesk(displayId)?.deskId
 
     /** Returns the id of the desk to which this task belongs. */
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopTasksController.kt b/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopTasksController.kt
index 87d9674..ea4d96a 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopTasksController.kt
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopTasksController.kt
@@ -1251,36 +1251,77 @@
             return
         }
 
+        val wct = WindowContainerTransaction()
         val displayAreaInfo = rootTaskDisplayAreaOrganizer.getDisplayAreaInfo(displayId)
         if (displayAreaInfo == null) {
             logW("moveToDisplay: display not found")
             return
         }
 
-        val wct = WindowContainerTransaction()
-
         // check if the task is part of splitscreen
         if (
             Flags.enableNonDefaultDisplaySplit() &&
                 Flags.enableMoveToNextDisplayShortcut() &&
                 splitScreenController.isTaskInSplitScreen(task.taskId)
         ) {
+            val activeDeskId = taskRepository.getActiveDeskId(displayId)
+            logV("moveToDisplay: moving split root to displayId=%d", displayId)
             val stageCoordinatorRootTaskToken =
                 splitScreenController.multiDisplayProvider.getDisplayRootForDisplayId(
                     DEFAULT_DISPLAY
                 )
-
             wct.reparent(stageCoordinatorRootTaskToken, displayAreaInfo.token, true /* onTop */)
-            transitions.startTransition(TRANSIT_CHANGE, wct, /* handler= */ null)
+            val deactivationRunnable =
+                if (activeDeskId != null) {
+                    // Split is being placed on top of an existing desk in the target display. Make
+                    // sure it is cleaned up.
+                    performDesktopExitCleanUp(
+                        wct = wct,
+                        deskId = activeDeskId,
+                        displayId = displayId,
+                        willExitDesktop = true,
+                        shouldEndUpAtHome = false,
+                    )
+                } else {
+                    null
+                }
+            val transition = transitions.startTransition(TRANSIT_CHANGE, wct, /* handler= */ null)
+            deactivationRunnable?.invoke(transition)
             return
         }
 
+        val destinationDeskId = taskRepository.getDefaultDeskId(displayId)
+        if (destinationDeskId == null) {
+            logW("moveToDisplay: desk not found for display: $displayId")
+            return
+        }
+
+        // TODO: b/393977830 and b/397437641 - do not assume that freeform==desktop.
         if (!task.isFreeform) {
             addMoveToDesktopChanges(wct, task, displayId)
         } else if (Flags.enableMoveToNextDisplayShortcut()) {
             applyFreeformDisplayChange(wct, task, displayId)
         }
-        wct.reparent(task.token, displayAreaInfo.token, /* onTop= */ true)
+
+        val activationRunnable: RunOnTransitStart?
+        if (DesktopExperienceFlags.ENABLE_MULTIPLE_DESKTOPS_BACKEND.isTrue) {
+            desksOrganizer.moveTaskToDesk(wct, destinationDeskId, task)
+            prepareForDeskActivation(displayId, wct)
+            desksOrganizer.activateDesk(wct, destinationDeskId)
+            activationRunnable = { transition ->
+                desksTransitionObserver.addPendingTransition(
+                    DeskTransition.ActiveDeskWithTask(
+                        token = transition,
+                        displayId = displayId,
+                        deskId = destinationDeskId,
+                        enterTaskId = task.taskId,
+                    )
+                )
+            }
+        } else {
+            wct.reparent(task.token, displayAreaInfo.token, /* onTop= */ true)
+            activationRunnable = null
+        }
         if (Flags.enableDisplayFocusInShellTransitions()) {
             // Bring the destination display to top with includingParents=true, so that the
             // destination display gains the display focus, which makes the top task in the display
@@ -1288,22 +1329,31 @@
             wct.reorder(task.token, /* onTop= */ true, /* includingParents= */ true)
         }
 
-        // TODO: b/394268248 - desk needs to be deactivated when moving the last task and going
-        //  home.
-        if (Flags.enablePerDisplayDesktopWallpaperActivity()) {
-            performDesktopExitCleanupIfNeeded(
-                taskId = task.taskId,
-                displayId = task.displayId,
-                wct = wct,
-                forceToFullscreen = false,
-                // TODO: b/371096166 - Temporary turing home relaunch off to prevent home stealing
-                // display focus. Remove shouldEndUpAtHome = false when home focus handling
-                // with connected display is implemented in wm core.
-                shouldEndUpAtHome = false,
-            )
-        }
-
-        transitions.startTransition(TRANSIT_CHANGE, wct, /* handler= */ null)
+        val sourceDisplayId = task.displayId
+        val sourceDeskId = taskRepository.getDeskIdForTask(task.taskId)
+        val shouldExitDesktopIfNeeded =
+            Flags.enablePerDisplayDesktopWallpaperActivity() ||
+                DesktopExperienceFlags.ENABLE_MULTIPLE_DESKTOPS_BACKEND.isTrue
+        val deactivationRunnable =
+            if (shouldExitDesktopIfNeeded) {
+                performDesktopExitCleanupIfNeeded(
+                    taskId = task.taskId,
+                    deskId = sourceDeskId,
+                    displayId = sourceDisplayId,
+                    wct = wct,
+                    forceToFullscreen = false,
+                    // TODO: b/371096166 - Temporary turing home relaunch off to prevent home
+                    // stealing
+                    // display focus. Remove shouldEndUpAtHome = false when home focus handling
+                    // with connected display is implemented in wm core.
+                    shouldEndUpAtHome = false,
+                )
+            } else {
+                null
+            }
+        val transition = transitions.startTransition(TRANSIT_CHANGE, wct, /* handler= */ null)
+        deactivationRunnable?.invoke(transition)
+        activationRunnable?.invoke(transition)
     }
 
     /**
@@ -2484,6 +2534,7 @@
         val displayLayout = displayController.getDisplayLayout(displayId) ?: return
         val tdaInfo = rootTaskDisplayAreaOrganizer.getDisplayAreaInfo(displayId)!!
         val tdaWindowingMode = tdaInfo.configuration.windowConfiguration.windowingMode
+        // TODO: b/397437641 - reconsider the windowing mode choice when multiple desks is enabled.
         val targetWindowingMode =
             if (tdaWindowingMode == WINDOWING_MODE_FREEFORM) {
                 // Display windowing is freeform, set to undefined and inherit it
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/EnterDesktopTaskTransitionHandler.java b/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/EnterDesktopTaskTransitionHandler.java
index 80e106f..4c17030 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/EnterDesktopTaskTransitionHandler.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/EnterDesktopTaskTransitionHandler.java
@@ -41,6 +41,7 @@
 import androidx.annotation.Nullable;
 
 import com.android.internal.jank.InteractionJankMonitor;
+import com.android.internal.util.LatencyTracker;
 import com.android.wm.shell.shared.desktopmode.DesktopModeTransitionSource;
 import com.android.wm.shell.transition.Transitions;
 import com.android.wm.shell.windowdecor.OnTaskResizeAnimationListener;
@@ -63,20 +64,25 @@
 
     private final List<IBinder> mPendingTransitionTokens = new ArrayList<>();
     private final InteractionJankMonitor mInteractionJankMonitor;
+    private final LatencyTracker mLatencyTracker;
 
     private OnTaskResizeAnimationListener mOnTaskResizeAnimationListener;
 
     public EnterDesktopTaskTransitionHandler(
-            Transitions transitions, InteractionJankMonitor interactionJankMonitor) {
-        this(transitions, interactionJankMonitor, SurfaceControl.Transaction::new);
+            Transitions transitions,
+            InteractionJankMonitor interactionJankMonitor,
+            LatencyTracker latencyTracker) {
+        this(transitions, interactionJankMonitor, latencyTracker, SurfaceControl.Transaction::new);
     }
 
     public EnterDesktopTaskTransitionHandler(
             Transitions transitions,
             InteractionJankMonitor interactionJankMonitor,
+            LatencyTracker latencyTracker,
             Supplier<SurfaceControl.Transaction> supplier) {
         mTransitions = transitions;
         mInteractionJankMonitor = interactionJankMonitor;
+        mLatencyTracker = latencyTracker;
         mTransactionSupplier = supplier;
     }
 
@@ -122,6 +128,13 @@
             }
         }
 
+        if (transitionHandled
+                && info.getType()
+                        == DesktopModeTransitionTypes
+                                .TRANSIT_ENTER_DESKTOP_FROM_APP_HANDLE_MENU_BUTTON) {
+            mLatencyTracker.onActionEnd(LatencyTracker.ACTION_DESKTOP_MODE_ENTER_APP_HANDLE_MENU);
+        }
+
         mPendingTransitionTokens.remove(transition);
 
         return transitionHandled;
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/multidesks/DesksTransitionObserver.kt b/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/multidesks/DesksTransitionObserver.kt
index e57b563..b521b2e 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/multidesks/DesksTransitionObserver.kt
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/multidesks/DesksTransitionObserver.kt
@@ -31,12 +31,14 @@
     private val desktopUserRepositories: DesktopUserRepositories,
     private val desksOrganizer: DesksOrganizer,
 ) {
-    private val deskTransitions = mutableMapOf<IBinder, DeskTransition>()
+    private val deskTransitions = mutableMapOf<IBinder, MutableSet<DeskTransition>>()
 
     /** Adds a pending desk transition to be tracked. */
     fun addPendingTransition(transition: DeskTransition) {
         if (!DesktopExperienceFlags.ENABLE_MULTIPLE_DESKTOPS_BACKEND.isTrue) return
-        deskTransitions[transition.token] = transition
+        val transitions = deskTransitions[transition.token] ?: mutableSetOf()
+        transitions += transition
+        deskTransitions[transition.token] = transitions
     }
 
     /**
@@ -45,7 +47,11 @@
      */
     fun onTransitionReady(transition: IBinder, info: TransitionInfo) {
         if (!DesktopExperienceFlags.ENABLE_MULTIPLE_DESKTOPS_BACKEND.isTrue) return
-        val deskTransition = deskTransitions.remove(transition) ?: return
+        val deskTransitions = deskTransitions.remove(transition) ?: return
+        deskTransitions.forEach { deskTransition -> handleDeskTransition(info, deskTransition) }
+    }
+
+    private fun handleDeskTransition(info: TransitionInfo, deskTransition: DeskTransition) {
         logD("Desk transition ready: %s", deskTransition)
         val desktopRepository = desktopUserRepositories.current
         when (deskTransition) {
@@ -60,16 +66,21 @@
                 deskTransition.onDeskRemovedListener?.onDeskRemoved(displayId, deskId)
             }
             is DeskTransition.ActivateDesk -> {
-                val activeDeskChange =
+                val activateDeskChange =
                     info.changes.find { change ->
                         desksOrganizer.isDeskActiveAtEnd(change, deskTransition.deskId)
                     }
-                activeDeskChange?.let {
-                    desktopRepository.setActiveDesk(
-                        displayId = deskTransition.displayId,
-                        deskId = deskTransition.deskId,
-                    )
+                if (activateDeskChange == null) {
+                    // Always activate even if there is no change in the transition for the
+                    // activated desk. This is necessary because some activation requests, such as
+                    // those involving empty desks, may not contain visibility changes that are
+                    // reported in the transition change list.
+                    logD("Activating desk without transition change")
                 }
+                desktopRepository.setActiveDesk(
+                    displayId = deskTransition.displayId,
+                    deskId = deskTransition.deskId,
+                )
             }
             is DeskTransition.ActiveDeskWithTask -> {
                 val withTask =
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/DesktopModeWindowDecorViewModel.java b/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/DesktopModeWindowDecorViewModel.java
index cf139a0..d9afd15 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/DesktopModeWindowDecorViewModel.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/DesktopModeWindowDecorViewModel.java
@@ -92,6 +92,7 @@
 import com.android.internal.jank.Cuj;
 import com.android.internal.jank.InteractionJankMonitor;
 import com.android.internal.protolog.ProtoLog;
+import com.android.internal.util.LatencyTracker;
 import com.android.window.flags.Flags;
 import com.android.wm.shell.R;
 import com.android.wm.shell.RootTaskDisplayAreaOrganizer;
@@ -260,6 +261,7 @@
     private final DesktopModeCompatPolicy mDesktopModeCompatPolicy;
     private final DesktopTilingDecorViewModel mDesktopTilingDecorViewModel;
     private final MultiDisplayDragMoveIndicatorController mMultiDisplayDragMoveIndicatorController;
+    private final LatencyTracker mLatencyTracker;
 
     public DesktopModeWindowDecorViewModel(
             Context context,
@@ -466,6 +468,7 @@
         mDesktopTilingDecorViewModel = desktopTilingDecorViewModel;
         mDesktopTasksController.setSnapEventHandler(this);
         mMultiDisplayDragMoveIndicatorController = multiDisplayDragMoveIndicatorController;
+        mLatencyTracker = LatencyTracker.getInstance(mContext);
         shellInit.addInitCallback(this::onInit, this);
     }
 
@@ -764,11 +767,19 @@
         final WindowContainerTransaction wct = new WindowContainerTransaction();
         mInteractionJankMonitor.begin(decoration.mTaskSurface, mContext, mMainHandler,
                 CUJ_DESKTOP_MODE_ENTER_MODE_APP_HANDLE_MENU);
+        mLatencyTracker.onActionStart(LatencyTracker.ACTION_DESKTOP_MODE_ENTER_APP_HANDLE_MENU);
         // App sometimes draws before the insets from WindowDecoration#relayout have
         // been added, so they must be added here
         decoration.addCaptionInset(wct);
-        mDesktopTasksController.moveTaskToDefaultDeskAndActivate(taskId, wct, source,
-                /* remoteTransition= */ null, /* moveToDesktopCallback */ null);
+        if (!mDesktopTasksController.moveTaskToDefaultDeskAndActivate(
+                taskId,
+                wct,
+                source,
+                /* remoteTransition= */ null,
+                /* moveToDesktopCallback= */ null)) {
+            mLatencyTracker.onActionCancel(
+                    LatencyTracker.ACTION_DESKTOP_MODE_ENTER_APP_HANDLE_MENU);
+        }
         decoration.closeHandleMenu();
 
         if (source == DesktopModeTransitionSource.APP_HANDLE_MENU_BUTTON) {
diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/desktopmode/DesktopTasksControllerTest.kt b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/desktopmode/DesktopTasksControllerTest.kt
index ff9fdd4..93eb396 100644
--- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/desktopmode/DesktopTasksControllerTest.kt
+++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/desktopmode/DesktopTasksControllerTest.kt
@@ -2780,6 +2780,79 @@
     }
 
     @Test
+    @EnableFlags(Flags.FLAG_ENABLE_MULTIPLE_DESKTOPS_BACKEND)
+    fun moveToNextDisplay_toDeskInOtherDisplay_movesToDeskAndActivates() {
+        val transition = Binder()
+        val targetDeskId = 4
+        taskRepository.addDesk(displayId = SECOND_DISPLAY, deskId = targetDeskId)
+        taskRepository.setDeskInactive(deskId = targetDeskId)
+        // Set up two display ids
+        whenever(rootTaskDisplayAreaOrganizer.displayIds)
+            .thenReturn(intArrayOf(DEFAULT_DISPLAY, SECOND_DISPLAY))
+        // Create a mock for the target display area: second display
+        val secondDisplayArea = DisplayAreaInfo(MockToken().token(), SECOND_DISPLAY, 0)
+        whenever(rootTaskDisplayAreaOrganizer.getDisplayAreaInfo(SECOND_DISPLAY))
+            .thenReturn(secondDisplayArea)
+        whenever(transitions.startTransition(eq(TRANSIT_CHANGE), any(), anyOrNull()))
+            .thenReturn(transition)
+
+        val task = setUpFreeformTask(displayId = DEFAULT_DISPLAY)
+        taskRepository.addTaskToDesk(
+            displayId = DEFAULT_DISPLAY,
+            deskId = 0,
+            taskId = task.taskId,
+            isVisible = true,
+        )
+        controller.moveToNextDisplay(task.taskId)
+
+        verify(desksOrganizer).moveTaskToDesk(any(), eq(targetDeskId), eq(task))
+        verify(desksOrganizer).activateDesk(any(), eq(targetDeskId))
+        verify(desksTransitionsObserver)
+            .addPendingTransition(
+                DeskTransition.ActiveDeskWithTask(
+                    token = transition,
+                    displayId = SECOND_DISPLAY,
+                    deskId = targetDeskId,
+                    enterTaskId = task.taskId,
+                )
+            )
+    }
+
+    @Test
+    @EnableFlags(Flags.FLAG_ENABLE_MULTIPLE_DESKTOPS_BACKEND)
+    fun moveToNextDisplay_wasLastTaskInSourceDesk_deactivates() {
+        val transition = Binder()
+        val sourceDeskId = 0
+        val targetDeskId = 4
+        taskRepository.addDesk(displayId = SECOND_DISPLAY, deskId = targetDeskId)
+        taskRepository.setDeskInactive(deskId = targetDeskId)
+        // Set up two display ids
+        whenever(rootTaskDisplayAreaOrganizer.displayIds)
+            .thenReturn(intArrayOf(DEFAULT_DISPLAY, SECOND_DISPLAY))
+        // Create a mock for the target display area: second display
+        val secondDisplayArea = DisplayAreaInfo(MockToken().token(), SECOND_DISPLAY, 0)
+        whenever(rootTaskDisplayAreaOrganizer.getDisplayAreaInfo(SECOND_DISPLAY))
+            .thenReturn(secondDisplayArea)
+        whenever(transitions.startTransition(eq(TRANSIT_CHANGE), any(), anyOrNull()))
+            .thenReturn(transition)
+
+        val task = setUpFreeformTask(displayId = DEFAULT_DISPLAY)
+        taskRepository.addTaskToDesk(
+            displayId = DEFAULT_DISPLAY,
+            deskId = sourceDeskId,
+            taskId = task.taskId,
+            isVisible = true,
+        )
+        controller.moveToNextDisplay(task.taskId)
+
+        verify(desksOrganizer).deactivateDesk(any(), eq(sourceDeskId))
+        verify(desksTransitionsObserver)
+            .addPendingTransition(
+                DeskTransition.DeactivateDesk(token = transition, deskId = sourceDeskId)
+            )
+    }
+
+    @Test
     fun getTaskWindowingMode() {
         val fullscreenTask = setUpFullscreenTask()
         val freeformTask = setUpFreeformTask()
diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/desktopmode/multidesks/DesksTransitionObserverTest.kt b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/desktopmode/multidesks/DesksTransitionObserverTest.kt
index 4dcf669..409ca57 100644
--- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/desktopmode/multidesks/DesksTransitionObserverTest.kt
+++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/desktopmode/multidesks/DesksTransitionObserverTest.kt
@@ -181,6 +181,23 @@
 
     @Test
     @EnableFlags(Flags.FLAG_ENABLE_MULTIPLE_DESKTOPS_BACKEND)
+    fun onTransitionReady_activateDesk_noTransitChange_updatesRepository() {
+        val transition = Binder()
+        val activateTransition =
+            DeskTransition.ActivateDesk(transition, displayId = DEFAULT_DISPLAY, deskId = 5)
+        repository.addDesk(DEFAULT_DISPLAY, deskId = 5)
+
+        observer.addPendingTransition(activateTransition)
+        observer.onTransitionReady(
+            transition = transition,
+            info = TransitionInfo(TRANSIT_TO_FRONT, /* flags= */ 0), // no changes.
+        )
+
+        assertThat(repository.getActiveDeskId(DEFAULT_DISPLAY)).isEqualTo(5)
+    }
+
+    @Test
+    @EnableFlags(Flags.FLAG_ENABLE_MULTIPLE_DESKTOPS_BACKEND)
     fun onTransitionReady_deactivateDesk_updatesRepository() {
         val transition = Binder()
         val deskChange = Change(mock(), mock())
@@ -244,4 +261,28 @@
 
         assertThat(repository.getActiveDeskId(DEFAULT_DISPLAY)).isNull()
     }
+
+    @Test
+    @EnableFlags(Flags.FLAG_ENABLE_MULTIPLE_DESKTOPS_BACKEND)
+    fun onTransitionReady_twoPendingTransitions_handlesBoth() {
+        val transition = Binder()
+        // Active one desk and deactivate another in different displays, such as in some
+        // move-to-next-display CUJs.
+        repository.addDesk(displayId = 0, deskId = 1)
+        repository.addDesk(displayId = 1, deskId = 2)
+        repository.setActiveDesk(displayId = 0, deskId = 1)
+        repository.setDeskInactive(2)
+        val activateTransition = DeskTransition.ActivateDesk(transition, displayId = 1, deskId = 2)
+        val deactivateTransition = DeskTransition.DeactivateDesk(transition, deskId = 1)
+
+        observer.addPendingTransition(activateTransition)
+        observer.addPendingTransition(deactivateTransition)
+        observer.onTransitionReady(
+            transition = transition,
+            info = TransitionInfo(TRANSIT_CHANGE, /* flags= */ 0),
+        )
+
+        assertThat(repository.getActiveDeskId(displayId = 0)).isNull()
+        assertThat(repository.getActiveDeskId(displayId = 1)).isEqualTo(2)
+    }
 }
diff --git a/libs/hwui/renderthread/CanvasContext.h b/libs/hwui/renderthread/CanvasContext.h
index f119102..3de8e05 100644
--- a/libs/hwui/renderthread/CanvasContext.h
+++ b/libs/hwui/renderthread/CanvasContext.h
@@ -312,7 +312,7 @@
     };
 
     // Need at least 4 because we do quad buffer. Add a few more for good measure.
-    RingBuffer<SwapHistory, 7> mSwapHistory;
+    RingBuffer<SwapHistory, 8> mSwapHistory;
     // Frame numbers start at 1, 0 means uninitialized
     uint64_t mFrameNumber = 0;
     int64_t mDamageId = 0;
diff --git a/packages/SettingsLib/SelectorWithWidgetPreference/res/layout/preference_widget_checkbox.xml b/packages/SettingsLib/SelectorWithWidgetPreference/res/layout/settingslib_preference_widget_checkbox.xml
similarity index 100%
rename from packages/SettingsLib/SelectorWithWidgetPreference/res/layout/preference_widget_checkbox.xml
rename to packages/SettingsLib/SelectorWithWidgetPreference/res/layout/settingslib_preference_widget_checkbox.xml
diff --git a/packages/SettingsLib/SelectorWithWidgetPreference/res/layout/preference_widget_radiobutton.xml b/packages/SettingsLib/SelectorWithWidgetPreference/res/layout/settingslib_preference_widget_radiobutton.xml
similarity index 100%
rename from packages/SettingsLib/SelectorWithWidgetPreference/res/layout/preference_widget_radiobutton.xml
rename to packages/SettingsLib/SelectorWithWidgetPreference/res/layout/settingslib_preference_widget_radiobutton.xml
diff --git a/packages/SettingsLib/SelectorWithWidgetPreference/src/com/android/settingslib/widget/SelectorWithWidgetPreference.java b/packages/SettingsLib/SelectorWithWidgetPreference/src/com/android/settingslib/widget/SelectorWithWidgetPreference.java
index 218983a..cde8b33 100644
--- a/packages/SettingsLib/SelectorWithWidgetPreference/src/com/android/settingslib/widget/SelectorWithWidgetPreference.java
+++ b/packages/SettingsLib/SelectorWithWidgetPreference/src/com/android/settingslib/widget/SelectorWithWidgetPreference.java
@@ -234,9 +234,9 @@
     private void init(@NonNull Context context, @Nullable AttributeSet attrs, int defStyleAttr,
             int defStyleRes) {
         if (mIsCheckBox) {
-            setWidgetLayoutResource(R.layout.preference_widget_checkbox);
+            setWidgetLayoutResource(R.layout.settingslib_preference_widget_checkbox);
         } else {
-            setWidgetLayoutResource(R.layout.preference_widget_radiobutton);
+            setWidgetLayoutResource(R.layout.settingslib_preference_widget_radiobutton);
         }
         setLayoutResource(R.layout.preference_selector_with_widget);
         setIconSpaceReserved(false);
diff --git a/packages/SettingsLib/res/layout-v33/preference_checkable_two_target.xml b/packages/SettingsLib/res/layout-v33/preference_checkable_two_target.xml
index 7ad018c..60d03e3 100644
--- a/packages/SettingsLib/res/layout-v33/preference_checkable_two_target.xml
+++ b/packages/SettingsLib/res/layout-v33/preference_checkable_two_target.xml
@@ -47,7 +47,7 @@
             android:clipToPadding="false"
             android:paddingTop="4dp"
             android:paddingBottom="4dp">
-            <include layout="@layout/preference_widget_checkbox" />
+            <include layout="@layout/settingslib_preference_widget_checkbox" />
         </LinearLayout>
 
         <RelativeLayout
diff --git a/packages/SettingsLib/res/layout/preference_checkable_two_target.xml b/packages/SettingsLib/res/layout/preference_checkable_two_target.xml
index f512f9b..ab7b04b 100644
--- a/packages/SettingsLib/res/layout/preference_checkable_two_target.xml
+++ b/packages/SettingsLib/res/layout/preference_checkable_two_target.xml
@@ -47,7 +47,7 @@
             android:clipToPadding="false"
             android:paddingTop="4dp"
             android:paddingBottom="4dp">
-            <include layout="@layout/preference_widget_checkbox" />
+            <include layout="@layout/settingslib_preference_widget_checkbox" />
         </LinearLayout>
 
         <RelativeLayout
diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/widget/SelectorWithWidgetPreferenceTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/widget/SelectorWithWidgetPreferenceTest.java
index c939c77..5076dea 100644
--- a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/widget/SelectorWithWidgetPreferenceTest.java
+++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/widget/SelectorWithWidgetPreferenceTest.java
@@ -78,14 +78,14 @@
     @Test
     public void shouldHaveRadioButtonWidgetLayoutByDefault() {
         assertThat(mPreference.getWidgetLayoutResource())
-                .isEqualTo(R.layout.preference_widget_radiobutton);
+                .isEqualTo(R.layout.settingslib_preference_widget_radiobutton);
     }
 
     @Test
     public void shouldHaveCheckBoxWidgetLayoutIfSet() {
         mPreference = new SelectorWithWidgetPreference(mContext, true);
         assertThat(mPreference.getWidgetLayoutResource())
-                .isEqualTo(R.layout.preference_widget_checkbox);
+                .isEqualTo(R.layout.settingslib_preference_widget_checkbox);
     }
 
     @Test
diff --git a/packages/SystemUI/compose/features/src/com/android/systemui/communal/ui/compose/CommunalContainer.kt b/packages/SystemUI/compose/features/src/com/android/systemui/communal/ui/compose/CommunalContainer.kt
index 9b76f15..4e1aab5 100644
--- a/packages/SystemUI/compose/features/src/com/android/systemui/communal/ui/compose/CommunalContainer.kt
+++ b/packages/SystemUI/compose/features/src/com/android/systemui/communal/ui/compose/CommunalContainer.kt
@@ -282,6 +282,7 @@
             CommunalBackgroundType.ANIMATED -> AnimatedLinearGradient()
             CommunalBackgroundType.NONE -> BackgroundTopScrim()
             CommunalBackgroundType.BLUR -> Background()
+            CommunalBackgroundType.SCRIM -> Scrimmed()
         }
 
         with(content) {
@@ -304,6 +305,11 @@
     Box(modifier = Modifier.matchParentSize().background(Color(backgroundColor.toArgb())))
 }
 
+@Composable
+private fun BoxScope.Scrimmed() {
+    Box(modifier = Modifier.matchParentSize().alpha(0.34f).background(Color.Black))
+}
+
 /** Experimental hub background, static linear gradient */
 @Composable
 private fun BoxScope.StaticLinearGradient() {
diff --git a/packages/SystemUI/compose/features/src/com/android/systemui/keyguard/ui/composable/section/BottomAreaSection.kt b/packages/SystemUI/compose/features/src/com/android/systemui/keyguard/ui/composable/section/BottomAreaSection.kt
index 52ccab3..ec7e495 100644
--- a/packages/SystemUI/compose/features/src/com/android/systemui/keyguard/ui/composable/section/BottomAreaSection.kt
+++ b/packages/SystemUI/compose/features/src/com/android/systemui/keyguard/ui/composable/section/BottomAreaSection.kt
@@ -70,33 +70,29 @@
             key = if (isStart) StartButtonElementKey else EndButtonElementKey,
             modifier = modifier,
         ) {
-            content {
-                Shortcut(
-                    viewId = if (isStart) R.id.start_button else R.id.end_button,
-                    viewModel = if (isStart) viewModel.startButton else viewModel.endButton,
-                    transitionAlpha = viewModel.transitionAlpha,
-                    indicationController = indicationController,
-                    binder = keyguardQuickAffordanceViewBinder,
-                    modifier =
-                        if (applyPadding) {
-                            Modifier.shortcutPadding()
-                        } else {
-                            Modifier
-                        },
-                )
-            }
+            Shortcut(
+                viewId = if (isStart) R.id.start_button else R.id.end_button,
+                viewModel = if (isStart) viewModel.startButton else viewModel.endButton,
+                transitionAlpha = viewModel.transitionAlpha,
+                indicationController = indicationController,
+                binder = keyguardQuickAffordanceViewBinder,
+                modifier =
+                    if (applyPadding) {
+                        Modifier.shortcutPadding()
+                    } else {
+                        Modifier
+                    },
+            )
         }
     }
 
     @Composable
     fun ContentScope.IndicationArea(modifier: Modifier = Modifier) {
         Element(key = IndicationAreaElementKey, modifier = modifier.indicationAreaPadding()) {
-            content {
-                IndicationArea(
-                    indicationAreaViewModel = indicationAreaViewModel,
-                    indicationController = indicationController,
-                )
-            }
+            IndicationArea(
+                indicationAreaViewModel = indicationAreaViewModel,
+                indicationController = indicationController,
+            )
         }
     }
 
diff --git a/packages/SystemUI/compose/features/src/com/android/systemui/keyguard/ui/composable/section/DefaultClockSection.kt b/packages/SystemUI/compose/features/src/com/android/systemui/keyguard/ui/composable/section/DefaultClockSection.kt
index ae541dd..0583e8a 100644
--- a/packages/SystemUI/compose/features/src/com/android/systemui/keyguard/ui/composable/section/DefaultClockSection.kt
+++ b/packages/SystemUI/compose/features/src/com/android/systemui/keyguard/ui/composable/section/DefaultClockSection.kt
@@ -26,11 +26,9 @@
 import androidx.compose.runtime.Composable
 import androidx.compose.runtime.LaunchedEffect
 import androidx.compose.runtime.getValue
-import androidx.compose.runtime.key
 import androidx.compose.ui.Modifier
 import androidx.compose.ui.res.dimensionResource
 import androidx.compose.ui.viewinterop.AndroidView
-import androidx.core.view.contains
 import androidx.lifecycle.compose.collectAsStateWithLifecycle
 import com.android.compose.animation.scene.ContentScope
 import com.android.compose.modifiers.padding
@@ -132,18 +130,16 @@
         }
 
         Element(key = largeClockElementKey, modifier = modifier) {
-            content {
-                ClockView(
-                    checkNotNull(currentClock).largeClock.view,
-                    modifier =
-                        Modifier.fillMaxSize()
-                            .burnInAware(
-                                viewModel = aodBurnInViewModel,
-                                params = burnInParams,
-                                isClock = true,
-                            ),
-                )
-            }
+            ClockView(
+                checkNotNull(currentClock).largeClock.view,
+                modifier =
+                    Modifier.fillMaxSize()
+                        .burnInAware(
+                            viewModel = aodBurnInViewModel,
+                            params = burnInParams,
+                            isClock = true,
+                        ),
+            )
         }
     }
 
diff --git a/packages/SystemUI/compose/features/src/com/android/systemui/keyguard/ui/composable/section/SmartSpaceSection.kt b/packages/SystemUI/compose/features/src/com/android/systemui/keyguard/ui/composable/section/SmartSpaceSection.kt
index c3ba7ab..c7b797d 100644
--- a/packages/SystemUI/compose/features/src/com/android/systemui/keyguard/ui/composable/section/SmartSpaceSection.kt
+++ b/packages/SystemUI/compose/features/src/com/android/systemui/keyguard/ui/composable/section/SmartSpaceSection.kt
@@ -66,64 +66,61 @@
         val resources = LocalContext.current.resources
 
         Element(key = ClockElementKeys.smartspaceElementKey, modifier = modifier) {
-            content {
-                Column(
-                    modifier =
-                        modifier
-                            .onTopPlacementChanged(onTopChanged)
-                            .padding(
-                                top = { smartSpacePaddingTop(resources) },
-                                bottom = {
-                                    resources.getDimensionPixelSize(
-                                        R.dimen.keyguard_status_view_bottom_margin
-                                    )
-                                },
-                            )
-                ) {
-                    if (!keyguardSmartspaceViewModel.isSmartspaceEnabled) {
-                        return@Column
-                    }
+            Column(
+                modifier =
+                    modifier
+                        .onTopPlacementChanged(onTopChanged)
+                        .padding(
+                            top = { smartSpacePaddingTop(resources) },
+                            bottom = {
+                                resources.getDimensionPixelSize(
+                                    R.dimen.keyguard_status_view_bottom_margin
+                                )
+                            },
+                        )
+            ) {
+                if (!keyguardSmartspaceViewModel.isSmartspaceEnabled) {
+                    return@Column
+                }
 
-                    val paddingBelowClockStart =
-                        dimensionResource(R.dimen.below_clock_padding_start)
-                    val paddingBelowClockEnd = dimensionResource(R.dimen.below_clock_padding_end)
-                    val paddingCardHorizontal = paddingBelowClockEnd
+                val paddingBelowClockStart = dimensionResource(R.dimen.below_clock_padding_start)
+                val paddingBelowClockEnd = dimensionResource(R.dimen.below_clock_padding_end)
+                val paddingCardHorizontal = paddingBelowClockEnd
 
-                    if (keyguardSmartspaceViewModel.isDateWeatherDecoupled) {
-                        Row(
-                            verticalAlignment = Alignment.CenterVertically,
-                            modifier =
-                                Modifier.fillMaxWidth()
-                                    // All items will be constrained to be as tall as the shortest
-                                    // item.
-                                    .height(IntrinsicSize.Min)
-                                    .padding(start = paddingBelowClockStart),
-                        ) {
-                            Date(
-                                modifier =
-                                    Modifier.burnInAware(
-                                        viewModel = aodBurnInViewModel,
-                                        params = burnInParams,
-                                    )
-                            )
-                            Spacer(modifier = Modifier.width(4.dp))
-                            Weather(
-                                modifier =
-                                    Modifier.burnInAware(
-                                        viewModel = aodBurnInViewModel,
-                                        params = burnInParams,
-                                    )
-                            )
-                        }
-                    }
-
-                    Card(
+                if (keyguardSmartspaceViewModel.isDateWeatherDecoupled) {
+                    Row(
+                        verticalAlignment = Alignment.CenterVertically,
                         modifier =
                             Modifier.fillMaxWidth()
-                                .padding(start = paddingCardHorizontal, end = paddingCardHorizontal)
-                                .burnInAware(viewModel = aodBurnInViewModel, params = burnInParams)
-                    )
+                                // All items will be constrained to be as tall as the shortest
+                                // item.
+                                .height(IntrinsicSize.Min)
+                                .padding(start = paddingBelowClockStart),
+                    ) {
+                        Date(
+                            modifier =
+                                Modifier.burnInAware(
+                                    viewModel = aodBurnInViewModel,
+                                    params = burnInParams,
+                                )
+                        )
+                        Spacer(modifier = Modifier.width(4.dp))
+                        Weather(
+                            modifier =
+                                Modifier.burnInAware(
+                                    viewModel = aodBurnInViewModel,
+                                    params = burnInParams,
+                                )
+                        )
+                    }
                 }
+
+                Card(
+                    modifier =
+                        Modifier.fillMaxWidth()
+                            .padding(start = paddingCardHorizontal, end = paddingCardHorizontal)
+                            .burnInAware(viewModel = aodBurnInViewModel, params = burnInParams)
+                )
             }
         }
     }
diff --git a/packages/SystemUI/compose/features/src/com/android/systemui/keyguard/ui/composable/section/WeatherClockSection.kt b/packages/SystemUI/compose/features/src/com/android/systemui/keyguard/ui/composable/section/WeatherClockSection.kt
index 4fcb5ca..a8b2b13 100644
--- a/packages/SystemUI/compose/features/src/com/android/systemui/keyguard/ui/composable/section/WeatherClockSection.kt
+++ b/packages/SystemUI/compose/features/src/com/android/systemui/keyguard/ui/composable/section/WeatherClockSection.kt
@@ -24,7 +24,6 @@
 import androidx.compose.foundation.layout.padding
 import androidx.compose.foundation.layout.wrapContentSize
 import androidx.compose.runtime.Composable
-import androidx.compose.runtime.key
 import androidx.compose.ui.Alignment
 import androidx.compose.ui.Modifier
 import androidx.compose.ui.res.dimensionResource
@@ -109,14 +108,10 @@
         modifier: Modifier = Modifier,
     ) {
         Element(key = elementKey, modifier) {
-            content {
-                ClockView(
-                    clock.largeClock.layout.views.firstOrNull {
-                        it.id == weatherClockElementViewId
-                    },
-                    modifier,
-                )
-            }
+            ClockView(
+                clock.largeClock.layout.views.firstOrNull { it.id == weatherClockElementViewId },
+                modifier,
+            )
         }
     }
 
diff --git a/packages/SystemUI/compose/features/src/com/android/systemui/qs/footer/ui/compose/FooterActions.kt b/packages/SystemUI/compose/features/src/com/android/systemui/qs/footer/ui/compose/FooterActions.kt
index 9c85c96..60c01722 100644
--- a/packages/SystemUI/compose/features/src/com/android/systemui/qs/footer/ui/compose/FooterActions.kt
+++ b/packages/SystemUI/compose/features/src/com/android/systemui/qs/footer/ui/compose/FooterActions.kt
@@ -116,11 +116,9 @@
         QuickSettingsTheme {
             // This view has its own horizontal padding
             // TODO(b/321716470) This should use a lifecycle tied to the scene.
-            FooterActions(
-                viewModel = viewModel,
-                qsVisibilityLifecycleOwner = lifecycleOwner,
-                modifier = Modifier.element(QuickSettings.Elements.FooterActions),
-            )
+            Element(QuickSettings.Elements.FooterActions, Modifier) {
+                FooterActions(viewModel = viewModel, qsVisibilityLifecycleOwner = lifecycleOwner)
+            }
         }
     }
 }
diff --git a/packages/SystemUI/compose/features/src/com/android/systemui/shade/ui/composable/ShadeHeader.kt b/packages/SystemUI/compose/features/src/com/android/systemui/shade/ui/composable/ShadeHeader.kt
index db9035b..23baeac 100644
--- a/packages/SystemUI/compose/features/src/com/android/systemui/shade/ui/composable/ShadeHeader.kt
+++ b/packages/SystemUI/compose/features/src/com/android/systemui/shade/ui/composable/ShadeHeader.kt
@@ -440,33 +440,36 @@
 private fun ContentScope.Clock(scale: Float, onClick: () -> Unit, modifier: Modifier = Modifier) {
     val layoutDirection = LocalLayoutDirection.current
 
-    Element(key = ShadeHeader.Elements.Clock, modifier = modifier) {
+    ElementWithValues(key = ShadeHeader.Elements.Clock, modifier = modifier) {
         val animatedScale by animateElementFloatAsState(scale, ClockScale, canOverflow = false)
-        AndroidView(
-            factory = { context ->
-                Clock(
-                    ContextThemeWrapper(context, R.style.Theme_SystemUI_QuickSettings_Header),
-                    null,
-                )
-            },
-            modifier =
-                modifier
-                    // use graphicsLayer instead of Modifier.scale to anchor transform
-                    // to the (start, top) corner
-                    .graphicsLayer {
-                        scaleX = animatedScale
-                        scaleY = animatedScale
-                        transformOrigin =
-                            TransformOrigin(
-                                when (layoutDirection) {
-                                    LayoutDirection.Ltr -> 0f
-                                    LayoutDirection.Rtl -> 1f
-                                },
-                                0.5f,
-                            )
-                    }
-                    .clickable { onClick() },
-        )
+
+        content {
+            AndroidView(
+                factory = { context ->
+                    Clock(
+                        ContextThemeWrapper(context, R.style.Theme_SystemUI_QuickSettings_Header),
+                        null,
+                    )
+                },
+                modifier =
+                    modifier
+                        // use graphicsLayer instead of Modifier.scale to anchor transform to the
+                        // (start, top) corner
+                        .graphicsLayer {
+                            scaleX = animatedScale
+                            scaleY = animatedScale
+                            transformOrigin =
+                                TransformOrigin(
+                                    when (layoutDirection) {
+                                        LayoutDirection.Ltr -> 0f
+                                        LayoutDirection.Rtl -> 1f
+                                    },
+                                    0.5f,
+                                )
+                        }
+                        .clickable { onClick() },
+            )
+        }
     }
 }
 
diff --git a/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/MovableElement.kt b/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/MovableElement.kt
index f4af5f0..eab5206 100644
--- a/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/MovableElement.kt
+++ b/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/MovableElement.kt
@@ -35,6 +35,21 @@
     sceneOrOverlay: Content,
     key: ElementKey,
     modifier: Modifier,
+    content: @Composable BoxScope.() -> Unit,
+) {
+    Box(
+        modifier.element(layoutImpl, sceneOrOverlay, key),
+        propagateMinConstraints = true,
+        content = content,
+    )
+}
+
+@Composable
+internal fun ElementWithValues(
+    layoutImpl: SceneTransitionLayoutImpl,
+    sceneOrOverlay: Content,
+    key: ElementKey,
+    modifier: Modifier,
     content: @Composable ElementScope<ElementContentScope>.() -> Unit,
 ) {
     Box(modifier.element(layoutImpl, sceneOrOverlay, key), propagateMinConstraints = true) {
diff --git a/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/SceneTransitionLayout.kt b/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/SceneTransitionLayout.kt
index f423bab..53d0ee1 100644
--- a/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/SceneTransitionLayout.kt
+++ b/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/SceneTransitionLayout.kt
@@ -22,6 +22,7 @@
 import androidx.compose.foundation.OverscrollEffect
 import androidx.compose.foundation.OverscrollFactory
 import androidx.compose.foundation.gestures.Orientation
+import androidx.compose.foundation.layout.BoxScope
 import androidx.compose.runtime.Composable
 import androidx.compose.runtime.SideEffect
 import androidx.compose.runtime.Stable
@@ -188,7 +189,7 @@
      * Additionally, this [key] will be used to detect elements that are shared between contents to
      * automatically interpolate their size and offset. If you need to animate shared element values
      * (i.e. values associated to this element that change depending on which content it is composed
-     * in), use [Element] instead.
+     * in), use [ElementWithValues] instead.
      *
      * Note that shared elements tagged using this function will be duplicated in each content they
      * are part of, so any **internal** state (e.g. state created using `remember {
@@ -196,9 +197,12 @@
      * [MovableElement] instead.
      *
      * @see Element
+     * @see ElementWithValues
      * @see MovableElement
      */
-    fun Modifier.element(key: ElementKey): Modifier
+    // TODO(b/389985793): Does replacing this by Element have a noticeable impact on performance and
+    // should we deprecate it?
+    @Stable fun Modifier.element(key: ElementKey): Modifier
 
     /**
      * Create an element identified by [key].
@@ -207,17 +211,29 @@
      * in multiple contents and that can be transformed during transitions, the same way that
      * [element] does.
      *
-     * The only difference with [element] is that the provided [ElementScope] allows you to
-     * [animate element values][ElementScope.animateElementValueAsState] or specify its
-     * [movable content][Element.movableContent] that will be "moved" and composed only once during
-     * transitions (as opposed to [element] that duplicates shared elements) so that any internal
-     * state is preserved during and after the transition.
+     * The only difference with [element] is that [Element] introduces its own recomposition scope
+     * and layout node, which can be helpful to avoid expensive recompositions when a transition is
+     * started or finished (see b/389985793#comment103 for details).
      *
      * @see element
+     * @see ElementWithValues
      * @see MovableElement
      */
     @Composable
-    fun Element(
+    fun Element(key: ElementKey, modifier: Modifier, content: @Composable BoxScope.() -> Unit)
+
+    /**
+     * Create an element identified by [key].
+     *
+     * The only difference with [Element] is that the provided [ElementScope] allows you to
+     * [animate element values][ElementScope.animateElementValueAsState].
+     *
+     * @see element
+     * @see Element
+     * @see MovableElement
+     */
+    @Composable
+    fun ElementWithValues(
         key: ElementKey,
         modifier: Modifier,
 
@@ -230,17 +246,19 @@
     /**
      * Create a *movable* element identified by [key].
      *
-     * Similar to [Element], this creates an element that will be automatically shared when present
-     * in multiple contents and that can be transformed during transitions, and you can also use the
-     * provided [ElementScope] to [animate element values][ElementScope.animateElementValueAsState].
+     * Similar to [ElementWithValues], this creates an element that will be automatically shared
+     * when present in multiple contents and that can be transformed during transitions, and you can
+     * also use the provided [ElementScope] to
+     * [animate element values][ElementScope.animateElementValueAsState].
      *
-     * The important difference with [element] and [Element] is that this element
-     * [content][ElementScope.content] will be "moved" and composed only once during transitions, as
-     * opposed to [element] and [Element] that duplicates shared elements, so that any internal
-     * state is preserved during and after the transition.
+     * The important difference with [element], [Element] and [ElementWithValues] is that this
+     * element [content][ElementScope.content] will be "moved" and composed only once during
+     * transitions, as opposed to [element], [Element] and [ElementWithValues] that duplicates
+     * shared elements, so that any internal state is preserved during and after the transition.
      *
      * @see element
      * @see Element
+     * @see ElementWithValues
      */
     @Composable
     fun MovableElement(
@@ -415,7 +433,7 @@
  *
  * We can't reuse BoxScope directly because of the @LayoutScopeMarker annotation on it, which would
  * prevent us from calling Modifier.element() and other methods of [ContentScope] inside any Box {}
- * in the [content][ElementScope.content] of a [ContentScope.Element] or a
+ * in the [content][ElementScope.content] of a [ContentScope.ElementWithValues] or a
  * [ContentScope.MovableElement].
  */
 @Stable
diff --git a/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/content/Content.kt b/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/content/Content.kt
index 95d6440..9ca45fe 100644
--- a/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/content/Content.kt
+++ b/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/content/Content.kt
@@ -21,6 +21,7 @@
 import androidx.compose.foundation.OverscrollEffect
 import androidx.compose.foundation.OverscrollFactory
 import androidx.compose.foundation.layout.Box
+import androidx.compose.foundation.layout.BoxScope
 import androidx.compose.runtime.Composable
 import androidx.compose.runtime.CompositionLocalProvider
 import androidx.compose.runtime.Stable
@@ -45,6 +46,7 @@
 import com.android.compose.animation.scene.ElementKey
 import com.android.compose.animation.scene.ElementScope
 import com.android.compose.animation.scene.ElementStateScope
+import com.android.compose.animation.scene.ElementWithValues
 import com.android.compose.animation.scene.InternalContentScope
 import com.android.compose.animation.scene.MovableElement
 import com.android.compose.animation.scene.MovableElementContentScope
@@ -222,12 +224,21 @@
     override fun Element(
         key: ElementKey,
         modifier: Modifier,
-        content: @Composable (ElementScope<ElementContentScope>.() -> Unit),
+        content: @Composable BoxScope.() -> Unit,
     ) {
         Element(layoutImpl, this@ContentScopeImpl.content, key, modifier, content)
     }
 
     @Composable
+    override fun ElementWithValues(
+        key: ElementKey,
+        modifier: Modifier,
+        content: @Composable (ElementScope<ElementContentScope>.() -> Unit),
+    ) {
+        ElementWithValues(layoutImpl, this@ContentScopeImpl.content, key, modifier, content)
+    }
+
+    @Composable
     override fun MovableElement(
         key: MovableElementKey,
         modifier: Modifier,
diff --git a/packages/SystemUI/compose/scene/tests/src/com/android/compose/animation/scene/AnimatedSharedAsStateTest.kt b/packages/SystemUI/compose/scene/tests/src/com/android/compose/animation/scene/AnimatedSharedAsStateTest.kt
index d11e6da1..d06e040 100644
--- a/packages/SystemUI/compose/scene/tests/src/com/android/compose/animation/scene/AnimatedSharedAsStateTest.kt
+++ b/packages/SystemUI/compose/scene/tests/src/com/android/compose/animation/scene/AnimatedSharedAsStateTest.kt
@@ -67,7 +67,7 @@
     @Composable
     private fun ContentScope.Foo(targetValues: Values, onCurrentValueChanged: (Values) -> Unit) {
         val key = TestElements.Foo
-        Element(key, Modifier) {
+        ElementWithValues(key, Modifier) {
             val int by animateElementIntAsState(targetValues.int, key = TestValues.Value1)
             val float by animateElementFloatAsState(targetValues.float, key = TestValues.Value2)
             val dp by animateElementDpAsState(targetValues.dp, key = TestValues.Value3)
diff --git a/packages/SystemUI/compose/scene/tests/src/com/android/compose/animation/scene/ElementTest.kt b/packages/SystemUI/compose/scene/tests/src/com/android/compose/animation/scene/ElementTest.kt
index 698a808..338fb9b 100644
--- a/packages/SystemUI/compose/scene/tests/src/com/android/compose/animation/scene/ElementTest.kt
+++ b/packages/SystemUI/compose/scene/tests/src/com/android/compose/animation/scene/ElementTest.kt
@@ -1163,7 +1163,7 @@
         @Composable
         fun ContentScope.Foo(size: Dp, value: Float, modifier: Modifier = Modifier) {
             val contentKey = this.contentKey
-            Element(TestElements.Foo, modifier.size(size)) {
+            ElementWithValues(TestElements.Foo, modifier.size(size)) {
                 val animatedValue = animateElementFloatAsState(value, TestValues.Value1)
                 LaunchedEffect(animatedValue) {
                     snapshotFlow { animatedValue.value }.collect { lastValues[contentKey] = it }
@@ -2090,11 +2090,9 @@
             TestContentScope(currentScene = SceneA) {
                 Column {
                     Element(TestElements.Foo, Modifier.size(40.dp)) {
-                        content {
-                            // Modifier.size() sets a preferred size and this should be ignored
-                            // because of the previously set 40dp size.
-                            Box(Modifier.testTag(contentTestTag).size(20.dp))
-                        }
+                        // Modifier.size() sets a preferred size and this should be ignored because
+                        // of the previously set 40dp size.
+                        Box(Modifier.testTag(contentTestTag).size(20.dp))
                     }
 
                     MovableElement(movable, Modifier.size(40.dp)) {
@@ -2283,4 +2281,35 @@
             .assertSizeIsEqualTo(50.dp)
             .assertPositionInRootIsEqualTo(100.dp, 100.dp)
     }
+
+    @Test
+    fun elementContentIsNotRecomposedWhenATransitionStarts() {
+        var compositions = 0
+        val state = rule.runOnUiThread { MutableSceneTransitionLayoutStateForTests(SceneA) }
+        val scope =
+            rule.setContentAndCreateMainScope {
+                SceneTransitionLayoutForTesting(state) {
+                    scene(SceneA) {
+                        Box(Modifier.fillMaxSize()) {
+                            Element(TestElements.Foo, Modifier) { SideEffect { compositions++ } }
+                        }
+                    }
+                    scene(SceneB) { Box(Modifier.fillMaxSize()) }
+                    scene(SceneC) { Box(Modifier.fillMaxSize()) }
+                }
+            }
+
+        assertThat(compositions).isEqualTo(1)
+
+        scope.launch { state.startTransition(transition(SceneA, SceneB)) }
+        rule.waitForIdle()
+
+        scope.launch { state.startTransition(transition(SceneA, SceneC)) }
+        rule.waitForIdle()
+
+        scope.launch { state.startTransition(transition(SceneA, SceneB)) }
+        rule.waitForIdle()
+
+        assertThat(compositions).isEqualTo(1)
+    }
 }
diff --git a/packages/SystemUI/compose/scene/tests/src/com/android/compose/animation/scene/MovableElementTest.kt b/packages/SystemUI/compose/scene/tests/src/com/android/compose/animation/scene/MovableElementTest.kt
index e023936..ebbde70 100644
--- a/packages/SystemUI/compose/scene/tests/src/com/android/compose/animation/scene/MovableElementTest.kt
+++ b/packages/SystemUI/compose/scene/tests/src/com/android/compose/animation/scene/MovableElementTest.kt
@@ -313,7 +313,7 @@
     fun elementScopeExtendsBoxScope() {
         rule.setContent {
             TestContentScope {
-                Element(TestElements.Foo, Modifier.size(200.dp)) {
+                ElementWithValues(TestElements.Foo, Modifier.size(200.dp)) {
                     content {
                         Box {
                             Box(Modifier.testTag("bottomEnd").align(Alignment.BottomEnd))
diff --git a/packages/SystemUI/compose/scene/tests/src/com/android/compose/animation/scene/SceneTransitionLayoutTest.kt b/packages/SystemUI/compose/scene/tests/src/com/android/compose/animation/scene/SceneTransitionLayoutTest.kt
index 3578be4..d7f7a51 100644
--- a/packages/SystemUI/compose/scene/tests/src/com/android/compose/animation/scene/SceneTransitionLayoutTest.kt
+++ b/packages/SystemUI/compose/scene/tests/src/com/android/compose/animation/scene/SceneTransitionLayoutTest.kt
@@ -129,7 +129,7 @@
 
     @Composable
     private fun ContentScope.SharedFoo(size: Dp, childOffset: Dp, modifier: Modifier = Modifier) {
-        Element(TestElements.Foo, modifier.size(size).background(Color.Red)) {
+        ElementWithValues(TestElements.Foo, modifier.size(size).background(Color.Red)) {
             // Offset the single child of Foo by some animated shared offset.
             val offset by animateElementDpAsState(childOffset, TestValues.Value1)
 
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/ui/viewmodel/DozingToDreamingTransitionViewModelTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/ui/viewmodel/DozingToDreamingTransitionViewModelTest.kt
deleted file mode 100644
index 052dfd5..0000000
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/ui/viewmodel/DozingToDreamingTransitionViewModelTest.kt
+++ /dev/null
@@ -1,54 +0,0 @@
-/*
- * Copyright (C) 2025 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.systemui.keyguard.ui.viewmodel
-
-import androidx.test.ext.junit.runners.AndroidJUnit4
-import androidx.test.filters.SmallTest
-import com.android.systemui.SysuiTestCase
-import com.android.systemui.keyguard.data.repository.fakeKeyguardTransitionRepository
-import com.android.systemui.keyguard.shared.model.KeyguardState
-import com.android.systemui.kosmos.collectValues
-import com.android.systemui.kosmos.runTest
-import com.android.systemui.kosmos.testScope
-import com.android.systemui.testKosmos
-import com.google.common.truth.Truth.assertThat
-import org.junit.Test
-import org.junit.runner.RunWith
-
-@SmallTest
-@RunWith(AndroidJUnit4::class)
-class DozingToDreamingTransitionViewModelTest : SysuiTestCase() {
-    val kosmos = testKosmos()
-
-    val underTest by lazy { kosmos.dozingToDreamingTransitionViewModel }
-
-    @Test
-    fun notificationShadeAlpha() =
-        kosmos.runTest {
-            val values by collectValues(underTest.notificationAlpha)
-            assertThat(values).isEmpty()
-
-            fakeKeyguardTransitionRepository.sendTransitionSteps(
-                from = KeyguardState.DOZING,
-                to = KeyguardState.DREAMING,
-                testScope,
-            )
-
-            assertThat(values).isNotEmpty()
-            values.forEach { assertThat(it).isEqualTo(0) }
-        }
-}
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/NotificationShadeDepthControllerTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/NotificationShadeDepthControllerTest.kt
index c10fd5e..326d8ff 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/NotificationShadeDepthControllerTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/NotificationShadeDepthControllerTest.kt
@@ -19,7 +19,6 @@
 import android.os.IBinder
 import android.platform.test.annotations.DisableFlags
 import android.platform.test.annotations.EnableFlags
-import android.platform.test.annotations.RequiresFlagsDisabled
 import android.testing.TestableLooper.RunWithLooper
 import android.view.Choreographer
 import android.view.View
@@ -360,7 +359,7 @@
     }
 
     @Test
-    @RequiresFlagsDisabled(Flags.FLAG_NOTIFICATION_SHADE_BLUR)
+    @DisableFlags(Flags.FLAG_NOTIFICATION_SHADE_BLUR)
     fun updateBlurCallback_setsOpaque_whenScrim() {
         scrimVisibilityCaptor.value.accept(ScrimController.OPAQUE)
         notificationShadeDepthController.updateBlurCallback.doFrame(0)
diff --git a/packages/SystemUI/src/com/android/systemui/communal/data/repository/CommunalSettingsRepositoryModule.kt b/packages/SystemUI/src/com/android/systemui/communal/data/repository/CommunalSettingsRepositoryModule.kt
index 0f25225..c6708d4 100644
--- a/packages/SystemUI/src/com/android/systemui/communal/data/repository/CommunalSettingsRepositoryModule.kt
+++ b/packages/SystemUI/src/com/android/systemui/communal/data/repository/CommunalSettingsRepositoryModule.kt
@@ -17,6 +17,7 @@
 package com.android.systemui.communal.data.repository
 
 import com.android.systemui.Flags.glanceableHubBlurredBackground
+import com.android.systemui.Flags.glanceableHubV2
 import com.android.systemui.communal.shared.model.CommunalBackgroundType
 import dagger.Binds
 import dagger.Module
@@ -35,6 +36,10 @@
                 return CommunalBackgroundType.BLUR
             }
 
+            if (glanceableHubV2()) {
+                return CommunalBackgroundType.SCRIM
+            }
+
             return CommunalBackgroundType.ANIMATED
         }
     }
diff --git a/packages/SystemUI/src/com/android/systemui/communal/shared/model/CommunalBackgroundType.kt b/packages/SystemUI/src/com/android/systemui/communal/shared/model/CommunalBackgroundType.kt
index e1128ed..a84fa79 100644
--- a/packages/SystemUI/src/com/android/systemui/communal/shared/model/CommunalBackgroundType.kt
+++ b/packages/SystemUI/src/com/android/systemui/communal/shared/model/CommunalBackgroundType.kt
@@ -17,10 +17,11 @@
 package com.android.systemui.communal.shared.model
 
 /** Models the types of background that can be shown on the hub. */
-enum class CommunalBackgroundType(val value: Int) {
-    STATIC(0),
-    STATIC_GRADIENT(1),
-    ANIMATED(2),
-    NONE(3),
-    BLUR(4),
+enum class CommunalBackgroundType(val value: Int, val opaque: Boolean) {
+    STATIC(value = 0, opaque = true),
+    STATIC_GRADIENT(value = 1, opaque = true),
+    ANIMATED(value = 2, opaque = true),
+    NONE(value = 3, opaque = false),
+    BLUR(value = 4, opaque = false),
+    SCRIM(value = 5, opaque = false),
 }
diff --git a/packages/SystemUI/src/com/android/systemui/communal/ui/viewmodel/CommunalTransitionViewModel.kt b/packages/SystemUI/src/com/android/systemui/communal/ui/viewmodel/CommunalTransitionViewModel.kt
index 0cbbfd4..db5c7eb 100644
--- a/packages/SystemUI/src/com/android/systemui/communal/ui/viewmodel/CommunalTransitionViewModel.kt
+++ b/packages/SystemUI/src/com/android/systemui/communal/ui/viewmodel/CommunalTransitionViewModel.kt
@@ -19,6 +19,7 @@
 import android.graphics.Color
 import com.android.systemui.communal.domain.interactor.CommunalInteractor
 import com.android.systemui.communal.domain.interactor.CommunalSceneInteractor
+import com.android.systemui.communal.domain.interactor.CommunalSettingsInteractor
 import com.android.systemui.communal.shared.model.CommunalScenes
 import com.android.systemui.communal.util.CommunalColors
 import com.android.systemui.dagger.SysUISingleton
@@ -40,6 +41,7 @@
 import kotlinx.coroutines.flow.Flow
 import kotlinx.coroutines.flow.SharingStarted
 import kotlinx.coroutines.flow.combine
+import kotlinx.coroutines.flow.distinctUntilChanged
 import kotlinx.coroutines.flow.filter
 import kotlinx.coroutines.flow.flowOf
 import kotlinx.coroutines.flow.map
@@ -60,6 +62,7 @@
     glanceableHubToDreamTransitionViewModel: GlanceableHubToDreamingTransitionViewModel,
     communalInteractor: CommunalInteractor,
     private val communalSceneInteractor: CommunalSceneInteractor,
+    communalSettingsInteractor: CommunalSettingsInteractor,
     keyguardTransitionInteractor: KeyguardTransitionInteractor,
 ) {
     /**
@@ -146,13 +149,16 @@
             }
 
     val recentsBackgroundColor: Flow<Color?> =
-        combine(showCommunalFromOccluded, communalColors.backgroundColor) {
-            showCommunalFromOccluded,
-            backgroundColor ->
-            if (showCommunalFromOccluded) {
-                backgroundColor
-            } else {
-                null
+        combine(
+                showCommunalFromOccluded,
+                communalColors.backgroundColor,
+                communalSettingsInteractor.communalBackground,
+            ) { showCommunalFromOccluded, backgroundColor, backgroundType ->
+                if (showCommunalFromOccluded && backgroundType.opaque) {
+                    backgroundColor
+                } else {
+                    null
+                }
             }
-        }
+            .distinctUntilChanged()
 }
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/FromDozingTransitionInteractor.kt b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/FromDozingTransitionInteractor.kt
index 0700ec6..6f5f662 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/FromDozingTransitionInteractor.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/FromDozingTransitionInteractor.kt
@@ -159,7 +159,6 @@
                     val isKeyguardOccludedLegacy = keyguardInteractor.isKeyguardOccluded.value
                     val primaryBouncerShowing = keyguardInteractor.primaryBouncerShowing.value
                     val isKeyguardGoingAway = keyguardInteractor.isKeyguardGoingAway.value
-                    val canStartDreaming = dreamManager.canStartDreaming(false)
 
                     if (!deviceEntryInteractor.isLockscreenEnabled()) {
                         if (!SceneContainerFlag.isEnabled) {
@@ -192,13 +191,6 @@
                         if (!SceneContainerFlag.isEnabled) {
                             transitionToGlanceableHub()
                         }
-                    } else if (canStartDreaming) {
-                        // If we're waking up to dream, transition directly to dreaming without
-                        // showing the lockscreen.
-                        startTransitionTo(
-                            KeyguardState.DREAMING,
-                            ownerReason = "moving from doze to dream",
-                        )
                     } else {
                         startTransitionTo(KeyguardState.LOCKSCREEN)
                     }
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/DozingToDreamingTransitionViewModel.kt b/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/DozingToDreamingTransitionViewModel.kt
index 9018c58..e6a85c6 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/DozingToDreamingTransitionViewModel.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/DozingToDreamingTransitionViewModel.kt
@@ -39,6 +39,4 @@
         )
 
     val lockscreenAlpha: Flow<Float> = transitionAnimation.immediatelyTransitionTo(0f)
-    // Notifications should not be shown while transitioning to dream.
-    val notificationAlpha = transitionAnimation.immediatelyTransitionTo(0f)
 }
diff --git a/packages/SystemUI/src/com/android/systemui/qs/composefragment/QSFragmentCompose.kt b/packages/SystemUI/src/com/android/systemui/qs/composefragment/QSFragmentCompose.kt
index 6ad8bae..71eacdf 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/composefragment/QSFragmentCompose.kt
+++ b/packages/SystemUI/src/com/android/systemui/qs/composefragment/QSFragmentCompose.kt
@@ -312,20 +312,18 @@
         SceneTransitionLayout(state = sceneState, modifier = Modifier.fillMaxSize()) {
             scene(QuickSettings) {
                 LaunchedEffect(Unit) { viewModel.onQSOpen() }
-                QuickSettingsElement(Modifier.element(QuickSettings.rootElementKey))
+                Element(QuickSettings.rootElementKey, Modifier) { QuickSettingsElement() }
             }
 
             scene(QuickQuickSettings) {
                 LaunchedEffect(Unit) { viewModel.onQQSOpen() }
                 // Cannot pass the element modifier in because the top element has a `testTag`
                 // and this would overwrite it.
-                Box(Modifier.element(QuickQuickSettings.rootElementKey)) {
-                    QuickQuickSettingsElement()
-                }
+                Element(QuickQuickSettings.rootElementKey, Modifier) { QuickQuickSettingsElement() }
             }
 
             scene(SceneKeys.EditMode) {
-                EditModeElement(Modifier.element(SceneKeys.EditMode.rootElementKey))
+                Element(SceneKeys.EditMode.rootElementKey, Modifier) { EditModeElement() }
             }
         }
     }
@@ -656,10 +654,7 @@
                 )
         ) {
             if (viewModel.isQsEnabled) {
-                Box(
-                    modifier =
-                        Modifier.element(ElementKeys.QuickSettingsContent).fillMaxSize().weight(1f)
-                ) {
+                Element(ElementKeys.QuickSettingsContent, modifier = Modifier.weight(1f)) {
                     DisposableEffect(Unit) {
                         lifecycleScope.launch { scrollState.scrollTo(0) }
                         onDispose { lifecycleScope.launch { scrollState.scrollTo(0) } }
@@ -667,7 +662,8 @@
 
                     Column(
                         modifier =
-                            Modifier.onPlaced { coordinates ->
+                            Modifier.fillMaxSize()
+                                .onPlaced { coordinates ->
                                     val positionOnScreen = coordinates.positionOnScreen()
                                     val left = positionOnScreen.x
                                     val right = left + coordinates.size.width
@@ -744,13 +740,15 @@
                     }
                 }
                 QuickSettingsTheme {
-                    FooterActions(
-                        viewModel = viewModel.footerActionsViewModel,
-                        qsVisibilityLifecycleOwner = this@QSFragmentCompose,
-                        modifier =
-                            Modifier.sysuiResTag(ResIdTags.qsFooterActions)
-                                .element(ElementKeys.FooterActions),
-                    )
+                    Element(
+                        ElementKeys.FooterActions,
+                        Modifier.sysuiResTag(ResIdTags.qsFooterActions),
+                    ) {
+                        FooterActions(
+                            viewModel = viewModel.footerActionsViewModel,
+                            qsVisibilityLifecycleOwner = this@QSFragmentCompose,
+                        )
+                    }
                 }
             }
         }
diff --git a/packages/SystemUI/src/com/android/systemui/qs/composefragment/ui/GridAnchor.kt b/packages/SystemUI/src/com/android/systemui/qs/composefragment/ui/GridAnchor.kt
index 266e875..19ad9fc 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/composefragment/ui/GridAnchor.kt
+++ b/packages/SystemUI/src/com/android/systemui/qs/composefragment/ui/GridAnchor.kt
@@ -16,7 +16,6 @@
 
 package com.android.systemui.qs.composefragment.ui
 
-import androidx.compose.foundation.layout.Spacer
 import androidx.compose.runtime.Composable
 import androidx.compose.ui.Modifier
 import com.android.compose.animation.scene.ContentScope
@@ -29,5 +28,5 @@
 @Composable
 fun ContentScope.GridAnchor(modifier: Modifier = Modifier) {
     // The size of this anchor does not matter, as the tiles don't change size on expansion.
-    Spacer(modifier.element(ElementKeys.GridAnchor))
+    Element(ElementKeys.GridAnchor, modifier) {}
 }
diff --git a/packages/SystemUI/src/com/android/systemui/qs/panels/ui/compose/QuickQuickSettings.kt b/packages/SystemUI/src/com/android/systemui/qs/panels/ui/compose/QuickQuickSettings.kt
index b084f79..495870f 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/panels/ui/compose/QuickQuickSettings.kt
+++ b/packages/SystemUI/src/com/android/systemui/qs/panels/ui/compose/QuickQuickSettings.kt
@@ -71,17 +71,19 @@
             val it = sizedTiles[spanIndex]
             val column = cellIndex % columns
             cellIndex += it.width
-            Tile(
-                tile = it.tile,
-                iconOnly = it.isIcon,
-                modifier = Modifier.element(it.tile.spec.toElementKey(spanIndex)),
-                squishiness = { squishiness },
-                coroutineScope = scope,
-                bounceableInfo = bounceables.bounceableInfo(it, spanIndex, column, columns),
-                tileHapticsViewModelFactoryProvider = viewModel.tileHapticsViewModelFactoryProvider,
-                // There should be no QuickQuickSettings when the details view is enabled.
-                detailsViewModel = null,
-            )
+            Element(it.tile.spec.toElementKey(spanIndex), Modifier) {
+                Tile(
+                    tile = it.tile,
+                    iconOnly = it.isIcon,
+                    squishiness = { squishiness },
+                    coroutineScope = scope,
+                    bounceableInfo = bounceables.bounceableInfo(it, spanIndex, column, columns),
+                    tileHapticsViewModelFactoryProvider =
+                        viewModel.tileHapticsViewModelFactoryProvider,
+                    // There should be no QuickQuickSettings when the details view is enabled.
+                    detailsViewModel = null,
+                )
+            }
         }
     }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/qs/panels/ui/compose/infinitegrid/InfiniteGridLayout.kt b/packages/SystemUI/src/com/android/systemui/qs/panels/ui/compose/infinitegrid/InfiniteGridLayout.kt
index 1c540ee..dfee4976 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/panels/ui/compose/infinitegrid/InfiniteGridLayout.kt
+++ b/packages/SystemUI/src/com/android/systemui/qs/panels/ui/compose/infinitegrid/InfiniteGridLayout.kt
@@ -99,16 +99,17 @@
             val it = sizedTiles[spanIndex]
             val column = cellIndex % columns
             cellIndex += it.width
-            Tile(
-                tile = it.tile,
-                iconOnly = iconTilesViewModel.isIconTile(it.tile.spec),
-                modifier = Modifier.element(it.tile.spec.toElementKey(spanIndex)),
-                squishiness = { squishiness },
-                tileHapticsViewModelFactoryProvider = tileHapticsViewModelFactoryProvider,
-                coroutineScope = scope,
-                bounceableInfo = bounceables.bounceableInfo(it, spanIndex, column, columns),
-                detailsViewModel = detailsViewModel,
-            )
+            Element(it.tile.spec.toElementKey(spanIndex), Modifier) {
+                Tile(
+                    tile = it.tile,
+                    iconOnly = iconTilesViewModel.isIconTile(it.tile.spec),
+                    squishiness = { squishiness },
+                    tileHapticsViewModelFactoryProvider = tileHapticsViewModelFactoryProvider,
+                    coroutineScope = scope,
+                    bounceableInfo = bounceables.bounceableInfo(it, spanIndex, column, columns),
+                    detailsViewModel = detailsViewModel,
+                )
+            }
         }
     }
 
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/ui/viewmodel/SharedNotificationContainerViewModel.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/ui/viewmodel/SharedNotificationContainerViewModel.kt
index 877aa76..33cc62c 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/ui/viewmodel/SharedNotificationContainerViewModel.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/ui/viewmodel/SharedNotificationContainerViewModel.kt
@@ -50,7 +50,6 @@
 import com.android.systemui.keyguard.ui.viewmodel.AodToLockscreenTransitionViewModel
 import com.android.systemui.keyguard.ui.viewmodel.AodToOccludedTransitionViewModel
 import com.android.systemui.keyguard.ui.viewmodel.AodToPrimaryBouncerTransitionViewModel
-import com.android.systemui.keyguard.ui.viewmodel.DozingToDreamingTransitionViewModel
 import com.android.systemui.keyguard.ui.viewmodel.DozingToGlanceableHubTransitionViewModel
 import com.android.systemui.keyguard.ui.viewmodel.DozingToLockscreenTransitionViewModel
 import com.android.systemui.keyguard.ui.viewmodel.DozingToOccludedTransitionViewModel
@@ -144,7 +143,6 @@
     private val aodToOccludedTransitionViewModel: AodToOccludedTransitionViewModel,
     private val aodToGlanceableHubTransitionViewModel: AodToGlanceableHubTransitionViewModel,
     private val aodToPrimaryBouncerTransitionViewModel: AodToPrimaryBouncerTransitionViewModel,
-    private val dozingToDreamingTransitionViewModel: DozingToDreamingTransitionViewModel,
     dozingToGlanceableHubTransitionViewModel: DozingToGlanceableHubTransitionViewModel,
     private val dozingToLockscreenTransitionViewModel: DozingToLockscreenTransitionViewModel,
     private val dozingToOccludedTransitionViewModel: DozingToOccludedTransitionViewModel,
@@ -603,7 +601,6 @@
             aodToOccludedTransitionViewModel.lockscreenAlpha(viewState),
             aodToGlanceableHubTransitionViewModel.lockscreenAlpha(viewState),
             aodToPrimaryBouncerTransitionViewModel.notificationAlpha,
-            dozingToDreamingTransitionViewModel.notificationAlpha,
             dozingToLockscreenTransitionViewModel.lockscreenAlpha,
             dozingToOccludedTransitionViewModel.lockscreenAlpha(viewState),
             dozingToPrimaryBouncerTransitionViewModel.notificationAlpha,
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/communal/ui/viewmodel/CommunalTransitionViewModelKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/communal/ui/viewmodel/CommunalTransitionViewModelKosmos.kt
index 7b0c09c..9109b36 100644
--- a/packages/SystemUI/tests/utils/src/com/android/systemui/communal/ui/viewmodel/CommunalTransitionViewModelKosmos.kt
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/communal/ui/viewmodel/CommunalTransitionViewModelKosmos.kt
@@ -18,6 +18,7 @@
 
 import com.android.systemui.communal.domain.interactor.communalInteractor
 import com.android.systemui.communal.domain.interactor.communalSceneInteractor
+import com.android.systemui.communal.domain.interactor.communalSettingsInteractor
 import com.android.systemui.communal.util.communalColors
 import com.android.systemui.keyguard.domain.interactor.keyguardTransitionInteractor
 import com.android.systemui.keyguard.ui.viewmodel.dreamingToGlanceableHubTransitionViewModel
@@ -41,5 +42,6 @@
             communalSceneInteractor = communalSceneInteractor,
             keyguardTransitionInteractor = keyguardTransitionInteractor,
             communalColors = communalColors,
+            communalSettingsInteractor = communalSettingsInteractor,
         )
     }
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/notification/stack/ui/viewmodel/SharedNotificationContainerViewModelKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/notification/stack/ui/viewmodel/SharedNotificationContainerViewModelKosmos.kt
index 51bb94f..17ef208 100644
--- a/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/notification/stack/ui/viewmodel/SharedNotificationContainerViewModelKosmos.kt
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/notification/stack/ui/viewmodel/SharedNotificationContainerViewModelKosmos.kt
@@ -30,7 +30,6 @@
 import com.android.systemui.keyguard.ui.viewmodel.aodToLockscreenTransitionViewModel
 import com.android.systemui.keyguard.ui.viewmodel.aodToOccludedTransitionViewModel
 import com.android.systemui.keyguard.ui.viewmodel.aodToPrimaryBouncerTransitionViewModel
-import com.android.systemui.keyguard.ui.viewmodel.dozingToDreamingTransitionViewModel
 import com.android.systemui.keyguard.ui.viewmodel.dozingToGlanceableHubTransitionViewModel
 import com.android.systemui.keyguard.ui.viewmodel.dozingToLockscreenTransitionViewModel
 import com.android.systemui.keyguard.ui.viewmodel.dozingToOccludedTransitionViewModel
@@ -84,7 +83,6 @@
         aodToLockscreenTransitionViewModel = aodToLockscreenTransitionViewModel,
         aodToOccludedTransitionViewModel = aodToOccludedTransitionViewModel,
         aodToPrimaryBouncerTransitionViewModel = aodToPrimaryBouncerTransitionViewModel,
-        dozingToDreamingTransitionViewModel = dozingToDreamingTransitionViewModel,
         dozingToGlanceableHubTransitionViewModel = dozingToGlanceableHubTransitionViewModel,
         dozingToLockscreenTransitionViewModel = dozingToLockscreenTransitionViewModel,
         dozingToOccludedTransitionViewModel = dozingToOccludedTransitionViewModel,
diff --git a/services/accessibility/java/com/android/server/accessibility/autoclick/AutoclickController.java b/services/accessibility/java/com/android/server/accessibility/autoclick/AutoclickController.java
index aa82df4..9ee7ec9 100644
--- a/services/accessibility/java/com/android/server/accessibility/autoclick/AutoclickController.java
+++ b/services/accessibility/java/com/android/server/accessibility/autoclick/AutoclickController.java
@@ -230,6 +230,11 @@
         return Flags.enableAutoclickIndicator() && mAutoclickTypePanel.isPaused();
     }
 
+    @VisibleForTesting
+    void onChangeForTesting(boolean selfChange, Uri uri) {
+        mAutoclickSettingsObserver.onChange(selfChange, uri);
+    }
+
     /**
      * Observes autoclick setting values, and updates ClickScheduler delay and indicator size
      * whenever the setting value changes.
diff --git a/services/core/java/com/android/server/dreams/DreamManagerService.java b/services/core/java/com/android/server/dreams/DreamManagerService.java
index 2af74f6..7e8bb28 100644
--- a/services/core/java/com/android/server/dreams/DreamManagerService.java
+++ b/services/core/java/com/android/server/dreams/DreamManagerService.java
@@ -569,8 +569,7 @@
     }
 
     private void requestDreamInternal() {
-        if (isDreamingInternal() && !dreamIsFrontmost() && mController.bringDreamToFront()
-                && !isDozingInternal()) {
+        if (isDreamingInternal() && !dreamIsFrontmost() && mController.bringDreamToFront()) {
             return;
         }
 
diff --git a/services/core/java/com/android/server/policy/PhoneWindowManager.java b/services/core/java/com/android/server/policy/PhoneWindowManager.java
index 980fb155..d11f5e7 100644
--- a/services/core/java/com/android/server/policy/PhoneWindowManager.java
+++ b/services/core/java/com/android/server/policy/PhoneWindowManager.java
@@ -1163,15 +1163,6 @@
         }
     }
 
-    private boolean shouldShowHub() {
-        final boolean hubEnabled = Settings.Secure.getIntForUser(
-                mContext.getContentResolver(), Settings.Secure.GLANCEABLE_HUB_ENABLED,
-                1, mCurrentUserId) == 1;
-
-        return mUserManagerInternal != null && mUserManagerInternal.isUserUnlocked(mCurrentUserId)
-                && hubEnabled && mDreamManagerInternal.dreamConditionActive();
-    }
-
     @VisibleForTesting
     void powerPress(long eventTime, int count, int displayId) {
         // SideFPS still needs to know about suppressed power buttons, in case it needs to block
@@ -1260,8 +1251,7 @@
                             mContext.getContentResolver(), Settings.Secure.GLANCEABLE_HUB_ENABLED,
                             1, mCurrentUserId) == 1;
 
-                    if ((mDreamManagerInternal != null && mDreamManagerInternal.isDreaming())
-                            || isKeyguardShowing()) {
+                    if (mDreamManagerInternal.isDreaming() || isKeyguardShowing()) {
                         // If the device is already dreaming or on keyguard, go to sleep.
                         sleepDefaultDisplayFromPowerButton(eventTime, 0);
                         break;
@@ -1271,10 +1261,9 @@
                     // show hub.
                     boolean keyguardAvailable = !mLockPatternUtils.isLockScreenDisabled(
                             mCurrentUserId);
-                    if (shouldShowHub() && keyguardAvailable) {
-                        // If the hub can be launched, send a message to keyguard. We do not know if
-                        // the hub is already running or not, keyguard handles turning screen off if
-                        // it is.
+                    if (mUserManagerInternal.isUserUnlocked(mCurrentUserId) && hubEnabled
+                            && keyguardAvailable && mDreamManagerInternal.dreamConditionActive()) {
+                        // If the hub can be launched, send a message to keyguard.
                         Bundle options = new Bundle();
                         options.putBoolean(EXTRA_TRIGGER_HUB, true);
                         lockNow(options);
@@ -1335,14 +1324,14 @@
      * @param isScreenOn Whether the screen is currently on.
      * @param noDreamAction The action to perform if dreaming is not possible.
      */
-    private boolean attemptToDreamFromShortPowerButtonPress(
+    private void attemptToDreamFromShortPowerButtonPress(
             boolean isScreenOn, Runnable noDreamAction) {
         if (mShortPressOnPowerBehavior != SHORT_PRESS_POWER_DREAM_OR_SLEEP
                 && mShortPressOnPowerBehavior != SHORT_PRESS_POWER_HUB_OR_DREAM_OR_SLEEP) {
             // If the power button behavior isn't one that should be able to trigger the dream, give
             // up.
             noDreamAction.run();
-            return false;
+            return;
         }
 
         final DreamManagerInternal dreamManagerInternal = getDreamManagerInternal();
@@ -1350,7 +1339,7 @@
             Slog.d(TAG, "Can't start dreaming when attempting to dream from short power"
                     + " press (isScreenOn=" + isScreenOn + ")");
             noDreamAction.run();
-            return false;
+            return;
         }
 
         synchronized (mLock) {
@@ -1361,8 +1350,6 @@
         }
 
         dreamManagerInternal.requestDream();
-
-        return true;
     }
 
     /**
@@ -2340,10 +2327,6 @@
         WindowWakeUpPolicy getWindowWakeUpPolicy() {
             return new WindowWakeUpPolicy(mContext);
         }
-
-        DreamManagerInternal getDreamManagerInternal() {
-            return LocalServices.getService(DreamManagerInternal.class);
-        }
     }
 
     /** {@inheritDoc} */
@@ -2362,7 +2345,7 @@
         mActivityTaskManagerInternal = LocalServices.getService(ActivityTaskManagerInternal.class);
         mInputManager = mContext.getSystemService(InputManager.class);
         mInputManagerInternal = LocalServices.getService(InputManagerInternal.class);
-        mDreamManagerInternal = injector.getDreamManagerInternal();
+        mDreamManagerInternal = LocalServices.getService(DreamManagerInternal.class);
         mPowerManagerInternal = LocalServices.getService(PowerManagerInternal.class);
         mAppOpsManager = mContext.getSystemService(AppOpsManager.class);
         mSensorPrivacyManager = mContext.getSystemService(SensorPrivacyManager.class);
@@ -6409,17 +6392,6 @@
                 event.getDisplayId(), event.getKeyCode(), "wakeUpFromWakeKey")) {
             return;
         }
-
-        if (!shouldShowHub()
-                && mShortPressOnPowerBehavior == SHORT_PRESS_POWER_HUB_OR_DREAM_OR_SLEEP
-                && event.getKeyCode() == KEYCODE_POWER
-                && attemptToDreamFromShortPowerButtonPress(false, () -> {})) {
-            // In the case that we should wake to dream and successfully initiate dreaming, do not
-            // continue waking up. Doing so will exit the dream state and cause UI to react
-            // accordingly.
-            return;
-        }
-
         wakeUpFromWakeKey(
                 event.getEventTime(),
                 event.getKeyCode(),
diff --git a/services/tests/servicestests/src/com/android/server/accessibility/autoclick/AutoclickControllerTest.java b/services/tests/servicestests/src/com/android/server/accessibility/autoclick/AutoclickControllerTest.java
index 0745c68..17d8882 100644
--- a/services/tests/servicestests/src/com/android/server/accessibility/autoclick/AutoclickControllerTest.java
+++ b/services/tests/servicestests/src/com/android/server/accessibility/autoclick/AutoclickControllerTest.java
@@ -41,6 +41,7 @@
 import android.view.WindowManager;
 import android.view.accessibility.AccessibilityManager;
 
+import com.android.internal.accessibility.util.AccessibilityUtils;
 import com.android.server.accessibility.AccessibilityTraceManager;
 
 import org.junit.After;
@@ -79,7 +80,9 @@
 
     @After
     public void tearDown() {
+        mController.onDestroy();
         mTestableLooper.processAllMessages();
+        TestableLooper.remove(this);
     }
 
     @Test
@@ -403,6 +406,133 @@
 
     @Test
     @EnableFlags(com.android.server.accessibility.Flags.FLAG_ENABLE_AUTOCLICK_INDICATOR)
+    public void onCursorAreaSizeSettingsChange_moveWithinCustomRadius_clickNotTriggered() {
+        // Move mouse to initialize autoclick panel before enabling ignore minor cursor movement.
+        injectFakeMouseActionHoverMoveEvent();
+        enableIgnoreMinorCursorMovement();
+
+        // Set a custom cursor area size.
+        int customSize = 250;
+        Settings.Secure.putIntForUser(mTestableContext.getContentResolver(),
+                Settings.Secure.ACCESSIBILITY_AUTOCLICK_CURSOR_AREA_SIZE,
+                customSize,
+                mTestableContext.getUserId());
+        mController.onChangeForTesting(/* selfChange= */ true,
+                Settings.Secure.getUriFor(
+                        Settings.Secure.ACCESSIBILITY_AUTOCLICK_CURSOR_AREA_SIZE));
+        assertThat(mController.mAutoclickIndicatorView.getRadiusForTesting()).isEqualTo(customSize);
+
+        // Move the mouse down, less than customSize radius so a click is not triggered.
+        float moveDownY = customSize - 25;
+        MotionEvent hoverMove = MotionEvent.obtain(
+                /* downTime= */ 0,
+                /* eventTime= */ 150,
+                /* action= */ MotionEvent.ACTION_HOVER_MOVE,
+                /* x= */ 0f,
+                /* y= */ moveDownY,
+                /* metaState= */ 0);
+        hoverMove.setSource(InputDevice.SOURCE_MOUSE);
+        mController.onMotionEvent(hoverMove, hoverMove, /* policyFlags= */ 0);
+        assertThat(mController.mClickScheduler.getIsActiveForTesting()).isFalse();
+    }
+
+    @Test
+    @EnableFlags(com.android.server.accessibility.Flags.FLAG_ENABLE_AUTOCLICK_INDICATOR)
+    public void onCursorAreaSizeSettingsChange_moveOutsideCustomRadius_clickTriggered() {
+        // Move mouse to initialize autoclick panel before enabling ignore minor cursor movement.
+        injectFakeMouseActionHoverMoveEvent();
+        enableIgnoreMinorCursorMovement();
+
+        // Set a custom cursor area size.
+        int customSize = 250;
+        Settings.Secure.putIntForUser(mTestableContext.getContentResolver(),
+                Settings.Secure.ACCESSIBILITY_AUTOCLICK_CURSOR_AREA_SIZE,
+                customSize,
+                mTestableContext.getUserId());
+        mController.onChangeForTesting(/* selfChange= */ true,
+                Settings.Secure.getUriFor(
+                        Settings.Secure.ACCESSIBILITY_AUTOCLICK_CURSOR_AREA_SIZE));
+        assertThat(mController.mAutoclickIndicatorView.getRadiusForTesting()).isEqualTo(customSize);
+
+        // Move the mouse right, greater than customSize radius so a click is triggered.
+        float moveRightX = customSize + 100;
+        MotionEvent hoverMove = MotionEvent.obtain(
+                /* downTime= */ 0,
+                /* eventTime= */ 200,
+                /* action= */ MotionEvent.ACTION_HOVER_MOVE,
+                /* x= */ moveRightX,
+                /* y= */ 0,
+                /* metaState= */ 0);
+        hoverMove.setSource(InputDevice.SOURCE_MOUSE);
+        mController.onMotionEvent(hoverMove, hoverMove, /* policyFlags= */ 0);
+        assertThat(mController.mClickScheduler.getIsActiveForTesting()).isTrue();
+    }
+
+    @Test
+    @EnableFlags(com.android.server.accessibility.Flags.FLAG_ENABLE_AUTOCLICK_INDICATOR)
+    public void onIgnoreCursorMovementFromSettingsChange_clickTriggered() {
+        // Send initial mouse movement.
+        injectFakeMouseActionHoverMoveEvent();
+
+        // Set a custom cursor area size.
+        int customSize = 250;
+        Settings.Secure.putIntForUser(mTestableContext.getContentResolver(),
+                Settings.Secure.ACCESSIBILITY_AUTOCLICK_CURSOR_AREA_SIZE,
+                customSize,
+                mTestableContext.getUserId());
+        mController.onChangeForTesting(/* selfChange= */ true,
+                Settings.Secure.getUriFor(
+                        Settings.Secure.ACCESSIBILITY_AUTOCLICK_CURSOR_AREA_SIZE));
+
+        // Move the mouse down less than customSize radius but ignore custom movement is not enabled
+        // so a click is triggered.
+        float moveDownY = customSize - 100;
+        MotionEvent hoverMove = MotionEvent.obtain(
+                /* downTime= */ 0,
+                /* eventTime= */ 150,
+                /* action= */ MotionEvent.ACTION_HOVER_MOVE,
+                /* x= */ 0f,
+                /* y= */ moveDownY,
+                /* metaState= */ 0);
+        hoverMove.setSource(InputDevice.SOURCE_MOUSE);
+        mController.onMotionEvent(hoverMove, hoverMove, /* policyFlags= */ 0);
+        assertThat(mController.mClickScheduler.getIsActiveForTesting()).isTrue();
+    }
+
+    @Test
+    @EnableFlags(com.android.server.accessibility.Flags.FLAG_ENABLE_AUTOCLICK_INDICATOR)
+    public void onIgnoreCursorMovementFromSettingsChange_clickNotTriggered() {
+        // Move mouse to initialize autoclick panel before enabling ignore minor cursor movement.
+        injectFakeMouseActionHoverMoveEvent();
+        enableIgnoreMinorCursorMovement();
+
+        // Set a custom cursor area size.
+        int customSize = 250;
+        Settings.Secure.putIntForUser(mTestableContext.getContentResolver(),
+                Settings.Secure.ACCESSIBILITY_AUTOCLICK_CURSOR_AREA_SIZE,
+                customSize,
+                mTestableContext.getUserId());
+        mController.onChangeForTesting(/* selfChange= */ true,
+                Settings.Secure.getUriFor(
+                        Settings.Secure.ACCESSIBILITY_AUTOCLICK_CURSOR_AREA_SIZE));
+
+        // After enabling ignore custom movement, move the mouse right, less than customSize radius
+        // so a click won't be triggered.
+        float moveRightX = customSize - 100;
+        MotionEvent hoverMove = MotionEvent.obtain(
+                /* downTime= */ 0,
+                /* eventTime= */ 200,
+                /* action= */ MotionEvent.ACTION_HOVER_MOVE,
+                /* x= */ moveRightX,
+                /* y= */ 0,
+                /* metaState= */ 0);
+        hoverMove.setSource(InputDevice.SOURCE_MOUSE);
+        mController.onMotionEvent(hoverMove, hoverMove, /* policyFlags= */ 0);
+        assertThat(mController.mClickScheduler.getIsActiveForTesting()).isFalse();
+    }
+
+    @Test
+    @EnableFlags(com.android.server.accessibility.Flags.FLAG_ENABLE_AUTOCLICK_INDICATOR)
     public void pauseButton_flagOn_clickNotTriggeredWhenPaused() {
         injectFakeMouseActionHoverMoveEvent();
 
@@ -473,4 +603,14 @@
                 /* y= */ 0,
                 /* metaState= */ 0);
     }
+
+    private void enableIgnoreMinorCursorMovement() {
+        Settings.Secure.putIntForUser(mTestableContext.getContentResolver(),
+                Settings.Secure.ACCESSIBILITY_AUTOCLICK_IGNORE_MINOR_CURSOR_MOVEMENT,
+                AccessibilityUtils.State.ON,
+                mTestableContext.getUserId());
+        mController.onChangeForTesting(/* selfChange= */ true,
+                Settings.Secure.getUriFor(
+                        Settings.Secure.ACCESSIBILITY_AUTOCLICK_IGNORE_MINOR_CURSOR_MOVEMENT));
+    }
 }
diff --git a/services/tests/wmtests/src/com/android/server/policy/PhoneWindowManagerTests.java b/services/tests/wmtests/src/com/android/server/policy/PhoneWindowManagerTests.java
index 22c86eb..32a3b7f 100644
--- a/services/tests/wmtests/src/com/android/server/policy/PhoneWindowManagerTests.java
+++ b/services/tests/wmtests/src/com/android/server/policy/PhoneWindowManagerTests.java
@@ -272,19 +272,6 @@
     }
 
     @Test
-    public void powerPress_withoutDreamManagerInternal_doesNotCrash() {
-        when(mDisplayPolicy.isAwake()).thenReturn(true);
-        mDreamManagerInternal = null;
-        initPhoneWindowManager();
-
-        // Power button pressed.
-        int eventTime = 0;
-        mPhoneWindowManager.powerPress(eventTime, 1, 0);
-
-        // verify no crash
-    }
-
-    @Test
     public void powerPress_hubOrDreamOrSleep_hubAvailableLocks() {
         when(mDisplayPolicy.isAwake()).thenReturn(true);
         mContext.getTestablePermissions().setPermission(android.Manifest.permission.DEVICE_POWER,
@@ -365,10 +352,5 @@
         WindowWakeUpPolicy getWindowWakeUpPolicy() {
             return mock(WindowWakeUpPolicy.class);
         }
-
-        @Override
-        DreamManagerInternal getDreamManagerInternal() {
-            return mDreamManagerInternal;
-        }
     }
 }
diff --git a/tests/Input/src/com/android/test/input/AnrTest.kt b/tests/Input/src/com/android/test/input/AnrTest.kt
index cd6ab30..73192ea 100644
--- a/tests/Input/src/com/android/test/input/AnrTest.kt
+++ b/tests/Input/src/com/android/test/input/AnrTest.kt
@@ -27,8 +27,6 @@
 import android.os.Build
 import android.os.IInputConstants.UNMULTIPLIED_DEFAULT_DISPATCHING_TIMEOUT_MILLIS
 import android.os.SystemClock
-import android.provider.Settings
-import android.provider.Settings.Global.HIDE_ERROR_DIALOGS
 import android.server.wm.CtsWindowInfoUtils.waitForStableWindowGeometry
 import android.testing.PollingCheck
 
@@ -38,6 +36,7 @@
 import androidx.test.uiautomator.Until
 
 import com.android.cts.input.DebugInputRule
+import com.android.cts.input.ShowErrorDialogsRule
 import com.android.cts.input.UinputTouchScreen
 
 import java.time.Duration
@@ -79,18 +78,16 @@
     @get:Rule
     val debugInputRule = DebugInputRule()
 
+    @get:Rule
+    val showErrorDialogs = ShowErrorDialogsRule()
+
     @Before
     fun setUp() {
-        val contentResolver = instrumentation.targetContext.contentResolver
-        hideErrorDialogs = Settings.Global.getInt(contentResolver, HIDE_ERROR_DIALOGS, 0)
-        Settings.Global.putInt(contentResolver, HIDE_ERROR_DIALOGS, 0)
         PACKAGE_NAME = UnresponsiveGestureMonitorActivity::class.java.getPackage()!!.getName()
     }
 
     @After
     fun tearDown() {
-        val contentResolver = instrumentation.targetContext.contentResolver
-        Settings.Global.putInt(contentResolver, HIDE_ERROR_DIALOGS, hideErrorDialogs)
     }
 
     @Test