Merge "Do not call credential if authenticators does not allow" into main
diff --git a/res/drawable/battery_tips_all_rounded_bg.xml b/res/drawable/battery_tips_all_rounded_bg.xml
deleted file mode 100644
index ba164b9..0000000
--- a/res/drawable/battery_tips_all_rounded_bg.xml
+++ /dev/null
@@ -1,22 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-  Copyright (C) 2023 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.
-  -->
-
-<shape xmlns:android="http://schemas.android.com/apk/res/android"
-    android:shape="rectangle">
-    <solid android:color="@color/settingslib_materialColorSurfaceBright" />
-    <corners android:radius="@dimen/battery_tips_card_corner_radius_normal" />
-</shape>
\ No newline at end of file
diff --git a/res/drawable/battery_tips_all_rounded_bg_ripple.xml b/res/drawable/battery_tips_all_rounded_bg_ripple.xml
deleted file mode 100644
index 3180570..0000000
--- a/res/drawable/battery_tips_all_rounded_bg_ripple.xml
+++ /dev/null
@@ -1,21 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-  Copyright (C) 2023 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.
-  -->
-
-<ripple xmlns:android="http://schemas.android.com/apk/res/android"
-    android:color="?android:attr/colorControlHighlight">
-    <item android:drawable="@drawable/battery_tips_all_rounded_bg"/>
-</ripple>
\ No newline at end of file
diff --git a/res/drawable/battery_tips_half_rounded_bottom_bg.xml b/res/drawable/battery_tips_half_rounded_bottom_bg.xml
deleted file mode 100644
index 7766de6..0000000
--- a/res/drawable/battery_tips_half_rounded_bottom_bg.xml
+++ /dev/null
@@ -1,27 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-  Copyright (C) 2023 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.
-  -->
-
-<shape xmlns:android="http://schemas.android.com/apk/res/android"
-    android:shape="rectangle">
-    <solid android:color="@color/settingslib_dialog_background"/>
-    <corners
-        android:topLeftRadius="@dimen/battery_tips_card_corner_radius_small"
-        android:topRightRadius="@dimen/battery_tips_card_corner_radius_small"
-        android:bottomLeftRadius="@dimen/battery_tips_card_corner_radius_normal"
-        android:bottomRightRadius="@dimen/battery_tips_card_corner_radius_normal"
-        />
-</shape>
\ No newline at end of file
diff --git a/res/drawable/battery_tips_half_rounded_top_bg.xml b/res/drawable/battery_tips_half_rounded_top_bg.xml
deleted file mode 100644
index aba1a4f..0000000
--- a/res/drawable/battery_tips_half_rounded_top_bg.xml
+++ /dev/null
@@ -1,27 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-  Copyright (C) 2023 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.
-  -->
-
-<shape xmlns:android="http://schemas.android.com/apk/res/android"
-    android:shape="rectangle">
-    <solid android:color="@color/settingslib_dialog_background"/>
-    <corners
-        android:topLeftRadius="@dimen/battery_tips_card_corner_radius_normal"
-        android:topRightRadius="@dimen/battery_tips_card_corner_radius_normal"
-        android:bottomLeftRadius="@dimen/battery_tips_card_corner_radius_small"
-        android:bottomRightRadius="@dimen/battery_tips_card_corner_radius_small"
-        />
-</shape>
\ No newline at end of file
diff --git a/res/layout-land/bluetooth_audio_streams_qr_code.xml b/res/layout-land/bluetooth_audio_streams_qr_code.xml
index 1715197..432d75e 100644
--- a/res/layout-land/bluetooth_audio_streams_qr_code.xml
+++ b/res/layout-land/bluetooth_audio_streams_qr_code.xml
@@ -15,48 +15,48 @@
   ~ limitations under the License.
   -->
 
-<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+<androidx.core.widget.NestedScrollView
+    xmlns:android="http://schemas.android.com/apk/res/android"
     android:layout_width="match_parent"
-    android:layout_height="match_parent"
-    android:orientation="horizontal"
-    android:padding="25dp"
-    android:baselineAligned="false">
+    android:layout_height="wrap_content">
 
-    <LinearLayout
-        android:layout_width="0dp"
-        android:layout_height="match_parent"
-        android:layout_weight="1"
-        android:orientation="vertical">
-
-        <TextView
-            android:id="@android:id/summary"
+        <LinearLayout
             android:layout_width="match_parent"
-            android:layout_height="wrap_content"
-            android:gravity="start"
-            android:textSize="15sp"
-            android:textColor="?android:attr/textColorPrimary" />
+            android:layout_height="match_parent"
+            android:orientation="horizontal"
+            android:padding="25dp"
+            android:gravity="center">
+
+            <TextView
+                android:id="@android:id/summary"
+                android:layout_width="0dp"
+                android:layout_height="wrap_content"
+                android:layout_weight="1"
+                android:gravity="start"
+                android:textSize="15sp"
+                android:textColor="?android:attr/textColorPrimary"/>
+
+            <LinearLayout
+                android:layout_width="0dp"
+                android:layout_height="wrap_content"
+                android:orientation="vertical"
+                android:layout_weight="1"
+                android:gravity="center">
+
+                <ImageView
+                    android:id="@+id/qrcode_view"
+                    android:layout_width="@dimen/qrcode_size"
+                    android:layout_height="@dimen/qrcode_size"
+                    android:contentDescription="@string/qr_code_content_description"
+                    android:focusable="true" />
+
+                <TextView
+                    android:id="@+id/password"
+                    android:layout_width="wrap_content"
+                    android:layout_height="wrap_content"
+                    android:textSize="15sp"
+                    android:textColor="?android:attr/textColorPrimary"
+                    android:gravity="center" />
+            </LinearLayout>
     </LinearLayout>
-
-    <LinearLayout
-        android:layout_width="0dp"
-        android:layout_height="wrap_content"
-        android:layout_weight="1"
-        android:gravity="center"
-        android:orientation="vertical">
-
-        <ImageView
-            android:id="@+id/qrcode_view"
-            android:layout_width="@dimen/qrcode_size"
-            android:layout_height="@dimen/qrcode_size"
-            android:contentDescription="@string/qr_code_content_description"
-            android:focusable="true" />
-
-        <TextView
-            android:id="@+id/password"
-            android:layout_width="wrap_content"
-            android:layout_height="wrap_content"
-            android:textSize="15sp"
-            android:textColor="?android:attr/textColorPrimary" />
-    </LinearLayout>
-
-</LinearLayout>
+</androidx.core.widget.NestedScrollView>
\ No newline at end of file
diff --git a/res/layout-land/qrcode_scanner_fragment.xml b/res/layout-land/qrcode_scanner_fragment.xml
index 0e563e3..daad35d 100644
--- a/res/layout-land/qrcode_scanner_fragment.xml
+++ b/res/layout-land/qrcode_scanner_fragment.xml
@@ -15,60 +15,45 @@
      limitations under the License.
 -->
 
-<LinearLayout
+<androidx.core.widget.NestedScrollView
     xmlns:android="http://schemas.android.com/apk/res/android"
     android:layout_width="match_parent"
-    android:layout_height="match_parent"
-    android:orientation="horizontal">
+    android:layout_height="wrap_content">
 
     <LinearLayout
-        android:layout_width="0dp"
+        android:layout_width="match_parent"
         android:layout_height="match_parent"
-        android:layout_weight="1"
-        android:orientation="vertical">
-            <TextView
-                android:id="@android:id/summary"
-                style="@style/QrCodeScanner"
-                android:gravity="center"
-                android:layout_width="match_parent"
-                android:layout_height="wrap_content"/>
-        </LinearLayout>
-
-    <LinearLayout
-        android:layout_width="0dp"
-        android:layout_height="wrap_content"
-        android:layout_weight="1"
-        android:gravity="center"
-        android:orientation="vertical">
-
-        <FrameLayout
-            android:layout_width="wrap_content"
-            android:layout_height="wrap_content"
-            android:layout_gravity="top"
-            android:gravity="center"
-            android:clipChildren="true"
-            android:contentDescription="@string/audio_streams_qr_code_scanner_label"
-            android:focusable="true">
-            <TextureView
-                android:id="@+id/preview_view"
-                android:layout_marginStart="@dimen/qrcode_preview_margin"
-                android:layout_marginEnd="@dimen/qrcode_preview_margin"
-                android:layout_width="match_parent"
-                android:layout_height="@dimen/qrcode_preview_size"/>
-        </FrameLayout>
+        android:orientation="horizontal"
+        android:paddingTop="@dimen/audio_streams_qrcode_scanner_fragment_padding">
 
         <TextView
-            android:id="@+id/error_message"
-            style="@style/TextAppearance.ErrorText"
-            android:layout_width="wrap_content"
+            android:id="@android:id/summary"
+            style="@style/QrCodeScanner"
+            android:layout_width="0dp"
+            android:layout_height="match_parent"
+            android:layout_weight="1"
+            android:gravity="center" />
+
+        <LinearLayout
+            android:layout_width="0dp"
             android:layout_height="wrap_content"
-            android:layout_marginTop="16dp"
-            android:gravity="center"
-            android:layout_gravity="center"
-            android:visibility="invisible"/>
+            android:orientation="vertical"
+            android:layout_weight="1"
+            android:gravity="center">
+            <TextureView
+                android:id="@+id/preview_view"
+                android:layout_width="@dimen/audio_streams_qrcode_preview_size"
+                android:layout_height="@dimen/audio_streams_qrcode_preview_size"
+                android:contentDescription="@string/audio_streams_qr_code_scanner_label"
+                android:focusable="true" />
+            <TextView
+                android:id="@+id/error_message"
+                style="@style/TextAppearance.ErrorText"
+                android:layout_width="match_parent"
+                android:layout_height="wrap_content"
+                android:visibility="gone"/>
+        </LinearLayout>
 
     </LinearLayout>
 
-
-</LinearLayout>
-
+</androidx.core.widget.NestedScrollView>
diff --git a/res/layout/battery_tips_card.xml b/res/layout/battery_tips_card.xml
deleted file mode 100644
index 18c326f..0000000
--- a/res/layout/battery_tips_card.xml
+++ /dev/null
@@ -1,61 +0,0 @@
-<LinearLayout
-    xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:app="http://schemas.android.com/apk/res-auto"
-    android:id="@+id/battery_tips_card"
-    android:layout_width="match_parent"
-    android:layout_height="wrap_content"
-    android:layout_marginStart="?android:attr/listPreferredItemPaddingStart"
-    android:layout_marginEnd="?android:attr/listPreferredItemPaddingEnd"
-    android:background="@drawable/battery_tips_all_rounded_bg_ripple"
-    android:orientation="vertical"
-    android:padding="20dp">
-
-    <ImageView
-        android:id="@+id/icon"
-        android:layout_width="wrap_content"
-        android:layout_height="wrap_content"
-        android:layout_gravity="center_vertical|start"
-        android:contentDescription="@string/battery_usage_anomaly_content_description"
-        android:src="@drawable/ic_battery_tips_lightbulb" />
-
-    <TextView
-        android:id="@+id/title"
-        android:layout_width="match_parent"
-        android:layout_height="wrap_content"
-        android:layout_marginTop="8dp"
-        android:textAlignment="viewStart"
-        android:textAppearance="@style/TextAppearance.Material3.TitleMedium"
-        android:textColor="@color/settingslib_materialColorOnSurface" />
-
-    <LinearLayout
-        android:layout_width="match_parent"
-        android:layout_height="wrap_content"
-        android:layout_marginTop="8dp"
-        android:gravity="end"
-        android:orientation="horizontal">
-
-        <com.google.android.material.button.MaterialButton
-            android:id="@+id/dismiss_button"
-            style="@style/Widget.Material3.Button.TextButton"
-            android:layout_width="wrap_content"
-            android:layout_height="wrap_content"
-            android:layout_gravity="end|center_vertical"
-            android:layout_marginEnd="8dp"
-            android:paddingHorizontal="16dp"
-            android:text="@string/battery_tips_card_dismiss_button"
-            android:textAppearance="@style/TextAppearance.MaterialComponents.Subtitle2"
-            android:textColor="@color/color_accent_selector" />
-
-        <com.google.android.material.button.MaterialButton
-            android:id="@+id/main_button"
-            style="@style/Widget.Material3.Button"
-            android:layout_width="wrap_content"
-            android:layout_height="wrap_content"
-            android:layout_gravity="end|center_vertical"
-            android:paddingHorizontal="16dp"
-            android:text="@string/battery_tips_card_action_button"
-            android:textAppearance="@style/TextAppearance.MaterialComponents.Subtitle2"
-            android:textColor="@color/settingslib_materialColorOnPrimary"
-            app:backgroundTint="@color/color_accent_selector" />
-    </LinearLayout>
-</LinearLayout>
\ No newline at end of file
diff --git a/res/layout/bluetooth_audio_streams_qr_code.xml b/res/layout/bluetooth_audio_streams_qr_code.xml
index ae2d4e0..ab61f50 100644
--- a/res/layout/bluetooth_audio_streams_qr_code.xml
+++ b/res/layout/bluetooth_audio_streams_qr_code.xml
@@ -15,7 +15,7 @@
   ~ limitations under the License.
   -->
 
-<LinearLayout
+<androidx.core.widget.NestedScrollView
     xmlns:android="http://schemas.android.com/apk/res/android"
     android:layout_width="match_parent"
     android:layout_height="match_parent">
@@ -23,10 +23,9 @@
     <LinearLayout
         android:layout_width="match_parent"
         android:layout_height="match_parent"
-        android:clipToPadding="false"
         android:paddingLeft="25dp"
         android:paddingRight="25dp"
-        android:gravity="center_horizontal"
+        android:gravity="center"
         android:orientation="vertical">
 
         <TextView
@@ -35,30 +34,24 @@
             android:layout_height="wrap_content"
             android:gravity="start"
             android:textSize="15sp"
-            android:textColor="?android:attr/textColorPrimary"/>
+            android:textColor="?android:attr/textColorPrimary" />
 
-        <LinearLayout
-            android:layout_width="match_parent"
+        <ImageView
+            android:id="@+id/qrcode_view"
+            android:layout_width="@dimen/qrcode_size"
+            android:layout_height="@dimen/qrcode_size"
+            android:contentDescription="@string/qr_code_content_description"
+            android:focusable="true"
+            android:paddingTop="70dp"/>
+
+        <TextView
+            android:id="@+id/password"
+            android:layout_width="wrap_content"
             android:layout_height="wrap_content"
-            android:gravity="center"
-            android:orientation="vertical"
-            android:paddingTop="70dp">
-
-            <ImageView
-                android:id="@+id/qrcode_view"
-                android:layout_width="@dimen/qrcode_size"
-                android:layout_height="@dimen/qrcode_size"
-                android:contentDescription="@string/qr_code_content_description"
-                android:focusable="true"/>
-
-            <TextView
-                android:id="@+id/password"
-                android:layout_width="wrap_content"
-                android:layout_height="wrap_content"
-                android:textSize="15sp"
-                android:textColor="?android:attr/textColorPrimary"/>
-        </LinearLayout>
+            android:textSize="15sp"
+            android:textColor="?android:attr/textColorPrimary"
+            android:gravity="center" />
 
     </LinearLayout>
 
-</LinearLayout>
\ No newline at end of file
+</androidx.core.widget.NestedScrollView>
\ No newline at end of file
diff --git a/res/layout/preference_background.xml b/res/layout/preference_background.xml
index 129076a..51718b8 100644
--- a/res/layout/preference_background.xml
+++ b/res/layout/preference_background.xml
@@ -17,6 +17,7 @@
   -->
 
 <FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:androidprv="http://schemas.android.com/apk/prv/res/android"
     xmlns:app="http://schemas.android.com/apk/res-auto"
     android:layout_height="wrap_content"
     android:layout_width="match_parent"
@@ -64,7 +65,7 @@
                 android:layout_height="wrap_content"
                 android:singleLine="true"
                 android:textAppearance="?android:attr/textAppearanceListItem"
-                android:textColor="?android:attr/textColorPrimary"
+                android:textColor="?androidprv:attr/materialColorOnPrimaryContainer"
                 android:ellipsize="marquee"
                 android:fadingEdge="horizontal"
                 android:hyphenationFrequency="normalFast"
@@ -77,7 +78,7 @@
                 android:layout_alignStart="@android:id/title"
                 android:layout_alignLeft="@android:id/title"
                 android:textAppearance="?android:attr/textAppearanceSmall"
-                android:textColor="?android:attr/textColorSecondary"
+                android:textColor="?androidprv:attr/materialColorOnPrimaryContainer"
                 android:hyphenationFrequency="normalFast"
                 android:lineBreakWordStyle="phrase"
                 android:maxLines="4"
diff --git a/res/layout/preference_widget_arrow.xml b/res/layout/preference_widget_arrow.xml
index e7a3f82..f36f693 100644
--- a/res/layout/preference_widget_arrow.xml
+++ b/res/layout/preference_widget_arrow.xml
@@ -17,10 +17,11 @@
 
 <ImageView
     xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:androidprv="http://schemas.android.com/apk/prv/res/android"
     android:layout_width="match_parent"
     android:layout_height="match_parent"
     android:layout_gravity="center_vertical"
     android:contentDescription="@null"
     android:scaleType="center"
-    android:tint="?android:attr/textColorPrimary"
+    android:tint="?androidprv:attr/materialColorOnPrimaryContainer"
     android:src="@drawable/ic_arrow_forward" />
\ No newline at end of file
diff --git a/res/layout/qrcode_scanner_fragment.xml b/res/layout/qrcode_scanner_fragment.xml
index 72049a4..1526cf8 100644
--- a/res/layout/qrcode_scanner_fragment.xml
+++ b/res/layout/qrcode_scanner_fragment.xml
@@ -15,69 +15,41 @@
      limitations under the License.
 -->
 
-<LinearLayout
+<androidx.core.widget.NestedScrollView
     xmlns:android="http://schemas.android.com/apk/res/android"
     android:layout_width="match_parent"
-    android:layout_height="match_parent"
-    android:orientation="vertical">
+    android:layout_height="wrap_content">
 
     <LinearLayout
         android:layout_width="match_parent"
         android:layout_height="wrap_content"
-        android:layout_weight="3"
-        android:layout_marginBottom="55dp">
-        <LinearLayout
+        android:orientation="vertical"
+        android:gravity="center"
+        android:layout_margin="20dp">
+
+        <TextView
+            android:id="@android:id/summary"
+            style="@style/QrCodeScanner"
+            android:gravity="center"
             android:layout_width="match_parent"
             android:layout_height="wrap_content"
-            android:paddingStart="40dp"
-            android:paddingEnd="40dp"
-            android:layout_gravity="bottom"
-            android:gravity="center"
-            android:orientation="vertical">
-            <TextView
-                android:id="@android:id/summary"
-                style="@style/QrCodeScanner"
-                android:gravity="center"
-                android:layout_width="match_parent"
-                android:layout_height="wrap_content"
-                android:layout_marginTop="20dp"/>
-        </LinearLayout>
-    </LinearLayout>
+            android:layout_margin="40dp" />
 
-    <LinearLayout
-        android:layout_width="match_parent"
-        android:layout_height="wrap_content"
-        android:layout_weight="7"
-        android:orientation="vertical">
-
-        <FrameLayout
-            android:layout_width="wrap_content"
-            android:layout_height="wrap_content"
-            android:layout_gravity="top"
-            android:gravity="center"
-            android:clipChildren="true"
+        <TextureView
+            android:id="@+id/preview_view"
+            android:layout_width="@dimen/audio_streams_qrcode_preview_size"
+            android:layout_height="@dimen/audio_streams_qrcode_preview_size"
             android:contentDescription="@string/audio_streams_qr_code_scanner_label"
-            android:focusable="true">
-            <TextureView
-                android:id="@+id/preview_view"
-                android:layout_marginStart="@dimen/qrcode_preview_margin"
-                android:layout_marginEnd="@dimen/qrcode_preview_margin"
-                android:layout_width="match_parent"
-                android:layout_height="@dimen/qrcode_preview_size"/>
-        </FrameLayout>
+            android:focusable="true" />
 
         <TextView
             android:id="@+id/error_message"
             style="@style/TextAppearance.ErrorText"
-            android:layout_width="wrap_content"
+            android:layout_width="match_parent"
             android:layout_height="wrap_content"
-            android:layout_marginTop="16dp"
             android:gravity="center"
-            android:layout_gravity="center"
-            android:visibility="invisible"/>
-
+            android:visibility="gone"/>
     </LinearLayout>
 
-
-</LinearLayout>
+</androidx.core.widget.NestedScrollView>
 
diff --git a/res/values/arrays.xml b/res/values/arrays.xml
index a24dc86..598ec3e 100644
--- a/res/values/arrays.xml
+++ b/res/values/arrays.xml
@@ -1555,26 +1555,26 @@
     <!-- Descriptions of the icons in zen_mode_icon_options. Should describe the associated image
          [CHAR LIMIT=NONE] -->
     <string-array name="zen_mode_icon_options_descriptions">
-        <item>Bedtime</item>
-        <item>Driving</item>
-        <item>Immersive</item>
+        <item>Half-moon</item>
+        <item>Car</item>
+        <item>Person\'s mind</item>
         <item>Calendar</item>
-        <item>Time</item>
-        <item>Beach</item>
-        <item>Camping</item>
-        <item>Theater</item>
-        <item>Gaming</item>
-        <item>Gym</item>
-        <item>Ball sports</item>
-        <item>Martial arts</item>
+        <item>Clock</item>
+        <item>Beach umbrella</item>
+        <item>Tent</item>
+        <item>Film reel</item>
+        <item>Game controller</item>
+        <item>Gym dumbbell</item>
+        <item>Person throwing ball</item>
+        <item>Person kicking</item>
         <item>Swimming</item>
-        <item>Hiking</item>
+        <item>Person hiking</item>
         <item>Golf</item>
-        <item>Workshop</item>
-        <item>Work</item>
+        <item>Workshop tools</item>
+        <item>Briefcase</item>
         <item>Star</item>
-        <item>Zen</item>
-        <item>Managed</item>
+        <item>Lotus flower</item>
+        <item>Supervisor</item>
     </string-array>
 
     <!-- Packages that will not show Display over other apps permission -->
diff --git a/res/values/dimens.xml b/res/values/dimens.xml
index b1dabe8..2024a45 100755
--- a/res/values/dimens.xml
+++ b/res/values/dimens.xml
@@ -500,7 +500,9 @@
     <dimen name="contrast_button_horizontal_spacing">16dp</dimen>
 
     <dimen name="audio_streams_qrcode_size">264dp</dimen>
+    <dimen name="audio_streams_qrcode_preview_size">300dp</dimen>
     <dimen name="audio_streams_qrcode_preview_radius">30dp</dimen>
+    <dimen name="audio_streams_qrcode_scanner_fragment_padding">16dp</dimen>
 
     <!-- Zen Modes -->
     <dimen name="zen_mode_header_size">136dp</dimen>
diff --git a/res/values/strings.xml b/res/values/strings.xml
index dc986ad..1d60218 100644
--- a/res/values/strings.xml
+++ b/res/values/strings.xml
@@ -409,7 +409,7 @@
     <string name="desc_app_locale_selection_supported">Set the language for each app.</string>
 
     <!-- Description for the introduction to language picker activity. [CHAR LIMIT=NONE]-->
-    <string name="desc_introduction_of_language_picker">Your system, apps, and websites use the first supported language from your preferred languages.</string>
+    <string name="desc_introduction_of_language_picker">Your device, apps, and websites use the first supported language from your preferred language list.\n\nMany apps will also use the region from your preferred language to format dates, numbers, and units. To change your region, add a language, then choose your preferred region.</string>
 
     <!-- Description for the notice of language picker. [CHAR LIMIT=NONE]-->
     <string name="desc_notice_of_language_picker">To select a language for each app, go to app language settings.</string>
@@ -7984,6 +7984,26 @@
     <!-- Priority Modes: Option to choose a calendar-events-based schedule for a mode. [CHAR_LIMIT=40] -->
     <string name="zen_mode_select_schedule_calendar">Calendar events</string>
 
+    <!-- Priority Modes: Summary for the modes segment, when at least one mode is active. [CHAR LIMIT=NONE]-->
+    <string name="zen_modes_summary_some_active">
+        {count, plural, offset:2
+            =0    {}
+            =1    {{mode_1} is active}
+            =2    {{mode_1} and {mode_2} are active}
+            =3    {{mode_1}, {mode_2}, and {mode_3} are active}
+            other {{mode_1}, {mode_2}, and # more are active}
+        }
+    </string>
+
+    <!-- Priority Modes: Summary for the modes segment, when no modes are active. [CHAR LIMIT=NONE]-->
+    <string name="zen_modes_summary_none_active">
+        {count, plural,
+            =0    {}
+            =1    {1 mode can turn on automatically}
+            other {# modes can turn on automatically}
+        }
+    </string>
+
     <!-- Priority Modes: Short text that indicates that a mode is currently on (active). [CHAR_LIMIT=10] -->
     <string name="zen_mode_active_text">ON</string>
 
@@ -13460,7 +13480,7 @@
     <!-- Label of the color option show in the summary of screen flash preference. [CHAR LIMIT=60] -->
     <string name="screen_flash_color_violet">Violet</string>
     <!-- Button to save the selection in screen flash color selection dialog. [CHAR LIMIT=20] -->
-    <string name="color_selector_dialog_done">Done</string>
+    <string name="color_selector_dialog_save">Save</string>
     <!-- Button to close the dialog without saving in screen flash color selection dialog. [CHAR LIMIT=20] -->
     <string name="color_selector_dialog_cancel">Cancel</string>
 
diff --git a/res/xml/power_usage_advanced.xml b/res/xml/power_usage_advanced.xml
index c129453..f0104e5 100644
--- a/res/xml/power_usage_advanced.xml
+++ b/res/xml/power_usage_advanced.xml
@@ -27,7 +27,7 @@
             "com.android.settings.fuelgauge.batteryusage.BatteryTipsController"
         settings:isPreferenceVisible="false">
 
-        <com.android.settings.fuelgauge.batteryusage.BatteryTipsCardPreference
+        <com.android.settings.widget.TipCardPreference
             android:key="battery_tips_card"
             settings:isPreferenceVisible="false" />
 
diff --git a/res/xml/sound_settings.xml b/res/xml/sound_settings.xml
index 15312c8..393009e 100644
--- a/res/xml/sound_settings.xml
+++ b/res/xml/sound_settings.xml
@@ -105,6 +105,14 @@
         settings:keywords="@string/keywords_sounds_and_notifications_interruptions"
         settings:controller="com.android.settings.notification.zen.ZenModePreferenceController"/>
 
+    <com.android.settingslib.RestrictedPreference
+        android:key="modes_notifications"
+        android:order="-130"
+        android:title="@string/zen_modes_list_title"
+        settings:useAdminDisabledSummary="true"
+        android:fragment="com.android.settings.notification.modes.ZenModesListFragment"
+        settings:controller="com.android.settings.notification.modes.ZenModesLinkPreferenceController"/>
+
     <!-- Phone ringtone -->
     <com.android.settings.DefaultRingtonePreference
         android:key="phone_ringtone"
diff --git a/src/com/android/settings/accessibility/FlashNotificationsPreviewPreferenceController.java b/src/com/android/settings/accessibility/FlashNotificationsPreviewPreferenceController.java
index ae1adfa..fe69b2b 100644
--- a/src/com/android/settings/accessibility/FlashNotificationsPreviewPreferenceController.java
+++ b/src/com/android/settings/accessibility/FlashNotificationsPreviewPreferenceController.java
@@ -110,7 +110,7 @@
         if (preference == null) {
             return;
         }
-        preference.setEnabled(FlashNotificationsUtil.getFlashNotificationsState(mContext)
+        preference.setVisible(FlashNotificationsUtil.getFlashNotificationsState(mContext)
                 != FlashNotificationsUtil.State.OFF);
     }
 }
diff --git a/src/com/android/settings/accessibility/ScreenFlashNotificationColorDialogFragment.java b/src/com/android/settings/accessibility/ScreenFlashNotificationColorDialogFragment.java
index ca77f16..5094154 100644
--- a/src/com/android/settings/accessibility/ScreenFlashNotificationColorDialogFragment.java
+++ b/src/com/android/settings/accessibility/ScreenFlashNotificationColorDialogFragment.java
@@ -65,8 +65,7 @@
         final ScreenFlashNotificationColorDialogFragment result =
                 new ScreenFlashNotificationColorDialogFragment();
         result.mCurrentColor = initialColor;
-        result.mConsumer = colorConsumer != null ? colorConsumer : i -> {
-        };
+        result.mConsumer = colorConsumer != null ? colorConsumer : i -> {};
         return result;
     }
 
@@ -89,7 +88,7 @@
                 .setNeutralButton(R.string.flash_notifications_preview, null)
                 .setNegativeButton(R.string.color_selector_dialog_cancel, (dialog, which) -> {
                 })
-                .setPositiveButton(R.string.color_selector_dialog_done, (dialog, which) -> {
+                .setPositiveButton(R.string.color_selector_dialog_save, (dialog, which) -> {
                     mCurrentColor = colorSelectorLayout.getCheckedColor(DEFAULT_SCREEN_FLASH_COLOR);
                     mConsumer.accept(mCurrentColor);
                 })
diff --git a/src/com/android/settings/bluetooth/BluetoothDetailsHeaderController.java b/src/com/android/settings/bluetooth/BluetoothDetailsHeaderController.java
index 5ffa8cf..462f422 100644
--- a/src/com/android/settings/bluetooth/BluetoothDetailsHeaderController.java
+++ b/src/com/android/settings/bluetooth/BluetoothDetailsHeaderController.java
@@ -47,7 +47,7 @@
 
     @Override
     public boolean isAvailable() {
-        boolean hasLeAudio = mCachedDevice.getConnectableProfiles()
+        boolean hasLeAudio = mCachedDevice.getUiAccessibleProfiles()
                 .stream()
                 .anyMatch(profile -> profile.getProfileId() == BluetoothProfile.LE_AUDIO);
         return !BluetoothUtils.isAdvancedDetailsHeader(mCachedDevice.getDevice()) && !hasLeAudio;
diff --git a/src/com/android/settings/bluetooth/BluetoothDetailsProfilesController.java b/src/com/android/settings/bluetooth/BluetoothDetailsProfilesController.java
index 50c908d..2b74684 100644
--- a/src/com/android/settings/bluetooth/BluetoothDetailsProfilesController.java
+++ b/src/com/android/settings/bluetooth/BluetoothDetailsProfilesController.java
@@ -314,7 +314,7 @@
             return result;
         }
         for (CachedBluetoothDevice cachedItem : mAllOfCachedDevices) {
-            List<LocalBluetoothProfile> tmpResult = cachedItem.getConnectableProfiles();
+            List<LocalBluetoothProfile> tmpResult = cachedItem.getUiAccessibleProfiles();
             for (LocalBluetoothProfile profile : tmpResult) {
                 if (mProfileDeviceMap.containsKey(profile.toString())) {
                     mProfileDeviceMap.get(profile.toString()).add(cachedItem);
diff --git a/src/com/android/settings/bluetooth/LeAudioBluetoothDetailsHeaderController.java b/src/com/android/settings/bluetooth/LeAudioBluetoothDetailsHeaderController.java
index a64874d..4be4d63 100644
--- a/src/com/android/settings/bluetooth/LeAudioBluetoothDetailsHeaderController.java
+++ b/src/com/android/settings/bluetooth/LeAudioBluetoothDetailsHeaderController.java
@@ -107,7 +107,7 @@
         if (mCachedDevice == null || mProfileManager == null) {
             return CONDITIONALLY_UNAVAILABLE;
         }
-        boolean hasLeAudio = mCachedDevice.getConnectableProfiles()
+        boolean hasLeAudio = mCachedDevice.getUiAccessibleProfiles()
                 .stream()
                 .anyMatch(profile -> profile.getProfileId() == BluetoothProfile.LE_AUDIO);
 
diff --git a/src/com/android/settings/connecteddevice/audiosharing/AudioSharingDevicePreferenceController.java b/src/com/android/settings/connecteddevice/audiosharing/AudioSharingDevicePreferenceController.java
index a0c0b44..d6ad4bc 100644
--- a/src/com/android/settings/connecteddevice/audiosharing/AudioSharingDevicePreferenceController.java
+++ b/src/com/android/settings/connecteddevice/audiosharing/AudioSharingDevicePreferenceController.java
@@ -437,7 +437,7 @@
     }
 
     private boolean isMediaDevice(CachedBluetoothDevice cachedDevice) {
-        return cachedDevice.getConnectableProfiles().stream()
+        return cachedDevice.getUiAccessibleProfiles().stream()
                 .anyMatch(
                         profile ->
                                 profile instanceof A2dpProfile
diff --git a/src/com/android/settings/connecteddevice/audiosharing/AudioSharingDeviceVolumeControlUpdater.java b/src/com/android/settings/connecteddevice/audiosharing/AudioSharingDeviceVolumeControlUpdater.java
index 2e93539..548d17c 100644
--- a/src/com/android/settings/connecteddevice/audiosharing/AudioSharingDeviceVolumeControlUpdater.java
+++ b/src/com/android/settings/connecteddevice/audiosharing/AudioSharingDeviceVolumeControlUpdater.java
@@ -16,13 +16,9 @@
 
 package com.android.settings.connecteddevice.audiosharing;
 
-import android.app.settings.SettingsEnums;
-import android.bluetooth.BluetoothCsipSetCoordinator;
 import android.bluetooth.BluetoothDevice;
 import android.content.Context;
-import android.media.AudioManager;
 import android.util.Log;
-import android.widget.SeekBar;
 
 import androidx.annotation.Nullable;
 import androidx.annotation.VisibleForTesting;
@@ -40,7 +36,7 @@
 public class AudioSharingDeviceVolumeControlUpdater extends BluetoothDeviceUpdater
         implements Preference.OnPreferenceClickListener {
 
-    private static final String TAG = "AudioSharingDeviceVolumeControlUpdater";
+    private static final String TAG = "AudioSharingVolUpdater";
 
     @VisibleForTesting
     static final String PREF_KEY_PREFIX = "audio_sharing_volume_control_";
@@ -91,36 +87,9 @@
         if (cachedDevice == null) return;
         final BluetoothDevice device = cachedDevice.getDevice();
         if (!mPreferenceMap.containsKey(device)) {
-            SeekBar.OnSeekBarChangeListener listener =
-                    new SeekBar.OnSeekBarChangeListener() {
-                        @Override
-                        public void onProgressChanged(
-                                SeekBar seekBar, int progress, boolean fromUser) {}
-
-                        @Override
-                        public void onStartTrackingTouch(SeekBar seekBar) {}
-
-                        @Override
-                        public void onStopTrackingTouch(SeekBar seekBar) {
-                            int progress = seekBar.getProgress();
-                            int groupId = BluetoothUtils.getGroupId(cachedDevice);
-                            if (groupId != BluetoothCsipSetCoordinator.GROUP_ID_INVALID
-                                    && groupId
-                                            == BluetoothUtils.getPrimaryGroupIdForBroadcast(
-                                                    mContext.getContentResolver())) {
-                                // Set media stream volume for primary buds, audio manager will
-                                // update all buds volume in the audio sharing.
-                                setAudioManagerStreamVolume(progress);
-                            } else {
-                                // Set buds volume for other buds.
-                                setDeviceVolume(cachedDevice, progress);
-                            }
-                        }
-                    };
             AudioSharingDeviceVolumePreference vPreference =
                     new AudioSharingDeviceVolumePreference(mPrefContext, cachedDevice);
             vPreference.initialize();
-            vPreference.setOnSeekBarChangeListener(listener);
             vPreference.setKey(getPreferenceKeyPrefix() + cachedDevice.hashCode());
             vPreference.setIcon(com.android.settingslib.R.drawable.ic_bt_untethered_earbuds);
             vPreference.setTitle(cachedDevice.getName());
@@ -154,35 +123,4 @@
 
     @Override
     public void refreshPreference() {}
-
-    private void setDeviceVolume(CachedBluetoothDevice cachedDevice, int progress) {
-        if (mVolumeControl != null) {
-            mVolumeControl.setDeviceVolume(
-                    cachedDevice.getDevice(), progress, /* isGroupOp= */ true);
-            mMetricsFeatureProvider.action(
-                    mContext,
-                    SettingsEnums.ACTION_AUDIO_SHARING_CHANGE_MEDIA_DEVICE_VOLUME,
-                    /* isPrimary= */ false);
-        }
-    }
-
-    private void setAudioManagerStreamVolume(int progress) {
-        int seekbarRange =
-                AudioSharingDeviceVolumePreference.MAX_VOLUME
-                        - AudioSharingDeviceVolumePreference.MIN_VOLUME;
-        try {
-            AudioManager audioManager = mContext.getSystemService(AudioManager.class);
-            int streamVolumeRange =
-                    audioManager.getStreamMaxVolume(AudioManager.STREAM_MUSIC)
-                            - audioManager.getStreamMinVolume(AudioManager.STREAM_MUSIC);
-            int volume = Math.round((float) progress * streamVolumeRange / seekbarRange);
-            audioManager.setStreamVolume(AudioManager.STREAM_MUSIC, volume, 0);
-            mMetricsFeatureProvider.action(
-                    mContext,
-                    SettingsEnums.ACTION_AUDIO_SHARING_CHANGE_MEDIA_DEVICE_VOLUME,
-                    /* isPrimary= */ true);
-        } catch (RuntimeException e) {
-            Log.e(TAG, "Fail to setAudioManagerStreamVolumeForFallbackDevice, error = " + e);
-        }
-    }
 }
diff --git a/src/com/android/settings/connecteddevice/audiosharing/AudioSharingDeviceVolumeGroupController.java b/src/com/android/settings/connecteddevice/audiosharing/AudioSharingDeviceVolumeGroupController.java
index 48b04b4..42de10a 100644
--- a/src/com/android/settings/connecteddevice/audiosharing/AudioSharingDeviceVolumeGroupController.java
+++ b/src/com/android/settings/connecteddevice/audiosharing/AudioSharingDeviceVolumeGroupController.java
@@ -61,7 +61,7 @@
 
 public class AudioSharingDeviceVolumeGroupController extends AudioSharingBasePreferenceController
         implements DevicePreferenceCallback {
-    private static final String TAG = "AudioSharingDeviceVolumeGroupController";
+    private static final String TAG = "AudioSharingVolCtlr";
     private static final String KEY = "audio_sharing_device_volume_group";
 
     @Nullable private final LocalBluetoothManager mBtManager;
diff --git a/src/com/android/settings/connecteddevice/audiosharing/AudioSharingDeviceVolumePreference.java b/src/com/android/settings/connecteddevice/audiosharing/AudioSharingDeviceVolumePreference.java
index 01afc02..816ec6e 100644
--- a/src/com/android/settings/connecteddevice/audiosharing/AudioSharingDeviceVolumePreference.java
+++ b/src/com/android/settings/connecteddevice/audiosharing/AudioSharingDeviceVolumePreference.java
@@ -16,27 +16,46 @@
 
 package com.android.settings.connecteddevice.audiosharing;
 
+import android.app.settings.SettingsEnums;
+import android.bluetooth.BluetoothCsipSetCoordinator;
+import android.bluetooth.BluetoothDevice;
 import android.content.Context;
+import android.media.AudioManager;
+import android.util.Log;
 import android.widget.SeekBar;
 
 import androidx.annotation.NonNull;
 import androidx.annotation.Nullable;
 
 import com.android.settings.R;
+import com.android.settings.bluetooth.Utils;
+import com.android.settings.overlay.FeatureFactory;
 import com.android.settings.widget.SeekBarPreference;
+import com.android.settingslib.bluetooth.BluetoothUtils;
 import com.android.settingslib.bluetooth.CachedBluetoothDevice;
+import com.android.settingslib.bluetooth.LocalBluetoothManager;
+import com.android.settingslib.bluetooth.VolumeControlProfile;
+import com.android.settingslib.core.instrumentation.MetricsFeatureProvider;
+import com.android.settingslib.utils.ThreadUtils;
 
 public class AudioSharingDeviceVolumePreference extends SeekBarPreference {
+    private static final String TAG = "AudioSharingVolPref";
+
     public static final int MIN_VOLUME = 0;
     public static final int MAX_VOLUME = 255;
 
+    private final Context mContext;
     private final CachedBluetoothDevice mCachedDevice;
     @Nullable protected SeekBar mSeekBar;
+    private Boolean mTrackingTouch = false;
+    private MetricsFeatureProvider mMetricsFeatureProvider =
+            FeatureFactory.getFeatureFactory().getMetricsFeatureProvider();
 
     public AudioSharingDeviceVolumePreference(
             Context context, @NonNull CachedBluetoothDevice device) {
         super(context);
         setLayoutResource(R.layout.preference_volume_slider);
+        mContext = context;
         mCachedDevice = device;
     }
 
@@ -54,4 +73,95 @@
         setMax(MAX_VOLUME);
         setMin(MIN_VOLUME);
     }
+
+    @Override
+    public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
+        super.onProgressChanged(seekBar, progress, fromUser);
+        // When user use talk back swipe up/down or use Switch Access to change the volume bar
+        // progress, there is no onStopTrackingTouch triggered. So we need to check this scenario
+        // and update the device volume here.
+        if (fromUser && !mTrackingTouch) {
+            Log.d(TAG, "onProgressChanged from user and not in touch, handleProgressChange.");
+            handleProgressChange(progress);
+        }
+    }
+
+    @Override
+    public void onStartTrackingTouch(SeekBar seekBar) {
+        mTrackingTouch = true;
+        super.onStartTrackingTouch(seekBar);
+    }
+
+    @Override
+    public void onStopTrackingTouch(SeekBar seekBar) {
+        mTrackingTouch = false;
+        super.onStopTrackingTouch(seekBar);
+        // When user touch the volume bar to change volume, we only update the device volume when
+        // user stop touching the bar.
+        Log.d(TAG, "onStopTrackingTouch, handleProgressChange.");
+        handleProgressChange(seekBar.getProgress());
+    }
+
+    private void handleProgressChange(int progress) {
+        var unused =
+                ThreadUtils.postOnBackgroundThread(
+                        () -> {
+                            int groupId = BluetoothUtils.getGroupId(mCachedDevice);
+                            if (groupId != BluetoothCsipSetCoordinator.GROUP_ID_INVALID
+                                    && groupId
+                                            == BluetoothUtils.getPrimaryGroupIdForBroadcast(
+                                                    mContext.getContentResolver())) {
+                                // Set media stream volume for primary buds, audio manager will
+                                // update all buds volume in the audio sharing.
+                                setAudioManagerStreamVolume(progress);
+                            } else {
+                                // Set buds volume for other buds.
+                                setDeviceVolume(mCachedDevice.getDevice(), progress);
+                            }
+                        });
+    }
+
+    private void setDeviceVolume(@Nullable BluetoothDevice device, int progress) {
+        if (device == null) {
+            Log.d(TAG, "Skip set device volume, device is null");
+            return;
+        }
+        LocalBluetoothManager btManager = Utils.getLocalBtManager(mContext);
+        VolumeControlProfile vc =
+                btManager == null ? null : btManager.getProfileManager().getVolumeControlProfile();
+        if (vc != null) {
+            vc.setDeviceVolume(device, progress, /* isGroupOp= */ true);
+            mMetricsFeatureProvider.action(
+                    mContext,
+                    SettingsEnums.ACTION_AUDIO_SHARING_CHANGE_MEDIA_DEVICE_VOLUME,
+                    /* isPrimary= */ false);
+            Log.d(
+                    TAG,
+                    "set device volume, device = "
+                            + device.getAnonymizedAddress()
+                            + " volume = "
+                            + progress);
+        }
+    }
+
+    private void setAudioManagerStreamVolume(int progress) {
+        int seekbarRange =
+                AudioSharingDeviceVolumePreference.MAX_VOLUME
+                        - AudioSharingDeviceVolumePreference.MIN_VOLUME;
+        try {
+            AudioManager audioManager = mContext.getSystemService(AudioManager.class);
+            int streamVolumeRange =
+                    audioManager.getStreamMaxVolume(AudioManager.STREAM_MUSIC)
+                            - audioManager.getStreamMinVolume(AudioManager.STREAM_MUSIC);
+            int volume = Math.round((float) progress * streamVolumeRange / seekbarRange);
+            audioManager.setStreamVolume(AudioManager.STREAM_MUSIC, volume, 0);
+            mMetricsFeatureProvider.action(
+                    mContext,
+                    SettingsEnums.ACTION_AUDIO_SHARING_CHANGE_MEDIA_DEVICE_VOLUME,
+                    /* isPrimary= */ true);
+            Log.d(TAG, "set music stream volume, volume = " + progress);
+        } catch (RuntimeException e) {
+            Log.e(TAG, "Fail to setAudioManagerStreamVolumeForFallbackDevice, error = " + e);
+        }
+    }
 }
diff --git a/src/com/android/settings/connecteddevice/audiosharing/audiostreams/AudioStreamsHelper.java b/src/com/android/settings/connecteddevice/audiosharing/audiostreams/AudioStreamsHelper.java
index 215b677..c219e0b 100644
--- a/src/com/android/settings/connecteddevice/audiosharing/audiostreams/AudioStreamsHelper.java
+++ b/src/com/android/settings/connecteddevice/audiosharing/audiostreams/AudioStreamsHelper.java
@@ -28,10 +28,13 @@
 import android.bluetooth.BluetoothLeBroadcastReceiveState;
 import android.content.Context;
 import android.content.Intent;
+import android.content.res.Configuration;
 import android.util.Log;
 
 import androidx.annotation.VisibleForTesting;
+import androidx.fragment.app.FragmentActivity;
 
+import com.android.settings.R;
 import com.android.settings.connecteddevice.audiosharing.AudioSharingUtils;
 import com.android.settingslib.bluetooth.BluetoothUtils;
 import com.android.settingslib.bluetooth.CachedBluetoothDevice;
@@ -40,6 +43,7 @@
 import com.android.settingslib.bluetooth.LocalBluetoothProfileManager;
 import com.android.settingslib.utils.ThreadUtils;
 
+import com.google.android.material.appbar.AppBarLayout;
 import com.google.common.base.Strings;
 
 import java.util.ArrayList;
@@ -346,4 +350,16 @@
         intent.putParcelableArrayListExtra(DEVICES, new ArrayList<>(devices));
         context.startService(intent);
     }
+
+    static void configureAppBarByOrientation(@Nullable FragmentActivity activity) {
+        if (activity != null) {
+            AppBarLayout appBarLayout = activity.findViewById(R.id.app_bar);
+            if (appBarLayout != null) {
+                boolean canAppBarExpand =
+                        activity.getResources().getConfiguration().orientation
+                                == Configuration.ORIENTATION_PORTRAIT;
+                appBarLayout.setExpanded(canAppBarExpand);
+            }
+        }
+    }
 }
diff --git a/src/com/android/settings/connecteddevice/audiosharing/audiostreams/AudioStreamsQrCodeFragment.java b/src/com/android/settings/connecteddevice/audiosharing/audiostreams/AudioStreamsQrCodeFragment.java
index 47f9c75..3c362c0 100644
--- a/src/com/android/settings/connecteddevice/audiosharing/audiostreams/AudioStreamsQrCodeFragment.java
+++ b/src/com/android/settings/connecteddevice/audiosharing/audiostreams/AudioStreamsQrCodeFragment.java
@@ -61,6 +61,8 @@
     @Override
     public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
         super.onViewCreated(view, savedInstanceState);
+        // Collapse or expand the app bar based on orientation for better display the qr code image.
+        AudioStreamsHelper.configureAppBarByOrientation(getActivity());
         var unused = ThreadUtils.postOnBackgroundThread(
                 () -> {
                     BluetoothLeBroadcastMetadata broadcastMetadata = getBroadcastMetadata();
diff --git a/src/com/android/settings/connecteddevice/audiosharing/audiostreams/AudioStreamsQrCodeScanFragment.java b/src/com/android/settings/connecteddevice/audiosharing/audiostreams/AudioStreamsQrCodeScanFragment.java
index 8df4317..76854a4 100644
--- a/src/com/android/settings/connecteddevice/audiosharing/audiostreams/AudioStreamsQrCodeScanFragment.java
+++ b/src/com/android/settings/connecteddevice/audiosharing/audiostreams/AudioStreamsQrCodeScanFragment.java
@@ -116,6 +116,8 @@
     @Override
     public final View onCreateView(
             LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
+        // Collapse or expand the app bar based on orientation for better display the qr camera.
+        AudioStreamsHelper.configureAppBarByOrientation(getActivity());
         return inflater.inflate(
                 R.layout.qrcode_scanner_fragment, container, /* attachToRoot */ false);
     }
diff --git a/src/com/android/settings/datausage/lib/AppDataUsageRepository.kt b/src/com/android/settings/datausage/lib/AppDataUsageRepository.kt
index 0055463..6ed9f7c 100644
--- a/src/com/android/settings/datausage/lib/AppDataUsageRepository.kt
+++ b/src/com/android/settings/datausage/lib/AppDataUsageRepository.kt
@@ -28,6 +28,7 @@
 import android.util.SparseBooleanArray
 import androidx.annotation.VisibleForTesting
 import androidx.core.util.keyIterator
+import androidx.core.util.valueIterator
 import com.android.settings.R
 import com.android.settings.datausage.lib.NetworkStatsRepository.Companion.Bucket
 import com.android.settingslib.AppItem
@@ -49,33 +50,30 @@
 
     @VisibleForTesting
     fun getAppPercent(carrierId: Int?, buckets: List<Bucket>): List<Pair<AppItem, Int>> {
-        val items = ArrayList<AppItem>()
         val knownItems = SparseArray<AppItem>()
         val profiles = context.userManager.userProfiles
         val userManager : UserManager = context.getSystemService(Context.USER_SERVICE) as UserManager
         val userIdToIsHiddenMap = profiles.associate { profile ->
             profile.identifier to shouldSkipProfile(userManager, profile)
         }
-        bindStats(buckets, userIdToIsHiddenMap, knownItems, items)
+        bindStats(buckets, userIdToIsHiddenMap, knownItems)
         val restrictedUids = context.getSystemService(NetworkPolicyManager::class.java)!!
             .getUidsWithPolicy(NetworkPolicyManager.POLICY_REJECT_METERED_BACKGROUND)
         for (uid in restrictedUids) {
             // Only splice in restricted state for current user or managed users
-            if (!profiles.contains(UserHandle.getUserHandleForUid(uid))) {
-                continue
-            }
-            var item = knownItems[uid]
-            if (item == null) {
-                item = AppItem(uid)
-                item.total = 0
-                item.addUid(uid)
-                items.add(item)
-                knownItems.put(item.key, item)
-            }
+            if (UserHandle.getUserHandleForUid(uid) !in profiles) continue
+            val item =
+                knownItems[uid]
+                    ?: AppItem(uid).apply {
+                        category = AppItem.CATEGORY_APP
+                        addUid(uid)
+                        knownItems.put(uid, this)
+                    }
             item.restricted = true
         }
 
-        val filteredItems = filterItems(carrierId, items).sorted()
+        val filteredItems =
+            filterItems(carrierId, knownItems.valueIterator().asSequence().toList()).sorted()
         val largest: Long = filteredItems.maxOfOrNull { it.total } ?: 0
         return filteredItems.map { item ->
             val percentTotal = if (largest > 0) (item.total * 100 / largest).toInt() else 0
@@ -106,7 +104,6 @@
         buckets: List<Bucket>,
         userIdToIsHiddenMap: Map<Int, Boolean>,
         knownItems: SparseArray<AppItem>,
-        items: ArrayList<AppItem>,
     ) {
         for (bucket in buckets) {
             // Decide how to collapse items together
@@ -126,7 +123,6 @@
                             knownItems = knownItems,
                             bucket = bucket,
                             itemCategory = AppItem.CATEGORY_USER,
-                            items = items,
                         )
                     }
                     collapseKey = getAppUid(uid)
@@ -157,7 +153,6 @@
                 knownItems = knownItems,
                 bucket = bucket,
                 itemCategory = category,
-                items = items,
             )
         }
     }
@@ -187,15 +182,13 @@
         knownItems: SparseArray<AppItem>,
         bucket: Bucket,
         itemCategory: Int,
-        items: ArrayList<AppItem>,
     ) {
-        var item = knownItems[collapseKey]
-        if (item == null) {
-            item = AppItem(collapseKey)
-            item.category = itemCategory
-            items.add(item)
-            knownItems.put(item.key, item)
-        }
+        val item =
+            knownItems[collapseKey]
+                ?: AppItem(collapseKey).apply {
+                    category = itemCategory
+                    knownItems.put(collapseKey, this)
+                }
         item.addUid(bucket.uid)
         item.total += bucket.bytes
     }
diff --git a/src/com/android/settings/fuelgauge/BatteryHeaderPreferenceController.java b/src/com/android/settings/fuelgauge/BatteryHeaderPreferenceController.java
index f121d0c..891a997 100644
--- a/src/com/android/settings/fuelgauge/BatteryHeaderPreferenceController.java
+++ b/src/com/android/settings/fuelgauge/BatteryHeaderPreferenceController.java
@@ -92,8 +92,7 @@
                 && mBatterySettingsFeatureProvider.isChargingOptimizationMode(mContext)) {
             return info.remainingLabel;
         }
-        if (info.remainingLabel == null
-                || info.batteryStatus == BatteryManager.BATTERY_STATUS_NOT_CHARGING) {
+        if (info.batteryStatus == BatteryManager.BATTERY_STATUS_NOT_CHARGING) {
             return info.statusLabel;
         }
         if (info.pluggedStatus == BatteryManager.BATTERY_PLUGGED_WIRELESS) {
@@ -106,6 +105,9 @@
                 return wirelessChargingLabel;
             }
         }
+        if (info.remainingLabel == null) {
+            return info.statusLabel;
+        }
         if (info.statusLabel != null && !info.discharging) {
             // Charging state
             if (com.android.settingslib.fuelgauge.BatteryUtils.isChargingStringV2Enabled()) {
diff --git a/src/com/android/settings/fuelgauge/batteryusage/AnomalyEventWrapper.java b/src/com/android/settings/fuelgauge/batteryusage/AnomalyEventWrapper.java
index be5de06..c62728b 100644
--- a/src/com/android/settings/fuelgauge/batteryusage/AnomalyEventWrapper.java
+++ b/src/com/android/settings/fuelgauge/batteryusage/AnomalyEventWrapper.java
@@ -28,10 +28,11 @@
 import com.android.settings.R;
 import com.android.settings.SettingsActivity;
 import com.android.settings.core.SubSettingLauncher;
+import com.android.settings.widget.TipCardPreference;
 
 import java.util.function.Function;
 
-final class AnomalyEventWrapper {
+class AnomalyEventWrapper {
     private static final String TAG = "AnomalyEventWrapper";
 
     private final Context mContext;
@@ -235,16 +236,16 @@
         return mHighlightSlotPair;
     }
 
-    boolean updateTipsCardPreference(BatteryTipsCardPreference preference) {
+    boolean updateTipsCardPreference(TipCardPreference preference) {
         final String titleString = getTitleString();
         if (TextUtils.isEmpty(titleString)) {
             return false;
         }
         preference.setTitle(titleString);
-        preference.setIconResourceId(getIconResId());
-        preference.setButtonColorResourceId(getColorResId());
-        preference.setMainButtonLabel(getMainBtnString());
-        preference.setDismissButtonLabel(getDismissBtnString());
+        preference.setIconResId(getIconResId());
+        preference.setTintColorResId(getColorResId());
+        preference.setPrimaryButtonText(getDismissBtnString());
+        preference.setSecondaryButtonText(getMainBtnString());
         return true;
     }
 
diff --git a/src/com/android/settings/fuelgauge/batteryusage/BatteryTipsCardPreference.java b/src/com/android/settings/fuelgauge/batteryusage/BatteryTipsCardPreference.java
deleted file mode 100644
index bbd1099..0000000
--- a/src/com/android/settings/fuelgauge/batteryusage/BatteryTipsCardPreference.java
+++ /dev/null
@@ -1,150 +0,0 @@
-/*
- * Copyright (C) 2023 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.settings.fuelgauge.batteryusage;
-
-import android.content.Context;
-import android.text.TextUtils;
-import android.util.AttributeSet;
-import android.view.View;
-import android.widget.ImageView;
-import android.widget.LinearLayout;
-import android.widget.TextView;
-
-import androidx.annotation.VisibleForTesting;
-import androidx.preference.Preference;
-import androidx.preference.PreferenceViewHolder;
-
-import com.android.settings.R;
-
-import com.google.android.material.button.MaterialButton;
-
-/** A preference for displaying the battery tips card view. */
-public class BatteryTipsCardPreference extends Preference implements View.OnClickListener {
-
-    private static final String TAG = "BatteryTipsCardPreference";
-
-    interface OnConfirmListener {
-        void onConfirm();
-    }
-
-    interface OnRejectListener {
-        void onReject();
-    }
-
-    private OnConfirmListener mOnConfirmListener;
-    private OnRejectListener mOnRejectListener;
-    private int mIconResourceId = 0;
-    private int mButtonColorResourceId = 0;
-
-    @VisibleForTesting CharSequence mMainButtonLabel;
-    @VisibleForTesting CharSequence mDismissButtonLabel;
-
-    public BatteryTipsCardPreference(Context context, AttributeSet attrs) {
-        super(context, attrs);
-        setLayoutResource(R.layout.battery_tips_card);
-        setViewId(R.id.battery_tips_card);
-        setSelectable(false);
-    }
-
-    public void setOnConfirmListener(OnConfirmListener listener) {
-        mOnConfirmListener = listener;
-    }
-
-    public void setOnRejectListener(OnRejectListener listener) {
-        mOnRejectListener = listener;
-    }
-
-    /**
-     * Sets the icon in tips card.
-     */
-    public void setIconResourceId(int resourceId) {
-        if (mIconResourceId != resourceId) {
-            mIconResourceId = resourceId;
-            notifyChanged();
-        }
-    }
-
-    /**
-     * Sets the background color for main button and the text color for dismiss button.
-     */
-    public void setButtonColorResourceId(int resourceId) {
-        if (mButtonColorResourceId != resourceId) {
-            mButtonColorResourceId = resourceId;
-            notifyChanged();
-        }
-    }
-
-    /**
-     * Sets the label of main button in tips card.
-     */
-    public void setMainButtonLabel(CharSequence label) {
-        if (!TextUtils.equals(mMainButtonLabel, label)) {
-            mMainButtonLabel = label;
-            notifyChanged();
-        }
-    }
-
-    /**
-     * Sets the label of dismiss button in tips card.
-     */
-    public void setDismissButtonLabel(CharSequence label) {
-        if (!TextUtils.equals(mDismissButtonLabel, label)) {
-            mDismissButtonLabel = label;
-            notifyChanged();
-        }
-    }
-
-    @Override
-    public void onClick(View view) {
-        final int viewId = view.getId();
-        if (viewId == R.id.main_button || viewId == R.id.battery_tips_card) {
-            if (mOnConfirmListener != null) {
-                mOnConfirmListener.onConfirm();
-            }
-        } else if (viewId == R.id.dismiss_button) {
-            if (mOnRejectListener != null) {
-                mOnRejectListener.onReject();
-            }
-        }
-    }
-
-    @Override
-    public void onBindViewHolder(PreferenceViewHolder view) {
-        super.onBindViewHolder(view);
-
-        ((TextView) view.findViewById(R.id.title)).setText(getTitle());
-
-        final LinearLayout tipsCard = (LinearLayout) view.findViewById(R.id.battery_tips_card);
-        tipsCard.setOnClickListener(this);
-        final MaterialButton mainButton = (MaterialButton) view.findViewById(R.id.main_button);
-        mainButton.setOnClickListener(this);
-        mainButton.setText(mMainButtonLabel);
-        final MaterialButton dismissButton =
-                (MaterialButton) view.findViewById(R.id.dismiss_button);
-        dismissButton.setOnClickListener(this);
-        dismissButton.setText(mDismissButtonLabel);
-        if (mButtonColorResourceId != 0) {
-            final int colorInt = getContext().getColor(mButtonColorResourceId);
-            mainButton.setBackgroundColor(colorInt);
-            dismissButton.setTextColor(colorInt);
-        }
-
-        if (mIconResourceId != 0) {
-            ((ImageView) view.findViewById(R.id.icon)).setImageResource(mIconResourceId);
-        }
-    }
-}
diff --git a/src/com/android/settings/fuelgauge/batteryusage/BatteryTipsController.java b/src/com/android/settings/fuelgauge/batteryusage/BatteryTipsController.java
index 821c868..405b786 100644
--- a/src/com/android/settings/fuelgauge/batteryusage/BatteryTipsController.java
+++ b/src/com/android/settings/fuelgauge/batteryusage/BatteryTipsController.java
@@ -25,6 +25,7 @@
 import com.android.internal.annotations.VisibleForTesting;
 import com.android.settings.core.BasePreferenceController;
 import com.android.settings.overlay.FeatureFactory;
+import com.android.settings.widget.TipCardPreference;
 import com.android.settingslib.core.instrumentation.MetricsFeatureProvider;
 
 /** Controls the update for battery tips card */
@@ -50,10 +51,9 @@
         void onAnomalyReject();
     }
 
-    private OnAnomalyConfirmListener mOnAnomalyConfirmListener;
-    private OnAnomalyRejectListener mOnAnomalyRejectListener;
-
-    @VisibleForTesting BatteryTipsCardPreference mCardPreference;
+    @VisibleForTesting OnAnomalyConfirmListener mOnAnomalyConfirmListener;
+    @VisibleForTesting OnAnomalyRejectListener mOnAnomalyRejectListener;
+    @VisibleForTesting TipCardPreference mCardPreference;
     @VisibleForTesting AnomalyEventWrapper mAnomalyEventWrapper = null;
     @VisibleForTesting Boolean mIsAcceptable = false;
 
@@ -117,42 +117,20 @@
             return;
         }
 
-        // Set battery tips card listener
-        mCardPreference.setOnConfirmListener(
+        mCardPreference.setPrimaryButtonAction(
                 () -> {
-                    mCardPreference.setVisible(false);
-                    if (mOnAnomalyConfirmListener != null) {
-                        mOnAnomalyConfirmListener.onAnomalyConfirm();
-                    } else if (mAnomalyEventWrapper.updateSystemSettingsIfAvailable()
-                            || mAnomalyEventWrapper.launchSubSetting()) {
-                        mMetricsFeatureProvider.action(
-                                /* attribution= */ SettingsEnums.FUELGAUGE_BATTERY_HISTORY_DETAIL,
-                                /* action= */ SettingsEnums.ACTION_BATTERY_TIPS_CARD_ACCEPT,
-                                /* pageId= */ SettingsEnums.FUELGAUGE_BATTERY_HISTORY_DETAIL,
-                                /* key= */ ANOMALY_KEY,
-                                /* value= */ anomalyKeyNumber);
-                    }
+                    onBatteryTipsCardDismiss(anomalyKeyNumber);
+                    return null;
                 });
-        mCardPreference.setOnRejectListener(
+        mCardPreference.setSecondaryButtonAction(
                 () -> {
-                    mCardPreference.setVisible(false);
-                    if (mOnAnomalyRejectListener != null) {
-                        mOnAnomalyRejectListener.onAnomalyReject();
-                    }
-                    // For anomaly events with same record key, dismissed until next time full
-                    // charged.
-                    final String dismissRecordKey = mAnomalyEventWrapper.getDismissRecordKey();
-                    if (!TextUtils.isEmpty(dismissRecordKey)) {
-                        DatabaseUtils.setDismissedPowerAnomalyKeys(mContext, dismissRecordKey);
-                    }
-                    mMetricsFeatureProvider.action(
-                            /* attribution= */ SettingsEnums.FUELGAUGE_BATTERY_HISTORY_DETAIL,
-                            /* action= */ SettingsEnums.ACTION_BATTERY_TIPS_CARD_DISMISS,
-                            /* pageId= */ SettingsEnums.FUELGAUGE_BATTERY_HISTORY_DETAIL,
-                            /* key= */ ANOMALY_KEY,
-                            /* value= */ anomalyKeyNumber);
+                    onBatteryTipsCardAccept(anomalyKeyNumber);
+                    return null;
                 });
 
+        mCardPreference.setPrimaryButtonVisibility(true);
+        mCardPreference.setSecondaryButtonVisibility(true);
+        mCardPreference.buildContent();
         mCardPreference.setVisible(true);
         mMetricsFeatureProvider.action(
                 /* attribution= */ SettingsEnums.FUELGAUGE_BATTERY_HISTORY_DETAIL,
@@ -161,4 +139,37 @@
                 /* key= */ ANOMALY_KEY,
                 /* value= */ anomalyKeyNumber);
     }
+
+    private void onBatteryTipsCardDismiss(final int anomalyKeyNumber) {
+        mCardPreference.setVisible(false);
+        if (mOnAnomalyRejectListener != null) {
+            mOnAnomalyRejectListener.onAnomalyReject();
+        }
+        // For anomaly events with same record key, dismissed until next time full charged.
+        final String dismissRecordKey = mAnomalyEventWrapper.getDismissRecordKey();
+        if (!TextUtils.isEmpty(dismissRecordKey)) {
+            DatabaseUtils.setDismissedPowerAnomalyKeys(mContext, dismissRecordKey);
+        }
+        mMetricsFeatureProvider.action(
+                /* attribution= */ SettingsEnums.FUELGAUGE_BATTERY_HISTORY_DETAIL,
+                /* action= */ SettingsEnums.ACTION_BATTERY_TIPS_CARD_DISMISS,
+                /* pageId= */ SettingsEnums.FUELGAUGE_BATTERY_HISTORY_DETAIL,
+                /* key= */ ANOMALY_KEY,
+                /* value= */ anomalyKeyNumber);
+    }
+
+    private void onBatteryTipsCardAccept(final int anomalyKeyNumber) {
+        mCardPreference.setVisible(false);
+        if (mOnAnomalyConfirmListener != null) {
+            mOnAnomalyConfirmListener.onAnomalyConfirm();
+        } else if (mAnomalyEventWrapper.updateSystemSettingsIfAvailable()
+                || mAnomalyEventWrapper.launchSubSetting()) {
+            mMetricsFeatureProvider.action(
+                    /* attribution= */ SettingsEnums.FUELGAUGE_BATTERY_HISTORY_DETAIL,
+                    /* action= */ SettingsEnums.ACTION_BATTERY_TIPS_CARD_ACCEPT,
+                    /* pageId= */ SettingsEnums.FUELGAUGE_BATTERY_HISTORY_DETAIL,
+                    /* key= */ ANOMALY_KEY,
+                    /* value= */ anomalyKeyNumber);
+        }
+    }
 }
diff --git a/src/com/android/settings/network/ims/VolteQueryImsState.java b/src/com/android/settings/network/ims/VolteQueryImsState.java
index b09a130..5acf2db 100644
--- a/src/com/android/settings/network/ims/VolteQueryImsState.java
+++ b/src/com/android/settings/network/ims/VolteQueryImsState.java
@@ -19,6 +19,7 @@
 import static android.telephony.ims.ProvisioningManager.KEY_VOIMS_OPT_IN_STATUS;
 
 import android.content.Context;
+import android.content.pm.PackageManager;
 import android.telecom.TelecomManager;
 import android.telephony.AccessNetworkConstants;
 import android.telephony.SubscriptionManager;
@@ -143,6 +144,11 @@
      * @return true when VoIMS opt-in has been enabled, otherwise false
      */
     public boolean isVoImsOptInEnabled() {
+        if (!mContext.getPackageManager().hasSystemFeature(PackageManager.FEATURE_TELEPHONY_IMS)) {
+            // If the device does not have PackageManager.FEATURE_TELEPHONY_IMS,
+            // ProvisioningManager.getProvisioningIntValue() could not be called.
+            return false;
+        }
         int voImsOptInStatus = ProvisioningManager.createForSubscriptionId(mSubId)
                 .getProvisioningIntValue(KEY_VOIMS_OPT_IN_STATUS);
         return voImsOptInStatus == ProvisioningManager.PROVISIONING_VALUE_ENABLED;
diff --git a/src/com/android/settings/notification/modes/SetupInterstitialActivity.java b/src/com/android/settings/notification/modes/SetupInterstitialActivity.java
index 028e15b..225ded0 100644
--- a/src/com/android/settings/notification/modes/SetupInterstitialActivity.java
+++ b/src/com/android/settings/notification/modes/SetupInterstitialActivity.java
@@ -115,18 +115,21 @@
         if (intent == null) {
             Log.w(TAG, "no intent found for modes interstitial");
             finish();
+            return;
         }
 
         String modeId = intent.getStringExtra(EXTRA_AUTOMATIC_ZEN_RULE_ID);
         if (modeId == null) {
             Log.w(TAG, "no mode id included in intent: " + intent);
             finish();
+            return;
         }
 
         ZenMode mode = mBackend.getMode(modeId);
         if (mode == null) {
             Log.w(TAG, "mode not found for mode id: " + modeId);
             finish();
+            return;
         }
         setTitle(mode.getName());
 
@@ -237,11 +240,11 @@
             // Don't come back to this activity after sending the user to the modes page, if
             // they happen to go back. Forward the activity result in case we got here (indirectly)
             // from some app that is waiting for the result.
-            finish();
             if (updated) {
                 ZenSubSettingLauncher.forMode(this, modeId)
                         .addFlags(Intent.FLAG_ACTIVITY_FORWARD_RESULT).launch();
             }
+            finish();
         };
     }
 
diff --git a/src/com/android/settings/notification/modes/ZenModeSummaryHelper.java b/src/com/android/settings/notification/modes/ZenModeSummaryHelper.java
index 7a16d91..c5300da 100644
--- a/src/com/android/settings/notification/modes/ZenModeSummaryHelper.java
+++ b/src/com/android/settings/notification/modes/ZenModeSummaryHelper.java
@@ -42,13 +42,10 @@
 
 import android.content.Context;
 import android.icu.text.MessageFormat;
-import android.provider.Settings;
 import android.service.notification.ZenDeviceEffects;
-import android.service.notification.ZenModeConfig;
 import android.service.notification.ZenPolicy;
 import android.service.notification.ZenPolicy.ConversationSenders;
 import android.service.notification.ZenPolicy.PeopleType;
-import android.util.ArrayMap;
 
 import androidx.annotation.NonNull;
 import androidx.annotation.Nullable;
@@ -496,32 +493,36 @@
         return msgFormat.format(args);
     }
 
-    String getSoundSummary(int zenMode, ZenModeConfig config) {
-        if (zenMode != Settings.Global.ZEN_MODE_OFF) {
-            String description = ZenModeConfig.getDescription(mContext, true, config, false);
+    String getModesSummary(List<ZenMode> modes) {
+        List<ZenMode> activeModes = modes.stream().filter(ZenMode::isActive).toList();
 
-            if (description == null) {
-                return mContext.getString(R.string.zen_mode_sound_summary_on);
-            } else {
-                return mContext.getString(R.string.zen_mode_sound_summary_on_with_info,
-                        description);
-            }
-        } else {
-            int count = 0;
-            final ArrayMap<String, ZenModeConfig.ZenRule> ruleMap = config.automaticRules;
-            if (ruleMap != null) {
-                for (ZenModeConfig.ZenRule rule : ruleMap.values()) {
-                    if (rule != null && rule.enabled) {
-                        count++;
-                    }
+        if (!activeModes.isEmpty()) {
+            MessageFormat msgFormat = new MessageFormat(
+                    mContext.getString(R.string.zen_modes_summary_some_active),
+                    Locale.getDefault());
+
+            Map<String, Object> args = new HashMap<>();
+            args.put("count", activeModes.size());
+            args.put("mode_1", activeModes.get(0).getName());
+            if (activeModes.size() >= 2) {
+                args.put("mode_2", activeModes.get(1).getName());
+                if (activeModes.size() == 3) {
+                    args.put("mode_3", activeModes.get(2).getName());
                 }
             }
+
+            return msgFormat.format(args);
+        } else {
+            int automaticModeCount = (int) modes.stream()
+                    .filter(m -> m.isEnabled() && !m.isManualDnd() && !m.isCustomManual())
+                    .count();
+
             MessageFormat msgFormat = new MessageFormat(
-                    mContext.getString(R.string.modes_sound_summary_off),
+                    mContext.getString(R.string.zen_modes_summary_none_active),
                     Locale.getDefault());
-            Map<String, Object> msgArgs = new HashMap<>();
-            msgArgs.put("count", count);
+            Map<String, Object> msgArgs = Map.of("count", automaticModeCount);
             return msgFormat.format(msgArgs);
         }
     }
+
 }
diff --git a/src/com/android/settings/notification/modes/ZenModesLinkPreferenceController.java b/src/com/android/settings/notification/modes/ZenModesLinkPreferenceController.java
index f2679d7..aba82c8 100644
--- a/src/com/android/settings/notification/modes/ZenModesLinkPreferenceController.java
+++ b/src/com/android/settings/notification/modes/ZenModesLinkPreferenceController.java
@@ -17,35 +17,31 @@
 package com.android.settings.notification.modes;
 
 import android.app.Flags;
-import android.app.NotificationManager;
-import android.content.ContentResolver;
 import android.content.Context;
-import android.database.ContentObserver;
-import android.net.Uri;
-import android.os.Handler;
-import android.os.UserHandle;
-import android.provider.Settings;
 
 import androidx.preference.Preference;
 import androidx.preference.PreferenceScreen;
 
-import com.android.settings.R;
 import com.android.settings.core.BasePreferenceController;
 import com.android.settingslib.core.lifecycle.LifecycleObserver;
-import com.android.settingslib.core.lifecycle.events.OnPause;
-import com.android.settingslib.core.lifecycle.events.OnResume;
+import com.android.settingslib.core.lifecycle.events.OnStart;
+import com.android.settingslib.core.lifecycle.events.OnStop;
+import com.android.settingslib.notification.modes.ZenModesBackend;
 
 public class ZenModesLinkPreferenceController extends BasePreferenceController
-        implements LifecycleObserver, OnResume, OnPause {
+        implements LifecycleObserver, OnStart, OnStop {
 
-    private SettingObserver mSettingObserver;
-    private ZenModeSummaryHelper mSummaryBuilder;
-    private NotificationManager mNm;
+    private final ZenModesBackend mBackend;
+    private final ZenSettingsObserver mSettingObserver;
+    private final ZenModeSummaryHelper mSummaryBuilder;
+
+    private Preference mPreference;
 
     public ZenModesLinkPreferenceController(Context context, String key) {
         super(context, key);
+        mBackend = ZenModesBackend.getInstance(context);
         mSummaryBuilder = new ZenModeSummaryHelper(context, ZenHelperBackend.getInstance(context));
-        mNm = mContext.getSystemService(NotificationManager.class);
+        mSettingObserver = new ZenSettingsObserver(context, this::onZenSettingsChanged);
     }
 
     @Override
@@ -57,64 +53,31 @@
     @Override
     public void displayPreference(PreferenceScreen screen) {
         super.displayPreference(screen);
-        Preference preference = screen.findPreference(getPreferenceKey());
-        mSettingObserver = new SettingObserver(preference);
+        mPreference = screen.findPreference(getPreferenceKey());
     }
 
     @Override
-    public void onResume() {
+    public void onStart() {
         if (mSettingObserver != null) {
-            mSettingObserver.register(mContext.getContentResolver());
+            mSettingObserver.register();
         }
     }
 
-    @Override
-    public void onPause() {
-        if (mSettingObserver != null) {
-            mSettingObserver.unregister(mContext.getContentResolver());
+    private void onZenSettingsChanged() {
+        if (mPreference != null) {
+            updateState(mPreference);
         }
     }
 
     @Override
     public void updateState(Preference preference) {
-        preference.setSummary(mSummaryBuilder.getSoundSummary(
-                Settings.Global.getInt(mContext.getContentResolver(),
-                        Settings.Global.ZEN_MODE,
-                        Settings.Global.ZEN_MODE_OFF),
-                mNm.getZenModeConfig()));
+        preference.setSummary(mSummaryBuilder.getModesSummary(mBackend.getModes()));
     }
 
-    class SettingObserver extends ContentObserver {
-        private final Uri ZEN_MODE_URI = Settings.Global.getUriFor(Settings.Global.ZEN_MODE);
-        private final Uri ZEN_MODE_CONFIG_ETAG_URI = Settings.Global.getUriFor(
-                Settings.Global.ZEN_MODE_CONFIG_ETAG);
-
-        private final Preference mPreference;
-
-        public SettingObserver(Preference preference) {
-            super(new Handler());
-            mPreference = preference;
-        }
-
-        public void register(ContentResolver cr) {
-            cr.registerContentObserver(ZEN_MODE_URI, false, this, UserHandle.USER_ALL);
-            cr.registerContentObserver(ZEN_MODE_CONFIG_ETAG_URI, false, this, UserHandle.USER_ALL);
-        }
-
-        public void unregister(ContentResolver cr) {
-            cr.unregisterContentObserver(this);
-        }
-
-        @Override
-        public void onChange(boolean selfChange, Uri uri) {
-            super.onChange(selfChange, uri);
-            if (ZEN_MODE_URI.equals(uri)) {
-                updateState(mPreference);
-            }
-
-            if (ZEN_MODE_CONFIG_ETAG_URI.equals(uri)) {
-                updateState(mPreference);
-            }
+    @Override
+    public void onStop() {
+        if (mSettingObserver != null) {
+            mSettingObserver.unregister();
         }
     }
 }
diff --git a/src/com/android/settings/notification/modes/ZenModesListItemPreference.java b/src/com/android/settings/notification/modes/ZenModesListItemPreference.java
index 9de56b1..e09d04c 100644
--- a/src/com/android/settings/notification/modes/ZenModesListItemPreference.java
+++ b/src/com/android/settings/notification/modes/ZenModesListItemPreference.java
@@ -74,15 +74,16 @@
         }
 
         setTitle(mZenMode.getName());
+        String dynamicDescription = zenMode.getDynamicDescription(mContext);
         CharSequence statusText = switch (mZenMode.getStatus()) {
             case ENABLED_AND_ACTIVE ->
-                    Strings.isNullOrEmpty(mZenMode.getTriggerDescription())
+                    Strings.isNullOrEmpty(dynamicDescription)
                             ? mContext.getString(R.string.zen_mode_active_text)
                             : mContext.getString(
                                     R.string.zen_mode_format_status_and_trigger,
                                     mContext.getString(R.string.zen_mode_active_text),
-                                    mZenMode.getRule().getTriggerDescription());
-            case ENABLED -> mZenMode.getRule().getTriggerDescription();
+                                    dynamicDescription);
+            case ENABLED -> dynamicDescription;
             case DISABLED_BY_USER -> mContext.getString(R.string.zen_mode_disabled_by_user);
             case DISABLED_BY_OTHER -> mContext.getString(R.string.zen_mode_disabled_needs_setup);
         };
diff --git a/src/com/android/settings/password/ConfirmLockPassword.java b/src/com/android/settings/password/ConfirmLockPassword.java
index b9b1810..ead79d7 100644
--- a/src/com/android/settings/password/ConfirmLockPassword.java
+++ b/src/com/android/settings/password/ConfirmLockPassword.java
@@ -64,6 +64,7 @@
 import com.android.internal.widget.LockscreenCredential;
 import com.android.internal.widget.TextViewInputDisabler;
 import com.android.settings.R;
+import com.android.settings.SetupRedactionInterstitial;
 import com.android.settingslib.animation.AppearAnimationUtils;
 import com.android.settingslib.animation.DisappearAnimationUtils;
 
@@ -723,6 +724,7 @@
             Intent result = new Intent();
             if (mRemoteValidation && containsGatekeeperPasswordHandle(resultData)) {
                 result.putExtra(EXTRA_KEY_GK_PW_HANDLE, getGatekeeperPasswordHandle(resultData));
+                SetupRedactionInterstitial.setEnabled(getContext(), true);
             }
             mCredentialCheckResultTracker.setResult(/* matched= */ true, result,
                     /* timeoutMs= */ 0, mEffectiveUserId);
diff --git a/src/com/android/settings/password/ConfirmLockPattern.java b/src/com/android/settings/password/ConfirmLockPattern.java
index 3415478..28d790e 100644
--- a/src/com/android/settings/password/ConfirmLockPattern.java
+++ b/src/com/android/settings/password/ConfirmLockPattern.java
@@ -54,6 +54,7 @@
 import com.android.internal.widget.LockPatternView.Cell;
 import com.android.internal.widget.LockscreenCredential;
 import com.android.settings.R;
+import com.android.settings.SetupRedactionInterstitial;
 import com.android.settingslib.animation.AppearAnimationCreator;
 import com.android.settingslib.animation.AppearAnimationUtils;
 import com.android.settingslib.animation.DisappearAnimationUtils;
@@ -751,6 +752,7 @@
             Intent result = new Intent();
             if (mRemoteValidation && containsGatekeeperPasswordHandle(resultData)) {
                 result.putExtra(EXTRA_KEY_GK_PW_HANDLE, getGatekeeperPasswordHandle(resultData));
+                SetupRedactionInterstitial.setEnabled(getContext(), true);
             }
             mCredentialCheckResultTracker.setResult(/* matched= */ true, result,
                     /* timeoutMs= */ 0, mEffectiveUserId);
diff --git a/src/com/android/settings/slices/SettingsSliceProvider.java b/src/com/android/settings/slices/SettingsSliceProvider.java
index ec60f44..8720160 100644
--- a/src/com/android/settings/slices/SettingsSliceProvider.java
+++ b/src/com/android/settings/slices/SettingsSliceProvider.java
@@ -120,6 +120,16 @@
      * permission can use them.
      */
     private static final List<Uri> PUBLICLY_SUPPORTED_CUSTOM_SLICE_URIS =
+            android.app.Flags.modesUi()
+                    ?
+                    Arrays.asList(
+                            CustomSliceRegistry.BLUETOOTH_URI,
+                            CustomSliceRegistry.FLASHLIGHT_SLICE_URI,
+                            CustomSliceRegistry.LOCATION_SLICE_URI,
+                            CustomSliceRegistry.MOBILE_DATA_SLICE_URI,
+                            CustomSliceRegistry.WIFI_CALLING_URI,
+                            CustomSliceRegistry.WIFI_SLICE_URI
+                    ) :
             Arrays.asList(
                     CustomSliceRegistry.BLUETOOTH_URI,
                     CustomSliceRegistry.FLASHLIGHT_SLICE_URI,
@@ -184,7 +194,9 @@
         }
 
         if (CustomSliceRegistry.ZEN_MODE_SLICE_URI.equals(sliceUri)) {
-            registerIntentToUri(ZenModeSliceBuilder.INTENT_FILTER, sliceUri);
+            if (!android.app.Flags.modesUi()) {
+                registerIntentToUri(ZenModeSliceBuilder.INTENT_FILTER, sliceUri);
+            }
             return;
         } else if (CustomSliceRegistry.BLUETOOTH_URI.equals(sliceUri)) {
             registerIntentToUri(BluetoothSliceBuilder.INTENT_FILTER, sliceUri);
@@ -256,7 +268,8 @@
                         .getSlicesFeatureProvider()
                         .getNewWifiCallingSliceHelper(getContext())
                         .createWifiCallingSlice(sliceUri);
-            } else if (CustomSliceRegistry.ZEN_MODE_SLICE_URI.equals(sliceUri)) {
+            } else if (!android.app.Flags.modesUi()
+                    && CustomSliceRegistry.ZEN_MODE_SLICE_URI.equals(sliceUri)) {
                 return ZenModeSliceBuilder.getSlice(getContext());
             } else if (CustomSliceRegistry.BLUETOOTH_URI.equals(sliceUri)) {
                 return BluetoothSliceBuilder.getSlice(getContext());
diff --git a/src/com/android/settings/widget/TipCardPreference.kt b/src/com/android/settings/widget/TipCardPreference.kt
index 0ae7d2a..0ca0272 100644
--- a/src/com/android/settings/widget/TipCardPreference.kt
+++ b/src/com/android/settings/widget/TipCardPreference.kt
@@ -19,6 +19,7 @@
 import android.content.Context
 import android.content.res.Resources
 import android.util.AttributeSet
+import androidx.compose.ui.graphics.Color
 import androidx.compose.ui.graphics.vector.ImageVector
 import androidx.compose.ui.res.vectorResource
 import com.android.settings.spa.preference.ComposePreference
@@ -37,6 +38,9 @@
     /** A icon resource id for displaying icon on tips card. */
     var iconResId: Int? = null
 
+    /** A color resource id for displaying icon and button text on tips card. */
+    var tintColorResId: Int? = null
+
     /** The primary button's text. */
     var primaryButtonText: String = ""
 
@@ -85,6 +89,8 @@
                     title = title?.toString() ?: "",
                     text = summary?.toString() ?: "",
                     buttons = listOfNotNull(configPrimaryButton(), configSecondaryButton()),
+                    tintColor = tintColorResId?.let { Color(context.getColor(it)) }
+                        ?: Color.Unspecified,
                     onDismiss = onDismiss,
                     imageVector =
                     iconResId
diff --git a/tests/robotests/src/com/android/settings/accessibility/FlashNotificationsPreviewPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/accessibility/FlashNotificationsPreviewPreferenceControllerTest.java
index 0f32f31..6432a17 100644
--- a/tests/robotests/src/com/android/settings/accessibility/FlashNotificationsPreviewPreferenceControllerTest.java
+++ b/tests/robotests/src/com/android/settings/accessibility/FlashNotificationsPreviewPreferenceControllerTest.java
@@ -67,22 +67,23 @@
     public MockitoRule mMockitoRule = MockitoJUnit.rule();
     @Spy
     private final Context mContext = ApplicationProvider.getApplicationContext();
-    @Mock
-    private PreferenceScreen mPreferenceScreen;
-    @Mock
-    private Preference mPreference;
     @Spy
     private ContentResolver mContentResolver = mContext.getContentResolver();
-
+    @Mock
+    private PreferenceScreen mPreferenceScreen;
+    private Preference mPreference;
     private FlashNotificationsPreviewPreferenceController mController;
 
     @Before
     public void setUp() {
         MockitoAnnotations.initMocks(this);
-        when(mPreferenceScreen.findPreference(PREFERENCE_KEY)).thenReturn(mPreference);
-        when(mPreference.getKey()).thenReturn(PREFERENCE_KEY);
 
         when(mContext.getContentResolver()).thenReturn(mContentResolver);
+
+        mPreference = new Preference(mContext);
+        mPreference.setKey(PREFERENCE_KEY);
+        when(mPreferenceScreen.findPreference(PREFERENCE_KEY)).thenReturn(mPreference);
+
         mController = new FlashNotificationsPreviewPreferenceController(mContext, PREFERENCE_KEY);
     }
 
@@ -97,40 +98,45 @@
     }
 
     @Test
-    public void testDisplayPreference_torchPresent_cameraOff_screenOff_verifyDisabled() {
+    public void testDisplayPreference_torchPresent_cameraOff_screenOff_notVisible() {
         setFlashNotificationsState(FlashNotificationsUtil.State.OFF);
 
         mController.displayPreference(mPreferenceScreen);
-        verify(mPreference).setEnabled(eq(false));
+
+        assertThat(mPreference.isVisible()).isFalse();
     }
 
     @Test
-    public void testDisplayPreference_torchPresent_cameraOn_screenOff_verifyEnabled() {
+    public void testDisplayPreference_torchPresent_cameraOn_screenOff_isVisible() {
         setFlashNotificationsState(FlashNotificationsUtil.State.CAMERA);
 
         mController.displayPreference(mPreferenceScreen);
-        verify(mPreference).setEnabled(eq(true));
+
+        assertThat(mPreference.isVisible()).isTrue();
     }
 
     @Test
-    public void testDisplayPreference_torchPresent_cameraOff_screenOn_verifyEnabled() {
+    public void testDisplayPreference_torchPresent_cameraOff_screenOn_isVisible() {
         setFlashNotificationsState(FlashNotificationsUtil.State.SCREEN);
 
         mController.displayPreference(mPreferenceScreen);
-        verify(mPreference).setEnabled(eq(true));
+
+        assertThat(mPreference.isVisible()).isTrue();
     }
 
     @Test
-    public void testDisplayPreference_torchPresent_cameraOn_screenOn_verifyEnabled() {
+    public void testDisplayPreference_torchPresent_cameraOn_screenOn_isVisible() {
         setFlashNotificationsState(FlashNotificationsUtil.State.CAMERA_SCREEN);
 
         mController.displayPreference(mPreferenceScreen);
-        verify(mPreference).setEnabled(eq(true));
+
+        assertThat(mPreference.isVisible()).isTrue();
     }
 
     @Test
     public void testHandlePreferenceTreeClick_invalidPreference() {
         mController.handlePreferenceTreeClick(mock(Preference.class));
+
         verify(mContext, never()).sendBroadcastAsUser(any(), any());
     }
 
@@ -160,6 +166,7 @@
     @Test
     public void onStateChanged_onResume_cameraUri_verifyRegister() {
         mController.onStateChanged(mock(LifecycleOwner.class), Lifecycle.Event.ON_RESUME);
+
         verify(mContentResolver).registerContentObserver(
                 eq(Settings.System.getUriFor(Settings.System.CAMERA_FLASH_NOTIFICATION)),
                 anyBoolean(), eq(mController.mContentObserver));
@@ -168,6 +175,7 @@
     @Test
     public void onStateChanged_onResume_screenUri_verifyRegister() {
         mController.onStateChanged(mock(LifecycleOwner.class), Lifecycle.Event.ON_RESUME);
+
         verify(mContentResolver).registerContentObserver(
                 eq(Settings.System.getUriFor(Settings.System.SCREEN_FLASH_NOTIFICATION)),
                 anyBoolean(), eq(mController.mContentObserver));
@@ -176,6 +184,7 @@
     @Test
     public void onStateChanged_onPause_verifyUnregister() {
         mController.onStateChanged(mock(LifecycleOwner.class), Lifecycle.Event.ON_PAUSE);
+
         verify(mContentResolver).unregisterContentObserver(eq(mController.mContentObserver));
     }
 }
diff --git a/tests/robotests/src/com/android/settings/bluetooth/BluetoothDetailsProfilesControllerTest.java b/tests/robotests/src/com/android/settings/bluetooth/BluetoothDetailsProfilesControllerTest.java
index 219c37b..4f084a4 100644
--- a/tests/robotests/src/com/android/settings/bluetooth/BluetoothDetailsProfilesControllerTest.java
+++ b/tests/robotests/src/com/android/settings/bluetooth/BluetoothDetailsProfilesControllerTest.java
@@ -114,7 +114,7 @@
         setUpMockProfiles();
         when(mCachedBluetoothDeviceManager.getCachedDevicesCopy())
                 .thenReturn(ImmutableList.of(mCachedDevice));
-        when(mCachedDevice.getConnectableProfiles())
+        when(mCachedDevice.getUiAccessibleProfiles())
                 .thenAnswer(invocation -> new ArrayList<>(mConnectableProfiles));
         when(mCachedDevice.getProfiles())
                 .thenAnswer(invocation -> ImmutableList.of(mConnectableProfiles));
diff --git a/tests/robotests/src/com/android/settings/connecteddevice/audiosharing/AudioSharingDevicePreferenceControllerTest.java b/tests/robotests/src/com/android/settings/connecteddevice/audiosharing/AudioSharingDevicePreferenceControllerTest.java
index f3f32ae..03f1303 100644
--- a/tests/robotests/src/com/android/settings/connecteddevice/audiosharing/AudioSharingDevicePreferenceControllerTest.java
+++ b/tests/robotests/src/com/android/settings/connecteddevice/audiosharing/AudioSharingDevicePreferenceControllerTest.java
@@ -303,7 +303,7 @@
 
     @Test
     public void onProfileConnectionStateChanged_notMediaDevice_doNothing() {
-        doReturn(ImmutableList.of()).when(mCachedDevice).getConnectableProfiles();
+        doReturn(ImmutableList.of()).when(mCachedDevice).getUiAccessibleProfiles();
         mController.onProfileConnectionStateChanged(
                 mCachedDevice, BluetoothAdapter.STATE_CONNECTED, BluetoothProfile.HID_DEVICE);
         verifyNoInteractions(mDialogHandler);
@@ -313,7 +313,7 @@
     public void onProfileConnectionStateChanged_leaDeviceDisconnected_closeOpeningDialogsForIt() {
         // Test when LEA device LE_AUDIO_BROADCAST_ASSISTANT disconnected.
         when(mDevice.isConnected()).thenReturn(true);
-        doReturn(ImmutableList.of(mLeAudioProfile)).when(mCachedDevice).getConnectableProfiles();
+        doReturn(ImmutableList.of(mLeAudioProfile)).when(mCachedDevice).getUiAccessibleProfiles();
         doReturn(ImmutableList.of(mLeAudioProfile)).when(mCachedDevice).getProfiles();
         mController.onProfileConnectionStateChanged(
                 mCachedDevice,
@@ -325,7 +325,7 @@
     @Test
     public void onProfileConnectionStateChanged_assistantProfileConnecting_doNothing() {
         // Test when LEA device LE_AUDIO_BROADCAST_ASSISTANT connecting
-        doReturn(ImmutableList.of(mLeAudioProfile)).when(mCachedDevice).getConnectableProfiles();
+        doReturn(ImmutableList.of(mLeAudioProfile)).when(mCachedDevice).getUiAccessibleProfiles();
         doReturn(ImmutableList.of(mLeAudioProfile)).when(mCachedDevice).getProfiles();
         mController.onProfileConnectionStateChanged(
                 mCachedDevice,
@@ -338,7 +338,7 @@
     public void onProfileConnectionStateChanged_otherProfileConnected_doNothing() {
         // Test when LEA device other profile connected
         when(mDevice.isConnected()).thenReturn(true);
-        doReturn(ImmutableList.of(mLeAudioProfile)).when(mCachedDevice).getConnectableProfiles();
+        doReturn(ImmutableList.of(mLeAudioProfile)).when(mCachedDevice).getUiAccessibleProfiles();
         doReturn(ImmutableList.of(mLeAudioProfile)).when(mCachedDevice).getProfiles();
         mController.onProfileConnectionStateChanged(
                 mCachedDevice, BluetoothAdapter.STATE_CONNECTED, BluetoothProfile.A2DP);
@@ -349,7 +349,7 @@
     public void onProfileConnectionStateChanged_otherProfileConnecting_doNothing() {
         // Test when LEA device other profile connecting
         when(mDevice.isConnected()).thenReturn(true);
-        doReturn(ImmutableList.of(mLeAudioProfile)).when(mCachedDevice).getConnectableProfiles();
+        doReturn(ImmutableList.of(mLeAudioProfile)).when(mCachedDevice).getUiAccessibleProfiles();
         doReturn(ImmutableList.of(mLeAudioProfile)).when(mCachedDevice).getProfiles();
         mController.onProfileConnectionStateChanged(
                 mCachedDevice, BluetoothAdapter.STATE_CONNECTING, BluetoothProfile.A2DP);
@@ -360,7 +360,7 @@
     public void onProfileConnectionStateChanged_assistantProfileConnected_handle() {
         // Test when LEA device LE_AUDIO_BROADCAST_ASSISTANT connected
         when(mDevice.isConnected()).thenReturn(true);
-        doReturn(ImmutableList.of(mLeAudioProfile)).when(mCachedDevice).getConnectableProfiles();
+        doReturn(ImmutableList.of(mLeAudioProfile)).when(mCachedDevice).getUiAccessibleProfiles();
         doReturn(ImmutableList.of(mLeAudioProfile)).when(mCachedDevice).getProfiles();
         mController.onProfileConnectionStateChanged(
                 mCachedDevice,
@@ -374,7 +374,7 @@
             onProfileConnectionStateChanged_nonLeaDeviceDisconnected_closeOpeningDialogsForIt() {
         // Test when non-LEA device totally disconnected
         when(mLeAudioProfile.isEnabled(mDevice)).thenReturn(false);
-        doReturn(ImmutableList.of(mA2dpProfile)).when(mCachedDevice).getConnectableProfiles();
+        doReturn(ImmutableList.of(mA2dpProfile)).when(mCachedDevice).getUiAccessibleProfiles();
         doReturn(ImmutableList.of(mLeAudioProfile, mA2dpProfile)).when(mCachedDevice).getProfiles();
         when(mCachedDevice.isConnected()).thenReturn(false);
         mController.onProfileConnectionStateChanged(
@@ -390,7 +390,7 @@
                 .thenReturn(BluetoothAdapter.STATE_CONNECTED);
         doReturn(ImmutableList.of(mA2dpProfile, mHeadsetProfile))
                 .when(mCachedDevice)
-                .getConnectableProfiles();
+                .getUiAccessibleProfiles();
         doReturn(ImmutableList.of(mA2dpProfile, mHeadsetProfile)).when(mCachedDevice).getProfiles();
         mController.onProfileConnectionStateChanged(
                 mCachedDevice, BluetoothAdapter.STATE_CONNECTED, BluetoothProfile.A2DP);
@@ -405,7 +405,7 @@
                 .thenReturn(BluetoothAdapter.STATE_DISCONNECTED);
         doReturn(ImmutableList.of(mA2dpProfile, mHeadsetProfile))
                 .when(mCachedDevice)
-                .getConnectableProfiles();
+                .getUiAccessibleProfiles();
         doReturn(ImmutableList.of(mA2dpProfile, mHeadsetProfile)).when(mCachedDevice).getProfiles();
         mController.onProfileConnectionStateChanged(
                 mCachedDevice, BluetoothAdapter.STATE_CONNECTED, BluetoothProfile.A2DP);
diff --git a/tests/robotests/src/com/android/settings/connecteddevice/audiosharing/AudioSharingDeviceVolumeControlUpdaterTest.java b/tests/robotests/src/com/android/settings/connecteddevice/audiosharing/AudioSharingDeviceVolumeControlUpdaterTest.java
index 3c12946..95e51e9 100644
--- a/tests/robotests/src/com/android/settings/connecteddevice/audiosharing/AudioSharingDeviceVolumeControlUpdaterTest.java
+++ b/tests/robotests/src/com/android/settings/connecteddevice/audiosharing/AudioSharingDeviceVolumeControlUpdaterTest.java
@@ -31,15 +31,11 @@
 import static org.mockito.Mockito.when;
 import static org.robolectric.Shadows.shadowOf;
 
-import android.app.settings.SettingsEnums;
 import android.bluetooth.BluetoothDevice;
 import android.bluetooth.BluetoothLeBroadcastReceiveState;
 import android.bluetooth.BluetoothProfile;
 import android.content.Context;
-import android.media.AudioManager;
 import android.os.Looper;
-import android.provider.Settings;
-import android.widget.SeekBar;
 
 import androidx.preference.Preference;
 import androidx.test.core.app.ApplicationProvider;
@@ -47,7 +43,6 @@
 import com.android.settings.bluetooth.BluetoothDevicePreference;
 import com.android.settings.bluetooth.Utils;
 import com.android.settings.connecteddevice.DevicePreferenceCallback;
-import com.android.settings.testutils.FakeFeatureFactory;
 import com.android.settings.testutils.shadow.ShadowBluetoothUtils;
 import com.android.settingslib.bluetooth.CachedBluetoothDevice;
 import com.android.settingslib.bluetooth.CachedBluetoothDeviceManager;
@@ -55,7 +50,6 @@
 import com.android.settingslib.bluetooth.LocalBluetoothLeBroadcastAssistant;
 import com.android.settingslib.bluetooth.LocalBluetoothManager;
 import com.android.settingslib.bluetooth.LocalBluetoothProfileManager;
-import com.android.settingslib.bluetooth.VolumeControlProfile;
 
 import com.google.common.collect.ImmutableList;
 import com.google.common.collect.ImmutableSet;
@@ -80,13 +74,7 @@
 @Config(shadows = {ShadowBluetoothUtils.class})
 public class AudioSharingDeviceVolumeControlUpdaterTest {
     private static final String TEST_DEVICE_NAME = "test";
-    private static final String TAG = "AudioSharingDeviceVolumeControlUpdater";
-    private static final String TEST_SETTINGS_KEY =
-            "bluetooth_le_broadcast_fallback_active_group_id";
-    private static final int TEST_DEVICE_GROUP_ID = 1;
-    private static final int TEST_VOLUME_VALUE = 255;
-    private static final int TEST_MAX_STREAM_VALUE = 10;
-    private static final int TEST_MIN_STREAM_VALUE = 0;
+    private static final String TAG = "AudioSharingVolUpdater";
 
     @Rule public final MockitoRule mMockitoRule = MockitoJUnit.rule();
 
@@ -98,39 +86,32 @@
     @Mock private LocalBluetoothProfileManager mLocalBtProfileManager;
     @Mock private LocalBluetoothLeBroadcast mBroadcast;
     @Mock private LocalBluetoothLeBroadcastAssistant mAssistant;
-    @Mock private VolumeControlProfile mVolumeControl;
     @Mock private BluetoothLeBroadcastReceiveState mState;
-    @Mock private AudioManager mAudioManager;
 
     private Context mContext;
     private AudioSharingDeviceVolumeControlUpdater mDeviceUpdater;
     private Collection<CachedBluetoothDevice> mCachedDevices;
-    private FakeFeatureFactory mFeatureFactory;
 
     @Before
     public void setUp() {
-        mContext = spy(ApplicationProvider.getApplicationContext());
+        mContext = ApplicationProvider.getApplicationContext();
         ShadowBluetoothUtils.sLocalBluetoothManager = mLocalBtManager;
         mLocalBtManager = Utils.getLocalBtManager(mContext);
-        mFeatureFactory = FakeFeatureFactory.setupForTest();
         when(mLocalBtManager.getCachedDeviceManager()).thenReturn(mCachedDeviceManager);
         when(mLocalBtManager.getProfileManager()).thenReturn(mLocalBtProfileManager);
         when(mLocalBtProfileManager.getLeAudioBroadcastProfile()).thenReturn(mBroadcast);
         when(mLocalBtProfileManager.getLeAudioBroadcastAssistantProfile()).thenReturn(mAssistant);
-        when(mLocalBtProfileManager.getVolumeControlProfile()).thenReturn(mVolumeControl);
         List<Long> bisSyncState = new ArrayList<>();
         bisSyncState.add(1L);
         when(mState.getBisSyncState()).thenReturn(bisSyncState);
         doReturn(TEST_DEVICE_NAME).when(mCachedBluetoothDevice).getName();
         doReturn(mBluetoothDevice).when(mCachedBluetoothDevice).getDevice();
         doReturn(ImmutableSet.of()).when(mCachedBluetoothDevice).getMemberDevice();
-        doReturn(TEST_DEVICE_GROUP_ID).when(mCachedBluetoothDevice).getGroupId();
         mCachedDevices = new ArrayList<>();
         mCachedDevices.add(mCachedBluetoothDevice);
         when(mCachedDeviceManager.getCachedDevicesCopy()).thenReturn(mCachedDevices);
         doNothing().when(mDevicePreferenceCallback).onDeviceAdded(any(Preference.class));
         doNothing().when(mDevicePreferenceCallback).onDeviceRemoved(any(Preference.class));
-        when(mContext.getSystemService(AudioManager.class)).thenReturn(mAudioManager);
         mDeviceUpdater =
                 spy(
                         new AudioSharingDeviceVolumeControlUpdater(
@@ -251,76 +232,6 @@
     }
 
     @Test
-    public void addPreference_notFallbackDevice_setDeviceVolume() {
-        ArgumentCaptor<Preference> captor = ArgumentCaptor.forClass(Preference.class);
-        setupPreferenceMapWithDevice();
-
-        verify(mDevicePreferenceCallback).onDeviceAdded(captor.capture());
-        assertThat(captor.getValue() instanceof AudioSharingDeviceVolumePreference).isTrue();
-        AudioSharingDeviceVolumePreference preference =
-                (AudioSharingDeviceVolumePreference) captor.getValue();
-
-        SeekBar seekBar = mock(SeekBar.class);
-        when(seekBar.getProgress()).thenReturn(TEST_VOLUME_VALUE);
-        preference.onStopTrackingTouch(seekBar);
-
-        verify(mVolumeControl)
-                .setDeviceVolume(mBluetoothDevice, TEST_VOLUME_VALUE, /* isGroupOp= */ true);
-        verifyNoInteractions(mAudioManager);
-        verify(mFeatureFactory.metricsFeatureProvider)
-                .action(
-                        mContext,
-                        SettingsEnums.ACTION_AUDIO_SHARING_CHANGE_MEDIA_DEVICE_VOLUME,
-                        /* isPrimary= */ false);
-    }
-
-    @Test
-    public void addPreference_fallbackDevice_setStreamVolume() {
-        ArgumentCaptor<Preference> captor = ArgumentCaptor.forClass(Preference.class);
-        setupPreferenceMapWithDevice();
-
-        verify(mDevicePreferenceCallback).onDeviceAdded(captor.capture());
-        assertThat(captor.getValue() instanceof AudioSharingDeviceVolumePreference).isTrue();
-        AudioSharingDeviceVolumePreference preference =
-                (AudioSharingDeviceVolumePreference) captor.getValue();
-
-        Settings.Secure.putInt(
-                mContext.getContentResolver(), TEST_SETTINGS_KEY, TEST_DEVICE_GROUP_ID);
-        when(mAudioManager.getStreamMaxVolume(AudioManager.STREAM_MUSIC))
-                .thenReturn(TEST_MAX_STREAM_VALUE);
-        when(mAudioManager.getStreamMinVolume(AudioManager.STREAM_MUSIC))
-                .thenReturn(TEST_MIN_STREAM_VALUE);
-        SeekBar seekBar = mock(SeekBar.class);
-        when(seekBar.getProgress()).thenReturn(TEST_VOLUME_VALUE);
-        preference.onStopTrackingTouch(seekBar);
-
-        verifyNoInteractions(mVolumeControl);
-        verify(mAudioManager)
-                .setStreamVolume(AudioManager.STREAM_MUSIC, TEST_MAX_STREAM_VALUE, /* flags= */ 0);
-        verify(mFeatureFactory.metricsFeatureProvider)
-                .action(
-                        mContext,
-                        SettingsEnums.ACTION_AUDIO_SHARING_CHANGE_MEDIA_DEVICE_VOLUME,
-                        /* isPrimary= */ true);
-    }
-
-    @Test
-    public void testOnSeekBarChangeListener_doNothing() {
-        ArgumentCaptor<Preference> captor = ArgumentCaptor.forClass(Preference.class);
-        setupPreferenceMapWithDevice();
-
-        verify(mDevicePreferenceCallback).onDeviceAdded(captor.capture());
-        assertThat(captor.getValue() instanceof AudioSharingDeviceVolumePreference).isTrue();
-        AudioSharingDeviceVolumePreference preference =
-                (AudioSharingDeviceVolumePreference) captor.getValue();
-        SeekBar seekBar = mock(SeekBar.class);
-        preference.onProgressChanged(seekBar, TEST_VOLUME_VALUE, /* fromUser= */ false);
-
-        verifyNoInteractions(mAudioManager);
-        verifyNoInteractions(mVolumeControl);
-    }
-
-    @Test
     public void getLogTag_returnsCorrectTag() {
         assertThat(mDeviceUpdater.getLogTag()).isEqualTo(TAG);
     }
diff --git a/tests/robotests/src/com/android/settings/connecteddevice/audiosharing/AudioSharingDeviceVolumePreferenceTest.java b/tests/robotests/src/com/android/settings/connecteddevice/audiosharing/AudioSharingDeviceVolumePreferenceTest.java
index 8ceb0eb..5ff143f 100644
--- a/tests/robotests/src/com/android/settings/connecteddevice/audiosharing/AudioSharingDeviceVolumePreferenceTest.java
+++ b/tests/robotests/src/com/android/settings/connecteddevice/audiosharing/AudioSharingDeviceVolumePreferenceTest.java
@@ -18,11 +18,32 @@
 
 import static com.google.common.truth.Truth.assertThat;
 
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.anyBoolean;
+import static org.mockito.ArgumentMatchers.eq;
+import static org.mockito.Mockito.never;
+import static org.mockito.Mockito.spy;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.verifyNoInteractions;
+import static org.mockito.Mockito.when;
+
+import android.app.settings.SettingsEnums;
+import android.bluetooth.BluetoothDevice;
 import android.content.Context;
+import android.media.AudioManager;
+import android.provider.Settings;
+import android.widget.SeekBar;
 
 import androidx.test.core.app.ApplicationProvider;
 
+import com.android.settings.bluetooth.Utils;
+import com.android.settings.testutils.FakeFeatureFactory;
+import com.android.settings.testutils.shadow.ShadowBluetoothUtils;
+import com.android.settingslib.bluetooth.BluetoothUtils;
 import com.android.settingslib.bluetooth.CachedBluetoothDevice;
+import com.android.settingslib.bluetooth.LocalBluetoothManager;
+import com.android.settingslib.bluetooth.LocalBluetoothProfileManager;
+import com.android.settingslib.bluetooth.VolumeControlProfile;
 
 import org.junit.Before;
 import org.junit.Rule;
@@ -32,18 +53,45 @@
 import org.mockito.junit.MockitoJUnit;
 import org.mockito.junit.MockitoRule;
 import org.robolectric.RobolectricTestRunner;
+import org.robolectric.annotation.Config;
 
 @RunWith(RobolectricTestRunner.class)
+@Config(shadows = {ShadowBluetoothUtils.class})
 public class AudioSharingDeviceVolumePreferenceTest {
+    private static final int TEST_DEVICE_GROUP_ID = 1;
+    private static final int TEST_VOLUME_VALUE = 255;
+    private static final int TEST_MAX_STREAM_VALUE = 10;
+    private static final int TEST_MIN_STREAM_VALUE = 0;
+
     @Rule public final MockitoRule mMockitoRule = MockitoJUnit.rule();
 
+    @Mock private LocalBluetoothManager mLocalBtManager;
+    @Mock private LocalBluetoothProfileManager mLocalBtProfileManager;
+    @Mock private VolumeControlProfile mVolumeControl;
     @Mock private CachedBluetoothDevice mCachedDevice;
+    @Mock private BluetoothDevice mDevice;
+    @Mock private AudioManager mAudioManager;
+    @Mock private SeekBar mSeekBar;
     private Context mContext;
     private AudioSharingDeviceVolumePreference mPreference;
+    private FakeFeatureFactory mFeatureFactory;
 
     @Before
     public void setup() {
-        mContext = ApplicationProvider.getApplicationContext();
+        mContext = spy(ApplicationProvider.getApplicationContext());
+        ShadowBluetoothUtils.sLocalBluetoothManager = mLocalBtManager;
+        mLocalBtManager = Utils.getLocalBtManager(mContext);
+        mFeatureFactory = FakeFeatureFactory.setupForTest();
+        when(mLocalBtManager.getProfileManager()).thenReturn(mLocalBtProfileManager);
+        when(mLocalBtProfileManager.getVolumeControlProfile()).thenReturn(mVolumeControl);
+        when(mContext.getSystemService(AudioManager.class)).thenReturn(mAudioManager);
+        when(mAudioManager.getStreamMaxVolume(AudioManager.STREAM_MUSIC))
+                .thenReturn(TEST_MAX_STREAM_VALUE);
+        when(mAudioManager.getStreamMinVolume(AudioManager.STREAM_MUSIC))
+                .thenReturn(TEST_MIN_STREAM_VALUE);
+        when(mCachedDevice.getDevice()).thenReturn(mDevice);
+        when(mCachedDevice.getGroupId()).thenReturn(TEST_DEVICE_GROUP_ID);
+        when(mSeekBar.getProgress()).thenReturn(TEST_VOLUME_VALUE);
         mPreference = new AudioSharingDeviceVolumePreference(mContext, mCachedDevice);
     }
 
@@ -58,4 +106,128 @@
         assertThat(mPreference.getMax()).isEqualTo(AudioSharingDeviceVolumePreference.MAX_VOLUME);
         assertThat(mPreference.getMin()).isEqualTo(AudioSharingDeviceVolumePreference.MIN_VOLUME);
     }
+
+    @Test
+    public void onStopTrackingTouch_notFallbackDevice_setDeviceVolume() {
+        mPreference.onStopTrackingTouch(mSeekBar);
+
+        verify(mVolumeControl).setDeviceVolume(mDevice, TEST_VOLUME_VALUE, /* isGroupOp= */ true);
+        verifyNoInteractions(mAudioManager);
+        verify(mFeatureFactory.metricsFeatureProvider)
+                .action(
+                        mContext,
+                        SettingsEnums.ACTION_AUDIO_SHARING_CHANGE_MEDIA_DEVICE_VOLUME,
+                        /* isPrimary= */ false);
+    }
+
+    @Test
+    public void onProgressChanged_notFallbackDevice_fromUserNotInTouch_setDeviceVolume() {
+        mPreference.onProgressChanged(mSeekBar, TEST_VOLUME_VALUE, /* fromUser= */ true);
+
+        verify(mVolumeControl).setDeviceVolume(mDevice, TEST_VOLUME_VALUE, /* isGroupOp= */ true);
+        verifyNoInteractions(mAudioManager);
+        verify(mFeatureFactory.metricsFeatureProvider)
+                .action(
+                        mContext,
+                        SettingsEnums.ACTION_AUDIO_SHARING_CHANGE_MEDIA_DEVICE_VOLUME,
+                        /* isPrimary= */ false);
+    }
+
+    @Test
+    public void onProgressChanged_notFallbackDevice_fromUserInTouch_doNothing() {
+        mPreference.onStartTrackingTouch(mSeekBar);
+        mPreference.onProgressChanged(mSeekBar, TEST_VOLUME_VALUE, /* fromUser= */ true);
+
+        verifyNoInteractions(mVolumeControl);
+        verifyNoInteractions(mAudioManager);
+        verify(mFeatureFactory.metricsFeatureProvider, never())
+                .action(
+                        any(Context.class),
+                        eq(SettingsEnums.ACTION_AUDIO_SHARING_CHANGE_MEDIA_DEVICE_VOLUME),
+                        anyBoolean());
+    }
+
+    @Test
+    public void onProgressChanged_notFallbackDevice_notFromUserNotInTouch_doNothing() {
+        mPreference.onProgressChanged(mSeekBar, TEST_VOLUME_VALUE, /* fromUser= */ false);
+
+        verifyNoInteractions(mVolumeControl);
+        verifyNoInteractions(mAudioManager);
+        verify(mFeatureFactory.metricsFeatureProvider, never())
+                .action(
+                        any(Context.class),
+                        eq(SettingsEnums.ACTION_AUDIO_SHARING_CHANGE_MEDIA_DEVICE_VOLUME),
+                        anyBoolean());
+    }
+
+    @Test
+    public void onStopTrackingTouch_fallbackDevice_setDeviceVolume() {
+        Settings.Secure.putInt(
+                mContext.getContentResolver(),
+                BluetoothUtils.getPrimaryGroupIdUriForBroadcast(),
+                TEST_DEVICE_GROUP_ID);
+        mPreference.onStopTrackingTouch(mSeekBar);
+
+        verifyNoInteractions(mVolumeControl);
+        verify(mAudioManager)
+                .setStreamVolume(AudioManager.STREAM_MUSIC, TEST_MAX_STREAM_VALUE, /* flags= */ 0);
+        verify(mFeatureFactory.metricsFeatureProvider)
+                .action(
+                        mContext,
+                        SettingsEnums.ACTION_AUDIO_SHARING_CHANGE_MEDIA_DEVICE_VOLUME,
+                        /* isPrimary= */ true);
+    }
+
+    @Test
+    public void onProgressChanged_fallbackDevice_fromUserNotInTouch_setDeviceVolume() {
+        Settings.Secure.putInt(
+                mContext.getContentResolver(),
+                BluetoothUtils.getPrimaryGroupIdUriForBroadcast(),
+                TEST_DEVICE_GROUP_ID);
+        mPreference.onProgressChanged(mSeekBar, TEST_VOLUME_VALUE, /* fromUser= */ true);
+
+        verifyNoInteractions(mVolumeControl);
+        verify(mAudioManager)
+                .setStreamVolume(AudioManager.STREAM_MUSIC, TEST_MAX_STREAM_VALUE, /* flags= */ 0);
+        verify(mFeatureFactory.metricsFeatureProvider)
+                .action(
+                        mContext,
+                        SettingsEnums.ACTION_AUDIO_SHARING_CHANGE_MEDIA_DEVICE_VOLUME,
+                        /* isPrimary= */ true);
+    }
+
+    @Test
+    public void onProgressChanged_fallbackDevice_fromUserInTouch_doNothing() {
+        Settings.Secure.putInt(
+                mContext.getContentResolver(),
+                BluetoothUtils.getPrimaryGroupIdUriForBroadcast(),
+                TEST_DEVICE_GROUP_ID);
+        mPreference.onStartTrackingTouch(mSeekBar);
+        mPreference.onProgressChanged(mSeekBar, TEST_VOLUME_VALUE, /* fromUser= */ true);
+
+        verifyNoInteractions(mVolumeControl);
+        verifyNoInteractions(mAudioManager);
+        verify(mFeatureFactory.metricsFeatureProvider, never())
+                .action(
+                        any(Context.class),
+                        eq(SettingsEnums.ACTION_AUDIO_SHARING_CHANGE_MEDIA_DEVICE_VOLUME),
+                        anyBoolean());
+    }
+
+    @Test
+    public void onProgressChanged_fallbackDevice_notFromUserNotInTouch_doNothing() {
+        Settings.Secure.putInt(
+                mContext.getContentResolver(),
+                BluetoothUtils.getPrimaryGroupIdUriForBroadcast(),
+                TEST_DEVICE_GROUP_ID);
+        mPreference.onProgressChanged(mSeekBar, TEST_VOLUME_VALUE, /* fromUser= */ false);
+
+        verifyNoInteractions(mVolumeControl);
+        verifyNoInteractions(mAudioManager);
+        verify(mFeatureFactory.metricsFeatureProvider, never())
+                .action(
+                        any(Context.class),
+                        eq(SettingsEnums.ACTION_AUDIO_SHARING_CHANGE_MEDIA_DEVICE_VOLUME),
+                        anyBoolean());
+    }
 }
diff --git a/tests/robotests/src/com/android/settings/connecteddevice/audiosharing/audiostreams/AudioStreamsHelperTest.java b/tests/robotests/src/com/android/settings/connecteddevice/audiosharing/audiostreams/AudioStreamsHelperTest.java
index b91866b..4266798 100644
--- a/tests/robotests/src/com/android/settings/connecteddevice/audiosharing/audiostreams/AudioStreamsHelperTest.java
+++ b/tests/robotests/src/com/android/settings/connecteddevice/audiosharing/audiostreams/AudioStreamsHelperTest.java
@@ -16,6 +16,9 @@
 
 package com.android.settings.connecteddevice.audiosharing.audiostreams;
 
+import static android.content.res.Configuration.ORIENTATION_LANDSCAPE;
+import static android.content.res.Configuration.ORIENTATION_PORTRAIT;
+
 import static com.google.common.truth.Truth.assertThat;
 
 import static org.mockito.ArgumentMatchers.any;
@@ -32,9 +35,13 @@
 import android.bluetooth.BluetoothLeBroadcastMetadata;
 import android.bluetooth.BluetoothLeBroadcastReceiveState;
 import android.content.Context;
+import android.content.res.Configuration;
+import android.content.res.Resources;
 
+import androidx.fragment.app.FragmentActivity;
 import androidx.test.core.app.ApplicationProvider;
 
+import com.android.settings.R;
 import com.android.settings.testutils.shadow.ShadowThreadUtils;
 import com.android.settingslib.bluetooth.CachedBluetoothDevice;
 import com.android.settingslib.bluetooth.CachedBluetoothDeviceManager;
@@ -42,6 +49,7 @@
 import com.android.settingslib.bluetooth.LocalBluetoothManager;
 import com.android.settingslib.bluetooth.LocalBluetoothProfileManager;
 
+import com.google.android.material.appbar.AppBarLayout;
 import com.google.common.collect.ImmutableList;
 import com.google.common.collect.ImmutableSet;
 
@@ -91,8 +99,7 @@
 
     @Test
     public void addSource_noDevice_doNothing() {
-        when(mAssistant.getAllConnectedDevices())
-                .thenReturn(Collections.emptyList());
+        when(mAssistant.getAllConnectedDevices()).thenReturn(Collections.emptyList());
         mHelper.addSource(mMetadata);
 
         verify(mAssistant, never()).addSource(any(), any(), anyBoolean());
@@ -114,8 +121,7 @@
 
     @Test
     public void removeSource_noDevice_doNothing() {
-        when(mAssistant.getAllConnectedDevices())
-                .thenReturn(Collections.emptyList());
+        when(mAssistant.getAllConnectedDevices()).thenReturn(Collections.emptyList());
         mHelper.removeSource(BROADCAST_ID_1);
 
         verify(mAssistant, never()).removeSource(any(), anyInt());
@@ -236,4 +242,40 @@
 
         verify(mContext).startService(any());
     }
+
+    @Test
+    public void configureAppBarByOrientation_landscape_shouldNotExpand() {
+        FragmentActivity fragmentActivity = mock(FragmentActivity.class);
+        // AppBarLayout requires a Theme.AppCompat.
+        mContext.setTheme(R.style.Theme_Settings_Home);
+        AppBarLayout appBarLayout = spy(new AppBarLayout(mContext));
+        setUpFragment(fragmentActivity, appBarLayout, ORIENTATION_LANDSCAPE);
+
+        AudioStreamsHelper.configureAppBarByOrientation(fragmentActivity);
+
+        verify(appBarLayout).setExpanded(eq(false));
+    }
+
+    @Test
+    public void configureAppBarByOrientation_portrait_shouldExpand() {
+        FragmentActivity fragmentActivity = mock(FragmentActivity.class);
+        // AppBarLayout requires a Theme.AppCompat.
+        mContext.setTheme(R.style.Theme_Settings_Home);
+        AppBarLayout appBarLayout = spy(new AppBarLayout(mContext));
+        setUpFragment(fragmentActivity, appBarLayout, ORIENTATION_PORTRAIT);
+
+        AudioStreamsHelper.configureAppBarByOrientation(fragmentActivity);
+
+        verify(appBarLayout).setExpanded(eq(true));
+    }
+
+    private void setUpFragment(
+            FragmentActivity fragmentActivity, AppBarLayout appBarLayout, int orientationPortrait) {
+        Resources resources = mock(Resources.class);
+        when(fragmentActivity.getResources()).thenReturn(resources);
+        Configuration configuration = new Configuration();
+        configuration.orientation = orientationPortrait;
+        when(resources.getConfiguration()).thenReturn(configuration);
+        when(fragmentActivity.findViewById(anyInt())).thenReturn(appBarLayout);
+    }
 }
diff --git a/tests/robotests/src/com/android/settings/fuelgauge/batteryusage/BatteryTipsCardPreferenceTest.java b/tests/robotests/src/com/android/settings/fuelgauge/batteryusage/BatteryTipsCardPreferenceTest.java
deleted file mode 100644
index 5f86301..0000000
--- a/tests/robotests/src/com/android/settings/fuelgauge/batteryusage/BatteryTipsCardPreferenceTest.java
+++ /dev/null
@@ -1,293 +0,0 @@
-/*
- * Copyright (C) 2023 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.settings.fuelgauge.batteryusage;
-
-import static com.google.common.truth.Truth.assertThat;
-
-import static org.mockito.ArgumentMatchers.any;
-import static org.mockito.ArgumentMatchers.eq;
-import static org.mockito.Mockito.doNothing;
-import static org.mockito.Mockito.doReturn;
-import static org.mockito.Mockito.never;
-import static org.mockito.Mockito.spy;
-import static org.mockito.Mockito.verify;
-import static org.mockito.Mockito.when;
-
-import android.app.settings.SettingsEnums;
-import android.content.Context;
-import android.content.Intent;
-import android.provider.Settings;
-import android.util.Pair;
-import android.view.View;
-
-import com.android.settings.DisplaySettings;
-import com.android.settings.R;
-import com.android.settings.SettingsActivity;
-import com.android.settings.testutils.BatteryTestUtils;
-import com.android.settings.testutils.FakeFeatureFactory;
-import com.android.settingslib.core.instrumentation.MetricsFeatureProvider;
-
-import org.junit.Before;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.mockito.ArgumentCaptor;
-import org.mockito.Mock;
-import org.mockito.MockitoAnnotations;
-import org.robolectric.RobolectricTestRunner;
-import org.robolectric.RuntimeEnvironment;
-
-import java.util.Map;
-import java.util.Optional;
-import java.util.TimeZone;
-
-@RunWith(RobolectricTestRunner.class)
-public final class BatteryTipsCardPreferenceTest {
-
-    private Context mContext;
-    private FakeFeatureFactory mFeatureFactory;
-    private BatteryTipsCardPreference mBatteryTipsCardPreference;
-    private PowerUsageAdvanced mPowerUsageAdvanced;
-    private BatteryTipsController mBatteryTipsController;
-    private BatteryChartPreferenceController mBatteryChartPreferenceController;
-
-    @Mock private View mFakeView;
-    @Mock private BatteryUsageBreakdownController mBatteryUsageBreakdownController;
-    @Mock private BatteryDiffEntry mFakeEntry;
-
-    @Before
-    public void setUp() {
-        MockitoAnnotations.initMocks(this);
-        TimeZone.setDefault(TimeZone.getTimeZone("GMT+8"));
-        mContext = spy(RuntimeEnvironment.application);
-        mFeatureFactory = FakeFeatureFactory.setupForTest();
-        mBatteryTipsCardPreference = new BatteryTipsCardPreference(mContext, /* attrs= */ null);
-        mBatteryTipsController = new BatteryTipsController(mContext);
-        mBatteryChartPreferenceController =
-                spy(new BatteryChartPreferenceController(mContext, null, null));
-        mBatteryChartPreferenceController.mPrefContext = mContext;
-        mBatteryTipsController.mCardPreference = mBatteryTipsCardPreference;
-
-        mPowerUsageAdvanced = spy(new PowerUsageAdvanced());
-        doReturn(mContext).when(mPowerUsageAdvanced).getContext();
-        mPowerUsageAdvanced.mBatteryTipsController = mBatteryTipsController;
-        mPowerUsageAdvanced.mBatteryChartPreferenceController = mBatteryChartPreferenceController;
-        mPowerUsageAdvanced.mBatteryUsageBreakdownController = mBatteryUsageBreakdownController;
-        mPowerUsageAdvanced.mBatteryLevelData =
-                Optional.of(
-                        new BatteryLevelData(
-                                Map.of(
-                                        1694354400000L, 1, // 2023-09-10 22:00:00
-                                        1694361600000L, 2, // 2023-09-11 00:00:00
-                                        1694368800000L, 3))); // 2023-09-11 02:00:00
-        doReturn("TestEntriesKey").when(mFakeEntry).getKey();
-    }
-
-    @Test
-    public void constructor_returnExpectedResult() {
-        assertThat(mBatteryTipsCardPreference.getLayoutResource())
-                .isEqualTo(R.layout.battery_tips_card);
-    }
-
-    @Test
-    public void onClick_mainBtnOfSettingsAnomalyLaunchPage_getAdaptiveBrightnessLauncher() {
-        final ArgumentCaptor<Intent> captor = ArgumentCaptor.forClass(Intent.class);
-        PowerAnomalyEvent adaptiveBrightnessAnomaly =
-                BatteryTestUtils.createAdaptiveBrightnessAnomalyEvent(/* changeSettings= */ false);
-        when(mFeatureFactory.powerUsageFeatureProvider.isBatteryTipsEnabled()).thenReturn(true);
-        when(mFakeView.getId()).thenReturn(R.id.main_button);
-        doNothing().when(mContext).startActivity(captor.capture());
-
-        mPowerUsageAdvanced.onDisplayAnomalyEventUpdated(
-                adaptiveBrightnessAnomaly, adaptiveBrightnessAnomaly);
-        mBatteryTipsCardPreference.onClick(mFakeView);
-
-        assertThat(mBatteryTipsCardPreference.isVisible()).isFalse();
-        verify(mContext).startActivity(any(Intent.class));
-        final Intent intent = captor.getValue();
-        assertThat(intent.getStringExtra(SettingsActivity.EXTRA_SHOW_FRAGMENT))
-                .isEqualTo(DisplaySettings.class.getName());
-        assertThat(intent.getIntExtra(MetricsFeatureProvider.EXTRA_SOURCE_METRICS_CATEGORY, -1))
-                .isEqualTo(SettingsEnums.DISPLAY);
-        verify(mFeatureFactory.metricsFeatureProvider)
-                .action(
-                        SettingsEnums.FUELGAUGE_BATTERY_HISTORY_DETAIL,
-                        SettingsEnums.ACTION_BATTERY_TIPS_CARD_SHOW,
-                        SettingsEnums.FUELGAUGE_BATTERY_HISTORY_DETAIL,
-                        BatteryTipsController.ANOMALY_KEY,
-                        PowerAnomalyKey.KEY_BRIGHTNESS.getNumber());
-        verify(mFeatureFactory.metricsFeatureProvider)
-                .action(
-                        SettingsEnums.FUELGAUGE_BATTERY_HISTORY_DETAIL,
-                        SettingsEnums.ACTION_BATTERY_TIPS_CARD_ACCEPT,
-                        SettingsEnums.FUELGAUGE_BATTERY_HISTORY_DETAIL,
-                        BatteryTipsController.ANOMALY_KEY,
-                        PowerAnomalyKey.KEY_BRIGHTNESS.getNumber());
-    }
-
-    @Test
-    public void onClick_mainBtnOfSettingsAnomalyChangeSettings_settingsChanged()
-            throws Settings.SettingNotFoundException {
-        Settings.System.putInt(
-                mContext.getContentResolver(),
-                Settings.System.SCREEN_BRIGHTNESS_MODE,
-                Settings.System.SCREEN_BRIGHTNESS_MODE_MANUAL);
-        final ArgumentCaptor<Intent> captor = ArgumentCaptor.forClass(Intent.class);
-        PowerAnomalyEvent adaptiveBrightnessAnomaly =
-                BatteryTestUtils.createAdaptiveBrightnessAnomalyEvent(/* changeSettings= */ true);
-        when(mFeatureFactory.powerUsageFeatureProvider.isBatteryTipsEnabled()).thenReturn(true);
-        when(mFakeView.getId()).thenReturn(R.id.main_button);
-        doNothing().when(mContext).startActivity(captor.capture());
-
-        mPowerUsageAdvanced.onDisplayAnomalyEventUpdated(
-                adaptiveBrightnessAnomaly, adaptiveBrightnessAnomaly);
-        mBatteryTipsCardPreference.onClick(mFakeView);
-
-        assertThat(mBatteryTipsCardPreference.isVisible()).isFalse();
-        assertThat(
-                        Settings.System.getInt(
-                                mContext.getContentResolver(),
-                                Settings.System.SCREEN_BRIGHTNESS_MODE))
-                .isEqualTo(Settings.System.SCREEN_BRIGHTNESS_MODE_AUTOMATIC);
-        verify(mContext, never()).startActivity(any(Intent.class));
-        verify(mFeatureFactory.metricsFeatureProvider)
-                .action(
-                        SettingsEnums.FUELGAUGE_BATTERY_HISTORY_DETAIL,
-                        SettingsEnums.ACTION_BATTERY_TIPS_CARD_SHOW,
-                        SettingsEnums.FUELGAUGE_BATTERY_HISTORY_DETAIL,
-                        BatteryTipsController.ANOMALY_KEY,
-                        PowerAnomalyKey.KEY_BRIGHTNESS.getNumber());
-        verify(mFeatureFactory.metricsFeatureProvider)
-                .action(
-                        SettingsEnums.FUELGAUGE_BATTERY_HISTORY_DETAIL,
-                        SettingsEnums.ACTION_BATTERY_TIPS_CARD_ACCEPT,
-                        SettingsEnums.FUELGAUGE_BATTERY_HISTORY_DETAIL,
-                        BatteryTipsController.ANOMALY_KEY,
-                        PowerAnomalyKey.KEY_BRIGHTNESS.getNumber());
-    }
-
-    @Test
-    public void onClick_dismissBtnOfSettingsAnomaly_cardDismissAndLogged() {
-        final PowerAnomalyEvent screenTimeoutAnomaly =
-                BatteryTestUtils.createScreenTimeoutAnomalyEvent();
-        DatabaseUtils.removeDismissedPowerAnomalyKeys(mContext);
-        when(mFeatureFactory.powerUsageFeatureProvider.isBatteryTipsEnabled()).thenReturn(true);
-        when(mFakeView.getId()).thenReturn(R.id.dismiss_button);
-
-        mPowerUsageAdvanced.onDisplayAnomalyEventUpdated(
-                screenTimeoutAnomaly, screenTimeoutAnomaly);
-        mBatteryTipsCardPreference.onClick(mFakeView);
-
-        assertThat(mBatteryTipsCardPreference.isVisible()).isFalse();
-        assertThat(DatabaseUtils.getDismissedPowerAnomalyKeys(mContext)).hasSize(1);
-        assertThat(DatabaseUtils.getDismissedPowerAnomalyKeys(mContext))
-                .contains(PowerAnomalyKey.KEY_SCREEN_TIMEOUT.name());
-        verify(mFeatureFactory.metricsFeatureProvider)
-                .action(
-                        SettingsEnums.FUELGAUGE_BATTERY_HISTORY_DETAIL,
-                        SettingsEnums.ACTION_BATTERY_TIPS_CARD_SHOW,
-                        SettingsEnums.FUELGAUGE_BATTERY_HISTORY_DETAIL,
-                        BatteryTipsController.ANOMALY_KEY,
-                        PowerAnomalyKey.KEY_SCREEN_TIMEOUT.getNumber());
-        verify(mFeatureFactory.metricsFeatureProvider)
-                .action(
-                        SettingsEnums.FUELGAUGE_BATTERY_HISTORY_DETAIL,
-                        SettingsEnums.ACTION_BATTERY_TIPS_CARD_DISMISS,
-                        SettingsEnums.FUELGAUGE_BATTERY_HISTORY_DETAIL,
-                        BatteryTipsController.ANOMALY_KEY,
-                        PowerAnomalyKey.KEY_SCREEN_TIMEOUT.getNumber());
-    }
-
-    @Test
-    public void onClick_mainBtnOfAppsAnomaly_selectHighlightSlot() {
-        final PowerAnomalyEvent appsAnomaly = BatteryTestUtils.createAppAnomalyEvent();
-        when(mFeatureFactory.powerUsageFeatureProvider.isBatteryTipsEnabled()).thenReturn(true);
-        when(mFakeView.getId()).thenReturn(R.id.main_button);
-        doNothing().when(mBatteryChartPreferenceController).selectHighlightSlotIndex();
-        when(mPowerUsageAdvanced.findRelatedBatteryDiffEntry(any())).thenReturn(mFakeEntry);
-
-        mPowerUsageAdvanced.onDisplayAnomalyEventUpdated(appsAnomaly, appsAnomaly);
-        assertHighlightSlotIndexPair(1, 0);
-        mBatteryTipsCardPreference.onClick(mFakeView);
-
-        assertThat(mBatteryTipsCardPreference.isVisible()).isFalse();
-        verify(mContext, never()).startActivity(any(Intent.class));
-        verify(mBatteryChartPreferenceController).onHighlightSlotIndexUpdate(eq(1), eq(0));
-        verify(mBatteryChartPreferenceController).selectHighlightSlotIndex();
-        verify(mFeatureFactory.metricsFeatureProvider)
-                .action(
-                        SettingsEnums.FUELGAUGE_BATTERY_HISTORY_DETAIL,
-                        SettingsEnums.ACTION_BATTERY_TIPS_CARD_SHOW,
-                        SettingsEnums.FUELGAUGE_BATTERY_HISTORY_DETAIL,
-                        BatteryTipsController.ANOMALY_KEY,
-                        PowerAnomalyKey.KEY_APP_TOTAL_HIGHER_THAN_USUAL.getNumber());
-        verify(mFeatureFactory.metricsFeatureProvider)
-                .action(
-                        SettingsEnums.FUELGAUGE_BATTERY_HISTORY_DETAIL,
-                        SettingsEnums.ACTION_BATTERY_TIPS_CARD_ACCEPT,
-                        SettingsEnums.FUELGAUGE_BATTERY_HISTORY_DETAIL,
-                        BatteryTipsController.ANOMALY_KEY,
-                        PowerAnomalyKey.KEY_APP_TOTAL_HIGHER_THAN_USUAL.getNumber());
-    }
-
-    @Test
-    public void onClick_dismissBtnOfAppsAnomaly_keepHighlightSlotIndex() {
-        final PowerAnomalyEvent appsAnomaly = BatteryTestUtils.createAppAnomalyEvent();
-        when(mFeatureFactory.powerUsageFeatureProvider.isBatteryTipsEnabled()).thenReturn(true);
-        when(mFakeView.getId()).thenReturn(R.id.dismiss_button);
-        when(mPowerUsageAdvanced.findRelatedBatteryDiffEntry(any())).thenReturn(mFakeEntry);
-
-        mPowerUsageAdvanced.onDisplayAnomalyEventUpdated(appsAnomaly, appsAnomaly);
-        assertHighlightSlotIndexPair(1, 0);
-        mBatteryTipsCardPreference.onClick(mFakeView);
-
-        assertThat(mBatteryTipsCardPreference.isVisible()).isFalse();
-        verify(mContext, never()).startActivity(any(Intent.class));
-        verify(mBatteryChartPreferenceController).onHighlightSlotIndexUpdate(eq(1), eq(0));
-        verify(mBatteryChartPreferenceController, never()).selectHighlightSlotIndex();
-        verify(mFeatureFactory.metricsFeatureProvider)
-                .action(
-                        SettingsEnums.FUELGAUGE_BATTERY_HISTORY_DETAIL,
-                        SettingsEnums.ACTION_BATTERY_TIPS_CARD_SHOW,
-                        SettingsEnums.FUELGAUGE_BATTERY_HISTORY_DETAIL,
-                        BatteryTipsController.ANOMALY_KEY,
-                        PowerAnomalyKey.KEY_APP_TOTAL_HIGHER_THAN_USUAL.getNumber());
-        verify(mFeatureFactory.metricsFeatureProvider)
-                .action(
-                        SettingsEnums.FUELGAUGE_BATTERY_HISTORY_DETAIL,
-                        SettingsEnums.ACTION_BATTERY_TIPS_CARD_DISMISS,
-                        SettingsEnums.FUELGAUGE_BATTERY_HISTORY_DETAIL,
-                        BatteryTipsController.ANOMALY_KEY,
-                        PowerAnomalyKey.KEY_APP_TOTAL_HIGHER_THAN_USUAL.getNumber());
-    }
-
-    private void assertHighlightSlotIndexPair(
-            int dailyHighlightSlotIndex, int hourlyHighlightSlotIndex) {
-        assertThat(mPowerUsageAdvanced.mBatteryLevelData.isPresent()).isTrue();
-        assertThat(mPowerUsageAdvanced.mHighlightEventWrapper.isPresent()).isTrue();
-        Pair<Integer, Integer> slotIndexPair =
-                mPowerUsageAdvanced
-                        .mHighlightEventWrapper
-                        .get()
-                        .getHighlightSlotPair(mPowerUsageAdvanced.mBatteryLevelData.get());
-        assertThat(slotIndexPair)
-                .isEqualTo(Pair.create(dailyHighlightSlotIndex, hourlyHighlightSlotIndex));
-        assertThat(mPowerUsageAdvanced.mBatteryChartPreferenceController.mDailyHighlightSlotIndex)
-                .isEqualTo(dailyHighlightSlotIndex);
-        assertThat(mPowerUsageAdvanced.mBatteryChartPreferenceController.mHourlyHighlightSlotIndex)
-                .isEqualTo(hourlyHighlightSlotIndex);
-    }
-}
diff --git a/tests/robotests/src/com/android/settings/fuelgauge/batteryusage/BatteryTipsControllerTest.java b/tests/robotests/src/com/android/settings/fuelgauge/batteryusage/BatteryTipsControllerTest.java
index 954437f..6c29036b 100644
--- a/tests/robotests/src/com/android/settings/fuelgauge/batteryusage/BatteryTipsControllerTest.java
+++ b/tests/robotests/src/com/android/settings/fuelgauge/batteryusage/BatteryTipsControllerTest.java
@@ -16,8 +16,13 @@
 
 package com.android.settings.fuelgauge.batteryusage;
 
+
+import static com.google.common.truth.Truth.assertThat;
+
 import static org.mockito.Mockito.doReturn;
+import static org.mockito.Mockito.never;
 import static org.mockito.Mockito.spy;
+import static org.mockito.Mockito.times;
 import static org.mockito.Mockito.verify;
 import static org.mockito.Mockito.when;
 
@@ -29,11 +34,11 @@
 import com.android.settings.R;
 import com.android.settings.testutils.BatteryTestUtils;
 import com.android.settings.testutils.FakeFeatureFactory;
+import com.android.settings.widget.TipCardPreference;
 
 import org.junit.Before;
 import org.junit.Test;
 import org.junit.runner.RunWith;
-import org.mockito.Mock;
 import org.mockito.MockitoAnnotations;
 import org.robolectric.RobolectricTestRunner;
 import org.robolectric.RuntimeEnvironment;
@@ -47,134 +52,156 @@
     private Context mContext;
     private FakeFeatureFactory mFeatureFactory;
     private BatteryTipsController mBatteryTipsController;
-
-    @Mock private BatteryTipsCardPreference mBatteryTipsCardPreference;
+    private TipCardPreference mCardPreference;
 
     @Before
     public void setUp() {
         MockitoAnnotations.initMocks(this);
         Locale.setDefault(new Locale("en_US"));
-        org.robolectric.shadows.ShadowSettings.set24HourTimeFormat(false);
         TimeZone.setDefault(TimeZone.getTimeZone("UTC"));
+
         mContext = spy(RuntimeEnvironment.application);
         final Resources resources = spy(mContext.getResources());
         resources.getConfiguration().setLocales(new LocaleList(new Locale("en_US")));
         doReturn(resources).when(mContext).getResources();
         mFeatureFactory = FakeFeatureFactory.setupForTest();
-        mBatteryTipsController = new BatteryTipsController(mContext);
-        mBatteryTipsController.mCardPreference = mBatteryTipsCardPreference;
+        mBatteryTipsController = spy(new BatteryTipsController(mContext));
+        mCardPreference = new TipCardPreference(mContext);
+        mBatteryTipsController.mCardPreference = mCardPreference;
     }
 
     @Test
     public void handleBatteryTipsCardUpdated_null_hidePreference() {
         mBatteryTipsController.handleBatteryTipsCardUpdated(/* powerAnomalyEvents= */ null, false);
 
-        verify(mBatteryTipsCardPreference).setVisible(false);
+        assertThat(mCardPreference.isVisible()).isFalse();
     }
 
     @Test
     public void handleBatteryTipsCardUpdated_adaptiveBrightnessAnomaly_showAnomaly() {
-        PowerAnomalyEvent event = BatteryTestUtils.createAdaptiveBrightnessAnomalyEvent();
+        AnomalyEventWrapper anomalyEventWrapper =
+                spy(
+                        new AnomalyEventWrapper(
+                                mContext,
+                                BatteryTestUtils.createAdaptiveBrightnessAnomalyEvent(true)));
         when(mFeatureFactory.powerUsageFeatureProvider.isBatteryTipsEnabled()).thenReturn(true);
 
-        mBatteryTipsController.handleBatteryTipsCardUpdated(
-                new AnomalyEventWrapper(mContext, event), false);
+        mBatteryTipsController.handleBatteryTipsCardUpdated(anomalyEventWrapper, false);
 
-        // Check pre-defined string
-        verify(mBatteryTipsCardPreference)
-                .setTitle("Turn on adaptive brightness to extend battery life");
-        verify(mBatteryTipsCardPreference).setIconResourceId(R.drawable.ic_battery_tips_lightbulb);
-        verify(mBatteryTipsCardPreference).setButtonColorResourceId(R.color.color_accent_selector);
-        verify(mBatteryTipsCardPreference).setMainButtonLabel("View Settings");
-        verify(mBatteryTipsCardPreference).setDismissButtonLabel("Got it");
-        // Check proto info
-        verify(mBatteryTipsCardPreference).setVisible(true);
-        verify(mFeatureFactory.metricsFeatureProvider)
-                .action(
-                        SettingsEnums.FUELGAUGE_BATTERY_HISTORY_DETAIL,
-                        SettingsEnums.ACTION_BATTERY_TIPS_CARD_SHOW,
-                        SettingsEnums.FUELGAUGE_BATTERY_HISTORY_DETAIL,
-                        BatteryTipsController.ANOMALY_KEY,
-                        PowerAnomalyKey.KEY_BRIGHTNESS.getNumber());
+        assertThat(mCardPreference.getTitle())
+                .isEqualTo("Turn on adaptive brightness to extend battery life");
+        assertThat(mCardPreference.getPrimaryButtonText()).isEqualTo("Got it");
+        assertThat(mCardPreference.getSecondaryButtonText()).isEqualTo("View Settings");
+        assertThat(mCardPreference.getIconResId()).isEqualTo(R.drawable.ic_battery_tips_lightbulb);
+        assertThat(mCardPreference.getTintColorResId()).isEqualTo(R.color.color_accent_selector);
+        assertThat(mCardPreference.getPrimaryButtonVisibility()).isTrue();
+        assertThat(mCardPreference.getSecondaryButtonVisibility()).isTrue();
+        assertCardButtonActionAndMetrics(anomalyEventWrapper);
     }
 
     @Test
     public void handleBatteryTipsCardUpdated_screenTimeoutAnomaly_showAnomaly() {
-        PowerAnomalyEvent event = BatteryTestUtils.createScreenTimeoutAnomalyEvent();
+        AnomalyEventWrapper anomalyEventWrapper =
+                spy(
+                        new AnomalyEventWrapper(
+                                mContext, BatteryTestUtils.createScreenTimeoutAnomalyEvent(true)));
         when(mFeatureFactory.powerUsageFeatureProvider.isBatteryTipsEnabled()).thenReturn(true);
 
-        mBatteryTipsController.handleBatteryTipsCardUpdated(
-                new AnomalyEventWrapper(mContext, event), false);
+        mBatteryTipsController.handleBatteryTipsCardUpdated(anomalyEventWrapper, false);
 
-        verify(mBatteryTipsCardPreference).setTitle("Reduce screen timeout to extend battery life");
-        verify(mBatteryTipsCardPreference).setIconResourceId(R.drawable.ic_battery_tips_lightbulb);
-        verify(mBatteryTipsCardPreference).setButtonColorResourceId(R.color.color_accent_selector);
-        verify(mBatteryTipsCardPreference).setMainButtonLabel("View Settings");
-        verify(mBatteryTipsCardPreference).setDismissButtonLabel("Got it");
-        verify(mBatteryTipsCardPreference).setVisible(true);
-        verify(mFeatureFactory.metricsFeatureProvider)
-                .action(
-                        SettingsEnums.FUELGAUGE_BATTERY_HISTORY_DETAIL,
-                        SettingsEnums.ACTION_BATTERY_TIPS_CARD_SHOW,
-                        SettingsEnums.FUELGAUGE_BATTERY_HISTORY_DETAIL,
-                        BatteryTipsController.ANOMALY_KEY,
-                        PowerAnomalyKey.KEY_SCREEN_TIMEOUT.getNumber());
+        assertThat(mCardPreference.getTitle())
+                .isEqualTo("Reduce screen timeout to extend battery life");
+        assertThat(mCardPreference.getPrimaryButtonText()).isEqualTo("Got it");
+        assertThat(mCardPreference.getSecondaryButtonText()).isEqualTo("View Settings");
+        assertThat(mCardPreference.getIconResId()).isEqualTo(R.drawable.ic_battery_tips_lightbulb);
+        assertThat(mCardPreference.getTintColorResId()).isEqualTo(R.color.color_accent_selector);
+        assertThat(mCardPreference.getPrimaryButtonVisibility()).isTrue();
+        assertThat(mCardPreference.getSecondaryButtonVisibility()).isTrue();
+        assertCardButtonActionAndMetrics(anomalyEventWrapper);
     }
 
     @Test
     public void handleBatteryTipsCardUpdated_screenTimeoutAnomalyHasTitle_showAnomaly() {
-        PowerAnomalyEvent event = BatteryTestUtils.createScreenTimeoutAnomalyEvent();
+        PowerAnomalyEvent anomalyEvent = BatteryTestUtils.createScreenTimeoutAnomalyEvent(true);
         String testTitle = "TestTitle";
-        event =
-                event.toBuilder()
+        anomalyEvent =
+                anomalyEvent.toBuilder()
                         .setWarningBannerInfo(
-                                event.getWarningBannerInfo().toBuilder()
+                                anomalyEvent.getWarningBannerInfo().toBuilder()
                                         .setTitleString(testTitle)
                                         .build())
                         .build();
+        AnomalyEventWrapper anomalyEventWrapper =
+                spy(new AnomalyEventWrapper(mContext, anomalyEvent));
         when(mFeatureFactory.powerUsageFeatureProvider.isBatteryTipsEnabled()).thenReturn(true);
 
-        mBatteryTipsController.handleBatteryTipsCardUpdated(
-                new AnomalyEventWrapper(mContext, event), false);
+        mBatteryTipsController.handleBatteryTipsCardUpdated(anomalyEventWrapper, false);
 
-        verify(mBatteryTipsCardPreference).setTitle(testTitle);
-        verify(mBatteryTipsCardPreference).setIconResourceId(R.drawable.ic_battery_tips_lightbulb);
-        verify(mBatteryTipsCardPreference).setButtonColorResourceId(R.color.color_accent_selector);
-        verify(mBatteryTipsCardPreference).setMainButtonLabel("View Settings");
-        verify(mBatteryTipsCardPreference).setDismissButtonLabel("Got it");
-        verify(mBatteryTipsCardPreference).setVisible(true);
-        verify(mFeatureFactory.metricsFeatureProvider)
-                .action(
-                        SettingsEnums.FUELGAUGE_BATTERY_HISTORY_DETAIL,
-                        SettingsEnums.ACTION_BATTERY_TIPS_CARD_SHOW,
-                        SettingsEnums.FUELGAUGE_BATTERY_HISTORY_DETAIL,
-                        BatteryTipsController.ANOMALY_KEY,
-                        PowerAnomalyKey.KEY_SCREEN_TIMEOUT.getNumber());
+        assertThat(mCardPreference.getTitle()).isEqualTo(testTitle);
+        assertThat(mCardPreference.getPrimaryButtonText()).isEqualTo("Got it");
+        assertThat(mCardPreference.getSecondaryButtonText()).isEqualTo("View Settings");
+        assertThat(mCardPreference.getIconResId()).isEqualTo(R.drawable.ic_battery_tips_lightbulb);
+        assertThat(mCardPreference.getTintColorResId()).isEqualTo(R.color.color_accent_selector);
+        assertThat(mCardPreference.getPrimaryButtonVisibility()).isTrue();
+        assertThat(mCardPreference.getSecondaryButtonVisibility()).isTrue();
+        assertCardButtonActionAndMetrics(anomalyEventWrapper);
     }
 
     @Test
     public void handleBatteryTipsCardUpdated_appAnomaly_showAnomaly() {
-        PowerAnomalyEvent event = BatteryTestUtils.createAppAnomalyEvent();
+        AnomalyEventWrapper anomalyEventWrapper =
+                spy(new AnomalyEventWrapper(mContext, BatteryTestUtils.createAppAnomalyEvent()));
         when(mFeatureFactory.powerUsageFeatureProvider.isBatteryTipsEnabled()).thenReturn(true);
 
-        AnomalyEventWrapper eventWrapper = new AnomalyEventWrapper(mContext, event);
-        eventWrapper.setRelatedBatteryDiffEntry(new BatteryDiffEntry(mContext, "", "Chrome", 0));
-        mBatteryTipsController.handleBatteryTipsCardUpdated(eventWrapper, false);
+        anomalyEventWrapper.setRelatedBatteryDiffEntry(
+                new BatteryDiffEntry(mContext, "", "Chrome", 0));
+        mBatteryTipsController.setOnAnomalyConfirmListener(
+                () -> mBatteryTipsController.acceptTipsCard());
+        mBatteryTipsController.handleBatteryTipsCardUpdated(anomalyEventWrapper, true);
 
-        verify(mBatteryTipsCardPreference).setTitle("Chrome used more battery than usual");
-        verify(mBatteryTipsCardPreference)
-                .setIconResourceId(R.drawable.ic_battery_tips_warning_icon);
-        verify(mBatteryTipsCardPreference)
-                .setButtonColorResourceId(R.color.color_battery_anomaly_app_warning_selector);
-        verify(mBatteryTipsCardPreference).setMainButtonLabel("Check");
-        verify(mBatteryTipsCardPreference).setDismissButtonLabel("Got it");
-        verify(mBatteryTipsCardPreference).setVisible(true);
+        assertThat(mCardPreference.getTitle()).isEqualTo("Chrome used more battery than usual");
+        assertThat(mCardPreference.getPrimaryButtonText()).isEqualTo("Got it");
+        assertThat(mCardPreference.getSecondaryButtonText()).isEqualTo("Check");
+        assertThat(mCardPreference.getIconResId())
+                .isEqualTo(R.drawable.ic_battery_tips_warning_icon);
+        assertThat(mCardPreference.getTintColorResId())
+                .isEqualTo(R.color.color_battery_anomaly_app_warning_selector);
+        assertThat(mCardPreference.getPrimaryButtonVisibility()).isTrue();
+        assertThat(mCardPreference.getSecondaryButtonVisibility()).isTrue();
+        assertThat(mCardPreference.isVisible()).isTrue();
+        assertCardButtonActionAndMetrics(anomalyEventWrapper);
+    }
+
+    private void assertCardButtonActionAndMetrics(final AnomalyEventWrapper anomalyEventWrapper) {
+        when(anomalyEventWrapper.updateSystemSettingsIfAvailable()).thenReturn(true);
+
+        final int powerAnomalyKeyNumber = anomalyEventWrapper.getAnomalyKeyNumber();
+        assertCardMetrics(SettingsEnums.ACTION_BATTERY_TIPS_CARD_SHOW, powerAnomalyKeyNumber);
+        assertThat(mCardPreference.isVisible()).isTrue();
+
+        // Check accept button action
+        mCardPreference.setVisible(true);
+        mCardPreference.getSecondaryButtonAction().invoke();
+        assertCardMetrics(SettingsEnums.ACTION_BATTERY_TIPS_CARD_ACCEPT, powerAnomalyKeyNumber);
+        assertThat(mCardPreference.isVisible()).isFalse();
+        final boolean isAppAnomalyCard = powerAnomalyKeyNumber > 1;
+        verify(anomalyEventWrapper, isAppAnomalyCard ? never() : times(1))
+                .updateSystemSettingsIfAvailable();
+
+        // Check reject button action
+        mCardPreference.setVisible(true);
+        mCardPreference.getPrimaryButtonAction().invoke();
+        assertCardMetrics(SettingsEnums.ACTION_BATTERY_TIPS_CARD_DISMISS, powerAnomalyKeyNumber);
+        assertThat(mCardPreference.isVisible()).isFalse();
+    }
+
+    private void assertCardMetrics(final int action, final int powerAnomalyKeyNumber) {
         verify(mFeatureFactory.metricsFeatureProvider)
                 .action(
                         SettingsEnums.FUELGAUGE_BATTERY_HISTORY_DETAIL,
-                        SettingsEnums.ACTION_BATTERY_TIPS_CARD_SHOW,
+                        action,
                         SettingsEnums.FUELGAUGE_BATTERY_HISTORY_DETAIL,
                         BatteryTipsController.ANOMALY_KEY,
-                        PowerAnomalyKey.KEY_APP_TOTAL_HIGHER_THAN_USUAL.getNumber());
+                        powerAnomalyKeyNumber);
     }
 }
diff --git a/tests/robotests/src/com/android/settings/notification/modes/SetupInterstitialActivityTest.java b/tests/robotests/src/com/android/settings/notification/modes/SetupInterstitialActivityTest.java
index e73610b..129e56e 100644
--- a/tests/robotests/src/com/android/settings/notification/modes/SetupInterstitialActivityTest.java
+++ b/tests/robotests/src/com/android/settings/notification/modes/SetupInterstitialActivityTest.java
@@ -82,6 +82,41 @@
     }
 
     @Test
+    public void invalidIntent_doesNotQueryBackend() {
+        // Mode is set up sensibly
+        ZenMode mode = new TestModeBuilder().setId(MODE_ID).setEnabled(false).build();
+        when(mBackend.getMode(MODE_ID)).thenReturn(mode);
+
+        // but the intent is lacking the zen mode extra
+        ActivityScenario<SetupInterstitialActivity> scenario =
+                ActivityScenario.launch(new Intent(Intent.ACTION_MAIN)
+                        .setClass(RuntimeEnvironment.getApplication(),
+                                SetupInterstitialActivity.class));
+        // creating the scenario takes it through onResume(), which would query the backend if
+        // it had mode data.
+        scenario.onActivity(activity -> {
+            assertThat(activity.isFinishing()).isTrue();
+            verify(mBackend, never()).getMode(any());
+        });
+        scenario.close();
+    }
+
+    @Test
+    public void invalidModeId_doesNotCrash() {
+        when(mBackend.getMode(MODE_ID)).thenReturn(null);
+        ActivityScenario<SetupInterstitialActivity> scenario =
+                ActivityScenario.launch(new Intent(Intent.ACTION_MAIN)
+                        .setClass(RuntimeEnvironment.getApplication(),
+                                SetupInterstitialActivity.class)
+                        .putExtra(EXTRA_AUTOMATIC_ZEN_RULE_ID, MODE_ID));
+        // do nothing, but it would crash if attempting to work with a null mode at any point
+        scenario.onActivity(activity -> {
+            assertThat(activity.isFinishing()).isTrue();
+        });
+        scenario.close();
+    }
+
+    @Test
     public void enableButton_enablesModeAndRedirectsToModePage() {
         ZenMode mode = new TestModeBuilder().setId(MODE_ID).setEnabled(false).build();
         when(mBackend.getMode(MODE_ID)).thenReturn(mode);
diff --git a/tests/robotests/src/com/android/settings/notification/modes/ZenModesSummaryHelperTest.java b/tests/robotests/src/com/android/settings/notification/modes/ZenModeSummaryHelperTest.java
similarity index 81%
rename from tests/robotests/src/com/android/settings/notification/modes/ZenModesSummaryHelperTest.java
rename to tests/robotests/src/com/android/settings/notification/modes/ZenModeSummaryHelperTest.java
index 948eec0..a0e1d38 100644
--- a/tests/robotests/src/com/android/settings/notification/modes/ZenModesSummaryHelperTest.java
+++ b/tests/robotests/src/com/android/settings/notification/modes/ZenModeSummaryHelperTest.java
@@ -16,10 +16,6 @@
 
 package com.android.settings.notification.modes;
 
-import static android.provider.Settings.Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS;
-import static android.provider.Settings.Global.ZEN_MODE_OFF;
-import static android.service.notification.Condition.SOURCE_UNKNOWN;
-import static android.service.notification.Condition.STATE_TRUE;
 import static android.service.notification.ZenPolicy.CONVERSATION_SENDERS_ANYONE;
 import static android.service.notification.ZenPolicy.CONVERSATION_SENDERS_IMPORTANT;
 import static android.service.notification.ZenPolicy.PEOPLE_TYPE_ANYONE;
@@ -33,17 +29,16 @@
 
 import static org.robolectric.Shadows.shadowOf;
 
+import android.app.AutomaticZenRule;
 import android.app.Flags;
-import android.content.ComponentName;
 import android.content.Context;
 import android.content.pm.ApplicationInfo;
 import android.content.pm.UserInfo;
-import android.net.Uri;
 import android.os.UserHandle;
 import android.os.UserManager;
 import android.platform.test.annotations.EnableFlags;
 import android.platform.test.flag.junit.SetFlagsRule;
-import android.service.notification.Condition;
+import android.service.notification.SystemZenRules;
 import android.service.notification.ZenDeviceEffects;
 import android.service.notification.ZenModeConfig;
 import android.service.notification.ZenPolicy;
@@ -65,7 +60,8 @@
 import java.util.Random;
 
 @RunWith(RobolectricTestRunner.class)
-public class ZenModesSummaryHelperTest {
+@EnableFlags(Flags.FLAG_MODES_UI)
+public class ZenModeSummaryHelperTest {
     private static final int WORK_PROFILE_ID = 3;
 
     private Context mContext;
@@ -480,85 +476,90 @@
     }
 
     @Test
-    @EnableFlags(Flags.FLAG_MODES_UI)
-    public void getSoundSummary_off_noRules() {
-        ZenModeConfig config = new ZenModeConfig();
-
-        assertThat(mSummaryHelper.getSoundSummary(ZEN_MODE_OFF, config)).isEqualTo("Off");
+    public void getModesSummary_noRules_noSummary() {
+        String summary = mSummaryHelper.getModesSummary(ImmutableList.of());
+        assertThat(summary).isEmpty();
     }
 
     @Test
-    @EnableFlags(Flags.FLAG_MODES_UI)
-    public void getSoundSummary_off_oneRule() {
-        ZenModeConfig config = new ZenModeConfig();
-        ZenModeConfig.ZenRule rule = new ZenModeConfig.ZenRule();
-        rule.enabled = true;
-        config.automaticRules.put("key", rule);
-
-        assertThat(mSummaryHelper.getSoundSummary(ZEN_MODE_OFF, config))
-                .isEqualTo("Off / 1 mode can turn on automatically");
+    public void getModesSummary_onlyDndAndNotActive_noSummary() {
+        ImmutableList<ZenMode> modes = ImmutableList.of(TestModeBuilder.MANUAL_DND_INACTIVE);
+        String summary = mSummaryHelper.getModesSummary(modes);
+        assertThat(summary).isEmpty();
     }
 
     @Test
-    @EnableFlags(Flags.FLAG_MODES_UI)
-    public void getSoundSummary_off_twoRules() {
-        ZenModeConfig config = new ZenModeConfig();
-        ZenModeConfig.ZenRule rule = new ZenModeConfig.ZenRule();
-        rule.enabled = true;
-        ZenModeConfig.ZenRule rule2 = new ZenModeConfig.ZenRule();
-        rule2.enabled = true;
-        config.automaticRules.put("key", rule);
-        config.automaticRules.put("key2", rule2);
+    public void getModesSummary_noRulesActive_countsOnlyEnabledAutomaticModes() {
+        ImmutableList<ZenMode> modes = ImmutableList.of(
+                TestModeBuilder.MANUAL_DND_INACTIVE, // Not automatic
+                new TestModeBuilder().setName("Auto 1").build(), // App provided automatic
+                new TestModeBuilder()
+                        .setName("Custom manual 1")
+                        .setPackage(SystemZenRules.PACKAGE_ANDROID)
+                        .setType(AutomaticZenRule.TYPE_OTHER)
+                        .setConditionId(ZenModeConfig.toCustomManualConditionId())
+                        .build(), // Custom manual, not automatic
+                new TestModeBuilder()
+                        .setName("Disabled 1")
+                        .setEnabled(false)
+                        .build(), // Would be automatic, but it's disabled.
+                new TestModeBuilder()
+                        .setName("Sleep")
+                        .setPackage(SystemZenRules.PACKAGE_ANDROID)
+                        .setType(AutomaticZenRule.TYPE_SCHEDULE_TIME)
+                        .build() // Time based, automatic.
+        );
 
-        assertThat(mSummaryHelper.getSoundSummary(ZEN_MODE_OFF, config))
-                .isEqualTo("Off / 2 modes can turn on automatically");
+        String summary = mSummaryHelper.getModesSummary(modes);
+        assertThat(summary).isEqualTo("2 modes can turn on automatically");
     }
 
     @Test
-    @EnableFlags(Flags.FLAG_MODES_UI)
-    public void getSoundSummary_on_noDescription() {
-        ZenModeConfig config = new ZenModeConfig();
-        config.manualRule.conditionId = Uri.EMPTY;
-        config.manualRule.pkg = "android";
-        config.manualRule.zenMode = ZEN_MODE_IMPORTANT_INTERRUPTIONS;
-        config.manualRule.condition = new Condition(Uri.EMPTY, "", STATE_TRUE, SOURCE_UNKNOWN);
-        assertThat(mSummaryHelper.getSoundSummary(ZEN_MODE_IMPORTANT_INTERRUPTIONS, config))
-                .isEqualTo("On");
+    public void getModesSummary_oneModeActive_listsMode() {
+        ImmutableList<ZenMode> modes = ImmutableList.of(
+                TestModeBuilder.MANUAL_DND_ACTIVE,
+                new TestModeBuilder().setName("Inactive").setActive(false).build());
+
+        String summary = mSummaryHelper.getModesSummary(modes);
+        assertThat(summary).isEqualTo("Do Not Disturb is active");
     }
 
     @Test
-    @EnableFlags(Flags.FLAG_MODES_UI)
-    public void getSoundSummary_on_manualDescription() {
-        ZenModeConfig config = new ZenModeConfig();
-        config.manualRule.conditionId = ZenModeConfig.toCountdownConditionId(
-                System.currentTimeMillis() + 10000, false);
-        config.manualRule.pkg = "android";
-        config.manualRule.zenMode = ZEN_MODE_IMPORTANT_INTERRUPTIONS;
-        config.manualRule.condition = new Condition(Uri.EMPTY, "", STATE_TRUE, SOURCE_UNKNOWN);
-        assertThat(mSummaryHelper.getSoundSummary(ZEN_MODE_IMPORTANT_INTERRUPTIONS, config))
-                .startsWith("On /");
+    public void getModesSummary_twoModesActive_listsModes() {
+        ImmutableList<ZenMode> modes = ImmutableList.of(
+                TestModeBuilder.MANUAL_DND_ACTIVE,
+                new TestModeBuilder().setName("Inactive").setActive(false).build(),
+                new TestModeBuilder().setName("Active #1").setActive(true).build());
+
+        String summary = mSummaryHelper.getModesSummary(modes);
+        assertThat(summary).isEqualTo("Do Not Disturb and Active #1 are active");
     }
 
     @Test
-    @EnableFlags(Flags.FLAG_MODES_UI)
-    public void getSoundSummary_on_automatic() {
-        ZenModeConfig config = new ZenModeConfig();
-        ZenModeConfig.ZenRule rule = new ZenModeConfig.ZenRule();
-        rule.configurationActivity = new ComponentName("a", "a");
-        rule.component = new ComponentName("b", "b");
-        rule.conditionId = new Uri.Builder().scheme("hello").build();
-        rule.condition = new Condition(rule.conditionId, "", STATE_TRUE);
-        rule.enabled = true;
-        rule.creationTime = 123;
-        rule.id = "id";
-        rule.zenMode = ZEN_MODE_IMPORTANT_INTERRUPTIONS;
-        rule.modified = true;
-        rule.name = "name";
-        rule.snoozing = false;
-        rule.pkg = "b";
-        config.automaticRules.put("key", rule);
+    public void getModesSummary_threeModesActive_listsModes() {
+        ImmutableList<ZenMode> modes = ImmutableList.of(
+                TestModeBuilder.MANUAL_DND_INACTIVE,
+                new TestModeBuilder().setName("Inactive #1").setActive(false).build(),
+                new TestModeBuilder().setName("Active #1").setActive(true).build(),
+                new TestModeBuilder().setName("Active #2").setActive(true).build(),
+                new TestModeBuilder().setName("Inactive #2").setActive(false).build(),
+                new TestModeBuilder().setName("Active #3").setActive(true).build());
 
-        assertThat(mSummaryHelper.getSoundSummary(ZEN_MODE_IMPORTANT_INTERRUPTIONS, config))
-                .startsWith("On /");
+        String summary = mSummaryHelper.getModesSummary(modes);
+        assertThat(summary).isEqualTo("Active #1, Active #2, and Active #3 are active");
+    }
+
+    @Test
+    public void getModesSummary_manyModesActive_listsACouple() {
+        ImmutableList<ZenMode> modes = ImmutableList.of(
+                TestModeBuilder.MANUAL_DND_ACTIVE,
+                new TestModeBuilder().setName("Inactive #1").setActive(false).build(),
+                new TestModeBuilder().setName("Active #1").setActive(true).build(),
+                new TestModeBuilder().setName("Active #2").setActive(true).build(),
+                new TestModeBuilder().setName("Inactive #2").setActive(false).build(),
+                new TestModeBuilder().setName("Active #3").setActive(true).build());
+
+        String summary = mSummaryHelper.getModesSummary(modes);
+        assertThat(summary).isEqualTo("Do Not Disturb, Active #1, and 2 more are active");
     }
 }
diff --git a/tests/robotests/src/com/android/settings/password/ConfirmLockPasswordTest.java b/tests/robotests/src/com/android/settings/password/ConfirmLockPasswordTest.java
index 4ac375f..9e8535a 100644
--- a/tests/robotests/src/com/android/settings/password/ConfirmLockPasswordTest.java
+++ b/tests/robotests/src/com/android/settings/password/ConfirmLockPasswordTest.java
@@ -16,6 +16,8 @@
 
 package com.android.settings.password;
 
+import static android.content.pm.PackageManager.COMPONENT_ENABLED_STATE_ENABLED;
+
 import static com.android.settings.password.ConfirmLockPassword.ConfirmLockPasswordFragment;
 import static com.android.settings.password.TestUtils.GUESS_INVALID_RESULT;
 import static com.android.settings.password.TestUtils.GUESS_VALID_RESULT;
@@ -42,6 +44,7 @@
 import android.Manifest;
 import android.app.KeyguardManager;
 import android.app.admin.ManagedSubscriptionsPolicy;
+import android.content.ComponentName;
 import android.content.Context;
 import android.content.Intent;
 import android.os.UserHandle;
@@ -55,6 +58,7 @@
 
 import com.android.internal.widget.LockPatternUtils;
 import com.android.settings.R;
+import com.android.settings.SetupRedactionInterstitial;
 import com.android.settings.testutils.shadow.ShadowDevicePolicyManager;
 import com.android.settings.testutils.shadow.ShadowLockPatternUtils;
 import com.android.settings.testutils.shadow.ShadowUserManager;
@@ -305,6 +309,32 @@
         assertThat(mLockPatternUtils.isSecure(fragment.mEffectiveUserId)).isFalse();
     }
 
+    @Test
+    public void onChosenLockSaveFinished_setsRedactionInterstitial() throws Exception {
+        // This test verifies that the RedactionInterstitial is available. This is the screen
+        // responsible for allowing the user to show sensitive lockscreen content. This
+        // also allows the Settings tile for RedactionInterstitial to appear in the "anything else"
+        // page during SUW.
+        final ConfirmDeviceCredentialBaseActivity activity =
+                buildConfirmDeviceCredentialBaseActivity(
+                        ConfirmLockPassword.class,
+                        createRemoteLockscreenValidationIntent(
+                                KeyguardManager.PASSWORD, VALID_REMAINING_ATTEMPTS));
+        final ConfirmLockPasswordFragment fragment =
+                (ConfirmLockPasswordFragment) getConfirmDeviceCredentialBaseFragment(activity);
+        final Intent intent = new Intent();
+        intent.putExtra(ChooseLockSettingsHelper.EXTRA_KEY_GK_PW_HANDLE, 1L);
+
+        fragment.onChosenLockSaveFinished(true, intent);
+
+        final ComponentName componentName =
+                new ComponentName(mContext, SetupRedactionInterstitial.class);
+        final int isEnabled = mContext.getPackageManager()
+                .getComponentEnabledSetting(componentName);
+
+        assertThat(isEnabled).isEqualTo(COMPONENT_ENABLED_STATE_ENABLED);
+    }
+
     private void triggerHandleNext(
             ConfirmLockPasswordFragment fragment, ImeAwareEditText passwordEntry) {
         passwordEntry.setText("Password");
diff --git a/tests/robotests/src/com/android/settings/password/ConfirmLockPatternTest.java b/tests/robotests/src/com/android/settings/password/ConfirmLockPatternTest.java
index 04a76b8..9e7ec06 100644
--- a/tests/robotests/src/com/android/settings/password/ConfirmLockPatternTest.java
+++ b/tests/robotests/src/com/android/settings/password/ConfirmLockPatternTest.java
@@ -16,6 +16,9 @@
 
 package com.android.settings.password;
 
+import static android.content.pm.PackageManager.COMPONENT_ENABLED_STATE_ENABLED;
+
+import static com.android.settings.password.ConfirmLockPattern.ConfirmLockPatternFragment;
 import static com.android.settings.password.TestUtils.GUESS_INVALID_RESULT;
 import static com.android.settings.password.TestUtils.GUESS_VALID_RESULT;
 import static com.android.settings.password.TestUtils.LOCKOUT_RESULT;
@@ -39,6 +42,7 @@
 import android.Manifest;
 import android.app.KeyguardManager;
 import android.app.admin.ManagedSubscriptionsPolicy;
+import android.content.ComponentName;
 import android.content.Context;
 import android.content.Intent;
 import android.os.UserHandle;
@@ -51,6 +55,7 @@
 import com.android.internal.widget.LockPatternUtils;
 import com.android.internal.widget.LockPatternView;
 import com.android.settings.R;
+import com.android.settings.SetupRedactionInterstitial;
 import com.android.settings.testutils.shadow.ShadowDevicePolicyManager;
 import com.android.settings.testutils.shadow.ShadowLockPatternUtils;
 import com.android.settings.testutils.shadow.ShadowUserManager;
@@ -284,6 +289,32 @@
         assertThat(mLockPatternUtils.isSecure(fragment.mEffectiveUserId)).isFalse();
     }
 
+    @Test
+    public void onChosenLockSaveFinished_setsRedactionInterstitial() throws Exception {
+        // This test verifies that the RedactionInterstitial is available. This is the screen
+        // responsible for allowing the user to show sensitive lockscreen content. This
+        // also allows the Settings tile for RedactionInterstitial to appear in the "anything else"
+        // page during SUW.
+        final ConfirmDeviceCredentialBaseActivity activity =
+                buildConfirmDeviceCredentialBaseActivity(
+                        ConfirmLockPattern.class,
+                        createRemoteLockscreenValidationIntent(
+                                KeyguardManager.PATTERN, VALID_REMAINING_ATTEMPTS));
+        final ConfirmLockPatternFragment fragment = (ConfirmLockPatternFragment)
+                getConfirmDeviceCredentialBaseFragment(activity);
+        final Intent intent = new Intent();
+        intent.putExtra(ChooseLockSettingsHelper.EXTRA_KEY_GK_PW_HANDLE, 1L);
+
+        fragment.onChosenLockSaveFinished(true, intent);
+
+        final ComponentName componentName =
+                new ComponentName(mContext, SetupRedactionInterstitial.class);
+        final int isEnabled = mContext.getPackageManager()
+                .getComponentEnabledSetting(componentName);
+
+        assertThat(isEnabled).isEqualTo(COMPONENT_ENABLED_STATE_ENABLED);
+    }
+
     private void triggerOnPatternDetected(LockPatternView lockPatternView) {
         List<LockPatternView.Cell> pattern = List.of(LockPatternView.Cell.of(0, 0));
         lockPatternView.setPattern(LockPatternView.DisplayMode.Correct, pattern);
diff --git a/tests/robotests/src/com/android/settings/slices/SettingsSliceProviderTest.java b/tests/robotests/src/com/android/settings/slices/SettingsSliceProviderTest.java
index 84c8586..edb310e 100644
--- a/tests/robotests/src/com/android/settings/slices/SettingsSliceProviderTest.java
+++ b/tests/robotests/src/com/android/settings/slices/SettingsSliceProviderTest.java
@@ -30,7 +30,6 @@
 import static org.mockito.ArgumentMatchers.anyString;
 import static org.mockito.ArgumentMatchers.eq;
 import static org.mockito.Mockito.doReturn;
-import static org.mockito.Mockito.mock;
 import static org.mockito.Mockito.never;
 import static org.mockito.Mockito.spy;
 import static org.mockito.Mockito.verify;
@@ -131,12 +130,18 @@
             CustomSliceRegistry.LOCATION_SLICE_URI
     );
 
-    private static final List<Uri> SPECIAL_CASE_OEM_URIS = Arrays.asList(
-            CustomSliceRegistry.ZEN_MODE_SLICE_URI,
-            CustomSliceRegistry.FLASHLIGHT_SLICE_URI,
-            CustomSliceRegistry.MOBILE_DATA_SLICE_URI,
-            CustomSliceRegistry.WIFI_CALLING_URI
-    );
+    private static final List<Uri> SPECIAL_CASE_OEM_URIS = android.app.Flags.modesUi()
+            ? Arrays.asList(
+                    CustomSliceRegistry.FLASHLIGHT_SLICE_URI,
+                    CustomSliceRegistry.MOBILE_DATA_SLICE_URI,
+                    CustomSliceRegistry.WIFI_CALLING_URI
+            ) :
+            Arrays.asList(
+                CustomSliceRegistry.ZEN_MODE_SLICE_URI,
+                CustomSliceRegistry.FLASHLIGHT_SLICE_URI,
+                CustomSliceRegistry.MOBILE_DATA_SLICE_URI,
+                CustomSliceRegistry.WIFI_CALLING_URI
+            );
 
     @Before
     public void setUp() {
diff --git a/tests/robotests/src/com/android/settings/testutils/BatteryTestUtils.java b/tests/robotests/src/com/android/settings/testutils/BatteryTestUtils.java
index a151632..951f2f0 100644
--- a/tests/robotests/src/com/android/settings/testutils/BatteryTestUtils.java
+++ b/tests/robotests/src/com/android/settings/testutils/BatteryTestUtils.java
@@ -264,18 +264,28 @@
 
     /** Create a power anomaly event proto of screen timeout. */
     public static PowerAnomalyEvent createScreenTimeoutAnomalyEvent() {
+        return createScreenTimeoutAnomalyEvent(false);
+    }
+
+    /** Create a power anomaly event proto of screen timeout. */
+    public static PowerAnomalyEvent createScreenTimeoutAnomalyEvent(boolean changeSettings) {
+        WarningBannerInfo.Builder warningBannerInfoBuilder =
+                WarningBannerInfo.newBuilder()
+                        .setMainButtonDestination(ScreenTimeoutSettings.class.getName())
+                        .setMainButtonSourceMetricsCategory(SettingsEnums.SCREEN_TIMEOUT)
+                        .setMainButtonSourceHighlightKey("60000");
+        if (changeSettings) {
+            warningBannerInfoBuilder
+                    .setMainButtonConfigSettingsName(Settings.System.SCREEN_OFF_TIMEOUT)
+                    .setMainButtonConfigSettingsValue(60000);
+        }
         return PowerAnomalyEvent.newBuilder()
                 .setEventId("ScreenTimeoutAnomaly")
                 .setType(PowerAnomalyType.TYPE_SETTINGS_BANNER)
                 .setKey(PowerAnomalyKey.KEY_SCREEN_TIMEOUT)
                 .setDismissRecordKey(PowerAnomalyKey.KEY_SCREEN_TIMEOUT.name())
                 .setScore(1.1f)
-                .setWarningBannerInfo(
-                        WarningBannerInfo.newBuilder()
-                                .setMainButtonDestination(ScreenTimeoutSettings.class.getName())
-                                .setMainButtonSourceMetricsCategory(SettingsEnums.SCREEN_TIMEOUT)
-                                .setMainButtonSourceHighlightKey("60000")
-                                .build())
+                .setWarningBannerInfo(warningBannerInfoBuilder.build())
                 .build();
     }
 
diff --git a/tests/spa_unit/src/com/android/settings/datausage/lib/AppDataUsageRepositoryTest.kt b/tests/spa_unit/src/com/android/settings/datausage/lib/AppDataUsageRepositoryTest.kt
index 3f517a9..5026b08 100644
--- a/tests/spa_unit/src/com/android/settings/datausage/lib/AppDataUsageRepositoryTest.kt
+++ b/tests/spa_unit/src/com/android/settings/datausage/lib/AppDataUsageRepositoryTest.kt
@@ -38,48 +38,55 @@
 import org.mockito.kotlin.doReturn
 import org.mockito.kotlin.mock
 import org.mockito.kotlin.spy
+import org.mockito.kotlin.stub
 
 @RunWith(AndroidJUnit4::class)
 class AppDataUsageRepositoryTest {
-    @get:Rule
-    val mockito: MockitoRule = MockitoJUnit.rule()
+    @get:Rule val mockito: MockitoRule = MockitoJUnit.rule()
 
-    private val mockUserManager = mock<UserManager> {
-        on { userProfiles } doReturn listOf(UserHandle.of(USER_ID))
-        on { getUserInfo(USER_ID) } doReturn UserInfo(USER_ID, "", 0)
-    }
+    private val mockUserManager =
+        mock<UserManager> {
+            on { userProfiles } doReturn listOf(UserHandle.of(USER_ID))
+            on { getUserInfo(USER_ID) } doReturn UserInfo(USER_ID, "", 0)
+        }
 
-    private val mockNetworkPolicyManager = mock<NetworkPolicyManager> {
-        on { getUidsWithPolicy(NetworkPolicyManager.POLICY_REJECT_METERED_BACKGROUND) } doReturn
-            intArrayOf()
-    }
+    private val mockNetworkPolicyManager =
+        mock<NetworkPolicyManager> {
+            on { getUidsWithPolicy(NetworkPolicyManager.POLICY_REJECT_METERED_BACKGROUND) } doReturn
+                intArrayOf()
+        }
 
-    private val mockResources = mock<Resources> {
-        on { getIntArray(R.array.datausage_hiding_carrier_service_carrier_id) } doReturn
-            intArrayOf(HIDING_CARRIER_ID)
+    private val mockResources =
+        mock<Resources> {
+            on { getIntArray(R.array.datausage_hiding_carrier_service_carrier_id) } doReturn
+                intArrayOf(HIDING_CARRIER_ID)
 
-        on { getStringArray(R.array.datausage_hiding_carrier_service_package_names) } doReturn
-            arrayOf(HIDING_PACKAGE_NAME)
-    }
+            on { getStringArray(R.array.datausage_hiding_carrier_service_package_names) } doReturn
+                arrayOf(HIDING_PACKAGE_NAME)
+        }
 
-    private val context: Context = spy(ApplicationProvider.getApplicationContext()) {
-        on { userManager } doReturn mockUserManager
-        on { getSystemService(NetworkPolicyManager::class.java) } doReturn mockNetworkPolicyManager
-        on { resources } doReturn mockResources
-    }
+    private val context: Context =
+        spy(ApplicationProvider.getApplicationContext()) {
+            on { userManager } doReturn mockUserManager
+            on { getSystemService(NetworkPolicyManager::class.java) } doReturn
+                mockNetworkPolicyManager
+            on { resources } doReturn mockResources
+        }
 
     @Test
     fun getAppPercent_noAppToHide() {
-        val repository = AppDataUsageRepository(
-            context = context,
-            currentUserId = USER_ID,
-            template = Template,
-            getPackageName = { null },
-        )
-        val buckets = listOf(
-            Bucket(uid = APP_ID_1, bytes = 1, startTimeStamp = 0, endTimeStamp = 0),
-            Bucket(uid = APP_ID_2, bytes = 2, startTimeStamp = 0, endTimeStamp = 0),
-        )
+        val repository =
+            AppDataUsageRepository(
+                context = context,
+                currentUserId = USER_ID,
+                template = Template,
+                getPackageName = { null },
+            )
+        val buckets =
+            listOf(
+                Bucket(uid = APP_ID_1, bytes = 1, startTimeStamp = 0, endTimeStamp = 0),
+                Bucket(uid = APP_ID_2, bytes = 2, startTimeStamp = 0, endTimeStamp = 0),
+            )
 
         val appPercentList = repository.getAppPercent(null, buckets)
 
@@ -100,16 +107,18 @@
 
     @Test
     fun getAppPercent_hasAppToHide() {
-        val repository = AppDataUsageRepository(
-            context = context,
-            currentUserId = USER_ID,
-            template = Template,
-            getPackageName = { if (it.key == APP_ID_1) HIDING_PACKAGE_NAME else null },
-        )
-        val buckets = listOf(
-            Bucket(uid = APP_ID_1, bytes = 1, startTimeStamp = 0, endTimeStamp = 0),
-            Bucket(uid = APP_ID_2, bytes = 2, startTimeStamp = 0, endTimeStamp = 0),
-        )
+        val repository =
+            AppDataUsageRepository(
+                context = context,
+                currentUserId = USER_ID,
+                template = Template,
+                getPackageName = { if (it.key == APP_ID_1) HIDING_PACKAGE_NAME else null },
+            )
+        val buckets =
+            listOf(
+                Bucket(uid = APP_ID_1, bytes = 1, startTimeStamp = 0, endTimeStamp = 0),
+                Bucket(uid = APP_ID_2, bytes = 2, startTimeStamp = 0, endTimeStamp = 0),
+            )
 
         val appPercentList = repository.getAppPercent(HIDING_CARRIER_ID, buckets)
 
@@ -122,6 +131,43 @@
         assertThat(appPercentList[0].second).isEqualTo(100)
     }
 
+    @Test
+    fun getAppPercent_restricted() {
+        mockNetworkPolicyManager.stub {
+            on { getUidsWithPolicy(NetworkPolicyManager.POLICY_REJECT_METERED_BACKGROUND) } doReturn
+                intArrayOf(APP_ID_1)
+        }
+        val repository =
+            AppDataUsageRepository(
+                context = context,
+                currentUserId = USER_ID,
+                template = Template,
+                getPackageName = { null },
+            )
+        val buckets =
+            listOf(
+                Bucket(uid = APP_ID_2, bytes = 2, startTimeStamp = 0, endTimeStamp = 0),
+            )
+
+        val appPercentList = repository.getAppPercent(null, buckets)
+
+        assertThat(appPercentList).hasSize(2)
+        appPercentList[0].first.apply {
+            assertThat(key).isEqualTo(APP_ID_2)
+            assertThat(category).isEqualTo(AppItem.CATEGORY_APP)
+            assertThat(total).isEqualTo(2)
+            assertThat(restricted).isFalse()
+        }
+        assertThat(appPercentList[0].second).isEqualTo(100)
+        appPercentList[1].first.apply {
+            assertThat(key).isEqualTo(APP_ID_1)
+            assertThat(category).isEqualTo(AppItem.CATEGORY_APP)
+            assertThat(total).isEqualTo(0)
+            assertThat(restricted).isTrue()
+        }
+        assertThat(appPercentList[1].second).isEqualTo(0)
+    }
+
     private companion object {
         const val USER_ID = 1
         const val APP_ID_1 = 110001