Merge "Improve VibrationThread assertions for debugging" into main
diff --git a/core/api/test-current.txt b/core/api/test-current.txt
index 4222c7c..514a582 100644
--- a/core/api/test-current.txt
+++ b/core/api/test-current.txt
@@ -2586,7 +2586,7 @@
   }
 
   public class UserManager {
-    method @FlaggedApi("android.os.allow_private_profile") @RequiresPermission(anyOf={android.Manifest.permission.MANAGE_USERS, android.Manifest.permission.CREATE_USERS}, conditional=true) public boolean canAddPrivateProfile();
+    method @FlaggedApi("android.os.allow_private_profile") @RequiresPermission(anyOf={android.Manifest.permission.MANAGE_USERS, android.Manifest.permission.CREATE_USERS}) public boolean canAddPrivateProfile();
     method @Nullable @RequiresPermission(anyOf={android.Manifest.permission.MANAGE_USERS, android.Manifest.permission.CREATE_USERS}) public android.content.pm.UserInfo createProfileForUser(@Nullable String, @NonNull String, int, int, @Nullable String[]);
     method @Nullable @RequiresPermission(anyOf={android.Manifest.permission.MANAGE_USERS, android.Manifest.permission.CREATE_USERS}) public android.content.pm.UserInfo createRestrictedProfile(@Nullable String);
     method @Nullable @RequiresPermission(anyOf={android.Manifest.permission.MANAGE_USERS, android.Manifest.permission.CREATE_USERS}) public android.content.pm.UserInfo createUser(@Nullable String, @NonNull String, int);
diff --git a/core/java/android/os/UserManager.java b/core/java/android/os/UserManager.java
index 33bf4a2..767019d 100644
--- a/core/java/android/os/UserManager.java
+++ b/core/java/android/os/UserManager.java
@@ -3324,8 +3324,7 @@
     @FlaggedApi(android.os.Flags.FLAG_ALLOW_PRIVATE_PROFILE)
     @RequiresPermission(anyOf = {
             Manifest.permission.MANAGE_USERS,
-            Manifest.permission.CREATE_USERS},
-            conditional = true)
+            Manifest.permission.CREATE_USERS})
     @UserHandleAware
     public boolean canAddPrivateProfile() {
         if (!android.multiuser.Flags.enablePrivateSpaceFeatures()) return false;
diff --git a/core/java/android/view/textclassifier/intent/OWNERS b/core/java/android/view/textclassifier/intent/OWNERS
index 3465fe6..dc18514 100644
--- a/core/java/android/view/textclassifier/intent/OWNERS
+++ b/core/java/android/view/textclassifier/intent/OWNERS
@@ -1,6 +1,5 @@
 # Bug component: 709498
 
-mns@google.com
 toki@google.com
 svetoslavganov@android.com
 svetoslavganov@google.com
diff --git a/core/java/android/widget/RemoteViews.java b/core/java/android/widget/RemoteViews.java
index 0a5c14e..222a7b3 100644
--- a/core/java/android/widget/RemoteViews.java
+++ b/core/java/android/widget/RemoteViews.java
@@ -9216,6 +9216,7 @@
         public static RemoteResponse fromFillInIntent(@NonNull Intent fillIntent) {
             RemoteResponse response = new RemoteResponse();
             response.mFillIntent = fillIntent;
+            fillIntent.collectExtraIntentKeys();
             return response;
         }
 
@@ -9224,6 +9225,7 @@
             RemoteResponse response = new RemoteResponse();
             response.mPendingIntent = pendingIntent;
             response.mFillIntent = intent;
+            intent.collectExtraIntentKeys();
             return response;
         }
 
diff --git a/core/java/android/window/flags/lse_desktop_experience.aconfig b/core/java/android/window/flags/lse_desktop_experience.aconfig
index f77a366..2e36e9a 100644
--- a/core/java/android/window/flags/lse_desktop_experience.aconfig
+++ b/core/java/android/window/flags/lse_desktop_experience.aconfig
@@ -206,6 +206,13 @@
 }
 
 flag {
+    name: "enable_camera_compat_for_desktop_windowing_opt_out_api"
+    namespace: "lse_desktop_experience"
+    description: "Introduces a developer API to opt-out of Camera Compat treatment for fixed-orientation apps in desktop windowing mode"
+    bug: "397165621"
+}
+
+flag {
     name: "enable_task_stack_observer_in_shell"
     namespace: "lse_desktop_experience"
     description: "Introduces a new observer in shell to track the task stack."
@@ -794,4 +801,14 @@
     namespace: "lse_desktop_experience"
     description: "Enable Desktop Mode on Projected Mode devices but constrained to the external display."
     bug: "384568161"
+}
+
+flag {
+    name: "enable_persisting_density_scale_for_connected_displays"
+    namespace: "lse_desktop_experience"
+    description: "Enables persisting density scale on resolution change for connected displays."
+    bug: "392855657"
+    metadata {
+        purpose: PURPOSE_BUGFIX
+    }
 }
\ No newline at end of file
diff --git a/core/tests/coretests/src/android/widget/RemoteViewsTest.java b/core/tests/coretests/src/android/widget/RemoteViewsTest.java
index 8b0d315..9110898 100644
--- a/core/tests/coretests/src/android/widget/RemoteViewsTest.java
+++ b/core/tests/coretests/src/android/widget/RemoteViewsTest.java
@@ -22,6 +22,7 @@
 
 import static org.junit.Assert.assertArrayEquals;
 import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotEquals;
 import static org.junit.Assert.assertNotNull;
 import static org.junit.Assert.assertNull;
 import static org.junit.Assert.assertSame;
@@ -1065,6 +1066,22 @@
         assertEquals(b1Memory + b2Memory, rv.estimateTotalBitmapMemoryUsage());
     }
 
+    @Test
+    public void remoteResponse_FillInIntentNestedIntentKeysCollected() {
+        Intent fillInIntent = new Intent();
+        fillInIntent.putExtra("extraIntent", new Intent());
+        RemoteViews.RemoteResponse.fromFillInIntent(fillInIntent);
+        assertNotEquals(0, fillInIntent.getExtendedFlags()
+                & Intent.EXTENDED_FLAG_NESTED_INTENT_KEYS_COLLECTED);
+
+        fillInIntent = new Intent();
+        fillInIntent.putExtra("extraIntent", new Intent());
+        RemoteViews rv = new RemoteViews(mPackage, R.layout.remote_views_test);
+        rv.setOnClickFillInIntent(R.id.view, fillInIntent);
+        assertNotEquals(0, fillInIntent.getExtendedFlags()
+                & Intent.EXTENDED_FLAG_NESTED_INTENT_KEYS_COLLECTED);
+    }
+
     private static LayoutInflater.Factory2 createLayoutInflaterFactory(String viewTypeToReplace,
             View replacementView) {
         return new LayoutInflater.Factory2() {
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 ca870d2..87d9674 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
@@ -1745,6 +1745,9 @@
                 launchWindowingMode = WINDOWING_MODE_FULLSCREEN
                 pendingIntentBackgroundActivityStartMode =
                     ActivityOptions.MODE_BACKGROUND_ACTIVITY_START_ALLOW_ALWAYS
+                if (Flags.enablePerDisplayDesktopWallpaperActivity()) {
+                    launchDisplayId = displayId
+                }
             }
         val pendingIntent =
             PendingIntent.getActivityAsUser(
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/pip2/PipSurfaceTransactionHelper.java b/libs/WindowManager/Shell/src/com/android/wm/shell/pip2/PipSurfaceTransactionHelper.java
index c4d065f..e0cae81 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/pip2/PipSurfaceTransactionHelper.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/pip2/PipSurfaceTransactionHelper.java
@@ -134,6 +134,18 @@
     }
 
     /**
+     * Operates the round corner radius on a given transaction and leash, scaled by bounds
+     * @return same {@link PipSurfaceTransactionHelper} instance for method chaining
+     */
+    public PipSurfaceTransactionHelper round(SurfaceControl.Transaction tx, SurfaceControl leash,
+            Rect fromBounds, Rect toBounds) {
+        final float scale = (float) (Math.hypot(fromBounds.width(), fromBounds.height())
+                / Math.hypot(toBounds.width(), toBounds.height()));
+        tx.setCornerRadius(leash, mCornerRadius * scale);
+        return this;
+    }
+
+    /**
      * Operates the shadow radius on a given transaction and leash
      * @return same {@link PipSurfaceTransactionHelper} instance for method chaining
      */
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/pip2/animation/PipResizeAnimator.java b/libs/WindowManager/Shell/src/com/android/wm/shell/pip2/animation/PipResizeAnimator.java
index 06e8349..eb5fe88 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/pip2/animation/PipResizeAnimator.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/pip2/animation/PipResizeAnimator.java
@@ -173,7 +173,7 @@
         transformTensor.postRotate(degrees, targetBounds.centerX(), targetBounds.centerY());
 
         tx.setMatrix(leash, transformTensor, mMatrixTmp)
-                .setCornerRadius(leash, cornerRadius)
+                .setCornerRadius(leash, cornerRadius / scaleX)
                 .setShadowRadius(leash, shadowRadius);
     }
 
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/pip2/phone/PipScheduler.java b/libs/WindowManager/Shell/src/com/android/wm/shell/pip2/phone/PipScheduler.java
index df7a25a..7805ec3 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/pip2/phone/PipScheduler.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/pip2/phone/PipScheduler.java
@@ -55,6 +55,7 @@
     private PipTransitionController mPipTransitionController;
     private PipSurfaceTransactionHelper.SurfaceControlTransactionFactory
             mSurfaceControlTransactionFactory;
+    private final PipSurfaceTransactionHelper mPipSurfaceTransactionHelper;
 
     @Nullable private Runnable mUpdateMovementBoundsRunnable;
 
@@ -75,6 +76,7 @@
 
         mSurfaceControlTransactionFactory =
                 new PipSurfaceTransactionHelper.VsyncSurfaceControlTransactionFactory();
+        mPipSurfaceTransactionHelper = new PipSurfaceTransactionHelper(mContext);
         mPipAlphaAnimatorSupplier = PipAlphaAnimator::new;
     }
 
@@ -214,6 +216,8 @@
         transformTensor.postTranslate(toBounds.left, toBounds.top);
         transformTensor.postRotate(degrees, toBounds.centerX(), toBounds.centerY());
 
+        mPipSurfaceTransactionHelper.round(tx, leash, mPipBoundsState.getBounds(), toBounds);
+
         tx.setMatrix(leash, transformTensor, mMatrixTmp);
         tx.apply();
     }
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/pip2/phone/PipTransition.java b/libs/WindowManager/Shell/src/com/android/wm/shell/pip2/phone/PipTransition.java
index 97b3e5a..0cfab11 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/pip2/phone/PipTransition.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/pip2/phone/PipTransition.java
@@ -50,6 +50,7 @@
 import android.graphics.Rect;
 import android.os.Bundle;
 import android.os.IBinder;
+import android.os.SystemProperties;
 import android.view.SurfaceControl;
 import android.view.WindowManager;
 import android.window.TransitionInfo;
@@ -105,7 +106,10 @@
      * The fixed start delay in ms when fading out the content overlay from bounds animation.
      * The fadeout animation is guaranteed to start after the client has drawn under the new config.
      */
-    private static final int CONTENT_OVERLAY_FADE_OUT_DELAY_MS = 500;
+    private static final int EXTRA_CONTENT_OVERLAY_FADE_OUT_DELAY_MS =
+            SystemProperties.getInt(
+                    "persist.wm.debug.extra_content_overlay_fade_out_delay_ms", 400);
+    private static final int CONTENT_OVERLAY_FADE_OUT_DURATION_MS = 500;
 
     //
     // Dependencies
@@ -551,7 +555,8 @@
             @NonNull Runnable onAnimationEnd) {
         PipAlphaAnimator animator = new PipAlphaAnimator(mContext, overlayLeash,
                 null /* startTx */, null /* finishTx */, PipAlphaAnimator.FADE_OUT);
-        animator.setDuration(CONTENT_OVERLAY_FADE_OUT_DELAY_MS);
+        animator.setDuration(CONTENT_OVERLAY_FADE_OUT_DURATION_MS);
+        animator.setStartDelay(EXTRA_CONTENT_OVERLAY_FADE_OUT_DELAY_MS);
         animator.setAnimationEndCallback(onAnimationEnd);
         animator.start();
     }
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 0b160c6..9a73b02 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
@@ -2809,6 +2809,7 @@
 
         // Should launch home
         wct.assertPendingIntentAt(0, launchHomeIntent(DEFAULT_DISPLAY))
+        wct.assertPendingIntentActivityOptionsLaunchDisplayIdAt(0, DEFAULT_DISPLAY)
     }
 
     @Test
@@ -3931,6 +3932,7 @@
         // Should launch home
         assertNotNull(result, "Should handle request")
             .assertPendingIntentAt(0, launchHomeIntent(DEFAULT_DISPLAY))
+        result!!.assertPendingIntentActivityOptionsLaunchDisplayIdAt(0, DEFAULT_DISPLAY)
     }
 
     @Test
@@ -3957,6 +3959,7 @@
         // Should launch home
         assertNotNull(result, "Should handle request")
             .assertPendingIntentAt(0, launchHomeIntent(DEFAULT_DISPLAY))
+        result!!.assertPendingIntentActivityOptionsLaunchDisplayIdAt(0, DEFAULT_DISPLAY)
     }
 
     @Test
@@ -4089,6 +4092,7 @@
         // Should launch home
         assertNotNull(result, "Should handle request")
             .assertPendingIntentAt(0, launchHomeIntent(DEFAULT_DISPLAY))
+        result!!.assertPendingIntentActivityOptionsLaunchDisplayIdAt(0, DEFAULT_DISPLAY)
     }
 
     @Test
@@ -4105,6 +4109,7 @@
         // Should launch home
         assertNotNull(result, "Should handle request")
             .assertPendingIntentAt(0, launchHomeIntent(SECOND_DISPLAY))
+        result!!.assertPendingIntentActivityOptionsLaunchDisplayIdAt(0, SECOND_DISPLAY)
     }
 
     @Test
@@ -6898,6 +6903,18 @@
     assertThat(op.pendingIntent?.intent?.categories).isEqualTo(intent.categories)
 }
 
+private fun WindowContainerTransaction.assertPendingIntentActivityOptionsLaunchDisplayIdAt(
+    index: Int,
+    displayId: Int,
+) {
+    assertIndexInBounds(index)
+    val op = hierarchyOps[index]
+    if (op.launchOptions != null) {
+        val options = ActivityOptions(op.launchOptions)
+        assertThat(options.launchDisplayId).isEqualTo(displayId)
+    }
+}
+
 private fun WindowContainerTransaction.assertLaunchTask(taskId: Int, windowingMode: Int) {
     val keyLaunchWindowingMode = "android.activity.windowingMode"
 
diff --git a/packages/SettingsLib/ActionButtonsPreference/res/layout-v35/settingslib_expressive_action_buttons.xml b/packages/SettingsLib/ActionButtonsPreference/res/layout-v36/settingslib_expressive_action_buttons.xml
similarity index 100%
rename from packages/SettingsLib/ActionButtonsPreference/res/layout-v35/settingslib_expressive_action_buttons.xml
rename to packages/SettingsLib/ActionButtonsPreference/res/layout-v36/settingslib_expressive_action_buttons.xml
diff --git a/packages/SettingsLib/ActionButtonsPreference/res/values-v35/styles_expressive.xml b/packages/SettingsLib/ActionButtonsPreference/res/values-v36/styles_expressive.xml
similarity index 100%
rename from packages/SettingsLib/ActionButtonsPreference/res/values-v35/styles_expressive.xml
rename to packages/SettingsLib/ActionButtonsPreference/res/values-v36/styles_expressive.xml
diff --git a/packages/SettingsLib/BannerMessagePreference/res/drawable-v35/settingslib_expressive_card_background.xml b/packages/SettingsLib/BannerMessagePreference/res/drawable-v36/settingslib_expressive_card_background.xml
similarity index 100%
rename from packages/SettingsLib/BannerMessagePreference/res/drawable-v35/settingslib_expressive_card_background.xml
rename to packages/SettingsLib/BannerMessagePreference/res/drawable-v36/settingslib_expressive_card_background.xml
diff --git a/packages/SettingsLib/BannerMessagePreference/res/drawable-v35/settingslib_resolved_banner_avd.xml b/packages/SettingsLib/BannerMessagePreference/res/drawable-v36/settingslib_resolved_banner_avd.xml
similarity index 100%
rename from packages/SettingsLib/BannerMessagePreference/res/drawable-v35/settingslib_resolved_banner_avd.xml
rename to packages/SettingsLib/BannerMessagePreference/res/drawable-v36/settingslib_resolved_banner_avd.xml
diff --git a/packages/SettingsLib/BannerMessagePreference/res/layout-v35/settingslib_expressive_banner_message.xml b/packages/SettingsLib/BannerMessagePreference/res/layout-v36/settingslib_expressive_banner_message.xml
similarity index 100%
rename from packages/SettingsLib/BannerMessagePreference/res/layout-v35/settingslib_expressive_banner_message.xml
rename to packages/SettingsLib/BannerMessagePreference/res/layout-v36/settingslib_expressive_banner_message.xml
diff --git a/packages/SettingsLib/BannerMessagePreference/res/values-v35/styles_expressive.xml b/packages/SettingsLib/BannerMessagePreference/res/values-v36/styles_expressive.xml
similarity index 100%
rename from packages/SettingsLib/BannerMessagePreference/res/values-v35/styles_expressive.xml
rename to packages/SettingsLib/BannerMessagePreference/res/values-v36/styles_expressive.xml
diff --git a/packages/SettingsLib/ButtonPreference/res/layout-v35/settingslib_expressive_button_filled.xml b/packages/SettingsLib/ButtonPreference/res/layout-v36/settingslib_expressive_button_filled.xml
similarity index 100%
rename from packages/SettingsLib/ButtonPreference/res/layout-v35/settingslib_expressive_button_filled.xml
rename to packages/SettingsLib/ButtonPreference/res/layout-v36/settingslib_expressive_button_filled.xml
diff --git a/packages/SettingsLib/ButtonPreference/res/layout-v35/settingslib_expressive_button_filled_extra.xml b/packages/SettingsLib/ButtonPreference/res/layout-v36/settingslib_expressive_button_filled_extra.xml
similarity index 100%
rename from packages/SettingsLib/ButtonPreference/res/layout-v35/settingslib_expressive_button_filled_extra.xml
rename to packages/SettingsLib/ButtonPreference/res/layout-v36/settingslib_expressive_button_filled_extra.xml
diff --git a/packages/SettingsLib/ButtonPreference/res/layout-v35/settingslib_expressive_button_filled_large.xml b/packages/SettingsLib/ButtonPreference/res/layout-v36/settingslib_expressive_button_filled_large.xml
similarity index 100%
rename from packages/SettingsLib/ButtonPreference/res/layout-v35/settingslib_expressive_button_filled_large.xml
rename to packages/SettingsLib/ButtonPreference/res/layout-v36/settingslib_expressive_button_filled_large.xml
diff --git a/packages/SettingsLib/ButtonPreference/res/layout-v35/settingslib_expressive_button_outline.xml b/packages/SettingsLib/ButtonPreference/res/layout-v36/settingslib_expressive_button_outline.xml
similarity index 100%
rename from packages/SettingsLib/ButtonPreference/res/layout-v35/settingslib_expressive_button_outline.xml
rename to packages/SettingsLib/ButtonPreference/res/layout-v36/settingslib_expressive_button_outline.xml
diff --git a/packages/SettingsLib/ButtonPreference/res/layout-v35/settingslib_expressive_button_outline_extra.xml b/packages/SettingsLib/ButtonPreference/res/layout-v36/settingslib_expressive_button_outline_extra.xml
similarity index 100%
rename from packages/SettingsLib/ButtonPreference/res/layout-v35/settingslib_expressive_button_outline_extra.xml
rename to packages/SettingsLib/ButtonPreference/res/layout-v36/settingslib_expressive_button_outline_extra.xml
diff --git a/packages/SettingsLib/ButtonPreference/res/layout-v35/settingslib_expressive_button_outline_large.xml b/packages/SettingsLib/ButtonPreference/res/layout-v36/settingslib_expressive_button_outline_large.xml
similarity index 100%
rename from packages/SettingsLib/ButtonPreference/res/layout-v35/settingslib_expressive_button_outline_large.xml
rename to packages/SettingsLib/ButtonPreference/res/layout-v36/settingslib_expressive_button_outline_large.xml
diff --git a/packages/SettingsLib/ButtonPreference/res/layout-v35/settingslib_expressive_button_tonal.xml b/packages/SettingsLib/ButtonPreference/res/layout-v36/settingslib_expressive_button_tonal.xml
similarity index 100%
rename from packages/SettingsLib/ButtonPreference/res/layout-v35/settingslib_expressive_button_tonal.xml
rename to packages/SettingsLib/ButtonPreference/res/layout-v36/settingslib_expressive_button_tonal.xml
diff --git a/packages/SettingsLib/ButtonPreference/res/layout-v35/settingslib_expressive_button_tonal_extra.xml b/packages/SettingsLib/ButtonPreference/res/layout-v36/settingslib_expressive_button_tonal_extra.xml
similarity index 100%
rename from packages/SettingsLib/ButtonPreference/res/layout-v35/settingslib_expressive_button_tonal_extra.xml
rename to packages/SettingsLib/ButtonPreference/res/layout-v36/settingslib_expressive_button_tonal_extra.xml
diff --git a/packages/SettingsLib/ButtonPreference/res/layout-v35/settingslib_expressive_button_tonal_large.xml b/packages/SettingsLib/ButtonPreference/res/layout-v36/settingslib_expressive_button_tonal_large.xml
similarity index 100%
rename from packages/SettingsLib/ButtonPreference/res/layout-v35/settingslib_expressive_button_tonal_large.xml
rename to packages/SettingsLib/ButtonPreference/res/layout-v36/settingslib_expressive_button_tonal_large.xml
diff --git a/packages/SettingsLib/CollapsingToolbarBaseActivity/res/drawable-v35/settingslib_expressive_icon_back.xml b/packages/SettingsLib/CollapsingToolbarBaseActivity/res/drawable-v36/settingslib_expressive_icon_back.xml
similarity index 100%
rename from packages/SettingsLib/CollapsingToolbarBaseActivity/res/drawable-v35/settingslib_expressive_icon_back.xml
rename to packages/SettingsLib/CollapsingToolbarBaseActivity/res/drawable-v36/settingslib_expressive_icon_back.xml
diff --git a/packages/SettingsLib/CollapsingToolbarBaseActivity/res/layout-v35/settingslib_expressive_collapsing_toolbar_base_layout.xml b/packages/SettingsLib/CollapsingToolbarBaseActivity/res/layout-v36/settingslib_expressive_collapsing_toolbar_base_layout.xml
similarity index 100%
rename from packages/SettingsLib/CollapsingToolbarBaseActivity/res/layout-v35/settingslib_expressive_collapsing_toolbar_base_layout.xml
rename to packages/SettingsLib/CollapsingToolbarBaseActivity/res/layout-v36/settingslib_expressive_collapsing_toolbar_base_layout.xml
diff --git a/packages/SettingsLib/CollapsingToolbarBaseActivity/res/layout-v35/settingslib_expressive_collapsing_toolbar_content_layout.xml b/packages/SettingsLib/CollapsingToolbarBaseActivity/res/layout-v36/settingslib_expressive_collapsing_toolbar_content_layout.xml
similarity index 100%
rename from packages/SettingsLib/CollapsingToolbarBaseActivity/res/layout-v35/settingslib_expressive_collapsing_toolbar_content_layout.xml
rename to packages/SettingsLib/CollapsingToolbarBaseActivity/res/layout-v36/settingslib_expressive_collapsing_toolbar_content_layout.xml
diff --git a/packages/SettingsLib/CollapsingToolbarBaseActivity/res/values-night-v35/themes.xml b/packages/SettingsLib/CollapsingToolbarBaseActivity/res/values-night-v36/themes.xml
similarity index 100%
rename from packages/SettingsLib/CollapsingToolbarBaseActivity/res/values-night-v35/themes.xml
rename to packages/SettingsLib/CollapsingToolbarBaseActivity/res/values-night-v36/themes.xml
diff --git a/packages/SettingsLib/CollapsingToolbarBaseActivity/res/values-v35/styles.xml b/packages/SettingsLib/CollapsingToolbarBaseActivity/res/values-v36/styles.xml
similarity index 100%
rename from packages/SettingsLib/CollapsingToolbarBaseActivity/res/values-v35/styles.xml
rename to packages/SettingsLib/CollapsingToolbarBaseActivity/res/values-v36/styles.xml
diff --git a/packages/SettingsLib/CollapsingToolbarBaseActivity/res/values-v35/styles_expressive.xml b/packages/SettingsLib/CollapsingToolbarBaseActivity/res/values-v36/styles_expressive.xml
similarity index 100%
rename from packages/SettingsLib/CollapsingToolbarBaseActivity/res/values-v35/styles_expressive.xml
rename to packages/SettingsLib/CollapsingToolbarBaseActivity/res/values-v36/styles_expressive.xml
diff --git a/packages/SettingsLib/CollapsingToolbarBaseActivity/res/values-v35/themes.xml b/packages/SettingsLib/CollapsingToolbarBaseActivity/res/values-v36/themes.xml
similarity index 100%
rename from packages/SettingsLib/CollapsingToolbarBaseActivity/res/values-v35/themes.xml
rename to packages/SettingsLib/CollapsingToolbarBaseActivity/res/values-v36/themes.xml
diff --git a/packages/SettingsLib/CollapsingToolbarBaseActivity/res/values-v35/themes_expressive.xml b/packages/SettingsLib/CollapsingToolbarBaseActivity/res/values-v36/themes_expressive.xml
similarity index 100%
rename from packages/SettingsLib/CollapsingToolbarBaseActivity/res/values-v35/themes_expressive.xml
rename to packages/SettingsLib/CollapsingToolbarBaseActivity/res/values-v36/themes_expressive.xml
diff --git a/packages/SettingsLib/MainSwitchPreference/res/color-night-v35/settingslib_main_switch_text_color.xml b/packages/SettingsLib/MainSwitchPreference/res/color-night-v36/settingslib_main_switch_text_color.xml
similarity index 100%
rename from packages/SettingsLib/MainSwitchPreference/res/color-night-v35/settingslib_main_switch_text_color.xml
rename to packages/SettingsLib/MainSwitchPreference/res/color-night-v36/settingslib_main_switch_text_color.xml
diff --git a/packages/SettingsLib/MainSwitchPreference/res/color-v35/settingslib_main_switch_text_color.xml b/packages/SettingsLib/MainSwitchPreference/res/color-v36/settingslib_main_switch_text_color.xml
similarity index 100%
rename from packages/SettingsLib/MainSwitchPreference/res/color-v35/settingslib_main_switch_text_color.xml
rename to packages/SettingsLib/MainSwitchPreference/res/color-v36/settingslib_main_switch_text_color.xml
diff --git a/packages/SettingsLib/MainSwitchPreference/res/drawable-v35/settingslib_expressive_switch_bar_bg.xml b/packages/SettingsLib/MainSwitchPreference/res/drawable-v36/settingslib_expressive_switch_bar_bg.xml
similarity index 100%
rename from packages/SettingsLib/MainSwitchPreference/res/drawable-v35/settingslib_expressive_switch_bar_bg.xml
rename to packages/SettingsLib/MainSwitchPreference/res/drawable-v36/settingslib_expressive_switch_bar_bg.xml
diff --git a/packages/SettingsLib/MainSwitchPreference/res/layout-v35/settingslib_expressive_main_switch_bar.xml b/packages/SettingsLib/MainSwitchPreference/res/layout-v36/settingslib_expressive_main_switch_bar.xml
similarity index 100%
rename from packages/SettingsLib/MainSwitchPreference/res/layout-v35/settingslib_expressive_main_switch_bar.xml
rename to packages/SettingsLib/MainSwitchPreference/res/layout-v36/settingslib_expressive_main_switch_bar.xml
diff --git a/packages/SettingsLib/MainSwitchPreference/res/layout-v35/settingslib_expressive_main_switch_layout.xml b/packages/SettingsLib/MainSwitchPreference/res/layout-v36/settingslib_expressive_main_switch_layout.xml
similarity index 100%
rename from packages/SettingsLib/MainSwitchPreference/res/layout-v35/settingslib_expressive_main_switch_layout.xml
rename to packages/SettingsLib/MainSwitchPreference/res/layout-v36/settingslib_expressive_main_switch_layout.xml
diff --git a/packages/SettingsLib/ProfileSelector/res/color-night-v35/settingslib_tabs_indicator_color.xml b/packages/SettingsLib/ProfileSelector/res/color-night-v36/settingslib_tabs_indicator_color.xml
similarity index 100%
rename from packages/SettingsLib/ProfileSelector/res/color-night-v35/settingslib_tabs_indicator_color.xml
rename to packages/SettingsLib/ProfileSelector/res/color-night-v36/settingslib_tabs_indicator_color.xml
diff --git a/packages/SettingsLib/SettingsTheme/res/color-night-v35/settingslib_switch_track_outline_color.xml b/packages/SettingsLib/SettingsTheme/res/color-night-v36/settingslib_switch_track_outline_color.xml
similarity index 100%
rename from packages/SettingsLib/SettingsTheme/res/color-night-v35/settingslib_switch_track_outline_color.xml
rename to packages/SettingsLib/SettingsTheme/res/color-night-v36/settingslib_switch_track_outline_color.xml
diff --git a/packages/SettingsLib/SettingsTheme/res/color-v35/settingslib_expressive_color_main_switch_track.xml b/packages/SettingsLib/SettingsTheme/res/color-v36/settingslib_expressive_color_main_switch_track.xml
similarity index 100%
rename from packages/SettingsLib/SettingsTheme/res/color-v35/settingslib_expressive_color_main_switch_track.xml
rename to packages/SettingsLib/SettingsTheme/res/color-v36/settingslib_expressive_color_main_switch_track.xml
diff --git a/packages/SettingsLib/SettingsTheme/res/color-v35/settingslib_preference_bg_color.xml b/packages/SettingsLib/SettingsTheme/res/color-v36/settingslib_preference_bg_color.xml
similarity index 100%
rename from packages/SettingsLib/SettingsTheme/res/color-v35/settingslib_preference_bg_color.xml
rename to packages/SettingsLib/SettingsTheme/res/color-v36/settingslib_preference_bg_color.xml
diff --git a/packages/SettingsLib/SettingsTheme/res/color-v35/settingslib_switch_track_outline_color.xml b/packages/SettingsLib/SettingsTheme/res/color-v36/settingslib_switch_track_outline_color.xml
similarity index 100%
rename from packages/SettingsLib/SettingsTheme/res/color-v35/settingslib_switch_track_outline_color.xml
rename to packages/SettingsLib/SettingsTheme/res/color-v36/settingslib_switch_track_outline_color.xml
diff --git a/packages/SettingsLib/SettingsTheme/res/color-v35/settingslib_text_color_primary.xml b/packages/SettingsLib/SettingsTheme/res/color-v36/settingslib_text_color_primary.xml
similarity index 100%
rename from packages/SettingsLib/SettingsTheme/res/color-v35/settingslib_text_color_primary.xml
rename to packages/SettingsLib/SettingsTheme/res/color-v36/settingslib_text_color_primary.xml
diff --git a/packages/SettingsLib/SettingsTheme/res/color-v35/settingslib_text_color_secondary.xml b/packages/SettingsLib/SettingsTheme/res/color-v36/settingslib_text_color_secondary.xml
similarity index 100%
rename from packages/SettingsLib/SettingsTheme/res/color-v35/settingslib_text_color_secondary.xml
rename to packages/SettingsLib/SettingsTheme/res/color-v36/settingslib_text_color_secondary.xml
diff --git a/packages/SettingsLib/SettingsTheme/res/drawable-v35/settingslib_arrow_drop_down.xml b/packages/SettingsLib/SettingsTheme/res/drawable-v36/settingslib_arrow_drop_down.xml
similarity index 100%
rename from packages/SettingsLib/SettingsTheme/res/drawable-v35/settingslib_arrow_drop_down.xml
rename to packages/SettingsLib/SettingsTheme/res/drawable-v36/settingslib_arrow_drop_down.xml
diff --git a/packages/SettingsLib/SettingsTheme/res/drawable-v35/settingslib_list_divider.xml b/packages/SettingsLib/SettingsTheme/res/drawable-v36/settingslib_list_divider.xml
similarity index 100%
rename from packages/SettingsLib/SettingsTheme/res/drawable-v35/settingslib_list_divider.xml
rename to packages/SettingsLib/SettingsTheme/res/drawable-v36/settingslib_list_divider.xml
diff --git a/packages/SettingsLib/SettingsTheme/res/drawable-v35/settingslib_progress_horizontal.xml b/packages/SettingsLib/SettingsTheme/res/drawable-v36/settingslib_progress_horizontal.xml
similarity index 100%
rename from packages/SettingsLib/SettingsTheme/res/drawable-v35/settingslib_progress_horizontal.xml
rename to packages/SettingsLib/SettingsTheme/res/drawable-v36/settingslib_progress_horizontal.xml
diff --git a/packages/SettingsLib/SettingsTheme/res/drawable-v35/settingslib_round_background.xml b/packages/SettingsLib/SettingsTheme/res/drawable-v36/settingslib_round_background.xml
similarity index 100%
rename from packages/SettingsLib/SettingsTheme/res/drawable-v35/settingslib_round_background.xml
rename to packages/SettingsLib/SettingsTheme/res/drawable-v36/settingslib_round_background.xml
diff --git a/packages/SettingsLib/SettingsTheme/res/drawable-v35/settingslib_round_background_bottom.xml b/packages/SettingsLib/SettingsTheme/res/drawable-v36/settingslib_round_background_bottom.xml
similarity index 100%
rename from packages/SettingsLib/SettingsTheme/res/drawable-v35/settingslib_round_background_bottom.xml
rename to packages/SettingsLib/SettingsTheme/res/drawable-v36/settingslib_round_background_bottom.xml
diff --git a/packages/SettingsLib/SettingsTheme/res/drawable-v35/settingslib_round_background_bottom_highlighted.xml b/packages/SettingsLib/SettingsTheme/res/drawable-v36/settingslib_round_background_bottom_highlighted.xml
similarity index 100%
rename from packages/SettingsLib/SettingsTheme/res/drawable-v35/settingslib_round_background_bottom_highlighted.xml
rename to packages/SettingsLib/SettingsTheme/res/drawable-v36/settingslib_round_background_bottom_highlighted.xml
diff --git a/packages/SettingsLib/SettingsTheme/res/drawable-v35/settingslib_round_background_bottom_selected.xml b/packages/SettingsLib/SettingsTheme/res/drawable-v36/settingslib_round_background_bottom_selected.xml
similarity index 100%
rename from packages/SettingsLib/SettingsTheme/res/drawable-v35/settingslib_round_background_bottom_selected.xml
rename to packages/SettingsLib/SettingsTheme/res/drawable-v36/settingslib_round_background_bottom_selected.xml
diff --git a/packages/SettingsLib/SettingsTheme/res/drawable-v35/settingslib_round_background_center.xml b/packages/SettingsLib/SettingsTheme/res/drawable-v36/settingslib_round_background_center.xml
similarity index 100%
rename from packages/SettingsLib/SettingsTheme/res/drawable-v35/settingslib_round_background_center.xml
rename to packages/SettingsLib/SettingsTheme/res/drawable-v36/settingslib_round_background_center.xml
diff --git a/packages/SettingsLib/SettingsTheme/res/drawable-v35/settingslib_round_background_center_highlighted.xml b/packages/SettingsLib/SettingsTheme/res/drawable-v36/settingslib_round_background_center_highlighted.xml
similarity index 100%
rename from packages/SettingsLib/SettingsTheme/res/drawable-v35/settingslib_round_background_center_highlighted.xml
rename to packages/SettingsLib/SettingsTheme/res/drawable-v36/settingslib_round_background_center_highlighted.xml
diff --git a/packages/SettingsLib/SettingsTheme/res/drawable-v35/settingslib_round_background_center_selected.xml b/packages/SettingsLib/SettingsTheme/res/drawable-v36/settingslib_round_background_center_selected.xml
similarity index 100%
rename from packages/SettingsLib/SettingsTheme/res/drawable-v35/settingslib_round_background_center_selected.xml
rename to packages/SettingsLib/SettingsTheme/res/drawable-v36/settingslib_round_background_center_selected.xml
diff --git a/packages/SettingsLib/SettingsTheme/res/drawable-v35/settingslib_round_background_highlighted.xml b/packages/SettingsLib/SettingsTheme/res/drawable-v36/settingslib_round_background_highlighted.xml
similarity index 100%
rename from packages/SettingsLib/SettingsTheme/res/drawable-v35/settingslib_round_background_highlighted.xml
rename to packages/SettingsLib/SettingsTheme/res/drawable-v36/settingslib_round_background_highlighted.xml
diff --git a/packages/SettingsLib/SettingsTheme/res/drawable-v35/settingslib_round_background_selected.xml b/packages/SettingsLib/SettingsTheme/res/drawable-v36/settingslib_round_background_selected.xml
similarity index 100%
rename from packages/SettingsLib/SettingsTheme/res/drawable-v35/settingslib_round_background_selected.xml
rename to packages/SettingsLib/SettingsTheme/res/drawable-v36/settingslib_round_background_selected.xml
diff --git a/packages/SettingsLib/SettingsTheme/res/drawable-v35/settingslib_round_background_top.xml b/packages/SettingsLib/SettingsTheme/res/drawable-v36/settingslib_round_background_top.xml
similarity index 100%
rename from packages/SettingsLib/SettingsTheme/res/drawable-v35/settingslib_round_background_top.xml
rename to packages/SettingsLib/SettingsTheme/res/drawable-v36/settingslib_round_background_top.xml
diff --git a/packages/SettingsLib/SettingsTheme/res/drawable-v35/settingslib_round_background_top_highlighted.xml b/packages/SettingsLib/SettingsTheme/res/drawable-v36/settingslib_round_background_top_highlighted.xml
similarity index 100%
rename from packages/SettingsLib/SettingsTheme/res/drawable-v35/settingslib_round_background_top_highlighted.xml
rename to packages/SettingsLib/SettingsTheme/res/drawable-v36/settingslib_round_background_top_highlighted.xml
diff --git a/packages/SettingsLib/SettingsTheme/res/drawable-v35/settingslib_round_background_top_selected.xml b/packages/SettingsLib/SettingsTheme/res/drawable-v36/settingslib_round_background_top_selected.xml
similarity index 100%
rename from packages/SettingsLib/SettingsTheme/res/drawable-v35/settingslib_round_background_top_selected.xml
rename to packages/SettingsLib/SettingsTheme/res/drawable-v36/settingslib_round_background_top_selected.xml
diff --git a/packages/SettingsLib/SettingsTheme/res/drawable-v35/settingslib_spinner_background.xml b/packages/SettingsLib/SettingsTheme/res/drawable-v36/settingslib_spinner_background.xml
similarity index 100%
rename from packages/SettingsLib/SettingsTheme/res/drawable-v35/settingslib_spinner_background.xml
rename to packages/SettingsLib/SettingsTheme/res/drawable-v36/settingslib_spinner_background.xml
diff --git a/packages/SettingsLib/SettingsTheme/res/drawable-v35/settingslib_spinner_dropdown_background.xml b/packages/SettingsLib/SettingsTheme/res/drawable-v36/settingslib_spinner_dropdown_background.xml
similarity index 100%
rename from packages/SettingsLib/SettingsTheme/res/drawable-v35/settingslib_spinner_dropdown_background.xml
rename to packages/SettingsLib/SettingsTheme/res/drawable-v36/settingslib_spinner_dropdown_background.xml
diff --git a/packages/SettingsLib/SettingsTheme/res/layout-v35/settingslib_expressive_preference.xml b/packages/SettingsLib/SettingsTheme/res/layout-v36/settingslib_expressive_preference.xml
similarity index 100%
rename from packages/SettingsLib/SettingsTheme/res/layout-v35/settingslib_expressive_preference.xml
rename to packages/SettingsLib/SettingsTheme/res/layout-v36/settingslib_expressive_preference.xml
diff --git a/packages/SettingsLib/SettingsTheme/res/layout-v35/settingslib_expressive_preference_icon_frame.xml b/packages/SettingsLib/SettingsTheme/res/layout-v36/settingslib_expressive_preference_icon_frame.xml
similarity index 100%
rename from packages/SettingsLib/SettingsTheme/res/layout-v35/settingslib_expressive_preference_icon_frame.xml
rename to packages/SettingsLib/SettingsTheme/res/layout-v36/settingslib_expressive_preference_icon_frame.xml
diff --git a/packages/SettingsLib/SettingsTheme/res/layout-v35/settingslib_expressive_preference_switch.xml b/packages/SettingsLib/SettingsTheme/res/layout-v36/settingslib_expressive_preference_switch.xml
similarity index 100%
rename from packages/SettingsLib/SettingsTheme/res/layout-v35/settingslib_expressive_preference_switch.xml
rename to packages/SettingsLib/SettingsTheme/res/layout-v36/settingslib_expressive_preference_switch.xml
diff --git a/packages/SettingsLib/SettingsTheme/res/layout-v35/settingslib_expressive_two_target_divider.xml b/packages/SettingsLib/SettingsTheme/res/layout-v36/settingslib_expressive_two_target_divider.xml
similarity index 100%
rename from packages/SettingsLib/SettingsTheme/res/layout-v35/settingslib_expressive_two_target_divider.xml
rename to packages/SettingsLib/SettingsTheme/res/layout-v36/settingslib_expressive_two_target_divider.xml
diff --git a/packages/SettingsLib/SettingsTheme/res/values-night-v35/colors.xml b/packages/SettingsLib/SettingsTheme/res/values-night-v36/colors.xml
similarity index 100%
rename from packages/SettingsLib/SettingsTheme/res/values-night-v35/colors.xml
rename to packages/SettingsLib/SettingsTheme/res/values-night-v36/colors.xml
diff --git a/packages/SettingsLib/SettingsTheme/res/values-v35/colors.xml b/packages/SettingsLib/SettingsTheme/res/values-v36/colors.xml
similarity index 100%
rename from packages/SettingsLib/SettingsTheme/res/values-v35/colors.xml
rename to packages/SettingsLib/SettingsTheme/res/values-v36/colors.xml
diff --git a/packages/SettingsLib/SettingsTheme/res/values-v35/dimens.xml b/packages/SettingsLib/SettingsTheme/res/values-v36/dimens.xml
similarity index 100%
rename from packages/SettingsLib/SettingsTheme/res/values-v35/dimens.xml
rename to packages/SettingsLib/SettingsTheme/res/values-v36/dimens.xml
diff --git a/packages/SettingsLib/SettingsTheme/res/values-v35/styles_expressive.xml b/packages/SettingsLib/SettingsTheme/res/values-v36/styles_expressive.xml
similarity index 100%
rename from packages/SettingsLib/SettingsTheme/res/values-v35/styles_expressive.xml
rename to packages/SettingsLib/SettingsTheme/res/values-v36/styles_expressive.xml
diff --git a/packages/SettingsLib/SettingsTheme/res/values-v35/styles_preference_expressive.xml b/packages/SettingsLib/SettingsTheme/res/values-v36/styles_preference_expressive.xml
similarity index 100%
rename from packages/SettingsLib/SettingsTheme/res/values-v35/styles_preference_expressive.xml
rename to packages/SettingsLib/SettingsTheme/res/values-v36/styles_preference_expressive.xml
diff --git a/packages/SettingsLib/SettingsTheme/res/values-v35/themes.xml b/packages/SettingsLib/SettingsTheme/res/values-v36/themes.xml
similarity index 94%
rename from packages/SettingsLib/SettingsTheme/res/values-v35/themes.xml
rename to packages/SettingsLib/SettingsTheme/res/values-v36/themes.xml
index b6e80c7..1c45ff6 100644
--- a/packages/SettingsLib/SettingsTheme/res/values-v35/themes.xml
+++ b/packages/SettingsLib/SettingsTheme/res/values-v36/themes.xml
@@ -16,7 +16,7 @@
   -->
 
 <resources>
-    <style name="Theme.SettingsBase_v35" parent="Theme.SettingsBase_v33" >
+    <style name="Theme.SettingsBase_v36" parent="Theme.SettingsBase_v33" >
         <item name="android:colorAccent">@color/settingslib_materialColorPrimary</item>
         <item name="android:colorBackground">@color/settingslib_materialColorSurfaceContainer</item>
         <item name="android:textColorPrimary">@color/settingslib_materialColorOnSurface</item>
@@ -27,5 +27,5 @@
         <item name="android:clipChildren">false</item>
     </style>
 
-    <style name="Theme.SettingsBase" parent="Theme.SettingsBase_v35" />
+    <style name="Theme.SettingsBase" parent="Theme.SettingsBase_v36" />
 </resources>
\ No newline at end of file
diff --git a/packages/SettingsLib/SettingsTheme/res/values-v35/themes_expressive.xml b/packages/SettingsLib/SettingsTheme/res/values-v36/themes_expressive.xml
similarity index 100%
rename from packages/SettingsLib/SettingsTheme/res/values-v35/themes_expressive.xml
rename to packages/SettingsLib/SettingsTheme/res/values-v36/themes_expressive.xml
diff --git a/packages/SettingsLib/SettingsTheme/res/values-v35/themes_preference_expressive.xml b/packages/SettingsLib/SettingsTheme/res/values-v36/themes_preference_expressive.xml
similarity index 100%
rename from packages/SettingsLib/SettingsTheme/res/values-v35/themes_preference_expressive.xml
rename to packages/SettingsLib/SettingsTheme/res/values-v36/themes_preference_expressive.xml
diff --git a/packages/SettingsLib/TwoTargetPreference/res/layout-v35/settingslib_expressive_preference_two_target.xml b/packages/SettingsLib/TwoTargetPreference/res/layout-v36/settingslib_expressive_preference_two_target.xml
similarity index 100%
rename from packages/SettingsLib/TwoTargetPreference/res/layout-v35/settingslib_expressive_preference_two_target.xml
rename to packages/SettingsLib/TwoTargetPreference/res/layout-v36/settingslib_expressive_preference_two_target.xml
diff --git a/packages/SystemUI/aconfig/systemui.aconfig b/packages/SystemUI/aconfig/systemui.aconfig
index eb5b22f..f2c76ba 100644
--- a/packages/SystemUI/aconfig/systemui.aconfig
+++ b/packages/SystemUI/aconfig/systemui.aconfig
@@ -1939,6 +1939,16 @@
 }
 
 flag {
+   name: "notification_appear_nonlinear"
+   namespace: "systemui"
+   description: "Fix linear usage of notification appear"
+   bug: "397658189"
+   metadata {
+     purpose: PURPOSE_BUGFIX
+   }
+}
+
+flag {
   name: "disable_shade_trackpad_two_finger_swipe"
   namespace: "systemui"
   description: "Disables expansion of the shade via two finger swipe on a trackpad"
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/tiles/CastTileTest.java b/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/tiles/CastTileTest.java
index 31a627f..765c574 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/tiles/CastTileTest.java
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/tiles/CastTileTest.java
@@ -50,6 +50,8 @@
 import com.android.systemui.qs.QSHost;
 import com.android.systemui.qs.QsEventLogger;
 import com.android.systemui.qs.logging.QSLogger;
+import com.android.systemui.shade.domain.interactor.FakeShadeDialogContextInteractor;
+import com.android.systemui.shade.domain.interactor.ShadeDialogContextInteractor;
 import com.android.systemui.statusbar.connectivity.IconState;
 import com.android.systemui.statusbar.connectivity.NetworkController;
 import com.android.systemui.statusbar.connectivity.SignalCallback;
@@ -107,6 +109,8 @@
     private final FakeConnectivityRepository mConnectivityRepository =
             new FakeConnectivityRepository();
     private final FakeFeatureFlags mFeatureFlags = new FakeFeatureFlags();
+    private final ShadeDialogContextInteractor mShadeDialogContextInteractor =
+            new FakeShadeDialogContextInteractor(mContext);
 
     private TestableLooper mTestableLooper;
     private CastTile mCastTile;
@@ -535,7 +539,8 @@
                 mDialogTransitionAnimator,
                 mConnectivityRepository,
                 mJavaAdapter,
-                mFeatureFlags
+                mFeatureFlags,
+                mShadeDialogContextInteractor
         );
         mCastTile.initialize();
 
@@ -578,7 +583,8 @@
                 mDialogTransitionAnimator,
                 mConnectivityRepository,
                 mJavaAdapter,
-                mFeatureFlags
+                mFeatureFlags,
+                mShadeDialogContextInteractor
         );
         mCastTile.initialize();
 
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 83361da..4b06cde 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/NotificationShadeDepthControllerTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/NotificationShadeDepthControllerTest.kt
@@ -34,7 +34,6 @@
 import com.android.systemui.plugins.statusbar.StatusBarStateController
 import com.android.systemui.res.R
 import com.android.systemui.shade.ShadeExpansionChangeEvent
-import com.android.systemui.shared.Flags as SharedFlags
 import com.android.systemui.statusbar.phone.BiometricUnlockController
 import com.android.systemui.statusbar.phone.DozeParameters
 import com.android.systemui.statusbar.phone.ScrimController
@@ -44,11 +43,10 @@
 import com.android.systemui.testKosmos
 import com.android.systemui.util.WallpaperController
 import com.android.systemui.util.mockito.eq
+import com.android.systemui.wallpapers.domain.interactor.WallpaperInteractor
 import com.android.systemui.window.domain.interactor.WindowRootViewBlurInteractor
 import com.android.wm.shell.appzoomout.AppZoomOut
 import com.google.common.truth.Truth.assertThat
-import java.util.Optional
-import java.util.function.Consumer
 import org.junit.Before
 import org.junit.Rule
 import org.junit.Test
@@ -69,6 +67,8 @@
 import org.mockito.Mockito.verify
 import org.mockito.Mockito.`when`
 import org.mockito.junit.MockitoJUnit
+import java.util.Optional
+import java.util.function.Consumer
 
 @RunWith(AndroidJUnit4::class)
 @RunWithLooper
@@ -76,6 +76,7 @@
 class NotificationShadeDepthControllerTest : SysuiTestCase() {
     private val kosmos = testKosmos()
 
+    private val applicationScope = kosmos.testScope.backgroundScope
     @Mock private lateinit var windowRootViewBlurInteractor: WindowRootViewBlurInteractor
     @Mock private lateinit var statusBarStateController: StatusBarStateController
     @Mock private lateinit var blurUtils: BlurUtils
@@ -84,6 +85,7 @@
     @Mock private lateinit var keyguardInteractor: KeyguardInteractor
     @Mock private lateinit var choreographer: Choreographer
     @Mock private lateinit var wallpaperController: WallpaperController
+    @Mock private lateinit var wallpaperInteractor: WallpaperInteractor
     @Mock private lateinit var notificationShadeWindowController: NotificationShadeWindowController
     @Mock private lateinit var dumpManager: DumpManager
     @Mock private lateinit var appZoomOutOptional: Optional<AppZoomOut>
@@ -128,12 +130,14 @@
                 keyguardInteractor,
                 choreographer,
                 wallpaperController,
+                wallpaperInteractor,
                 notificationShadeWindowController,
                 dozeParameters,
                 context,
                 ResourcesSplitShadeStateController(),
                 windowRootViewBlurInteractor,
                 appZoomOutOptional,
+                applicationScope,
                 dumpManager,
                 configurationController,
             )
@@ -310,22 +314,24 @@
     }
 
     @Test
-    @DisableFlags(SharedFlags.FLAG_AMBIENT_AOD)
-    fun onDozeAmountChanged_appliesBlur() {
-        statusBarStateListener.onDozeAmountChanged(1f, 1f)
-        notificationShadeDepthController.updateBlurCallback.doFrame(0)
-        verify(blurUtils).applyBlur(any(), eq(maxBlur), eq(false))
-    }
-
-    @Test
-    @EnableFlags(SharedFlags.FLAG_AMBIENT_AOD)
     fun onDozeAmountChanged_doesNotApplyBlurWithAmbientAod() {
+        notificationShadeDepthController.wallpaperSupportsAmbientMode = false
+
         statusBarStateListener.onDozeAmountChanged(1f, 1f)
         notificationShadeDepthController.updateBlurCallback.doFrame(0)
         verify(blurUtils).applyBlur(any(), eq(0), eq(false))
     }
 
     @Test
+    fun onDozeAmountChanged_appliesBlurWithAmbientAod() {
+        notificationShadeDepthController.wallpaperSupportsAmbientMode = true
+
+        statusBarStateListener.onDozeAmountChanged(1f, 1f)
+        notificationShadeDepthController.updateBlurCallback.doFrame(0)
+        verify(blurUtils).applyBlur(any(), eq(maxBlur), eq(false))
+    }
+
+    @Test
     fun setFullShadeTransition_appliesBlur_onlyIfSupported() {
         reset(blurUtils)
         `when`(blurUtils.blurRadiusOfRatio(anyFloat())).then { answer ->
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/chips/ui/viewmodel/OngoingActivityChipsViewModelTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/chips/ui/viewmodel/OngoingActivityChipsViewModelTest.kt
index 719924c..1b5b0d6 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/chips/ui/viewmodel/OngoingActivityChipsViewModelTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/chips/ui/viewmodel/OngoingActivityChipsViewModelTest.kt
@@ -72,7 +72,6 @@
 /** Tests for [OngoingActivityChipsViewModel] when the [StatusBarNotifChips] flag is disabled. */
 @SmallTest
 @RunWith(AndroidJUnit4::class)
-@EnableFlags(StatusBarChipsModernization.FLAG_NAME)
 @DisableFlags(StatusBarNotifChips.FLAG_NAME)
 class OngoingActivityChipsViewModelTest : SysuiTestCase() {
     private val kosmos = testKosmos().useUnconfinedTestDispatcher()
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/notification/stack/StackStateAnimatorTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/notification/stack/StackStateAnimatorTest.kt
index 67415de..e7be20e 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/notification/stack/StackStateAnimatorTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/notification/stack/StackStateAnimatorTest.kt
@@ -88,6 +88,7 @@
                 /* delay= */ 0L,
                 /* duration= */ ANIMATION_DURATION_HEADS_UP_APPEAR.toLong(),
                 /* isHeadsUpAppear= */ true,
+                /* isHeadsUpCycling= */ false,
                 /* onEndRunnable= */ null,
             )
     }
@@ -111,6 +112,7 @@
                 /* delay= */ 0L,
                 /* duration= */ ANIMATION_DURATION_HEADS_UP_APPEAR.toLong(),
                 /* isHeadsUpAppear= */ true,
+                /* isHeadsUpCycling= */ false,
                 /* onEndRunnable= */ null,
             )
     }
@@ -128,6 +130,7 @@
                 /* delay= */ eq(0L),
                 /* translationDirection= */ eq(0f),
                 /* isHeadsUpAnimation= */ eq(true),
+                /* isHeadsUpCycling= */ eq(false),
                 /* onStartedRunnable= */ any(),
                 /* onFinishedRunnable= */ runnableCaptor.capture(),
                 /* animationListener= */ any(),
diff --git a/packages/SystemUI/res/anim/volume_dialog_ringer_close.xml b/packages/SystemUI/res/anim/volume_dialog_ringer_close.xml
new file mode 100644
index 0000000..e7ba52c
--- /dev/null
+++ b/packages/SystemUI/res/anim/volume_dialog_ringer_close.xml
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="utf-8"?><!--
+  ~ 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.
+  -->
+
+<pathInterpolator
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    android:controlX1="0.20"
+    android:controlY1="0.00"
+    android:controlX2="0.00"
+    android:controlY2="1.00" />
\ No newline at end of file
diff --git a/packages/SystemUI/res/anim/volume_dialog_ringer_open.xml b/packages/SystemUI/res/anim/volume_dialog_ringer_open.xml
new file mode 100644
index 0000000..3b18eef
--- /dev/null
+++ b/packages/SystemUI/res/anim/volume_dialog_ringer_open.xml
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="utf-8"?><!--
+  ~ 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.
+  -->
+
+<pathInterpolator
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    android:controlX1="0.05"
+    android:controlY1="0.70"
+    android:controlX2="0.10"
+    android:controlY2="1.00" />
\ No newline at end of file
diff --git a/packages/SystemUI/src/com/android/systemui/media/controls/ui/controller/MediaHierarchyManager.kt b/packages/SystemUI/src/com/android/systemui/media/controls/ui/controller/MediaHierarchyManager.kt
index b64cb3d..f06c4cc 100644
--- a/packages/SystemUI/src/com/android/systemui/media/controls/ui/controller/MediaHierarchyManager.kt
+++ b/packages/SystemUI/src/com/android/systemui/media/controls/ui/controller/MediaHierarchyManager.kt
@@ -58,6 +58,7 @@
 import com.android.systemui.statusbar.CrossFadeHelper
 import com.android.systemui.statusbar.StatusBarState
 import com.android.systemui.statusbar.SysuiStatusBarStateController
+import com.android.systemui.statusbar.featurepods.popups.StatusBarPopupChips
 import com.android.systemui.statusbar.notification.stack.StackStateAnimator
 import com.android.systemui.statusbar.phone.KeyguardBypassController
 import com.android.systemui.statusbar.policy.ConfigurationController
@@ -229,7 +230,7 @@
         else result.setIntersect(animationStartClipping, targetClipping)
     }
 
-    private val mediaHosts = arrayOfNulls<MediaHost>(LOCATION_COMMUNAL_HUB + 1)
+    private val mediaHosts = arrayOfNulls<MediaHost>(LOCATION_STATUS_BAR_POPUP + 1)
 
     /**
      * The last location where this view was at before going to the desired location. This is useful
@@ -374,6 +375,15 @@
             }
         }
 
+    /** Is the Media Control StatusBarPopup showing */
+    var isMediaControlPopupShowing: Boolean = false
+        set(value) {
+            if (field != value && StatusBarPopupChips.isEnabled) {
+                field = value
+                updateDesiredLocation(forceNoAnimation = true)
+            }
+        }
+
     /** Are location changes currently blocked? */
     private val blockLocationChanges: Boolean
         get() {
@@ -1225,6 +1235,7 @@
             // Keep the current location until we're allowed to again
             return desiredLocation
         }
+
         val onLockscreen =
             (!bypassController.bypassEnabled && (statusbarState == StatusBarState.KEYGUARD))
 
@@ -1234,6 +1245,8 @@
             (onCommunalNotDreaming && qsExpansion == 0.0f) || onCommunalDreamingAndShadeExpanding
         val location =
             when {
+                isMediaControlPopupShowing && StatusBarPopupChips.isEnabled ->
+                    LOCATION_STATUS_BAR_POPUP
                 dreamOverlayActive && dreamMediaComplicationActive -> LOCATION_DREAM_OVERLAY
                 onCommunal -> LOCATION_COMMUNAL_HUB
                 (qsExpansion > 0.0f || inSplitShade) && !onLockscreen -> LOCATION_QS
@@ -1377,6 +1390,9 @@
         /** Attached to a view in the communal UI grid */
         const val LOCATION_COMMUNAL_HUB = 4
 
+        /** Attached to a popup that is shown with a media control chip in the status bar */
+        const val LOCATION_STATUS_BAR_POPUP = 5
+
         /** Attached at the root of the hierarchy in an overlay */
         const val IN_OVERLAY = -1000
 
@@ -1422,6 +1438,7 @@
             MediaHierarchyManager.LOCATION_LOCKSCREEN,
             MediaHierarchyManager.LOCATION_DREAM_OVERLAY,
             MediaHierarchyManager.LOCATION_COMMUNAL_HUB,
+            MediaHierarchyManager.LOCATION_STATUS_BAR_POPUP,
             MediaHierarchyManager.LOCATION_UNKNOWN,
         ],
 )
diff --git a/packages/SystemUI/src/com/android/systemui/media/controls/util/MediaUiEventLogger.kt b/packages/SystemUI/src/com/android/systemui/media/controls/util/MediaUiEventLogger.kt
index 09f973c..f0da226 100644
--- a/packages/SystemUI/src/com/android/systemui/media/controls/util/MediaUiEventLogger.kt
+++ b/packages/SystemUI/src/com/android/systemui/media/controls/util/MediaUiEventLogger.kt
@@ -45,7 +45,7 @@
         uid: Int,
         packageName: String,
         instanceId: InstanceId,
-        playbackLocation: Int
+        playbackLocation: Int,
     ) {
         val event =
             when (playbackLocation) {
@@ -61,7 +61,7 @@
         uid: Int,
         packageName: String,
         instanceId: InstanceId,
-        playbackLocation: Int
+        playbackLocation: Int,
     ) {
         val event =
             when (playbackLocation) {
@@ -112,7 +112,7 @@
             MediaUiEvent.OPEN_SETTINGS_LONG_PRESS,
             uid,
             packageName,
-            instanceId
+            instanceId,
         )
     }
 
@@ -156,6 +156,8 @@
                     MediaUiEvent.MEDIA_CAROUSEL_LOCATION_DREAM
                 MediaHierarchyManager.LOCATION_COMMUNAL_HUB ->
                     MediaUiEvent.MEDIA_CAROUSEL_LOCATION_COMMUNAL
+                MediaHierarchyManager.LOCATION_STATUS_BAR_POPUP ->
+                    MediaUiEvent.MEDIA_CAROUSEL_LOCATION_STATUS_BAR_POPUP
                 else -> throw IllegalArgumentException("Unknown media carousel location $location")
             }
         logger.log(event)
@@ -166,7 +168,7 @@
             MediaUiEvent.MEDIA_RECOMMENDATION_ADDED,
             0,
             packageName,
-            instanceId
+            instanceId,
         )
     }
 
@@ -175,7 +177,7 @@
             MediaUiEvent.MEDIA_RECOMMENDATION_REMOVED,
             0,
             packageName,
-            instanceId
+            instanceId,
         )
     }
 
@@ -184,7 +186,7 @@
             MediaUiEvent.MEDIA_RECOMMENDATION_ACTIVATED,
             uid,
             packageName,
-            instanceId
+            instanceId,
         )
     }
 
@@ -194,7 +196,7 @@
             0,
             packageName,
             instanceId,
-            position
+            position,
         )
     }
 
@@ -203,7 +205,7 @@
             MediaUiEvent.MEDIA_RECOMMENDATION_CARD_TAP,
             0,
             packageName,
-            instanceId
+            instanceId,
         )
     }
 
@@ -212,7 +214,7 @@
             MediaUiEvent.MEDIA_OPEN_BROADCAST_DIALOG,
             uid,
             packageName,
-            instanceId
+            instanceId,
         )
     }
 
@@ -221,7 +223,7 @@
             MediaUiEvent.MEDIA_CAROUSEL_SINGLE_PLAYER,
             uid,
             packageName,
-            instanceId
+            instanceId,
         )
     }
 
@@ -230,7 +232,7 @@
             MediaUiEvent.MEDIA_CAROUSEL_MULTIPLE_PLAYERS,
             uid,
             packageName,
-            instanceId
+            instanceId,
         )
     }
 }
@@ -280,6 +282,8 @@
     MEDIA_CAROUSEL_LOCATION_DREAM(1040),
     @UiEvent(doc = "The media carousel moved to the communal hub UI")
     MEDIA_CAROUSEL_LOCATION_COMMUNAL(1520),
+    @UiEvent(doc = "The media carousel moved to the status bar popup")
+    MEDIA_CAROUSEL_LOCATION_STATUS_BAR_POPUP(2170),
     @UiEvent(doc = "A media recommendation card was added to the media carousel")
     MEDIA_RECOMMENDATION_ADDED(1041),
     @UiEvent(doc = "A media recommendation card was removed from the media carousel")
diff --git a/packages/SystemUI/src/com/android/systemui/media/dagger/MediaModule.java b/packages/SystemUI/src/com/android/systemui/media/dagger/MediaModule.java
index 45a3a8c..662a9c7 100644
--- a/packages/SystemUI/src/com/android/systemui/media/dagger/MediaModule.java
+++ b/packages/SystemUI/src/com/android/systemui/media/dagger/MediaModule.java
@@ -49,6 +49,7 @@
     String KEYGUARD = "media_keyguard";
     String DREAM = "dream";
     String COMMUNAL_HUB = "communal_Hub";
+    String POPUP = "popup";
 
     /** */
     @Provides
@@ -102,7 +103,26 @@
     @Provides
     @SysUISingleton
     @Named(COMMUNAL_HUB)
-    static MediaHost providesCommunalMediaHost(MediaHost.MediaHostStateHolder stateHolder,
+    static MediaHost providesCommunalMediaHost(
+            MediaHost.MediaHostStateHolder stateHolder,
+            MediaHierarchyManager hierarchyManager,
+            MediaDataManager dataManager,
+            MediaHostStatesManager statesManager,
+            MediaCarouselController carouselController,
+            MediaCarouselControllerLogger logger) {
+        return new MediaHost(
+                stateHolder,
+                hierarchyManager,
+                dataManager,
+                statesManager,
+                carouselController,
+                logger);
+    }
+
+    @Provides
+    @SysUISingleton
+    @Named(POPUP)
+    static MediaHost providesPopupMediaHost(MediaHost.MediaHostStateHolder stateHolder,
             MediaHierarchyManager hierarchyManager, MediaDataManager dataManager,
             MediaHostStatesManager statesManager, MediaCarouselController carouselController,
             MediaCarouselControllerLogger logger) {
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/CastTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/CastTile.java
index 30c2adf..c60e3da 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/CastTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/CastTile.java
@@ -54,6 +54,7 @@
 import com.android.systemui.qs.logging.QSLogger;
 import com.android.systemui.qs.tileimpl.QSTileImpl;
 import com.android.systemui.res.R;
+import com.android.systemui.shade.domain.interactor.ShadeDialogContextInteractor;
 import com.android.systemui.statusbar.connectivity.NetworkController;
 import com.android.systemui.statusbar.connectivity.SignalCallback;
 import com.android.systemui.statusbar.connectivity.WifiIndicators;
@@ -89,6 +90,7 @@
     private final Callback mCallback = new Callback();
     private final TileJavaAdapter mJavaAdapter;
     private final FeatureFlags mFeatureFlags;
+    private final ShadeDialogContextInteractor mShadeDialogContextInteractor;
     private boolean mCastTransportAllowed;
     private boolean mHotspotConnected;
 
@@ -110,7 +112,8 @@
             DialogTransitionAnimator dialogTransitionAnimator,
             ConnectivityRepository connectivityRepository,
             TileJavaAdapter javaAdapter,
-            FeatureFlags featureFlags
+            FeatureFlags featureFlags,
+            ShadeDialogContextInteractor shadeDialogContextInteractor
     ) {
         super(host, uiEventLogger, backgroundLooper, mainHandler, falsingManager, metricsLogger,
                 statusBarStateController, activityStarter, qsLogger);
@@ -120,6 +123,7 @@
         mDialogTransitionAnimator = dialogTransitionAnimator;
         mJavaAdapter = javaAdapter;
         mFeatureFlags = featureFlags;
+        mShadeDialogContextInteractor = shadeDialogContextInteractor;
         mController.observe(this, mCallback);
         mKeyguard.observe(this, mCallback);
         if (!mFeatureFlags.isEnabled(SIGNAL_CALLBACK_DEPRECATION)) {
@@ -220,7 +224,7 @@
         mUiHandler.post(() -> {
             final DialogHolder holder = new DialogHolder();
             final Dialog dialog = MediaRouteDialogPresenter.createDialog(
-                    mContext,
+                    mShadeDialogContextInteractor.getContext(),
                     ROUTE_TYPE_REMOTE_DISPLAY,
                     v -> {
                         ActivityTransitionAnimator.Controller controller =
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationShadeDepthController.kt b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationShadeDepthController.kt
index 3db0048..84266e8 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationShadeDepthController.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationShadeDepthController.kt
@@ -38,13 +38,13 @@
 import com.android.systemui.Flags.spatialModelAppPushback
 import com.android.systemui.animation.ShadeInterpolation
 import com.android.systemui.dagger.SysUISingleton
+import com.android.systemui.dagger.qualifiers.Application
 import com.android.systemui.dump.DumpManager
 import com.android.systemui.keyguard.domain.interactor.KeyguardInteractor
 import com.android.systemui.plugins.statusbar.StatusBarStateController
 import com.android.systemui.shade.ShadeDisplayAware
 import com.android.systemui.shade.ShadeExpansionChangeEvent
 import com.android.systemui.shade.ShadeExpansionListener
-import com.android.systemui.shared.Flags.ambientAod
 import com.android.systemui.statusbar.phone.BiometricUnlockController
 import com.android.systemui.statusbar.phone.BiometricUnlockController.MODE_WAKE_AND_UNLOCK
 import com.android.systemui.statusbar.phone.DozeParameters
@@ -53,8 +53,11 @@
 import com.android.systemui.statusbar.policy.KeyguardStateController
 import com.android.systemui.statusbar.policy.SplitShadeStateController
 import com.android.systemui.util.WallpaperController
+import com.android.systemui.wallpapers.domain.interactor.WallpaperInteractor
 import com.android.systemui.window.domain.interactor.WindowRootViewBlurInteractor
 import com.android.wm.shell.appzoomout.AppZoomOut
+import kotlinx.coroutines.CoroutineScope
+import kotlinx.coroutines.launch
 import java.io.PrintWriter
 import java.util.Optional
 import javax.inject.Inject
@@ -76,12 +79,14 @@
     private val keyguardInteractor: KeyguardInteractor,
     private val choreographer: Choreographer,
     private val wallpaperController: WallpaperController,
+    private val wallpaperInteractor: WallpaperInteractor,
     private val notificationShadeWindowController: NotificationShadeWindowController,
     private val dozeParameters: DozeParameters,
     @ShadeDisplayAware private val context: Context,
     private val splitShadeStateController: SplitShadeStateController,
     private val windowRootViewBlurInteractor: WindowRootViewBlurInteractor,
     private val appZoomOutOptional: Optional<AppZoomOut>,
+    @Application private val applicationScope: CoroutineScope,
     dumpManager: DumpManager,
     configurationController: ConfigurationController,
 ) : ShadeExpansionListener, Dumpable {
@@ -110,6 +115,8 @@
     private var prevTimestamp: Long = -1
     private var prevShadeDirection = 0
     private var prevShadeVelocity = 0f
+    private var prevDozeAmount: Float = 0f
+    @VisibleForTesting var wallpaperSupportsAmbientMode: Boolean = false
     // tracks whether app launch transition is in progress. This involves two independent factors
     // that control blur, shade expansion and app launch animation from outside sysui.
     // They can complete out of order, this flag will be reset by the animation that finishes later.
@@ -219,7 +226,15 @@
         }
 
     /** Blur radius of the wake-up animation on this frame. */
-    private var wakeAndUnlockBlurRadius = 0f
+    private var wakeBlurRadius = 0f
+        set(value) {
+            if (field == value) return
+            field = value
+            scheduleUpdate()
+        }
+
+    /** Blur radius of the unlock animation on this frame. */
+    private var unlockBlurRadius = 0f
         set(value) {
             if (field == value) return
             field = value
@@ -246,14 +261,16 @@
             ShadeInterpolation.getNotificationScrimAlpha(qsPanelExpansion) * shadeExpansion
         combinedBlur = max(combinedBlur, blurUtils.blurRadiusOfRatio(qsExpandedRatio))
         combinedBlur = max(combinedBlur, blurUtils.blurRadiusOfRatio(transitionToFullShadeProgress))
-        var shadeRadius = max(combinedBlur, wakeAndUnlockBlurRadius)
+        var shadeRadius = max(combinedBlur, max(wakeBlurRadius, unlockBlurRadius))
 
         if (areBlursDisabledForAppLaunch || blursDisabledForUnlock) {
             shadeRadius = 0f
         }
 
         var blur = shadeRadius.toInt()
-        val zoomOut = blurRadiusToZoomOut(blurRadius = shadeRadius)
+        // If the blur comes from waking up, we don't want to zoom out the background
+        val zoomOut =
+            if (shadeRadius != wakeBlurRadius) blurRadiusToZoomOut(blurRadius = shadeRadius) else 0f
         // Make blur be 0 if it is necessary to stop blur effect.
         if (scrimsVisible) {
             if (!Flags.notificationShadeBlur()) {
@@ -338,14 +355,14 @@
                         startDelay = keyguardStateController.keyguardFadingAwayDelay
                         interpolator = Interpolators.FAST_OUT_SLOW_IN
                         addUpdateListener { animation: ValueAnimator ->
-                            wakeAndUnlockBlurRadius =
+                            unlockBlurRadius =
                                 blurUtils.blurRadiusOfRatio(animation.animatedValue as Float)
                         }
                         addListener(
                             object : AnimatorListenerAdapter() {
                                 override fun onAnimationEnd(animation: Animator) {
                                     keyguardAnimator = null
-                                    wakeAndUnlockBlurRadius = 0f
+                                    unlockBlurRadius = 0f
                                 }
                             }
                         )
@@ -381,15 +398,20 @@
             }
 
             override fun onDozeAmountChanged(linear: Float, eased: Float) {
-                wakeAndUnlockBlurRadius =
-                    if (ambientAod()) {
-                        0f
-                    } else {
-                        blurUtils.blurRadiusOfRatio(eased)
-                    }
+                prevDozeAmount = eased
+                updateWakeBlurRadius(prevDozeAmount)
             }
         }
 
+    private fun updateWakeBlurRadius(ratio: Float) {
+        wakeBlurRadius =
+            if (!wallpaperSupportsAmbientMode) {
+                0f
+            } else {
+                blurUtils.blurRadiusOfRatio(ratio)
+            }
+    }
+
     init {
         dumpManager.registerCriticalDumpable(javaClass.name, this)
         if (WAKE_UP_ANIMATION_ENABLED) {
@@ -411,6 +433,12 @@
                 }
             }
         )
+        applicationScope.launch {
+            wallpaperInteractor.wallpaperSupportsAmbientMode.collect { supported ->
+                wallpaperSupportsAmbientMode = supported
+                updateWakeBlurRadius(prevDozeAmount)
+            }
+        }
         initBlurListeners()
     }
 
@@ -585,7 +613,8 @@
             it.println("shouldApplyShadeBlur: ${shouldApplyShadeBlur()}")
             it.println("shadeAnimation: ${shadeAnimation.radius}")
             it.println("brightnessMirrorRadius: ${brightnessMirrorSpring.radius}")
-            it.println("wakeAndUnlockBlur: $wakeAndUnlockBlurRadius")
+            it.println("wakeBlur: $wakeBlurRadius")
+            it.println("unlockBlur: $wakeBlurRadius")
             it.println("blursDisabledForAppLaunch: $blursDisabledForAppLaunch")
             it.println("appLaunchTransitionIsInProgress: $appLaunchTransitionIsInProgress")
             it.println("qsPanelExpansion: $qsPanelExpansion")
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/featurepods/media/ui/compose/MediaControlPopup.kt b/packages/SystemUI/src/com/android/systemui/statusbar/featurepods/media/ui/compose/MediaControlPopup.kt
new file mode 100644
index 0000000..80bdb7f
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/featurepods/media/ui/compose/MediaControlPopup.kt
@@ -0,0 +1,56 @@
+/*
+ * 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.statusbar.featurepods.media.ui.compose
+
+import android.widget.FrameLayout
+import androidx.compose.foundation.layout.height
+import androidx.compose.foundation.layout.width
+import androidx.compose.foundation.shape.RoundedCornerShape
+import androidx.compose.runtime.Composable
+import androidx.compose.ui.Modifier
+import androidx.compose.ui.draw.clip
+import androidx.compose.ui.res.dimensionResource
+import androidx.compose.ui.unit.dp
+import androidx.compose.ui.viewinterop.AndroidView
+import com.android.systemui.media.controls.ui.view.MediaHost
+import com.android.systemui.res.R
+
+/** Displays a popup containing media controls. Embeds the MediaCarousel within a Compose popup. */
+@Composable
+fun MediaControlPopup(mediaHost: MediaHost, modifier: Modifier = Modifier) {
+    AndroidView(
+        modifier =
+            modifier
+                .width(400.dp)
+                .height(200.dp)
+                .clip(
+                    shape =
+                        RoundedCornerShape(dimensionResource(R.dimen.notification_corner_radius))
+                ),
+        factory = { _ ->
+            mediaHost.hostView.apply {
+                layoutParams =
+                    FrameLayout.LayoutParams(
+                        FrameLayout.LayoutParams.MATCH_PARENT,
+                        FrameLayout.LayoutParams.MATCH_PARENT,
+                    )
+            }
+            mediaHost.hostView
+        },
+        onReset = {},
+    )
+}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/featurepods/popups/ui/compose/StatusBarPopup.kt b/packages/SystemUI/src/com/android/systemui/statusbar/featurepods/popups/ui/compose/StatusBarPopup.kt
index 8a66904..ead5148 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/featurepods/popups/ui/compose/StatusBarPopup.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/featurepods/popups/ui/compose/StatusBarPopup.kt
@@ -28,7 +28,9 @@
 import androidx.compose.ui.unit.dp
 import androidx.compose.ui.window.Popup
 import androidx.compose.ui.window.PopupProperties
+import com.android.systemui.media.controls.ui.view.MediaHost
 import com.android.systemui.res.R
+import com.android.systemui.statusbar.featurepods.media.ui.compose.MediaControlPopup
 import com.android.systemui.statusbar.featurepods.popups.shared.model.PopupChipId
 import com.android.systemui.statusbar.featurepods.popups.shared.model.PopupChipModel
 
@@ -37,7 +39,7 @@
  * status bar.
  */
 @Composable
-fun StatusBarPopup(viewModel: PopupChipModel.Shown) {
+fun StatusBarPopup(viewModel: PopupChipModel.Shown, mediaHost: MediaHost) {
     val density = Density(LocalContext.current)
     Popup(
         properties =
@@ -56,7 +58,7 @@
         Box(modifier = Modifier.padding(8.dp).wrapContentSize()) {
             when (viewModel.chipId) {
                 is PopupChipId.MediaControl -> {
-                    // TODO(b/385202114): Populate MediaControlPopup contents.
+                    MediaControlPopup(mediaHost = mediaHost)
                 }
             }
             // Future popup types will be handled here.
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/featurepods/popups/ui/compose/StatusBarPopupChip.kt b/packages/SystemUI/src/com/android/systemui/statusbar/featurepods/popups/ui/compose/StatusBarPopupChip.kt
index eb85d2f..c77decd 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/featurepods/popups/ui/compose/StatusBarPopupChip.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/featurepods/popups/ui/compose/StatusBarPopupChip.kt
@@ -16,33 +16,49 @@
 
 package com.android.systemui.statusbar.featurepods.popups.ui.compose
 
-import androidx.compose.animation.animateContentSize
+import androidx.compose.foundation.LocalIndication
 import androidx.compose.foundation.background
+import androidx.compose.foundation.border
 import androidx.compose.foundation.clickable
-import androidx.compose.foundation.hoverable
+import androidx.compose.foundation.indication
 import androidx.compose.foundation.interaction.MutableInteractionSource
 import androidx.compose.foundation.interaction.collectIsHoveredAsState
 import androidx.compose.foundation.layout.Arrangement
+import androidx.compose.foundation.layout.Box
 import androidx.compose.foundation.layout.Row
+import androidx.compose.foundation.layout.height
 import androidx.compose.foundation.layout.padding
+import androidx.compose.foundation.layout.width
 import androidx.compose.foundation.layout.widthIn
 import androidx.compose.foundation.shape.CircleShape
 import androidx.compose.foundation.shape.RoundedCornerShape
 import androidx.compose.material3.MaterialTheme
-import androidx.compose.material3.Surface
 import androidx.compose.material3.Text
 import androidx.compose.material3.contentColorFor
+import androidx.compose.material3.minimumInteractiveComponentSize
 import androidx.compose.material3.ripple
 import androidx.compose.runtime.Composable
 import androidx.compose.runtime.getValue
+import androidx.compose.runtime.mutableStateOf
 import androidx.compose.runtime.remember
+import androidx.compose.runtime.setValue
 import androidx.compose.ui.Alignment
 import androidx.compose.ui.Modifier
+import androidx.compose.ui.draw.clip
+import androidx.compose.ui.draw.drawWithCache
+import androidx.compose.ui.graphics.BlendMode
+import androidx.compose.ui.graphics.Brush
+import androidx.compose.ui.graphics.Color
+import androidx.compose.ui.graphics.CompositingStrategy
+import androidx.compose.ui.layout.layout
+import androidx.compose.ui.res.dimensionResource
 import androidx.compose.ui.semantics.Role
-import androidx.compose.ui.text.style.TextOverflow
+import androidx.compose.ui.text.rememberTextMeasurer
+import androidx.compose.ui.unit.Dp
 import androidx.compose.ui.unit.dp
 import com.android.compose.modifiers.thenIf
 import com.android.systemui.common.ui.compose.Icon
+import com.android.systemui.res.R
 import com.android.systemui.statusbar.featurepods.popups.shared.model.HoverBehavior
 import com.android.systemui.statusbar.featurepods.popups.shared.model.PopupChipModel
 
@@ -54,31 +70,48 @@
 @Composable
 fun StatusBarPopupChip(viewModel: PopupChipModel.Shown, modifier: Modifier = Modifier) {
     val hasHoverBehavior = viewModel.hoverBehavior !is HoverBehavior.None
-    val hoverInteractionSource = remember { MutableInteractionSource() }
-    val isHovered by hoverInteractionSource.collectIsHoveredAsState()
+    val interactionSource = remember { MutableInteractionSource() }
+    val hoveredState by interactionSource.collectIsHoveredAsState()
+    val isHovered = hasHoverBehavior && hoveredState
     val isPopupShown = viewModel.isPopupShown
-
+    val indication = if (hoveredState) null else LocalIndication.current
+    val chipShape =
+        RoundedCornerShape(dimensionResource(id = R.dimen.ongoing_activity_chip_corner_radius))
     val chipBackgroundColor =
         if (isPopupShown) {
-            MaterialTheme.colorScheme.primaryContainer
+            MaterialTheme.colorScheme.primary
         } else {
-            MaterialTheme.colorScheme.surfaceContainerHighest
+            MaterialTheme.colorScheme.surfaceDim
         }
-    Surface(
-        shape = RoundedCornerShape(16.dp),
+
+    // Use a Box with `fillMaxHeight` to create a larger click surface for the chip. The visible
+    // height of the chip is determined by the height of the background of the Row below. The
+    // `indication` for Clicks is applied in the Row below as well.
+    Box(
+        contentAlignment = Alignment.Center,
         modifier =
-            modifier
-                .widthIn(max = 120.dp)
-                .padding(vertical = 4.dp)
-                .animateContentSize()
-                .thenIf(hasHoverBehavior) { Modifier.hoverable(hoverInteractionSource) }
-                .thenIf(!isPopupShown) { Modifier.clickable { viewModel.showPopup() } },
-        color = chipBackgroundColor,
+            modifier.minimumInteractiveComponentSize().thenIf(!isPopupShown) {
+                Modifier.clickable(
+                    onClick = { viewModel.showPopup() },
+                    indication = null,
+                    interactionSource = interactionSource,
+                )
+            },
     ) {
         Row(
-            modifier = Modifier.padding(start = 4.dp, end = 8.dp),
-            verticalAlignment = Alignment.CenterVertically,
             horizontalArrangement = Arrangement.spacedBy(4.dp),
+            verticalAlignment = Alignment.CenterVertically,
+            modifier =
+                Modifier.height(dimensionResource(R.dimen.ongoing_appops_chip_height))
+                    .clip(chipShape)
+                    .background(chipBackgroundColor)
+                    .border(
+                        width = dimensionResource(id = R.dimen.ongoing_activity_chip_outline_width),
+                        color = MaterialTheme.colorScheme.outlineVariant,
+                        shape = chipShape,
+                    )
+                    .indication(interactionSource, indication)
+                    .padding(start = 4.dp, end = 8.dp),
         ) {
             val iconColor =
                 if (isHovered) chipBackgroundColor else contentColorFor(chipBackgroundColor)
@@ -92,9 +125,11 @@
                         else -> viewModel.icon
                     },
                 modifier =
-                    Modifier.thenIf(isHovered) {
-                            Modifier.padding(3.dp)
-                                .background(color = iconBackgroundColor, shape = CircleShape)
+                    Modifier.height(20.dp)
+                        .width(20.dp)
+                        .thenIf(isHovered) {
+                            Modifier.background(color = iconBackgroundColor, shape = CircleShape)
+                                .padding(2.dp)
                         }
                         .thenIf(hoverBehavior is HoverBehavior.Button) {
                             Modifier.clickable(
@@ -102,18 +137,67 @@
                                 onClick = (hoverBehavior as HoverBehavior.Button).onIconPressed,
                                 indication = ripple(),
                                 interactionSource = iconInteractionSource,
+                                enabled = isHovered,
                             )
-                        }
-                        .padding(3.dp),
+                        },
                 tint = iconColor,
             )
 
+            val text = viewModel.chipText
+            val textStyle = MaterialTheme.typography.labelLarge
+            val textMeasurer = rememberTextMeasurer()
+            var textOverflow by remember { mutableStateOf(false) }
+
             Text(
-                text = viewModel.chipText,
-                style = MaterialTheme.typography.labelLarge,
+                text = text,
+                style = textStyle,
                 softWrap = false,
-                overflow = TextOverflow.Ellipsis,
+                modifier =
+                    Modifier.widthIn(
+                            max =
+                                dimensionResource(id = R.dimen.ongoing_activity_chip_max_text_width)
+                        )
+                        .layout { measurables, constraints ->
+                            val placeable = measurables.measure(constraints)
+                            val intrinsicWidth =
+                                textMeasurer.measure(text, textStyle, softWrap = false).size.width
+                            textOverflow = intrinsicWidth > constraints.maxWidth
+
+                            layout(placeable.width, placeable.height) {
+                                if (textOverflow) {
+                                    placeable.placeWithLayer(0, 0) {
+                                        compositingStrategy = CompositingStrategy.Offscreen
+                                    }
+                                } else {
+                                    placeable.place(0, 0)
+                                }
+                            }
+                        }
+                        .overflowFadeOut(
+                            hasOverflow = { textOverflow },
+                            fadeLength =
+                                dimensionResource(
+                                    id = R.dimen.ongoing_activity_chip_text_fading_edge_length
+                                ),
+                        ),
             )
         }
     }
 }
+
+private fun Modifier.overflowFadeOut(hasOverflow: () -> Boolean, fadeLength: Dp): Modifier {
+    return drawWithCache {
+        val width = size.width
+        val start = (width - fadeLength.toPx()).coerceAtLeast(0f)
+        val gradient =
+            Brush.horizontalGradient(
+                colors = listOf(Color.Black, Color.Transparent),
+                startX = start,
+                endX = width,
+            )
+        onDrawWithContent {
+            drawContent()
+            if (hasOverflow()) drawRect(brush = gradient, blendMode = BlendMode.DstIn)
+        }
+    }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/featurepods/popups/ui/compose/StatusBarPopupChipsContainer.kt b/packages/SystemUI/src/com/android/systemui/statusbar/featurepods/popups/ui/compose/StatusBarPopupChipsContainer.kt
index 16538c9..f5f1f20 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/featurepods/popups/ui/compose/StatusBarPopupChipsContainer.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/featurepods/popups/ui/compose/StatusBarPopupChipsContainer.kt
@@ -20,14 +20,37 @@
 import androidx.compose.foundation.layout.Row
 import androidx.compose.foundation.layout.padding
 import androidx.compose.runtime.Composable
+import androidx.compose.runtime.LaunchedEffect
+import androidx.compose.runtime.getValue
+import androidx.compose.runtime.remember
+import androidx.compose.runtime.setValue
 import androidx.compose.ui.Alignment
 import androidx.compose.ui.Modifier
 import androidx.compose.ui.unit.dp
+import com.android.systemui.media.controls.ui.view.MediaHost
+import com.android.systemui.scene.shared.flag.SceneContainerFlag
+import com.android.systemui.statusbar.featurepods.popups.shared.model.PopupChipId
 import com.android.systemui.statusbar.featurepods.popups.shared.model.PopupChipModel
 
 /** Container view that holds all right hand side chips in the status bar. */
 @Composable
-fun StatusBarPopupChipsContainer(chips: List<PopupChipModel.Shown>, modifier: Modifier = Modifier) {
+fun StatusBarPopupChipsContainer(
+    chips: List<PopupChipModel.Shown>,
+    mediaHost: MediaHost,
+    onMediaControlPopupVisibilityChanged: (Boolean) -> Unit,
+    modifier: Modifier = Modifier,
+) {
+    if (!SceneContainerFlag.isEnabled) {
+        val isMediaControlPopupShown =
+            remember(chips) {
+                chips.any { it.chipId == PopupChipId.MediaControl && it.isPopupShown }
+            }
+
+        LaunchedEffect(isMediaControlPopupShown) {
+            onMediaControlPopupVisibilityChanged(isMediaControlPopupShown)
+        }
+    }
+
     //    TODO(b/385353140): Add padding and spacing for this container according to UX specs.
     Box {
         Row(
@@ -37,7 +60,7 @@
             chips.forEach { chip ->
                 StatusBarPopupChip(chip)
                 if (chip.isPopupShown) {
-                    StatusBarPopup(chip)
+                    StatusBarPopup(viewModel = chip, mediaHost = mediaHost)
                 }
             }
         }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ActivatableNotificationView.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ActivatableNotificationView.java
index b077327..4ed9dce 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ActivatableNotificationView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ActivatableNotificationView.java
@@ -16,8 +16,10 @@
 
 package com.android.systemui.statusbar.notification.row;
 
+import static com.android.systemui.Flags.notificationAppearNonlinear;
 import static com.android.systemui.Flags.notificationBackgroundTintOptimization;
 import static com.android.systemui.Flags.notificationRowTransparency;
+import static com.android.systemui.Flags.physicalNotificationMovement;
 import static com.android.systemui.statusbar.notification.row.ExpandableView.ClipSide.BOTTOM;
 import static com.android.systemui.statusbar.notification.row.ExpandableView.ClipSide.TOP;
 
@@ -71,7 +73,8 @@
      * #ALPHA_APPEAR_START_FRACTION.
      */
 
-    private static final float ALPHA_APPEAR_START_FRACTION = .7f;
+    private static final float ALPHA_APPEAR_START_FRACTION =
+            notificationAppearNonlinear() ? .55f : .7f;
     /**
      * The content should show fully with progress at #ALPHA_APPEAR_END_FRACTION
      * The start of the animation is at #ALPHA_APPEAR_START_FRACTION
@@ -111,6 +114,7 @@
     private float mOverrideAmount;
     private boolean mShadowHidden;
     private boolean mIsHeadsUpAnimation;
+    private boolean mIsHeadsUpCycling;
     /* In order to track headsup longpress coorindate. */
     protected Point mTargetPoint;
     private boolean mDismissed;
@@ -349,10 +353,12 @@
 
     @Override
     public long performRemoveAnimation(long duration, long delay, float translationDirection,
-            boolean isHeadsUpAnimation, Runnable onStartedRunnable, Runnable onFinishedRunnable,
-            AnimatorListenerAdapter animationListener, ClipSide clipSide) {
+            boolean isHeadsUpAnimation, boolean isHeadsUpCycling, Runnable onStartedRunnable,
+            Runnable onFinishedRunnable, AnimatorListenerAdapter animationListener,
+            ClipSide clipSide) {
         enableAppearDrawing(true);
         mIsHeadsUpAnimation = isHeadsUpAnimation;
+        mIsHeadsUpCycling = isHeadsUpCycling;
         if (mDrawingAppearAnimation) {
             startAppearAnimation(false /* isAppearing */, translationDirection,
                     delay, duration, onStartedRunnable, onFinishedRunnable, animationListener,
@@ -370,9 +376,10 @@
 
     @Override
     public void performAddAnimation(long delay, long duration, boolean isHeadsUpAppear,
-            Runnable onFinishRunnable) {
+            boolean isHeadsUpCycling, Runnable onFinishRunnable) {
         enableAppearDrawing(true);
         mIsHeadsUpAnimation = isHeadsUpAppear;
+        mIsHeadsUpCycling = isHeadsUpCycling;
         if (mDrawingAppearAnimation) {
             startAppearAnimation(true /* isAppearing */, isHeadsUpAppear ? 0.0f : -1.0f, delay,
                     duration, null, null, null, ClipSide.BOTTOM);
@@ -404,14 +411,14 @@
             targetValue = 0.0f;
         }
 
-        if (NotificationHeadsUpCycling.isEnabled()) {
-            // TODO(b/316404716): add avalanche filtering
+        if (NotificationHeadsUpCycling.isEnabled() && !useNonLinearAnimation()) {
             mCurrentAppearInterpolator = Interpolators.LINEAR;
         }
 
         mAppearAnimator = ValueAnimator.ofFloat(mAppearAnimationFraction,
                 targetValue);
-        mAppearAnimator.setInterpolator(mCurrentAppearInterpolator);
+        mAppearAnimator.setInterpolator(
+                useNonLinearAnimation() ? Interpolators.LINEAR : mCurrentAppearInterpolator);
         mAppearAnimator.setDuration(
                 (long) (duration * Math.abs(mAppearAnimationFraction - targetValue)));
         mAppearAnimator.addUpdateListener(animation -> {
@@ -530,7 +537,13 @@
      * @param clipSide Which side if view we want to clip from
      */
     private void updateAppearRect(ClipSide clipSide) {
-        float interpolatedFraction = mAppearAnimationFraction;
+        float interpolatedFraction;
+        if (useNonLinearAnimation()) {
+            interpolatedFraction = mCurrentAppearInterpolator.getInterpolation(
+                    mAppearAnimationFraction);
+        } else {
+            interpolatedFraction = mAppearAnimationFraction;
+        }
         mAppearAnimationTranslation = (1.0f - interpolatedFraction) * mAnimationTranslationY;
         final int fullHeight = getActualHeight();
         float height = fullHeight * interpolatedFraction;
@@ -558,6 +571,11 @@
         }
     }
 
+    private boolean useNonLinearAnimation() {
+        return notificationAppearNonlinear() && (!mIsHeadsUpCycling
+                || physicalNotificationMovement());
+    }
+
     private void updateAppearRect() {
         updateAppearRect(ClipSide.BOTTOM);
     }
@@ -567,7 +585,7 @@
                 mAppearAnimationFraction,
                 ALPHA_APPEAR_START_FRACTION,
                 ALPHA_APPEAR_END_FRACTION,
-                Interpolators.ALPHA_IN
+                notificationAppearNonlinear() ? mCurrentAppearInterpolator : Interpolators.ALPHA_IN
         );
     }
 
@@ -813,6 +831,7 @@
         pw.print("mDrawingAppearAnimation", mDrawingAppearAnimation);
         pw.print("mAppearAnimationFraction", mAppearAnimationFraction);
         pw.print("mIsHeadsUpAnimation", mIsHeadsUpAnimation);
+        pw.print("mIsHeadsUpCycling", mIsHeadsUpCycling);
         pw.print("mTargetPoint", mTargetPoint);
         pw.println();
     }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRow.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRow.java
index d2800d7..4c74408 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRow.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRow.java
@@ -3494,20 +3494,17 @@
 
     @Override
     public void performAddAnimation(long delay, long duration, boolean isHeadsUpAppear,
-            Runnable onFinishRunnable) {
+            boolean isHeadsUpCycling, Runnable onFinishRunnable) {
         mLogger.logStartAppearAnimation(mLoggingKey, /* isAppear = */ true);
-        super.performAddAnimation(delay, duration, isHeadsUpAppear, onFinishRunnable);
+        super.performAddAnimation(delay, duration, isHeadsUpAppear, isHeadsUpCycling,
+                onFinishRunnable);
     }
 
     @Override
-    public long performRemoveAnimation(
-            long duration,
-            long delay,
-            float translationDirection,
-            boolean isHeadsUpAnimation,
-            Runnable onStartedRunnable,
-            Runnable onFinishedRunnable,
-            AnimatorListenerAdapter animationListener, ClipSide clipSide) {
+    public long performRemoveAnimation(long duration, long delay, float translationDirection,
+            boolean isHeadsUpAnimation, boolean isHeadsUpCycling, Runnable onStartedRunnable,
+            Runnable onFinishedRunnable, AnimatorListenerAdapter animationListener,
+            ClipSide clipSide) {
         mLogger.logStartAppearAnimation(mLoggingKey, /* isAppear = */ false);
         if (mMenuRow != null && mMenuRow.isMenuVisible()) {
             Animator anim = getTranslateViewAnimator(0f, null /* listener */);
@@ -3522,9 +3519,9 @@
 
                     @Override
                     public void onAnimationEnd(Animator animation) {
-                        ExpandableNotificationRow.super.performRemoveAnimation(
-                                duration, delay, translationDirection, isHeadsUpAnimation,
-                                null, onFinishedRunnable, animationListener, ClipSide.BOTTOM);
+                        ExpandableNotificationRow.super.performRemoveAnimation(duration, delay,
+                                translationDirection, isHeadsUpAnimation, isHeadsUpCycling, null,
+                                onFinishedRunnable, animationListener, ClipSide.BOTTOM);
                     }
                 });
                 anim.start();
@@ -3532,8 +3529,8 @@
             }
         }
         return super.performRemoveAnimation(duration, delay, translationDirection,
-                isHeadsUpAnimation, onStartedRunnable, onFinishedRunnable, animationListener,
-                clipSide);
+                isHeadsUpAnimation, isHeadsUpCycling, onStartedRunnable, onFinishedRunnable,
+                animationListener, clipSide);
     }
 
     @Override
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableView.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableView.java
index da664f8..292f74a 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableView.java
@@ -467,7 +467,8 @@
      *                             remove animation should be performed upwards,
      *                             such that the  child appears to be going away to the top. 1
      *                             Should mean the opposite.
-     * @param isHeadsUpAnimation   Is this a headsUp animation.
+     * @param isHeadsUpAnimation   Is this a headsUp animation
+     * @param isHeadsUpCycling     Is this the cycling heads up animation
      * @param onFinishedRunnable   A runnable which should be run when the animation is finished.
      * @param animationListener    An animation listener to add to the animation.
      * @return The additional delay, in milliseconds, that this view needs to add before the
@@ -475,7 +476,7 @@
      */
     public abstract long performRemoveAnimation(long duration,
             long delay, float translationDirection, boolean isHeadsUpAnimation,
-            Runnable onStartedRunnable,
+            boolean isHeadsUpCycling, Runnable onStartedRunnable,
             Runnable onFinishedRunnable,
             AnimatorListenerAdapter animationListener, ClipSide clipSide);
 
@@ -485,11 +486,12 @@
     }
 
     public void performAddAnimation(long delay, long duration, boolean isHeadsUpAppear) {
-        performAddAnimation(delay, duration, isHeadsUpAppear, null);
+        performAddAnimation(delay, duration, isHeadsUpAppear, false /* isHeadsUpCycling */,
+                null);
     }
 
     public abstract void performAddAnimation(long delay, long duration, boolean isHeadsUpAppear,
-            Runnable onEndRunnable);
+            boolean isHeadsUpCycling, Runnable onEndRunnable);
 
     public int getPinnedHeadsUpHeight() {
         return getIntrinsicHeight();
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/StackScrollerDecorView.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/StackScrollerDecorView.java
index cd228e7..a064d1c 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/StackScrollerDecorView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/StackScrollerDecorView.java
@@ -260,7 +260,7 @@
     @Override
     public long performRemoveAnimation(long duration, long delay,
             float translationDirection, boolean isHeadsUpAnimation,
-            Runnable onStartedRunnable,
+            boolean isHeadsUpCycling, Runnable onStartedRunnable,
             Runnable onFinishedRunnable,
             AnimatorListenerAdapter animationListener, ClipSide clipSide) {
         // TODO: Use duration
@@ -279,7 +279,7 @@
 
     @Override
     public void performAddAnimation(long delay, long duration, boolean isHeadsUpAppear,
-            Runnable endRunnable) {
+            boolean isHeadsUpCycling, Runnable endRunnable) {
         // TODO: use delay and duration
         setContentVisibleAnimated(true);
     }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/MediaContainerView.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/MediaContainerView.kt
index bd7bd59..4d10a52 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/MediaContainerView.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/MediaContainerView.kt
@@ -70,14 +70,15 @@
     }
 
     override fun performRemoveAnimation(
-            duration: Long,
-            delay: Long,
-            translationDirection: Float,
-            isHeadsUpAnimation: Boolean,
-            onStartedRunnable: Runnable?,
-            onFinishedRunnable: Runnable?,
-            animationListener: AnimatorListenerAdapter?,
-            clipSide: ClipSide
+        duration: Long,
+        delay: Long,
+        translationDirection: Float,
+        isHeadsUpAnimation: Boolean,
+        isHeadsUpCycling: Boolean,
+        onStartedRunnable: Runnable?,
+        onFinishedRunnable: Runnable?,
+        animationListener: AnimatorListenerAdapter?,
+        clipSide: ClipSide,
     ): Long {
         return 0
     }
@@ -86,7 +87,8 @@
         delay: Long,
         duration: Long,
         isHeadsUpAppear: Boolean,
-        onEnd: Runnable?
+        isHeadsUpCycling: Boolean,
+        onEnd: Runnable?,
     ) {
         // No animation, it doesn't need it, this would be local
     }
@@ -103,9 +105,7 @@
         assertMediaContainerVisibility(visibility)
     }
 
-    /**
-     * visibility should be aligned with MediaContainerView visibility on the keyguard.
-     */
+    /** visibility should be aligned with MediaContainerView visibility on the keyguard. */
     private fun isVisibilityValid(visibility: Int): Boolean {
         val currentViewState = viewState as? MediaContainerViewState ?: return true
         val shouldBeGone = !currentViewState.shouldBeVisible
@@ -113,8 +113,7 @@
     }
 
     /**
-     * b/298213983
-     * MediaContainerView's visibility is changed to VISIBLE when it should be GONE.
+     * b/298213983 MediaContainerView's visibility is changed to VISIBLE when it should be GONE.
      * This method check this state and logs.
      */
     private fun assertMediaContainerVisibility(visibility: Int) {
@@ -122,8 +121,10 @@
 
         if (currentViewState is MediaContainerViewState) {
             if (!currentViewState.shouldBeVisible && visibility == VISIBLE) {
-                Log.wtf("MediaContainerView", "MediaContainerView should be GONE " +
-                        "but its visibility changed to VISIBLE")
+                Log.wtf(
+                    "MediaContainerView",
+                    "MediaContainerView should be GONE " + "but its visibility changed to VISIBLE",
+                )
             }
         }
     }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/StackStateAnimator.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/StackStateAnimator.java
index 5e0d57e..2b05223 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/StackStateAnimator.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/StackStateAnimator.java
@@ -506,8 +506,8 @@
                 }
                 changingView.performRemoveAnimation(ANIMATION_DURATION_APPEAR_DISAPPEAR,
                         0 /* delay */, translationDirection, false /* isHeadsUpAppear */,
-                        startAnimation, postAnimation, getGlobalAnimationFinishedListener(),
-                        ExpandableView.ClipSide.BOTTOM);
+                        false /* isHeadsUpCycling */, startAnimation, postAnimation,
+                        getGlobalAnimationFinishedListener(), ExpandableView.ClipSide.BOTTOM);
                 needsCustomAnimation = true;
             } else if (event.animationType ==
                     NotificationStackScrollLayout.AnimationEvent.ANIMATION_TYPE_REMOVE_SWIPED_OUT) {
@@ -538,7 +538,7 @@
                     };
                 }
                 changingView.performAddAnimation(0, ANIMATION_DURATION_HEADS_UP_CYCLING,
-                        /* isHeadsUpAppear= */ true, onAnimationEnd);
+                        /* isHeadsUpAppear= */ true, /* isHeadsUpCycling= */ true, onAnimationEnd);
             } else if (event.animationType == ANIMATION_TYPE_HEADS_UP_APPEAR) {
                 mHeadsUpAppearChildren.add(changingView);
 
@@ -559,7 +559,7 @@
                     onAnimationEnd = () -> mLogger.appearAnimationEnded(finalKey);
                 }
                 changingView.performAddAnimation(0, ANIMATION_DURATION_HEADS_UP_APPEAR,
-                        /* isHeadsUpAppear= */ true, onAnimationEnd);
+                        /* isHeadsUpAppear= */ true, /* isHeadsUpCycling= */ false, onAnimationEnd);
             } else if (event.animationType == ANIMATION_TYPE_HEADS_UP_CYCLING_OUT) {
                 mHeadsUpDisappearChildren.add(changingView);
                 Runnable endRunnable = null;
@@ -629,6 +629,7 @@
                             // translation, the actual translation is in StackScrollAlgorithm.
                             /* translationDirection= */ 0.0f,
                             /* isHeadsUpAnimation= */ true,
+                            /* isHeadsUpCycling= */ true,
                             startAnimation, postAnimation,
                             getGlobalAnimationFinishedListener(), ExpandableView.ClipSide.TOP);
                     mAnimationProperties.delay += removeAnimationDelay;
@@ -706,6 +707,7 @@
                     long removeAnimationDelay = changingView.performRemoveAnimation(
                             ANIMATION_DURATION_HEADS_UP_DISAPPEAR,
                             0, 0.0f, true /* isHeadsUpAppear */,
+                            false /* isHeadsUpCycling */,
                             startAnimation, postAnimation,
                             getGlobalAnimationFinishedListener(), ExpandableView.ClipSide.BOTTOM);
                     mAnimationProperties.delay += removeAnimationDelay;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/shared/ui/composable/StatusBarRoot.kt b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/shared/ui/composable/StatusBarRoot.kt
index 39a1b46..4189221 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/shared/ui/composable/StatusBarRoot.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/shared/ui/composable/StatusBarRoot.kt
@@ -37,6 +37,10 @@
 import com.android.compose.theme.PlatformTheme
 import com.android.keyguard.AlphaOptimizedLinearLayout
 import com.android.systemui.lifecycle.rememberViewModel
+import com.android.systemui.media.controls.ui.controller.MediaHierarchyManager
+import com.android.systemui.media.controls.ui.view.MediaHost
+import com.android.systemui.media.controls.ui.view.MediaHostState
+import com.android.systemui.media.dagger.MediaModule.POPUP
 import com.android.systemui.plugins.DarkIconDispatcher
 import com.android.systemui.res.R
 import com.android.systemui.statusbar.chips.ui.compose.OngoingActivityChips
@@ -67,6 +71,7 @@
 import com.android.systemui.statusbar.pipeline.shared.ui.viewmodel.HomeStatusBarViewModel
 import com.android.systemui.statusbar.pipeline.shared.ui.viewmodel.HomeStatusBarViewModel.HomeStatusBarViewModelFactory
 import javax.inject.Inject
+import javax.inject.Named
 
 /** Factory to simplify the dependency management for [StatusBarRoot] */
 class StatusBarRootFactory
@@ -81,6 +86,8 @@
     private val ongoingCallController: OngoingCallController,
     private val darkIconDispatcherStore: DarkIconDispatcherStore,
     private val eventAnimationInteractor: SystemStatusEventAnimationInteractor,
+    private val mediaHierarchyManager: MediaHierarchyManager,
+    @Named(POPUP) private val mediaHost: MediaHost,
 ) {
     fun create(root: ViewGroup, andThen: (ViewGroup) -> Unit): ComposeView {
         val composeView = ComposeView(root.context)
@@ -99,6 +106,8 @@
                     ongoingCallController = ongoingCallController,
                     darkIconDispatcher = darkIconDispatcher,
                     eventAnimationInteractor = eventAnimationInteractor,
+                    mediaHierarchyManager = mediaHierarchyManager,
+                    mediaHost = mediaHost,
                     onViewCreated = andThen,
                 )
             }
@@ -130,6 +139,8 @@
     ongoingCallController: OngoingCallController,
     darkIconDispatcher: DarkIconDispatcher,
     eventAnimationInteractor: SystemStatusEventAnimationInteractor,
+    mediaHierarchyManager: MediaHierarchyManager,
+    mediaHost: MediaHost,
     onViewCreated: (ViewGroup) -> Unit,
 ) {
     val displayId = parent.context.displayId
@@ -237,6 +248,15 @@
 
                     // Add a composable container for `StatusBarPopupChip`s
                     if (StatusBarPopupChips.isEnabled) {
+                        with(mediaHost) {
+                            expansion = MediaHostState.EXPANDED
+                            expandedMatchesParentHeight = true
+                            showsOnlyActiveMedia = true
+                            falsingProtectionNeeded = false
+                            disablePagination = true
+                            init(MediaHierarchyManager.LOCATION_STATUS_BAR_POPUP)
+                        }
+
                         val endSideContent =
                             phoneStatusBarView.requireViewById<AlphaOptimizedLinearLayout>(
                                 R.id.status_bar_end_side_content
@@ -256,7 +276,12 @@
 
                                 setContent {
                                     StatusBarPopupChipsContainer(
-                                        chips = statusBarViewModel.popupChips
+                                        chips = statusBarViewModel.popupChips,
+                                        mediaHost = mediaHost,
+                                        onMediaControlPopupVisibilityChanged = { popupShowing ->
+                                            mediaHierarchyManager.isMediaControlPopupShowing =
+                                                popupShowing
+                                        },
                                     )
                                 }
                             }
diff --git a/packages/SystemUI/src/com/android/systemui/volume/dialog/ringer/ui/binder/VolumeDialogRingerViewBinder.kt b/packages/SystemUI/src/com/android/systemui/volume/dialog/ringer/ui/binder/VolumeDialogRingerViewBinder.kt
index 0bdf99e..14eede6 100644
--- a/packages/SystemUI/src/com/android/systemui/volume/dialog/ringer/ui/binder/VolumeDialogRingerViewBinder.kt
+++ b/packages/SystemUI/src/com/android/systemui/volume/dialog/ringer/ui/binder/VolumeDialogRingerViewBinder.kt
@@ -24,6 +24,7 @@
 import androidx.annotation.LayoutRes
 import androidx.compose.ui.util.fastForEachIndexed
 import androidx.constraintlayout.motion.widget.MotionLayout
+import androidx.constraintlayout.motion.widget.MotionScene
 import androidx.dynamicanimation.animation.FloatValueHolder
 import androidx.dynamicanimation.animation.SpringAnimation
 import androidx.dynamicanimation.animation.SpringForce
@@ -47,6 +48,7 @@
 import javax.inject.Inject
 import kotlin.properties.Delegates
 import kotlinx.coroutines.CoroutineScope
+import kotlinx.coroutines.ExperimentalCoroutinesApi
 import kotlinx.coroutines.coroutineScope
 import kotlinx.coroutines.delay
 import kotlinx.coroutines.flow.mapLatest
@@ -55,6 +57,7 @@
 // Ensure roundness and color of button is updated when progress is changed by a minimum fraction.
 private const val BUTTON_MIN_VISIBLE_CHANGE = 0.05F
 
+@OptIn(ExperimentalCoroutinesApi::class)
 @VolumeDialogScope
 class VolumeDialogRingerViewBinder
 @Inject
@@ -208,6 +211,13 @@
                                     ringerState.orientation,
                                     ringerBackgroundView,
                                 )
+                                drawerContainer
+                                    .getTransition(R.id.close_to_open_transition)
+                                    .setInterpolatorInfo(
+                                        MotionScene.Transition.INTERPOLATE_REFERENCE_ID,
+                                        null,
+                                        R.anim.volume_dialog_ringer_open,
+                                    )
                                 drawerContainer.transitionToState(
                                     R.id.volume_dialog_ringer_drawer_open
                                 )
@@ -370,6 +380,12 @@
         orientation: Int,
     ) {
         setTransition(R.id.close_to_open_transition)
+        getTransition(R.id.close_to_open_transition)
+            .setInterpolatorInfo(
+                MotionScene.Transition.INTERPOLATE_REFERENCE_ID,
+                null,
+                R.anim.volume_dialog_ringer_close,
+            )
         updateCloseState(this, selectedIndex, orientation, ringerBackground)
         transitionToState(R.id.volume_dialog_ringer_drawer_close)
     }
diff --git a/packages/SystemUI/tests/src/com/android/systemui/media/controls/ui/controller/MediaHierarchyManagerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/media/controls/ui/controller/MediaHierarchyManagerTest.kt
index 6ca4ae2..14b1412 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/media/controls/ui/controller/MediaHierarchyManagerTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/media/controls/ui/controller/MediaHierarchyManagerTest.kt
@@ -17,6 +17,7 @@
 package com.android.systemui.media.controls.ui.controller
 
 import android.graphics.Rect
+import android.platform.test.annotations.EnableFlags
 import android.provider.Settings
 import android.testing.TestableLooper
 import android.view.ViewGroup
@@ -36,7 +37,6 @@
 import com.android.systemui.keyguard.WakefulnessLifecycle
 import com.android.systemui.keyguard.data.repository.fakeKeyguardRepository
 import com.android.systemui.keyguard.data.repository.fakeKeyguardTransitionRepository
-import com.android.systemui.keyguard.data.repository.keyguardRepository
 import com.android.systemui.keyguard.domain.interactor.keyguardInteractor
 import com.android.systemui.keyguard.shared.model.KeyguardState
 import com.android.systemui.kosmos.testScope
@@ -50,6 +50,7 @@
 import com.android.systemui.shade.domain.interactor.ShadeInteractor
 import com.android.systemui.statusbar.StatusBarState
 import com.android.systemui.statusbar.SysuiStatusBarStateController
+import com.android.systemui.statusbar.featurepods.popups.StatusBarPopupChips
 import com.android.systemui.statusbar.phone.KeyguardBypassController
 import com.android.systemui.statusbar.policy.FakeConfigurationController
 import com.android.systemui.statusbar.policy.KeyguardStateController
@@ -581,6 +582,36 @@
         }
 
     @Test
+    @EnableFlags(StatusBarPopupChips.FLAG_NAME)
+    fun testStatusBarPopupLocation() =
+        testScope.runTest {
+            mediaHierarchyManager.isMediaControlPopupShowing = true
+            runCurrent()
+
+            verify(mediaCarouselController)
+                .onDesiredLocationChanged(
+                    eq(MediaHierarchyManager.LOCATION_STATUS_BAR_POPUP),
+                    nullable(),
+                    eq(false),
+                    anyLong(),
+                    anyLong(),
+                )
+            clearInvocations(mediaCarouselController)
+
+            mediaHierarchyManager.isMediaControlPopupShowing = false
+            runCurrent()
+
+            verify(mediaCarouselController)
+                .onDesiredLocationChanged(
+                    eq(MediaHierarchyManager.LOCATION_QQS),
+                    any<MediaHostState>(),
+                    eq(false),
+                    anyLong(),
+                    anyLong(),
+                )
+        }
+
+    @Test
     fun testCommunalLocationVisibilityWithShadeShowing() =
         testScope.runTest {
             whenever(mediaDataManager.hasActiveMediaOrRecommendation()).thenReturn(true)
diff --git a/services/core/java/com/android/server/om/OverlayManagerSettings.java b/services/core/java/com/android/server/om/OverlayManagerSettings.java
index cb01727..1ac9711 100644
--- a/services/core/java/com/android/server/om/OverlayManagerSettings.java
+++ b/services/core/java/com/android/server/om/OverlayManagerSettings.java
@@ -544,6 +544,7 @@
                     // and overwritten.
                     throw new XmlPullParserException("old version " + oldVersion + "; ignoring");
                 case 3:
+                case 4:
                     // Upgrading from version 3 to 5 is not a breaking change so do not ignore the
                     // overlay file.
                     return;
diff --git a/services/core/java/com/android/server/pm/DeletePackageHelper.java b/services/core/java/com/android/server/pm/DeletePackageHelper.java
index 6bec34e..38aa57f 100644
--- a/services/core/java/com/android/server/pm/DeletePackageHelper.java
+++ b/services/core/java/com/android/server/pm/DeletePackageHelper.java
@@ -24,6 +24,7 @@
 import static android.content.pm.PackageManager.DELETE_SUCCEEDED;
 import static android.content.pm.PackageManager.MATCH_KNOWN_PACKAGES;
 import static android.content.pm.PackageManager.PERMISSION_GRANTED;
+import static android.os.UserHandle.USER_ALL;
 
 import static com.android.server.pm.InstructionSets.getAppDexInstructionSets;
 import static com.android.server.pm.PackageManagerService.DEBUG_COMPRESSION;
@@ -122,7 +123,7 @@
         final boolean res;
 
         final int removeUser = (deleteFlags & PackageManager.DELETE_ALL_USERS) != 0
-                ? UserHandle.USER_ALL : userId;
+                ? USER_ALL : userId;
 
         final PackageSetting uninstalledPs;
         final PackageSetting disabledSystemPs;
@@ -183,7 +184,7 @@
                 if (libraryInfo != null) {
                     boolean flagSdkLibIndependence = Flags.sdkLibIndependence();
                     for (int currUserId : allUsers) {
-                        if (removeUser != UserHandle.USER_ALL && removeUser != currUserId) {
+                        if (removeUser != USER_ALL && removeUser != currUserId) {
                             continue;
                         }
                         var libClientPackagesPair = computer.getPackagesUsingSharedLibrary(
@@ -227,7 +228,7 @@
                     && ((deleteFlags & PackageManager.DELETE_SYSTEM_APP) == 0)) {
                 // We're downgrading a system app, which will apply to all users, so
                 // freeze them all during the downgrade
-                freezeUser = UserHandle.USER_ALL;
+                freezeUser = USER_ALL;
                 priorUserStates = new SparseArray<>();
                 for (int i = 0; i < allUsers.length; i++) {
                     PackageUserState userState = uninstalledPs.readUserState(allUsers[i]);
@@ -421,7 +422,7 @@
         if (PackageManagerServiceUtils.isSystemApp(ps)) {
             final boolean deleteSystem = (flags & PackageManager.DELETE_SYSTEM_APP) != 0;
             final boolean deleteAllUsers =
-                    user == null || user.getIdentifier() == UserHandle.USER_ALL;
+                    user == null || user.getIdentifier() == USER_ALL;
             if ((!deleteSystem || deleteAllUsers) && disabledPs == null) {
                 Slog.w(TAG, "Attempt to delete unknown system package "
                         + ps.getPkg().getPackageName());
@@ -464,9 +465,9 @@
                     Manifest.permission.SUSPEND_APPS, packageName, userId) == PERMISSION_GRANTED);
         }
 
-        final int userId = user == null ? UserHandle.USER_ALL : user.getIdentifier();
+        final int userId = user == null ? USER_ALL : user.getIdentifier();
         // Remember which users are affected, before the installed states are modified
-        outInfo.mRemovedUsers = userId == UserHandle.USER_ALL
+        outInfo.mRemovedUsers = userId == USER_ALL
                 ? ps.queryUsersInstalledOrHasData(allUserHandles)
                 : new int[]{userId};
         outInfo.populateBroadcastUsers(ps);
@@ -479,7 +480,7 @@
         outInfo.mRemovedPackageVersionCode = ps.getVersionCode();
 
         if ((!systemApp || (flags & PackageManager.DELETE_SYSTEM_APP) != 0)
-                && userId != UserHandle.USER_ALL) {
+                && userId != USER_ALL) {
             // The caller is asking that the package only be deleted for a single
             // user.  To do this, we just mark its uninstalled state and delete
             // its data. If this is a system app, we only allow this to happen if
@@ -552,7 +553,7 @@
         for (final int affectedUserId : outInfo.mRemovedUsers) {
             if (hadSuspendAppsPermission.get(affectedUserId)) {
                 mPm.unsuspendForSuspendingPackage(snapshot, packageName,
-                        affectedUserId /*suspendingUserId*/, true /*inAllUsers*/);
+                        affectedUserId /*suspendingUserId*/, USER_ALL);
                 mPm.removeAllDistractingPackageRestrictions(snapshot, affectedUserId);
             }
         }
@@ -590,7 +591,7 @@
 
     @GuardedBy("mPm.mLock")
     private void markPackageUninstalledForUserLPw(PackageSetting ps, UserHandle user, int flags) {
-        final int[] userIds = (user == null || user.getIdentifier() == UserHandle.USER_ALL)
+        final int[] userIds = (user == null || user.getIdentifier() == USER_ALL)
                 ? mUserManagerInternal.getUserIds()
                 : new int[] {user.getIdentifier()};
         for (int nextUserId : userIds) {
@@ -687,7 +688,7 @@
             flags |= PackageManager.DELETE_KEEP_DATA;
         }
         try (PackageManagerTracedLock installLock = mPm.mInstallLock.acquireLock()) {
-            deleteInstalledPackageLIF(deletedPs, UserHandle.USER_ALL, true, flags, allUserHandles,
+            deleteInstalledPackageLIF(deletedPs, USER_ALL, true, flags, allUserHandles,
                     outInfo, writeSettings);
         }
     }
diff --git a/services/core/java/com/android/server/pm/PackageManagerInternalBase.java b/services/core/java/com/android/server/pm/PackageManagerInternalBase.java
index ed568b8..f5230c5 100644
--- a/services/core/java/com/android/server/pm/PackageManagerInternalBase.java
+++ b/services/core/java/com/android/server/pm/PackageManagerInternalBase.java
@@ -689,7 +689,7 @@
         final int suspendingUserId =
                 crossUserSuspensionEnabledRo() ? UserHandle.USER_SYSTEM : affectedUser;
         mService.unsuspendForSuspendingPackage(
-                snapshot(), PLATFORM_PACKAGE_NAME, suspendingUserId, /* inAllUsers= */ false);
+                snapshot(), PLATFORM_PACKAGE_NAME, suspendingUserId, affectedUser);
     }
 
     @Override
diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java
index 91a1c9c..021da6f 100644
--- a/services/core/java/com/android/server/pm/PackageManagerService.java
+++ b/services/core/java/com/android/server/pm/PackageManagerService.java
@@ -34,6 +34,7 @@
 import static android.crashrecovery.flags.Flags.refactorCrashrecovery;
 import static android.os.Process.INVALID_UID;
 import static android.os.Trace.TRACE_TAG_PACKAGE_MANAGER;
+import static android.os.UserHandle.USER_ALL;
 import static android.os.storage.StorageManager.FLAG_STORAGE_CE;
 import static android.os.storage.StorageManager.FLAG_STORAGE_DE;
 import static android.os.storage.StorageManager.FLAG_STORAGE_EXTERNAL;
@@ -1587,13 +1588,13 @@
     }
 
     void scheduleWritePackageRestrictions(UserHandle user) {
-        final int userId = user == null ? UserHandle.USER_ALL : user.getIdentifier();
+        final int userId = user == null ? USER_ALL : user.getIdentifier();
         scheduleWritePackageRestrictions(userId);
     }
 
     void scheduleWritePackageRestrictions(@CanBeALL @UserIdInt int userId) {
         invalidatePackageInfoCache();
-        if (userId == UserHandle.USER_ALL) {
+        if (userId == USER_ALL) {
             synchronized (mDirtyUsers) {
                 for (int aUserId : mUserManager.getUserIds()) {
                     mDirtyUsers.add(aUserId);
@@ -1806,7 +1807,7 @@
     private void installAllowlistedSystemPackages() {
         if (mUserManager.installWhitelistedSystemPackages(isFirstBoot(), isDeviceUpgrading(),
                 mExistingPackages)) {
-            scheduleWritePackageRestrictions(UserHandle.USER_ALL);
+            scheduleWritePackageRestrictions(USER_ALL);
             scheduleWriteSettings();
         }
     }
@@ -2393,7 +2394,7 @@
                     final PackageSetting ps = packageSettings.valueAt(i);
                     if (Objects.equals(StorageManager.UUID_PRIVATE_INTERNAL, ps.getVolumeUuid())) {
                         // No apps are running this early, so no need to freeze
-                        mAppDataHelper.clearAppDataLIF(ps.getPkg(), UserHandle.USER_ALL,
+                        mAppDataHelper.clearAppDataLIF(ps.getPkg(), USER_ALL,
                                 FLAG_STORAGE_DE | FLAG_STORAGE_CE | FLAG_STORAGE_EXTERNAL
                                         | Installer.FLAG_CLEAR_CODE_CACHE_ONLY
                                         | Installer.FLAG_CLEAR_APP_DATA_KEEP_ART_PROFILES);
@@ -3076,7 +3077,7 @@
 
     @NonNull
     int[] resolveUserIds(@CanBeALL @UserIdInt int userId) {
-        return (userId == UserHandle.USER_ALL) ? mUserManager.getUserIds() : new int[] { userId };
+        return (userId == USER_ALL) ? mUserManager.getUserIds() : new int[]{userId};
     }
 
     private void setUpInstantAppInstallerActivityLP(ActivityInfo installerActivity) {
@@ -3109,7 +3110,7 @@
     }
 
     void killApplication(String pkgName, @AppIdInt int appId, String reason, int exitInfoReason) {
-        killApplication(pkgName, appId, UserHandle.USER_ALL, reason, exitInfoReason);
+        killApplication(pkgName, appId, USER_ALL, reason, exitInfoReason);
     }
 
     void killApplication(String pkgName, @AppIdInt int appId,
@@ -3229,23 +3230,24 @@
     }
 
     /**
-     * @param inAllUsers Whether to unsuspend packages suspended by the given package in other
-     *                   users. This flag is only used when cross-user suspension is enabled.
+     * @param suspendingUserId The user that has suspended apps using the suspending package.
+     * @param targetUserId The user whose apps should be unsuspended. Pass {@code USER_ALL} to
+     *                     unsuspend for all users.
      */
     void unsuspendForSuspendingPackage(@NonNull Computer computer, String suspendingPackage,
-            @UserIdInt int suspendingUserId, boolean inAllUsers) {
+            @UserIdInt int suspendingUserId, @CanBeALL @UserIdInt int targetUserId) {
         // TODO: This can be replaced by a special parameter to iterate all packages, rather than
         //  this weird pre-collect of all packages.
         final String[] allPackages = computer.getPackageStates().keySet().toArray(new String[0]);
         final Predicate<UserPackage> suspenderPredicate =
                 UserPackage.of(suspendingUserId, suspendingPackage)::equals;
-        if (!crossUserSuspensionEnabledRo() || !inAllUsers) {
+        if (!crossUserSuspensionEnabledRo() || targetUserId != USER_ALL) {
             mSuspendPackageHelper.removeSuspensionsBySuspendingPackage(computer,
-                    allPackages, suspenderPredicate, suspendingUserId);
+                    allPackages, suspenderPredicate, targetUserId);
         } else {
-            for (int targetUserId: mUserManager.getUserIds()) {
+            for (int user : mUserManager.getUserIds()) {
                 mSuspendPackageHelper.removeSuspensionsBySuspendingPackage(
-                        computer, allPackages, suspenderPredicate, targetUserId);
+                        computer, allPackages, suspenderPredicate, user);
             }
         }
     }
@@ -3382,7 +3384,7 @@
                 && !snapshot.isCallerSameApp(packageName, callingUid)) {
             return false;
         }
-        return isPackageDeviceAdmin(packageName, UserHandle.USER_ALL);
+        return isPackageDeviceAdmin(packageName, USER_ALL);
     }
 
     // TODO(b/261957226): centralise this logic in DPM
@@ -3406,7 +3408,7 @@
                 // Does it contain a device admin for any user?
                 int[] allUsers = mUserManager.getUserIds();
                 int[] targetUsers;
-                if (userId == UserHandle.USER_ALL) {
+                if (userId == USER_ALL) {
                     targetUsers = allUsers;
                 } else {
                     targetUsers = new int[]{userId};
@@ -4153,7 +4155,7 @@
                 // This app should not generally be allowed to get disabled by the UI, but
                 // if it ever does, we don't want to end up with some of the user's apps
                 // permanently suspended.
-                unsuspendForSuspendingPackage(computer, packageName, userId, true /* inAllUsers */);
+                unsuspendForSuspendingPackage(computer, packageName, userId, USER_ALL);
                 removeAllDistractingPackageRestrictions(computer, userId);
             }
             success = true;
@@ -4244,9 +4246,9 @@
         };
         mContext.getContentResolver().registerContentObserver(android.provider.Settings.Global
                         .getUriFor(Global.ENABLE_EPHEMERAL_FEATURE),
-                false, co, UserHandle.USER_ALL);
+                false, co, USER_ALL);
         mContext.getContentResolver().registerContentObserver(android.provider.Settings.Secure
-                .getUriFor(Secure.INSTANT_APPS_ENABLED), false, co, UserHandle.USER_ALL);
+                .getUriFor(Secure.INSTANT_APPS_ENABLED), false, co, USER_ALL);
         co.onChange(true);
 
         mAppsFilter.onSystemReady(LocalServices.getService(PackageManagerInternal.class));
@@ -4774,7 +4776,7 @@
             final Computer snapshot = snapshotComputer();
             final AndroidPackage pkg = snapshot.getPackage(packageName);
             try (PackageFreezer ignored =
-                            freezePackage(packageName, UserHandle.USER_ALL,
+                            freezePackage(packageName, USER_ALL,
                                     "clearApplicationProfileData",
                                     ApplicationExitInfo.REASON_OTHER, null /* request */)) {
                 try (PackageManagerTracedLock installLock = mInstallLock.acquireLock()) {
@@ -4820,7 +4822,7 @@
                 public void run() {
                     mHandler.removeCallbacks(this);
                     final boolean succeeded;
-                    try (PackageFreezer freezer = freezePackage(packageName, UserHandle.USER_ALL,
+                    try (PackageFreezer freezer = freezePackage(packageName, USER_ALL,
                             "clearApplicationUserData",
                             ApplicationExitInfo.REASON_USER_REQUESTED, null /* request */,
                             /* waitAppKilled= */ true)) {
@@ -4847,7 +4849,7 @@
                                 == PERMISSION_GRANTED) {
                             final Computer snapshot = snapshotComputer();
                             unsuspendForSuspendingPackage(
-                                    snapshot, packageName, userId, true /* inAllUsers */);
+                                    snapshot, packageName, userId, USER_ALL);
                             removeAllDistractingPackageRestrictions(snapshot, userId);
                             synchronized (mLock) {
                                 flushPackageRestrictionsAsUserInternalLocked(userId);
@@ -6372,13 +6374,13 @@
             if (mComponentResolver.updateMimeGroup(snapshotComputer(), packageName, mimeGroup)) {
                 Binder.withCleanCallingIdentity(() -> {
                     mPreferredActivityHelper.clearPackagePreferredActivities(packageName,
-                            UserHandle.USER_ALL);
+                            USER_ALL);
                     // Send the ACTION_PACKAGE_CHANGED when the mimeGroup has changes
                     final Computer snapShot = snapshotComputer();
                     final ArrayList<String> components = new ArrayList<>(
                             Collections.singletonList(packageName));
                     final int appId = packageState.getAppId();
-                    final int[] userIds = resolveUserIds(UserHandle.USER_ALL);
+                    final int[] userIds = resolveUserIds(USER_ALL);
                     final String reason = "The mimeGroup is changed";
                     for (int i = 0; i < userIds.length; i++) {
                         final PackageUserStateInternal pkgUserState =
diff --git a/services/tests/servicestests/src/com/android/server/om/OverlayManagerSettingsTests.java b/services/tests/servicestests/src/com/android/server/om/OverlayManagerSettingsTests.java
index ad3855f..b1cf905 100644
--- a/services/tests/servicestests/src/com/android/server/om/OverlayManagerSettingsTests.java
+++ b/services/tests/servicestests/src/com/android/server/om/OverlayManagerSettingsTests.java
@@ -37,10 +37,12 @@
 import android.util.Xml;
 
 import androidx.annotation.NonNull;
-import androidx.test.runner.AndroidJUnit4;
 
 import com.android.modules.utils.TypedXmlPullParser;
 
+import junitparams.JUnitParamsRunner;
+import junitparams.Parameters;
+
 import org.junit.Before;
 import org.junit.Test;
 import org.junit.runner.RunWith;
@@ -56,7 +58,7 @@
 
 import javax.annotation.Nullable;
 
-@RunWith(AndroidJUnit4.class)
+@RunWith(JUnitParamsRunner.class)
 public class OverlayManagerSettingsTests {
     private OverlayManagerSettings mSettings;
     private static final int USER_0 = 0;
@@ -439,6 +441,39 @@
     }
 
     @Test
+    @Parameters(method = "getPreviousVersions")
+    public void testRestoreWithPreviousVersion(int version) throws Exception {
+        final String xml =
+                "<?xml version='1.0' encoding='utf-8' standalone='yes'?>\n"
+                        + "<overlays version='" + version + "'>\n"
+                        + "<item packageName='com.test.overlay'\n"
+                        + "      overlayName='test'\n"
+                        + "      userId='1234'\n"
+                        + "      targetPackageName='com.test.target'\n"
+                        + "      baseCodePath='/data/app/com.test.overlay-1/base.apk'\n"
+                        + "      state='" + STATE_DISABLED + "'\n"
+                        + "      isEnabled='false'\n"
+                        + "      category='test-category'\n"
+                        + "      isStatic='false'\n"
+                        + "      priority='0' />\n"
+                        + "</overlays>\n";
+        ByteArrayInputStream is = new ByteArrayInputStream(xml.getBytes(UTF_8));
+
+        mSettings.restore(is);
+        final OverlayIdentifier identifier = new OverlayIdentifier("com.test.overlay", "test");
+        OverlayInfo oi = mSettings.getOverlayInfo(identifier, 1234);
+        assertNotNull(oi);
+        assertEquals("com.test.overlay", oi.packageName);
+        assertEquals("test", oi.overlayName);
+        assertEquals("com.test.target", oi.targetPackageName);
+        assertEquals("/data/app/com.test.overlay-1/base.apk", oi.baseCodePath);
+        assertEquals(1234, oi.userId);
+        assertEquals(STATE_DISABLED, oi.state);
+        assertFalse(mSettings.getEnabled(identifier, 1234));
+        assertTrue(oi.constraints.isEmpty());
+    }
+
+    @Test
     public void testPersistAndRestore() throws Exception {
         insertSetting(OVERLAY_A_USER0);
         insertSetting(OVERLAY_B_USER1);
@@ -585,4 +620,11 @@
                         TextUtils.join(",", expected), TextUtils.join(",", actual)));
         }
     }
+
+    private static Integer[] getPreviousVersions() {
+        return new Integer[]{
+                3,
+                4,
+        };
+    }
 }