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();
+ }
}