Merge "Support vendor modes in color mode preference" into sc-dev
diff --git a/res/drawable/baseline_near_me.xml b/res/drawable/baseline_near_me.xml
deleted file mode 100644
index 343f970..0000000
--- a/res/drawable/baseline_near_me.xml
+++ /dev/null
@@ -1,23 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2021 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.
--->
-<vector xmlns:android="http://schemas.android.com/apk/res/android"
-    android:width="24dp"
-    android:height="24dp"
-    android:viewportWidth="24"
-    android:viewportHeight="24"
-    android:tint="?attr/colorControlNormal">
-  <path
-      android:fillColor="@android:color/black"
-      android:pathData="M21,3L3,10.53v0.98l6.84,2.65L12.48,21h0.98L21,3z"/>
-</vector>
diff --git a/res/layout/apps_filter_spinner.xml b/res/layout/apps_filter_spinner.xml
index 13d8078..1de5705 100644
--- a/res/layout/apps_filter_spinner.xml
+++ b/res/layout/apps_filter_spinner.xml
@@ -36,7 +36,7 @@
         android:layout_width="56dp"
         android:layout_height="56dp"
         android:layout_marginTop="12dp"
-        android:layout_toRightOf="@id/filter_spinner"
+        android:layout_toEndOf="@id/filter_spinner"
         android:contentDescription="@string/configure"
         android:scaleType="center"
         android:src="@drawable/ic_apps_filter_settings_24dp"
diff --git a/res/layout/settings_collapsing_base_layout.xml b/res/layout/settings_collapsing_base_layout.xml
deleted file mode 100644
index 97d249c..0000000
--- a/res/layout/settings_collapsing_base_layout.xml
+++ /dev/null
@@ -1,68 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-     Copyright (C) 2021 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.
--->
-<androidx.coordinatorlayout.widget.CoordinatorLayout
-    xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:app="http://schemas.android.com/apk/res-auto"
-    android:id="@+id/content_parent"
-    android:layout_width="match_parent"
-    android:layout_height="match_parent"
-    android:fitsSystemWindows="true">
-
-    <com.google.android.material.appbar.AppBarLayout
-        android:id="@+id/app_bar"
-        android:layout_width="match_parent"
-        android:layout_height="wrap_content"
-        android:fitsSystemWindows="true"
-        android:outlineAmbientShadowColor="@android:color/transparent"
-        android:outlineSpotShadowColor="@android:color/transparent"
-        android:background="@android:color/transparent"
-        android:theme="@style/Theme.CollapsingToolbar.Settings">
-
-        <com.google.android.material.appbar.CollapsingToolbarLayout
-            android:id="@+id/collapsing_toolbar"
-            android:layout_width="match_parent"
-            android:layout_height="@dimen/toolbar_one_line_height"
-            android:clipToPadding="false"
-            app:contentScrim="@color/color_surface_header"
-            app:maxLines="3"
-            app:layout_scrollFlags="scroll|exitUntilCollapsed|snap"
-            app:scrimAnimationDuration="50"
-            app:scrimVisibleHeightTrigger="@dimen/scrim_visible_height_trigger"
-            app:statusBarScrim="@empty"
-            app:titleCollapseMode="fade"
-            app:collapsedTitleTextAppearance="@style/ToolbarText.Collapsed"
-            app:expandedTitleTextAppearance="@style/ToolbarText.Expanded"
-            app:expandedTitleMarginStart="@dimen/expanded_title_margin_start"
-            app:expandedTitleMarginEnd="@dimen/expanded_title_margin_end"
-            app:toolbarId="@id/action_bar">
-
-            <Toolbar
-                android:id="@+id/action_bar"
-                android:layout_width="match_parent"
-                android:layout_height="?attr/actionBarSize"
-                android:theme="?android:attr/actionBarTheme"
-                app:layout_collapseMode="pin"/>
-
-        </com.google.android.material.appbar.CollapsingToolbarLayout>
-    </com.google.android.material.appbar.AppBarLayout>
-
-    <FrameLayout
-        android:id="@+id/content_frame"
-        android:layout_width="match_parent"
-        android:layout_height="wrap_content"
-        app:layout_behavior="@string/appbar_scrolling_view_behavior"/>
-</androidx.coordinatorlayout.widget.CoordinatorLayout>
\ No newline at end of file
diff --git a/res/values/dimens.xml b/res/values/dimens.xml
index 6047092..0aaf930 100755
--- a/res/values/dimens.xml
+++ b/res/values/dimens.xml
@@ -443,15 +443,7 @@
     <!-- Battery usage chart view component -->
     <dimen name="chartview_divider_width">1dp</dimen>
     <dimen name="chartview_divider_height">4dp</dimen>
-    <dimen name="chartview_trapezoid_radius">2dp</dimen>
+    <dimen name="chartview_trapezoid_radius">3dp</dimen>
     <dimen name="chartview_trapezoid_margin_start">1dp</dimen>
     <dimen name="chartview_trapezoid_margin_bottom">2dp</dimen>
-
-    <!-- Collapsing toolbar layout dimensions -->
-    <dimen name="toolbar_one_line_height">226dp</dimen>
-    <dimen name="toolbar_two_lines_height">270dp</dimen>
-    <dimen name="toolbar_three_lines_height">314dp</dimen>
-    <dimen name="scrim_visible_height_trigger">174dp</dimen>
-    <dimen name="expanded_title_margin_start">24dp</dimen>
-    <dimen name="expanded_title_margin_end">24dp</dimen>
 </resources>
diff --git a/res/values/strings.xml b/res/values/strings.xml
index 6134100..8586700 100644
--- a/res/values/strings.xml
+++ b/res/values/strings.xml
@@ -739,6 +739,8 @@
     <string name="security_dashboard_summary">Screen lock, fingerprint</string>
     <!-- Summary for Security settings when fingerprint is not supported [CHAR LIMIT=NONE]-->
     <string name="security_dashboard_summary_no_fingerprint">Screen lock</string>
+    <!-- Summary for Security settings when biometric unlock is supported [CHAR LIMIT=NONE] -->
+    <string name="security_dashboard_summary_biometric">Screen lock, biometric unlock, app security</string>
 
     <!-- Face enrollment and settings --><skip />
     <!-- Message shown in summary field when face unlock is set up. [CHAR LIMIT=40] -->
@@ -4121,7 +4123,7 @@
     <!-- Description text for Bluetooth always scanning -->
     <string name="location_scanning_bluetooth_always_scanning_description">Allow apps and services to scan for nearby devices at any time, even when Bluetooth is off. This can be used, for example, to improve location-based features and services.</string>
     <!-- [CHAR LIMIT=60] Location Services preference title -->
-    <string name="location_services_preference_title">Manage location services</string>
+    <string name="location_services_preference_title">Location services</string>
     <!-- [CHAR LIMIT=60] Location Services screen, screen title -->
     <string name="location_services_screen_title">Location Services</string>
     <!-- [CHAR LIMIT=50] Location settings screen, sub category for location services for managed profile -->
@@ -5691,15 +5693,54 @@
     <!-- Title for the prompt shown as a placeholder if no accessibility services are installed. [CHAR LIMIT=50] -->
     <string name="accessibility_no_services_installed">No services installed</string>
 
-    <!-- Title for the acccessibility shortcut's summary if no service is selected for use with the shortcut. [CHAR LIMIT=50] -->
+    <!-- Title for the accessibility shortcut's summary if no service is selected for use with the shortcut. [CHAR LIMIT=50] -->
     <string name="accessibility_no_service_selected">No service selected</string>
 
     <!-- Default description for an accessibility service if the latter doesn't provide one. [CHAR LIMIT=NONE] -->
     <string name="accessibility_service_default_description">No description provided.</string>
 
-    <!-- Accessibility settings: button for lauching settings for an accessibility service -->
+    <!-- Accessibility settings: button for launching settings for an accessibility service -->
     <string name="settings_button">Settings</string>
 
+    <!-- List of synonyms used in the settings search bar to find the “Extra Dim” setting, which dims your screen. Title name is located at strings/reduce_bright_colors_preference_title. [CHAR LIMIT=NONE] -->
+    <string name="keywords_reduce_bright_colors">light sensitivity, photophobia, dark theme, migraine, headache, reading mode, night mode, reduce brightness, white point</string>
+    <!-- List of synonyms used in the settings search bar to find the “Accessibility”. [CHAR LIMIT=NONE] -->
+    <string name="keywords_accessibility">Ease of use, ease of access, assistance, assistive</string>
+    <!-- List of synonyms used in the settings search bar to find the “Magnification”. [CHAR LIMIT=NONE] -->
+    <string name="keywords_magnification">Window Magnifier, Zoom, Magnification, Low vision, Enlarge, make bigger</string>
+    <!-- List of synonyms used in the settings search bar to find the “TalkBack”. [CHAR LIMIT=NONE] -->
+    <string name="keywords_talkback">Screen reader, Voice Over, VoiceOver, Voice Assistance, Blind, Low Vision, TTS, text to speech, spoken feedback</string>
+    <!-- List of synonyms used in the settings search bar to find the “Live Caption”. [CHAR LIMIT=NONE] -->
+    <string name="keywords_live_caption">Captions, closed captions, CC, Live Transcribe, hard of hearing, hearing loss, CART, speech to text, subtitle</string>
+    <!-- List of synonyms used in the settings search bar to find the “Live Transcribe”. [CHAR LIMIT=NONE] -->
+    <string name="keywords_live_transcribe">Captions, closed captions, CC, Live Caption, hard of hearing, hearing loss, CART, speech to text, subtitle</string>
+    <!-- List of synonyms used in the settings search bar to find the “Sound Notifications”. [CHAR LIMIT=NONE] -->
+    <string name="keywords_sound_notifications">Notifications, hard of hearing, hearing loss, notify</string>
+    <!-- List of synonyms used in the settings search bar to find the “Sound Amplifier”. [CHAR LIMIT=NONE] -->
+    <string name="keywords_sound_amplifier">PSAP, amplify, sound amplification, hard of hearing, hearing loss, amplification</string>
+    <!-- List of synonyms used in the settings search bar to find the “Display size”. [CHAR LIMIT=NONE] -->
+    <string name="keywords_display_size">screen size, large screen</string>
+    <!-- List of synonyms used in the settings search bar to find the “Bold text”. [CHAR LIMIT=NONE] -->
+    <string name="keywords_bold_text">High contrast, low vision, bold font, bold face</string>
+    <!-- List of synonyms used in the settings search bar to find the “Select to Speak”. [CHAR LIMIT=NONE] -->
+    <string name="keywords_select_to_speak">Hear text, read aloud, speak screen, screen reader</string>
+    <!-- List of synonyms used in the settings search bar to find the “Color correction”. [CHAR LIMIT=NONE] -->
+    <string name="keywords_color_correction">adjust color </string>
+    <!-- List of synonyms used in the settings search bar to find the “Color inversion”. [CHAR LIMIT=NONE] -->
+    <string name="keywords_color_inversion">turn screen dark, turn screen light</string>
+    <!-- List of synonyms used in the settings search bar to find the “Accessibility Menu”. [CHAR LIMIT=NONE] -->
+    <string name="keywords_accessibility_menu">motor, quick menu, assistive menu, touch, dexterity</string>
+    <!-- List of synonyms used in the settings search bar to find the “Switch Access”. [CHAR LIMIT=NONE] -->
+    <string name="keywords_switch_access">motor, switch, hand, AT, assistive technology, paralysis, ALS, scanning, step scanning</string>
+    <!-- List of synonyms used in the settings search bar to find the “Autoclick(dwell timing)”. [CHAR LIMIT=NONE] -->
+    <string name="keywords_auto_click">motor, mouse</string>
+    <!-- List of synonyms used in the settings search bar to find the “Hearing aids”. [CHAR LIMIT=NONE] -->
+    <string name="keywords_hearing_aids">hard of hearing, hearing loss</string>
+    <!-- List of synonyms used in the settings search bar to find the “Real-time text (RTT)”. [CHAR LIMIT=NONE] -->
+    <string name="keywords_rtt">hard of hearing, hearing loss, captions, Teletype, tty</string>
+    <!-- List of synonyms used in the settings search bar to find the “Voice Access”. [CHAR LIMIT=NONE] -->
+    <string name="keywords_voice_access">voice, voice control, motor, hand, mic, microphone, dictation, talk, control</string>
+
     <!-- Printing settings -->
     <skip />
 
@@ -6255,8 +6296,39 @@
     <string name ="battery_detail_info_title">Since full charge</string>
     <!-- Title for the battery management group [CHAR LIMIT=40] -->
     <string name ="battery_detail_manage_title">Manage battery usage</string>
+
     <!-- Description for battery total and background usage time for an app, i.e. 1 hr 15 min total • 39 min background for past 24 hr. Note: ^1 and ^2 should be used in all translations [CHAR LIMIT=120] -->
     <string name="battery_total_and_background_usage"><xliff:g id="time" example="1 hr 15 min">^1</xliff:g> total • <xliff:g id="time" example="39 min">^2</xliff:g> background for past 24 hr</string>
+    <!-- Description for battery total and background usage time in a time period for an app, i.e. 1 hr 15 min total • 39 min background for 12 am-2 am. Note: ^1, ^2 and ^3 should be used in all translations [CHAR LIMIT=120] -->
+    <string name="battery_total_and_background_usage_with_period"><xliff:g id="time" example="1 hr 15 min">^1</xliff:g> total • <xliff:g id="time" example="39 min">^2</xliff:g> background for <xliff:g id="time_period" example="12 am-2 am">^3</xliff:g></string>
+
+    <!-- Description for battery total usage time is less than a minute for an app [CHAR LIMIT=120] -->
+    <string name="battery_total_usage_less_minute">Total less than a minute for past 24 hr</string>
+    <!-- Description for battery total usage time is less than a minute in a time period for an app, i.e. Total less than a minute for 12 am-2 am. Note: ^1 should be used in all translations[CHAR LIMIT=120] -->
+    <string name="battery_total_usage_less_minute_with_period">Total less than a minute for <xliff:g id="time_period" example="12 am-2 am">^1</xliff:g></string>
+
+    <!-- Description for battery background usage time is less than a minute for an app [CHAR LIMIT=120] -->
+    <string name="battery_background_usage_less_minute">Background less than a minute for past 24 hr</string>
+    <!-- Description for battery background usage time is less than a minute in a time period for an app, i.e. Background less than a minute for 12 am-2 am. Note: ^1 should be used in all translations[CHAR LIMIT=120] -->
+    <string name="battery_background_usage_less_minute_with_period">Background less than a minute for <xliff:g id="time_period" example="12 am-2 am">^1</xliff:g></string>
+
+    <!-- Description for battery total usage time for an app, i.e. 1 hr 15 min total for past 24 hr. Note: ^1 should be used in all translations [CHAR LIMIT=120] -->
+    <string name="battery_total_usage"><xliff:g id="time" example="1 hr 15 min">^1</xliff:g> total for past 24 hr</string>
+    <!-- Description for battery total usage time in a time period for an app, i.e. 1 hr 15 min total for 12 am-2 am. Note: ^1 and ^2 should be used in all translations [CHAR LIMIT=120] -->
+    <string name="battery_total_usage_with_period"><xliff:g id="time" example="1 hr 15 min">^1</xliff:g> total for <xliff:g id="time_period" example="12 am-2 am">^2</xliff:g></string>
+
+    <!-- Description for battery background usage time for an app, i.e. 1 hr 15 min background for past 24 hr. Note: ^1 should be used in all translations [CHAR LIMIT=120] -->
+    <string name="battery_background_usage"><xliff:g id="time" example="1 hr 15 min">^1</xliff:g> background for past 24 hr</string>
+    <!-- Description for battery background usage time in a time period for an app, i.e. 1 hr 15 min background for 12 am-2 am. Note: ^1 and ^2 should be used in all translations [CHAR LIMIT=120] -->
+    <string name="battery_background_usage_with_period"><xliff:g id="time" example="1 hr 15 min">^1</xliff:g> background for <xliff:g id="time_period" example="12 am-2 am">^2</xliff:g></string>
+
+    <!-- Description for battery total usage with background usage time less than a minute for an app, i.e. 1 hr 15 min total • background less than a minute for past 24 hr. Note: ^1 should be used in all translations [CHAR LIMIT=120] -->
+    <string name="battery_total_usage_and_background_less_minute_usage"><xliff:g id="time" example="1 hr 15 min">^1</xliff:g> total • background less than a minute for past 24 hr</string>
+    <!-- Description for battery total usage with background usage time less than a minute in a time period for an app, i.e. 1 hr 15 min total • background less than a minute for 12 am-2 am. Note: ^1 and ^2 should be used in all translations [CHAR LIMIT=120] -->
+    <string name="battery_total_usage_and_background_less_minute_usage_with_period"><xliff:g id="time" example="1 hr 15 min">^1</xliff:g> total • background less than a minute for <xliff:g id="time_period" example="12 am-2 am">^2</xliff:g></string>
+
+    <!-- Description for no any battery usage for past 24 hr [CHAR LIMIT=120] -->
+    <string name="battery_not_usage">No usage for past 24 hr</string>
 
     <!-- Graph subtext displayed to user when enhanced battery estimate is being used [CHAR LIMIT=120] -->
     <string name="advanced_battery_graph_subtext">Battery left estimate is based on your device usage</string>
@@ -7950,7 +8022,7 @@
     <string name="keywords_wifi_calling">wifi, wi-fi, call, calling</string>
     <string name="keywords_display">screen, touchscreen</string>
     <string name="keywords_display_brightness_level">dim screen, touchscreen, battery, bright</string>
-    <string name="keywords_display_night_display">dim screen, night, tint, night shift, brightness, screen color, colour, color</string>
+    <string name="keywords_display_night_display">dim screen, night, tint, night shift, brightness, screen color, colour, color, light sensitivity, photophobia, make darker, darken, dark mode, migraine</string>
     <string name="keywords_display_wallpaper">background, personalize, customize display</string>
     <string name="keywords_display_font_size">text size</string>
     <!-- Search keyword for "Cast" settings [CHAR_LIMIT=NONE]-->
@@ -8076,10 +8148,7 @@
     <string name="keywords_add_language">add language, add a language</string>
 
     <!-- List of synonyms for the font size, used to match in settings search [CHAR LIMIT=NONE] -->
-    <string name="keywords_font_size">text size</string>
-
-    <!-- List of synonyms used in the settings search bar to find the “Extra Dim” setting, which dims your screen. Title name is located at strings/reduce_bright_colors_preference_title. [CHAR LIMIT=NONE] -->
-    <string name="keywords_reduce_bright_colors">light sensitivity, photophobia, dark theme, migraine, headache, reading mode, night mode, reduce brightness, white point</string>
+    <string name="keywords_font_size">text size, large print, large font, large text, low vision, make text bigger, font enlarger, font enlargement</string>
 
     <!-- Option title for the default sound, context based on screen -->
     <string name="default_sound">Default sound</string>
@@ -13187,4 +13256,13 @@
 
     <!-- Label for button to not allow grant the permission for remote devices. [CHAR_LIMIT=50] -->
     <string name="request_manage_bluetooth_permission_dont_allow">Don\u2019t allow</string>
+
+    <!-- Title for UWB preference [CHAR_LIMIT=60] -->
+    <string name="uwb_settings_title">Ultra-WideBand (UWB)</string>
+
+    <!-- Summary for UWB preference. [CHAR_LIMIT=NONE]-->
+    <string name="uwb_settings_summary">Helps identify the relative position of nearby devices that have UWB</string>
+
+    <!-- Summary for UWB preference when airplane mode is disabled. [CHAR_LIMIT=NONE]-->
+    <string name="uwb_settings_summary_airplane_mode">Turn off Airplane mode to use UWB. </string>
 </resources>
diff --git a/res/values/styles.xml b/res/values/styles.xml
index e91ddcb..b27cc5d 100644
--- a/res/values/styles.xml
+++ b/res/values/styles.xml
@@ -787,7 +787,7 @@
         <item name="android:fontFamily">@*android:string/config_headlineFontFamily</item>
     </style>
 
-    <style name="HomepageTitleText" parent="ToolbarText.Expanded">
+    <style name="HomepageTitleText" parent="CollapsingToolbarTitle.Expanded">
         <item name="android:layout_width">wrap_content</item>
         <item name="android:layout_height">wrap_content</item>
         <item name="android:layout_marginBottom">@dimen/homepage_title_margin_bottom</item>
@@ -879,8 +879,4 @@
         <item name="android:textSize">16sp</item>
         <item name="android:textColor">?android:attr/textColorSecondary</item>
     </style>
-
-    <style name="ToolbarText.Collapsed" parent="CollapsingToolbarTitle.Collapsed"/>
-    <style name="ToolbarText.Expanded" parent="CollapsingToolbarTitle"/>
-    <style name="ToolbarText.MoreThanTwoLines" parent="CollapsingToolbarTitle.MoreThanTwoLines"/>
 </resources>
diff --git a/res/values/styles_preference.xml b/res/values/styles_preference.xml
index c162fc4..5ad553a 100644
--- a/res/values/styles_preference.xml
+++ b/res/values/styles_preference.xml
@@ -30,7 +30,6 @@
 
     <style name="PreferenceTheme.SetupWizard" parent="@style/SettingsPreferenceTheme">
         <item name="preferenceFragmentCompatStyle">@style/SetupWizardPreferenceFragmentStyle</item>
-        <item name="preferenceStyle">@style/Preference.Material</item>
     </style>
 
     <style name="ApnPreference" parent="@style/Preference.Material">
diff --git a/res/values/themes.xml b/res/values/themes.xml
index 02f94d2..0bd7c5b 100644
--- a/res/values/themes.xml
+++ b/res/values/themes.xml
@@ -272,5 +272,7 @@
     <style name="Theme.NotificationHistory" parent="@android:style/Theme.DeviceDefault.DayNight">
         <item name="android:windowActionBar">false</item>
         <item name="android:windowNoTitle">true</item>
+        <item name="android:navigationBarColor">@android:color/transparent</item>
+        <item name="android:statusBarColor">@android:color/transparent</item>
     </style>
 </resources>
diff --git a/res/xml/app_notification_settings.xml b/res/xml/app_notification_settings.xml
index a801ae1..edf8cb9 100644
--- a/res/xml/app_notification_settings.xml
+++ b/res/xml/app_notification_settings.xml
@@ -26,7 +26,7 @@
     <com.android.settings.widget.SettingsMainSwitchPreference
         android:key="block" />
 
-    <com.android.settings.notification.app.NotificationFooterPreference
+    <com.android.settingslib.widget.FooterPreference
         android:key="block_desc" />
 
 
@@ -96,11 +96,11 @@
 
     </PreferenceCategory>
 
-    <com.android.settings.notification.app.NotificationFooterPreference
+    <com.android.settingslib.widget.FooterPreference
         android:key="desc"
         android:order="5000" />
 
-    <com.android.settings.notification.app.NotificationFooterPreference
+    <com.android.settingslib.widget.FooterPreference
         android:key="deleted"
         android:order="8000" />
 
diff --git a/res/xml/channel_notification_settings.xml b/res/xml/channel_notification_settings.xml
index 95f7944..97dcc26 100644
--- a/res/xml/channel_notification_settings.xml
+++ b/res/xml/channel_notification_settings.xml
@@ -116,11 +116,11 @@
         android:title="@string/app_settings_link"
         settings:allowDividerAbove="true"/>
 
-    <com.android.settings.notification.app.NotificationFooterPreference
+    <com.android.settingslib.widget.FooterPreference
         android:key="desc"
         android:order="100"/>
 
-    <com.android.settings.notification.app.NotificationFooterPreference
+    <com.android.settingslib.widget.FooterPreference
         android:key="block_desc"
         android:order="110"
         settings:allowDividerAbove="false"/>
diff --git a/res/xml/connected_devices_advanced.xml b/res/xml/connected_devices_advanced.xml
index 3ff7d99..85e4a76 100644
--- a/res/xml/connected_devices_advanced.xml
+++ b/res/xml/connected_devices_advanced.xml
@@ -65,6 +65,13 @@
         android:icon="@drawable/ic_folder_vd_theme_24"
         android:title="@string/bluetooth_show_files_received_via_bluetooth"/>
 
+    <SwitchPreference
+        android:key="uwb_settings"
+        android:title="@string/uwb_settings_title"
+        android:order="100"
+        android:summary="@string/summary_placeholder"
+        settings:controller="com.android.settings.uwb.UwbPreferenceController"/>
+
     <PreferenceCategory
         android:key="dashboard_tile_placeholder"
         android:order="-8"/>
diff --git a/res/xml/conversation_notification_settings.xml b/res/xml/conversation_notification_settings.xml
index ea555c2..7e475be 100644
--- a/res/xml/conversation_notification_settings.xml
+++ b/res/xml/conversation_notification_settings.xml
@@ -58,7 +58,7 @@
         android:summary="@string/demote_conversation_summary"
         settings:allowDividerAbove="true"/>
 
-    <com.android.settings.notification.app.NotificationFooterPreference
+    <com.android.settingslib.widget.FooterPreference
         android:key="block_desc"
         settings:allowDividerAbove="false"/>
 
diff --git a/res/xml/date_time_prefs.xml b/res/xml/date_time_prefs.xml
index 6fc0b25..47056df 100644
--- a/res/xml/date_time_prefs.xml
+++ b/res/xml/date_time_prefs.xml
@@ -53,11 +53,10 @@
         settings:keywords="@string/keywords_time_zone"/>
 
     <!-- This preference gets removed if location-based time zone detection is not supported -->
-    <com.android.settingslib.RestrictedSwitchPreference
+    <SwitchPreference
         android:key="location_time_zone_detection"
         android:title="@string/location_time_zone_detection_toggle_title"
         settings:controller="com.android.settings.datetime.LocationTimeZoneDetectionPreferenceController"
-        settings:userRestriction="no_config_date_time"
     />
 
     <PreferenceCategory
diff --git a/res/xml/location_settings.xml b/res/xml/location_settings.xml
index cae128b..a950b3a 100644
--- a/res/xml/location_settings.xml
+++ b/res/xml/location_settings.xml
@@ -27,14 +27,6 @@
         settings:controller=
             "com.android.settings.location.RecentLocationAccessPreferenceController"/>
 
-    <Preference
-        android:key="recent_location_access_see_all_button"
-        android:title="@string/location_recent_location_access_see_all"
-        android:icon="@drawable/ic_chevron_right_24dp"
-        android:fragment="com.android.settings.location.RecentLocationAccessSeeAllFragment"
-        settings:controller="com.android.settings.location.RecentLocationAccessSeeAllButtonPreferenceController"
-        settings:searchable="false"/>
-
     <PreferenceCategory
         android:key="location_advanced_settings"
         android:layout="@layout/preference_category_no_label"
@@ -65,7 +57,7 @@
         <Preference
             android:fragment="com.android.settings.location.LocationServices"
             android:key="location_services"
-            android:icon="@drawable/baseline_near_me"
+            android:icon="@drawable/ic_chevron_right_24dp"
             android:title="@string/location_services_preference_title"
             settings:controller="com.android.settings.location.LocationServicesPreferenceController"/>
 
diff --git a/res/xml/location_settings_personal.xml b/res/xml/location_settings_personal.xml
index 726a96c..a798899 100644
--- a/res/xml/location_settings_personal.xml
+++ b/res/xml/location_settings_personal.xml
@@ -28,14 +28,6 @@
         settings:controller=
             "com.android.settings.location.RecentLocationAccessPreferenceController"/>
 
-    <Preference
-        android:key="recent_location_access_see_all_button"
-        android:title="@string/location_recent_location_access_see_all"
-        android:icon="@drawable/ic_chevron_right_24dp"
-        android:fragment="com.android.settings.location.RecentLocationAccessSeeAllFragment"
-        settings:controller="com.android.settings.location.RecentLocationAccessSeeAllButtonPreferenceController"
-        settings:searchable="false"/>
-
     <!-- This preference category gets removed if new_recent_location_ui is disabled -->
     <Preference
         android:key="app_level_permissions"
diff --git a/res/xml/location_settings_workprofile.xml b/res/xml/location_settings_workprofile.xml
index 99ccf14..62ec0cb 100644
--- a/res/xml/location_settings_workprofile.xml
+++ b/res/xml/location_settings_workprofile.xml
@@ -28,15 +28,6 @@
         settings:controller=
             "com.android.settings.location.RecentLocationAccessPreferenceController"/>
 
-    <Preference
-        android:key="recent_location_access_see_all_button"
-        android:title="@string/location_recent_location_access_see_all"
-        android:icon="@drawable/ic_chevron_right_24dp"
-        android:fragment="com.android.settings.location.RecentLocationAccessSeeAllFragment"
-        settings:controller="com.android.settings.location.RecentLocationAccessSeeAllButtonPreferenceController"
-        settings:forWork="true"
-        settings:searchable="false"/>
-
     <com.android.settingslib.RestrictedSwitchPreference
         android:key="managed_profile_location_switch"
         android:title="@string/managed_profile_location_switch_title"
diff --git a/res/xml/notification_group_settings.xml b/res/xml/notification_group_settings.xml
index cbe23c6..e714759 100644
--- a/res/xml/notification_group_settings.xml
+++ b/res/xml/notification_group_settings.xml
@@ -31,9 +31,9 @@
         android:title="@string/app_settings_link"
         settings:allowDividerAbove="true"/>
 
-    <com.android.settings.notification.NotificationFooterPreference
+    <com.android.settingslib.widget.FooterPreference
         android:key="desc" />
 
-    <com.android.settings.notification.NotificationFooterPreference
+    <com.android.settingslib.widget.FooterPreference
         android:key="block_desc" />
 </PreferenceScreen>
diff --git a/src/com/android/settings/accessibility/AccessibilityEditDialogUtils.java b/src/com/android/settings/accessibility/AccessibilityEditDialogUtils.java
index 5402a9b..26c2313 100644
--- a/src/com/android/settings/accessibility/AccessibilityEditDialogUtils.java
+++ b/src/com/android/settings/accessibility/AccessibilityEditDialogUtils.java
@@ -26,6 +26,7 @@
 import android.graphics.drawable.Drawable;
 import android.text.Spannable;
 import android.text.SpannableString;
+import android.text.SpannableStringBuilder;
 import android.text.TextUtils;
 import android.text.method.LinkMovementMethod;
 import android.text.style.ImageSpan;
@@ -320,8 +321,13 @@
     }
 
     private static CharSequence retrieveSummary(Context context, int lineHeight) {
-        return AccessibilityUtil.isFloatingMenuEnabled(context)
-                ? getSummaryStringWithLink(context) : getSummaryStringWithIcon(context, lineHeight);
+        final SpannableStringBuilder sb = new SpannableStringBuilder();
+        if (!AccessibilityUtil.isFloatingMenuEnabled(context)) {
+            sb.append(getSummaryStringWithIcon(context, lineHeight));
+            sb.append("\n\n");
+        }
+        sb.append(getCustomizeAccessibilityButtonLink(context));
+        return sb;
     }
 
     private static int retrieveSoftwareShortcutImageResId(Context context) {
@@ -330,7 +336,7 @@
                 : R.drawable.accessibility_shortcut_type_software;
     }
 
-    private static CharSequence getSummaryStringWithLink(Context context) {
+    private static CharSequence getCustomizeAccessibilityButtonLink(Context context) {
         final View.OnClickListener linkListener = v -> new SubSettingLauncher(context)
                 .setDestination(AccessibilityButtonFragment.class.getName())
                 .setSourceMetricsCategory(
diff --git a/src/com/android/settings/biometrics/BiometricEnrollActivity.java b/src/com/android/settings/biometrics/BiometricEnrollActivity.java
index cede6a0..0a2e5fe 100644
--- a/src/com/android/settings/biometrics/BiometricEnrollActivity.java
+++ b/src/com/android/settings/biometrics/BiometricEnrollActivity.java
@@ -16,6 +16,9 @@
 
 package com.android.settings.biometrics;
 
+import static android.provider.Settings.ACTION_BIOMETRIC_ENROLL;
+import static android.provider.Settings.EXTRA_BIOMETRIC_AUTHENTICATORS_ALLOWED;
+
 import android.annotation.NonNull;
 import android.app.admin.DevicePolicyManager;
 import android.app.settings.SettingsEnums;
@@ -24,6 +27,7 @@
 import android.content.res.Resources;
 import android.hardware.biometrics.BiometricManager;
 import android.hardware.biometrics.BiometricManager.Authenticators;
+import android.hardware.biometrics.BiometricManager.BiometricError;
 import android.hardware.face.FaceManager;
 import android.hardware.face.FaceSensorPropertiesInternal;
 import android.hardware.fingerprint.FingerprintManager;
@@ -31,11 +35,11 @@
 import android.os.Bundle;
 import android.os.UserHandle;
 import android.os.UserManager;
-import android.provider.Settings;
 import android.util.Log;
 
 import androidx.annotation.Nullable;
 
+import com.android.internal.util.FrameworkStatsLog;
 import com.android.internal.widget.LockPatternUtils;
 import com.android.settings.R;
 import com.android.settings.SetupWizardUtils;
@@ -68,12 +72,14 @@
     public static final String EXTRA_SKIP_INTRO = "skip_intro";
 
     private static final String SAVED_STATE_CONFIRMING_CREDENTIALS = "confirming_credentials";
+    private static final String SAVED_STATE_ENROLL_ACTION_LOGGED = "enroll_action_logged";
     private static final String SAVED_STATE_GK_PW_HANDLE = "gk_pw_handle";
 
     public static final class InternalActivity extends BiometricEnrollActivity {}
 
     private int mUserId = UserHandle.myUserId();
     private boolean mConfirmingCredentials;
+    private boolean mIsEnrollActionLogged;
     private boolean mIsFaceEnrollable;
     private boolean mIsFingerprintEnrollable;
     @Nullable private Long mGkPwHandle;
@@ -91,15 +97,44 @@
         }
 
         if (savedInstanceState != null) {
-            mConfirmingCredentials = savedInstanceState
-                    .getBoolean(SAVED_STATE_CONFIRMING_CREDENTIALS, false);
+            mConfirmingCredentials = savedInstanceState.getBoolean(
+                    SAVED_STATE_CONFIRMING_CREDENTIALS, false);
+            mIsEnrollActionLogged = savedInstanceState.getBoolean(
+                    SAVED_STATE_ENROLL_ACTION_LOGGED, false);
             if (savedInstanceState.containsKey(SAVED_STATE_GK_PW_HANDLE)) {
                 mGkPwHandle = savedInstanceState.getLong(SAVED_STATE_GK_PW_HANDLE);
             }
         }
 
-        // Put the theme in the intent so it gets propagated to other activities in the flow
+        // Log a framework stats event if this activity was launched via intent action.
         final Intent intent = getIntent();
+        if (!mIsEnrollActionLogged && ACTION_BIOMETRIC_ENROLL.equals(intent.getAction())) {
+            mIsEnrollActionLogged = true;
+
+            // Get the current status for each authenticator type.
+            @BiometricError final int strongBiometricStatus;
+            @BiometricError final int weakBiometricStatus;
+            @BiometricError final int deviceCredentialStatus;
+            final BiometricManager bm = getSystemService(BiometricManager.class);
+            if (bm != null) {
+                strongBiometricStatus = bm.canAuthenticate(Authenticators.BIOMETRIC_STRONG);
+                weakBiometricStatus = bm.canAuthenticate(Authenticators.BIOMETRIC_WEAK);
+                deviceCredentialStatus = bm.canAuthenticate(Authenticators.DEVICE_CREDENTIAL);
+            } else {
+                strongBiometricStatus = BiometricManager.BIOMETRIC_ERROR_NO_HARDWARE;
+                weakBiometricStatus = BiometricManager.BIOMETRIC_ERROR_NO_HARDWARE;
+                deviceCredentialStatus = BiometricManager.BIOMETRIC_ERROR_NO_HARDWARE;
+            }
+
+            FrameworkStatsLog.write(FrameworkStatsLog.AUTH_ENROLL_ACTION_INVOKED,
+                    strongBiometricStatus == BiometricManager.BIOMETRIC_SUCCESS,
+                    weakBiometricStatus == BiometricManager.BIOMETRIC_SUCCESS,
+                    deviceCredentialStatus == BiometricManager.BIOMETRIC_SUCCESS,
+                    intent.hasExtra(EXTRA_BIOMETRIC_AUTHENTICATORS_ALLOWED),
+                    intent.getIntExtra(EXTRA_BIOMETRIC_AUTHENTICATORS_ALLOWED, 0));
+        }
+
+        // Put the theme in the intent so it gets propagated to other activities in the flow
         if (intent.getStringExtra(WizardManagerHelper.EXTRA_THEME) == null) {
             intent.putExtra(
                     WizardManagerHelper.EXTRA_THEME,
@@ -108,7 +143,7 @@
 
         // Default behavior is to enroll BIOMETRIC_WEAK or above. See ACTION_BIOMETRIC_ENROLL.
         final int authenticators = intent.getIntExtra(
-                Settings.EXTRA_BIOMETRIC_AUTHENTICATORS_ALLOWED, Authenticators.BIOMETRIC_WEAK);
+                EXTRA_BIOMETRIC_AUTHENTICATORS_ALLOWED, Authenticators.BIOMETRIC_WEAK);
 
         Log.d(TAG, "Authenticators: " + authenticators);
 
@@ -132,7 +167,7 @@
         } else {
             // If the caller is not setup wizard, and the user has something enrolled, finish.
             final BiometricManager bm = getSystemService(BiometricManager.class);
-            final @BiometricManager.BiometricError int result = bm.canAuthenticate(authenticators);
+            final @BiometricError int result = bm.canAuthenticate(authenticators);
             if (result != BiometricManager.BIOMETRIC_ERROR_NONE_ENROLLED) {
                 Log.e(TAG, "Unexpected result: " + result);
                 finish();
@@ -159,6 +194,7 @@
     protected void onSaveInstanceState(@NonNull Bundle outState) {
         super.onSaveInstanceState(outState);
         outState.putBoolean(SAVED_STATE_CONFIRMING_CREDENTIALS, mConfirmingCredentials);
+        outState.putBoolean(SAVED_STATE_ENROLL_ACTION_LOGGED, mIsEnrollActionLogged);
         if (mGkPwHandle != null) {
             outState.putLong(SAVED_STATE_GK_PW_HANDLE, mGkPwHandle);
         }
diff --git a/src/com/android/settings/core/SettingsBaseActivity.java b/src/com/android/settings/core/SettingsBaseActivity.java
index 569e480..e0e41de 100644
--- a/src/com/android/settings/core/SettingsBaseActivity.java
+++ b/src/com/android/settings/core/SettingsBaseActivity.java
@@ -49,8 +49,6 @@
 import com.google.android.material.appbar.CollapsingToolbarLayout;
 import com.google.android.setupcompat.util.WizardManagerHelper;
 
-import java.lang.reflect.Field;
-import java.lang.reflect.Method;
 import java.util.ArrayList;
 import java.util.List;
 import java.util.Map;
@@ -61,7 +59,6 @@
     protected static final boolean DEBUG_TIMING = false;
     private static final String TAG = "SettingsBaseActivity";
     private static final String DATA_SCHEME_PKG = "package";
-    private static final int TOOLBAR_MAX_LINE_NUMBER = 2;
 
     // Serves as a temporary list of tiles to ignore until we heard back from the PM that they
     // are disabled.
@@ -95,7 +92,7 @@
 
         if (FeatureFlagUtils.isEnabled(this, FeatureFlags.SILKY_HOME)
                 && isToolbarEnabled() && !isAnySetupWizard) {
-            super.setContentView(R.layout.settings_collapsing_base_layout);
+            super.setContentView(R.layout.collapsing_toolbar_base_layout);
             mCollapsingToolbarLayout = findViewById(R.id.collapsing_toolbar);
         } else {
             super.setContentView(R.layout.settings_base_layout);
@@ -108,7 +105,6 @@
             return;
         }
         setActionBar(toolbar);
-        initCollapsingToolbar();
 
         if (DEBUG_TIMING) {
             Log.d(TAG, "onCreate took " + (System.currentTimeMillis() - startTime) + " ms");
@@ -207,50 +203,6 @@
         return true;
     }
 
-    private void initCollapsingToolbar() {
-        if (mCollapsingToolbarLayout == null) {
-            return;
-        }
-        mCollapsingToolbarLayout.addOnLayoutChangeListener(new View.OnLayoutChangeListener() {
-            @Override
-            public void onLayoutChange(View v, int left, int top, int right, int bottom,
-                    int oldLeft, int oldTop, int oldRight, int oldBottom) {
-                v.removeOnLayoutChangeListener(this);
-                final int count = getLineCount();
-                if (count > TOOLBAR_MAX_LINE_NUMBER) {
-                    ViewGroup.LayoutParams lp = mCollapsingToolbarLayout.getLayoutParams();
-                    lp.height = getResources()
-                            .getDimensionPixelSize(R.dimen.toolbar_three_lines_height);
-                    mCollapsingToolbarLayout.setLayoutParams(lp);
-                } else if (count == TOOLBAR_MAX_LINE_NUMBER) {
-                    ViewGroup.LayoutParams lp = mCollapsingToolbarLayout.getLayoutParams();
-                    lp.height =
-                            getResources().getDimensionPixelSize(R.dimen.toolbar_two_lines_height);
-                    mCollapsingToolbarLayout.setLayoutParams(lp);
-                }
-            }
-        });
-    }
-
-    private int getLineCount() {
-        try {
-            final Class<?> toolbarClazz = mCollapsingToolbarLayout.getClass();
-            final Field textHelperField = toolbarClazz.getDeclaredField("collapsingTextHelper");
-            textHelperField.setAccessible(true);
-            final Object textHelperObj = textHelperField.get(mCollapsingToolbarLayout);
-
-            final Field layoutField = textHelperObj.getClass().getDeclaredField("textLayout");
-            layoutField.setAccessible(true);
-            final Object layoutObj = layoutField.get(textHelperObj);
-
-            final Method method = layoutObj.getClass().getDeclaredMethod("getLineCount");
-            return (int) method.invoke(layoutObj);
-        } catch (Exception e) {
-            return 0;
-        }
-    }
-
-
     private void onCategoriesChanged(Set<String> categories) {
         final int N = mCategoryListeners.size();
         for (int i = 0; i < N; i++) {
diff --git a/src/com/android/settings/development/qstile/DevelopmentTiles.java b/src/com/android/settings/development/qstile/DevelopmentTiles.java
index 16084c0..c55d0cb 100644
--- a/src/com/android/settings/development/qstile/DevelopmentTiles.java
+++ b/src/com/android/settings/development/qstile/DevelopmentTiles.java
@@ -371,7 +371,7 @@
             mContext = getApplicationContext();
             mSensorPrivacyManager = (SensorPrivacyManager) mContext.getSystemService(
                     Context.SENSOR_PRIVACY_SERVICE);
-            mIsEnabled = mSensorPrivacyManager.isSensorPrivacyEnabled();
+            mIsEnabled = mSensorPrivacyManager.isAllSensorPrivacyEnabled();
             mMetricsFeatureProvider = FeatureFactory.getFactory(
                     mContext).getMetricsFeatureProvider();
             mKeyguardManager = (KeyguardManager) mContext.getSystemService(
@@ -392,7 +392,7 @@
             mMetricsFeatureProvider.action(getApplicationContext(), SettingsEnums.QS_SENSOR_PRIVACY,
                     isEnabled);
             mIsEnabled = isEnabled;
-            mSensorPrivacyManager.setSensorPrivacy(isEnabled);
+            mSensorPrivacyManager.setAllSensorPrivacy(isEnabled);
         }
     }
 
diff --git a/src/com/android/settings/display/AdaptiveSleepCameraStatePreferenceController.java b/src/com/android/settings/display/AdaptiveSleepCameraStatePreferenceController.java
index 72a1c66..ba7a3ab 100644
--- a/src/com/android/settings/display/AdaptiveSleepCameraStatePreferenceController.java
+++ b/src/com/android/settings/display/AdaptiveSleepCameraStatePreferenceController.java
@@ -43,7 +43,7 @@
         mPreference.setPositiveButtonText(R.string.allow);
         mPrivacyManager = SensorPrivacyManager.getInstance(context);
         mPrivacyManager.addSensorPrivacyListener(CAMERA,
-                enabled -> updateVisibility());
+                (sensor, enabled) -> updateVisibility());
         mPreference.setPositiveButtonOnClickListener(p -> {
             mPrivacyManager.setSensorPrivacy(CAMERA, false);
         });
diff --git a/src/com/android/settings/display/ScreenTimeoutSettings.java b/src/com/android/settings/display/ScreenTimeoutSettings.java
index 444f8ef8..27e1e1b 100644
--- a/src/com/android/settings/display/ScreenTimeoutSettings.java
+++ b/src/com/android/settings/display/ScreenTimeoutSettings.java
@@ -111,9 +111,7 @@
         mPrivacyPreference.setLayoutResource(R.layout.preference_footer);
         mPrivacyManager = SensorPrivacyManager.getInstance(context);
         mPrivacyManager.addSensorPrivacyListener(CAMERA,
-                enabled -> {
-                    mAdaptiveSleepController.updatePreference();
-                });
+                (sensor, enabled) -> mAdaptiveSleepController.updatePreference());
     }
 
     @Override
diff --git a/src/com/android/settings/display/SmartAutoRotateCameraStateController.java b/src/com/android/settings/display/SmartAutoRotateCameraStateController.java
index 1480785..9e2a784 100644
--- a/src/com/android/settings/display/SmartAutoRotateCameraStateController.java
+++ b/src/com/android/settings/display/SmartAutoRotateCameraStateController.java
@@ -43,7 +43,7 @@
     public SmartAutoRotateCameraStateController(Context context, String key) {
         super(context, key);
         mPrivacyManager = SensorPrivacyManager.getInstance(context);
-        mPrivacyManager.addSensorPrivacyListener(CAMERA, enabled -> {
+        mPrivacyManager.addSensorPrivacyListener(CAMERA, (sensor, enabled) -> {
             mPreference.setVisible(enabled);
             updateState(mPreference);
         });
diff --git a/src/com/android/settings/display/SmartAutoRotateController.java b/src/com/android/settings/display/SmartAutoRotateController.java
index e3b2665..cf2a9a6 100644
--- a/src/com/android/settings/display/SmartAutoRotateController.java
+++ b/src/com/android/settings/display/SmartAutoRotateController.java
@@ -52,7 +52,8 @@
         super(context, preferenceKey);
         mMetricsFeatureProvider = FeatureFactory.getFactory(context).getMetricsFeatureProvider();
         mPrivacyManager = SensorPrivacyManager.getInstance(context);
-        mPrivacyManager.addSensorPrivacyListener(CAMERA, enabled -> updateState(mPreference));
+        mPrivacyManager
+                .addSensorPrivacyListener(CAMERA, (sensor, enabled) -> updateState(mPreference));
     }
 
     @Override
diff --git a/src/com/android/settings/fuelgauge/AdvancedPowerUsageDetail.java b/src/com/android/settings/fuelgauge/AdvancedPowerUsageDetail.java
index 432224d..3ef7c45 100644
--- a/src/com/android/settings/fuelgauge/AdvancedPowerUsageDetail.java
+++ b/src/com/android/settings/fuelgauge/AdvancedPowerUsageDetail.java
@@ -27,6 +27,7 @@
 import android.os.UserHandle;
 import android.text.Html;
 import android.text.TextUtils;
+import android.text.format.DateUtils;
 import android.util.Log;
 import android.view.View;
 
@@ -282,20 +283,8 @@
 
         final long foregroundTimeMs = bundle.getLong(EXTRA_FOREGROUND_TIME);
         final long backgroundTimeMs = bundle.getLong(EXTRA_BACKGROUND_TIME);
-        final long totalTimeMs = foregroundTimeMs + backgroundTimeMs;
-        //TODO(b/178197718) Refine the layout
-        controller.setSummary(TextUtils.expandTemplate(
-                getText(R.string.battery_total_and_background_usage),
-                StringUtil.formatElapsedTime(
-                        getContext(),
-                        totalTimeMs,
-                        /* withSeconds */ false,
-                        /* collapseTimeUnit */ false),
-                StringUtil.formatElapsedTime(
-                        getContext(),
-                        backgroundTimeMs,
-                        /* withSeconds */ false,
-                        /* collapseTimeUnit */ false)));
+        //TODO(b/178197718) Update layout to support multiple lines
+        controller.setSummary(getAppActiveTime(foregroundTimeMs, backgroundTimeMs));
 
         controller.done(context, true /* rebindActions */);
     }
@@ -388,4 +377,53 @@
     private void updatePreferenceState(RadioButtonPreference preference, String selectedKey) {
         preference.setChecked(selectedKey.equals(preference.getKey()));
     }
+
+    //TODO(b/178197718) Update method to support time period
+    private CharSequence getAppActiveTime(long foregroundTimeMs, long backgroundTimeMs) {
+        final long totalTimeMs = foregroundTimeMs + backgroundTimeMs;
+        final CharSequence usageTimeSummary;
+
+        if (totalTimeMs == 0) {
+            usageTimeSummary = getText(R.string.battery_not_usage);
+        // Shows background summary only if we don't have foreground usage time.
+        } else if (foregroundTimeMs == 0 && backgroundTimeMs != 0) {
+            usageTimeSummary = backgroundTimeMs < DateUtils.MINUTE_IN_MILLIS ?
+                    getText(R.string.battery_background_usage_less_minute) :
+                    TextUtils.expandTemplate(getText(R.string.battery_background_usage),
+                    StringUtil.formatElapsedTime(
+                            getContext(),
+                            backgroundTimeMs,
+                            /* withSeconds */ false,
+                            /* collapseTimeUnit */ false));
+        // Shows total usage summary only if total usage time is small.
+        } else if (totalTimeMs < DateUtils.MINUTE_IN_MILLIS) {
+            usageTimeSummary = getText(R.string.battery_total_usage_less_minute);
+        // Shows different total usage summary when background usage time is small.
+        } else if (backgroundTimeMs < DateUtils.MINUTE_IN_MILLIS) {
+            usageTimeSummary = TextUtils.expandTemplate(
+                    getText(backgroundTimeMs == 0 ?
+                            R.string.battery_total_usage :
+                            R.string.battery_total_usage_and_background_less_minute_usage),
+                    StringUtil.formatElapsedTime(
+                            getContext(),
+                            totalTimeMs,
+                            /* withSeconds */ false,
+                            /* collapseTimeUnit */ false));
+        // Shows default summary.
+        } else {
+            usageTimeSummary = TextUtils.expandTemplate(
+                    getText(R.string.battery_total_and_background_usage),
+                    StringUtil.formatElapsedTime(
+                            getContext(),
+                            totalTimeMs,
+                            /* withSeconds */ false,
+                            /* collapseTimeUnit */ false),
+                    StringUtil.formatElapsedTime(
+                            getContext(),
+                            backgroundTimeMs,
+                            /* withSeconds */ false,
+                            /* collapseTimeUnit */ false));
+        }
+        return usageTimeSummary;
+    }
 }
diff --git a/src/com/android/settings/fuelgauge/BatteryChartPreferenceController.java b/src/com/android/settings/fuelgauge/BatteryChartPreferenceController.java
index f12de01..7131f28 100644
--- a/src/com/android/settings/fuelgauge/BatteryChartPreferenceController.java
+++ b/src/com/android/settings/fuelgauge/BatteryChartPreferenceController.java
@@ -12,7 +12,6 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  *
- *
  */
 
 package com.android.settings.fuelgauge;
@@ -51,7 +50,7 @@
 /** Controls the update for chart graph and the list items. */
 public class BatteryChartPreferenceController extends AbstractPreferenceController
         implements PreferenceControllerMixin, LifecycleObserver, OnPause, OnDestroy,
-                BatteryChartView.OnSelectListener {
+                BatteryChartView.OnSelectListener, ExpandDividerPreference.OnExpandListener {
     private static final String TAG = "BatteryChartPreferenceController";
     private static final int CHART_KEY_ARRAY_SIZE = 25;
     private static final int CHART_LEVEL_ARRAY_SIZE = 13;
@@ -65,6 +64,7 @@
     @VisibleForTesting BatteryUtils mBatteryUtils;
     @VisibleForTesting PreferenceGroup mAppListPrefGroup;
     @VisibleForTesting BatteryChartView mBatteryChartView;
+    @VisibleForTesting ExpandDividerPreference mExpandDividerPreference;
 
     @VisibleForTesting int[] mBatteryHistoryLevels;
     @VisibleForTesting long[] mBatteryHistoryKeys;
@@ -76,9 +76,13 @@
     private final Handler mHandler = new Handler(Looper.getMainLooper());
     private final CharSequence[] mNotAllowShowSummaryPackages;
 
+    private boolean mIsExpanded = false;
+
     // Preference cache to avoid create new instance each time.
     @VisibleForTesting
     final Map<String, Preference> mPreferenceCache = new HashMap<>();
+    @VisibleForTesting
+    final List<BatteryDiffEntry> mSystemEntries = new ArrayList<>();
 
     public BatteryChartPreferenceController(
             Context context, String preferenceKey,
@@ -163,6 +167,12 @@
         refreshUi(trapezoidIndex, /*isForce=*/ false);
     }
 
+    @Override
+    public void onExpand(boolean isExpanded) {
+        mIsExpanded = isExpanded;
+        refreshExpandUi();
+    }
+
     void setBatteryHistoryMap(
             final Map<Long, List<BatteryHistEntry>> batteryHistoryMap) {
         mHandler.post(() -> setBatteryHistoryMapInner(batteryHistoryMap));
@@ -266,10 +276,10 @@
         }
         // Separates data into two groups and sort them individually.
         final List<BatteryDiffEntry> appEntries = new ArrayList<>();
-        final List<BatteryDiffEntry> systemEntries = new ArrayList<>();
+        mSystemEntries.clear();
         entries.forEach(entry -> {
             if (entry.isSystemEntry()) {
-                systemEntries.add(entry);
+                mSystemEntries.add(entry);
             } else {
                 appEntries.add(entry);
             }
@@ -279,11 +289,25 @@
             }
         });
         Collections.sort(appEntries, BatteryDiffEntry.COMPARATOR);
-        Collections.sort(systemEntries, BatteryDiffEntry.COMPARATOR);
+        Collections.sort(mSystemEntries, BatteryDiffEntry.COMPARATOR);
         Log.d(TAG, String.format("addAllPreferences() app=%d system=%d",
-            appEntries.size(), systemEntries.size()));
-        addPreferenceToScreen(appEntries);
-        addPreferenceToScreen(systemEntries);
+            appEntries.size(), mSystemEntries.size()));
+
+        // Adds app entries to the list if it is not empty.
+        if (!appEntries.isEmpty()) {
+            addPreferenceToScreen(appEntries);
+        }
+        // Adds the expabable divider if we have two sections data.
+        if (!appEntries.isEmpty() && !mSystemEntries.isEmpty()) {
+            if (mExpandDividerPreference == null) {
+                mExpandDividerPreference = new ExpandDividerPreference(mPrefContext);
+                mExpandDividerPreference.setOnExpandListener(this);
+            }
+            mExpandDividerPreference.setOrder(
+                mAppListPrefGroup.getPreferenceCount());
+            mAppListPrefGroup.addPreference(mExpandDividerPreference);
+        }
+        refreshExpandUi();
     }
 
     @VisibleForTesting
@@ -293,6 +317,7 @@
         }
         int prefIndex = mAppListPrefGroup.getPreferenceCount();
         for (BatteryDiffEntry entry : entries) {
+            boolean isAdded = false;
             final String appLabel = entry.getAppLabel();
             final Drawable appIcon = entry.getAppIcon();
             if (TextUtils.isEmpty(appLabel) || appIcon == null) {
@@ -300,8 +325,13 @@
                 continue;
             }
             final String prefKey = entry.mBatteryHistEntry.getKey();
-            PowerGaugePreference pref =
-                (PowerGaugePreference) mPreferenceCache.get(prefKey);
+            PowerGaugePreference pref = mAppListPrefGroup.findPreference(prefKey);
+            if (pref != null) {
+                isAdded = true;
+                Log.w(TAG, "preference should be removed for\n" + entry);
+            } else {
+                pref = (PowerGaugePreference) mPreferenceCache.get(prefKey);
+            }
             // Creates new innstance if cached preference is not found.
             if (pref == null) {
                 pref = new PowerGaugePreference(mPrefContext);
@@ -316,7 +346,9 @@
             // Sets the BatteryDiffEntry to preference for launching detailed page.
             pref.setBatteryDiffEntry(entry);
             setPreferenceSummary(pref, entry);
-            mAppListPrefGroup.addPreference(pref);
+            if (!isAdded) {
+                mAppListPrefGroup.addPreference(pref);
+            }
             prefIndex++;
         }
     }
@@ -337,6 +369,22 @@
         mAppListPrefGroup.removeAll();
     }
 
+    private void refreshExpandUi() {
+        if (mIsExpanded) {
+            addPreferenceToScreen(mSystemEntries);
+        } else {
+            // Removes and recycles all system entries to hide all of them.
+            for (BatteryDiffEntry entry : mSystemEntries) {
+                final String prefKey = entry.mBatteryHistEntry.getKey();
+                final Preference pref = mAppListPrefGroup.findPreference(prefKey);
+                if (pref != null) {
+                    mAppListPrefGroup.removePreference(pref);
+                    mPreferenceCache.put(pref.getKey(), pref);
+                }
+            }
+        }
+    }
+
     @VisibleForTesting
     void setPreferenceSummary(
             PowerGaugePreference preference, BatteryDiffEntry entry) {
diff --git a/src/com/android/settings/fuelgauge/BatteryChartView.java b/src/com/android/settings/fuelgauge/BatteryChartView.java
index 26eb3e4..f970072 100644
--- a/src/com/android/settings/fuelgauge/BatteryChartView.java
+++ b/src/com/android/settings/fuelgauge/BatteryChartView.java
@@ -97,8 +97,18 @@
     public void setLevels(int[] levels) {
         // We should provide trapezoid count + 1 data to draw all trapezoids.
         mLevels = levels.length == mTrapezoidCount + 1 ? levels : null;
-        setClickable(mLevels != null);
+        setClickable(false);
         invalidate();
+        if (mLevels == null) {
+            return;
+        }
+        // Sets the chart is clickable if there is at least one valid item in it.
+        for (int index = 0; index < mLevels.length; index++) {
+            if (mLevels[index] != 0) {
+                setClickable(true);
+                break;
+            }
+        }
     }
 
     /** Sets the selected group index to draw highlight effect. */
diff --git a/src/com/android/settings/fuelgauge/ConvertUtils.java b/src/com/android/settings/fuelgauge/ConvertUtils.java
index 30982da..2e8726e 100644
--- a/src/com/android/settings/fuelgauge/ConvertUtils.java
+++ b/src/com/android/settings/fuelgauge/ConvertUtils.java
@@ -71,6 +71,7 @@
 
     private static String sZoneId;
     private static SimpleDateFormat sSimpleDateFormat;
+    private static SimpleDateFormat sSimpleDateFormatForHour;
 
     private ConvertUtils() {}
 
@@ -139,10 +140,27 @@
             sZoneId = currentZoneId;
             sSimpleDateFormat =
                 new SimpleDateFormat("MMM dd,yyyy HH:mm:ss", Locale.ENGLISH);
+            sSimpleDateFormatForHour = null;
         }
         return sSimpleDateFormat.format(new Date(timestamp));
     }
 
+    /** Converts UTC timestamp to local time hour data. */
+    public static int utcToLocalTimeHour(long timestamp) {
+        final String currentZoneId = TimeZone.getDefault().getID();
+        if (!currentZoneId.equals(sZoneId) || sSimpleDateFormatForHour == null) {
+            sZoneId = currentZoneId;
+            sSimpleDateFormat = null;
+            sSimpleDateFormatForHour = new SimpleDateFormat("HH", Locale.ENGLISH);
+        }
+        try {
+            return Integer.parseInt(
+                sSimpleDateFormatForHour.format(new Date(timestamp)));
+        } catch (NumberFormatException e) {
+            return Integer.MIN_VALUE;
+        }
+    }
+
     /** Gets indexed battery usage data for each corresponding time slot. */
     public static Map<Integer, List<BatteryDiffEntry>> getIndexedUsageMap(
             final Context context,
diff --git a/src/com/android/settings/location/LocationPersonalSettings.java b/src/com/android/settings/location/LocationPersonalSettings.java
index 0553d96..ab392d6 100644
--- a/src/com/android/settings/location/LocationPersonalSettings.java
+++ b/src/com/android/settings/location/LocationPersonalSettings.java
@@ -51,7 +51,6 @@
 
         use(AppLocationPermissionPreferenceController.class).init(this);
         use(LocationSettingsFooterPreferenceController.class).init(this);
-        use(RecentLocationAccessSeeAllButtonPreferenceController.class).init(this);
 
         final int profileType = getArguments().getInt(ProfileSelectFragment.EXTRA_PROFILE);
         final RecentLocationAccessPreferenceController controller = use(
diff --git a/src/com/android/settings/location/LocationSettings.java b/src/com/android/settings/location/LocationSettings.java
index fe3cf30..093dc85 100644
--- a/src/com/android/settings/location/LocationSettings.java
+++ b/src/com/android/settings/location/LocationSettings.java
@@ -83,7 +83,6 @@
 
         use(AppLocationPermissionPreferenceController.class).init(this);
         use(RecentLocationAccessPreferenceController.class).init(this);
-        use(RecentLocationAccessSeeAllButtonPreferenceController.class).init(this);
         use(LocationForWorkPreferenceController.class).init(this);
         use(LocationSettingsFooterPreferenceController.class).init(this);
     }
diff --git a/src/com/android/settings/location/LocationWorkProfileSettings.java b/src/com/android/settings/location/LocationWorkProfileSettings.java
index 24c44f3..f50ba90 100644
--- a/src/com/android/settings/location/LocationWorkProfileSettings.java
+++ b/src/com/android/settings/location/LocationWorkProfileSettings.java
@@ -51,7 +51,6 @@
 
         use(AppLocationPermissionPreferenceController.class).init(this);
         use(LocationForWorkPreferenceController.class).init(this);
-        use(RecentLocationAccessSeeAllButtonPreferenceController.class).init(this);
         use(LocationSettingsFooterPreferenceController.class).init(this);
 
         final int profileType = getArguments().getInt(ProfileSelectFragment.EXTRA_PROFILE);
diff --git a/src/com/android/settings/location/RecentLocationAccessSeeAllButtonPreferenceController.java b/src/com/android/settings/location/RecentLocationAccessSeeAllButtonPreferenceController.java
deleted file mode 100644
index 68cde63..0000000
--- a/src/com/android/settings/location/RecentLocationAccessSeeAllButtonPreferenceController.java
+++ /dev/null
@@ -1,49 +0,0 @@
-/*
- * Copyright 2021 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.location;
-
-import android.content.Context;
-
-import androidx.preference.Preference;
-import androidx.preference.PreferenceScreen;
-
-/**
- * Preference controller that handles the "See All" button for recent location access.
- */
-public class RecentLocationAccessSeeAllButtonPreferenceController extends
-        LocationBasePreferenceController {
-
-    private Preference mPreference;
-
-    /**
-     * Constructor of {@link RecentLocationAccessSeeAllButtonPreferenceController}.
-     */
-    public RecentLocationAccessSeeAllButtonPreferenceController(Context context, String key) {
-        super(context, key);
-    }
-
-    @Override
-    public void displayPreference(PreferenceScreen screen) {
-        super.displayPreference(screen);
-        mPreference = screen.findPreference(getPreferenceKey());
-    }
-
-    @Override
-    public void onLocationModeChanged(int mode, boolean restricted) {
-        boolean enabled = mLocationEnabler.isEnabled(mode);
-        mPreference.setVisible(enabled);
-    }
-}
diff --git a/src/com/android/settings/network/telephony/Enable2gPreferenceController.java b/src/com/android/settings/network/telephony/Enable2gPreferenceController.java
index cf08d10..d336cb4 100644
--- a/src/com/android/settings/network/telephony/Enable2gPreferenceController.java
+++ b/src/com/android/settings/network/telephony/Enable2gPreferenceController.java
@@ -72,7 +72,7 @@
     public int getAvailabilityStatus(int subId) {
         final PersistableBundle carrierConfig = mCarrierConfigManager.getConfigForSubId(subId);
         boolean visible =
-                subId != SubscriptionManager.INVALID_SUBSCRIPTION_ID
+                SubscriptionManager.isUsableSubscriptionId(subId)
                 && carrierConfig != null
                 && !carrierConfig.getBoolean(CarrierConfigManager.KEY_HIDE_ENABLE_2G)
                 && mTelephonyManager.isRadioInterfaceCapabilitySupported(
@@ -89,6 +89,9 @@
 
     @Override
     public boolean setChecked(boolean isChecked) {
+        if (!SubscriptionManager.isUsableSubscriptionId(mSubId)) {
+            return false;
+        }
         long currentlyAllowedNetworkTypes = mTelephonyManager.getAllowedNetworkTypesForReason(
                 mTelephonyManager.ALLOWED_NETWORK_TYPES_REASON_ENABLE_2G);
         boolean enabled = (currentlyAllowedNetworkTypes & BITMASK_2G) != 0;
diff --git a/src/com/android/settings/notification/NotificationAssistantPreferenceController.java b/src/com/android/settings/notification/NotificationAssistantPreferenceController.java
index 6237326..a46f164 100644
--- a/src/com/android/settings/notification/NotificationAssistantPreferenceController.java
+++ b/src/com/android/settings/notification/NotificationAssistantPreferenceController.java
@@ -77,11 +77,7 @@
     protected void setNotificationAssistantGranted(ComponentName cn) {
         if (Settings.Secure.getIntForUser(mContext.getContentResolver(),
                 Settings.Secure.NAS_SETTINGS_UPDATED, 0, mUserId) == 0) {
-            for (int profileId : mUserManager.getProfileIds(mUserId, false)) {
-                Settings.Secure.putIntForUser(mContext.getContentResolver(),
-                        Settings.Secure.NAS_SETTINGS_UPDATED, 1, profileId);
-            }
-            mNotificationBackend.resetDefaultNotificationAssistant(cn != null);
+            mNotificationBackend.setNASMigrationDoneAndResetDefault(mUserId, cn != null);
         }
         mNotificationBackend.setNotificationAssistantGranted(cn);
     }
diff --git a/src/com/android/settings/notification/NotificationBackend.java b/src/com/android/settings/notification/NotificationBackend.java
index b08d02c..e448dda 100644
--- a/src/com/android/settings/notification/NotificationBackend.java
+++ b/src/com/android/settings/notification/NotificationBackend.java
@@ -570,9 +570,9 @@
         }
     }
 
-    public void resetDefaultNotificationAssistant(boolean loadFromConfig) {
+    public void setNASMigrationDoneAndResetDefault(int userId, boolean loadFromConfig) {
         try {
-            sINM.resetDefaultNotificationAssistant(loadFromConfig);
+            sINM.setNASMigrationDoneAndResetDefault(userId, loadFromConfig);
         } catch (Exception e) {
             Log.w(TAG, "Error calling NoMan", e);
         }
diff --git a/src/com/android/settings/notification/app/NotificationFooterPreference.java b/src/com/android/settings/notification/app/NotificationFooterPreference.java
deleted file mode 100644
index 6f34cdd..0000000
--- a/src/com/android/settings/notification/app/NotificationFooterPreference.java
+++ /dev/null
@@ -1,58 +0,0 @@
-/*
- * Copyright (C) 2017 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.notification.app;
-
-import android.content.Context;
-import android.text.method.LinkMovementMethod;
-import android.util.AttributeSet;
-import android.widget.TextView;
-
-import androidx.core.content.res.TypedArrayUtils;
-import androidx.preference.Preference;
-import androidx.preference.PreferenceViewHolder;
-
-import com.android.settingslib.R;
-
-/**
- * FooterPreference that can have any key or ordering.
- */
-public class NotificationFooterPreference extends Preference {
-
-    public NotificationFooterPreference(Context context, AttributeSet attrs) {
-        super(context, attrs, TypedArrayUtils.getAttr(
-                context, R.attr.footerPreferenceStyle, android.R.attr.preferenceStyle));
-        init();
-    }
-
-    public NotificationFooterPreference(Context context) {
-        this(context, null);
-    }
-
-    @Override
-    public void onBindViewHolder(PreferenceViewHolder holder) {
-        super.onBindViewHolder(holder);
-        TextView title = holder.itemView.findViewById(android.R.id.title);
-        title.setMovementMethod(new LinkMovementMethod());
-        title.setClickable(false);
-        title.setLongClickable(false);
-    }
-
-    private void init() {
-        setIcon(R.drawable.ic_info_outline_24dp);
-        setSelectable(false);
-    }
-}
diff --git a/src/com/android/settings/uwb/UwbPreferenceController.java b/src/com/android/settings/uwb/UwbPreferenceController.java
new file mode 100644
index 0000000..daadb63
--- /dev/null
+++ b/src/com/android/settings/uwb/UwbPreferenceController.java
@@ -0,0 +1,168 @@
+/*
+ * Copyright (C) 2021 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.uwb;
+
+import static androidx.lifecycle.Lifecycle.Event.ON_START;
+import static androidx.lifecycle.Lifecycle.Event.ON_STOP;
+
+import android.content.BroadcastReceiver;
+import android.content.Context;
+import android.content.Intent;
+import android.content.IntentFilter;
+import android.content.pm.PackageManager;
+import android.provider.Settings;
+import android.uwb.UwbManager;
+import android.uwb.UwbManager.AdapterStateCallback;
+
+import androidx.lifecycle.LifecycleObserver;
+import androidx.lifecycle.OnLifecycleEvent;
+import androidx.preference.Preference;
+import androidx.preference.PreferenceScreen;
+
+import com.android.internal.annotations.VisibleForTesting;
+import com.android.settings.R;
+import com.android.settings.core.TogglePreferenceController;
+
+import java.util.concurrent.Executor;
+import java.util.concurrent.Executors;
+
+/** Controller for "UWB" toggle. */
+public class UwbPreferenceController extends TogglePreferenceController implements
+        AdapterStateCallback, LifecycleObserver {
+    @VisibleForTesting
+    static final String KEY_UWB_SETTINGS = "uwb_settings";
+    @VisibleForTesting
+    UwbManager mUwbManager;
+    @VisibleForTesting
+    boolean mAirplaneModeOn;
+    @VisibleForTesting
+    private final BroadcastReceiver mAirplaneModeChangedReceiver;
+    private final Executor mExecutor;
+    private boolean mIsChecked = true;
+    boolean mRegisteredAdapterStateCallback = false;
+    private Preference mPreference;
+
+    public UwbPreferenceController(Context context, String key) {
+        super(context, key);
+        mExecutor = Executors.newSingleThreadExecutor();
+        mUwbManager = context.getSystemService(UwbManager.class);
+        mAirplaneModeOn = Settings.Global.getInt(mContext.getContentResolver(),
+                Settings.Global.AIRPLANE_MODE_ON, 0) == 1;
+        mAirplaneModeChangedReceiver = new BroadcastReceiver() {
+            @Override
+            public void onReceive(Context context, Intent intent) {
+                updateState(mPreference);
+            }
+        };
+    }
+
+    @VisibleForTesting
+    boolean isUwbSupportedOnDevice() {
+        return mContext.getPackageManager().hasSystemFeature(PackageManager.FEATURE_UWB);
+    }
+
+    @Override
+    public int getAvailabilityStatus() {
+        if (!isUwbSupportedOnDevice()) {
+            return UNSUPPORTED_ON_DEVICE;
+        } else if (mAirplaneModeOn) {
+            return DISABLED_DEPENDENT_SETTING;
+        } else {
+            return AVAILABLE;
+        }
+    }
+
+    @Override
+    public void displayPreference(PreferenceScreen screen) {
+        super.displayPreference(screen);
+        mPreference = screen.findPreference(getPreferenceKey());
+    }
+
+    @Override
+    public boolean isChecked() {
+        //TODO(b/186075119): Update toggle state by assigning to the real value by default.
+        return mIsChecked;
+    }
+
+    @Override
+    public boolean setChecked(boolean isChecked) {
+        mIsChecked = isChecked;
+        mUwbManager.setUwbEnabled(isChecked);
+        return true;
+    }
+
+    @Override
+    public void onStateChanged(int state, int reason) {
+        // Only update toggle state from service the first time. Otherwise toggle state is
+        // changed from controller. For example, UWB is disabled if airplane mode is on but we do
+        // not want to change the preference for the user in this case.
+        if (!mRegisteredAdapterStateCallback) {
+            mIsChecked = state == STATE_ENABLED_ACTIVE || state == STATE_ENABLED_INACTIVE;
+            mRegisteredAdapterStateCallback = true;
+        }
+    }
+
+    /** Called when activity starts being displayed to user. */
+    @OnLifecycleEvent(ON_START)
+    public void onStart() {
+        if (isUwbSupportedOnDevice()) {
+            mUwbManager.registerAdapterStateCallback(mExecutor, this);
+        }
+        if (mAirplaneModeChangedReceiver != null) {
+            mContext.registerReceiver(mAirplaneModeChangedReceiver,
+                    new IntentFilter(Intent.ACTION_AIRPLANE_MODE_CHANGED));
+        }
+        refreshSummary(mPreference);
+    }
+
+    /** Called when activity stops being displayed to user. */
+    @OnLifecycleEvent(ON_STOP)
+    public void onStop() {
+        if (isUwbSupportedOnDevice()) {
+            mUwbManager.unregisterAdapterStateCallback(this);
+        }
+        if (mAirplaneModeChangedReceiver != null) {
+            mContext.unregisterReceiver(mAirplaneModeChangedReceiver);
+        }
+    }
+
+    @Override
+    public void updateState(Preference preference) {
+        super.updateState(preference);
+        mAirplaneModeOn = Settings.Global.getInt(mContext.getContentResolver(),
+                Settings.Global.AIRPLANE_MODE_ON, 0) == 1;
+        preference.setEnabled(!mAirplaneModeOn);
+        if (isUwbSupportedOnDevice()) {
+            if (mAirplaneModeOn) {
+                mUwbManager.setUwbEnabled(false);
+            } else {
+                mUwbManager.setUwbEnabled(mIsChecked);
+            }
+        }
+        refreshSummary(preference);
+    }
+
+    @Override
+    public CharSequence getSummary() {
+        if (mAirplaneModeOn) {
+            return mContext.getResources().getString(R.string.uwb_settings_summary_airplane_mode);
+        } else {
+            return mContext.getResources().getString(R.string.uwb_settings_summary);
+        }
+    }
+}
+
diff --git a/tests/robotests/src/com/android/settings/fuelgauge/AdvancedPowerUsageDetailTest.java b/tests/robotests/src/com/android/settings/fuelgauge/AdvancedPowerUsageDetailTest.java
index a288c3a..dd10a9e 100644
--- a/tests/robotests/src/com/android/settings/fuelgauge/AdvancedPowerUsageDetailTest.java
+++ b/tests/robotests/src/com/android/settings/fuelgauge/AdvancedPowerUsageDetailTest.java
@@ -249,14 +249,122 @@
     }
 
     @Test
-    public void testInitHeader_hasCorrectSummary() {
-        mFragment.mAppEntry = null;
+    public void testInitHeader_noUsageTime_hasCorrectSummary() {
+        Bundle bundle = new Bundle(2);
+        bundle.putLong(AdvancedPowerUsageDetail.EXTRA_BACKGROUND_TIME, /* value */ 0);
+        bundle.putLong(AdvancedPowerUsageDetail.EXTRA_FOREGROUND_TIME, /* value */ 0);
+        when(mFragment.getArguments()).thenReturn(bundle);
+
         mFragment.initHeader();
 
         ArgumentCaptor<CharSequence> captor = ArgumentCaptor.forClass(CharSequence.class);
         verify(mEntityHeaderController).setSummary(captor.capture());
         assertThat(captor.getValue().toString())
-                .isEqualTo("0 min total • 0 min background for past 24 hr");
+                .isEqualTo("No usage for past 24 hr");
+    }
+
+    @Test
+    public void testInitHeader_backgroundTwoMinutesForegroundZero_hasCorrectSummary() {
+        final long backgroundTimeTwoMinutes = 120000;
+        final long foregroundTimeZero = 0;
+        Bundle bundle = new Bundle(2);
+        bundle.putLong(AdvancedPowerUsageDetail.EXTRA_BACKGROUND_TIME, backgroundTimeTwoMinutes);
+        bundle.putLong(AdvancedPowerUsageDetail.EXTRA_FOREGROUND_TIME, foregroundTimeZero);
+        when(mFragment.getArguments()).thenReturn(bundle);
+
+        mFragment.initHeader();
+
+        ArgumentCaptor<CharSequence> captor = ArgumentCaptor.forClass(CharSequence.class);
+        verify(mEntityHeaderController).setSummary(captor.capture());
+        assertThat(captor.getValue().toString())
+                .isEqualTo("2 min background for past 24 hr");
+    }
+
+    @Test
+    public void testInitHeader_backgroundLessThanAMinutesForegroundZero_hasCorrectSummary() {
+        final long backgroundTimeLessThanAMinute = 59999;
+        final long foregroundTimeZero = 0;
+        Bundle bundle = new Bundle(2);
+        bundle.putLong(
+                AdvancedPowerUsageDetail.EXTRA_BACKGROUND_TIME, backgroundTimeLessThanAMinute);
+        bundle.putLong(AdvancedPowerUsageDetail.EXTRA_FOREGROUND_TIME, foregroundTimeZero);
+        when(mFragment.getArguments()).thenReturn(bundle);
+
+        mFragment.initHeader();
+
+        ArgumentCaptor<CharSequence> captor = ArgumentCaptor.forClass(CharSequence.class);
+        verify(mEntityHeaderController).setSummary(captor.capture());
+        assertThat(captor.getValue().toString())
+                .isEqualTo("Background less than a minute for past 24 hr");
+    }
+
+    @Test
+    public void testInitHeader_totalUsageLessThanAMinutes_hasCorrectSummary() {
+        final long backgroundTimeLessThanHalfMinute = 20000;
+        final long foregroundTimeLessThanHalfMinute = 20000;
+        Bundle bundle = new Bundle(2);
+        bundle.putLong(
+                AdvancedPowerUsageDetail.EXTRA_BACKGROUND_TIME, backgroundTimeLessThanHalfMinute);
+        bundle.putLong(
+                AdvancedPowerUsageDetail.EXTRA_FOREGROUND_TIME, foregroundTimeLessThanHalfMinute);
+        when(mFragment.getArguments()).thenReturn(bundle);
+
+        mFragment.initHeader();
+
+        ArgumentCaptor<CharSequence> captor = ArgumentCaptor.forClass(CharSequence.class);
+        verify(mEntityHeaderController).setSummary(captor.capture());
+        assertThat(captor.getValue().toString())
+                .isEqualTo("Total less than a minute for past 24 hr");
+    }
+
+    @Test
+    public void testInitHeader_TotalAMinutesBackgroundLessThanAMinutes_hasCorrectSummary() {
+        final long backgroundTimeZero = 59999;
+        final long foregroundTimeTwoMinutes = 1;
+        Bundle bundle = new Bundle(2);
+        bundle.putLong(AdvancedPowerUsageDetail.EXTRA_BACKGROUND_TIME, backgroundTimeZero);
+        bundle.putLong(AdvancedPowerUsageDetail.EXTRA_FOREGROUND_TIME, foregroundTimeTwoMinutes);
+        when(mFragment.getArguments()).thenReturn(bundle);
+
+        mFragment.initHeader();
+
+        ArgumentCaptor<CharSequence> captor = ArgumentCaptor.forClass(CharSequence.class);
+        verify(mEntityHeaderController).setSummary(captor.capture());
+        assertThat(captor.getValue().toString())
+                .isEqualTo("1 min total • background less than a minute for past 24 hr");
+    }
+
+    @Test
+    public void testInitHeader_TotalAMinutesBackgroundZero_hasCorrectSummary() {
+        final long backgroundTimeZero = 0;
+        final long foregroundTimeAMinutes = 60000;
+        Bundle bundle = new Bundle(2);
+        bundle.putLong(AdvancedPowerUsageDetail.EXTRA_BACKGROUND_TIME, backgroundTimeZero);
+        bundle.putLong(AdvancedPowerUsageDetail.EXTRA_FOREGROUND_TIME, foregroundTimeAMinutes);
+        when(mFragment.getArguments()).thenReturn(bundle);
+
+        mFragment.initHeader();
+
+        ArgumentCaptor<CharSequence> captor = ArgumentCaptor.forClass(CharSequence.class);
+        verify(mEntityHeaderController).setSummary(captor.capture());
+        assertThat(captor.getValue().toString())
+                .isEqualTo("1 min total for past 24 hr");
+    }
+
+    @Test
+    public void testInitHeader_foregroundTwoMinutesBackgroundFourMinutes_hasCorrectSummary() {
+        final long backgroundTimeFourMinute = 240000;
+        final long foregroundTimeTwoMinutes = 120000;
+        Bundle bundle = new Bundle(2);
+        bundle.putLong(AdvancedPowerUsageDetail.EXTRA_BACKGROUND_TIME, backgroundTimeFourMinute);
+        bundle.putLong(AdvancedPowerUsageDetail.EXTRA_FOREGROUND_TIME, foregroundTimeTwoMinutes);
+        when(mFragment.getArguments()).thenReturn(bundle);
+        mFragment.initHeader();
+
+        ArgumentCaptor<CharSequence> captor = ArgumentCaptor.forClass(CharSequence.class);
+        verify(mEntityHeaderController).setSummary(captor.capture());
+        assertThat(captor.getValue().toString())
+                .isEqualTo("6 min total • 4 min background for past 24 hr");
     }
 
     @Test
diff --git a/tests/robotests/src/com/android/settings/fuelgauge/BatteryChartPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/fuelgauge/BatteryChartPreferenceControllerTest.java
index c8bbba3..9f0ffb0 100644
--- a/tests/robotests/src/com/android/settings/fuelgauge/BatteryChartPreferenceControllerTest.java
+++ b/tests/robotests/src/com/android/settings/fuelgauge/BatteryChartPreferenceControllerTest.java
@@ -43,6 +43,7 @@
 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;
@@ -56,6 +57,8 @@
 
 @RunWith(RobolectricTestRunner.class)
 public final class BatteryChartPreferenceControllerTest {
+    private static final String PREF_KEY = "pref_key";
+    private static final String PREF_SUMMARY = "fake preference summary";
 
     @Mock private InstrumentedPreferenceFragment mFragment;
     @Mock private SettingsActivity mSettingsActivity;
@@ -119,10 +122,9 @@
 
     @Test
     public void testOnDestroy_clearPreferenceCache() {
-        final String prefKey = "preference fake key";
         // Ensures the testing environment is correct.
         mBatteryChartPreferenceController.mPreferenceCache.put(
-            prefKey, mPowerGaugePreference);
+            PREF_KEY, mPowerGaugePreference);
         assertThat(mBatteryChartPreferenceController.mPreferenceCache).hasSize(1);
 
         mBatteryChartPreferenceController.onDestroy();
@@ -230,17 +232,16 @@
     @Test
     public void testRemoveAndCacheAllPrefs_buildCacheAndRemoveAllPreference() {
         final int trapezoidIndex = 1;
-        final String prefKey = "preference fake key";
         doReturn(1).when(mAppListGroup).getPreferenceCount();
         doReturn(mPowerGaugePreference).when(mAppListGroup).getPreference(0);
-        doReturn(prefKey).when(mPowerGaugePreference).getKey();
+        doReturn(PREF_KEY).when(mPowerGaugePreference).getKey();
         // Ensures the testing data is correct.
         assertThat(mBatteryChartPreferenceController.mPreferenceCache).isEmpty();
 
         mBatteryChartPreferenceController.refreshUi(
             trapezoidIndex, /*isForce=*/ true);
 
-        assertThat(mBatteryChartPreferenceController.mPreferenceCache.get(prefKey))
+        assertThat(mBatteryChartPreferenceController.mPreferenceCache.get(PREF_KEY))
             .isEqualTo(mPowerGaugePreference);
         verify(mAppListGroup).removeAll();
     }
@@ -254,12 +255,12 @@
 
     @Test
     public void testAddPreferenceToScreen_addPreferenceIntoScreen() {
-        final String prefKey = "preference fake key";
         final String appLabel = "fake app label";
         doReturn(1).when(mAppListGroup).getPreferenceCount();
         doReturn(mDrawable).when(mBatteryDiffEntry).getAppIcon();
         doReturn(appLabel).when(mBatteryDiffEntry).getAppLabel();
-        doReturn(prefKey).when(mBatteryHistEntry).getKey();
+        doReturn(PREF_KEY).when(mBatteryHistEntry).getKey();
+        doReturn(null).when(mAppListGroup).findPreference(PREF_KEY);
 
         mBatteryChartPreferenceController.addPreferenceToScreen(
             Arrays.asList(mBatteryDiffEntry));
@@ -267,11 +268,11 @@
         // Verifies the preference cache.
         final PowerGaugePreference pref =
             (PowerGaugePreference) mBatteryChartPreferenceController.mPreferenceCache
-                .get(prefKey);
+                .get(PREF_KEY);
         assertThat(pref).isNotNull();
         // Verifies the added preference configuration.
         verify(mAppListGroup).addPreference(pref);
-        assertThat(pref.getKey()).isEqualTo(prefKey);
+        assertThat(pref.getKey()).isEqualTo(PREF_KEY);
         assertThat(pref.getTitle()).isEqualTo(appLabel);
         assertThat(pref.getIcon()).isEqualTo(mDrawable);
         assertThat(pref.getOrder()).isEqualTo(1);
@@ -280,6 +281,21 @@
     }
 
     @Test
+    public void testAddPreferenceToScreen_alreadyInScreen_notAddPreferenceAgain() {
+        final String appLabel = "fake app label";
+        doReturn(1).when(mAppListGroup).getPreferenceCount();
+        doReturn(mDrawable).when(mBatteryDiffEntry).getAppIcon();
+        doReturn(appLabel).when(mBatteryDiffEntry).getAppLabel();
+        doReturn(PREF_KEY).when(mBatteryHistEntry).getKey();
+        doReturn(mPowerGaugePreference).when(mAppListGroup).findPreference(PREF_KEY);
+
+        mBatteryChartPreferenceController.addPreferenceToScreen(
+            Arrays.asList(mBatteryDiffEntry));
+
+        verify(mAppListGroup, never()).addPreference(any());
+    }
+
+    @Test
     public void testHandlePreferenceTreeClick_notPowerGaugePreference_returnFalse() {
         assertThat(mBatteryChartPreferenceController.handlePreferenceTreeClick(mAppListGroup))
             .isFalse();
@@ -309,7 +325,7 @@
     @Test
     public void testSetPreferenceSummary_setNullContentIfTotalUsageTimeIsZero() {
         final PowerGaugePreference pref = new PowerGaugePreference(mContext);
-        pref.setSummary("fake preference summary");
+        pref.setSummary(PREF_SUMMARY);
 
         mBatteryChartPreferenceController.setPreferenceSummary(
             pref, createBatteryDiffEntry(
@@ -321,7 +337,7 @@
     @Test
     public void testSetPreferenceSummary_setBackgroundUsageTimeOnly() {
         final PowerGaugePreference pref = new PowerGaugePreference(mContext);
-        pref.setSummary("fake preference summary");
+        pref.setSummary(PREF_SUMMARY);
 
         mBatteryChartPreferenceController.setPreferenceSummary(
             pref, createBatteryDiffEntry(
@@ -333,7 +349,7 @@
     @Test
     public void testSetPreferenceSummary_setTotalUsageTimeLessThanAMinute() {
         final PowerGaugePreference pref = new PowerGaugePreference(mContext);
-        pref.setSummary("fake preference summary");
+        pref.setSummary(PREF_SUMMARY);
 
         mBatteryChartPreferenceController.setPreferenceSummary(
             pref, createBatteryDiffEntry(
@@ -345,7 +361,7 @@
     @Test
     public void testSetPreferenceSummary_setTotalTimeIfBackgroundTimeLessThanAMinute() {
         final PowerGaugePreference pref = new PowerGaugePreference(mContext);
-        pref.setSummary("fake preference summary");
+        pref.setSummary(PREF_SUMMARY);
 
         mBatteryChartPreferenceController.setPreferenceSummary(
             pref, createBatteryDiffEntry(
@@ -357,7 +373,7 @@
     @Test
     public void testSetPreferenceSummary_setTotalAndBackgroundUsageTime() {
         final PowerGaugePreference pref = new PowerGaugePreference(mContext);
-        pref.setSummary("fake preference summary");
+        pref.setSummary(PREF_SUMMARY);
 
         mBatteryChartPreferenceController.setPreferenceSummary(
             pref, createBatteryDiffEntry(
@@ -369,7 +385,7 @@
     @Test
     public void testSetPreferenceSummary_notAllowShownPackage_setSummayAsNull() {
         final PowerGaugePreference pref = new PowerGaugePreference(mContext);
-        pref.setSummary("fake preference summary");
+        pref.setSummary(PREF_SUMMARY);
         final BatteryDiffEntry batteryDiffEntry =
             spy(createBatteryDiffEntry(
                 /*foregroundUsageTimeInMs=*/ DateUtils.MINUTE_IN_MILLIS,
@@ -416,23 +432,54 @@
 
     @Test
     public void testValidateSlotTimestamp_returnExpectedResult() {
-        final List<Long> slotTimestampList =
+        final ArrayList<Long> slotTimestampList = new ArrayList<Long>(
             Arrays.asList(
                 Long.valueOf(0),
                 Long.valueOf(DateUtils.HOUR_IN_MILLIS),
                 Long.valueOf(DateUtils.HOUR_IN_MILLIS * 2 + DateUtils.MINUTE_IN_MILLIS),
-                Long.valueOf(DateUtils.HOUR_IN_MILLIS * 3 + DateUtils.MINUTE_IN_MILLIS * 2));
+                Long.valueOf(DateUtils.HOUR_IN_MILLIS * 3 + DateUtils.MINUTE_IN_MILLIS * 2)));
         // Verifies the testing data is correct before we added invalid data into it.
         assertThat(BatteryChartPreferenceController.validateSlotTimestamp(slotTimestampList))
             .isTrue();
 
         // Insert invalid timestamp into the list.
         slotTimestampList.add(
-            Long.valueOf(DateUtils.HOUR_IN_MILLIS * 4 + DateUtils.MINUTE_IN_MILLIS * 3));
+            Long.valueOf(DateUtils.HOUR_IN_MILLIS * 4 + DateUtils.MINUTE_IN_MILLIS * 6));
         assertThat(BatteryChartPreferenceController.validateSlotTimestamp(slotTimestampList))
             .isFalse();
     }
 
+    @Test
+    public void testOnExpand_expandedIsTrue_addSystemEntriesToPreferenceGroup() {
+        doReturn(1).when(mAppListGroup).getPreferenceCount();
+        mBatteryChartPreferenceController.mSystemEntries.add(mBatteryDiffEntry);
+        doReturn("label").when(mBatteryDiffEntry).getAppLabel();
+        doReturn(mDrawable).when(mBatteryDiffEntry).getAppIcon();
+        doReturn(PREF_KEY).when(mBatteryHistEntry).getKey();
+
+        mBatteryChartPreferenceController.onExpand(/*isExpanded=*/ true);
+
+        final ArgumentCaptor<Preference> captor = ArgumentCaptor.forClass(Preference.class);
+        verify(mAppListGroup).addPreference(captor.capture());
+        // Verifies the added preference.
+        assertThat(captor.getValue().getKey()).isEqualTo(PREF_KEY);
+    }
+
+    @Test
+    public void testOnExpand_expandedIsFalse_removeSystemEntriesFromPreferenceGroup() {
+        doReturn(PREF_KEY).when(mBatteryHistEntry).getKey();
+        doReturn(mPowerGaugePreference).when(mAppListGroup).findPreference(PREF_KEY);
+        mBatteryChartPreferenceController.mSystemEntries.add(mBatteryDiffEntry);
+        // Verifies the cache is empty first.
+        assertThat(mBatteryChartPreferenceController.mPreferenceCache).isEmpty();
+
+        mBatteryChartPreferenceController.onExpand(/*isExpanded=*/ false);
+
+        verify(mAppListGroup).findPreference(PREF_KEY);
+        verify(mAppListGroup).removePreference(mPowerGaugePreference);
+        assertThat(mBatteryChartPreferenceController.mPreferenceCache).hasSize(1);
+    }
+
     private static Map<Long, List<BatteryHistEntry>> createBatteryHistoryMap(int size) {
         final Map<Long, List<BatteryHistEntry>> batteryHistoryMap = new HashMap<>();
         for (int index = 0; index < size; index++) {
diff --git a/tests/robotests/src/com/android/settings/notification/NotificationAssistantPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/notification/NotificationAssistantPreferenceControllerTest.java
index f6b72d9..9b45a98 100644
--- a/tests/robotests/src/com/android/settings/notification/NotificationAssistantPreferenceControllerTest.java
+++ b/tests/robotests/src/com/android/settings/notification/NotificationAssistantPreferenceControllerTest.java
@@ -122,13 +122,13 @@
         assertEquals(1, Settings.Secure.getIntForUser(mContext.getContentResolver(),
                 Settings.Secure.NAS_SETTINGS_UPDATED, 0, 10));
         verify(mBackend, times(1))
-                .resetDefaultNotificationAssistant(eq(true));
+                .setNASMigrationDoneAndResetDefault(eq(0), eq(true));
 
         //Test user enable again, migration should not happen
         mPreferenceController.setNotificationAssistantGranted(mNASComponent);
         //Number of invocations should not increase
         verify(mBackend, times(1))
-                .resetDefaultNotificationAssistant(eq(true));
+                .setNASMigrationDoneAndResetDefault(eq(0), eq(true));
     }
 
     @Test
@@ -146,13 +146,13 @@
         assertEquals(0, Settings.Secure.getIntForUser(mContext.getContentResolver(),
                 Settings.Secure.NAS_SETTINGS_UPDATED, 0, 20));
         verify(mBackend, times(1))
-                .resetDefaultNotificationAssistant(eq(true));
+                .setNASMigrationDoneAndResetDefault(eq(0), eq(true));
 
         //Test user enable again, migration should not happen
         mPreferenceController.setNotificationAssistantGranted(mNASComponent);
         //Number of invocations should not increase
         verify(mBackend, times(1))
-                .resetDefaultNotificationAssistant(eq(true));
+                .setNASMigrationDoneAndResetDefault(eq(0), eq(true));
     }
 
     @Test
@@ -170,13 +170,13 @@
         assertEquals(1, Settings.Secure.getIntForUser(mContext.getContentResolver(),
                 Settings.Secure.NAS_SETTINGS_UPDATED, 0, 10));
         verify(mBackend, times(1))
-                .resetDefaultNotificationAssistant(eq(false));
+                .setNASMigrationDoneAndResetDefault(eq(0), eq(false));
 
         //Test user disable again, migration should not happen
         mPreferenceController.setChecked(false);
         //Number of invocations should not increase
         verify(mBackend, times(1))
-                .resetDefaultNotificationAssistant(eq(false));
+                .setNASMigrationDoneAndResetDefault(eq(0), eq(false));
     }
 
 }
diff --git a/tests/robotests/src/com/android/settings/uwb/UwbPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/uwb/UwbPreferenceControllerTest.java
new file mode 100644
index 0000000..00dc4df
--- /dev/null
+++ b/tests/robotests/src/com/android/settings/uwb/UwbPreferenceControllerTest.java
@@ -0,0 +1,176 @@
+/*
+ * Copyright (C) 2021 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.uwb;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import static org.mockito.Mockito.clearInvocations;
+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 android.content.Context;
+import android.content.pm.PackageManager;
+import android.uwb.UwbManager;
+
+import com.android.settings.core.BasePreferenceController;
+
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.junit.MockitoJUnit;
+import org.mockito.junit.MockitoRule;
+import org.robolectric.RobolectricTestRunner;
+import org.robolectric.RuntimeEnvironment;
+
+/** Unit tests for UWB preference toggle. */
+@RunWith(RobolectricTestRunner.class)
+public class UwbPreferenceControllerTest {
+    @Rule
+    public MockitoRule rule = MockitoJUnit.rule();
+
+    private Context mContext;
+    private PackageManager mPackageManager;
+    private UwbPreferenceController mController;
+
+    @Mock
+    private UwbManager mUwbManager;
+
+    @Before
+    public void setUp() {
+        mContext = spy(RuntimeEnvironment.application);
+        mPackageManager = spy(mContext.getPackageManager());
+        mController = new UwbPreferenceController(mContext, "uwb_settings");
+        mController.mUwbManager = mUwbManager;
+    }
+
+    @Test
+    public void getAvailabilityStatus_uwbDisabled_shouldReturnDisabled() {
+        doReturn(mPackageManager).when(mContext).getPackageManager();
+        doReturn(true).when(mPackageManager)
+                .hasSystemFeature(PackageManager.FEATURE_UWB);
+        mController.mAirplaneModeOn = true;
+
+        assertThat(mController.getAvailabilityStatus())
+                .isEqualTo(BasePreferenceController.DISABLED_DEPENDENT_SETTING);
+    }
+
+    @Test
+    public void getAvailabilityStatus_uwbShown_shouldReturnAvailable() {
+        doReturn(mPackageManager).when(mContext).getPackageManager();
+        doReturn(true).when(mPackageManager)
+                .hasSystemFeature(PackageManager.FEATURE_UWB);
+        mController.mAirplaneModeOn = false;
+
+        assertThat(mController.getAvailabilityStatus())
+                .isEqualTo(BasePreferenceController.AVAILABLE);
+    }
+
+    @Test
+    public void getAvailabilityStatus_uwbNotShown_shouldReturnUnsupported() {
+        doReturn(mPackageManager).when(mContext).getPackageManager();
+        doReturn(false).when(mPackageManager)
+                .hasSystemFeature(PackageManager.FEATURE_UWB);
+
+        assertThat(mController.getAvailabilityStatus())
+                .isEqualTo(BasePreferenceController.UNSUPPORTED_ON_DEVICE);
+    }
+
+    @Test
+    public void onStateChanged_stateNotRegistered_shouldUpdate() {
+        mController.mRegisteredAdapterStateCallback = false;
+        mController.onStateChanged(UwbManager.AdapterStateCallback.STATE_DISABLED,
+                UwbManager.AdapterStateCallback.STATE_CHANGED_REASON_SYSTEM_POLICY);
+
+        assertThat(mController.isChecked()).isFalse();
+    }
+
+    @Test
+    public void onStateChanged_stateRegistered_shouldNotUpdate() {
+        mController.mRegisteredAdapterStateCallback = true;
+        mController.onStateChanged(UwbManager.AdapterStateCallback.STATE_ENABLED_INACTIVE,
+                UwbManager.AdapterStateCallback.STATE_CHANGED_REASON_SYSTEM_POLICY);
+
+        assertThat(mController.isChecked()).isTrue();
+    }
+
+    @Test
+    public void isChecked_uwbEnabledInactive_shouldReturnTrue() {
+        doReturn(mPackageManager).when(mContext).getPackageManager();
+        doReturn(true).when(mPackageManager)
+                .hasSystemFeature(PackageManager.FEATURE_UWB);
+        mController.mRegisteredAdapterStateCallback = false;
+        mController.onStateChanged(UwbManager.AdapterStateCallback.STATE_ENABLED_INACTIVE,
+                UwbManager.AdapterStateCallback.STATE_CHANGED_REASON_SYSTEM_POLICY);
+
+        assertThat(mController.isChecked()).isTrue();
+    }
+
+    @Test
+    public void isChecked_uwbEnabledActive_shouldReturnTrue() {
+        doReturn(mPackageManager).when(mContext).getPackageManager();
+        doReturn(true).when(mPackageManager)
+                .hasSystemFeature(PackageManager.FEATURE_UWB);
+        mController.mRegisteredAdapterStateCallback = false;
+        mController.onStateChanged(UwbManager.AdapterStateCallback.STATE_ENABLED_ACTIVE,
+                UwbManager.AdapterStateCallback.STATE_CHANGED_REASON_SYSTEM_POLICY);
+
+        assertThat(mController.isChecked()).isTrue();
+    }
+
+    @Test
+    public void isChecked_uwbDisabled_shouldReturnFalse() {
+        doReturn(mPackageManager).when(mContext).getPackageManager();
+        doReturn(true).when(mPackageManager)
+                .hasSystemFeature(PackageManager.FEATURE_UWB);
+        mController.mRegisteredAdapterStateCallback = false;
+        mController.onStateChanged(UwbManager.AdapterStateCallback.STATE_DISABLED,
+                UwbManager.AdapterStateCallback.STATE_CHANGED_REASON_SYSTEM_POLICY);
+
+        assertThat(mController.isChecked()).isFalse();
+    }
+
+    @Test
+    public void setChecked_uwbDisabled_shouldEnableUwb() {
+        clearInvocations(mUwbManager);
+        doReturn(mPackageManager).when(mContext).getPackageManager();
+        doReturn(true).when(mPackageManager)
+                .hasSystemFeature(PackageManager.FEATURE_UWB);
+
+        mController.setChecked(true);
+
+        verify(mUwbManager).setUwbEnabled(true);
+        verify(mUwbManager, never()).setUwbEnabled(false);
+    }
+
+    @Test
+    public void setChecked_uwbEnabled_shouldDisableUwb() {
+        clearInvocations(mUwbManager);
+        doReturn(mPackageManager).when(mContext).getPackageManager();
+        doReturn(true).when(mPackageManager)
+                .hasSystemFeature(PackageManager.FEATURE_UWB);
+
+        mController.setChecked(false);
+
+        verify(mUwbManager).setUwbEnabled(false);
+        verify(mUwbManager, never()).setUwbEnabled(true);
+    }
+}
+
diff --git a/tests/unit/src/com/android/settings/network/telephony/Enable2gPreferenceControllerTest.java b/tests/unit/src/com/android/settings/network/telephony/Enable2gPreferenceControllerTest.java
index 293a19d..5ade979 100644
--- a/tests/unit/src/com/android/settings/network/telephony/Enable2gPreferenceControllerTest.java
+++ b/tests/unit/src/com/android/settings/network/telephony/Enable2gPreferenceControllerTest.java
@@ -48,6 +48,8 @@
     @Mock
     private TelephonyManager mTelephonyManager;
     @Mock
+    private TelephonyManager mInvalidTelephonyManager;
+    @Mock
     private CarrierConfigManager mCarrierConfigManager;
 
     private PersistableBundle mPersistableBundle;
@@ -65,6 +67,8 @@
               .thenReturn(mCarrierConfigManager);
 
         doReturn(mTelephonyManager).when(mTelephonyManager).createForSubscriptionId(SUB_ID);
+        doReturn(mInvalidTelephonyManager).when(mTelephonyManager).createForSubscriptionId(
+                SubscriptionManager.INVALID_SUBSCRIPTION_ID);
 
         mPersistableBundle = new PersistableBundle();
         doReturn(mPersistableBundle).when(mCarrierConfigManager).getConfigForSubId(SUB_ID);
@@ -121,6 +125,18 @@
     }
 
     @Test
+    public void setChecked_invalidSubIdAndIsCheckedTrue_returnFalse() {
+        mController.init(SubscriptionManager.INVALID_SUBSCRIPTION_ID);
+        assertThat(mController.setChecked(true)).isFalse();
+    }
+
+    @Test
+    public void setChecked_invalidSubIdAndIsCheckedFalse_returnFalse() {
+        mController.init(SubscriptionManager.INVALID_SUBSCRIPTION_ID);
+        assertThat(mController.setChecked(false)).isFalse();
+    }
+
+    @Test
     public void onPreferenceChange_update() {
         // Set "Enable 2G" flag to "on"
         when(mTelephonyManager.getAllowedNetworkTypesForReason(