Merge "Name AppFunction executors" into main
diff --git a/core/java/com/android/internal/protolog/ProtoLogViewerConfigReader.java b/core/java/com/android/internal/protolog/ProtoLogViewerConfigReader.java
index 3c201fc..571fe0b 100644
--- a/core/java/com/android/internal/protolog/ProtoLogViewerConfigReader.java
+++ b/core/java/com/android/internal/protolog/ProtoLogViewerConfigReader.java
@@ -96,6 +96,7 @@
                 logger.log("Unloading viewer config hash " + hash);
                 mLogMessageMap.remove(hash);
             }
+            mGroupHashes.remove(group);
         }
     }
 
diff --git a/core/res/res/values/themes_device_defaults.xml b/core/res/res/values/themes_device_defaults.xml
index d35bfb7..352c390 100644
--- a/core/res/res/values/themes_device_defaults.xml
+++ b/core/res/res/values/themes_device_defaults.xml
@@ -212,9 +212,9 @@
 
         <!-- Color palette -->
         <item name="colorPrimary">@color/primary_device_default_dark</item>
-        <item name="colorPrimaryDark">@color/primary_device_default_dark</item>
+        <item name="colorPrimaryDark">@color/primary_dark_device_default_dark</item>
         <item name="colorAccent">@color/accent_device_default_dark</item>
-        <item name="colorAccentPrimary">@color/system_primary_dark</item>
+        <item name="colorAccentPrimary">@color/accent_primary_device_default</item>
         <item name="colorAccentSecondary">@color/system_secondary_dark</item>
         <item name="colorAccentTertiary">@color/system_tertiary_dark</item>
         <item name="colorAccentPrimaryVariant">@color/system_primary_container_dark</item>
@@ -314,9 +314,9 @@
     <style name="Theme.DeviceDefault.NoActionBar" parent="Theme.Material.NoActionBar">
         <!-- Color palette -->
         <item name="colorPrimary">@color/primary_device_default_dark</item>
-        <item name="colorPrimaryDark">@color/primary_device_default_dark</item>
+        <item name="colorPrimaryDark">@color/primary_dark_device_default_dark</item>
         <item name="colorAccent">@color/accent_device_default_dark</item>
-        <item name="colorAccentPrimary">@color/system_primary_dark</item>
+        <item name="colorAccentPrimary">@color/accent_primary_device_default</item>
         <item name="colorAccentSecondary">@color/system_secondary_dark</item>
         <item name="colorAccentTertiary">@color/system_tertiary_dark</item>
         <item name="colorAccentPrimaryVariant">@color/system_primary_container_dark</item>
@@ -431,9 +431,9 @@
     <style name="Theme.DeviceDefault.NoActionBar.Fullscreen" parent="Theme.Material.NoActionBar.Fullscreen">
         <!-- Color palette -->
         <item name="colorPrimary">@color/primary_device_default_dark</item>
-        <item name="colorPrimaryDark">@color/primary_device_default_dark</item>
+        <item name="colorPrimaryDark">@color/primary_dark_device_default_dark</item>
         <item name="colorAccent">@color/accent_device_default_dark</item>
-        <item name="colorAccentPrimary">@color/system_primary_dark</item>
+        <item name="colorAccentPrimary">@color/accent_primary_device_default</item>
         <item name="colorAccentSecondary">@color/system_secondary_dark</item>
         <item name="colorAccentTertiary">@color/system_tertiary_dark</item>
         <item name="colorAccentPrimaryVariant">@color/system_primary_container_dark</item>
@@ -550,9 +550,9 @@
     <style name="Theme.DeviceDefault.NoActionBar.Overscan" parent="Theme.Material.NoActionBar.Overscan">
         <!-- Color palette -->
         <item name="colorPrimary">@color/primary_device_default_dark</item>
-        <item name="colorPrimaryDark">@color/primary_device_default_dark</item>
+        <item name="colorPrimaryDark">@color/primary_dark_device_default_dark</item>
         <item name="colorAccent">@color/accent_device_default_dark</item>
-        <item name="colorAccentPrimary">@color/system_primary_dark</item>
+        <item name="colorAccentPrimary">@color/accent_primary_device_default</item>
         <item name="colorAccentSecondary">@color/system_secondary_dark</item>
         <item name="colorAccentTertiary">@color/system_tertiary_dark</item>
         <item name="colorAccentPrimaryVariant">@color/system_primary_container_dark</item>
@@ -668,9 +668,9 @@
     <style name="Theme.DeviceDefault.NoActionBar.TranslucentDecor" parent="Theme.Material.NoActionBar.TranslucentDecor">
         <!-- Color palette -->
         <item name="colorPrimary">@color/primary_device_default_dark</item>
-        <item name="colorPrimaryDark">@color/primary_device_default_dark</item>
+        <item name="colorPrimaryDark">@color/primary_dark_device_default_dark</item>
         <item name="colorAccent">@color/accent_device_default_dark</item>
-        <item name="colorAccentPrimary">@color/system_primary_dark</item>
+        <item name="colorAccentPrimary">@color/accent_primary_device_default</item>
         <item name="colorAccentSecondary">@color/system_secondary_dark</item>
         <item name="colorAccentTertiary">@color/system_tertiary_dark</item>
         <item name="colorAccentPrimaryVariant">@color/system_primary_container_dark</item>
@@ -801,9 +801,9 @@
 
         <!-- Color palette -->
         <item name="colorPrimary">@color/primary_device_default_dark</item>
-        <item name="colorPrimaryDark">@color/primary_device_default_dark</item>
+        <item name="colorPrimaryDark">@color/primary_dark_device_default_dark</item>
         <item name="colorAccent">@color/accent_device_default_dark</item>
-        <item name="colorAccentPrimary">@color/system_primary_dark</item>
+        <item name="colorAccentPrimary">@color/accent_primary_device_default</item>
         <item name="colorAccentSecondary">@color/system_secondary_dark</item>
         <item name="colorAccentTertiary">@color/system_tertiary_dark</item>
         <item name="colorAccentPrimaryVariant">@color/system_primary_container_dark</item>
@@ -911,9 +911,9 @@
     <style name="Theme.DeviceDefault.Dialog.MinWidth" parent="Theme.Material.Dialog.MinWidth">
         <!-- Color palette -->
         <item name="colorPrimary">@color/primary_device_default_dark</item>
-        <item name="colorPrimaryDark">@color/primary_device_default_dark</item>
+        <item name="colorPrimaryDark">@color/primary_dark_device_default_dark</item>
         <item name="colorAccent">@color/accent_device_default_dark</item>
-        <item name="colorAccentPrimary">@color/system_primary_dark</item>
+        <item name="colorAccentPrimary">@color/accent_primary_device_default</item>
         <item name="colorAccentSecondary">@color/system_secondary_dark</item>
         <item name="colorAccentTertiary">@color/system_tertiary_dark</item>
         <item name="colorAccentPrimaryVariant">@color/system_primary_container_dark</item>
@@ -1027,9 +1027,9 @@
     <style name="Theme.DeviceDefault.Dialog.NoActionBar" parent="Theme.Material.Dialog.NoActionBar">
         <!-- Color palette -->
         <item name="colorPrimary">@color/primary_device_default_dark</item>
-        <item name="colorPrimaryDark">@color/primary_device_default_dark</item>
+        <item name="colorPrimaryDark">@color/primary_dark_device_default_dark</item>
         <item name="colorAccent">@color/accent_device_default_dark</item>
-        <item name="colorAccentPrimary">@color/system_primary_dark</item>
+        <item name="colorAccentPrimary">@color/accent_primary_device_default</item>
         <item name="colorAccentSecondary">@color/system_secondary_dark</item>
         <item name="colorAccentTertiary">@color/system_tertiary_dark</item>
         <item name="colorAccentPrimaryVariant">@color/system_primary_container_dark</item>
@@ -1144,9 +1144,9 @@
     <style name="Theme.DeviceDefault.Dialog.NoActionBar.MinWidth" parent="Theme.Material.Dialog.NoActionBar.MinWidth">
         <!-- Color palette -->
         <item name="colorPrimary">@color/primary_device_default_dark</item>
-        <item name="colorPrimaryDark">@color/primary_device_default_dark</item>
+        <item name="colorPrimaryDark">@color/primary_dark_device_default_dark</item>
         <item name="colorAccent">@color/accent_device_default_dark</item>
-        <item name="colorAccentPrimary">@color/system_primary_dark</item>
+        <item name="colorAccentPrimary">@color/accent_primary_device_default</item>
         <item name="colorAccentSecondary">@color/system_secondary_dark</item>
         <item name="colorAccentTertiary">@color/system_tertiary_dark</item>
         <item name="colorAccentPrimaryVariant">@color/system_primary_container_dark</item>
@@ -1277,9 +1277,9 @@
     <style name="Theme.DeviceDefault.DialogWhenLarge" parent="Theme.Material.DialogWhenLarge">
         <!-- Color palette -->
         <item name="colorPrimary">@color/primary_device_default_dark</item>
-        <item name="colorPrimaryDark">@color/primary_device_default_dark</item>
+        <item name="colorPrimaryDark">@color/primary_dark_device_default_dark</item>
         <item name="colorAccent">@color/accent_device_default_dark</item>
-        <item name="colorAccentPrimary">@color/system_primary_dark</item>
+        <item name="colorAccentPrimary">@color/accent_primary_device_default</item>
         <item name="colorAccentSecondary">@color/system_secondary_dark</item>
         <item name="colorAccentTertiary">@color/system_tertiary_dark</item>
         <item name="colorAccentPrimaryVariant">@color/system_primary_container_dark</item>
@@ -1395,9 +1395,9 @@
     <style name="Theme.DeviceDefault.DialogWhenLarge.NoActionBar" parent="Theme.Material.DialogWhenLarge.NoActionBar">
         <!-- Color palette -->
         <item name="colorPrimary">@color/primary_device_default_dark</item>
-        <item name="colorPrimaryDark">@color/primary_device_default_dark</item>
+        <item name="colorPrimaryDark">@color/primary_dark_device_default_dark</item>
         <item name="colorAccent">@color/accent_device_default_dark</item>
-        <item name="colorAccentPrimary">@color/system_primary_dark</item>
+        <item name="colorAccentPrimary">@color/accent_primary_device_default</item>
         <item name="colorAccentSecondary">@color/system_secondary_dark</item>
         <item name="colorAccentTertiary">@color/system_tertiary_dark</item>
         <item name="colorAccentPrimaryVariant">@color/system_primary_container_dark</item>
@@ -1511,9 +1511,9 @@
     <style name="Theme.DeviceDefault.Dialog.Presentation" parent="Theme.Material.Dialog.Presentation">
         <!-- Color palette -->
         <item name="colorPrimary">@color/primary_device_default_dark</item>
-        <item name="colorPrimaryDark">@color/primary_device_default_dark</item>
+        <item name="colorPrimaryDark">@color/primary_dark_device_default_dark</item>
         <item name="colorAccent">@color/accent_device_default_dark</item>
-        <item name="colorAccentPrimary">@color/system_primary_dark</item>
+        <item name="colorAccentPrimary">@color/accent_primary_device_default</item>
         <item name="colorAccentSecondary">@color/system_secondary_dark</item>
         <item name="colorAccentTertiary">@color/system_tertiary_dark</item>
         <item name="colorAccentPrimaryVariant">@color/system_primary_container_dark</item>
@@ -1629,9 +1629,9 @@
     <style name="Theme.DeviceDefault.Panel" parent="Theme.Material.Panel">
         <!-- Color palette -->
         <item name="colorPrimary">@color/primary_device_default_dark</item>
-        <item name="colorPrimaryDark">@color/primary_device_default_dark</item>
+        <item name="colorPrimaryDark">@color/primary_dark_device_default_dark</item>
         <item name="colorAccent">@color/accent_device_default_dark</item>
-        <item name="colorAccentPrimary">@color/system_primary_dark</item>
+        <item name="colorAccentPrimary">@color/accent_primary_device_default</item>
         <item name="colorAccentSecondary">@color/system_secondary_dark</item>
         <item name="colorAccentTertiary">@color/system_tertiary_dark</item>
         <item name="colorAccentPrimaryVariant">@color/system_primary_container_dark</item>
@@ -1746,9 +1746,9 @@
     <style name="Theme.DeviceDefault.Wallpaper" parent="Theme.Material.Wallpaper">
         <!-- Color palette -->
         <item name="colorPrimary">@color/primary_device_default_dark</item>
-        <item name="colorPrimaryDark">@color/primary_device_default_dark</item>
+        <item name="colorPrimaryDark">@color/primary_dark_device_default_dark</item>
         <item name="colorAccent">@color/accent_device_default_dark</item>
-        <item name="colorAccentPrimary">@color/system_primary_dark</item>
+        <item name="colorAccentPrimary">@color/accent_primary_device_default</item>
         <item name="colorAccentSecondary">@color/system_secondary_dark</item>
         <item name="colorAccentTertiary">@color/system_tertiary_dark</item>
         <item name="colorAccentPrimaryVariant">@color/system_primary_container_dark</item>
@@ -1863,9 +1863,9 @@
     <style name="Theme.DeviceDefault.Wallpaper.NoTitleBar" parent="Theme.Material.Wallpaper.NoTitleBar">
         <!-- Color palette -->
         <item name="colorPrimary">@color/primary_device_default_dark</item>
-        <item name="colorPrimaryDark">@color/primary_device_default_dark</item>
+        <item name="colorPrimaryDark">@color/primary_dark_device_default_dark</item>
         <item name="colorAccent">@color/accent_device_default_dark</item>
-        <item name="colorAccentPrimary">@color/system_primary_dark</item>
+        <item name="colorAccentPrimary">@color/accent_primary_device_default</item>
         <item name="colorAccentSecondary">@color/system_secondary_dark</item>
         <item name="colorAccentTertiary">@color/system_tertiary_dark</item>
         <item name="colorAccentPrimaryVariant">@color/system_primary_container_dark</item>
@@ -1980,9 +1980,9 @@
     <style name="Theme.DeviceDefault.InputMethod" parent="Theme.Material.InputMethod">
         <!-- Color palette -->
         <item name="colorPrimary">@color/primary_device_default_light</item>
-        <item name="colorPrimaryDark">@color/primary_device_default_light</item>
+        <item name="colorPrimaryDark">@color/primary_dark_device_default_light</item>
         <item name="colorAccent">@color/accent_device_default_light</item>
-        <item name="colorAccentPrimary">@color/system_primary_dark</item>
+        <item name="colorAccentPrimary">@color/accent_primary_device_default</item>
         <item name="colorAccentSecondary">@color/system_secondary_dark</item>
         <item name="colorAccentTertiary">@color/system_tertiary_dark</item>
         <item name="colorAccentPrimaryVariant">@color/system_primary_container_light</item>
@@ -2097,9 +2097,9 @@
     <style name="Theme.DeviceDefault.VoiceInteractionSession" parent="Theme.Material.VoiceInteractionSession">
         <!-- Color palette -->
         <item name="colorPrimary">@color/primary_device_default_light</item>
-        <item name="colorPrimaryDark">@color/primary_device_default_light</item>
+        <item name="colorPrimaryDark">@color/primary_dark_device_default_light</item>
         <item name="colorAccent">@color/accent_device_default_light</item>
-        <item name="colorAccentPrimary">@color/system_primary_dark</item>
+        <item name="colorAccentPrimary">@color/accent_primary_device_default</item>
         <item name="colorAccentSecondary">@color/system_secondary_dark</item>
         <item name="colorAccentTertiary">@color/system_tertiary_dark</item>
         <item name="colorAccentPrimaryVariant">@color/system_primary_container_light</item>
@@ -2218,9 +2218,9 @@
 
         <!-- Color palette -->
         <item name="colorPrimary">@color/primary_device_default_dark</item>
-        <item name="colorPrimaryDark">@color/primary_device_default_dark</item>
+        <item name="colorPrimaryDark">@color/primary_dark_device_default_dark</item>
         <item name="colorAccent">@color/accent_device_default_dark</item>
-        <item name="colorAccentPrimary">@color/system_primary_dark</item>
+        <item name="colorAccentPrimary">@color/accent_primary_device_default</item>
         <item name="colorAccentSecondary">@color/system_secondary_dark</item>
         <item name="colorAccentTertiary">@color/system_tertiary_dark</item>
         <item name="colorAccentPrimaryVariant">@color/system_primary_container_dark</item>
@@ -2336,9 +2336,9 @@
     <style name="Theme.DeviceDefault.SearchBar" parent="Theme.Material.SearchBar">
         <!-- Color palette -->
         <item name="colorPrimary">@color/primary_device_default_dark</item>
-        <item name="colorPrimaryDark">@color/primary_device_default_dark</item>
+        <item name="colorPrimaryDark">@color/primary_dark_device_default_dark</item>
         <item name="colorAccent">@color/accent_device_default_dark</item>
-        <item name="colorAccentPrimary">@color/system_primary_dark</item>
+        <item name="colorAccentPrimary">@color/accent_primary_device_default</item>
         <item name="colorAccentSecondary">@color/system_secondary_dark</item>
         <item name="colorAccentTertiary">@color/system_tertiary_dark</item>
         <item name="colorAccentPrimaryVariant">@color/system_primary_container_dark</item>
@@ -2451,9 +2451,9 @@
     <style name="Theme.DeviceDefault.Dialog.NoFrame" parent="Theme.Material.Dialog.NoFrame">
         <!-- Color palette -->
         <item name="colorPrimary">@color/primary_device_default_dark</item>
-        <item name="colorPrimaryDark">@color/primary_device_default_dark</item>
+        <item name="colorPrimaryDark">@color/primary_dark_device_default_dark</item>
         <item name="colorAccent">@color/accent_device_default_dark</item>
-        <item name="colorAccentPrimary">@color/system_primary_dark</item>
+        <item name="colorAccentPrimary">@color/accent_primary_device_default</item>
         <item name="colorAccentSecondary">@color/system_secondary_dark</item>
         <item name="colorAccentTertiary">@color/system_tertiary_dark</item>
         <item name="colorAccentPrimaryVariant">@color/system_primary_container_dark</item>
@@ -2720,9 +2720,9 @@
 
         <!-- Color palette -->
         <item name="colorPrimary">@color/primary_device_default_light</item>
-        <item name="colorPrimaryDark">@color/primary_device_default_light</item>
+        <item name="colorPrimaryDark">@color/primary_dark_device_default_light</item>
         <item name="colorAccent">@color/accent_device_default_light</item>
-        <item name="colorAccentPrimary">@color/system_primary_dark</item>
+        <item name="colorAccentPrimary">@color/accent_primary_device_default</item>
         <item name="colorAccentSecondary">@color/system_secondary_dark</item>
         <item name="colorAccentTertiary">@color/system_tertiary_dark</item>
         <item name="colorAccentPrimaryVariant">@color/system_primary_container_light</item>
@@ -2821,9 +2821,9 @@
     <style name="Theme.DeviceDefault.Light.DarkActionBar" parent="Theme.Material.Light.DarkActionBar">
         <!-- Color palette -->
         <item name="colorPrimary">@color/primary_device_default_dark</item>
-        <item name="colorPrimaryDark">@color/primary_device_default_dark</item>
+        <item name="colorPrimaryDark">@color/primary_dark_device_default_dark</item>
         <item name="colorAccent">@color/accent_device_default_light</item>
-        <item name="colorAccentPrimary">@color/system_primary_dark</item>
+        <item name="colorAccentPrimary">@color/accent_primary_device_default</item>
         <item name="colorAccentSecondary">@color/system_secondary_dark</item>
         <item name="colorAccentTertiary">@color/system_tertiary_dark</item>
         <item name="colorAccentPrimaryVariant">@color/system_primary_container_light</item>
@@ -2937,9 +2937,9 @@
     <style name="Theme.DeviceDefault.Light.NoActionBar" parent="Theme.Material.Light.NoActionBar">
         <!-- Color palette -->
         <item name="colorPrimary">@color/primary_device_default_light</item>
-        <item name="colorPrimaryDark">@color/primary_device_default_light</item>
+        <item name="colorPrimaryDark">@color/primary_dark_device_default_light</item>
         <item name="colorAccent">@color/accent_device_default_light</item>
-        <item name="colorAccentPrimary">@color/system_primary_dark</item>
+        <item name="colorAccentPrimary">@color/accent_primary_device_default</item>
         <item name="colorAccentSecondary">@color/system_secondary_dark</item>
         <item name="colorAccentTertiary">@color/system_tertiary_dark</item>
         <item name="colorAccentPrimaryVariant">@color/system_primary_container_light</item>
@@ -3054,9 +3054,9 @@
     <style name="Theme.DeviceDefault.Light.NoActionBar.Fullscreen" parent="Theme.Material.Light.NoActionBar.Fullscreen">
         <!-- Color palette -->
         <item name="colorPrimary">@color/primary_device_default_light</item>
-        <item name="colorPrimaryDark">@color/primary_device_default_light</item>
+        <item name="colorPrimaryDark">@color/primary_dark_device_default_light</item>
         <item name="colorAccent">@color/accent_device_default_light</item>
-        <item name="colorAccentPrimary">@color/system_primary_dark</item>
+        <item name="colorAccentPrimary">@color/accent_primary_device_default</item>
         <item name="colorAccentSecondary">@color/system_secondary_dark</item>
         <item name="colorAccentTertiary">@color/system_tertiary_dark</item>
         <item name="colorAccentPrimaryVariant">@color/system_primary_container_light</item>
@@ -3173,9 +3173,9 @@
     <style name="Theme.DeviceDefault.Light.NoActionBar.Overscan" parent="Theme.Material.Light.NoActionBar.Overscan">
         <!-- Color palette -->
         <item name="colorPrimary">@color/primary_device_default_light</item>
-        <item name="colorPrimaryDark">@color/primary_device_default_light</item>
+        <item name="colorPrimaryDark">@color/primary_dark_device_default_light</item>
         <item name="colorAccent">@color/accent_device_default_light</item>
-        <item name="colorAccentPrimary">@color/system_primary_dark</item>
+        <item name="colorAccentPrimary">@color/accent_primary_device_default</item>
         <item name="colorAccentSecondary">@color/system_secondary_dark</item>
         <item name="colorAccentTertiary">@color/system_tertiary_dark</item>
         <item name="colorAccentPrimaryVariant">@color/system_primary_container_light</item>
@@ -3291,9 +3291,9 @@
     <style name="Theme.DeviceDefault.Light.NoActionBar.TranslucentDecor" parent="Theme.Material.Light.NoActionBar.TranslucentDecor">
         <!-- Color palette -->
         <item name="colorPrimary">@color/primary_device_default_light</item>
-        <item name="colorPrimaryDark">@color/primary_device_default_light</item>
+        <item name="colorPrimaryDark">@color/primary_dark_device_default_light</item>
         <item name="colorAccent">@color/accent_device_default_light</item>
-        <item name="colorAccentPrimary">@color/system_primary_dark</item>
+        <item name="colorAccentPrimary">@color/accent_primary_device_default</item>
         <item name="colorAccentSecondary">@color/system_secondary_dark</item>
         <item name="colorAccentTertiary">@color/system_tertiary_dark</item>
         <item name="colorAccentPrimaryVariant">@color/system_primary_container_light</item>
@@ -3426,9 +3426,9 @@
 
         <!-- Color palette -->
         <item name="colorPrimary">@color/primary_device_default_light</item>
-        <item name="colorPrimaryDark">@color/primary_device_default_light</item>
+        <item name="colorPrimaryDark">@color/primary_dark_device_default_light</item>
         <item name="colorAccent">@color/accent_device_default_light</item>
-        <item name="colorAccentPrimary">@color/system_primary_dark</item>
+        <item name="colorAccentPrimary">@color/accent_primary_device_default</item>
         <item name="colorAccentSecondary">@color/system_secondary_dark</item>
         <item name="colorAccentTertiary">@color/system_tertiary_dark</item>
         <item name="colorAccentPrimaryVariant">@color/system_primary_container_light</item>
@@ -3535,9 +3535,9 @@
 
         <!-- Color palette -->
         <item name="colorPrimary">@color/primary_device_default_light</item>
-        <item name="colorPrimaryDark">@color/primary_device_default_light</item>
+        <item name="colorPrimaryDark">@color/primary_dark_device_default_light</item>
         <item name="colorAccent">@color/accent_device_default_light</item>
-        <item name="colorAccentPrimary">@color/system_primary_dark</item>
+        <item name="colorAccentPrimary">@color/accent_primary_device_default</item>
         <item name="colorAccentSecondary">@color/system_secondary_dark</item>
         <item name="colorAccentTertiary">@color/system_tertiary_dark</item>
         <item name="colorAccentPrimaryVariant">@color/system_primary_container_light</item>
@@ -3654,9 +3654,9 @@
 
         <!-- Color palette -->
         <item name="colorPrimary">@color/primary_device_default_light</item>
-        <item name="colorPrimaryDark">@color/primary_device_default_light</item>
+        <item name="colorPrimaryDark">@color/primary_dark_device_default_light</item>
         <item name="colorAccent">@color/accent_device_default_light</item>
-        <item name="colorAccentPrimary">@color/system_primary_dark</item>
+        <item name="colorAccentPrimary">@color/accent_primary_device_default</item>
         <item name="colorAccentSecondary">@color/system_secondary_dark</item>
         <item name="colorAccentTertiary">@color/system_tertiary_dark</item>
         <item name="colorAccentPrimaryVariant">@color/system_primary_container_light</item>
@@ -3774,9 +3774,9 @@
 
         <!-- Color palette -->
         <item name="colorPrimary">@color/primary_device_default_light</item>
-        <item name="colorPrimaryDark">@color/primary_device_default_light</item>
+        <item name="colorPrimaryDark">@color/primary_dark_device_default_light</item>
         <item name="colorAccent">@color/accent_device_default_light</item>
-        <item name="colorAccentPrimary">@color/system_primary_dark</item>
+        <item name="colorAccentPrimary">@color/accent_primary_device_default</item>
         <item name="colorAccentSecondary">@color/system_secondary_dark</item>
         <item name="colorAccentTertiary">@color/system_tertiary_dark</item>
         <item name="colorAccentPrimaryVariant">@color/system_primary_container_light</item>
@@ -3895,9 +3895,9 @@
 
         <!-- Color palette -->
         <item name="colorPrimary">@color/primary_device_default_light</item>
-        <item name="colorPrimaryDark">@color/primary_device_default_light</item>
+        <item name="colorPrimaryDark">@color/primary_dark_device_default_light</item>
         <item name="colorAccent">@color/accent_device_default_light</item>
-        <item name="colorAccentPrimary">@color/system_primary_dark</item>
+        <item name="colorAccentPrimary">@color/accent_primary_device_default</item>
         <item name="colorAccentSecondary">@color/system_secondary_dark</item>
         <item name="colorAccentTertiary">@color/system_tertiary_dark</item>
         <item name="colorAccentPrimaryVariant">@color/system_primary_container_light</item>
@@ -3996,9 +3996,9 @@
 
         <!-- Color palette -->
         <item name="colorPrimary">@color/primary_device_default_light</item>
-        <item name="colorPrimaryDark">@color/primary_device_default_light</item>
+        <item name="colorPrimaryDark">@color/primary_dark_device_default_light</item>
         <item name="colorAccent">@color/accent_device_default_light</item>
-        <item name="colorAccentPrimary">@color/system_primary_dark</item>
+        <item name="colorAccentPrimary">@color/accent_primary_device_default</item>
         <item name="colorAccentSecondary">@color/system_secondary_dark</item>
         <item name="colorAccentTertiary">@color/system_tertiary_dark</item>
         <item name="colorAccentPrimaryVariant">@color/system_primary_container_light</item>
@@ -4096,9 +4096,9 @@
 
         <!-- Color palette -->
         <item name="colorPrimary">@color/primary_device_default_light</item>
-        <item name="colorPrimaryDark">@color/primary_device_default_light</item>
+        <item name="colorPrimaryDark">@color/primary_dark_device_default_light</item>
         <item name="colorAccent">@color/accent_device_default_light</item>
-        <item name="colorAccentPrimary">@color/system_primary_dark</item>
+        <item name="colorAccentPrimary">@color/accent_primary_device_default</item>
         <item name="colorAccentSecondary">@color/system_secondary_dark</item>
         <item name="colorAccentTertiary">@color/system_tertiary_dark</item>
         <item name="colorAccentPrimaryVariant">@color/system_primary_container_light</item>
@@ -4217,9 +4217,9 @@
 
         <!-- Color palette -->
         <item name="colorPrimary">@color/primary_device_default_light</item>
-        <item name="colorPrimaryDark">@color/primary_device_default_light</item>
+        <item name="colorPrimaryDark">@color/primary_dark_device_default_light</item>
         <item name="colorAccent">@color/accent_device_default_light</item>
-        <item name="colorAccentPrimary">@color/system_primary_dark</item>
+        <item name="colorAccentPrimary">@color/accent_primary_device_default</item>
         <item name="colorAccentSecondary">@color/system_secondary_dark</item>
         <item name="colorAccentTertiary">@color/system_tertiary_dark</item>
         <item name="colorAccentPrimaryVariant">@color/system_primary_container_light</item>
@@ -4336,9 +4336,9 @@
 
         <!-- Color palette -->
         <item name="colorPrimary">@color/primary_device_default_light</item>
-        <item name="colorPrimaryDark">@color/primary_device_default_light</item>
+        <item name="colorPrimaryDark">@color/primary_dark_device_default_light</item>
         <item name="colorAccent">@color/accent_device_default_light</item>
-        <item name="colorAccentPrimary">@color/system_primary_dark</item>
+        <item name="colorAccentPrimary">@color/accent_primary_device_default</item>
         <item name="colorAccentSecondary">@color/system_secondary_dark</item>
         <item name="colorAccentTertiary">@color/system_tertiary_dark</item>
         <item name="colorAccentPrimaryVariant">@color/system_primary_container_light</item>
@@ -4454,9 +4454,9 @@
     <style name="Theme.DeviceDefault.Light.Panel" parent="Theme.Material.Light.Panel">
         <!-- Color palette -->
         <item name="colorPrimary">@color/primary_device_default_light</item>
-        <item name="colorPrimaryDark">@color/primary_device_default_light</item>
+        <item name="colorPrimaryDark">@color/primary_dark_device_default_light</item>
         <item name="colorAccent">@color/accent_device_default_light</item>
-        <item name="colorAccentPrimary">@color/system_primary_dark</item>
+        <item name="colorAccentPrimary">@color/accent_primary_device_default</item>
         <item name="colorAccentSecondary">@color/system_secondary_dark</item>
         <item name="colorAccentTertiary">@color/system_tertiary_dark</item>
         <item name="colorAccentPrimaryVariant">@color/system_primary_container_light</item>
@@ -4571,9 +4571,9 @@
 
         <!-- Color palette -->
         <item name="colorPrimary">@color/primary_device_default_light</item>
-        <item name="colorPrimaryDark">@color/primary_device_default_light</item>
+        <item name="colorPrimaryDark">@color/primary_dark_device_default_light</item>
         <item name="colorAccent">@color/accent_device_default_light</item>
-        <item name="colorAccentPrimary">@color/system_primary_dark</item>
+        <item name="colorAccentPrimary">@color/accent_primary_device_default</item>
         <item name="colorAccentSecondary">@color/system_secondary_dark</item>
         <item name="colorAccentTertiary">@color/system_tertiary_dark</item>
         <item name="colorAccentPrimaryVariant">@color/system_primary_container_light</item>
@@ -4688,9 +4688,9 @@
     <style name="Theme.DeviceDefault.Light.SearchBar" parent="Theme.Material.Light.SearchBar">
         <!-- Color palette -->
         <item name="colorPrimary">@color/primary_device_default_light</item>
-        <item name="colorPrimaryDark">@color/primary_device_default_light</item>
+        <item name="colorPrimaryDark">@color/primary_dark_device_default_light</item>
         <item name="colorAccent">@color/accent_device_default_light</item>
-        <item name="colorAccentPrimary">@color/system_primary_dark</item>
+        <item name="colorAccentPrimary">@color/accent_primary_device_default</item>
         <item name="colorAccentSecondary">@color/system_secondary_dark</item>
         <item name="colorAccentTertiary">@color/system_tertiary_dark</item>
         <item name="colorAccentPrimaryVariant">@color/system_primary_container_light</item>
@@ -4803,9 +4803,9 @@
     <style name="Theme.DeviceDefault.Light.Voice" parent="Theme.Material.Light.Voice">
         <!-- Color palette -->
         <item name="colorPrimary">@color/primary_device_default_light</item>
-        <item name="colorPrimaryDark">@color/primary_device_default_light</item>
+        <item name="colorPrimaryDark">@color/primary_dark_device_default_light</item>
         <item name="colorAccent">@color/accent_device_default_light</item>
-        <item name="colorAccentPrimary">@color/system_primary_dark</item>
+        <item name="colorAccentPrimary">@color/accent_primary_device_default</item>
         <item name="colorAccentSecondary">@color/system_secondary_dark</item>
         <item name="colorAccentTertiary">@color/system_tertiary_dark</item>
         <item name="colorAccentPrimaryVariant">@color/system_primary_container_light</item>
@@ -4937,7 +4937,7 @@
         <item name="colorPrimaryDark">@color/primary_dark_device_default_settings_light</item>
         <item name="colorSecondary">@color/secondary_device_default_settings_light</item>
         <item name="colorAccent">@color/accent_device_default_light</item>
-        <item name="colorAccentPrimary">@color/system_primary_dark</item>
+        <item name="colorAccentPrimary">@color/accent_primary_device_default</item>
         <item name="colorAccentSecondary">@color/system_secondary_dark</item>
         <item name="colorAccentTertiary">@color/system_tertiary_dark</item>
         <item name="colorAccentPrimaryVariant">@color/system_primary_container_light</item>
@@ -5044,7 +5044,7 @@
         <item name="colorPrimaryDark">@color/primary_dark_device_default_settings_light</item>
         <item name="colorSecondary">@color/secondary_device_default_settings_light</item>
         <item name="colorAccent">@color/accent_device_default_light</item>
-        <item name="colorAccentPrimary">@color/system_primary_dark</item>
+        <item name="colorAccentPrimary">@color/accent_primary_device_default</item>
         <item name="colorAccentSecondary">@color/system_secondary_dark</item>
         <item name="colorAccentTertiary">@color/system_tertiary_dark</item>
         <item name="colorAccentPrimaryVariant">@color/system_primary_container_light</item>
@@ -5148,7 +5148,7 @@
         <item name="colorPrimaryDark">@color/primary_dark_device_default_settings_light</item>
         <item name="colorSecondary">@color/secondary_device_default_settings_light</item>
         <item name="colorAccent">@color/accent_device_default_light</item>
-        <item name="colorAccentPrimary">@color/system_primary_dark</item>
+        <item name="colorAccentPrimary">@color/accent_primary_device_default</item>
         <item name="colorAccentSecondary">@color/system_secondary_dark</item>
         <item name="colorAccentTertiary">@color/system_tertiary_dark</item>
         <item name="colorAccentPrimaryVariant">@color/system_primary_container_light</item>
@@ -5245,7 +5245,7 @@
         <item name="colorPrimaryDark">@color/primary_dark_device_default_settings</item>
         <item name="colorSecondary">@color/secondary_device_default_settings</item>
         <item name="colorAccent">@color/accent_device_default_dark</item>
-        <item name="colorAccentPrimary">@color/system_primary_dark</item>
+        <item name="colorAccentPrimary">@color/accent_primary_device_default</item>
         <item name="colorAccentSecondary">@color/system_secondary_dark</item>
         <item name="colorAccentTertiary">@color/system_tertiary_dark</item>
         <item name="colorAccentPrimaryVariant">@color/system_primary_container_dark</item>
@@ -5361,7 +5361,7 @@
         <item name="colorPrimaryDark">@color/primary_dark_device_default_settings</item>
         <item name="colorSecondary">@color/secondary_device_default_settings</item>
         <item name="colorAccent">@color/accent_device_default_light</item>
-        <item name="colorAccentPrimary">@color/system_primary_dark</item>
+        <item name="colorAccentPrimary">@color/accent_primary_device_default</item>
         <item name="colorAccentSecondary">@color/system_secondary_dark</item>
         <item name="colorAccentTertiary">@color/system_tertiary_dark</item>
         <item name="colorAccentPrimaryVariant">@color/system_primary_container_light</item>
@@ -5487,7 +5487,7 @@
         <item name="colorPrimaryDark">@color/primary_dark_device_default_settings</item>
         <item name="colorSecondary">@color/secondary_device_default_settings</item>
         <item name="colorAccent">@color/accent_device_default_light</item>
-        <item name="colorAccentPrimary">@color/system_primary_dark</item>
+        <item name="colorAccentPrimary">@color/accent_primary_device_default</item>
         <item name="colorAccentSecondary">@color/system_secondary_dark</item>
         <item name="colorAccentTertiary">@color/system_tertiary_dark</item>
         <item name="colorAccentPrimaryVariant">@color/system_primary_container_light</item>
@@ -5606,7 +5606,7 @@
         <item name="colorPrimaryDark">@color/primary_dark_device_default_settings</item>
         <item name="colorSecondary">@color/secondary_device_default_settings</item>
         <item name="colorAccent">@color/accent_device_default_light</item>
-        <item name="colorAccentPrimary">@color/system_primary_dark</item>
+        <item name="colorAccentPrimary">@color/accent_primary_device_default</item>
         <item name="colorAccentSecondary">@color/system_secondary_dark</item>
         <item name="colorAccentTertiary">@color/system_tertiary_dark</item>
         <item name="colorAccentPrimaryVariant">@color/system_primary_container_light</item>
@@ -5788,7 +5788,7 @@
 
     <style name="ThemeOverlay.DeviceDefault.Accent">
         <item name="colorAccent">@color/accent_device_default_dark</item>
-        <item name="colorAccentPrimary">@color/system_primary_dark</item>
+        <item name="colorAccentPrimary">@color/accent_primary_device_default</item>
         <item name="colorAccentSecondary">@color/system_secondary_dark</item>
         <item name="colorAccentTertiary">@color/system_tertiary_dark</item>
 
@@ -5863,7 +5863,7 @@
 
     <style name="ThemeOverlay.DeviceDefault.Accent.Light">
         <item name="colorAccent">@color/accent_device_default_light</item>
-        <item name="colorAccentPrimary">@color/system_primary_dark</item>
+        <item name="colorAccentPrimary">@color/accent_primary_device_default</item>
         <item name="colorAccentSecondary">@color/system_secondary_dark</item>
         <item name="colorAccentTertiary">@color/system_tertiary_dark</item>
 
@@ -5942,7 +5942,7 @@
 
     <style name="ThemeOverlay.DeviceDefault.Dark.ActionBar.Accent" parent="ThemeOverlay.Material.Dark.ActionBar">
         <item name="colorAccent">@color/accent_device_default_dark</item>
-        <item name="colorAccentPrimary">@color/system_primary_dark</item>
+        <item name="colorAccentPrimary">@color/accent_primary_device_default</item>
         <item name="colorAccentSecondary">@color/system_secondary_dark</item>
         <item name="colorAccentTertiary">@color/system_tertiary_dark</item>
 
diff --git a/packages/SettingsLib/DataStore/src/com/android/settingslib/datastore/SettingsStore.kt b/packages/SettingsLib/DataStore/src/com/android/settingslib/datastore/SettingsStore.kt
index fdefa39..1b270de 100644
--- a/packages/SettingsLib/DataStore/src/com/android/settingslib/datastore/SettingsStore.kt
+++ b/packages/SettingsLib/DataStore/src/com/android/settingslib/datastore/SettingsStore.kt
@@ -99,6 +99,37 @@
         contentResolver.unregisterContentObserver(contentObserver)
     }
 
+    /** Gets the boolean value of given key. */
+    fun getBoolean(key: String): Boolean? = getValue(key, Boolean::class.javaObjectType)
+
+    /** Sets boolean value for given key, null value means delete the key from data store. */
+    fun setBoolean(key: String, value: Boolean?) =
+        setValue(key, Boolean::class.javaObjectType, value)
+
+    /** Gets the float value of given key. */
+    fun getFloat(key: String): Float? = getValue(key, Float::class.javaObjectType)
+
+    /** Sets float value for given key, null value means delete the key from data store. */
+    fun setFloat(key: String, value: Float?) = setValue(key, Float::class.javaObjectType, value)
+
+    /** Gets the int value of given key. */
+    fun getInt(key: String): Int? = getValue(key, Int::class.javaObjectType)
+
+    /** Sets int value for given key, null value means delete the key from data store. */
+    fun setInt(key: String, value: Int?) = setValue(key, Int::class.javaObjectType, value)
+
+    /** Gets the long value of given key. */
+    fun getLong(key: String): Long? = getValue(key, Long::class.javaObjectType)
+
+    /** Sets long value for given key, null value means delete the key from data store. */
+    fun setLong(key: String, value: Long?) = setValue(key, Long::class.javaObjectType, value)
+
+    /** Gets the string value of given key. */
+    fun getString(key: String): String? = getValue(key, String::class.javaObjectType)
+
+    /** Sets string value for given key, null value means delete the key from data store. */
+    fun setString(key: String, value: String?) = setValue(key, String::class.javaObjectType, value)
+
     /** Tag for logging. */
     abstract val tag: String
 }
diff --git a/packages/SettingsLib/src/com/android/settingslib/display/DisplayDensityUtils.java b/packages/SettingsLib/src/com/android/settingslib/display/DisplayDensityUtils.java
index d4d2b48..d91c6bd 100644
--- a/packages/SettingsLib/src/com/android/settingslib/display/DisplayDensityUtils.java
+++ b/packages/SettingsLib/src/com/android/settingslib/display/DisplayDensityUtils.java
@@ -30,11 +30,12 @@
 import android.view.IWindowManager;
 import android.view.WindowManagerGlobal;
 
+import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
+
 import com.android.settingslib.R;
 
 import java.util.Arrays;
-import java.util.HashMap;
-import java.util.Map;
 import java.util.function.Predicate;
 
 /**
@@ -82,38 +83,55 @@
     private final DisplayManager mDisplayManager;
 
     /**
-     * The text description of the density values of the default display.
+     * The text description of the density values.
      */
-    private String[] mDefaultDisplayDensityEntries;
+    @Nullable
+    private final String[] mEntries;
 
     /**
-     * The density values of the default display.
+     * The density values.
      */
-    private int[] mDefaultDisplayDensityValues;
+    @Nullable
+    private final int[] mValues;
 
-    /**
-     * The density values, indexed by display unique ID.
-     */
-    private final Map<String, int[]> mValuesPerDisplay = new HashMap();
+    private final int mDefaultDensity;
+    private final int mCurrentIndex;
 
-    private int mDefaultDensityForDefaultDisplay;
-    private int mCurrentIndex = -1;
-
-    public DisplayDensityUtils(Context context) {
+    public DisplayDensityUtils(@NonNull Context context) {
         this(context, INTERNAL_ONLY);
     }
 
     /**
-     * Creates an instance that stores the density values for the displays that satisfy
-     * the predicate.
+     * Creates an instance that stores the density values for the smallest display that satisfies
+     * the predicate. It is enough to store the values for one display because the same density
+     * should be set to all the displays that satisfy the predicate.
      * @param context The context
      * @param predicate Determines what displays the density should be set for. The default display
      *                  must satisfy this predicate.
      */
-    public DisplayDensityUtils(Context context, Predicate predicate) {
+    public DisplayDensityUtils(@NonNull Context context,
+            @NonNull Predicate<DisplayInfo> predicate) {
         mPredicate = predicate;
         mDisplayManager = context.getSystemService(DisplayManager.class);
 
+        Display defaultDisplay = mDisplayManager.getDisplay(Display.DEFAULT_DISPLAY);
+        DisplayInfo defaultDisplayInfo = new DisplayInfo();
+        if (!defaultDisplay.getDisplayInfo(defaultDisplayInfo)) {
+            Log.w(LOG_TAG, "Cannot fetch display info for the default display");
+            mEntries = null;
+            mValues = null;
+            mDefaultDensity = 0;
+            mCurrentIndex = -1;
+            return;
+        }
+        if (!mPredicate.test(defaultDisplayInfo)) {
+            throw new IllegalArgumentException(
+                    "Predicate must not filter out the default display.");
+        }
+
+        int idOfSmallestDisplay = Display.DEFAULT_DISPLAY;
+        int minDimensionPx = Math.min(defaultDisplayInfo.logicalWidth,
+                defaultDisplayInfo.logicalHeight);
         for (Display display : mDisplayManager.getDisplays(
                 DisplayManager.DISPLAY_CATEGORY_ALL_INCLUDING_DISABLED)) {
             DisplayInfo info = new DisplayInfo();
@@ -122,121 +140,123 @@
                 continue;
             }
             if (!mPredicate.test(info)) {
-                if (display.getDisplayId() == Display.DEFAULT_DISPLAY) {
-                    throw new IllegalArgumentException("Predicate must not filter out the default "
-                            + "display.");
-                }
                 continue;
             }
-
-            final int defaultDensity = DisplayDensityUtils.getDefaultDensityForDisplay(
-                    display.getDisplayId());
-            if (defaultDensity <= 0) {
-                Log.w(LOG_TAG, "Cannot fetch default density for display "
-                        + display.getDisplayId());
-                continue;
+            int minDimension = Math.min(info.logicalWidth, info.logicalHeight);
+            if (minDimension < minDimensionPx) {
+                minDimensionPx = minDimension;
+                idOfSmallestDisplay = display.getDisplayId();
             }
-
-            final Resources res = context.getResources();
-
-            final int currentDensity = info.logicalDensityDpi;
-            int currentDensityIndex = -1;
-
-            // Compute number of "larger" and "smaller" scales for this display.
-            final int minDimensionPx = Math.min(info.logicalWidth, info.logicalHeight);
-            final int maxDensity =
-                    DisplayMetrics.DENSITY_MEDIUM * minDimensionPx / MIN_DIMENSION_DP;
-            final float maxScaleDimen = context.getResources().getFraction(
-                    R.fraction.display_density_max_scale, 1, 1);
-            final float maxScale = Math.min(maxScaleDimen, maxDensity / (float) defaultDensity);
-            final float minScale = context.getResources().getFraction(
-                    R.fraction.display_density_min_scale, 1, 1);
-            final float minScaleInterval = context.getResources().getFraction(
-                    R.fraction.display_density_min_scale_interval, 1, 1);
-            final int numLarger = (int) MathUtils.constrain((maxScale - 1) / minScaleInterval,
-                    0, SUMMARIES_LARGER.length);
-            final int numSmaller = (int) MathUtils.constrain((1 - minScale) / minScaleInterval,
-                    0, SUMMARIES_SMALLER.length);
-
-            String[] entries = new String[1 + numSmaller + numLarger];
-            int[] values = new int[entries.length];
-            int curIndex = 0;
-
-            if (numSmaller > 0) {
-                final float interval = (1 - minScale) / numSmaller;
-                for (int i = numSmaller - 1; i >= 0; i--) {
-                    // Round down to a multiple of 2 by truncating the low bit.
-                    final int density = ((int) (defaultDensity * (1 - (i + 1) * interval))) & ~1;
-                    if (currentDensity == density) {
-                        currentDensityIndex = curIndex;
-                    }
-                    entries[curIndex] = res.getString(SUMMARIES_SMALLER[i]);
-                    values[curIndex] = density;
-                    curIndex++;
-                }
-            }
-
-            if (currentDensity == defaultDensity) {
-                currentDensityIndex = curIndex;
-            }
-            values[curIndex] = defaultDensity;
-            entries[curIndex] = res.getString(SUMMARY_DEFAULT);
-            curIndex++;
-
-            if (numLarger > 0) {
-                final float interval = (maxScale - 1) / numLarger;
-                for (int i = 0; i < numLarger; i++) {
-                    // Round down to a multiple of 2 by truncating the low bit.
-                    final int density = ((int) (defaultDensity * (1 + (i + 1) * interval))) & ~1;
-                    if (currentDensity == density) {
-                        currentDensityIndex = curIndex;
-                    }
-                    values[curIndex] = density;
-                    entries[curIndex] = res.getString(SUMMARIES_LARGER[i]);
-                    curIndex++;
-                }
-            }
-
-            final int displayIndex;
-            if (currentDensityIndex >= 0) {
-                displayIndex = currentDensityIndex;
-            } else {
-                // We don't understand the current density. Must have been set by
-                // someone else. Make room for another entry...
-                int newLength = values.length + 1;
-                values = Arrays.copyOf(values, newLength);
-                values[curIndex] = currentDensity;
-
-                entries = Arrays.copyOf(entries, newLength);
-                entries[curIndex] = res.getString(SUMMARY_CUSTOM, currentDensity);
-
-                displayIndex = curIndex;
-            }
-
-            if (display.getDisplayId() == Display.DEFAULT_DISPLAY) {
-                mDefaultDensityForDefaultDisplay = defaultDensity;
-                mCurrentIndex = displayIndex;
-                mDefaultDisplayDensityEntries = entries;
-                mDefaultDisplayDensityValues = values;
-            }
-            mValuesPerDisplay.put(info.uniqueId, values);
         }
+
+        final int defaultDensity =
+                DisplayDensityUtils.getDefaultDensityForDisplay(idOfSmallestDisplay);
+        if (defaultDensity <= 0) {
+            Log.w(LOG_TAG, "Cannot fetch default density for display " + idOfSmallestDisplay);
+            mEntries = null;
+            mValues = null;
+            mDefaultDensity = 0;
+            mCurrentIndex = -1;
+            return;
+        }
+
+        final Resources res = context.getResources();
+
+        final int currentDensity = defaultDisplayInfo.logicalDensityDpi;
+        int currentDensityIndex = -1;
+
+        // Compute number of "larger" and "smaller" scales for this display.
+        final int maxDensity =
+                DisplayMetrics.DENSITY_MEDIUM * minDimensionPx / MIN_DIMENSION_DP;
+        final float maxScaleDimen = context.getResources().getFraction(
+                R.fraction.display_density_max_scale, 1, 1);
+        final float maxScale = Math.min(maxScaleDimen, maxDensity / (float) defaultDensity);
+        final float minScale = context.getResources().getFraction(
+                R.fraction.display_density_min_scale, 1, 1);
+        final float minScaleInterval = context.getResources().getFraction(
+                R.fraction.display_density_min_scale_interval, 1, 1);
+        final int numLarger = (int) MathUtils.constrain((maxScale - 1) / minScaleInterval,
+                0, SUMMARIES_LARGER.length);
+        final int numSmaller = (int) MathUtils.constrain((1 - minScale) / minScaleInterval,
+                0, SUMMARIES_SMALLER.length);
+
+        String[] entries = new String[1 + numSmaller + numLarger];
+        int[] values = new int[entries.length];
+        int curIndex = 0;
+
+        if (numSmaller > 0) {
+            final float interval = (1 - minScale) / numSmaller;
+            for (int i = numSmaller - 1; i >= 0; i--) {
+                // Round down to a multiple of 2 by truncating the low bit.
+                final int density = ((int) (defaultDensity * (1 - (i + 1) * interval))) & ~1;
+                if (currentDensity == density) {
+                    currentDensityIndex = curIndex;
+                }
+                entries[curIndex] = res.getString(SUMMARIES_SMALLER[i]);
+                values[curIndex] = density;
+                curIndex++;
+            }
+        }
+
+        if (currentDensity == defaultDensity) {
+            currentDensityIndex = curIndex;
+        }
+        values[curIndex] = defaultDensity;
+        entries[curIndex] = res.getString(SUMMARY_DEFAULT);
+        curIndex++;
+
+        if (numLarger > 0) {
+            final float interval = (maxScale - 1) / numLarger;
+            for (int i = 0; i < numLarger; i++) {
+                // Round down to a multiple of 2 by truncating the low bit.
+                final int density = ((int) (defaultDensity * (1 + (i + 1) * interval))) & ~1;
+                if (currentDensity == density) {
+                    currentDensityIndex = curIndex;
+                }
+                values[curIndex] = density;
+                entries[curIndex] = res.getString(SUMMARIES_LARGER[i]);
+                curIndex++;
+            }
+        }
+
+        final int displayIndex;
+        if (currentDensityIndex >= 0) {
+            displayIndex = currentDensityIndex;
+        } else {
+            // We don't understand the current density. Must have been set by
+            // someone else. Make room for another entry...
+            int newLength = values.length + 1;
+            values = Arrays.copyOf(values, newLength);
+            values[curIndex] = currentDensity;
+
+            entries = Arrays.copyOf(entries, newLength);
+            entries[curIndex] = res.getString(SUMMARY_CUSTOM, currentDensity);
+
+            displayIndex = curIndex;
+        }
+
+        mDefaultDensity = defaultDensity;
+        mCurrentIndex = displayIndex;
+        mEntries = entries;
+        mValues = values;
     }
 
-    public String[] getDefaultDisplayDensityEntries() {
-        return mDefaultDisplayDensityEntries;
+    @Nullable
+    public String[] getEntries() {
+        return mEntries;
     }
 
-    public int[] getDefaultDisplayDensityValues() {
-        return mDefaultDisplayDensityValues;
+    @Nullable
+    public int[] getValues() {
+        return mValues;
     }
 
-    public int getCurrentIndexForDefaultDisplay() {
+    public int getCurrentIndex() {
         return mCurrentIndex;
     }
 
-    public int getDefaultDensityForDefaultDisplay() {
-        return mDefaultDensityForDefaultDisplay;
+    public int getDefaultDensity() {
+        return mDefaultDensity;
     }
 
     /**
@@ -311,15 +331,9 @@
                     if (!mPredicate.test(info)) {
                         continue;
                     }
-                    if (!mValuesPerDisplay.containsKey(info.uniqueId)) {
-                        Log.w(LOG_TAG, "Unable to save forced display density setting "
-                                + "for display " + info.uniqueId);
-                        continue;
-                    }
 
                     final IWindowManager wm = WindowManagerGlobal.getWindowManagerService();
-                    wm.setForcedDisplayDensityForUser(displayId,
-                            mValuesPerDisplay.get(info.uniqueId)[index], userId);
+                    wm.setForcedDisplayDensityForUser(displayId, mValues[index], userId);
                 }
             } catch (RemoteException exc) {
                 Log.w(LOG_TAG, "Unable to save forced display density setting");
diff --git a/packages/SystemUI/compose/features/src/com/android/systemui/statusbar/phone/SystemUIDialogFactoryExt.kt b/packages/SystemUI/compose/features/src/com/android/systemui/statusbar/phone/SystemUIDialogFactoryExt.kt
index fe97405..e9b7335 100644
--- a/packages/SystemUI/compose/features/src/com/android/systemui/statusbar/phone/SystemUIDialogFactoryExt.kt
+++ b/packages/SystemUI/compose/features/src/com/android/systemui/statusbar/phone/SystemUIDialogFactoryExt.kt
@@ -16,34 +16,58 @@
 
 package com.android.systemui.statusbar.phone
 
+import android.app.Dialog
 import android.content.Context
 import android.content.res.Configuration
 import android.os.Bundle
 import androidx.annotation.GravityInt
+import androidx.compose.foundation.clickable
+import androidx.compose.foundation.gestures.AnchoredDraggableDefaults
+import androidx.compose.foundation.gestures.AnchoredDraggableState
+import androidx.compose.foundation.gestures.DraggableAnchors
+import androidx.compose.foundation.gestures.Orientation
+import androidx.compose.foundation.gestures.anchoredDraggable
 import androidx.compose.foundation.gestures.detectTapGestures
+import androidx.compose.foundation.interaction.MutableInteractionSource
+import androidx.compose.foundation.interaction.collectIsDraggedAsState
 import androidx.compose.foundation.layout.Box
+import androidx.compose.foundation.layout.Column
 import androidx.compose.foundation.layout.WindowInsets
+import androidx.compose.foundation.layout.offset
 import androidx.compose.foundation.layout.padding
 import androidx.compose.foundation.layout.safeDrawing
+import androidx.compose.foundation.layout.size
 import androidx.compose.foundation.layout.widthIn
+import androidx.compose.foundation.layout.wrapContentWidth
 import androidx.compose.foundation.shape.RoundedCornerShape
 import androidx.compose.material3.LocalContentColor
 import androidx.compose.material3.MaterialTheme
 import androidx.compose.material3.Surface
 import androidx.compose.runtime.Composable
 import androidx.compose.runtime.CompositionLocalProvider
+import androidx.compose.runtime.LaunchedEffect
+import androidx.compose.runtime.getValue
+import androidx.compose.runtime.remember
 import androidx.compose.ui.Alignment
 import androidx.compose.ui.Modifier
 import androidx.compose.ui.input.pointer.pointerInput
+import androidx.compose.ui.layout.onSizeChanged
 import androidx.compose.ui.platform.ComposeView
 import androidx.compose.ui.platform.LocalConfiguration
 import androidx.compose.ui.platform.LocalDensity
 import androidx.compose.ui.platform.LocalLayoutDirection
 import androidx.compose.ui.res.dimensionResource
+import androidx.compose.ui.res.stringResource
+import androidx.compose.ui.semantics.contentDescription
+import androidx.compose.ui.semantics.semantics
 import androidx.compose.ui.unit.Dp
+import androidx.compose.ui.unit.IntOffset
 import androidx.compose.ui.unit.dp
+import androidx.compose.ui.unit.isSpecified
 import com.android.compose.theme.PlatformTheme
+import com.android.systemui.keyboard.shortcut.ui.composable.hasCompactWindowSize
 import com.android.systemui.res.R
+import kotlin.math.roundToInt
 
 /**
  * Create a [SystemUIDialog] with the given [content].
@@ -97,6 +121,9 @@
     theme: Int = R.style.Theme_SystemUI_BottomSheet,
     dismissOnDeviceLock: Boolean = SystemUIDialog.DEFAULT_DISMISS_ON_DEVICE_LOCK,
     content: @Composable (SystemUIDialog) -> Unit,
+    isDraggable: Boolean = true,
+    // TODO(b/337205027): remove maxWidth parameter when aligned to M3 spec
+    maxWidth: Dp = Dp.Unspecified,
 ): ComponentSystemUIDialog {
     return create(
         context = context,
@@ -104,9 +131,49 @@
         dismissOnDeviceLock = dismissOnDeviceLock,
         delegate = EdgeToEdgeDialogDelegate(),
         content = { dialog ->
+            val dragState =
+                if (isDraggable)
+                    remember { AnchoredDraggableState(initialValue = DragAnchors.Start) }
+                else null
+            val interactionSource =
+                if (isDraggable) remember { MutableInteractionSource() } else null
+            if (dragState != null) {
+                val isDragged by interactionSource!!.collectIsDraggedAsState()
+                LaunchedEffect(dragState.currentValue, isDragged) {
+                    if (!isDragged && dragState.currentValue == DragAnchors.End) dialog.dismiss()
+                }
+            }
             Box(
-                modifier = Modifier.bottomSheetClickable { dialog.dismiss() },
-                contentAlignment = Alignment.BottomCenter
+                modifier =
+                    Modifier.bottomSheetClickable { dialog.dismiss() }
+                        .then(
+                            if (isDraggable)
+                                Modifier.anchoredDraggable(
+                                        state = dragState!!,
+                                        interactionSource = interactionSource,
+                                        orientation = Orientation.Vertical,
+                                        flingBehavior =
+                                            AnchoredDraggableDefaults.flingBehavior(
+                                                state = dragState
+                                            ),
+                                    )
+                                    .offset {
+                                        IntOffset(x = 0, y = dragState.requireOffset().roundToInt())
+                                    }
+                                    .onSizeChanged { layoutSize ->
+                                        val dragEndPoint = layoutSize.height - dialog.height
+                                        dragState.updateAnchors(
+                                            DraggableAnchors {
+                                                DragAnchors.entries.forEach { anchor ->
+                                                    anchor at dragEndPoint * anchor.fraction
+                                                }
+                                            }
+                                        )
+                                    }
+                                    .padding(top = draggableTopPadding())
+                            else Modifier // No-Op
+                        ),
+                contentAlignment = Alignment.BottomCenter,
             ) {
                 val radius = dimensionResource(R.dimen.bottom_sheet_corner_radius)
                 Surface(
@@ -114,8 +181,11 @@
                         Modifier.bottomSheetPaddings()
                             // consume input so it doesn't get to the parent Composable
                             .bottomSheetClickable {}
-                            // TODO(b/337205027) change width
-                            .widthIn(max = 800.dp),
+                            .widthIn(
+                                max =
+                                    if (maxWidth.isSpecified) maxWidth
+                                    else DraggableBottomSheet.MaxWidth
+                            ),
                     shape = RoundedCornerShape(topStart = radius, topEnd = radius),
                     color = MaterialTheme.colorScheme.surfaceContainer,
                 ) {
@@ -127,7 +197,17 @@
                                 }
                         )
                     ) {
-                        content(dialog)
+                        if (isDraggable) {
+                            Column(
+                                Modifier.wrapContentWidth(Alignment.CenterHorizontally),
+                                horizontalAlignment = Alignment.CenterHorizontally,
+                            ) {
+                                DragHandle(dialog)
+                                content(dialog)
+                            }
+                        } else {
+                            content(dialog)
+                        }
                     }
                 }
             }
@@ -135,6 +215,11 @@
     )
 }
 
+private enum class DragAnchors(val fraction: Float) {
+    Start(0f),
+    End(1f),
+}
+
 private fun SystemUIDialogFactory.create(
     context: Context,
     theme: Int,
@@ -177,7 +262,7 @@
         padding(
             start = insets.getLeft(this, LocalLayoutDirection.current).toDp() + horizontalPadding,
             top = insets.getTop(this).toDp(),
-            end = insets.getRight(this, LocalLayoutDirection.current).toDp() + horizontalPadding
+            end = insets.getRight(this, LocalLayoutDirection.current).toDp() + horizontalPadding,
         )
     }
 }
@@ -191,3 +276,32 @@
 @Composable
 private fun Modifier.bottomSheetClickable(onClick: () -> Unit) =
     pointerInput(onClick) { detectTapGestures { onClick() } }
+
+@Composable
+private fun DragHandle(dialog: Dialog) {
+    // TODO(b/373340318): Rename drag handle string resource.
+    val dragHandleContentDescription =
+        stringResource(id = R.string.shortcut_helper_content_description_drag_handle)
+    Surface(
+        modifier =
+            Modifier.padding(top = 16.dp, bottom = 6.dp)
+                .semantics { contentDescription = dragHandleContentDescription }
+                .clickable { dialog.dismiss() },
+        color = MaterialTheme.colorScheme.outlineVariant,
+        shape = MaterialTheme.shapes.extraLarge,
+    ) {
+        Box(Modifier.size(width = 32.dp, height = 4.dp))
+    }
+}
+
+@Composable
+private fun draggableTopPadding(): Dp {
+    return if (hasCompactWindowSize()) DraggableBottomSheet.DefaultTopPadding
+    else DraggableBottomSheet.LargeScreenTopPadding
+}
+
+private object DraggableBottomSheet {
+    val DefaultTopPadding = 64.dp
+    val LargeScreenTopPadding = 72.dp
+    val MaxWidth = 640.dp
+}
diff --git a/packages/SystemUI/compose/features/src/com/android/systemui/volume/panel/ui/composable/VolumePanelRoot.kt b/packages/SystemUI/compose/features/src/com/android/systemui/volume/panel/ui/composable/VolumePanelRoot.kt
index 1cc0fb2..cf74785 100644
--- a/packages/SystemUI/compose/features/src/com/android/systemui/volume/panel/ui/composable/VolumePanelRoot.kt
+++ b/packages/SystemUI/compose/features/src/com/android/systemui/volume/panel/ui/composable/VolumePanelRoot.kt
@@ -31,7 +31,6 @@
 import androidx.compose.ui.semantics.semantics
 import androidx.compose.ui.unit.dp
 import androidx.lifecycle.compose.collectAsStateWithLifecycle
-import com.android.compose.theme.PlatformTheme
 import com.android.systemui.compose.modifiers.sysuiResTag
 import com.android.systemui.res.R
 import com.android.systemui.volume.panel.ui.layout.ComponentsLayout
@@ -43,30 +42,20 @@
 private val padding = 24.dp
 
 @Composable
-fun VolumePanelRoot(
-    viewModel: VolumePanelViewModel,
-    modifier: Modifier = Modifier,
-) {
+fun VolumePanelRoot(viewModel: VolumePanelViewModel, modifier: Modifier = Modifier) {
     val accessibilityTitle = stringResource(R.string.accessibility_volume_settings)
     val state: VolumePanelState by viewModel.volumePanelState.collectAsStateWithLifecycle()
     val components by viewModel.componentsLayout.collectAsStateWithLifecycle()
 
     with(VolumePanelComposeScope(state)) {
         components?.let { componentsState ->
-            PlatformTheme {
-                Components(
-                    componentsState,
-                    modifier
-                        .sysuiResTag(VolumePanelTestTag)
-                        .semantics { paneTitle = accessibilityTitle }
-                        .padding(
-                            start = padding,
-                            top = padding,
-                            end = padding,
-                            bottom = 20.dp,
-                        )
-                )
-            }
+            Components(
+                componentsState,
+                modifier
+                    .sysuiResTag(VolumePanelTestTag)
+                    .semantics { paneTitle = accessibilityTitle }
+                    .padding(start = padding, top = padding, end = padding, bottom = 20.dp),
+            )
         }
     }
 }
@@ -74,7 +63,7 @@
 @Composable
 private fun VolumePanelComposeScope.Components(
     layout: ComponentsLayout,
-    modifier: Modifier = Modifier
+    modifier: Modifier = Modifier,
 ) {
     val arrangement: Arrangement.Vertical =
         if (isLargeScreen) {
@@ -82,14 +71,11 @@
         } else {
             if (isPortrait) Arrangement.spacedBy(padding) else Arrangement.spacedBy(4.dp)
         }
-    Column(
-        modifier = modifier,
-        verticalArrangement = arrangement,
-    ) {
+    Column(modifier = modifier, verticalArrangement = arrangement) {
         if (isPortrait || isLargeScreen) {
             VerticalVolumePanelContent(
                 modifier = Modifier.weight(weight = 1f, fill = false),
-                layout = layout
+                layout = layout,
             )
         } else {
             HorizontalVolumePanelContent(
@@ -97,23 +83,17 @@
                 layout = layout,
             )
         }
-        BottomBar(
-            modifier = Modifier,
-            layout = layout,
-        )
+        BottomBar(modifier = Modifier, layout = layout)
     }
 }
 
 @Composable
 private fun VolumePanelComposeScope.BottomBar(
     layout: ComponentsLayout,
-    modifier: Modifier = Modifier
+    modifier: Modifier = Modifier,
 ) {
     if (layout.bottomBarComponent.isVisible) {
-        Box(
-            modifier = modifier.fillMaxWidth(),
-            contentAlignment = Alignment.Center,
-        ) {
+        Box(modifier = modifier.fillMaxWidth(), contentAlignment = Alignment.Center) {
             with(layout.bottomBarComponent.component as ComposeVolumePanelUiComponent) {
                 Content(Modifier)
             }
diff --git a/packages/SystemUI/customization/src/com/android/systemui/shared/clocks/AssetLoader.kt b/packages/SystemUI/customization/src/com/android/systemui/shared/clocks/AssetLoader.kt
index d001ef96..031fbab 100644
--- a/packages/SystemUI/customization/src/com/android/systemui/shared/clocks/AssetLoader.kt
+++ b/packages/SystemUI/customization/src/com/android/systemui/shared/clocks/AssetLoader.kt
@@ -68,7 +68,10 @@
         seedColor = null,
         overrideChroma = null,
         typefaceCache =
-            TypefaceCache(messageBuffer) { Typeface.createFromAsset(pluginCtx.assets, it) },
+            TypefaceCache(messageBuffer) {
+                // TODO(b/364680873): Move constant to config_clockFontFamily when shipping
+                return@TypefaceCache Typeface.create("google-sans-flex-clock", Typeface.NORMAL)
+            },
         getThemeSeedColor = getThemeSeedColor ?: Companion::getThemeSeedColor,
         messageBuffer = messageBuffer,
     )
diff --git a/packages/SystemUI/customization/src/com/android/systemui/shared/clocks/DefaultClockProvider.kt b/packages/SystemUI/customization/src/com/android/systemui/shared/clocks/DefaultClockProvider.kt
index 3903dba..900971b 100644
--- a/packages/SystemUI/customization/src/com/android/systemui/shared/clocks/DefaultClockProvider.kt
+++ b/packages/SystemUI/customization/src/com/android/systemui/shared/clocks/DefaultClockProvider.kt
@@ -17,6 +17,8 @@
 import android.content.res.Resources
 import android.view.LayoutInflater
 import com.android.systemui.customization.R
+import com.android.systemui.log.core.LogLevel
+import com.android.systemui.log.core.LogcatOnlyMessageBuffer
 import com.android.systemui.plugins.clocks.ClockController
 import com.android.systemui.plugins.clocks.ClockId
 import com.android.systemui.plugins.clocks.ClockMessageBuffers
@@ -53,7 +55,9 @@
         }
 
         return if (clockReactiveVariants) {
-            val assets = AssetLoader(ctx, ctx, "clocks/", messageBuffers!!.infraMessageBuffer)
+            val buffer =
+                messageBuffers?.infraMessageBuffer ?: LogcatOnlyMessageBuffer(LogLevel.INFO)
+            val assets = AssetLoader(ctx, ctx, "clocks/", buffer)
             FlexClockController(ctx, resources, assets, FLEX_DESIGN, messageBuffers)
         } else {
             DefaultClockController(
diff --git a/packages/SystemUI/customization/src/com/android/systemui/shared/clocks/FlexClockFaceController.kt b/packages/SystemUI/customization/src/com/android/systemui/shared/clocks/FlexClockFaceController.kt
index ef24d2a..9067fb0 100644
--- a/packages/SystemUI/customization/src/com/android/systemui/shared/clocks/FlexClockFaceController.kt
+++ b/packages/SystemUI/customization/src/com/android/systemui/shared/clocks/FlexClockFaceController.kt
@@ -71,7 +71,7 @@
         val layer = face.layers[0]
 
         layerController =
-            if (isLargeClock)
+            if (isLargeClock) {
                 ComposedDigitalLayerController(
                     ctx,
                     resources,
@@ -79,7 +79,7 @@
                     layer as ComposedDigitalHandLayer,
                     messageBuffer,
                 )
-            else {
+            } else {
                 val childView = SimpleDigitalClockTextView(ctx, messageBuffer)
                 SimpleDigitalHandLayerController(
                     ctx,
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/education/domain/ui/view/ContextualEduDialogTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/education/domain/ui/view/ContextualEduDialogTest.kt
new file mode 100644
index 0000000..90727b2
--- /dev/null
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/education/domain/ui/view/ContextualEduDialogTest.kt
@@ -0,0 +1,72 @@
+/*
+ * Copyright (C) 2024 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.education.domain.ui.view
+
+import android.testing.TestableLooper
+import android.view.accessibility.AccessibilityEvent
+import android.view.accessibility.AccessibilityManager
+import androidx.test.ext.junit.rules.ActivityScenarioRule
+import androidx.test.ext.junit.runners.AndroidJUnit4
+import androidx.test.filters.SmallTest
+import com.android.systemui.SysuiTestCase
+import com.android.systemui.activity.EmptyTestActivity
+import com.android.systemui.education.ui.view.ContextualEduDialog
+import com.android.systemui.education.ui.viewmodel.ContextualEduToastViewModel
+import kotlin.test.assertEquals
+import org.junit.Before
+import org.junit.Rule
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.mockito.ArgumentCaptor
+import org.mockito.Mock
+import org.mockito.junit.MockitoJUnit
+import org.mockito.kotlin.firstValue
+import org.mockito.kotlin.verify
+import org.mockito.kotlin.whenever
+
+@SmallTest
+@RunWith(AndroidJUnit4::class)
+@TestableLooper.RunWithLooper
+class ContextualEduDialogTest : SysuiTestCase() {
+    @Rule
+    @JvmField
+    val activityRule: ActivityScenarioRule<EmptyTestActivity> =
+        ActivityScenarioRule(EmptyTestActivity::class.java)
+    @get:Rule val mockitoRule = MockitoJUnit.rule()
+
+    @Mock private lateinit var accessibilityManager: AccessibilityManager
+    private lateinit var underTest: ContextualEduDialog
+
+    @Before
+    fun setUp() {
+        whenever(accessibilityManager.isEnabled).thenReturn(true)
+    }
+
+    @Test
+    fun sendAccessibilityInfo() {
+        val message = "Testing message"
+        val viewModel = ContextualEduToastViewModel(message, icon = 0, userId = 0)
+        activityRule.scenario.onActivity {
+            underTest = ContextualEduDialog(context, viewModel, accessibilityManager)
+            underTest.show()
+        }
+
+        val eventCaptor = ArgumentCaptor.forClass(AccessibilityEvent::class.java)
+        verify(accessibilityManager).sendAccessibilityEvent(eventCaptor.capture())
+        assertEquals(message, eventCaptor.firstValue.text[0])
+    }
+}
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/domain/interactor/KeyguardInteractorTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/domain/interactor/KeyguardInteractorTest.kt
index 3fb3eea..b3417b9 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/domain/interactor/KeyguardInteractorTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/domain/interactor/KeyguardInteractorTest.kt
@@ -150,6 +150,53 @@
             assertThat(secureCameraActive()).isFalse()
         }
 
+    /** Regression test for b/373700726. */
+    @Test
+    @DisableFlags(FLAG_KEYGUARD_WM_STATE_REFACTOR)
+    fun testSecureCameraStillFalseAfterDeviceUnlocked() =
+        testScope.runTest {
+            val secureCameraActive = collectLastValue(underTest.isSecureCameraActive)
+            runCurrent()
+
+            // Launch camera
+            underTest.onCameraLaunchDetected(StatusBarManager.CAMERA_LAUNCH_SOURCE_POWER_DOUBLE_TAP)
+            assertThat(secureCameraActive()).isTrue()
+
+            // Go back to keyguard
+            repository.setKeyguardShowing(true)
+            repository.setKeyguardOccluded(false)
+            assertThat(secureCameraActive()).isFalse()
+
+            // WHEN device is unlocked (and therefore keyguard is no longer showing)
+            repository.setKeyguardShowing(false)
+
+            // THEN we still show secure camera as *not* active
+            assertThat(secureCameraActive()).isFalse()
+        }
+
+    /** Regression test for b/373700726. */
+    @Test
+    @DisableFlags(FLAG_KEYGUARD_WM_STATE_REFACTOR)
+    fun testSecureCameraStillFalseAfterBouncerDismissed() =
+        testScope.runTest {
+            val secureCameraActive = collectLastValue(underTest.isSecureCameraActive)
+            runCurrent()
+
+            // Launch camera
+            underTest.onCameraLaunchDetected(StatusBarManager.CAMERA_LAUNCH_SOURCE_POWER_DOUBLE_TAP)
+            assertThat(secureCameraActive()).isTrue()
+
+            // Show bouncer
+            bouncerRepository.setPrimaryShow(true)
+            assertThat(secureCameraActive()).isFalse()
+
+            // WHEN device is unlocked (and therefore the bouncer is no longer showing)
+            bouncerRepository.setPrimaryShow(false)
+
+            // THEN we still show secure camera as *not* active
+            assertThat(secureCameraActive()).isFalse()
+        }
+
     @Test
     @DisableFlags(FLAG_KEYGUARD_WM_STATE_REFACTOR)
     fun keyguardVisibilityIsDefinedAsKeyguardShowingButNotOccluded() = runTest {
@@ -182,11 +229,7 @@
             val dismissAlpha by collectLastValue(underTest.dismissAlpha)
             assertThat(dismissAlpha).isEqualTo(1f)
 
-            keyguardTransitionRepository.sendTransitionSteps(
-                from = AOD,
-                to = LOCKSCREEN,
-                testScope,
-            )
+            keyguardTransitionRepository.sendTransitionSteps(from = AOD, to = LOCKSCREEN, testScope)
 
             repository.setStatusBarState(StatusBarState.KEYGUARD)
             // User begins to swipe up
@@ -208,11 +251,7 @@
             assertThat(dismissAlpha[0]).isEqualTo(1f)
             assertThat(dismissAlpha.size).isEqualTo(1)
 
-            keyguardTransitionRepository.sendTransitionSteps(
-                from = AOD,
-                to = LOCKSCREEN,
-                testScope,
-            )
+            keyguardTransitionRepository.sendTransitionSteps(from = AOD, to = LOCKSCREEN, testScope)
 
             // User begins to swipe up
             repository.setStatusBarState(StatusBarState.KEYGUARD)
@@ -328,11 +367,7 @@
 
             shadeRepository.setLegacyShadeExpansion(0f)
 
-            keyguardTransitionRepository.sendTransitionSteps(
-                from = AOD,
-                to = LOCKSCREEN,
-                testScope,
-            )
+            keyguardTransitionRepository.sendTransitionSteps(from = AOD, to = LOCKSCREEN, testScope)
 
             assertThat(keyguardTranslationY).isEqualTo(0f)
         }
@@ -350,11 +385,7 @@
 
             shadeRepository.setLegacyShadeExpansion(1f)
 
-            keyguardTransitionRepository.sendTransitionSteps(
-                from = AOD,
-                to = LOCKSCREEN,
-                testScope,
-            )
+            keyguardTransitionRepository.sendTransitionSteps(from = AOD, to = LOCKSCREEN, testScope)
 
             assertThat(keyguardTranslationY).isEqualTo(0f)
         }
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/panels/data/repository/QSColumnsRepositoryTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/panels/data/repository/QSColumnsRepositoryTest.kt
index fd1f52b..ec0773f 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/panels/data/repository/QSColumnsRepositoryTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/panels/data/repository/QSColumnsRepositoryTest.kt
@@ -16,7 +16,6 @@
 
 package com.android.systemui.qs.panels.data.repository
 
-import android.platform.test.annotations.EnableFlags
 import androidx.test.ext.junit.runners.AndroidJUnit4
 import androidx.test.filters.SmallTest
 import com.android.systemui.SysuiTestCase
@@ -25,7 +24,7 @@
 import com.android.systemui.kosmos.testCase
 import com.android.systemui.kosmos.testScope
 import com.android.systemui.res.R
-import com.android.systemui.shade.shared.flag.DualShade
+import com.android.systemui.shade.data.repository.fakeShadeRepository
 import com.android.systemui.testKosmos
 import com.google.common.truth.Truth.assertThat
 import kotlinx.coroutines.test.runTest
@@ -59,15 +58,22 @@
         }
 
     @Test
-    @EnableFlags(DualShade.FLAG_NAME)
     fun withDualShade_returnsCorrectValue() =
         with(kosmos) {
             testScope.runTest {
-                val latest by collectLastValue(underTest.columns)
-                assertThat(latest).isEqualTo(4)
+                val latest by collectLastValue(underTest.dualShadeColumns)
 
-                setColumnsInConfig(8, id = R.integer.quick_settings_dual_shade_num_columns)
-                // Asserts config changes are ignored
+                assertThat(latest).isEqualTo(4)
+            }
+        }
+
+    @Test
+    fun withSplitShade_returnsCorrectValue() =
+        with(kosmos) {
+            testScope.runTest {
+                val latest by collectLastValue(underTest.splitShadeColumns)
+                fakeShadeRepository.setShadeLayoutWide(true)
+
                 assertThat(latest).isEqualTo(4)
             }
         }
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/panels/domain/interactor/QSColumnsInteractorTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/panels/domain/interactor/QSColumnsInteractorTest.kt
new file mode 100644
index 0000000..35f7504
--- /dev/null
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/panels/domain/interactor/QSColumnsInteractorTest.kt
@@ -0,0 +1,101 @@
+/*
+ * Copyright (C) 2024 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.qs.panels.domain.interactor
+
+import android.content.res.mainResources
+import android.platform.test.annotations.DisableFlags
+import android.platform.test.annotations.EnableFlags
+import androidx.test.ext.junit.runners.AndroidJUnit4
+import androidx.test.filters.SmallTest
+import com.android.systemui.SysuiTestCase
+import com.android.systemui.common.ui.data.repository.configurationRepository
+import com.android.systemui.coroutines.collectLastValue
+import com.android.systemui.kosmos.testCase
+import com.android.systemui.kosmos.testScope
+import com.android.systemui.qs.panels.data.repository.QSColumnsRepository
+import com.android.systemui.qs.panels.data.repository.qsColumnsRepository
+import com.android.systemui.res.R
+import com.android.systemui.shade.data.repository.fakeShadeRepository
+import com.android.systemui.shade.shared.flag.DualShade
+import com.android.systemui.testKosmos
+import com.google.common.truth.Truth.assertThat
+import kotlinx.coroutines.test.runTest
+import org.junit.Before
+import org.junit.Test
+import org.junit.runner.RunWith
+
+@SmallTest
+@RunWith(AndroidJUnit4::class)
+class QSColumnsInteractorTest : SysuiTestCase() {
+    private val kosmos =
+        testKosmos().apply {
+            testCase.context.orCreateTestableResources.addOverride(
+                R.integer.quick_settings_infinite_grid_num_columns,
+                1,
+            )
+            testCase.context.orCreateTestableResources.addOverride(
+                R.integer.quick_settings_dual_shade_num_columns,
+                2,
+            )
+            testCase.context.orCreateTestableResources.addOverride(
+                R.integer.quick_settings_split_shade_num_columns,
+                3,
+            )
+            qsColumnsRepository = QSColumnsRepository(mainResources, configurationRepository)
+        }
+    private lateinit var underTest: QSColumnsInteractor
+
+    @Before
+    fun setUp() {
+        underTest = with(kosmos) { qsColumnsInteractor }
+    }
+
+    @Test
+    @DisableFlags(DualShade.FLAG_NAME)
+    fun withSingleShade_returnsCorrectValue() =
+        with(kosmos) {
+            testScope.runTest {
+                val latest by collectLastValue(underTest.columns)
+
+                assertThat(latest).isEqualTo(1)
+            }
+        }
+
+    @Test
+    @EnableFlags(DualShade.FLAG_NAME)
+    fun withDualShade_returnsCorrectValue() =
+        with(kosmos) {
+            testScope.runTest {
+                val latest by collectLastValue(underTest.columns)
+
+                assertThat(latest).isEqualTo(2)
+            }
+        }
+
+    @Test
+    @DisableFlags(DualShade.FLAG_NAME)
+    fun withSplitShade_returnsCorrectValue() =
+        with(kosmos) {
+            testScope.runTest {
+                val latest by collectLastValue(underTest.columns)
+
+                fakeShadeRepository.setShadeLayoutWide(true)
+
+                assertThat(latest).isEqualTo(3)
+            }
+        }
+}
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/core/StatusBarInitializerTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/core/StatusBarInitializerTest.kt
index c737bf7..e312d00 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/core/StatusBarInitializerTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/core/StatusBarInitializerTest.kt
@@ -20,12 +20,15 @@
 import android.app.FragmentTransaction
 import android.platform.test.annotations.DisableFlags
 import android.platform.test.annotations.EnableFlags
+import android.view.ViewGroup
 import androidx.test.ext.junit.runners.AndroidJUnit4
 import androidx.test.filters.SmallTest
 import com.android.systemui.Flags
 import com.android.systemui.SysuiTestCase
 import com.android.systemui.fragments.FragmentHostManager
 import com.android.systemui.statusbar.phone.fragment.CollapsedStatusBarFragment
+import com.android.systemui.statusbar.phone.fragment.dagger.HomeStatusBarComponent
+import com.android.systemui.statusbar.pipeline.shared.ui.composable.StatusBarRootFactory
 import com.android.systemui.statusbar.window.StatusBarWindowController
 import com.android.systemui.statusbar.window.StatusBarWindowControllerStore
 import com.google.common.truth.Truth.assertThat
@@ -35,6 +38,8 @@
 import org.junit.runner.RunWith
 import org.mockito.Mockito.mock
 import org.mockito.kotlin.any
+import org.mockito.kotlin.never
+import org.mockito.kotlin.verify
 import org.mockito.kotlin.whenever
 
 @SmallTest
@@ -42,27 +47,31 @@
 class StatusBarInitializerTest : SysuiTestCase() {
     private val windowController = mock(StatusBarWindowController::class.java)
     private val windowControllerStore = mock(StatusBarWindowControllerStore::class.java)
+    private val transaction = mock(FragmentTransaction::class.java)
+    private val fragmentManager = mock(FragmentManager::class.java)
+    private val fragmentHostManager = mock(FragmentHostManager::class.java)
+    private val backgroundView = mock(ViewGroup::class.java)
 
     @Before
     fun setup() {
         // TODO(b/364360986) this will go away once the fragment is deprecated. Hence, there is no
         // need right now for moving this to kosmos
-        val transaction = mock(FragmentTransaction::class.java)
-        val fragmentManager = mock(FragmentManager::class.java)
-        val fragmentHostManager = mock(FragmentHostManager::class.java)
         whenever(fragmentHostManager.addTagListener(any(), any())).thenReturn(fragmentHostManager)
         whenever(fragmentHostManager.fragmentManager).thenReturn(fragmentManager)
         whenever(fragmentManager.beginTransaction()).thenReturn(transaction)
         whenever(transaction.replace(any(), any(), any())).thenReturn(transaction)
         whenever(windowControllerStore.defaultDisplay).thenReturn(windowController)
         whenever(windowController.fragmentHostManager).thenReturn(fragmentHostManager)
+        whenever(windowController.backgroundView).thenReturn(backgroundView)
     }
 
     val underTest =
         StatusBarInitializerImpl(
-            collapsedStatusBarFragmentProvider = { mock(CollapsedStatusBarFragment::class.java) },
-            creationListeners = setOf(),
             statusBarWindowController = windowController,
+            collapsedStatusBarFragmentProvider = { mock(CollapsedStatusBarFragment::class.java) },
+            statusBarRootFactory = mock(StatusBarRootFactory::class.java),
+            componentFactory = mock(HomeStatusBarComponent.Factory::class.java),
+            creationListeners = setOf(),
         )
 
     @Test
@@ -79,6 +88,15 @@
     }
 
     @Test
+    @EnableFlags(Flags.FLAG_STATUS_BAR_SIMPLE_FRAGMENT)
+    fun simpleFragment_flagEnabled_doesNotCreateFragment() {
+        underTest.start()
+
+        verify(fragmentManager, never()).beginTransaction()
+        verify(transaction, never()).replace(any(), any(), any())
+    }
+
+    @Test
     @DisableFlags(Flags.FLAG_STATUS_BAR_SIMPLE_FRAGMENT)
     fun flagOff_doesNotInitializeViaCoreStartable() {
         underTest.start()
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/data/repository/StatusBarModeRepositoryImplTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/data/repository/StatusBarModeRepositoryImplTest.kt
index 48ae7a2..feda0c6 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/data/repository/StatusBarModeRepositoryImplTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/data/repository/StatusBarModeRepositoryImplTest.kt
@@ -36,7 +36,7 @@
 import com.android.systemui.statusbar.phone.LetterboxAppearance
 import com.android.systemui.statusbar.phone.LetterboxAppearanceCalculator
 import com.android.systemui.statusbar.phone.StatusBarBoundsProvider
-import com.android.systemui.statusbar.phone.fragment.dagger.StatusBarFragmentComponent
+import com.android.systemui.statusbar.phone.fragment.dagger.HomeStatusBarComponent
 import com.android.systemui.statusbar.phone.ongoingcall.data.repository.ongoingCallRepository
 import com.android.systemui.statusbar.phone.ongoingcall.shared.model.OngoingCallModel
 import com.android.systemui.statusbar.phone.ongoingcall.shared.model.inCallModel
@@ -62,8 +62,8 @@
     private val commandQueue = mock<CommandQueue>()
     private val letterboxAppearanceCalculator = mock<LetterboxAppearanceCalculator>()
     private val statusBarBoundsProvider = mock<StatusBarBoundsProvider>()
-    private val statusBarFragmentComponent =
-        mock<StatusBarFragmentComponent>().also {
+    private val homeStatusBarComponent =
+        mock<HomeStatusBarComponent>().also {
             whenever(it.boundsProvider).thenReturn(statusBarBoundsProvider)
         }
     private val ongoingCallRepository = kosmos.ongoingCallRepository
@@ -78,7 +78,7 @@
             )
             .apply {
                 this.start()
-                this.onStatusBarViewInitialized(statusBarFragmentComponent)
+                this.onStatusBarViewInitialized(homeStatusBarComponent)
             }
 
     private val commandQueueCallback: CommandQueue.Callbacks
@@ -235,9 +235,7 @@
         testScope.runTest {
             val latest by collectLastValue(underTest.isInFullscreenMode)
 
-            onSystemBarAttributesChanged(
-                requestedVisibleTypes = WindowInsets.Type.statusBars(),
-            )
+            onSystemBarAttributesChanged(requestedVisibleTypes = WindowInsets.Type.statusBars())
 
             assertThat(latest).isFalse()
         }
@@ -247,9 +245,7 @@
         testScope.runTest {
             val latest by collectLastValue(underTest.isInFullscreenMode)
 
-            onSystemBarAttributesChanged(
-                requestedVisibleTypes = WindowInsets.Type.navigationBars(),
-            )
+            onSystemBarAttributesChanged(requestedVisibleTypes = WindowInsets.Type.navigationBars())
 
             assertThat(latest).isTrue()
         }
@@ -259,9 +255,7 @@
         testScope.runTest {
             val latest by collectLastValue(underTest.isInFullscreenMode)
 
-            onSystemBarAttributesChanged(
-                requestedVisibleTypes = WindowInsets.Type.navigationBars(),
-            )
+            onSystemBarAttributesChanged(requestedVisibleTypes = WindowInsets.Type.navigationBars())
             assertThat(latest).isTrue()
 
             onSystemBarAttributesChanged(
@@ -347,7 +341,7 @@
             val startingLetterboxAppearance =
                 LetterboxAppearance(
                     APPEARANCE_LIGHT_STATUS_BARS,
-                    listOf(AppearanceRegion(APPEARANCE_LIGHT_STATUS_BARS, Rect(0, 0, 1, 1)))
+                    listOf(AppearanceRegion(APPEARANCE_LIGHT_STATUS_BARS, Rect(0, 0, 1, 1))),
                 )
             whenever(
                     letterboxAppearanceCalculator.getLetterboxAppearance(
@@ -371,7 +365,7 @@
             val newLetterboxAppearance =
                 LetterboxAppearance(
                     APPEARANCE_LOW_PROFILE_BARS,
-                    listOf(AppearanceRegion(APPEARANCE_LOW_PROFILE_BARS, Rect(10, 20, 30, 40)))
+                    listOf(AppearanceRegion(APPEARANCE_LOW_PROFILE_BARS, Rect(10, 20, 30, 40))),
                 )
             whenever(
                     letterboxAppearanceCalculator.getLetterboxAppearance(
@@ -398,9 +392,7 @@
             val latest by collectLastValue(underTest.statusBarAppearance)
 
             ongoingCallRepository.setOngoingCallState(inCallModel(startTimeMs = 34))
-            onSystemBarAttributesChanged(
-                requestedVisibleTypes = WindowInsets.Type.navigationBars(),
-            )
+            onSystemBarAttributesChanged(requestedVisibleTypes = WindowInsets.Type.navigationBars())
 
             assertThat(latest!!.mode).isEqualTo(StatusBarMode.SEMI_TRANSPARENT)
         }
@@ -438,9 +430,7 @@
     fun statusBarMode_transientShown_semiTransparent() =
         testScope.runTest {
             val latest by collectLastValue(underTest.statusBarAppearance)
-            onSystemBarAttributesChanged(
-                appearance = APPEARANCE_OPAQUE_STATUS_BARS,
-            )
+            onSystemBarAttributesChanged(appearance = APPEARANCE_OPAQUE_STATUS_BARS)
 
             underTest.showTransient()
 
@@ -453,7 +443,7 @@
             val latest by collectLastValue(underTest.statusBarAppearance)
 
             onSystemBarAttributesChanged(
-                appearance = APPEARANCE_LOW_PROFILE_BARS or APPEARANCE_OPAQUE_STATUS_BARS,
+                appearance = APPEARANCE_LOW_PROFILE_BARS or APPEARANCE_OPAQUE_STATUS_BARS
             )
 
             assertThat(latest!!.mode).isEqualTo(StatusBarMode.LIGHTS_OUT)
@@ -464,9 +454,7 @@
         testScope.runTest {
             val latest by collectLastValue(underTest.statusBarAppearance)
 
-            onSystemBarAttributesChanged(
-                appearance = APPEARANCE_LOW_PROFILE_BARS,
-            )
+            onSystemBarAttributesChanged(appearance = APPEARANCE_LOW_PROFILE_BARS)
 
             assertThat(latest!!.mode).isEqualTo(StatusBarMode.LIGHTS_OUT_TRANSPARENT)
         }
@@ -476,9 +464,7 @@
         testScope.runTest {
             val latest by collectLastValue(underTest.statusBarAppearance)
 
-            onSystemBarAttributesChanged(
-                appearance = APPEARANCE_OPAQUE_STATUS_BARS,
-            )
+            onSystemBarAttributesChanged(appearance = APPEARANCE_OPAQUE_STATUS_BARS)
 
             assertThat(latest!!.mode).isEqualTo(StatusBarMode.OPAQUE)
         }
@@ -488,9 +474,7 @@
         testScope.runTest {
             val latest by collectLastValue(underTest.statusBarAppearance)
 
-            onSystemBarAttributesChanged(
-                appearance = APPEARANCE_SEMI_TRANSPARENT_STATUS_BARS,
-            )
+            onSystemBarAttributesChanged(appearance = APPEARANCE_SEMI_TRANSPARENT_STATUS_BARS)
 
             assertThat(latest!!.mode).isEqualTo(StatusBarMode.SEMI_TRANSPARENT)
         }
@@ -500,9 +484,7 @@
         testScope.runTest {
             val latest by collectLastValue(underTest.statusBarAppearance)
 
-            onSystemBarAttributesChanged(
-                appearance = 0,
-            )
+            onSystemBarAttributesChanged(appearance = 0)
 
             assertThat(latest!!.mode).isEqualTo(StatusBarMode.TRANSPARENT)
         }
@@ -540,7 +522,7 @@
                 LetterboxDetails(
                     /* letterboxInnerBounds= */ Rect(0, 0, 10, 10),
                     /* letterboxFullBounds= */ Rect(0, 0, 20, 20),
-                    /* appAppearance= */ 0
+                    /* appAppearance= */ 0,
                 )
             )
         private val REGIONS_FROM_LETTERBOX_CALCULATOR =
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/pipeline/shared/ui/viewmodel/FakeCollapsedStatusBarViewBinder.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/pipeline/shared/ui/viewmodel/FakeHomeStatusBarViewBinder.kt
similarity index 84%
rename from packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/pipeline/shared/ui/viewmodel/FakeCollapsedStatusBarViewBinder.kt
rename to packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/pipeline/shared/ui/viewmodel/FakeHomeStatusBarViewBinder.kt
index 2ee928f..cdc7aa2 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/pipeline/shared/ui/viewmodel/FakeCollapsedStatusBarViewBinder.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/pipeline/shared/ui/viewmodel/FakeHomeStatusBarViewBinder.kt
@@ -17,21 +17,21 @@
 package com.android.systemui.statusbar.pipeline.shared.ui.viewmodel
 
 import android.view.View
-import com.android.systemui.statusbar.pipeline.shared.ui.binder.CollapsedStatusBarViewBinder
+import com.android.systemui.statusbar.pipeline.shared.ui.binder.HomeStatusBarViewBinder
 import com.android.systemui.statusbar.pipeline.shared.ui.binder.StatusBarVisibilityChangeListener
 
 /**
  * A fake view binder that can be used from Java tests.
  *
  * Since Java tests can't run tests within test scopes, we need to bypass the flows from
- * [CollapsedStatusBarViewModel] and just trigger the listener directly.
+ * [HomeStatusBarViewModel] and just trigger the listener directly.
  */
-class FakeCollapsedStatusBarViewBinder : CollapsedStatusBarViewBinder {
+class FakeHomeStatusBarViewBinder : HomeStatusBarViewBinder {
     var listener: StatusBarVisibilityChangeListener? = null
 
     override fun bind(
         view: View,
-        viewModel: CollapsedStatusBarViewModel,
+        viewModel: HomeStatusBarViewModel,
         listener: StatusBarVisibilityChangeListener,
     ) {
         this.listener = listener
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/pipeline/shared/ui/viewmodel/FakeCollapsedStatusBarViewModel.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/pipeline/shared/ui/viewmodel/FakeHomeStatusBarViewModel.kt
similarity index 90%
rename from packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/pipeline/shared/ui/viewmodel/FakeCollapsedStatusBarViewModel.kt
rename to packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/pipeline/shared/ui/viewmodel/FakeHomeStatusBarViewModel.kt
index cc90c11..02c1540 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/pipeline/shared/ui/viewmodel/FakeCollapsedStatusBarViewModel.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/pipeline/shared/ui/viewmodel/FakeHomeStatusBarViewModel.kt
@@ -23,7 +23,7 @@
 import kotlinx.coroutines.flow.MutableSharedFlow
 import kotlinx.coroutines.flow.MutableStateFlow
 
-class FakeCollapsedStatusBarViewModel : CollapsedStatusBarViewModel {
+class FakeHomeStatusBarViewModel : HomeStatusBarViewModel {
     private val areNotificationLightsOut = MutableStateFlow(false)
 
     override val isTransitioningFromLockscreenToOccluded = MutableStateFlow(false)
@@ -39,7 +39,7 @@
 
     override val isClockVisible =
         MutableStateFlow(
-            CollapsedStatusBarViewModel.VisibilityModel(
+            HomeStatusBarViewModel.VisibilityModel(
                 visibility = View.GONE,
                 shouldAnimateChange = false,
             )
@@ -47,7 +47,7 @@
 
     override val isNotificationIconContainerVisible =
         MutableStateFlow(
-            CollapsedStatusBarViewModel.VisibilityModel(
+            HomeStatusBarViewModel.VisibilityModel(
                 visibility = View.GONE,
                 shouldAnimateChange = false,
             )
@@ -55,7 +55,7 @@
 
     override val isSystemInfoVisible =
         MutableStateFlow(
-            CollapsedStatusBarViewModel.VisibilityModel(
+            HomeStatusBarViewModel.VisibilityModel(
                 visibility = View.GONE,
                 shouldAnimateChange = false,
             )
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/pipeline/shared/ui/viewmodel/CollapsedStatusBarViewModelImplTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/pipeline/shared/ui/viewmodel/HomeStatusBarViewModelImplTest.kt
similarity index 93%
rename from packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/pipeline/shared/ui/viewmodel/CollapsedStatusBarViewModelImplTest.kt
rename to packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/pipeline/shared/ui/viewmodel/HomeStatusBarViewModelImplTest.kt
index bd85780..b3a73d8 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/pipeline/shared/ui/viewmodel/CollapsedStatusBarViewModelImplTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/pipeline/shared/ui/viewmodel/HomeStatusBarViewModelImplTest.kt
@@ -16,6 +16,7 @@
 
 package com.android.systemui.statusbar.pipeline.shared.ui.viewmodel
 
+import android.app.StatusBarManager.CAMERA_LAUNCH_SOURCE_POWER_DOUBLE_TAP
 import android.app.StatusBarManager.DISABLE2_NONE
 import android.app.StatusBarManager.DISABLE_CLOCK
 import android.app.StatusBarManager.DISABLE_NONE
@@ -33,6 +34,7 @@
 import com.android.systemui.flags.EnableSceneContainer
 import com.android.systemui.keyguard.data.repository.fakeKeyguardTransitionRepository
 import com.android.systemui.keyguard.data.repository.keyguardOcclusionRepository
+import com.android.systemui.keyguard.domain.interactor.keyguardInteractor
 import com.android.systemui.keyguard.shared.model.KeyguardState
 import com.android.systemui.keyguard.shared.model.TransitionState
 import com.android.systemui.keyguard.shared.model.TransitionStep
@@ -75,7 +77,7 @@
 @SmallTest
 @OptIn(ExperimentalCoroutinesApi::class)
 @RunWith(AndroidJUnit4::class)
-class CollapsedStatusBarViewModelImplTest : SysuiTestCase() {
+class HomeStatusBarViewModelImplTest : SysuiTestCase() {
     private val kosmos =
         Kosmos().also {
             it.testCase = this
@@ -89,13 +91,13 @@
     private val keyguardTransitionRepository = kosmos.fakeKeyguardTransitionRepository
     private val disableFlagsRepository = kosmos.fakeDisableFlagsRepository
 
-    private lateinit var underTest: CollapsedStatusBarViewModel
+    private lateinit var underTest: HomeStatusBarViewModel
 
     @Before
     fun setUp() {
         setUpPackageManagerForMediaProjection(kosmos)
         // Initialize here because some flags are checked when this class is constructed
-        underTest = kosmos.collapsedStatusBarViewModel
+        underTest = kosmos.homeStatusBarViewModel
     }
 
     @Test
@@ -746,6 +748,45 @@
             assertThat(systemInfoVisible!!.visibility).isEqualTo(View.GONE)
         }
 
+    @Test
+    @DisableSceneContainer
+    fun secureCameraActive_sceneFlagOff_noStatusBarViewsShown() =
+        testScope.runTest {
+            val clockVisible by collectLastValue(underTest.isClockVisible)
+            val notifIconsVisible by collectLastValue(underTest.isNotificationIconContainerVisible)
+            val systemInfoVisible by collectLastValue(underTest.isSystemInfoVisible)
+
+            // Secure camera is an occluding activity
+            keyguardTransitionRepository.sendTransitionSteps(
+                from = KeyguardState.LOCKSCREEN,
+                to = KeyguardState.OCCLUDED,
+                testScope = this,
+            )
+            kosmos.keyguardInteractor.onCameraLaunchDetected(CAMERA_LAUNCH_SOURCE_POWER_DOUBLE_TAP)
+
+            assertThat(clockVisible!!.visibility).isEqualTo(View.GONE)
+            assertThat(notifIconsVisible!!.visibility).isEqualTo(View.GONE)
+            assertThat(systemInfoVisible!!.visibility).isEqualTo(View.GONE)
+        }
+
+    @Test
+    @EnableSceneContainer
+    fun secureCameraActive_sceneFlagOn_noStatusBarViewsShown() =
+        testScope.runTest {
+            val clockVisible by collectLastValue(underTest.isClockVisible)
+            val notifIconsVisible by collectLastValue(underTest.isNotificationIconContainerVisible)
+            val systemInfoVisible by collectLastValue(underTest.isSystemInfoVisible)
+
+            kosmos.sceneContainerRepository.snapToScene(Scenes.Lockscreen)
+            // Secure camera is an occluding activity
+            kosmos.keyguardOcclusionRepository.setShowWhenLockedActivityInfo(true, taskInfo = null)
+            kosmos.keyguardInteractor.onCameraLaunchDetected(CAMERA_LAUNCH_SOURCE_POWER_DOUBLE_TAP)
+
+            assertThat(clockVisible!!.visibility).isEqualTo(View.GONE)
+            assertThat(notifIconsVisible!!.visibility).isEqualTo(View.GONE)
+            assertThat(systemInfoVisible!!.visibility).isEqualTo(View.GONE)
+        }
+
     private fun activeNotificationsStore(notifications: List<ActiveNotificationModel>) =
         ActiveNotificationsStore.Builder()
             .apply { notifications.forEach(::addIndividualNotif) }
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/policy/ZenModesCleanupStartableTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/policy/ZenModesCleanupStartableTest.kt
index 4a53a7a..fd89581 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/policy/ZenModesCleanupStartableTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/policy/ZenModesCleanupStartableTest.kt
@@ -19,6 +19,7 @@
 import android.app.AutomaticZenRule
 import android.app.NotificationManager
 import android.net.Uri
+import android.platform.test.annotations.EnableFlags
 import androidx.test.ext.junit.runners.AndroidJUnit4
 import androidx.test.filters.SmallTest
 import com.android.systemui.SysuiTestCase
@@ -42,6 +43,7 @@
 @OptIn(ExperimentalCoroutinesApi::class)
 @RunWith(AndroidJUnit4::class)
 @SmallTest
+@EnableFlags(android.app.Flags.FLAG_MODES_UI)
 class ZenModesCleanupStartableTest : SysuiTestCase() {
 
     private val kosmos = testKosmos()
diff --git a/packages/SystemUI/res/values/config.xml b/packages/SystemUI/res/values/config.xml
index 7d840cf..f96a0b9 100644
--- a/packages/SystemUI/res/values/config.xml
+++ b/packages/SystemUI/res/values/config.xml
@@ -82,6 +82,9 @@
     <!-- The number of columns in the Dual Shade QuickSettings -->
     <integer name="quick_settings_dual_shade_num_columns">4</integer>
 
+    <!-- The number of columns in the Split Shade QuickSettings -->
+    <integer name="quick_settings_split_shade_num_columns">4</integer>
+
     <!-- Override column number for quick settings.
     For now, this value has effect only when flag lockscreen.enable_landscape is enabled.
     TODO (b/293252410) - change this comment/resource when flag is enabled -->
diff --git a/packages/SystemUI/src/com/android/systemui/education/ui/view/ContextualEduDialog.kt b/packages/SystemUI/src/com/android/systemui/education/ui/view/ContextualEduDialog.kt
index ca92953..1439ecd 100644
--- a/packages/SystemUI/src/com/android/systemui/education/ui/view/ContextualEduDialog.kt
+++ b/packages/SystemUI/src/com/android/systemui/education/ui/view/ContextualEduDialog.kt
@@ -22,13 +22,18 @@
 import android.view.Gravity
 import android.view.Window
 import android.view.WindowManager
+import android.view.accessibility.AccessibilityEvent
+import android.view.accessibility.AccessibilityManager
 import android.widget.ImageView
 import android.widget.TextView
 import com.android.systemui.education.ui.viewmodel.ContextualEduToastViewModel
 import com.android.systemui.res.R
 
-class ContextualEduDialog(context: Context, private val model: ContextualEduToastViewModel) :
-    Dialog(context) {
+class ContextualEduDialog(
+    context: Context,
+    private val model: ContextualEduToastViewModel,
+    private val accessibilityManager: AccessibilityManager,
+) : Dialog(context) {
     override fun onCreate(savedInstanceState: Bundle?) {
         setUpWindowProperties()
         setWindowPosition()
@@ -36,6 +41,7 @@
         window?.setTitle(context.getString(R.string.contextual_education_dialog_title))
         setContentView(R.layout.contextual_edu_dialog)
         setContent()
+        sendAccessibilityEvent()
         super.onCreate(savedInstanceState)
     }
 
@@ -44,10 +50,30 @@
         findViewById<ImageView>(R.id.edu_icon)?.let { it.setImageResource(model.icon) }
     }
 
+    private fun sendAccessibilityEvent() {
+        if (!accessibilityManager.isEnabled) {
+            return
+        }
+
+        // It is a toast-like dialog which is unobtrusive and not focusable. So it needs to call
+        // accessibilityManager.sendAccessibilityEvent explicitly to announce the message.
+        accessibilityManager.sendAccessibilityEvent(
+            AccessibilityEvent(AccessibilityEvent.TYPE_ANNOUNCEMENT).apply {
+                text.add(model.message)
+            }
+        )
+    }
+
     private fun setUpWindowProperties() {
         window?.apply {
             requestFeature(Window.FEATURE_NO_TITLE)
             setType(WindowManager.LayoutParams.TYPE_SYSTEM_DIALOG)
+            // NOT_TOUCH_MODAL allows users to interact with background elements and NOT_FOCUSABLE
+            // avoids changing the existing focus when dialog is shown.
+            addFlags(
+                WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL or
+                    WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE
+            )
             clearFlags(WindowManager.LayoutParams.FLAG_DIM_BEHIND)
             setBackgroundDrawableResource(android.R.color.transparent)
         }
diff --git a/packages/SystemUI/src/com/android/systemui/education/ui/view/ContextualEduUiCoordinator.kt b/packages/SystemUI/src/com/android/systemui/education/ui/view/ContextualEduUiCoordinator.kt
index 913ecdd..1996efa 100644
--- a/packages/SystemUI/src/com/android/systemui/education/ui/view/ContextualEduUiCoordinator.kt
+++ b/packages/SystemUI/src/com/android/systemui/education/ui/view/ContextualEduUiCoordinator.kt
@@ -25,6 +25,7 @@
 import android.content.Intent
 import android.os.Bundle
 import android.os.UserHandle
+import android.view.accessibility.AccessibilityManager
 import androidx.core.app.NotificationCompat
 import com.android.systemui.CoreStartable
 import com.android.systemui.dagger.SysUISingleton
@@ -64,12 +65,13 @@
         context: Context,
         viewModel: ContextualEduViewModel,
         notificationManager: NotificationManager,
+        accessibilityManager: AccessibilityManager,
     ) : this(
         applicationScope,
         viewModel,
         context,
         notificationManager,
-        createDialog = { model -> ContextualEduDialog(context, model) },
+        createDialog = { model -> ContextualEduDialog(context, model, accessibilityManager) },
     )
 
     var dialog: Dialog? = null
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/KeyguardInteractor.kt b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/KeyguardInteractor.kt
index d7f96b5..6ecbc61 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/KeyguardInteractor.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/KeyguardInteractor.kt
@@ -297,20 +297,39 @@
     val isKeyguardVisible: Flow<Boolean> =
         combine(isKeyguardShowing, isKeyguardOccluded) { showing, occluded -> showing && !occluded }
 
+    /**
+     * Event types that affect whether secure camera is active. Only used by [isSecureCameraActive].
+     */
+    private enum class SecureCameraRelatedEventType {
+        KeyguardBecameVisible,
+        PrimaryBouncerBecameVisible,
+        SecureCameraLaunched,
+    }
+
     /** Whether camera is launched over keyguard. */
-    val isSecureCameraActive: Flow<Boolean> by lazy {
-        combine(isKeyguardVisible, primaryBouncerShowing, onCameraLaunchDetected) {
-                isKeyguardVisible,
-                isPrimaryBouncerShowing,
-                cameraLaunchEvent ->
-                when {
-                    isKeyguardVisible -> false
-                    isPrimaryBouncerShowing -> false
-                    else -> cameraLaunchEvent.type == CameraLaunchType.POWER_DOUBLE_TAP
+    val isSecureCameraActive: Flow<Boolean> =
+        merge(
+                onCameraLaunchDetected
+                    .filter { it.type == CameraLaunchType.POWER_DOUBLE_TAP }
+                    .map { SecureCameraRelatedEventType.SecureCameraLaunched },
+                isKeyguardVisible
+                    .filter { it }
+                    .map { SecureCameraRelatedEventType.KeyguardBecameVisible },
+                primaryBouncerShowing
+                    .filter { it }
+                    .map { SecureCameraRelatedEventType.PrimaryBouncerBecameVisible },
+            )
+            .map {
+                when (it) {
+                    SecureCameraRelatedEventType.SecureCameraLaunched -> true
+                    // When secure camera is closed, either the keyguard or the primary bouncer will
+                    // have to show, so those events tell us that secure camera is no longer active.
+                    SecureCameraRelatedEventType.KeyguardBecameVisible -> false
+                    SecureCameraRelatedEventType.PrimaryBouncerBecameVisible -> false
                 }
             }
             .onStart { emit(false) }
-    }
+            .distinctUntilChanged()
 
     /** The approximate location on the screen of the fingerprint sensor, if one is available. */
     val fingerprintSensorLocation: Flow<Point?> = repository.fingerprintSensorLocation
diff --git a/packages/SystemUI/src/com/android/systemui/qs/panels/data/repository/QSColumnsRepository.kt b/packages/SystemUI/src/com/android/systemui/qs/panels/data/repository/QSColumnsRepository.kt
index 082f622..a9205c2 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/panels/data/repository/QSColumnsRepository.kt
+++ b/packages/SystemUI/src/com/android/systemui/qs/panels/data/repository/QSColumnsRepository.kt
@@ -19,40 +19,31 @@
 import android.content.res.Resources
 import com.android.systemui.common.ui.data.repository.ConfigurationRepository
 import com.android.systemui.dagger.SysUISingleton
-import com.android.systemui.dagger.qualifiers.Application
 import com.android.systemui.dagger.qualifiers.Main
 import com.android.systemui.res.R
-import com.android.systemui.shade.shared.flag.DualShade
 import com.android.systemui.util.kotlin.emitOnStart
 import javax.inject.Inject
-import kotlinx.coroutines.CoroutineScope
 import kotlinx.coroutines.ExperimentalCoroutinesApi
-import kotlinx.coroutines.flow.SharingStarted
-import kotlinx.coroutines.flow.StateFlow
+import kotlinx.coroutines.flow.Flow
 import kotlinx.coroutines.flow.flowOf
 import kotlinx.coroutines.flow.mapLatest
-import kotlinx.coroutines.flow.stateIn
 
 @OptIn(ExperimentalCoroutinesApi::class)
 @SysUISingleton
 class QSColumnsRepository
 @Inject
 constructor(
-    @Application scope: CoroutineScope,
     @Main private val resources: Resources,
     configurationRepository: ConfigurationRepository,
 ) {
-    val columns: StateFlow<Int> =
-        if (DualShade.isEnabled) {
-                flowOf(resources.getInteger(R.integer.quick_settings_dual_shade_num_columns))
-            } else {
-                configurationRepository.onConfigurationChange.emitOnStart().mapLatest {
-                    resources.getInteger(R.integer.quick_settings_infinite_grid_num_columns)
-                }
-            }
-            .stateIn(
-                scope,
-                SharingStarted.WhileSubscribed(),
-                resources.getInteger(R.integer.quick_settings_infinite_grid_num_columns),
-            )
+    val splitShadeColumns: Flow<Int> =
+        flowOf(resources.getInteger(R.integer.quick_settings_split_shade_num_columns))
+    val dualShadeColumns: Flow<Int> =
+        flowOf(resources.getInteger(R.integer.quick_settings_dual_shade_num_columns))
+    val columns: Flow<Int> =
+        configurationRepository.onConfigurationChange.emitOnStart().mapLatest {
+            resources.getInteger(R.integer.quick_settings_infinite_grid_num_columns)
+        }
+    val defaultColumns: Int =
+        resources.getInteger(R.integer.quick_settings_infinite_grid_num_columns)
 }
diff --git a/packages/SystemUI/src/com/android/systemui/qs/panels/domain/interactor/QSColumnsInteractor.kt b/packages/SystemUI/src/com/android/systemui/qs/panels/domain/interactor/QSColumnsInteractor.kt
index 9b45c56..11ea60e 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/panels/domain/interactor/QSColumnsInteractor.kt
+++ b/packages/SystemUI/src/com/android/systemui/qs/panels/domain/interactor/QSColumnsInteractor.kt
@@ -17,11 +17,35 @@
 package com.android.systemui.qs.panels.domain.interactor
 
 import com.android.systemui.dagger.SysUISingleton
+import com.android.systemui.dagger.qualifiers.Application
 import com.android.systemui.qs.panels.data.repository.QSColumnsRepository
+import com.android.systemui.shade.domain.interactor.ShadeInteractor
+import com.android.systemui.shade.shared.model.ShadeMode
 import javax.inject.Inject
+import kotlinx.coroutines.CoroutineScope
+import kotlinx.coroutines.ExperimentalCoroutinesApi
+import kotlinx.coroutines.flow.SharingStarted
 import kotlinx.coroutines.flow.StateFlow
+import kotlinx.coroutines.flow.flatMapLatest
+import kotlinx.coroutines.flow.stateIn
 
 @SysUISingleton
-class QSColumnsInteractor @Inject constructor(repo: QSColumnsRepository) {
-    val columns: StateFlow<Int> = repo.columns
+class QSColumnsInteractor
+@Inject
+constructor(
+    @Application scope: CoroutineScope,
+    repo: QSColumnsRepository,
+    shadeInteractor: ShadeInteractor,
+) {
+    @OptIn(ExperimentalCoroutinesApi::class)
+    val columns: StateFlow<Int> =
+        shadeInteractor.shadeMode
+            .flatMapLatest {
+                when (it) {
+                    ShadeMode.Dual -> repo.dualShadeColumns
+                    ShadeMode.Split -> repo.splitShadeColumns
+                    ShadeMode.Single -> repo.columns
+                }
+            }
+            .stateIn(scope, SharingStarted.WhileSubscribed(), repo.defaultColumns)
 }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/core/StatusBarInitializer.kt b/packages/SystemUI/src/com/android/systemui/statusbar/core/StatusBarInitializer.kt
index 2c94632..6201ca5 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/core/StatusBarInitializer.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/core/StatusBarInitializer.kt
@@ -16,6 +16,7 @@
 package com.android.systemui.statusbar.core
 
 import android.app.Fragment
+import android.view.ViewGroup
 import androidx.annotation.VisibleForTesting
 import com.android.systemui.CoreStartable
 import com.android.systemui.fragments.FragmentHostManager
@@ -23,9 +24,11 @@
 import com.android.systemui.statusbar.core.StatusBarInitializer.OnStatusBarViewInitializedListener
 import com.android.systemui.statusbar.core.StatusBarInitializer.OnStatusBarViewUpdatedListener
 import com.android.systemui.statusbar.phone.PhoneStatusBarTransitions
+import com.android.systemui.statusbar.phone.PhoneStatusBarView
 import com.android.systemui.statusbar.phone.PhoneStatusBarViewController
 import com.android.systemui.statusbar.phone.fragment.CollapsedStatusBarFragment
-import com.android.systemui.statusbar.phone.fragment.dagger.StatusBarFragmentComponent
+import com.android.systemui.statusbar.phone.fragment.dagger.HomeStatusBarComponent
+import com.android.systemui.statusbar.pipeline.shared.ui.composable.StatusBarRootFactory
 import com.android.systemui.statusbar.window.StatusBarWindowController
 import dagger.assisted.Assisted
 import dagger.assisted.AssistedFactory
@@ -57,7 +60,7 @@
          *   Can be used to retrieve dependencies from that scope, including the status bar root
          *   view.
          */
-        fun onStatusBarViewInitialized(component: StatusBarFragmentComponent)
+        fun onStatusBarViewInitialized(component: HomeStatusBarComponent)
     }
 
     interface OnStatusBarViewUpdatedListener {
@@ -77,9 +80,11 @@
 constructor(
     @Assisted private val statusBarWindowController: StatusBarWindowController,
     private val collapsedStatusBarFragmentProvider: Provider<CollapsedStatusBarFragment>,
+    private val statusBarRootFactory: StatusBarRootFactory,
+    private val componentFactory: HomeStatusBarComponent.Factory,
     private val creationListeners: Set<@JvmSuppressWildcards OnStatusBarViewInitializedListener>,
 ) : StatusBarInitializer {
-    private var component: StatusBarFragmentComponent? = null
+    private var component: HomeStatusBarComponent? = null
 
     @get:VisibleForTesting
     var initialized = false
@@ -109,21 +114,57 @@
     }
 
     private fun doStart() {
+        if (StatusBarSimpleFragment.isEnabled) doComposeStart() else doLegacyStart()
+    }
+
+    /**
+     * Stand up the [PhoneStatusBarView] in a compose root. There will be no
+     * [CollapsedStatusBarFragment] in this mode
+     */
+    private fun doComposeStart() {
+        initialized = true
+        val statusBarRoot =
+            statusBarRootFactory.create(statusBarWindowController.backgroundView as ViewGroup) { cv
+                ->
+                val phoneStatusBarView = cv.findViewById<PhoneStatusBarView>(R.id.status_bar)
+                component =
+                    componentFactory.create(phoneStatusBarView).also { component ->
+                        // CollapsedStatusBarFragment used to be responsible initializting
+                        component.init()
+
+                        statusBarViewUpdatedListener?.onStatusBarViewUpdated(
+                            component.phoneStatusBarViewController,
+                            component.phoneStatusBarTransitions,
+                        )
+
+                        creationListeners.forEach { listener ->
+                            listener.onStatusBarViewInitialized(component)
+                        }
+                    }
+            }
+
+        // Add the new compose view to the hierarchy because we don't use fragment transactions
+        // anymore
+        val windowBackgroundView = statusBarWindowController.backgroundView as ViewGroup
+        windowBackgroundView.addView(statusBarRoot)
+    }
+
+    private fun doLegacyStart() {
         initialized = true
         statusBarWindowController.fragmentHostManager
             .addTagListener(
                 CollapsedStatusBarFragment.TAG,
                 object : FragmentHostManager.FragmentListener {
                     override fun onFragmentViewCreated(tag: String, fragment: Fragment) {
-                        val statusBarFragmentComponent =
-                            (fragment as CollapsedStatusBarFragment).statusBarFragmentComponent
+                        component =
+                            (fragment as CollapsedStatusBarFragment).homeStatusBarComponent
                                 ?: throw IllegalStateException()
                         statusBarViewUpdatedListener?.onStatusBarViewUpdated(
-                            statusBarFragmentComponent.phoneStatusBarViewController,
-                            statusBarFragmentComponent.phoneStatusBarTransitions,
+                            component!!.phoneStatusBarViewController,
+                            component!!.phoneStatusBarTransitions,
                         )
                         creationListeners.forEach { listener ->
-                            listener.onStatusBarViewInitialized(statusBarFragmentComponent)
+                            listener.onStatusBarViewInitialized(component!!)
                         }
                     }
 
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/core/StatusBarOrchestrator.kt b/packages/SystemUI/src/com/android/systemui/statusbar/core/StatusBarOrchestrator.kt
index 47e6c57..5e59745 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/core/StatusBarOrchestrator.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/core/StatusBarOrchestrator.kt
@@ -169,11 +169,11 @@
     }
 
     private fun createAndAddWindow() {
-        initializeStatusBarFragment()
+        initializeStatusBarRootView()
         statusBarWindowController.attach()
     }
 
-    private fun initializeStatusBarFragment() {
+    private fun initializeStatusBarRootView() {
         statusBarInitializer.statusBarViewUpdatedListener =
             object : StatusBarInitializer.OnStatusBarViewUpdatedListener {
                 override fun onStatusBarViewUpdated(
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/data/repository/StatusBarModePerDisplayRepository.kt b/packages/SystemUI/src/com/android/systemui/statusbar/data/repository/StatusBarModePerDisplayRepository.kt
index 088c86d..44bee1d 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/data/repository/StatusBarModePerDisplayRepository.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/data/repository/StatusBarModePerDisplayRepository.kt
@@ -36,7 +36,7 @@
 import com.android.systemui.statusbar.phone.BoundsPair
 import com.android.systemui.statusbar.phone.LetterboxAppearanceCalculator
 import com.android.systemui.statusbar.phone.StatusBarBoundsProvider
-import com.android.systemui.statusbar.phone.fragment.dagger.StatusBarFragmentComponent
+import com.android.systemui.statusbar.phone.fragment.dagger.HomeStatusBarComponent
 import com.android.systemui.statusbar.phone.ongoingcall.data.repository.OngoingCallRepository
 import com.android.systemui.statusbar.phone.ongoingcall.shared.model.OngoingCallModel
 import dagger.assisted.Assisted
@@ -174,7 +174,7 @@
 
     private val _statusBarBounds = MutableStateFlow(BoundsPair(Rect(), Rect()))
 
-    override fun onStatusBarViewInitialized(component: StatusBarFragmentComponent) {
+    override fun onStatusBarViewInitialized(component: HomeStatusBarComponent) {
         val statusBarBoundsProvider = component.boundsProvider
         val listener =
             object : StatusBarBoundsProvider.BoundsChangeListener {
@@ -196,10 +196,9 @@
 
     /** Modifies the raw [StatusBarAttributes] if letterboxing is needed. */
     private val modifiedStatusBarAttributes: StateFlow<ModifiedStatusBarAttributes?> =
-        combine(
-                _originalStatusBarAttributes,
-                _statusBarBounds,
-            ) { originalAttributes, statusBarBounds ->
+        combine(_originalStatusBarAttributes, _statusBarBounds) {
+                originalAttributes,
+                statusBarBounds ->
                 if (originalAttributes == null) {
                     null
                 } else {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/data/repository/StatusBarModeRepositoryStore.kt b/packages/SystemUI/src/com/android/systemui/statusbar/data/repository/StatusBarModeRepositoryStore.kt
index 154be1f..2c9fa25 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/data/repository/StatusBarModeRepositoryStore.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/data/repository/StatusBarModeRepositoryStore.kt
@@ -20,7 +20,7 @@
 import com.android.systemui.dagger.SysUISingleton
 import com.android.systemui.dagger.qualifiers.DisplayId
 import com.android.systemui.statusbar.core.StatusBarInitializer
-import com.android.systemui.statusbar.phone.fragment.dagger.StatusBarFragmentComponent
+import com.android.systemui.statusbar.phone.fragment.dagger.HomeStatusBarComponent
 import dagger.Binds
 import dagger.Module
 import dagger.multibindings.ClassKey
@@ -56,7 +56,7 @@
         defaultDisplay.start()
     }
 
-    override fun onStatusBarViewInitialized(component: StatusBarFragmentComponent) {
+    override fun onStatusBarViewInitialized(component: HomeStatusBarComponent) {
         defaultDisplay.onStatusBarViewInitialized(component)
     }
 
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/HeadsUpAppearanceController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/HeadsUpAppearanceController.java
index 8f94c06..d0f4b6f 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/HeadsUpAppearanceController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/HeadsUpAppearanceController.java
@@ -16,7 +16,7 @@
 
 package com.android.systemui.statusbar.phone;
 
-import static com.android.systemui.statusbar.phone.fragment.dagger.StatusBarFragmentModule.OPERATOR_NAME_FRAME_VIEW;
+import static com.android.systemui.statusbar.phone.fragment.dagger.HomeStatusBarModule.OPERATOR_NAME_FRAME_VIEW;
 
 import android.graphics.Rect;
 import android.util.MathUtils;
@@ -44,7 +44,7 @@
 import com.android.systemui.statusbar.notification.row.shared.AsyncGroupHeaderViewInflation;
 import com.android.systemui.statusbar.notification.stack.NotificationRoundnessManager;
 import com.android.systemui.statusbar.notification.stack.NotificationStackScrollLayoutController;
-import com.android.systemui.statusbar.phone.fragment.dagger.StatusBarFragmentScope;
+import com.android.systemui.statusbar.phone.fragment.dagger.HomeStatusBarScope;
 import com.android.systemui.statusbar.policy.Clock;
 import com.android.systemui.statusbar.policy.HeadsUpManager;
 import com.android.systemui.statusbar.policy.KeyguardStateController;
@@ -63,7 +63,7 @@
  * Controls the appearance of heads up notifications in the icon area and the header itself.
  * It also controls the roundness of the heads up notifications and the pulsing notifications.
  */
-@StatusBarFragmentScope
+@HomeStatusBarScope
 public class HeadsUpAppearanceController extends ViewController<HeadsUpStatusBarView>
         implements OnHeadsUpChangedListener,
         DarkIconDispatcher.DarkReceiver,
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/LegacyLightsOutNotifController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/LegacyLightsOutNotifController.java
index 7c871e1..5acc3a6 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/LegacyLightsOutNotifController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/LegacyLightsOutNotifController.java
@@ -18,7 +18,7 @@
 
 import static android.view.WindowInsetsController.APPEARANCE_LOW_PROFILE_BARS;
 
-import static com.android.systemui.statusbar.phone.fragment.dagger.StatusBarFragmentModule.LIGHTS_OUT_NOTIF_VIEW;
+import static com.android.systemui.statusbar.phone.fragment.dagger.HomeStatusBarModule.LIGHTS_OUT_NOTIF_VIEW;
 
 import android.animation.Animator;
 import android.animation.AnimatorListenerAdapter;
@@ -37,7 +37,7 @@
 import com.android.systemui.statusbar.CommandQueue;
 import com.android.systemui.statusbar.notification.collection.NotifLiveDataStore;
 import com.android.systemui.statusbar.notification.shared.NotificationsLiveDataStoreRefactor;
-import com.android.systemui.statusbar.phone.fragment.dagger.StatusBarFragmentScope;
+import com.android.systemui.statusbar.phone.fragment.dagger.HomeStatusBarScope;
 import com.android.systemui.util.ViewController;
 
 import javax.inject.Inject;
@@ -51,7 +51,7 @@
  * This controller shows and hides the notification dot in the status bar to indicate
  * whether there are notifications when the device is in {@link View#SYSTEM_UI_FLAG_LOW_PROFILE}.
  */
-@StatusBarFragmentScope
+@HomeStatusBarScope
 public class LegacyLightsOutNotifController extends ViewController<View> {
     private final CommandQueue mCommandQueue;
     private final NotifLiveDataStore mNotifDataStore;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarBoundsProvider.kt b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarBoundsProvider.kt
index 00b08f0..3ac0bac 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarBoundsProvider.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarBoundsProvider.kt
@@ -18,10 +18,10 @@
 
 import android.graphics.Rect
 import android.view.View
-import com.android.systemui.statusbar.phone.fragment.dagger.StatusBarFragmentComponent
-import com.android.systemui.statusbar.phone.fragment.dagger.StatusBarFragmentModule.END_SIDE_CONTENT
-import com.android.systemui.statusbar.phone.fragment.dagger.StatusBarFragmentModule.START_SIDE_CONTENT
-import com.android.systemui.statusbar.phone.fragment.dagger.StatusBarFragmentScope
+import com.android.systemui.statusbar.phone.fragment.dagger.HomeStatusBarComponent
+import com.android.systemui.statusbar.phone.fragment.dagger.HomeStatusBarModule.END_SIDE_CONTENT
+import com.android.systemui.statusbar.phone.fragment.dagger.HomeStatusBarModule.START_SIDE_CONTENT
+import com.android.systemui.statusbar.phone.fragment.dagger.HomeStatusBarScope
 import com.android.systemui.util.ListenerSet
 import com.android.systemui.util.boundsOnScreen
 import javax.inject.Inject
@@ -33,13 +33,13 @@
  * This is distinct from [StatusBarContentInsetsProvider], which provides the bounds of full status
  * bar after accounting for system insets.
  */
-@StatusBarFragmentScope
+@HomeStatusBarScope
 class StatusBarBoundsProvider
 @Inject
 constructor(
     @Named(START_SIDE_CONTENT) private val startSideContent: View,
     @Named(END_SIDE_CONTENT) private val endSideContent: View,
-) : StatusBarFragmentComponent.Startable {
+) : HomeStatusBarComponent.Startable {
 
     interface BoundsChangeListener {
         fun onStatusBarBoundsChanged(bounds: BoundsPair)
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarDemoMode.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarDemoMode.java
index 25b8bfe0..1afe416 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarDemoMode.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarDemoMode.java
@@ -21,7 +21,7 @@
 import static com.android.systemui.shared.statusbar.phone.BarTransitions.MODE_TRANSLUCENT;
 import static com.android.systemui.shared.statusbar.phone.BarTransitions.MODE_TRANSPARENT;
 import static com.android.systemui.shared.statusbar.phone.BarTransitions.MODE_WARNING;
-import static com.android.systemui.statusbar.phone.fragment.dagger.StatusBarFragmentModule.OPERATOR_NAME_VIEW;
+import static com.android.systemui.statusbar.phone.fragment.dagger.HomeStatusBarModule.OPERATOR_NAME_VIEW;
 
 import android.annotation.NonNull;
 import android.os.Bundle;
@@ -32,7 +32,7 @@
 import com.android.systemui.demomode.DemoModeCommandReceiver;
 import com.android.systemui.demomode.DemoModeController;
 import com.android.systemui.navigationbar.NavigationBarController;
-import com.android.systemui.statusbar.phone.fragment.dagger.StatusBarFragmentScope;
+import com.android.systemui.statusbar.phone.fragment.dagger.HomeStatusBarScope;
 import com.android.systemui.statusbar.policy.Clock;
 import com.android.systemui.util.ViewController;
 
@@ -48,7 +48,7 @@
  * This class extends ViewController not because it controls a specific view, but because we want it
  * to get torn down and re-created in line with the view's lifecycle.
  */
-@StatusBarFragmentScope
+@HomeStatusBarScope
 public class StatusBarDemoMode extends ViewController<View> implements DemoMode {
     private final Clock mClockView;
     private final View mOperatorNameView;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/fragment/CollapsedStatusBarFragment.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/fragment/CollapsedStatusBarFragment.java
index d868519..37c8c63 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/fragment/CollapsedStatusBarFragment.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/fragment/CollapsedStatusBarFragment.java
@@ -66,15 +66,15 @@
 import com.android.systemui.statusbar.phone.PhoneStatusBarView;
 import com.android.systemui.statusbar.phone.StatusBarHideIconsForBouncerManager;
 import com.android.systemui.statusbar.phone.StatusBarLocation;
-import com.android.systemui.statusbar.phone.fragment.dagger.StatusBarFragmentComponent;
-import com.android.systemui.statusbar.phone.fragment.dagger.StatusBarFragmentComponent.Startable;
+import com.android.systemui.statusbar.phone.fragment.dagger.HomeStatusBarComponent;
+import com.android.systemui.statusbar.phone.fragment.dagger.HomeStatusBarComponent.Startable;
 import com.android.systemui.statusbar.phone.ongoingcall.OngoingCallController;
 import com.android.systemui.statusbar.phone.ongoingcall.OngoingCallListener;
 import com.android.systemui.statusbar.phone.ui.DarkIconManager;
 import com.android.systemui.statusbar.phone.ui.StatusBarIconController;
-import com.android.systemui.statusbar.pipeline.shared.ui.binder.CollapsedStatusBarViewBinder;
+import com.android.systemui.statusbar.pipeline.shared.ui.binder.HomeStatusBarViewBinder;
 import com.android.systemui.statusbar.pipeline.shared.ui.binder.StatusBarVisibilityChangeListener;
-import com.android.systemui.statusbar.pipeline.shared.ui.viewmodel.CollapsedStatusBarViewModel;
+import com.android.systemui.statusbar.pipeline.shared.ui.viewmodel.HomeStatusBarViewModel;
 import com.android.systemui.statusbar.policy.KeyguardStateController;
 import com.android.systemui.statusbar.window.StatusBarWindowStateController;
 import com.android.systemui.statusbar.window.StatusBarWindowStateListener;
@@ -115,7 +115,7 @@
     public static final int FADE_IN_DELAY = 50;
     private static final int SOURCE_SYSTEM_EVENT_ANIMATOR = 1;
     private static final int SOURCE_OTHER = 2;
-    private StatusBarFragmentComponent mStatusBarFragmentComponent;
+    private HomeStatusBarComponent mHomeStatusBarComponent;
     private PhoneStatusBarView mStatusBar;
     private final StatusBarStateController mStatusBarStateController;
     private final KeyguardStateController mKeyguardStateController;
@@ -134,7 +134,7 @@
     private StatusBarVisibilityModel mLastModifiedVisibility =
             StatusBarVisibilityModel.createDefaultModel();
     private DarkIconManager mDarkIconManager;
-    private final StatusBarFragmentComponent.Factory mStatusBarFragmentComponentFactory;
+    private final HomeStatusBarComponent.Factory mHomeStatusBarComponentFactory;
     private final CommandQueue mCommandQueue;
     private final CollapsedStatusBarFragmentLogger mCollapsedStatusBarFragmentLogger;
     private final OperatorNameViewController.Factory mOperatorNameViewControllerFactory;
@@ -143,8 +143,8 @@
     private final ShadeExpansionStateManager mShadeExpansionStateManager;
     private final StatusBarIconController mStatusBarIconController;
     private final CarrierConfigTracker mCarrierConfigTracker;
-    private final CollapsedStatusBarViewModel mCollapsedStatusBarViewModel;
-    private final CollapsedStatusBarViewBinder mCollapsedStatusBarViewBinder;
+    private final HomeStatusBarViewModel mHomeStatusBarViewModel;
+    private final HomeStatusBarViewBinder mHomeStatusBarViewBinder;
     private final StatusBarHideIconsForBouncerManager mStatusBarHideIconsForBouncerManager;
     private final DarkIconManager.Factory mDarkIconManagerFactory;
     private final SecureSettings mSecureSettings;
@@ -239,14 +239,14 @@
 
     @Inject
     public CollapsedStatusBarFragment(
-            StatusBarFragmentComponent.Factory statusBarFragmentComponentFactory,
+            HomeStatusBarComponent.Factory homeStatusBarComponentFactory,
             OngoingCallController ongoingCallController,
             SystemStatusAnimationScheduler animationScheduler,
             ShadeExpansionStateManager shadeExpansionStateManager,
             StatusBarIconController statusBarIconController,
             DarkIconManager.Factory darkIconManagerFactory,
-            CollapsedStatusBarViewModel collapsedStatusBarViewModel,
-            CollapsedStatusBarViewBinder collapsedStatusBarViewBinder,
+            HomeStatusBarViewModel homeStatusBarViewModel,
+            HomeStatusBarViewBinder homeStatusBarViewBinder,
             StatusBarHideIconsForBouncerManager statusBarHideIconsForBouncerManager,
             KeyguardStateController keyguardStateController,
             PanelExpansionInteractor panelExpansionInteractor,
@@ -262,13 +262,13 @@
             StatusBarWindowStateController statusBarWindowStateController,
             KeyguardUpdateMonitor keyguardUpdateMonitor,
             DemoModeController demoModeController) {
-        mStatusBarFragmentComponentFactory = statusBarFragmentComponentFactory;
+        mHomeStatusBarComponentFactory = homeStatusBarComponentFactory;
         mOngoingCallController = ongoingCallController;
         mAnimationScheduler = animationScheduler;
         mShadeExpansionStateManager = shadeExpansionStateManager;
         mStatusBarIconController = statusBarIconController;
-        mCollapsedStatusBarViewModel = collapsedStatusBarViewModel;
-        mCollapsedStatusBarViewBinder = collapsedStatusBarViewBinder;
+        mHomeStatusBarViewModel = homeStatusBarViewModel;
+        mHomeStatusBarViewBinder = homeStatusBarViewBinder;
         mStatusBarHideIconsForBouncerManager = statusBarHideIconsForBouncerManager;
         mDarkIconManagerFactory = darkIconManagerFactory;
         mKeyguardStateController = keyguardStateController;
@@ -335,11 +335,11 @@
     public void onViewCreated(View view, @Nullable Bundle savedInstanceState) {
         super.onViewCreated(view, savedInstanceState);
         mDumpManager.registerDumpable(getDumpableName(), this);
-        mStatusBarFragmentComponent = mStatusBarFragmentComponentFactory.create(
+        mHomeStatusBarComponent = mHomeStatusBarComponentFactory.create(
                 (PhoneStatusBarView) getView());
-        mStatusBarFragmentComponent.init();
+        mHomeStatusBarComponent.init();
         mStartableStates.clear();
-        for (Startable startable : mStatusBarFragmentComponent.getStartables()) {
+        for (Startable startable : mHomeStatusBarComponent.getStartables()) {
             mStartableStates.put(startable, Startable.State.STARTING);
             startable.start();
             mStartableStates.put(startable, Startable.State.STARTED);
@@ -371,8 +371,8 @@
         mCarrierConfigTracker.addCallback(mCarrierConfigCallback);
         mCarrierConfigTracker.addDefaultDataSubscriptionChangedListener(mDefaultDataListener);
 
-        mCollapsedStatusBarViewBinder.bind(
-                mStatusBar, mCollapsedStatusBarViewModel, mStatusBarVisibilityChangeListener);
+        mHomeStatusBarViewBinder.bind(
+                mStatusBar, mHomeStatusBarViewModel, mStatusBarVisibilityChangeListener);
     }
 
     private String getDumpableName() {
@@ -474,7 +474,7 @@
         mCarrierConfigTracker.removeCallback(mCarrierConfigCallback);
         mCarrierConfigTracker.removeDataSubscriptionChangedListener(mDefaultDataListener);
 
-        for (Startable startable : mStatusBarFragmentComponent.getStartables()) {
+        for (Startable startable : mHomeStatusBarComponent.getStartables()) {
             mStartableStates.put(startable, Startable.State.STOPPING);
             startable.stop();
             mStartableStates.put(startable, Startable.State.STOPPED);
@@ -515,8 +515,8 @@
      *   fragment functionality and we won't need to expose it here anymore.
      */
     @Nullable
-    public StatusBarFragmentComponent getStatusBarFragmentComponent() {
-        return mStatusBarFragmentComponent;
+    public HomeStatusBarComponent getHomeStatusBarComponent() {
+        return mHomeStatusBarComponent;
     }
 
     private StatusBarVisibilityChangeListener mStatusBarVisibilityChangeListener =
@@ -622,7 +622,7 @@
 
         // TODO(b/328393714) use HeadsUpNotificationInteractor.showHeadsUpStatusBar instead.
         boolean headsUpVisible =
-                mStatusBarFragmentComponent.getHeadsUpAppearanceController().shouldBeVisible();
+                mHomeStatusBarComponent.getHeadsUpAppearanceController().shouldBeVisible();
 
         if (SceneContainerFlag.isEnabled()) {
             // With the scene container, only use the value calculated by the view model to
@@ -757,7 +757,7 @@
         // transition to occluding to finish before allowing us to potentially show the status bar
         // again. (This status bar is always hidden on keyguard, so it's safe to continue hiding it
         // during this transition.) See b/273314977.
-        if (mCollapsedStatusBarViewModel.isTransitioningFromLockscreenToOccluded().getValue()) {
+        if (mHomeStatusBarViewModel.isTransitioningFromLockscreenToOccluded().getValue()) {
             return true;
         }
 
@@ -997,7 +997,7 @@
         pw.println("mHasPrimaryOngoingActivity=" + mHasPrimaryOngoingActivity);
         pw.println("mHasSecondaryOngoingActivity=" + mHasSecondaryOngoingActivity);
         pw.println("mAnimationsEnabled=" + mAnimationsEnabled);
-        StatusBarFragmentComponent component = mStatusBarFragmentComponent;
+        HomeStatusBarComponent component = mHomeStatusBarComponent;
         if (component == null) {
             pw.println("StatusBarFragmentComponent is null");
         } else {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/fragment/CollapsedStatusBarFragmentStartable.kt b/packages/SystemUI/src/com/android/systemui/statusbar/phone/fragment/CollapsedStatusBarFragmentStartable.kt
index 55af0e3..94006f6 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/fragment/CollapsedStatusBarFragmentStartable.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/fragment/CollapsedStatusBarFragmentStartable.kt
@@ -20,7 +20,7 @@
 import com.android.systemui.dagger.SysUISingleton
 import com.android.systemui.fragments.FragmentService
 import com.android.systemui.qs.QSFragmentStartable
-import com.android.systemui.statusbar.phone.fragment.dagger.StatusBarFragmentComponent
+import com.android.systemui.statusbar.phone.fragment.dagger.HomeStatusBarComponent
 import dagger.Binds
 import dagger.Module
 import dagger.multibindings.ClassKey
@@ -37,7 +37,7 @@
 @Inject
 constructor(
     private val fragmentService: FragmentService,
-    private val collapsedstatusBarFragmentProvider: Provider<CollapsedStatusBarFragment>
+    private val collapsedstatusBarFragmentProvider: Provider<CollapsedStatusBarFragment>,
 ) : CoreStartable {
     override fun start() {
         fragmentService.addFragmentInstantiationProvider(
@@ -47,7 +47,7 @@
     }
 }
 
-@Module(subcomponents = [StatusBarFragmentComponent::class])
+@Module(subcomponents = [HomeStatusBarComponent::class])
 interface CollapsedStatusBarFragmentStartableModule {
     @Binds
     @IntoMap
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/fragment/dagger/StatusBarFragmentComponent.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/fragment/dagger/HomeStatusBarComponent.java
similarity index 87%
rename from packages/SystemUI/src/com/android/systemui/statusbar/phone/fragment/dagger/StatusBarFragmentComponent.java
rename to packages/SystemUI/src/com/android/systemui/statusbar/phone/fragment/dagger/HomeStatusBarComponent.java
index 96faa35..d4cb625 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/fragment/dagger/StatusBarFragmentComponent.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/fragment/dagger/HomeStatusBarComponent.java
@@ -42,27 +42,29 @@
  * fragment is recreated.
  *
  * Anything that depends on {@link CollapsedStatusBarFragment} or {@link PhoneStatusBarView}
- * should be included here or in {@link StatusBarFragmentModule}.
+ * should be included here or in {@link HomeStatusBarModule}.
  */
-
 @Subcomponent(modules = {
-        StatusBarFragmentModule.class,
+        HomeStatusBarModule.class,
         StatusBarStartablesModule.class
 })
-@StatusBarFragmentScope
-public interface StatusBarFragmentComponent {
+@HomeStatusBarScope
+public interface HomeStatusBarComponent {
     /** Simple factory. */
     @Subcomponent.Factory
     interface Factory {
-        StatusBarFragmentComponent create(
+        /** */
+        HomeStatusBarComponent create(
                 @BindsInstance @RootView PhoneStatusBarView phoneStatusBarView);
     }
 
     /**
-     * Performs initialization logic after {@link StatusBarFragmentComponent} has been constructed.
+     * Performs initialization logic after {@link HomeStatusBarComponent} has been constructed.
      */
     interface Startable {
+        /** */
         void start();
+        /** */
         void stop();
 
         enum State {
@@ -86,32 +88,32 @@
     }
 
     /** */
-    @StatusBarFragmentScope
+    @HomeStatusBarScope
     BatteryMeterViewController getBatteryMeterViewController();
 
     /** */
-    @StatusBarFragmentScope
+    @HomeStatusBarScope
     @RootView
     PhoneStatusBarView getPhoneStatusBarView();
 
     /** */
-    @StatusBarFragmentScope
+    @HomeStatusBarScope
     PhoneStatusBarViewController getPhoneStatusBarViewController();
 
     /** */
-    @StatusBarFragmentScope
+    @HomeStatusBarScope
     HeadsUpAppearanceController getHeadsUpAppearanceController();
 
     /** */
-    @StatusBarFragmentScope
+    @HomeStatusBarScope
     LegacyLightsOutNotifController getLegacyLightsOutNotifController();
 
     /** */
-    @StatusBarFragmentScope
+    @HomeStatusBarScope
     StatusBarDemoMode getStatusBarDemoMode();
 
     /** */
-    @StatusBarFragmentScope
+    @HomeStatusBarScope
     PhoneStatusBarTransitions getPhoneStatusBarTransitions();
 
     /** */
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/fragment/dagger/StatusBarFragmentModule.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/fragment/dagger/HomeStatusBarModule.java
similarity index 89%
rename from packages/SystemUI/src/com/android/systemui/statusbar/phone/fragment/dagger/StatusBarFragmentModule.java
rename to packages/SystemUI/src/com/android/systemui/statusbar/phone/fragment/dagger/HomeStatusBarModule.java
index cf877a7..05b3238 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/fragment/dagger/StatusBarFragmentModule.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/fragment/dagger/HomeStatusBarModule.java
@@ -28,7 +28,6 @@
 import com.android.systemui.statusbar.phone.PhoneStatusBarViewController;
 import com.android.systemui.statusbar.phone.StatusBarLocation;
 import com.android.systemui.statusbar.policy.Clock;
-import com.android.systemui.statusbar.window.StatusBarWindowController;
 import com.android.systemui.statusbar.window.StatusBarWindowControllerStore;
 
 import dagger.Module;
@@ -38,9 +37,9 @@
 
 import javax.inject.Named;
 
-/** Dagger module for {@link StatusBarFragmentComponent}. */
+/** Dagger module for {@link HomeStatusBarComponent}. */
 @Module
-public interface StatusBarFragmentModule {
+public interface HomeStatusBarModule {
 
     String LIGHTS_OUT_NOTIF_VIEW = "lights_out_notif_view";
     String OPERATOR_NAME_VIEW = "operator_name_view";
@@ -50,21 +49,21 @@
 
     /** */
     @Provides
-    @StatusBarFragmentScope
+    @HomeStatusBarScope
     static BatteryMeterView provideBatteryMeterView(@RootView PhoneStatusBarView view) {
         return view.findViewById(R.id.battery);
     }
 
     /** */
     @Provides
-    @StatusBarFragmentScope
+    @HomeStatusBarScope
     static StatusBarLocation getStatusBarLocation() {
         return StatusBarLocation.HOME;
     }
 
     /** */
     @Provides
-    @StatusBarFragmentScope
+    @HomeStatusBarScope
     @Named(START_SIDE_CONTENT)
     static View startSideContent(@RootView PhoneStatusBarView view) {
         return view.findViewById(R.id.status_bar_start_side_content);
@@ -72,7 +71,7 @@
 
     /** */
     @Provides
-    @StatusBarFragmentScope
+    @HomeStatusBarScope
     @Named(END_SIDE_CONTENT)
     static View endSideContent(@RootView PhoneStatusBarView view) {
         return view.findViewById(R.id.status_bar_end_side_content);
@@ -80,7 +79,7 @@
 
     /** */
     @Provides
-    @StatusBarFragmentScope
+    @HomeStatusBarScope
     @Named(LIGHTS_OUT_NOTIF_VIEW)
     static View provideLightsOutNotifView(@RootView PhoneStatusBarView view) {
         return view.findViewById(R.id.notification_lights_out);
@@ -88,7 +87,7 @@
 
     /** */
     @Provides
-    @StatusBarFragmentScope
+    @HomeStatusBarScope
     @Named(OPERATOR_NAME_VIEW)
     static View provideOperatorNameView(@RootView PhoneStatusBarView view) {
         View operatorName = ((ViewStub) view.findViewById(R.id.operator_name_stub)).inflate();
@@ -98,7 +97,7 @@
 
     /** */
     @Provides
-    @StatusBarFragmentScope
+    @HomeStatusBarScope
     @Named(OPERATOR_NAME_FRAME_VIEW)
     static Optional<View> provideOperatorFrameNameView(@RootView PhoneStatusBarView view) {
         return Optional.ofNullable(view.findViewById(R.id.operator_name_frame));
@@ -106,14 +105,14 @@
 
     /** */
     @Provides
-    @StatusBarFragmentScope
+    @HomeStatusBarScope
     static Clock provideClock(@RootView PhoneStatusBarView view) {
         return view.findViewById(R.id.clock);
     }
 
     /** */
     @Provides
-    @StatusBarFragmentScope
+    @HomeStatusBarScope
     static PhoneStatusBarViewController providePhoneStatusBarViewController(
             PhoneStatusBarViewController.Factory phoneStatusBarViewControllerFactory,
             @RootView PhoneStatusBarView phoneStatusBarView) {
@@ -123,7 +122,7 @@
 
     /** */
     @Provides
-    @StatusBarFragmentScope
+    @HomeStatusBarScope
     static PhoneStatusBarTransitions providePhoneStatusBarTransitions(
             @RootView PhoneStatusBarView view,
             StatusBarWindowControllerStore statusBarWindowControllerStore) {
@@ -133,7 +132,7 @@
 
     /** */
     @Provides
-    @StatusBarFragmentScope
+    @HomeStatusBarScope
     static HeadsUpStatusBarView providesHeasdUpStatusBarView(@RootView PhoneStatusBarView view) {
         return view.findViewById(R.id.heads_up_status_bar_view);
     }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/fragment/dagger/StatusBarFragmentScope.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/fragment/dagger/HomeStatusBarScope.java
similarity index 87%
rename from packages/SystemUI/src/com/android/systemui/statusbar/phone/fragment/dagger/StatusBarFragmentScope.java
rename to packages/SystemUI/src/com/android/systemui/statusbar/phone/fragment/dagger/HomeStatusBarScope.java
index 96cff59..2b1eddd 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/fragment/dagger/StatusBarFragmentScope.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/fragment/dagger/HomeStatusBarScope.java
@@ -24,9 +24,9 @@
 import javax.inject.Scope;
 
 /**
- * Scope annotation for singleton items within the {@link StatusBarFragmentComponent}.
+ * Scope annotation for singleton items within the {@link HomeStatusBarComponent}.
  */
 @Documented
 @Retention(RUNTIME)
 @Scope
-public @interface StatusBarFragmentScope {}
+public @interface HomeStatusBarScope {}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/fragment/dagger/StatusBarStartablesModule.kt b/packages/SystemUI/src/com/android/systemui/statusbar/phone/fragment/dagger/StatusBarStartablesModule.kt
index 9003d13..ba91814 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/fragment/dagger/StatusBarStartablesModule.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/fragment/dagger/StatusBarStartablesModule.kt
@@ -28,5 +28,5 @@
     @IntoSet
     fun statusBarBoundsCalculator(
         statusBarBoundsProvider: StatusBarBoundsProvider
-    ): StatusBarFragmentComponent.Startable
+    ): HomeStatusBarComponent.Startable
 }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/dagger/StatusBarPipelineModule.kt b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/dagger/StatusBarPipelineModule.kt
index 4850049..935b101 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/dagger/StatusBarPipelineModule.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/dagger/StatusBarPipelineModule.kt
@@ -48,10 +48,10 @@
 import com.android.systemui.statusbar.pipeline.satellite.ui.viewmodel.DeviceBasedSatelliteViewModelImpl
 import com.android.systemui.statusbar.pipeline.shared.data.repository.ConnectivityRepository
 import com.android.systemui.statusbar.pipeline.shared.data.repository.ConnectivityRepositoryImpl
-import com.android.systemui.statusbar.pipeline.shared.ui.binder.CollapsedStatusBarViewBinder
-import com.android.systemui.statusbar.pipeline.shared.ui.binder.CollapsedStatusBarViewBinderImpl
-import com.android.systemui.statusbar.pipeline.shared.ui.viewmodel.CollapsedStatusBarViewModel
-import com.android.systemui.statusbar.pipeline.shared.ui.viewmodel.CollapsedStatusBarViewModelImpl
+import com.android.systemui.statusbar.pipeline.shared.ui.binder.HomeStatusBarViewBinder
+import com.android.systemui.statusbar.pipeline.shared.ui.binder.HomeStatusBarViewBinderImpl
+import com.android.systemui.statusbar.pipeline.shared.ui.viewmodel.HomeStatusBarViewModel
+import com.android.systemui.statusbar.pipeline.shared.ui.viewmodel.HomeStatusBarViewModelImpl
 import com.android.systemui.statusbar.pipeline.wifi.data.repository.RealWifiRepository
 import com.android.systemui.statusbar.pipeline.wifi.data.repository.WifiRepository
 import com.android.systemui.statusbar.pipeline.wifi.data.repository.WifiRepositorySwitcher
@@ -131,14 +131,10 @@
     abstract fun bindCarrierConfigStartable(impl: CarrierConfigCoreStartable): CoreStartable
 
     @Binds
-    abstract fun collapsedStatusBarViewModel(
-        impl: CollapsedStatusBarViewModelImpl
-    ): CollapsedStatusBarViewModel
+    abstract fun homeStatusBarViewModel(impl: HomeStatusBarViewModelImpl): HomeStatusBarViewModel
 
     @Binds
-    abstract fun collapsedStatusBarViewBinder(
-        impl: CollapsedStatusBarViewBinderImpl
-    ): CollapsedStatusBarViewBinder
+    abstract fun homeStatusBarViewBinder(impl: HomeStatusBarViewBinderImpl): HomeStatusBarViewBinder
 
     companion object {
 
@@ -162,7 +158,7 @@
         @SysUISingleton
         @Named(FIRST_MOBILE_SUB_SHOWING_NETWORK_TYPE_ICON)
         fun provideFirstMobileSubShowingNetworkTypeIconProvider(
-            mobileIconsViewModel: MobileIconsViewModel,
+            mobileIconsViewModel: MobileIconsViewModel
         ): Supplier<Flow<Boolean>> {
             return Supplier<Flow<Boolean>> {
                 mobileIconsViewModel.firstMobileSubShowingNetworkTypeIcon
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/shared/ui/binder/CollapsedStatusBarViewBinder.kt b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/shared/ui/binder/HomeStatusBarViewBinder.kt
similarity index 94%
rename from packages/SystemUI/src/com/android/systemui/statusbar/pipeline/shared/ui/binder/CollapsedStatusBarViewBinder.kt
rename to packages/SystemUI/src/com/android/systemui/statusbar/pipeline/shared/ui/binder/HomeStatusBarViewBinder.kt
index 3a07d9b..8d7b57d 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/shared/ui/binder/CollapsedStatusBarViewBinder.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/shared/ui/binder/HomeStatusBarViewBinder.kt
@@ -33,31 +33,32 @@
 import com.android.systemui.statusbar.core.StatusBarSimpleFragment
 import com.android.systemui.statusbar.notification.shared.NotificationsLiveDataStoreRefactor
 import com.android.systemui.statusbar.phone.fragment.CollapsedStatusBarFragment
-import com.android.systemui.statusbar.pipeline.shared.ui.viewmodel.CollapsedStatusBarViewModel
+import com.android.systemui.statusbar.pipeline.shared.ui.viewmodel.HomeStatusBarViewModel
+import com.android.systemui.statusbar.pipeline.shared.ui.viewmodel.HomeStatusBarViewModel.VisibilityModel
 import javax.inject.Inject
 import kotlinx.coroutines.launch
 
 /**
- * Interface to assist with binding the [CollapsedStatusBarFragment] to
- * [CollapsedStatusBarViewModel]. Used only to enable easy testing of [CollapsedStatusBarFragment].
+ * Interface to assist with binding the [CollapsedStatusBarFragment] to [HomeStatusBarViewModel].
+ * Used only to enable easy testing of [CollapsedStatusBarFragment].
  */
-interface CollapsedStatusBarViewBinder {
+interface HomeStatusBarViewBinder {
     /**
      * Binds the view to the view-model. [listener] will be notified whenever an event that may
      * change the status bar visibility occurs.
      */
     fun bind(
         view: View,
-        viewModel: CollapsedStatusBarViewModel,
+        viewModel: HomeStatusBarViewModel,
         listener: StatusBarVisibilityChangeListener,
     )
 }
 
 @SysUISingleton
-class CollapsedStatusBarViewBinderImpl @Inject constructor() : CollapsedStatusBarViewBinder {
+class HomeStatusBarViewBinderImpl @Inject constructor() : HomeStatusBarViewBinder {
     override fun bind(
         view: View,
-        viewModel: CollapsedStatusBarViewModel,
+        viewModel: HomeStatusBarViewModel,
         listener: StatusBarVisibilityChangeListener,
     ) {
         view.repeatWhenAttached {
@@ -185,9 +186,8 @@
         }
     }
 
-    private fun OngoingActivityChipModel.toVisibilityModel():
-        CollapsedStatusBarViewModel.VisibilityModel {
-        return CollapsedStatusBarViewModel.VisibilityModel(
+    private fun OngoingActivityChipModel.toVisibilityModel(): VisibilityModel {
+        return VisibilityModel(
             visibility = if (this is OngoingActivityChipModel.Shown) View.VISIBLE else View.GONE,
             // TODO(b/364653005): Figure out the animation story here.
             shouldAnimateChange = true,
@@ -224,7 +224,7 @@
             .start()
     }
 
-    private fun View.adjustVisibility(model: CollapsedStatusBarViewModel.VisibilityModel) {
+    private fun View.adjustVisibility(model: VisibilityModel) {
         if (model.visibility == View.VISIBLE) {
             this.show(model.shouldAnimateChange)
         } else {
@@ -298,7 +298,7 @@
 
     /**
      * Called when the scene state has changed such that the home status bar is newly allowed or no
-     * longer allowed. See [CollapsedStatusBarViewModel.isHomeStatusBarAllowedByScene].
+     * longer allowed. See [HomeStatusBarViewModel.isHomeStatusBarAllowedByScene].
      */
     fun onIsHomeStatusBarAllowedBySceneChanged(isHomeStatusBarAllowedByScene: Boolean)
 }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/shared/ui/composable/RetroText.kt b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/shared/ui/composable/RetroText.kt
new file mode 100644
index 0000000..71bbdea
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/shared/ui/composable/RetroText.kt
@@ -0,0 +1,66 @@
+/*
+ * Copyright (C) 2024 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.pipeline.shared.ui.composable
+
+import androidx.compose.foundation.layout.offset
+import androidx.compose.material3.Text
+import androidx.compose.runtime.Composable
+import androidx.compose.ui.Modifier
+import androidx.compose.ui.graphics.Color
+import androidx.compose.ui.text.TextStyle
+import androidx.compose.ui.text.font.FontStyle
+import androidx.compose.ui.text.font.FontWeight
+import androidx.compose.ui.text.style.TextAlign
+import androidx.compose.ui.unit.Dp
+import androidx.compose.ui.unit.dp
+import androidx.compose.ui.unit.sp
+
+private val retroColors =
+    listOf(
+        Color(0xFFEADFB4), // beige
+        Color(0xFF9BB0C1), // gray-blue
+        Color(0xFFF6995C), // orange
+        Color(0xFF51829B), // cyan
+    )
+
+/** Render a single string multiple times (with offsets) kinda like retro vintage text */
+@Composable
+fun RetroText(text: String = "") {
+    // Render the text for each retroColor, and then once for the foreground
+    for (i in retroColors.size downTo 1) {
+        val color = retroColors[i - 1]
+        RetroTextLayer(text = text, color = color, (-1.5 * i).dp, i.dp)
+    }
+
+    RetroTextLayer(text = text, color = Color.Black, ox = 0.dp, oy = 0.dp)
+}
+
+@Composable
+fun RetroTextLayer(text: String, color: Color, ox: Dp, oy: Dp) {
+    Text(
+        text = text,
+        modifier = Modifier.offset(ox, oy),
+        textAlign = TextAlign.Center,
+        style =
+            TextStyle(
+                fontSize = 18.sp,
+                fontWeight = FontWeight.Bold,
+                fontStyle = FontStyle.Italic,
+                color = color,
+            ),
+    )
+}
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
new file mode 100644
index 0000000..440eb91
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/shared/ui/composable/StatusBarRoot.kt
@@ -0,0 +1,195 @@
+/*
+ * Copyright (C) 2024 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.pipeline.shared.ui.composable
+
+import android.content.Context
+import android.view.LayoutInflater
+import android.view.View
+import android.view.ViewGroup
+import androidx.compose.foundation.layout.Box
+import androidx.compose.foundation.layout.Row
+import androidx.compose.foundation.layout.fillMaxSize
+import androidx.compose.runtime.Composable
+import androidx.compose.runtime.rememberCoroutineScope
+import androidx.compose.ui.Alignment
+import androidx.compose.ui.Modifier
+import androidx.compose.ui.draw.alpha
+import androidx.compose.ui.platform.ComposeView
+import androidx.compose.ui.viewinterop.AndroidView
+import androidx.lifecycle.compose.collectAsStateWithLifecycle
+import com.android.systemui.res.R
+import com.android.systemui.statusbar.notification.icon.ui.viewbinder.NotificationIconContainerStatusBarViewBinder
+import com.android.systemui.statusbar.phone.NotificationIconContainer
+import com.android.systemui.statusbar.phone.PhoneStatusBarView
+import com.android.systemui.statusbar.phone.StatusBarLocation
+import com.android.systemui.statusbar.phone.StatusIconContainer
+import com.android.systemui.statusbar.phone.ongoingcall.OngoingCallController
+import com.android.systemui.statusbar.phone.ui.DarkIconManager
+import com.android.systemui.statusbar.phone.ui.StatusBarIconController
+import com.android.systemui.statusbar.pipeline.shared.ui.binder.HomeStatusBarViewBinder
+import com.android.systemui.statusbar.pipeline.shared.ui.binder.StatusBarVisibilityChangeListener
+import com.android.systemui.statusbar.pipeline.shared.ui.viewmodel.HomeStatusBarViewModel
+import javax.inject.Inject
+import kotlinx.coroutines.launch
+
+/** Factory to simplify the dependency management for [StatusBarRoot] */
+class StatusBarRootFactory
+@Inject
+constructor(
+    private val context: Context,
+    private val homeStatusBarViewModel: HomeStatusBarViewModel,
+    private val homeStatusBarViewBinder: HomeStatusBarViewBinder,
+    private val notificationIconsBinder: NotificationIconContainerStatusBarViewBinder,
+    private val darkIconManagerFactory: DarkIconManager.Factory,
+    private val iconController: StatusBarIconController,
+    private val ongoingCallController: OngoingCallController,
+) {
+    fun create(root: ViewGroup, andThen: (ViewGroup) -> Unit): ComposeView {
+        val composeView = ComposeView(context)
+        composeView.apply {
+            setContent {
+                StatusBarRoot(
+                    parent = root,
+                    statusBarViewModel = homeStatusBarViewModel,
+                    statusBarViewBinder = homeStatusBarViewBinder,
+                    notificationIconsBinder = notificationIconsBinder,
+                    darkIconManagerFactory = darkIconManagerFactory,
+                    iconController = iconController,
+                    ongoingCallController = ongoingCallController,
+                    onViewCreated = andThen,
+                )
+            }
+        }
+
+        return composeView
+    }
+}
+
+/**
+ * For now, this class exists only to replace the former CollapsedStatusBarFragment. We simply stand
+ * up the PhoneStatusBarView here (allowing the component to be initialized from the [init] block).
+ * This is the place, for now, where we can manually set up lingering dependencies that came from
+ * the fragment until we can move them to recommended-arch style repos.
+ *
+ * @param onViewCreated called immediately after the view is inflated, and takes as a parameter the
+ *   newly-inflated PhoneStatusBarView. This lambda is useful for tying together old initialization
+ *   logic until it can be replaced.
+ */
+@Composable
+fun StatusBarRoot(
+    parent: ViewGroup,
+    statusBarViewModel: HomeStatusBarViewModel,
+    statusBarViewBinder: HomeStatusBarViewBinder,
+    notificationIconsBinder: NotificationIconContainerStatusBarViewBinder,
+    darkIconManagerFactory: DarkIconManager.Factory,
+    iconController: StatusBarIconController,
+    ongoingCallController: OngoingCallController,
+    onViewCreated: (ViewGroup) -> Unit,
+) {
+    // None of these methods are used when [StatusBarSimpleFragment] is on.
+    // This can be deleted once the fragment is gone
+    val nopVisibilityChangeListener =
+        object : StatusBarVisibilityChangeListener {
+            override fun onStatusBarVisibilityMaybeChanged() {}
+
+            override fun onTransitionFromLockscreenToDreamStarted() {}
+
+            override fun onOngoingActivityStatusChanged(
+                hasPrimaryOngoingActivity: Boolean,
+                hasSecondaryOngoingActivity: Boolean,
+                shouldAnimate: Boolean,
+            ) {}
+
+            override fun onIsHomeStatusBarAllowedBySceneChanged(
+                isHomeStatusBarAllowedByScene: Boolean
+            ) {}
+        }
+
+    Box(Modifier.fillMaxSize()) {
+        // TODO(b/364360986): remove this before rolling the flag forward
+        Disambiguation(viewModel = statusBarViewModel)
+
+        Row(Modifier.fillMaxSize()) {
+            val scope = rememberCoroutineScope()
+            AndroidView(
+                factory = { context ->
+                    val inflater = LayoutInflater.from(context)
+                    val phoneStatusBarView =
+                        inflater.inflate(R.layout.status_bar, parent, false) as PhoneStatusBarView
+
+                    // For now, just set up the system icons the same way we used to
+                    val statusIconContainer =
+                        phoneStatusBarView.requireViewById<StatusIconContainer>(R.id.statusIcons)
+                    // TODO(b/364360986): turn this into a repo/intr/viewmodel
+                    val darkIconManager =
+                        darkIconManagerFactory.create(statusIconContainer, StatusBarLocation.HOME)
+                    iconController.addIconGroup(darkIconManager)
+
+                    // TODO(b/372657935): This won't be needed once OngoingCallController is
+                    // implemented in recommended architecture
+                    ongoingCallController.setChipView(
+                        phoneStatusBarView.requireViewById(R.id.ongoing_activity_chip_primary)
+                    )
+
+                    // For notifications, first inflate the [NotificationIconContainer]
+                    val notificationIconArea =
+                        phoneStatusBarView.requireViewById<ViewGroup>(R.id.notification_icon_area)
+                    inflater.inflate(R.layout.notification_icon_area, notificationIconArea, true)
+                    // Then bind it using the icons binder
+                    val notificationIconContainer =
+                        phoneStatusBarView.requireViewById<NotificationIconContainer>(
+                            R.id.notificationIcons
+                        )
+                    scope.launch {
+                        notificationIconsBinder.bindWhileAttached(notificationIconContainer)
+                    }
+
+                    // This binder handles everything else
+                    scope.launch {
+                        statusBarViewBinder.bind(
+                            phoneStatusBarView,
+                            statusBarViewModel,
+                            nopVisibilityChangeListener,
+                        )
+                    }
+                    onViewCreated(phoneStatusBarView)
+                    phoneStatusBarView
+                }
+            )
+        }
+    }
+}
+
+/**
+ * This is our analog of the flexi "ribbon", which just shows some text so we know if the flag is on
+ */
+@Composable
+fun Disambiguation(viewModel: HomeStatusBarViewModel) {
+    val clockVisibilityModel =
+        viewModel.isClockVisible.collectAsStateWithLifecycle(
+            initialValue =
+                HomeStatusBarViewModel.VisibilityModel(
+                    visibility = View.GONE,
+                    shouldAnimateChange = false,
+                )
+        )
+    if (clockVisibilityModel.value.visibility == View.VISIBLE) {
+        Box(modifier = Modifier.fillMaxSize().alpha(0.5f), contentAlignment = Alignment.Center) {
+            RetroText(text = "COMPOSE->BAR")
+        }
+    }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/shared/ui/viewmodel/CollapsedStatusBarViewModel.kt b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/shared/ui/viewmodel/HomeStatusBarViewModel.kt
similarity index 84%
rename from packages/SystemUI/src/com/android/systemui/statusbar/pipeline/shared/ui/viewmodel/CollapsedStatusBarViewModel.kt
rename to packages/SystemUI/src/com/android/systemui/statusbar/pipeline/shared/ui/viewmodel/HomeStatusBarViewModel.kt
index 366ea35..4277a8b 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/shared/ui/viewmodel/CollapsedStatusBarViewModel.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/shared/ui/viewmodel/HomeStatusBarViewModel.kt
@@ -19,6 +19,7 @@
 import android.view.View
 import com.android.systemui.dagger.SysUISingleton
 import com.android.systemui.dagger.qualifiers.Application
+import com.android.systemui.keyguard.domain.interactor.KeyguardInteractor
 import com.android.systemui.keyguard.domain.interactor.KeyguardTransitionInteractor
 import com.android.systemui.keyguard.shared.model.Edge
 import com.android.systemui.keyguard.shared.model.KeyguardState.DREAMING
@@ -38,7 +39,7 @@
 import com.android.systemui.statusbar.notification.shared.NotificationsLiveDataStoreRefactor
 import com.android.systemui.statusbar.phone.domain.interactor.LightsOutInteractor
 import com.android.systemui.statusbar.pipeline.shared.domain.interactor.CollapsedStatusBarInteractor
-import com.android.systemui.statusbar.pipeline.shared.ui.viewmodel.CollapsedStatusBarViewModel.VisibilityModel
+import com.android.systemui.statusbar.pipeline.shared.ui.viewmodel.HomeStatusBarViewModel.VisibilityModel
 import javax.inject.Inject
 import kotlinx.coroutines.CoroutineScope
 import kotlinx.coroutines.flow.Flow
@@ -61,7 +62,7 @@
  * [StatusBarHideIconsForBouncerManager]. We should move those pieces of logic to this class instead
  * so that it's all in one place and easily testable outside of the fragment.
  */
-interface CollapsedStatusBarViewModel {
+interface HomeStatusBarViewModel {
     /**
      * True if the device is currently transitioning from lockscreen to occluded and false
      * otherwise.
@@ -116,19 +117,20 @@
 }
 
 @SysUISingleton
-class CollapsedStatusBarViewModelImpl
+class HomeStatusBarViewModelImpl
 @Inject
 constructor(
     collapsedStatusBarInteractor: CollapsedStatusBarInteractor,
     private val lightsOutInteractor: LightsOutInteractor,
     private val notificationsInteractor: ActiveNotificationsInteractor,
     keyguardTransitionInteractor: KeyguardTransitionInteractor,
+    keyguardInteractor: KeyguardInteractor,
     sceneInteractor: SceneInteractor,
     sceneContainerOcclusionInteractor: SceneContainerOcclusionInteractor,
     shadeInteractor: ShadeInteractor,
     ongoingActivityChipsViewModel: OngoingActivityChipsViewModel,
     @Application coroutineScope: CoroutineScope,
-) : CollapsedStatusBarViewModel {
+) : HomeStatusBarViewModel {
     override val isTransitioningFromLockscreenToOccluded: StateFlow<Boolean> =
         keyguardTransitionInteractor
             .isInTransition(Edge.create(from = LOCKSCREEN, to = OCCLUDED))
@@ -184,29 +186,43 @@
             // TODO(b/364360986): Add edge cases, like secure camera launch.
         }
 
-    private val isHomeScreenStatusBarAllowed: Flow<Boolean> =
+    private val isHomeStatusBarAllowed: Flow<Boolean> =
         if (SceneContainerFlag.isEnabled) {
             isHomeStatusBarAllowedByScene
         } else {
             isHomeScreenStatusBarAllowedLegacy
         }
 
+    private val shouldHomeStatusBarBeVisible =
+        combine(isHomeStatusBarAllowed, keyguardInteractor.isSecureCameraActive) {
+            isHomeStatusBarAllowed,
+            isSecureCameraActive ->
+            // When launching the camera over the lockscreen, the status icons would typically
+            // become visible momentarily before animating out, since we're not yet aware that the
+            // launching camera activity is fullscreen. Even once the activity finishes launching,
+            // it takes a short time before WM decides that the top app wants to hide the icons and
+            // tells us to hide them.
+            // To ensure that this high-visibility animation is smooth, keep the icons hidden during
+            // a camera launch. See b/257292822.
+            isHomeStatusBarAllowed && !isSecureCameraActive
+        }
+
     override val isClockVisible: Flow<VisibilityModel> =
         combine(
-            isHomeScreenStatusBarAllowed,
+            shouldHomeStatusBarBeVisible,
             collapsedStatusBarInteractor.visibilityViaDisableFlags,
-        ) { isStatusBarAllowed, visibilityViaDisableFlags ->
-            val showClock = isStatusBarAllowed && visibilityViaDisableFlags.isClockAllowed
+        ) { shouldStatusBarBeVisible, visibilityViaDisableFlags ->
+            val showClock = shouldStatusBarBeVisible && visibilityViaDisableFlags.isClockAllowed
             // TODO(b/364360986): Take CollapsedStatusBarFragment.clockHiddenMode into account.
             VisibilityModel(showClock.toVisibilityInt(), visibilityViaDisableFlags.animate)
         }
     override val isNotificationIconContainerVisible: Flow<VisibilityModel> =
         combine(
-            isHomeScreenStatusBarAllowed,
+            shouldHomeStatusBarBeVisible,
             collapsedStatusBarInteractor.visibilityViaDisableFlags,
-        ) { isStatusBarAllowed, visibilityViaDisableFlags ->
+        ) { shouldStatusBarBeVisible, visibilityViaDisableFlags ->
             val showNotificationIconContainer =
-                isStatusBarAllowed && visibilityViaDisableFlags.areNotificationIconsAllowed
+                shouldStatusBarBeVisible && visibilityViaDisableFlags.areNotificationIconsAllowed
             VisibilityModel(
                 showNotificationIconContainer.toVisibilityInt(),
                 visibilityViaDisableFlags.animate,
@@ -214,10 +230,11 @@
         }
     override val isSystemInfoVisible: Flow<VisibilityModel> =
         combine(
-            isHomeScreenStatusBarAllowed,
+            shouldHomeStatusBarBeVisible,
             collapsedStatusBarInteractor.visibilityViaDisableFlags,
-        ) { isStatusBarAllowed, visibilityViaDisableFlags ->
-            val showSystemInfo = isStatusBarAllowed && visibilityViaDisableFlags.isSystemInfoAllowed
+        ) { shouldStatusBarBeVisible, visibilityViaDisableFlags ->
+            val showSystemInfo =
+                shouldStatusBarBeVisible && visibilityViaDisableFlags.isSystemInfoAllowed
             VisibilityModel(showSystemInfo.toVisibilityInt(), visibilityViaDisableFlags.animate)
         }
 
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/window/StatusBarWindowView.java b/packages/SystemUI/src/com/android/systemui/statusbar/window/StatusBarWindowView.java
index d696979..fbf54e7 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/window/StatusBarWindowView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/window/StatusBarWindowView.java
@@ -30,8 +30,12 @@
 import android.view.WindowInsets;
 import android.widget.FrameLayout;
 
+import com.android.systemui.compose.ComposeInitializer;
+import com.android.systemui.statusbar.core.StatusBarSimpleFragment;
+
 /**
  * Status bar view.
+ * We now extend WindowRootView so that we can host Compose views
  */
 public class StatusBarWindowView extends FrameLayout {
 
@@ -50,6 +54,24 @@
     }
 
     @Override
+    public void onAttachedToWindow() {
+        super.onAttachedToWindow();
+
+        if (StatusBarSimpleFragment.isEnabled()) {
+            ComposeInitializer.INSTANCE.onAttachedToWindow(this);
+        }
+    }
+
+    @Override
+    public void onDetachedFromWindow() {
+        super.onDetachedFromWindow();
+
+        if (StatusBarSimpleFragment.isEnabled()) {
+            ComposeInitializer.INSTANCE.onDetachedFromWindow(this);
+        }
+    }
+
+    @Override
     public WindowInsets onApplyWindowInsets(WindowInsets windowInsets) {
         final Insets insets = windowInsets.getInsetsIgnoringVisibility(systemBars());
         mLeftInset = insets.left;
@@ -89,8 +111,8 @@
         final int count = getChildCount();
         for (int i = 0; i < count; i++) {
             View child = getChildAt(i);
-            if (child.getLayoutParams() instanceof LayoutParams) {
-                LayoutParams lp = (LayoutParams) child.getLayoutParams();
+            if (child.getLayoutParams() instanceof FrameLayout.LayoutParams) {
+                FrameLayout.LayoutParams lp = (FrameLayout.LayoutParams) child.getLayoutParams();
                 if (lp.rightMargin != mRightInset || lp.leftMargin != mLeftInset
                         || lp.topMargin != mTopInset) {
                     lp.rightMargin = mRightInset;
diff --git a/packages/SystemUI/src/com/android/systemui/volume/ui/navigation/VolumeNavigator.kt b/packages/SystemUI/src/com/android/systemui/volume/ui/navigation/VolumeNavigator.kt
index 3da725b..e590a7de 100644
--- a/packages/SystemUI/src/com/android/systemui/volume/ui/navigation/VolumeNavigator.kt
+++ b/packages/SystemUI/src/com/android/systemui/volume/ui/navigation/VolumeNavigator.kt
@@ -22,6 +22,7 @@
 import androidx.compose.runtime.LaunchedEffect
 import androidx.compose.runtime.remember
 import androidx.compose.runtime.rememberCoroutineScope
+import androidx.compose.ui.unit.dp
 import com.android.internal.logging.UiEventLogger
 import com.android.systemui.dagger.SysUISingleton
 import com.android.systemui.dagger.qualifiers.Application
@@ -89,7 +90,7 @@
             VolumePanelRoute.SETTINGS_VOLUME_PANEL ->
                 activityStarter.startActivity(
                     /* intent= */ Intent(Settings.Panel.ACTION_VOLUME),
-                    /* dismissShade= */ true
+                    /* dismissShade= */ true,
                 )
             VolumePanelRoute.SYSTEM_UI_VOLUME_PANEL ->
                 volumePanelFactory.create(aboveStatusBar = true, view = null)
@@ -122,6 +123,9 @@
                     remember(coroutineScope) { viewModelFactory.create(coroutineScope) }
                 )
             },
+            isDraggable = false,
+            // TODO(b/337205027) change maxWidth
+            maxWidth = 800.dp,
         )
     }
 }
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/CentralSurfacesImplTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/CentralSurfacesImplTest.java
index 8f64287..72f410b 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/CentralSurfacesImplTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/CentralSurfacesImplTest.java
@@ -186,6 +186,8 @@
 import com.android.systemui.statusbar.notification.stack.NotificationStackScrollLayout;
 import com.android.systemui.statusbar.notification.stack.NotificationStackScrollLayoutController;
 import com.android.systemui.statusbar.phone.fragment.CollapsedStatusBarFragment;
+import com.android.systemui.statusbar.phone.fragment.dagger.HomeStatusBarComponent;
+import com.android.systemui.statusbar.pipeline.shared.ui.composable.StatusBarRootFactory;
 import com.android.systemui.statusbar.policy.BatteryController;
 import com.android.systemui.statusbar.policy.ConfigurationController;
 import com.android.systemui.statusbar.policy.DeviceProvisionedController;
@@ -514,8 +516,9 @@
                 new StatusBarInitializerImpl(
                         mStatusBarWindowController,
                         mCollapsedStatusBarFragmentProvider,
-                        emptySet()
-                ),
+                        mock(StatusBarRootFactory.class),
+                        mock(HomeStatusBarComponent.Factory.class),
+                        emptySet()),
                 mStatusBarWindowControllerStore,
                 mStatusBarWindowStateController,
                 new FakeStatusBarModeRepository(),
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/fragment/CollapsedStatusBarFragmentTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/fragment/CollapsedStatusBarFragmentTest.java
index 15ef917..d01c1ca 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/fragment/CollapsedStatusBarFragmentTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/fragment/CollapsedStatusBarFragmentTest.java
@@ -66,12 +66,12 @@
 import com.android.systemui.statusbar.notification.icon.ui.viewbinder.NotificationIconContainerStatusBarViewBinder;
 import com.android.systemui.statusbar.phone.HeadsUpAppearanceController;
 import com.android.systemui.statusbar.phone.StatusBarHideIconsForBouncerManager;
-import com.android.systemui.statusbar.phone.fragment.dagger.StatusBarFragmentComponent;
+import com.android.systemui.statusbar.phone.fragment.dagger.HomeStatusBarComponent;
 import com.android.systemui.statusbar.phone.ongoingcall.OngoingCallController;
 import com.android.systemui.statusbar.phone.ui.DarkIconManager;
 import com.android.systemui.statusbar.phone.ui.StatusBarIconController;
-import com.android.systemui.statusbar.pipeline.shared.ui.viewmodel.FakeCollapsedStatusBarViewBinder;
-import com.android.systemui.statusbar.pipeline.shared.ui.viewmodel.FakeCollapsedStatusBarViewModel;
+import com.android.systemui.statusbar.pipeline.shared.ui.viewmodel.FakeHomeStatusBarViewBinder;
+import com.android.systemui.statusbar.pipeline.shared.ui.viewmodel.FakeHomeStatusBarViewModel;
 import com.android.systemui.statusbar.policy.KeyguardStateController;
 import com.android.systemui.statusbar.window.StatusBarWindowStateController;
 import com.android.systemui.statusbar.window.StatusBarWindowStateListener;
@@ -109,9 +109,9 @@
     private final CarrierConfigTracker mCarrierConfigTracker = mock(CarrierConfigTracker.class);
 
     @Mock
-    private StatusBarFragmentComponent.Factory mStatusBarFragmentComponentFactory;
+    private HomeStatusBarComponent.Factory mStatusBarFragmentComponentFactory;
     @Mock
-    private StatusBarFragmentComponent mStatusBarFragmentComponent;
+    private HomeStatusBarComponent mHomeStatusBarComponent;
     @Mock
     private StatusBarStateController mStatusBarStateController;
     @Mock
@@ -122,8 +122,8 @@
     private DarkIconManager.Factory mIconManagerFactory;
     @Mock
     private DarkIconManager mIconManager;
-    private FakeCollapsedStatusBarViewModel mCollapsedStatusBarViewModel;
-    private FakeCollapsedStatusBarViewBinder mCollapsedStatusBarViewBinder;
+    private FakeHomeStatusBarViewModel mCollapsedStatusBarViewModel;
+    private FakeHomeStatusBarViewBinder mCollapsedStatusBarViewBinder;
     @Mock
     private StatusBarHideIconsForBouncerManager mStatusBarHideIconsForBouncerManager;
     @Mock
@@ -1060,7 +1060,7 @@
     public void setUp_fragmentCreatesDaggerComponent() {
         CollapsedStatusBarFragment fragment = resumeAndGetFragment();
 
-        assertEquals(mStatusBarFragmentComponent, fragment.getStatusBarFragmentComponent());
+        assertEquals(mHomeStatusBarComponent, fragment.getHomeStatusBarComponent());
     }
 
     @Test
@@ -1190,8 +1190,8 @@
         mSecureSettings = mock(SecureSettings.class);
 
         mShadeExpansionStateManager = new ShadeExpansionStateManager();
-        mCollapsedStatusBarViewModel = new FakeCollapsedStatusBarViewModel();
-        mCollapsedStatusBarViewBinder = new FakeCollapsedStatusBarViewBinder();
+        mCollapsedStatusBarViewModel = new FakeHomeStatusBarViewModel();
+        mCollapsedStatusBarViewBinder = new FakeHomeStatusBarViewBinder();
 
         return new CollapsedStatusBarFragment(
                 mStatusBarFragmentComponentFactory,
@@ -1224,8 +1224,8 @@
 
     private void setUpDaggerComponent() {
         when(mStatusBarFragmentComponentFactory.create(any()))
-                .thenReturn(mStatusBarFragmentComponent);
-        when(mStatusBarFragmentComponent.getHeadsUpAppearanceController())
+                .thenReturn(mHomeStatusBarComponent);
+        when(mHomeStatusBarComponent.getHeadsUpAppearanceController())
                 .thenReturn(mHeadsUpAppearanceController);
     }
 
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/qs/panels/data/repository/QSColumnsRepositoryKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/qs/panels/data/repository/QSColumnsRepositoryKosmos.kt
index 0ca025f..742b79c 100644
--- a/packages/SystemUI/tests/utils/src/com/android/systemui/qs/panels/data/repository/QSColumnsRepositoryKosmos.kt
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/qs/panels/data/repository/QSColumnsRepositoryKosmos.kt
@@ -19,9 +19,6 @@
 import android.content.res.mainResources
 import com.android.systemui.common.ui.data.repository.configurationRepository
 import com.android.systemui.kosmos.Kosmos
-import com.android.systemui.kosmos.applicationCoroutineScope
 
-val Kosmos.qsColumnsRepository by
-    Kosmos.Fixture {
-        QSColumnsRepository(applicationCoroutineScope, mainResources, configurationRepository)
-    }
+var Kosmos.qsColumnsRepository by
+    Kosmos.Fixture { QSColumnsRepository(mainResources, configurationRepository) }
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/qs/panels/domain/interactor/QSColumnsInteractorKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/qs/panels/domain/interactor/QSColumnsInteractorKosmos.kt
index 02ed264..47615f5 100644
--- a/packages/SystemUI/tests/utils/src/com/android/systemui/qs/panels/domain/interactor/QSColumnsInteractorKosmos.kt
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/qs/panels/domain/interactor/QSColumnsInteractorKosmos.kt
@@ -17,6 +17,11 @@
 package com.android.systemui.qs.panels.domain.interactor
 
 import com.android.systemui.kosmos.Kosmos
+import com.android.systemui.kosmos.applicationCoroutineScope
 import com.android.systemui.qs.panels.data.repository.qsColumnsRepository
+import com.android.systemui.shade.domain.interactor.shadeInteractor
 
-val Kosmos.qsColumnsInteractor by Kosmos.Fixture { QSColumnsInteractor(qsColumnsRepository) }
+val Kosmos.qsColumnsInteractor by
+    Kosmos.Fixture {
+        QSColumnsInteractor(applicationCoroutineScope, qsColumnsRepository, shadeInteractor)
+    }
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/pipeline/shared/ui/viewmodel/CollapsedStatusBarViewModelKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/pipeline/shared/ui/viewmodel/HomeStatusBarViewModelKosmos.kt
similarity index 90%
rename from packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/pipeline/shared/ui/viewmodel/CollapsedStatusBarViewModelKosmos.kt
rename to packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/pipeline/shared/ui/viewmodel/HomeStatusBarViewModelKosmos.kt
index 1c7fd48..3a7ada2 100644
--- a/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/pipeline/shared/ui/viewmodel/CollapsedStatusBarViewModelKosmos.kt
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/pipeline/shared/ui/viewmodel/HomeStatusBarViewModelKosmos.kt
@@ -16,6 +16,7 @@
 
 package com.android.systemui.statusbar.pipeline.shared.ui.viewmodel
 
+import com.android.systemui.keyguard.domain.interactor.keyguardInteractor
 import com.android.systemui.keyguard.domain.interactor.keyguardTransitionInteractor
 import com.android.systemui.kosmos.Kosmos
 import com.android.systemui.kosmos.applicationCoroutineScope
@@ -27,13 +28,14 @@
 import com.android.systemui.statusbar.phone.domain.interactor.lightsOutInteractor
 import com.android.systemui.statusbar.pipeline.shared.domain.interactor.collapsedStatusBarInteractor
 
-val Kosmos.collapsedStatusBarViewModel: CollapsedStatusBarViewModel by
+val Kosmos.homeStatusBarViewModel: HomeStatusBarViewModel by
     Kosmos.Fixture {
-        CollapsedStatusBarViewModelImpl(
+        HomeStatusBarViewModelImpl(
             collapsedStatusBarInteractor,
             lightsOutInteractor,
             activeNotificationsInteractor,
             keyguardTransitionInteractor,
+            keyguardInteractor,
             sceneInteractor,
             sceneContainerOcclusionInteractor,
             shadeInteractor,
diff --git a/services/core/java/com/android/server/media/projection/MediaProjectionManagerService.java b/services/core/java/com/android/server/media/projection/MediaProjectionManagerService.java
index e7e519e..e0913cc 100644
--- a/services/core/java/com/android/server/media/projection/MediaProjectionManagerService.java
+++ b/services/core/java/com/android/server/media/projection/MediaProjectionManagerService.java
@@ -28,6 +28,7 @@
 import static android.media.projection.ReviewGrantedConsentResult.RECORD_CONTENT_DISPLAY;
 import static android.media.projection.ReviewGrantedConsentResult.RECORD_CONTENT_TASK;
 import static android.media.projection.ReviewGrantedConsentResult.UNKNOWN;
+import static android.provider.Settings.Global.DISABLE_SCREEN_SHARE_PROTECTIONS_FOR_APPS_AND_NOTIFICATIONS;
 import static android.view.Display.DEFAULT_DISPLAY;
 import static android.view.Display.INVALID_DISPLAY;
 
@@ -73,6 +74,7 @@
 import android.os.RemoteException;
 import android.os.SystemClock;
 import android.os.UserHandle;
+import android.provider.Settings;
 import android.util.ArrayMap;
 import android.util.Slog;
 import android.view.ContentRecordingSession;
@@ -195,6 +197,15 @@
             if (mProjectionGrant == null || mProjectionGrant.packageName == null) {
                 return false;
             }
+            boolean disableScreenShareProtections = Settings.Global.getInt(
+                    getContext().getContentResolver(),
+                    DISABLE_SCREEN_SHARE_PROTECTIONS_FOR_APPS_AND_NOTIFICATIONS, 0) != 0;
+            if (disableScreenShareProtections) {
+                Slog.v(TAG,
+                        "Allowing keyguard capture as screenshare protections are disabled.");
+                return true;
+            }
+
             if (mPackageManager.checkPermission(RECORD_SENSITIVE_CONTENT,
                     mProjectionGrant.packageName)
                     == PackageManager.PERMISSION_GRANTED) {
@@ -226,7 +237,8 @@
     void onKeyguardLockedStateChanged(boolean isKeyguardLocked) {
         if (!isKeyguardLocked) return;
         synchronized (mLock) {
-            if (mProjectionGrant != null && !canCaptureKeyguard()) {
+            if (mProjectionGrant != null && !canCaptureKeyguard()
+                    && mProjectionGrant.mVirtualDisplayId != INVALID_DISPLAY) {
                 Slog.d(TAG, "Content Recording: Stopped MediaProjection"
                         + " due to keyguard lock");
                 mProjectionGrant.stop();
diff --git a/services/tests/servicestests/src/com/android/server/media/projection/MediaProjectionManagerServiceTest.java b/services/tests/servicestests/src/com/android/server/media/projection/MediaProjectionManagerServiceTest.java
index 7e22d74..b1d658c 100644
--- a/services/tests/servicestests/src/com/android/server/media/projection/MediaProjectionManagerServiceTest.java
+++ b/services/tests/servicestests/src/com/android/server/media/projection/MediaProjectionManagerServiceTest.java
@@ -25,6 +25,7 @@
 import static android.media.projection.ReviewGrantedConsentResult.RECORD_CONTENT_DISPLAY;
 import static android.media.projection.ReviewGrantedConsentResult.RECORD_CONTENT_TASK;
 import static android.media.projection.ReviewGrantedConsentResult.UNKNOWN;
+import static android.provider.Settings.Global.DISABLE_SCREEN_SHARE_PROTECTIONS_FOR_APPS_AND_NOTIFICATIONS;
 import static android.view.ContentRecordingSession.TARGET_UID_FULL_SCREEN;
 import static android.view.ContentRecordingSession.TARGET_UID_UNKNOWN;
 import static android.view.ContentRecordingSession.createDisplaySession;
@@ -80,6 +81,7 @@
 import android.platform.test.annotations.EnableFlags;
 import android.platform.test.annotations.Presubmit;
 import android.platform.test.flag.junit.SetFlagsRule;
+import android.provider.Settings;
 import android.testing.TestableContext;
 import android.view.ContentRecordingSession;
 import android.view.ContentRecordingSession.RecordContent;
@@ -372,6 +374,50 @@
         });
     }
 
+    @EnableFlags(android.companion.virtualdevice.flags
+            .Flags.FLAG_MEDIA_PROJECTION_KEYGUARD_RESTRICTIONS)
+    @Test
+    public void testCreateProjection_keyguardLocked_screenshareProtectionsDisabled()
+            throws NameNotFoundException {
+        MediaProjectionManagerService.MediaProjection projection = startProjectionPreconditions();
+        int value = Settings.Global.getInt(mContext.getContentResolver(),
+                DISABLE_SCREEN_SHARE_PROTECTIONS_FOR_APPS_AND_NOTIFICATIONS, 0);
+        try {
+            Settings.Global.putInt(mContext.getContentResolver(),
+                    DISABLE_SCREEN_SHARE_PROTECTIONS_FOR_APPS_AND_NOTIFICATIONS, 1);
+            doReturn(true).when(mKeyguardManager).isKeyguardLocked();
+
+            doReturn(PackageManager.PERMISSION_DENIED).when(mPackageManager).checkPermission(
+                    RECORD_SENSITIVE_CONTENT, projection.packageName);
+
+            projection.start(mIMediaProjectionCallback);
+            projection.notifyVirtualDisplayCreated(10);
+
+            // The projection was started because it was allowed to capture the keyguard.
+            assertThat(mService.getActiveProjectionInfo()).isNotNull();
+        } finally {
+            Settings.Global.putInt(mContext.getContentResolver(),
+                    DISABLE_SCREEN_SHARE_PROTECTIONS_FOR_APPS_AND_NOTIFICATIONS, value);
+        }
+    }
+
+    @EnableFlags(android.companion.virtualdevice.flags
+            .Flags.FLAG_MEDIA_PROJECTION_KEYGUARD_RESTRICTIONS)
+    @Test
+    public void testCreateProjection_keyguardLocked_noDisplayCreated()
+            throws NameNotFoundException {
+        MediaProjectionManagerService.MediaProjection projection = startProjectionPreconditions();
+        doReturn(true).when(mKeyguardManager).isKeyguardLocked();
+
+        doReturn(PackageManager.PERMISSION_DENIED).when(mPackageManager).checkPermission(
+                RECORD_SENSITIVE_CONTENT, projection.packageName);
+
+        projection.start(mIMediaProjectionCallback);
+
+        // The projection was started because it was allowed to capture the keyguard.
+        assertThat(mService.getActiveProjectionInfo()).isNotNull();
+    }
+
     @Test
     public void testCreateProjection_attemptReuse_noPriorProjectionGrant()
             throws NameNotFoundException {
@@ -485,6 +531,7 @@
         MediaProjectionManagerService.MediaProjection projection =
                 startProjectionPreconditions(service);
         projection.start(mIMediaProjectionCallback);
+        projection.notifyVirtualDisplayCreated(10);
 
         assertThat(service.getActiveProjectionInfo()).isNotNull();
 
@@ -507,6 +554,7 @@
         MediaProjectionManagerService.MediaProjection projection =
                 startProjectionPreconditions(service);
         projection.start(mIMediaProjectionCallback);
+        projection.notifyVirtualDisplayCreated(10);
 
         assertThat(service.getActiveProjectionInfo()).isNotNull();
 
diff --git a/tests/BootImageProfileTest/Android.bp b/tests/BootImageProfileTest/Android.bp
index 9fb5aa2..dbdc4b4 100644
--- a/tests/BootImageProfileTest/Android.bp
+++ b/tests/BootImageProfileTest/Android.bp
@@ -19,6 +19,7 @@
     // to get the below license kinds:
     //   SPDX-license-identifier-Apache-2.0
     default_applicable_licenses: ["frameworks_base_license"],
+    default_team: "trendy_team_art_mainline",
 }
 
 java_test_host {
diff --git a/tests/Tracing/src/com/android/internal/protolog/ProtoLogViewerConfigReaderTest.java b/tests/Tracing/src/com/android/internal/protolog/ProtoLogViewerConfigReaderTest.java
index 28d7b42..d78ced1 100644
--- a/tests/Tracing/src/com/android/internal/protolog/ProtoLogViewerConfigReaderTest.java
+++ b/tests/Tracing/src/com/android/internal/protolog/ProtoLogViewerConfigReaderTest.java
@@ -121,4 +121,12 @@
         assertNull(mConfig.getViewerString(4));
         assertNull(mConfig.getViewerString(5));
     }
+
+    @Test
+    public void loadUnloadAndReloadViewerConfig() {
+        loadViewerConfig();
+        unloadViewerConfig();
+        loadViewerConfig();
+        unloadViewerConfig();
+    }
 }