Merge "Show built-in display if topology is visible" into main
diff --git a/Android.bp b/Android.bp
index e81ef9e..fccbfca 100644
--- a/Android.bp
+++ b/Android.bp
@@ -134,6 +134,7 @@
         "aconfig_settings_flags",
         "android.app.flags-aconfig",
         "android.provider.flags-aconfig",
+        "android.security.flags-aconfig",
     ],
 }
 
diff --git a/AndroidManifest.xml b/AndroidManifest.xml
index 3827916..7d335c3 100644
--- a/AndroidManifest.xml
+++ b/AndroidManifest.xml
@@ -1128,6 +1128,38 @@
         </activity>
 
         <activity
+            android:name=".Settings$TemperatureUnitSettingsActivity"
+            android:label="@string/temperature_preferences_title"
+            android:exported="true" >
+            <intent-filter android:priority="1">
+                <action android:name="android.settings.TEMPERATURE_UNIT_SETTINGS" />
+                <category android:name="android.intent.category.DEFAULT" />
+            </intent-filter>
+            <meta-data android:name="com.android.settings.FRAGMENT_CLASS"
+                android:value="com.android.settings.regionalpreferences.TemperatureUnitFragment"/>
+            <meta-data android:name="com.android.settings.HIGHLIGHT_MENU_KEY"
+                android:value="@string/menu_key_system"/>
+            <meta-data android:name="com.android.settings.PRIMARY_PROFILE_CONTROLLED"
+                android:value="true"/>
+        </activity>
+
+        <activity
+            android:name=".Settings$FirstDayOfWeekSettingsActivity"
+            android:label="@string/first_day_of_week_preferences_title"
+            android:exported="true" >
+            <intent-filter android:priority="1">
+                <action android:name="android.settings.FIRST_DAY_OF_WEEK_SETTINGS" />
+                <category android:name="android.intent.category.DEFAULT" />
+            </intent-filter>
+            <meta-data android:name="com.android.settings.FRAGMENT_CLASS"
+                android:value="com.android.settings.regionalpreferences.FirstDayOfWeekItemFragment"/>
+            <meta-data android:name="com.android.settings.HIGHLIGHT_MENU_KEY"
+                android:value="@string/menu_key_system"/>
+            <meta-data android:name="com.android.settings.PRIMARY_PROFILE_CONTROLLED"
+                android:value="true"/>
+        </activity>
+
+        <activity
             android:name=".Settings$KeyboardSettingsActivity"
             android:label="@string/keyboard_settings"
             android:exported="true"
diff --git a/PREUPLOAD.cfg b/PREUPLOAD.cfg
index 01d75e8..6e22780 100644
--- a/PREUPLOAD.cfg
+++ b/PREUPLOAD.cfg
@@ -1,5 +1,6 @@
 [Hook Scripts]
-checkcolor_hook = ${REPO_ROOT}/prebuilts/checkcolor/checkcolor.py -p .
+# TODO(b/377902600): Re-enable this hook once it is fixed.
+#checkcolor_hook = ${REPO_ROOT}/prebuilts/checkcolor/checkcolor.py -p .
 
 checkstyle_hook = ${REPO_ROOT}/prebuilts/checkstyle/checkstyle.py --sha ${PREUPLOAD_COMMIT}
 
diff --git a/aconfig/settings_biometrics_integration_declarations.aconfig b/aconfig/settings_biometrics_integration_declarations.aconfig
index 8168c85..cc756c6 100644
--- a/aconfig/settings_biometrics_integration_declarations.aconfig
+++ b/aconfig/settings_biometrics_integration_declarations.aconfig
@@ -41,3 +41,14 @@
   description: "This flag controls whether the onboarding education settings UX should be enabled"
   bug: "370940762"
 }
+
+flag {
+  name: "biometric_onboarding_education"
+  namespace: "biometrics_integration"
+  description: "This flag controls whether the onboarding education settings UX should be enabled"
+  bug: "370940762"
+  metadata {
+      purpose: PURPOSE_BUGFIX
+  }
+}
+
diff --git a/aconfig/settings_development_flag_declarations.aconfig b/aconfig/settings_development_flag_declarations.aconfig
index 318f862..f2452e5 100644
--- a/aconfig/settings_development_flag_declarations.aconfig
+++ b/aconfig/settings_development_flag_declarations.aconfig
@@ -19,3 +19,10 @@
   description: "Shows hdr/sdr dev opton on the development options page from aconfig"
   bug: "291863102"
 }
+
+flag {
+  name: "page_size_app_compat_setting"
+  namespace: "devoptions_settings"
+  description: "Flag to enable page size app compat mode from Settings."
+  bug: "371049373"
+}
diff --git a/res/layout/preference_battery_header_text.xml b/res/layout/preference_battery_header_text.xml
new file mode 100644
index 0000000..72bdbf6
--- /dev/null
+++ b/res/layout/preference_battery_header_text.xml
@@ -0,0 +1,32 @@
+<!--
+  ~ Copyright (C) 2024 The Android Open Source Project
+  ~
+  ~ Licensed under the Apache License, Version 2.0 (the "License");
+  ~ you may not use this file except in compliance with the License.
+  ~ You may obtain a copy of the License at
+  ~
+  ~      http://www.apache.org/licenses/LICENSE-2.0
+  ~
+  ~ Unless required by applicable law or agreed to in writing, software
+  ~ distributed under the License is distributed on an "AS IS" BASIS,
+  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  ~ See the License for the specific language governing permissions and
+  ~ limitations under the License.
+  -->
+<LinearLayout
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    android:layout_width="match_parent"
+    android:layout_height="wrap_content"
+    android:orientation="vertical"
+    android:layout_marginStart="?android:attr/listPreferredItemPaddingStart"
+    android:layout_marginEnd="?android:attr/listPreferredItemPaddingEnd"
+    android:paddingBottom="16dp">
+
+    <TextView
+        android:id="@+id/text"
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:ellipsize="marquee"
+        android:textAppearance="@*android:style/TextAppearance.DeviceDefault.Body1"
+        android:textSize="14sp"/>
+</LinearLayout>
\ No newline at end of file
diff --git a/res/values/strings.xml b/res/values/strings.xml
index 099056e..05b3b3f 100644
--- a/res/values/strings.xml
+++ b/res/values/strings.xml
@@ -470,6 +470,8 @@
     <string name="country_selection_title">Region preference</string>
     <!-- Hint text in a search edit box (used to filter long language / country lists) [CHAR LIMIT=25] -->
     <string name="search_language_hint">Type language name</string>
+    <!-- Category for more language settings. [CHAR LIMIT=NONE]-->
+    <string name="more_language_settings_category">More language settings</string>
 
     <!-- Regional Preferences begin -->
     <!-- The title of the menu entry of regional preferences. [CHAR LIMIT=50] -->
@@ -2871,9 +2873,9 @@
     <!-- Display settings screen, screen resolution option for high resolution [CHAR LIMIT=45] -->
     <string name="screen_resolution_option_high">High resolution</string>
     <!-- Display settings screen, screen resolution option for full resolution [CHAR LIMIT=45] -->
-    <string name="screen_resolution_option_full">Full resolution</string>
+    <string name="screen_resolution_option_full">Max resolution</string>
     <!-- The footer message for switch screen resolution [CHAR LIMIT=NONE] -->
-    <string name="screen_resolution_footer">Full resolution uses more of your battery. Switching your resolution may cause some apps to restart.</string>
+    <string name="screen_resolution_footer">Max resolution uses more of your battery. Switching your resolution may cause some apps to restart.</string>
     <!-- Message announced to a11y users when they selected one resolution [CHAR LIMIT=NONE] -->
     <string name="screen_resolution_selected_a11y">Selected</string>
 
@@ -3050,7 +3052,7 @@
     <!-- Dark UI screen footer action text linking to Modes settings. [CHAR LIMIT=NONE] -->
     <string name="dark_ui_modes_footer_action">Modes settings</string>
     <!-- Even Dimmer setting title. Allows device to reduce brightness even further than standard range. [CHAR LIMIT=NONE] -->
-    <string name="even_dimmer_display_title">Even dimmer</string>
+    <string name="even_dimmer_display_title">Extra dim</string>
     <!-- Even Dimmer setting summary. [CHAR LIMIT=NONE] -->
     <string name="even_dimmer_display_summary">Allow device to go dimmer than usual</string>
 
@@ -4681,6 +4683,9 @@
     <string name="pointer_stroke_style_name_none">None</string>
     <!-- Title for the button to trigger the 'touch gesture' education. [CHAR LIMIT=35] -->
     <string name="trackpad_touch_gesture">Learn touchpad gestures</string>
+    <!-- TODO(b/353947750): finalize this string and mark it translatable. -->
+    <!-- Notice displayed at the end of the touchpad settings page when the user has disabled system navigation gestures. "Pointer & touchpad accessibility" and "Use touchpad gestures" refer to other labels in Settings, and should be translated in exactly the same way. -->
+    <string name="trackpad_gestures_disabled_footer_text" translatable="false">Some settings are unavailable as touchpad gestures have been turned off. You can turn them on via Pointer &amp; touchpad accessibility > Use touchpad gestures</string>
     <!-- Search keywords for "touchpad" -->
     <string name="keywords_touchpad">trackpad, track pad, mouse, cursor, scroll, swipe, right click, click, pointer</string>
     <!-- Search keywords for 'Bottom-right tap', the name of the touchpad setting that allows the user to click the bottom right corner of the touchpad for more options. -->
@@ -4963,6 +4968,15 @@
     <string name="accessibility_pointer_and_touchpad_summary">Pointer color, pointer size &amp; more</string>
     <!-- Title for the accessibility pointer color customization page. [CHAR LIMIT=50] -->
     <string name="accessibility_pointer_color_customization_title">Pointer color customization</string>
+    <!-- TODO(b/353947750): finalize the four strings below and mark them translatable. -->
+    <!-- Title for the touchpad section of the accessibility pointer and touchpad page. -->
+    <string name="accessibility_touchpad_title" translatable="false">Touchpad</string>
+    <!-- Title for a settings toggle that allows the user to enable or disable system gestures (3- or 4-finger swipes for going home, back, to the overview screen, or between apps) being made on a touchpad. -->
+    <string name="accessibility_touchpad_system_gestures_enable_title" translatable="false">Use system gestures</string>
+    <!-- Description text for a settings toggle that allows the user to enable or disable system gestures (3- or 4-finger swipes for going home, back, to the overview screen, or between apps) being made on a touchpad. -->
+    <string name="accessibility_touchpad_system_gestures_enable_summary" translatable="false">When turned off, 3- or 4-finger gestures are ignored</string>
+    <!-- List of synonyms used in the settings search bar to find the "Use system gestures" touchpad setting, which allows the user to enable or disable system gestures (3- or 4-finger swipes for going home, back, to the overview screen, or between apps) being made on a touchpad. -->
+    <string name="keywords_accessibility_touchpad_system_gestures_enable" translatable="false">touchpad, trackpad, swipe</string>
     <!-- Title for the accessibility color contrast page. [CHAR LIMIT=50] -->
     <string name="accessibility_color_contrast_title">Color contrast</string>
     <!-- Intro for the accessibility color contrast page. [CHAR LIMIT=NONE] -->
@@ -12275,13 +12289,13 @@
     <!-- Search keywords for "_satellite_setting_preference_layout" [CHAR_LIMIT=NONE] -->
     <string name="keywords_satellite_setting">Satellite messaging</string>
     <!-- Category name "About satellite messaging" [CHAR_LIMIT=NONE] -->
-    <string name="category_name_about_satellite_messaging">About satellite messaging</string>
+    <string name="category_name_about_satellite_messaging">About <xliff:g id="subject" example="satellite messaging">%1$s</xliff:g></string>
     <!-- Summary for category "About satellite messaging" [CHAR_LIMIT=NONE] -->
     <string name="title_about_satellite_setting">You can send and receive text messages by satellite as part of an eligible <xliff:g id="carrier_name" example="T-Mobile">%1$s</xliff:g> account</string>
     <!-- Category title "Your mobile plan" [CHAR_LIMIT=NONE] -->
     <string name="category_title_your_satellite_plan">Your <xliff:g id="carrier_name" example="T-Mobile">%1$s</xliff:g> plan</string>
     <!-- Title for category "Your mobile plan when satellite is included in plan" [CHAR_LIMIT=NONE] -->
-    <string name="title_have_satellite_plan">Satellite messaging is included with your account</string>
+    <string name="title_have_satellite_plan">Messaging is included with your account</string>
     <!-- Title for category "Your mobile plan when satellite is not included in plan" [CHAR_LIMIT=NONE] -->
     <string name="title_no_satellite_plan">Satellite messaging isn\u2019t included with your account</string>
     <!-- text view "Learn more" [CHAR_LIMIT=NONE] -->
@@ -12297,15 +12311,24 @@
     <!-- Summary for satellite supported service [CHAR_LIMIT=NONE] -->
     <string name="summary_supported_service">You can text anyone, including emergency services. Your phone will reconnect to a mobile network when available.</string>
     <!-- learn more text - more about satellite messaging [CHAR_LIMIT=NONE] -->
-    <string name="satellite_setting_summary_more_information">Satellite messaging may take longer and is available only in some areas. Weather and certain structures may affect your satellite connection. Calling by satellite isn\u2019t available. Emergency calls may still connect.\n\nIt may take some time for account changes to show in Settings. Contact your carrier for details.</string>
+    <string name="satellite_setting_summary_more_information"><xliff:g id="subject" example="satellite messaging">%1$s</xliff:g> may take longer and is available only in some areas. Weather and certain structures may affect your satellite connection. Calling by satellite isn\u2019t available. Emergency calls may still connect.\n\nIt may take some time for account changes to show in Settings. Contact <xliff:g id="carrier_name" example="T-Mobile">%1$s</xliff:g> for details.</string>
     <!-- more about satellite messaging [CHAR_LIMIT=NONE] -->
-    <string name="more_about_satellite_messaging">More about satellite messaging</string>
+    <string name="more_about_satellite_messaging">More about <xliff:g id="subject" example="satellite messaging">%1$s</xliff:g></string>
     <!-- Title for satellite warning dialog to avoid user using wifi/bluetooth/airplane mode [CHAR_LIMIT=NONE] -->
     <string name="satellite_warning_dialog_title">Can’t turn on <xliff:g id="function" example="bluetooth">%1$s</xliff:g></string>
     <!-- Content for satellite warning dialog to avoid user using wifi/bluetooth/airplane mode [CHAR_LIMIT=NONE] -->
     <string name="satellite_warning_dialog_content">To turn on <xliff:g id="function" example="bluetooth">%1$s</xliff:g>, first end the satellite connection</string>
-    <!-- Category title for satellite functions in mobile network settings [CHAR LIMIT=60] -->
+    <!-- Category title for satellite functions with data transmission in mobile network settings [CHAR LIMIT=60] -->
     <string name="category_title_satellite_connectivity">Satellite connectivity</string>
+    <!-- Title for satellite functions with data transmission in mobile network settings [CHAR LIMIT=60] -->
+    <string name="title_satellite_setting_connectivity">Satellite connectivity</string>
+    <!-- Description of satellite function with data transmission [CHAR LIMIT=60] -->
+    <string name="description_satellite_setting_connectivity">satellite connectivity</string>
+    <!-- Description of satellite function [CHAR LIMIT=60] -->
+    <string name="description_satellite_setting_messaging">satellite messaging</string>
+    <!-- Title for notifying user's account be able to use data transmission of Satellite" [CHAR_LIMIT=NONE] -->
+    <string name="title_have_satellite_data_plan">Use of data is included with your account</string>
+
 
 
     <!-- Title for Apn settings in mobile network settings [CHAR LIMIT=60] -->
@@ -12783,6 +12806,9 @@
     <string name="page_agnostic_notification_channel_name">16KB Page-agnostic Mode</string>
     <string name="page_agnostic_notification_action">Read more</string>
 
+    <string name= "enable_16k_app_compat_title">Run app with page size compat mode</string>
+    <string name= "enable_16k_app_compat_details">App will be run in page size compatibility mode on 16 KB device toggled.</string>
+
     <!-- DSU Loader. Do not translate. -->
 
     <string name="dsu_loader_title" translatable="false">DSU Loader</string>
diff --git a/res/xml/accessibility_pointer_and_touchpad.xml b/res/xml/accessibility_pointer_and_touchpad.xml
index 8da4177..a46c857 100644
--- a/res/xml/accessibility_pointer_and_touchpad.xml
+++ b/res/xml/accessibility_pointer_and_touchpad.xml
@@ -46,4 +46,17 @@
         settings:keywords="@string/keywords_auto_click"
         settings:controller="com.android.settings.accessibility.AutoclickPreferenceController"/>
 
+    <PreferenceCategory
+        android:key="touchpad_category"
+        android:persistent="false"
+        android:title="@string/accessibility_touchpad_title">
+
+        <SwitchPreferenceCompat
+            android:key="touchpad_system_gestures_enable"
+            android:title="@string/accessibility_touchpad_system_gestures_enable_title"
+            android:summary="@string/accessibility_touchpad_system_gestures_enable_summary"
+            settings:keywords="@string/keywords_accessibility_touchpad_system_gestures_enable"/>
+
+    </PreferenceCategory>
+
 </PreferenceScreen>
diff --git a/res/xml/language_settings.xml b/res/xml/language_settings.xml
index fb79346..f9f423e 100644
--- a/res/xml/language_settings.xml
+++ b/res/xml/language_settings.xml
@@ -28,12 +28,13 @@
             android:title="@string/system_language"
             android:fragment="com.android.settings.localepicker.LocaleListEditor"
             settings:controller="com.android.settings.language.PhoneLanguagePreferenceController" />
+
         <Preference
             android:key="apps_language"
             android:title="@string/app_locales_picker_menu_title"
             android:summary="@string/app_locale_picker_summary"
             android:fragment="com.android.settings.applications.manageapplications.ManageApplications"
-            settings:controller="com.android.settings.applications.appinfo.ManageAppLocalePreferenceController">
+            settings:controller="com.android.settings.applications.appinfo.AppsLocalePreferenceController">
             <extra
                 android:name="classname"
                 android:value="com.android.settings.applications.appinfo.AppLocaleDetails" />
@@ -49,6 +50,22 @@
     </PreferenceCategory>
 
     <PreferenceCategory
+        android:key="more_language_settings_category"
+        android:title="@string/more_language_settings_category"
+        settings:controller="com.android.settings.language.MoreLanguagesSettingsCategoryController">
+        <Preference
+            android:key="apps_language_in_more_language_settings"
+            android:title="@string/app_locales_picker_menu_title"
+            android:summary="@string/app_locale_picker_summary"
+            android:fragment="com.android.settings.applications.manageapplications.ManageApplications"
+            settings:controller="com.android.settings.applications.appinfo.NewAppsLocalePreferenceController">
+            <extra
+                android:name="classname"
+                android:value="com.android.settings.applications.appinfo.AppLocaleDetails" />
+        </Preference>
+    </PreferenceCategory>
+
+    <PreferenceCategory
         android:key="regional_preferences_category"
         android:title="@string/regional_preferences_category_title"
         settings:controller="com.android.settings.regionalpreferences.RegionalPreferencesCategoryController">
diff --git a/res/xml/mobile_network_settings.xml b/res/xml/mobile_network_settings.xml
index fb20dce..3c1317d 100644
--- a/res/xml/mobile_network_settings.xml
+++ b/res/xml/mobile_network_settings.xml
@@ -206,7 +206,7 @@
 
         <PreferenceCategory
             android:key="telephony_satellite_settings_category_key"
-            android:title="@string/category_title_satellite_connectivity"
+            android:title="@string/satellite_setting_title"
             settings:controller="com.android.settings.network.telephony.SatelliteSettingsPreferenceCategoryController">
 
             <com.android.settingslib.RestrictedPreference
diff --git a/res/xml/power_usage_summary.xml b/res/xml/power_usage_summary.xml
index 794061a..c7cf873 100644
--- a/res/xml/power_usage_summary.xml
+++ b/res/xml/power_usage_summary.xml
@@ -25,8 +25,15 @@
         android:key="battery_header"
         android:title="@string/summary_placeholder"
         android:selectable="false"
+        android:paddingBottom="0px"
+        android:persistent="false"
         settings:controller="com.android.settings.fuelgauge.BatteryHeaderPreferenceController" />
 
+    <com.android.settings.fuelgauge.BatteryHeaderTextPreference
+        android:key="battery_header_text"
+        android:selectable="false"
+        settings:controller="com.android.settings.fuelgauge.BatteryHeaderTextPreferenceController" />
+
     <com.android.settingslib.widget.LayoutPreference
         android:key="battery_help_message"
         android:layout="@layout/preference_battery_error"
diff --git a/res/xml/satellite_setting.xml b/res/xml/satellite_setting.xml
index 09fbbd6..60fe5bf 100644
--- a/res/xml/satellite_setting.xml
+++ b/res/xml/satellite_setting.xml
@@ -22,7 +22,7 @@
     settings:keywords="@string/keywords_satellite_setting">
 
     <PreferenceCategory
-        android:title="@string/category_name_about_satellite_messaging">
+        android:key="key_category_about_satellite">
 
         <com.android.settingslib.widget.TopIntroPreference
             android:key="key_about_satellite_messaging"/>
@@ -35,6 +35,12 @@
         <Preference
             android:key="key_your_satellite_plan"
             android:icon="?android:attr/textColorPrimary"/>
+
+        <Preference
+            android:key="key_your_satellite_data_plan"
+            android:icon="?android:attr/textColorPrimary"
+            settings:isPreferenceVisible="false"/>
+
     </PreferenceCategory>
 
     <PreferenceCategory
diff --git a/res/xml/touchpad_and_mouse_settings.xml b/res/xml/touchpad_and_mouse_settings.xml
index cdfd398..b82b3a6 100644
--- a/res/xml/touchpad_and_mouse_settings.xml
+++ b/res/xml/touchpad_and_mouse_settings.xml
@@ -96,4 +96,10 @@
         android:key="trackpad_touch_gesture"
         android:title="@string/trackpad_touch_gesture"
         settings:controller="com.android.settings.inputmethod.TouchGesturesButtonPreferenceController"/>
+
+    <com.android.settingslib.widget.FooterPreference
+        android:key="trackpad_gestures_disabled_footer"
+        android:title="@string/trackpad_gestures_disabled_footer_text"
+        settings:searchable="false"
+        settings:controller="com.android.settings.inputmethod.TrackpadGesturesDisabledFooterPreferenceController"/>
 </PreferenceScreen>
diff --git a/src/com/android/settings/EventLogTags.logtags b/src/com/android/settings/EventLogTags.logtags
index 2c8ad35..4e5a742 100644
--- a/src/com/android/settings/EventLogTags.logtags
+++ b/src/com/android/settings/EventLogTags.logtags
@@ -1,4 +1,4 @@
-# See system/core/logcat/event.logtags for a description of the format of this file.
+# See system/logging/logcat/event.logtags for a description of the format of this file.
 
 option java_package com.android.settings
 
diff --git a/src/com/android/settings/Settings.java b/src/com/android/settings/Settings.java
index 09ee97f..cb4358f 100644
--- a/src/com/android/settings/Settings.java
+++ b/src/com/android/settings/Settings.java
@@ -98,6 +98,8 @@
     public static class LanguageSettingsActivity extends SettingsActivity { /* empty */ }
     /** Activity for the regional preferences settings. */
     public static class RegionalPreferencesActivity extends SettingsActivity { /* empty */ }
+    public static class TemperatureUnitSettingsActivity extends SettingsActivity { /* empty */ }
+    public static class FirstDayOfWeekSettingsActivity extends SettingsActivity { /* empty */ }
     public static class KeyboardSettingsActivity extends SettingsActivity { /* empty */ }
     /** Activity for the navigation mode settings. */
     public static class NavigationModeSettingsActivity extends SettingsActivity { /* empty */ }
diff --git a/src/com/android/settings/accessibility/AccessibilitySettings.java b/src/com/android/settings/accessibility/AccessibilitySettings.java
index 34badfc..39ce081 100644
--- a/src/com/android/settings/accessibility/AccessibilitySettings.java
+++ b/src/com/android/settings/accessibility/AccessibilitySettings.java
@@ -43,7 +43,6 @@
 import com.android.settings.R;
 import com.android.settings.accessibility.AccessibilityUtil.AccessibilityServiceFragmentType;
 import com.android.settings.dashboard.DashboardFragment;
-import com.android.settings.development.Enable16kUtils;
 import com.android.settings.overlay.FeatureFactory;
 import com.android.settings.search.BaseSearchIndexProvider;
 import com.android.settingslib.RestrictedPreference;
@@ -96,8 +95,6 @@
     static final String EXTRA_TIME_FOR_LOGGING = "start_time_to_log_a11y_tool";
     static final String EXTRA_METRICS_CATEGORY = "metrics_category";
 
-    public static final String VOICE_ACCESS_SERVICE = "android.apps.accessibility.voiceaccess";
-
     // Timeout before we update the services if packages are added/removed
     // since the AccessibilityManagerService has to do that processing first
     // to generate the AccessibilityServiceInfo we need for proper
@@ -503,11 +500,6 @@
         String[] services = getResources().getStringArray(key);
         PreferenceCategory category = mCategoryToPrefCategoryMap.get(categoryKey);
         for (int i = 0; i < services.length; i++) {
-            // TODO(b/335443194) Voice access is not available in 16kB mode.
-            if (services[i].contains(VOICE_ACCESS_SERVICE)
-                    && Enable16kUtils.isPageAgnosticModeOn(getContext())) {
-                continue;
-            }
             ComponentName component = ComponentName.unflattenFromString(services[i]);
             mPreBundledServiceComponentToCategoryMap.put(component, category);
         }
diff --git a/src/com/android/settings/accessibility/BaseCaptioningCustomController.java b/src/com/android/settings/accessibility/BaseCaptioningCustomController.java
new file mode 100644
index 0000000..68883d5
--- /dev/null
+++ b/src/com/android/settings/accessibility/BaseCaptioningCustomController.java
@@ -0,0 +1,35 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.settings.accessibility;
+
+import android.content.Context;
+
+import com.android.settings.core.BasePreferenceController;
+
+public class BaseCaptioningCustomController extends BasePreferenceController {
+    protected final CaptionHelper mCaptionHelper;
+
+    public BaseCaptioningCustomController(Context context, String preferenceKey) {
+        super(context, preferenceKey);
+        mCaptionHelper = new CaptionHelper(context);
+    }
+
+    @Override
+    public int getAvailabilityStatus() {
+        return mCaptionHelper.getCustomCaptionAvailability();
+    }
+}
diff --git a/src/com/android/settings/accessibility/CaptionHelper.java b/src/com/android/settings/accessibility/CaptionHelper.java
index 36d833c..f23b40c 100644
--- a/src/com/android/settings/accessibility/CaptionHelper.java
+++ b/src/com/android/settings/accessibility/CaptionHelper.java
@@ -18,6 +18,8 @@
 
 import static com.android.settings.accessibility.AccessibilityUtil.State.OFF;
 import static com.android.settings.accessibility.AccessibilityUtil.State.ON;
+import static com.android.settings.core.BasePreferenceController.AVAILABLE;
+import static com.android.settings.core.BasePreferenceController.AVAILABLE_UNSEARCHABLE;
 
 import android.content.ContentResolver;
 import android.content.Context;
@@ -211,4 +213,14 @@
     public Locale getLocale() {
         return mCaptioningManager.getLocale();
     }
+
+    /** Returns availability for custom caption preferences, depending on current user style. */
+    public int getCustomCaptionAvailability() {
+        if (com.android.settings.accessibility.Flags.fixA11ySettingsSearch()) {
+            return (getRawUserStyle() == CaptionStyle.PRESET_CUSTOM)
+                    ? AVAILABLE : AVAILABLE_UNSEARCHABLE;
+        } else {
+            return AVAILABLE;
+        }
+    }
 }
diff --git a/src/com/android/settings/accessibility/CaptioningBackgroundColorController.java b/src/com/android/settings/accessibility/CaptioningBackgroundColorController.java
index 686f725..e695809 100644
--- a/src/com/android/settings/accessibility/CaptioningBackgroundColorController.java
+++ b/src/com/android/settings/accessibility/CaptioningBackgroundColorController.java
@@ -25,23 +25,15 @@
 
 import com.android.settings.R;
 import com.android.settings.accessibility.ListDialogPreference.OnValueChangedListener;
-import com.android.settings.core.BasePreferenceController;
 
 /** Preference controller for captioning background color. */
-public class CaptioningBackgroundColorController extends BasePreferenceController
+public class CaptioningBackgroundColorController extends BaseCaptioningCustomController
         implements OnValueChangedListener {
 
-    private final CaptionHelper mCaptionHelper;
     private int mCachedNonDefaultOpacity = CaptionStyle.COLOR_UNSPECIFIED;
 
     public CaptioningBackgroundColorController(Context context, String preferenceKey) {
         super(context, preferenceKey);
-        mCaptionHelper = new CaptionHelper(context);
-    }
-
-    @Override
-    public int getAvailabilityStatus() {
-        return AVAILABLE;
     }
 
     @Override
diff --git a/src/com/android/settings/accessibility/CaptioningBackgroundOpacityController.java b/src/com/android/settings/accessibility/CaptioningBackgroundOpacityController.java
index 405f6d9..d13e1cb 100644
--- a/src/com/android/settings/accessibility/CaptioningBackgroundOpacityController.java
+++ b/src/com/android/settings/accessibility/CaptioningBackgroundOpacityController.java
@@ -23,22 +23,13 @@
 
 import com.android.settings.R;
 import com.android.settings.accessibility.ListDialogPreference.OnValueChangedListener;
-import com.android.settings.core.BasePreferenceController;
 
 /** Preference controller for captioning background opacity. */
-public class CaptioningBackgroundOpacityController extends BasePreferenceController
+public class CaptioningBackgroundOpacityController extends BaseCaptioningCustomController
         implements OnValueChangedListener {
 
-    private final CaptionHelper mCaptionHelper;
-
     public CaptioningBackgroundOpacityController(Context context, String preferenceKey) {
         super(context, preferenceKey);
-        mCaptionHelper = new CaptionHelper(context);
-    }
-
-    @Override
-    public int getAvailabilityStatus() {
-        return AVAILABLE;
     }
 
     @Override
diff --git a/src/com/android/settings/accessibility/CaptioningCustomController.java b/src/com/android/settings/accessibility/CaptioningCustomController.java
index 1b5b7e1..e30c90a 100644
--- a/src/com/android/settings/accessibility/CaptioningCustomController.java
+++ b/src/com/android/settings/accessibility/CaptioningCustomController.java
@@ -28,7 +28,6 @@
 import androidx.preference.Preference;
 import androidx.preference.PreferenceScreen;
 
-import com.android.settings.core.BasePreferenceController;
 import com.android.settingslib.core.lifecycle.LifecycleObserver;
 import com.android.settingslib.core.lifecycle.events.OnStart;
 import com.android.settingslib.core.lifecycle.events.OnStop;
@@ -37,12 +36,11 @@
 import java.util.List;
 
 /** Preference controller for captioning custom visibility. */
-public class CaptioningCustomController extends BasePreferenceController
+public class CaptioningCustomController extends BaseCaptioningCustomController
         implements LifecycleObserver, OnStart, OnStop {
 
     @Nullable
     private Preference mCustom;
-    private final CaptionHelper mCaptionHelper;
     private final ContentResolver mContentResolver;
     @VisibleForTesting
     AccessibilitySettingsContentObserver mSettingsContentObserver;
@@ -52,16 +50,15 @@
     );
 
     public CaptioningCustomController(Context context, String preferenceKey) {
-        this(context, preferenceKey, new CaptionHelper(context),
+        this(context, preferenceKey,
                 new AccessibilitySettingsContentObserver(new Handler(Looper.getMainLooper())));
     }
 
     @VisibleForTesting
     CaptioningCustomController(
-            Context context, String preferenceKey, CaptionHelper captionHelper,
+            Context context, String preferenceKey,
             AccessibilitySettingsContentObserver contentObserver) {
         super(context, preferenceKey);
-        mCaptionHelper = new CaptionHelper(context);
         mContentResolver = context.getContentResolver();
         mSettingsContentObserver = contentObserver;
         mSettingsContentObserver.registerKeysToObserverCallback(CAPTIONING_FEATURE_KEYS, key -> {
@@ -72,15 +69,6 @@
     }
 
     @Override
-    public int getAvailabilityStatus() {
-        if (com.android.settings.accessibility.Flags.fixA11ySettingsSearch()) {
-            return (shouldShowPreference()) ? AVAILABLE : AVAILABLE_UNSEARCHABLE;
-        } else {
-            return AVAILABLE;
-        }
-    }
-
-    @Override
     public void displayPreference(PreferenceScreen screen) {
         super.displayPreference(screen);
         mCustom = screen.findPreference(getPreferenceKey());
diff --git a/src/com/android/settings/accessibility/CaptioningEdgeColorController.java b/src/com/android/settings/accessibility/CaptioningEdgeColorController.java
index 4903ff4..bb9ce07 100644
--- a/src/com/android/settings/accessibility/CaptioningEdgeColorController.java
+++ b/src/com/android/settings/accessibility/CaptioningEdgeColorController.java
@@ -23,22 +23,13 @@
 
 import com.android.settings.R;
 import com.android.settings.accessibility.ListDialogPreference.OnValueChangedListener;
-import com.android.settings.core.BasePreferenceController;
 
 /** Preference controller for captioning edge color. */
-public class CaptioningEdgeColorController extends BasePreferenceController
+public class CaptioningEdgeColorController extends BaseCaptioningCustomController
         implements OnValueChangedListener {
 
-    private final CaptionHelper mCaptionHelper;
-
     public CaptioningEdgeColorController(Context context, String preferenceKey) {
         super(context, preferenceKey);
-        mCaptionHelper = new CaptionHelper(context);
-    }
-
-    @Override
-    public int getAvailabilityStatus() {
-        return AVAILABLE;
     }
 
     @Override
diff --git a/src/com/android/settings/accessibility/CaptioningEdgeTypeController.java b/src/com/android/settings/accessibility/CaptioningEdgeTypeController.java
index adb66d3..9e2ac20 100644
--- a/src/com/android/settings/accessibility/CaptioningEdgeTypeController.java
+++ b/src/com/android/settings/accessibility/CaptioningEdgeTypeController.java
@@ -21,22 +21,13 @@
 import androidx.preference.PreferenceScreen;
 
 import com.android.settings.accessibility.ListDialogPreference.OnValueChangedListener;
-import com.android.settings.core.BasePreferenceController;
 
 /** Preference controller for captioning edge type. */
-public class CaptioningEdgeTypeController extends BasePreferenceController
+public class CaptioningEdgeTypeController extends BaseCaptioningCustomController
         implements OnValueChangedListener {
 
-    private final CaptionHelper mCaptionHelper;
-
     public CaptioningEdgeTypeController(Context context, String preferenceKey) {
         super(context, preferenceKey);
-        mCaptionHelper = new CaptionHelper(context);
-    }
-
-    @Override
-    public int getAvailabilityStatus() {
-        return AVAILABLE;
     }
 
     @Override
diff --git a/src/com/android/settings/accessibility/CaptioningForegroundColorController.java b/src/com/android/settings/accessibility/CaptioningForegroundColorController.java
index 8e9ec18..4fc9c1b 100644
--- a/src/com/android/settings/accessibility/CaptioningForegroundColorController.java
+++ b/src/com/android/settings/accessibility/CaptioningForegroundColorController.java
@@ -24,23 +24,15 @@
 
 import com.android.settings.R;
 import com.android.settings.accessibility.ListDialogPreference.OnValueChangedListener;
-import com.android.settings.core.BasePreferenceController;
 
 /** Preference controller for captioning foreground color. */
-public class CaptioningForegroundColorController extends BasePreferenceController
+public class CaptioningForegroundColorController extends BaseCaptioningCustomController
         implements OnValueChangedListener {
 
-    private final CaptionHelper mCaptionHelper;
     private int mCachedNonDefaultOpacity = CaptionStyle.COLOR_UNSPECIFIED;
 
     public CaptioningForegroundColorController(Context context, String preferenceKey) {
         super(context, preferenceKey);
-        mCaptionHelper = new CaptionHelper(context);
-    }
-
-    @Override
-    public int getAvailabilityStatus() {
-        return AVAILABLE;
     }
 
     @Override
diff --git a/src/com/android/settings/accessibility/CaptioningForegroundOpacityController.java b/src/com/android/settings/accessibility/CaptioningForegroundOpacityController.java
index ab8a84b..c295399 100644
--- a/src/com/android/settings/accessibility/CaptioningForegroundOpacityController.java
+++ b/src/com/android/settings/accessibility/CaptioningForegroundOpacityController.java
@@ -23,22 +23,13 @@
 
 import com.android.settings.R;
 import com.android.settings.accessibility.ListDialogPreference.OnValueChangedListener;
-import com.android.settings.core.BasePreferenceController;
 
 /** Preference controller for captioning foreground opacity. */
-public class CaptioningForegroundOpacityController extends BasePreferenceController
+public class CaptioningForegroundOpacityController extends BaseCaptioningCustomController
         implements OnValueChangedListener {
 
-    private final CaptionHelper mCaptionHelper;
-
     public CaptioningForegroundOpacityController(Context context, String preferenceKey) {
         super(context, preferenceKey);
-        mCaptionHelper = new CaptionHelper(context);
-    }
-
-    @Override
-    public int getAvailabilityStatus() {
-        return AVAILABLE;
     }
 
     @Override
diff --git a/src/com/android/settings/accessibility/CaptioningTypefaceController.java b/src/com/android/settings/accessibility/CaptioningTypefaceController.java
index d8222fa..8eb6cd1 100644
--- a/src/com/android/settings/accessibility/CaptioningTypefaceController.java
+++ b/src/com/android/settings/accessibility/CaptioningTypefaceController.java
@@ -23,22 +23,12 @@
 import androidx.preference.ListPreference;
 import androidx.preference.Preference;
 
-import com.android.settings.core.BasePreferenceController;
-
 /** Preference controller for captioning type face. */
-public class CaptioningTypefaceController extends BasePreferenceController
+public class CaptioningTypefaceController extends BaseCaptioningCustomController
         implements Preference.OnPreferenceChangeListener {
 
-    private final CaptionHelper mCaptionHelper;
-
     public CaptioningTypefaceController(Context context, String preferenceKey) {
         super(context, preferenceKey);
-        mCaptionHelper = new CaptionHelper(context);
-    }
-
-    @Override
-    public int getAvailabilityStatus() {
-        return AVAILABLE;
     }
 
     @Override
diff --git a/src/com/android/settings/accessibility/CaptioningWindowColorController.java b/src/com/android/settings/accessibility/CaptioningWindowColorController.java
index b72b973..ff67420 100644
--- a/src/com/android/settings/accessibility/CaptioningWindowColorController.java
+++ b/src/com/android/settings/accessibility/CaptioningWindowColorController.java
@@ -19,43 +19,21 @@
 import android.content.Context;
 import android.content.res.Resources;
 import android.graphics.Color;
-import android.view.accessibility.CaptioningManager;
 import android.view.accessibility.CaptioningManager.CaptionStyle;
 
 import androidx.preference.PreferenceScreen;
 
-import com.android.internal.annotations.VisibleForTesting;
 import com.android.settings.R;
 import com.android.settings.accessibility.ListDialogPreference.OnValueChangedListener;
-import com.android.settings.core.BasePreferenceController;
 
 /** Preference controller for captioning window color. */
-public class CaptioningWindowColorController extends BasePreferenceController
+public class CaptioningWindowColorController extends BaseCaptioningCustomController
         implements OnValueChangedListener {
 
-    private final CaptionHelper mCaptionHelper;
     private int mCachedNonDefaultOpacity = CaptionStyle.COLOR_UNSPECIFIED;
 
-    @VisibleForTesting
-    CaptioningWindowColorController(Context context, String preferenceKey,
-            CaptionHelper captionHelper) {
-        super(context, preferenceKey);
-        mCaptionHelper = captionHelper;
-    }
-
     public CaptioningWindowColorController(Context context, String preferenceKey) {
-        this(context, preferenceKey, new CaptionHelper(context));
-    }
-
-    @Override
-    public int getAvailabilityStatus() {
-        if (com.android.settings.accessibility.Flags.fixA11ySettingsSearch()) {
-            return (mCaptionHelper.getRawUserStyle()
-                    == CaptioningManager.CaptionStyle.PRESET_CUSTOM)
-                    ? AVAILABLE : AVAILABLE_UNSEARCHABLE;
-        } else {
-            return AVAILABLE;
-        }
+        super(context, preferenceKey);
     }
 
     @Override
diff --git a/src/com/android/settings/accessibility/CaptioningWindowOpacityController.java b/src/com/android/settings/accessibility/CaptioningWindowOpacityController.java
index 0e6c6ff..5ad29db 100644
--- a/src/com/android/settings/accessibility/CaptioningWindowOpacityController.java
+++ b/src/com/android/settings/accessibility/CaptioningWindowOpacityController.java
@@ -18,41 +18,18 @@
 
 import android.content.Context;
 import android.content.res.Resources;
-import android.view.accessibility.CaptioningManager;
 
 import androidx.preference.PreferenceScreen;
 
-import com.android.internal.annotations.VisibleForTesting;
 import com.android.settings.R;
 import com.android.settings.accessibility.ListDialogPreference.OnValueChangedListener;
-import com.android.settings.core.BasePreferenceController;
 
 /** Preference controller for captioning window opacity. */
-public class CaptioningWindowOpacityController extends BasePreferenceController
+public class CaptioningWindowOpacityController extends BaseCaptioningCustomController
         implements OnValueChangedListener {
 
-    private final CaptionHelper mCaptionHelper;
-
-    @VisibleForTesting
-    CaptioningWindowOpacityController(Context context, String preferenceKey,
-            CaptionHelper captionHelper) {
-        super(context, preferenceKey);
-        mCaptionHelper = captionHelper;
-    }
-
     public CaptioningWindowOpacityController(Context context, String preferenceKey) {
-        this(context, preferenceKey, new CaptionHelper(context));
-    }
-
-    @Override
-    public int getAvailabilityStatus() {
-        if (com.android.settings.accessibility.Flags.fixA11ySettingsSearch()) {
-            return (mCaptionHelper.getRawUserStyle()
-                    == CaptioningManager.CaptionStyle.PRESET_CUSTOM)
-                    ? AVAILABLE : AVAILABLE_UNSEARCHABLE;
-        } else {
-            return AVAILABLE;
-        }
+        super(context, preferenceKey);
     }
 
     @Override
diff --git a/src/com/android/settings/accessibility/RestrictedPreferenceHelper.java b/src/com/android/settings/accessibility/RestrictedPreferenceHelper.java
index 82aa098..d97895a 100644
--- a/src/com/android/settings/accessibility/RestrictedPreferenceHelper.java
+++ b/src/com/android/settings/accessibility/RestrictedPreferenceHelper.java
@@ -16,8 +16,6 @@
 
 package com.android.settings.accessibility;
 
-import static com.android.settings.accessibility.AccessibilitySettings.VOICE_ACCESS_SERVICE;
-
 import android.accessibilityservice.AccessibilityServiceInfo;
 import android.accessibilityservice.AccessibilityShortcutInfo;
 import android.app.AppOpsManager;
@@ -31,7 +29,6 @@
 import android.text.TextUtils;
 
 import com.android.settings.R;
-import com.android.settings.development.Enable16kUtils;
 import com.android.settingslib.RestrictedLockUtils;
 import com.android.settingslib.RestrictedLockUtilsInternal;
 import com.android.settingslib.RestrictedPreference;
@@ -81,12 +78,6 @@
             final AccessibilityServiceInfo info = installedServices.get(i);
             final ResolveInfo resolveInfo = info.getResolveInfo();
             final String packageName = resolveInfo.serviceInfo.packageName;
-            // TODO(b/335443194) Voice access is not available in 16kB mode.
-            if (packageName.contains(VOICE_ACCESS_SERVICE)
-                    && Enable16kUtils.isPageAgnosticModeOn(mContext)) {
-                continue;
-            }
-
             final ComponentName componentName = new ComponentName(packageName,
                     resolveInfo.serviceInfo.name);
             final boolean serviceEnabled = enabledServices.contains(componentName);
diff --git a/src/com/android/settings/applications/appinfo/AppsLocalePreferenceController.java b/src/com/android/settings/applications/appinfo/AppsLocalePreferenceController.java
new file mode 100644
index 0000000..c66ea58
--- /dev/null
+++ b/src/com/android/settings/applications/appinfo/AppsLocalePreferenceController.java
@@ -0,0 +1,42 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.settings.applications.appinfo;
+
+import android.content.Context;
+
+import androidx.annotation.NonNull;
+
+import com.android.settings.core.BasePreferenceController;
+import com.android.settings.flags.Flags;
+
+/**
+ * A controller to update current locale information of application
+ * and a entry to launch {@link ManageApplications}.
+ */
+public class AppsLocalePreferenceController extends BasePreferenceController {
+    public AppsLocalePreferenceController(@NonNull Context context, @NonNull String key) {
+        super(context, key);
+    }
+
+    @Override
+    public int getAvailabilityStatus() {
+        if (!Flags.regionalPreferencesApiEnabled()) {
+            return AVAILABLE;
+        }
+        return CONDITIONALLY_UNAVAILABLE;
+    }
+}
diff --git a/src/com/android/settings/applications/appinfo/ExternalSourcesDetails.java b/src/com/android/settings/applications/appinfo/ExternalSourcesDetails.java
index 9a41f25..826583d 100644
--- a/src/com/android/settings/applications/appinfo/ExternalSourcesDetails.java
+++ b/src/com/android/settings/applications/appinfo/ExternalSourcesDetails.java
@@ -17,6 +17,8 @@
 
 import static android.app.Activity.RESULT_CANCELED;
 import static android.app.Activity.RESULT_OK;
+import static android.os.UserManager.DISALLOW_INSTALL_UNKNOWN_SOURCES;
+import static android.os.UserManager.DISALLOW_INSTALL_UNKNOWN_SOURCES_GLOBALLY;
 
 import android.app.AppOpsManager;
 import android.app.settings.SettingsEnums;
@@ -34,6 +36,7 @@
 import com.android.settings.applications.AppInfoWithHeader;
 import com.android.settings.applications.AppStateInstallAppsBridge;
 import com.android.settings.applications.AppStateInstallAppsBridge.InstallAppsState;
+import com.android.settingslib.RestrictedLockUtilsInternal;
 import com.android.settingslib.RestrictedSwitchPreference;
 import com.android.settingslib.applications.ApplicationsState.AppEntry;
 
@@ -82,15 +85,34 @@
     public static CharSequence getPreferenceSummary(Context context, AppEntry entry) {
         final UserHandle userHandle = UserHandle.getUserHandleForUid(entry.info.uid);
         final UserManager um = UserManager.get(context);
-        final int userRestrictionSource = um.getUserRestrictionSource(
-                UserManager.DISALLOW_INSTALL_UNKNOWN_SOURCES, userHandle)
-                | um.getUserRestrictionSource(
-                        UserManager.DISALLOW_INSTALL_UNKNOWN_SOURCES_GLOBALLY,
-                        userHandle);
-        if ((userRestrictionSource & UserManager.RESTRICTION_SOURCE_SYSTEM) != 0) {
-            return context.getString(com.android.settingslib.widget.restricted.R.string.disabled_by_admin);
-        } else if (userRestrictionSource != 0) {
-            return context.getString(com.android.settingslib.R.string.disabled);
+        if (android.security.Flags.aapmFeatureDisableInstallUnknownSources()) {
+            if (um.hasBaseUserRestriction(DISALLOW_INSTALL_UNKNOWN_SOURCES, userHandle)) {
+                return context.getString(com.android.settingslib.R.string.disabled);
+            } else if (um.hasUserRestrictionForUser(DISALLOW_INSTALL_UNKNOWN_SOURCES, userHandle)) {
+                return context.getString(
+                        com.android.settingslib.widget.restricted.R.string.disabled_by_admin);
+            } else if (um.hasUserRestrictionForUser(DISALLOW_INSTALL_UNKNOWN_SOURCES_GLOBALLY,
+                    userHandle)) {
+                if (RestrictedLockUtilsInternal.isPolicyEnforcedByAdvancedProtection(context,
+                        DISALLOW_INSTALL_UNKNOWN_SOURCES_GLOBALLY, userHandle.getIdentifier())) {
+                    return context.getString(com.android.settingslib.widget.restricted
+                            .R.string.disabled_by_advanced_protection);
+                } else {
+                    return context.getString(
+                            com.android.settingslib.widget.restricted.R.string.disabled_by_admin);
+                }
+            }
+        } else {
+            final int userRestrictionSource = um.getUserRestrictionSource(
+                    DISALLOW_INSTALL_UNKNOWN_SOURCES, userHandle)
+                    | um.getUserRestrictionSource(
+                            UserManager.DISALLOW_INSTALL_UNKNOWN_SOURCES_GLOBALLY, userHandle);
+            if ((userRestrictionSource & UserManager.RESTRICTION_SOURCE_SYSTEM) != 0) {
+                return context.getString(
+                        com.android.settingslib.widget.restricted.R.string.disabled_by_admin);
+            } else if (userRestrictionSource != 0) {
+                return context.getString(com.android.settingslib.R.string.disabled);
+            }
         }
         final InstallAppsState appsState = new AppStateInstallAppsBridge(context, null, null)
                 .createInstallAppsStateFor(entry.info.packageName, entry.info.uid);
@@ -110,14 +132,14 @@
         if (mPackageInfo == null || mPackageInfo.applicationInfo == null) {
             return false;
         }
-        if (mUserManager.hasBaseUserRestriction(UserManager.DISALLOW_INSTALL_UNKNOWN_SOURCES,
+        if (mUserManager.hasBaseUserRestriction(DISALLOW_INSTALL_UNKNOWN_SOURCES,
                 UserHandle.of(UserHandle.myUserId()))) {
             mSwitchPref.setChecked(false);
             mSwitchPref.setSummary(com.android.settingslib.R.string.disabled);
             mSwitchPref.setEnabled(false);
             return true;
         }
-        mSwitchPref.checkRestrictionAndSetDisabled(UserManager.DISALLOW_INSTALL_UNKNOWN_SOURCES);
+        mSwitchPref.checkRestrictionAndSetDisabled(DISALLOW_INSTALL_UNKNOWN_SOURCES);
         if (!mSwitchPref.isDisabledByAdmin()) {
             mSwitchPref.checkRestrictionAndSetDisabled(
                     UserManager.DISALLOW_INSTALL_UNKNOWN_SOURCES_GLOBALLY);
diff --git a/src/com/android/settings/applications/appinfo/NewAppsLocalePreferenceController.java b/src/com/android/settings/applications/appinfo/NewAppsLocalePreferenceController.java
new file mode 100644
index 0000000..abd7af8
--- /dev/null
+++ b/src/com/android/settings/applications/appinfo/NewAppsLocalePreferenceController.java
@@ -0,0 +1,44 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.settings.applications.appinfo;
+
+import android.content.Context;
+
+import androidx.annotation.NonNull;
+
+import com.android.settings.core.BasePreferenceController;
+import com.android.settings.flags.Flags;
+
+/**
+ * A controller to update current locale information of application
+ * and a entry to launch {@link ManageApplications}.
+ */
+public class NewAppsLocalePreferenceController extends BasePreferenceController {
+
+    public NewAppsLocalePreferenceController(@NonNull Context context, @NonNull String key) {
+        super(context, key);
+    }
+
+    @Override
+    public int getAvailabilityStatus() {
+        // TODO(b/381011808) After feature release, this class may be renamed.
+        if (Flags.regionalPreferencesApiEnabled()) {
+            return AVAILABLE;
+        }
+        return CONDITIONALLY_UNAVAILABLE;
+    }
+}
diff --git a/src/com/android/settings/bluetooth/BluetoothDetailsProfilesController.java b/src/com/android/settings/bluetooth/BluetoothDetailsProfilesController.java
index d75e7da..924ba2c 100644
--- a/src/com/android/settings/bluetooth/BluetoothDetailsProfilesController.java
+++ b/src/com/android/settings/bluetooth/BluetoothDetailsProfilesController.java
@@ -18,6 +18,7 @@
 
 import static android.bluetooth.BluetoothDevice.METADATA_MODEL_NAME;
 
+import android.app.settings.SettingsEnums;
 import android.bluetooth.BluetoothDevice;
 import android.bluetooth.BluetoothProfile;
 import android.content.Context;
@@ -83,6 +84,8 @@
     private static final boolean LE_AUDIO_TOGGLE_VISIBLE_DEFAULT_VALUE = true;
     private static final String LE_AUDIO_TOGGLE_VISIBLE_PROPERTY =
             "persist.bluetooth.leaudio.toggle_visible";
+    private static final String BYPASS_LE_AUDIO_ALLOWLIST_PROPERTY =
+            "persist.bluetooth.leaudio.bypass_allow_list";
 
     private Set<String> mInvisibleProfiles = Collections.emptySet();
     private final AtomicReference<Set<String>> mAdditionalInvisibleProfiles =
@@ -378,6 +381,16 @@
         return result;
     }
 
+    private boolean isCurrentDeviceInOrByPassAllowList() {
+        if (!SystemProperties.getBoolean(LE_AUDIO_CONNECTION_BY_DEFAULT_PROPERTY, true)) {
+            return false;
+        }
+        return SystemProperties.getBoolean(BYPASS_LE_AUDIO_ALLOWLIST_PROPERTY, false)
+                || isModelNameInAllowList(
+                BluetoothUtils.getStringMetaData(
+                        mCachedDevice.getDevice(), METADATA_MODEL_NAME));
+    }
+
     /**
      * Disable the Le Audio profile for each of the Le Audio devices.
      *
@@ -389,6 +402,11 @@
             return;
         }
 
+        mMetricsFeatureProvider.action(
+                mContext,
+                SettingsEnums.ACTION_BLUETOOTH_PROFILE_LE_AUDIO_OFF,
+                isCurrentDeviceInOrByPassAllowList());
+
         LocalBluetoothProfile asha = mProfileManager.getHearingAidProfile();
         LocalBluetoothProfile broadcastAssistant =
                 mProfileManager.getLeAudioBroadcastAssistantProfile();
@@ -427,6 +445,11 @@
             return;
         }
 
+        mMetricsFeatureProvider.action(
+                mContext,
+                SettingsEnums.ACTION_BLUETOOTH_PROFILE_LE_AUDIO_ON,
+                isCurrentDeviceInOrByPassAllowList());
+
         if (!SystemProperties.getBoolean(ENABLE_DUAL_MODE_AUDIO, false)) {
             Log.i(TAG, "Disabling classic audio profiles because dual mode is disabled");
             disableProfileBeforeUserEnablesLeAudio(mProfileManager.getA2dpProfile());
diff --git a/src/com/android/settings/connecteddevice/audiosharing/AudioSharingSwitchBarController.java b/src/com/android/settings/connecteddevice/audiosharing/AudioSharingSwitchBarController.java
index 0a9bc97..7ca3256 100644
--- a/src/com/android/settings/connecteddevice/audiosharing/AudioSharingSwitchBarController.java
+++ b/src/com/android/settings/connecteddevice/audiosharing/AudioSharingSwitchBarController.java
@@ -187,7 +187,6 @@
                                 TAG,
                                 "Skip handleOnBroadcastReady: null assistant or "
                                         + "sink has active local source.");
-                        cleanUpStatesForStartSharing();
                         return;
                     }
                     handleOnBroadcastReady();
diff --git a/src/com/android/settings/core/gateway/SettingsGateway.java b/src/com/android/settings/core/gateway/SettingsGateway.java
index 1a2e8eb..8541c7a 100644
--- a/src/com/android/settings/core/gateway/SettingsGateway.java
+++ b/src/com/android/settings/core/gateway/SettingsGateway.java
@@ -182,7 +182,9 @@
 import com.android.settings.privatespace.delete.PrivateSpaceDeleteFragment;
 import com.android.settings.privatespace.delete.PrivateSpaceDeletionProgressFragment;
 import com.android.settings.privatespace.onelock.PrivateSpaceBiometricSettings;
+import com.android.settings.regionalpreferences.FirstDayOfWeekItemFragment;
 import com.android.settings.regionalpreferences.RegionalPreferencesEntriesFragment;
+import com.android.settings.regionalpreferences.TemperatureUnitFragment;
 import com.android.settings.safetycenter.MoreSecurityPrivacyFragment;
 import com.android.settings.security.LockscreenDashboardFragment;
 import com.android.settings.security.MemtagPage;
@@ -395,6 +397,8 @@
             ColorContrastFragment.class.getName(),
             LongBackgroundTasksDetails.class.getName(),
             RegionalPreferencesEntriesFragment.class.getName(),
+            TemperatureUnitFragment.class.getName(),
+            FirstDayOfWeekItemFragment.class.getName(),
             BatteryInfoFragment.class.getName(),
             UserAspectRatioDetails.class.getName(),
             ScreenTimeoutSettings.class.getName(),
diff --git a/src/com/android/settings/enterprise/ActionDisabledByAdminDialog.java b/src/com/android/settings/enterprise/ActionDisabledByAdminDialog.java
index c4bef25..e05ae71 100644
--- a/src/com/android/settings/enterprise/ActionDisabledByAdminDialog.java
+++ b/src/com/android/settings/enterprise/ActionDisabledByAdminDialog.java
@@ -16,12 +16,18 @@
 
 package com.android.settings.enterprise;
 
+import static android.security.advancedprotection.AdvancedProtectionManager.ADVANCED_PROTECTION_SYSTEM_ENTITY;
+
 import android.app.Activity;
 import android.app.admin.DevicePolicyManager;
+import android.app.admin.EnforcingAdmin;
+import android.app.admin.UnknownAuthority;
+import android.content.ComponentName;
 import android.content.DialogInterface;
 import android.content.Intent;
 import android.os.Bundle;
 import android.os.UserHandle;
+import android.security.advancedprotection.AdvancedProtectionManager;
 
 import com.android.settingslib.RestrictedLockUtils;
 import com.android.settingslib.RestrictedLockUtils.EnforcedAdmin;
@@ -53,37 +59,67 @@
 
     @androidx.annotation.VisibleForTesting
     EnforcedAdmin getAdminDetailsFromIntent(Intent intent) {
-        final EnforcedAdmin admin = new EnforcedAdmin(null, UserHandle.of(UserHandle.myUserId()));
+        final EnforcedAdmin enforcedAdmin = new EnforcedAdmin(null, UserHandle.of(
+                UserHandle.myUserId()));
         if (intent == null) {
-            return admin;
+            return enforcedAdmin;
         }
-        admin.component = intent.getParcelableExtra(DevicePolicyManager.EXTRA_DEVICE_ADMIN);
+        enforcedAdmin.component = intent.getParcelableExtra(DevicePolicyManager.EXTRA_DEVICE_ADMIN,
+                ComponentName.class);
         int userId = intent.getIntExtra(Intent.EXTRA_USER_ID, UserHandle.myUserId());
 
         Bundle adminDetails = null;
-        if (admin.component == null) {
-            DevicePolicyManager devicePolicyManager = getSystemService(DevicePolicyManager.class);
-            adminDetails = devicePolicyManager.getEnforcingAdminAndUserDetails(userId,
-                    getRestrictionFromIntent(intent));
-            if (adminDetails != null) {
-                admin.component = adminDetails.getParcelable(
-                        DevicePolicyManager.EXTRA_DEVICE_ADMIN);
+        if (enforcedAdmin.component == null) {
+            DevicePolicyManager dpm = getSystemService(DevicePolicyManager.class);
+            final String restriction = getRestrictionFromIntent(intent);
+            if (android.security.Flags.aapmApi() && dpm != null && restriction != null) {
+                // TODO(b/381025131): Move advanced protection logic to DevicePolicyManager or
+                //  elsewhere.
+                launchAdvancedProtectionDialogOrTryToSetAdminComponent(dpm, userId, restriction,
+                        enforcedAdmin);
+            } else {
+                adminDetails = dpm.getEnforcingAdminAndUserDetails(userId, restriction);
+                if (adminDetails != null) {
+                    enforcedAdmin.component = adminDetails.getParcelable(
+                            DevicePolicyManager.EXTRA_DEVICE_ADMIN, ComponentName.class);
+                }
             }
         }
 
         if (intent.hasExtra(Intent.EXTRA_USER)) {
-            admin.user = intent.getParcelableExtra(Intent.EXTRA_USER);
+            enforcedAdmin.user = intent.getParcelableExtra(Intent.EXTRA_USER, UserHandle.class);
         } else {
             if (adminDetails != null) {
                 userId = adminDetails.getInt(Intent.EXTRA_USER_ID, UserHandle.myUserId());
             }
             if (userId == UserHandle.USER_NULL) {
-                admin.user = null;
+                enforcedAdmin.user = null;
             } else {
-                admin.user = UserHandle.of(userId);
+                enforcedAdmin.user = UserHandle.of(userId);
             }
         }
-        return admin;
+        return enforcedAdmin;
+    }
+
+    private void launchAdvancedProtectionDialogOrTryToSetAdminComponent(DevicePolicyManager dpm,
+            int userId, String restriction, EnforcedAdmin enforcedAdmin) {
+        EnforcingAdmin enforcingAdmin = dpm.getEnforcingAdmin(userId, restriction);
+        if (enforcingAdmin == null) {
+            return;
+        }
+        if (enforcingAdmin.getAuthority() instanceof UnknownAuthority authority
+                && ADVANCED_PROTECTION_SYSTEM_ENTITY.equals(authority.getName())) {
+            AdvancedProtectionManager apm = getSystemService(AdvancedProtectionManager.class);
+            if (apm == null) {
+                return;
+            }
+            Intent apmSupportIntent = apm.createSupportIntentForPolicyIdentifierOrRestriction(
+                    restriction, /* type */ null);
+            startActivityAsUser(apmSupportIntent, UserHandle.of(userId));
+            finish();
+        } else {
+            enforcedAdmin.component = enforcingAdmin.getComponentName();
+        }
     }
 
     @androidx.annotation.VisibleForTesting
diff --git a/src/com/android/settings/fuelgauge/BatteryHeaderPreference.kt b/src/com/android/settings/fuelgauge/BatteryHeaderPreference.kt
new file mode 100644
index 0000000..2a9b0e8
--- /dev/null
+++ b/src/com/android/settings/fuelgauge/BatteryHeaderPreference.kt
@@ -0,0 +1,95 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.settings.fuelgauge
+
+import android.content.Context
+import androidx.annotation.VisibleForTesting
+import androidx.preference.Preference
+import com.android.settings.R
+import com.android.settings.fuelgauge.BatteryBroadcastReceiver.BatteryUpdateType.BATTERY_NOT_PRESENT
+import com.android.settingslib.Utils
+import com.android.settingslib.fuelgauge.BatteryUtils
+import com.android.settingslib.metadata.PreferenceLifecycleContext
+import com.android.settingslib.metadata.PreferenceLifecycleProvider
+import com.android.settingslib.metadata.PreferenceMetadata
+import com.android.settingslib.preference.PreferenceBinding
+import com.android.settingslib.widget.UsageProgressBarPreference
+
+// LINT.IfChange
+class BatteryHeaderPreference :
+    PreferenceMetadata,
+    PreferenceBinding,
+    PreferenceLifecycleProvider {
+
+    @VisibleForTesting
+    var batteryBroadcastReceiver: BatteryBroadcastReceiver? = null
+
+    override val key: String
+        get() = KEY
+
+    override val title: Int
+        get() = R.string.summary_placeholder
+
+    override fun createWidget(context: Context) = UsageProgressBarPreference(context)
+
+    override fun bind(preference: Preference, metadata: PreferenceMetadata) {
+        super.bind(preference, metadata)
+        preference.isSelectable = false
+        if (preference is UsageProgressBarPreference) {
+            quickUpdateHeaderPreference(preference)
+        }
+    }
+
+    override fun isIndexable(context: Context) = false
+
+    override fun onCreate(context: PreferenceLifecycleContext) {
+        super.onCreate(context)
+        batteryBroadcastReceiver = BatteryBroadcastReceiver(context).apply {
+            setBatteryChangedListener {
+                if (it != BATTERY_NOT_PRESENT) {
+                    context.notifyPreferenceChange(KEY)
+                }
+            }
+        }
+    }
+
+    override fun onStart(context: PreferenceLifecycleContext) {
+        super.onStart(context)
+        batteryBroadcastReceiver?.register();
+    }
+
+    override fun onStop(context: PreferenceLifecycleContext) {
+        super.onStop(context)
+        batteryBroadcastReceiver?.unRegister();
+    }
+
+    companion object {
+        private const val KEY = "battery_header"
+        private const val BATTERY_MAX_LEVEL: Long = 100L
+
+        private fun quickUpdateHeaderPreference(preference: UsageProgressBarPreference) {
+            val batteryIntent = BatteryUtils.getBatteryIntent(preference.context) ?: return
+            val batteryLevel: Int = Utils.getBatteryLevel(batteryIntent)
+            preference.apply {
+                setUsageSummary(com.android.settings.Utils.formatPercentage(batteryLevel))
+                setPercent(batteryLevel.toLong(), BATTERY_MAX_LEVEL)
+                setBottomSummary("")
+            }
+        }
+    }
+}
+// LINT.ThenChange(BatteryHeaderPreferenceController.java)
diff --git a/src/com/android/settings/fuelgauge/BatteryHeaderPreferenceController.java b/src/com/android/settings/fuelgauge/BatteryHeaderPreferenceController.java
index 891a997..adcd7d1 100644
--- a/src/com/android/settings/fuelgauge/BatteryHeaderPreferenceController.java
+++ b/src/com/android/settings/fuelgauge/BatteryHeaderPreferenceController.java
@@ -1,5 +1,6 @@
 /*
- * Copyright (C) 2017 The Android Open Source Project
+ * Copyright (C) 2024 The Android Open Source Project
+ *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
  * You may obtain a copy of the License at
@@ -15,59 +16,77 @@
 
 package com.android.settings.fuelgauge;
 
+import static com.android.settings.fuelgauge.BatteryBroadcastReceiver.BatteryUpdateType.BATTERY_NOT_PRESENT;
+
 import android.content.Context;
 import android.content.Intent;
-import android.os.BatteryManager;
-import android.os.PowerManager;
-import android.util.Log;
 
+import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
 import androidx.annotation.VisibleForTesting;
+import androidx.lifecycle.Lifecycle;
+import androidx.lifecycle.LifecycleEventObserver;
+import androidx.lifecycle.LifecycleOwner;
 import androidx.preference.PreferenceScreen;
 
-import com.android.settings.R;
 import com.android.settings.core.BasePreferenceController;
 import com.android.settings.core.PreferenceControllerMixin;
-import com.android.settings.fuelgauge.batterytip.tips.BatteryTip;
-import com.android.settings.overlay.FeatureFactory;
 import com.android.settingslib.Utils;
 import com.android.settingslib.widget.UsageProgressBarPreference;
 
+// LINT.IfChange
 /** Controller that update the battery header view */
 public class BatteryHeaderPreferenceController extends BasePreferenceController
-        implements PreferenceControllerMixin, BatteryPreferenceController {
+        implements PreferenceControllerMixin, LifecycleEventObserver {
     private static final String TAG = "BatteryHeaderPreferenceController";
-
-    @VisibleForTesting static final String KEY_BATTERY_HEADER = "battery_header";
     private static final int BATTERY_MAX_LEVEL = 100;
 
-    @VisibleForTesting BatteryStatusFeatureProvider mBatteryStatusFeatureProvider;
-    @VisibleForTesting UsageProgressBarPreference mBatteryUsageProgressBarPref;
-
-    private final PowerManager mPowerManager;
-    private final BatterySettingsFeatureProvider mBatterySettingsFeatureProvider;
-
-    private BatteryTip mBatteryTip;
+    @Nullable @VisibleForTesting BatteryBroadcastReceiver mBatteryBroadcastReceiver;
+    @Nullable @VisibleForTesting UsageProgressBarPreference mBatteryUsageProgressBarPreference;
 
     public BatteryHeaderPreferenceController(Context context, String key) {
         super(context, key);
-        mPowerManager = context.getSystemService(PowerManager.class);
-        mBatteryStatusFeatureProvider =
-                FeatureFactory.getFeatureFactory().getBatteryStatusFeatureProvider();
-        mBatterySettingsFeatureProvider =
-                FeatureFactory.getFeatureFactory().getBatterySettingsFeatureProvider();
+    }
+
+    @Override
+    public void onStateChanged(@NonNull LifecycleOwner lifecycleOwner,
+            @NonNull Lifecycle.Event event) {
+        switch (event) {
+            case ON_CREATE:
+                mBatteryBroadcastReceiver = new BatteryBroadcastReceiver(mContext);
+                mBatteryBroadcastReceiver.setBatteryChangedListener(
+                        type -> {
+                            if (type != BATTERY_NOT_PRESENT) {
+                                quickUpdateHeaderPreference();
+                            }
+                        });
+                break;
+            case ON_START:
+                if (mBatteryBroadcastReceiver != null) {
+                    mBatteryBroadcastReceiver.register();
+                }
+                break;
+            case ON_STOP:
+                if (mBatteryBroadcastReceiver != null) {
+                    mBatteryBroadcastReceiver.unRegister();
+                }
+                break;
+            default:
+                break;
+        }
     }
 
     @Override
     public void displayPreference(PreferenceScreen screen) {
         super.displayPreference(screen);
-        mBatteryUsageProgressBarPref = screen.findPreference(getPreferenceKey());
-        // Set up empty space text first to prevent layout flaky before info loaded.
-        mBatteryUsageProgressBarPref.setBottomSummary(" ");
+        mBatteryUsageProgressBarPreference = screen.findPreference(getPreferenceKey());
+        // Hide the bottom summary from the progress bar.
+        mBatteryUsageProgressBarPreference.setBottomSummary("");
 
         if (com.android.settings.Utils.isBatteryPresent(mContext)) {
             quickUpdateHeaderPreference();
         } else {
-            mBatteryUsageProgressBarPref.setVisible(false);
+            mBatteryUsageProgressBarPreference.setVisible(false);
         }
     }
 
@@ -76,105 +95,23 @@
         return AVAILABLE_UNSEARCHABLE;
     }
 
-    private CharSequence generateLabel(BatteryInfo info) {
-        if (Utils.containsIncompatibleChargers(mContext, TAG)) {
-            return mContext.getString(
-                    com.android.settingslib.R.string.battery_info_status_not_charging);
-        }
-        if (BatteryUtils.isBatteryDefenderOn(info)
-                || FeatureFactory.getFeatureFactory()
-                .getPowerUsageFeatureProvider()
-                .isExtraDefend()) {
-            return mContext.getString(
-                    com.android.settingslib.R.string.battery_info_status_charging_on_hold);
-        }
-        if (info.remainingLabel != null
-                && mBatterySettingsFeatureProvider.isChargingOptimizationMode(mContext)) {
-            return info.remainingLabel;
-        }
-        if (info.batteryStatus == BatteryManager.BATTERY_STATUS_NOT_CHARGING) {
-            return info.statusLabel;
-        }
-        if (info.pluggedStatus == BatteryManager.BATTERY_PLUGGED_WIRELESS) {
-            final CharSequence wirelessChargingLabel =
-                    mBatterySettingsFeatureProvider.getWirelessChargingLabel(mContext, info);
-            if (wirelessChargingLabel != null) {
-                mBatteryUsageProgressBarPref.setBottomSummaryContentDescription(
-                        mBatterySettingsFeatureProvider
-                                .getWirelessChargingContentDescription(mContext, info));
-                return wirelessChargingLabel;
-            }
-        }
-        if (info.remainingLabel == null) {
-            return info.statusLabel;
-        }
-        if (info.statusLabel != null && !info.discharging) {
-            // Charging state
-            if (com.android.settingslib.fuelgauge.BatteryUtils.isChargingStringV2Enabled()) {
-                return info.isFastCharging
-                        ? mContext.getString(
-                                R.string.battery_state_and_duration,
-                                info.statusLabel,
-                                info.remainingLabel)
-                        : info.remainingLabel;
-            }
-            return mContext.getString(
-                    R.string.battery_state_and_duration, info.statusLabel, info.remainingLabel);
-        } else if (mPowerManager.isPowerSaveMode()) {
-            // Power save mode is on
-            final String powerSaverOn =
-                    mContext.getString(R.string.battery_tip_early_heads_up_done_title);
-            return mContext.getString(
-                    R.string.battery_state_and_duration, powerSaverOn, info.remainingLabel);
-        } else if (mBatteryTip != null && mBatteryTip.getType() == BatteryTip.TipType.LOW_BATTERY) {
-            // Low battery state
-            final String lowBattery = mContext.getString(R.string.low_battery_summary);
-            return mContext.getString(
-                    R.string.battery_state_and_duration, lowBattery, info.remainingLabel);
-        } else {
-            // Discharging state
-            return info.remainingLabel;
-        }
-    }
-
-    public void updateHeaderPreference(BatteryInfo info) {
-        if (!mBatteryStatusFeatureProvider.triggerBatteryStatusUpdate(this, info)) {
-            mBatteryUsageProgressBarPref.setBottomSummary(generateLabel(info));
-        }
-
-        mBatteryUsageProgressBarPref.setUsageSummary(
-                formatBatteryPercentageText(info.batteryLevel));
-        mBatteryUsageProgressBarPref.setPercent(info.batteryLevel, BATTERY_MAX_LEVEL);
-    }
-
-    /** Callback which receives text for the summary line. */
-    public void updateBatteryStatus(String label, BatteryInfo info) {
-        final CharSequence summary = label != null ? label : generateLabel(info);
-        mBatteryUsageProgressBarPref.setBottomSummary(summary);
-        Log.d(TAG, "updateBatteryStatus: " + label + " summary: " + summary);
-    }
-
+    /** Updates {@link UsageProgressBarPreference} information. */
     public void quickUpdateHeaderPreference() {
+        if (mBatteryUsageProgressBarPreference == null) {
+            return;
+        }
+
         Intent batteryBroadcast =
                 com.android.settingslib.fuelgauge.BatteryUtils.getBatteryIntent(mContext);
         final int batteryLevel = Utils.getBatteryLevel(batteryBroadcast);
-        final boolean discharging =
-                batteryBroadcast.getIntExtra(BatteryManager.EXTRA_PLUGGED, -1) == 0;
 
-        mBatteryUsageProgressBarPref.setUsageSummary(formatBatteryPercentageText(batteryLevel));
-        mBatteryUsageProgressBarPref.setPercent(batteryLevel, BATTERY_MAX_LEVEL);
-    }
-
-    /** Update summary when battery tips changed. */
-    public void updateHeaderByBatteryTips(BatteryTip batteryTip, BatteryInfo batteryInfo) {
-        mBatteryTip = batteryTip;
-
-        if (mBatteryTip != null && batteryInfo != null) {
-            updateHeaderPreference(batteryInfo);
-        }
+        mBatteryUsageProgressBarPreference.setUsageSummary(
+                formatBatteryPercentageText(batteryLevel));
+        mBatteryUsageProgressBarPreference.setPercent(batteryLevel, BATTERY_MAX_LEVEL);
     }
 
     private CharSequence formatBatteryPercentageText(int batteryLevel) {
         return com.android.settings.Utils.formatPercentage(batteryLevel);
     }
 }
+// LINT.ThenChange(BatteryHeaderPreference.kt)
diff --git a/src/com/android/settings/fuelgauge/BatteryHeaderTextPreference.java b/src/com/android/settings/fuelgauge/BatteryHeaderTextPreference.java
new file mode 100644
index 0000000..5c81277
--- /dev/null
+++ b/src/com/android/settings/fuelgauge/BatteryHeaderTextPreference.java
@@ -0,0 +1,60 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.settings.fuelgauge;
+
+import android.content.Context;
+import android.text.TextUtils;
+import android.util.AttributeSet;
+import android.widget.TextView;
+
+import androidx.annotation.Nullable;
+import androidx.preference.Preference;
+import androidx.preference.PreferenceViewHolder;
+
+import com.android.settings.R;
+
+/** A preference for battery header text. */
+public class BatteryHeaderTextPreference extends Preference {
+    private static final String TAG = "BatteryHeaderTextPreference";
+
+    @Nullable private CharSequence mText;
+    @Nullable private CharSequence mContentDescription;
+
+    public BatteryHeaderTextPreference(Context context, AttributeSet attrs) {
+        super(context, attrs);
+        setLayoutResource(R.layout.preference_battery_header_text);
+    }
+
+    @Override
+    public void onBindViewHolder(PreferenceViewHolder view) {
+        final TextView textView = (TextView) view.findViewById(R.id.text);
+        textView.setText(mText);
+        if (!TextUtils.isEmpty(mContentDescription)) {
+            textView.setContentDescription(mContentDescription);
+        }
+    }
+
+    void setText(@Nullable CharSequence text) {
+        mText = text;
+        notifyChanged();
+    }
+
+    void setContentDescription(@Nullable CharSequence contentDescription) {
+        mContentDescription = contentDescription;
+        notifyChanged();
+    }
+}
diff --git a/src/com/android/settings/fuelgauge/BatteryHeaderTextPreferenceController.java b/src/com/android/settings/fuelgauge/BatteryHeaderTextPreferenceController.java
index a7e1254..b609174 100644
--- a/src/com/android/settings/fuelgauge/BatteryHeaderTextPreferenceController.java
+++ b/src/com/android/settings/fuelgauge/BatteryHeaderTextPreferenceController.java
@@ -17,11 +17,12 @@
 package com.android.settings.fuelgauge;
 
 import android.content.Context;
-import android.content.Intent;
 import android.os.BatteryManager;
 import android.os.PowerManager;
 import android.util.Log;
 
+import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
 import androidx.annotation.VisibleForTesting;
 import androidx.preference.PreferenceScreen;
 
@@ -31,23 +32,20 @@
 import com.android.settings.fuelgauge.batterytip.tips.BatteryTip;
 import com.android.settings.overlay.FeatureFactory;
 import com.android.settingslib.Utils;
-import com.android.settingslib.widget.UsageProgressBarPreference;
 
 /** Controller that update the battery header view */
 public class BatteryHeaderTextPreferenceController extends BasePreferenceController
         implements PreferenceControllerMixin, BatteryPreferenceController {
-    private static final String TAG = "BatteryHeaderPreferenceController";
-
-    @VisibleForTesting static final String KEY_BATTERY_HEADER = "battery_header";
-    private static final int BATTERY_MAX_LEVEL = 100;
-
-    @VisibleForTesting BatteryStatusFeatureProvider mBatteryStatusFeatureProvider;
-    @VisibleForTesting UsageProgressBarPreference mBatteryUsageProgressBarPref;
+    private static final String TAG = "BatteryHeaderTextPreferenceController";
 
     private final PowerManager mPowerManager;
     private final BatterySettingsFeatureProvider mBatterySettingsFeatureProvider;
 
-    private BatteryTip mBatteryTip;
+    @Nullable private BatteryTip mBatteryTip;
+
+    @VisibleForTesting BatteryStatusFeatureProvider mBatteryStatusFeatureProvider;
+
+    @Nullable @VisibleForTesting BatteryHeaderTextPreference mBatteryHeaderTextPreference;
 
     public BatteryHeaderTextPreferenceController(Context context, String key) {
         super(context, key);
@@ -61,14 +59,11 @@
     @Override
     public void displayPreference(PreferenceScreen screen) {
         super.displayPreference(screen);
-        mBatteryUsageProgressBarPref = screen.findPreference(getPreferenceKey());
-        // Set up empty space text first to prevent layout flaky before info loaded.
-        mBatteryUsageProgressBarPref.setBottomSummary(" ");
+        mBatteryHeaderTextPreference = screen.findPreference(getPreferenceKey());
 
-        if (com.android.settings.Utils.isBatteryPresent(mContext)) {
-            quickUpdateHeaderPreference();
-        } else {
-            mBatteryUsageProgressBarPref.setVisible(false);
+        if (mBatteryHeaderTextPreference != null
+                && !com.android.settings.Utils.isBatteryPresent(mContext)) {
+            mBatteryHeaderTextPreference.setVisible(false);
         }
     }
 
@@ -77,7 +72,8 @@
         return AVAILABLE_UNSEARCHABLE;
     }
 
-    private CharSequence generateLabel(BatteryInfo info) {
+    @NonNull
+    private CharSequence generateLabel(@NonNull BatteryInfo info) {
         if (Utils.containsIncompatibleChargers(mContext, TAG)) {
             return mContext.getString(
                     com.android.settingslib.R.string.battery_info_status_not_charging);
@@ -99,8 +95,8 @@
         if (info.pluggedStatus == BatteryManager.BATTERY_PLUGGED_WIRELESS) {
             final CharSequence wirelessChargingLabel =
                     mBatterySettingsFeatureProvider.getWirelessChargingLabel(mContext, info);
-            if (wirelessChargingLabel != null) {
-                mBatteryUsageProgressBarPref.setBottomSummaryContentDescription(
+            if (mBatteryHeaderTextPreference != null && wirelessChargingLabel != null) {
+                mBatteryHeaderTextPreference.setContentDescription(
                         mBatterySettingsFeatureProvider
                                 .getWirelessChargingContentDescription(mContext, info));
                 return wirelessChargingLabel;
@@ -138,46 +134,33 @@
         }
     }
 
-    /** Updates the battery header. */
-    public void updateHeaderPreference(BatteryInfo info) {
-        if (!mBatteryStatusFeatureProvider.triggerBatteryStatusUpdate(this, info)) {
-            mBatteryUsageProgressBarPref.setBottomSummary(generateLabel(info));
+    /** Updates the battery header text with the given BatteryInfo. */
+    public void updateHeaderPreference(@NonNull BatteryInfo info) {
+        if (mBatteryHeaderTextPreference != null
+                && !mBatteryStatusFeatureProvider.triggerBatteryStatusUpdate(this, info)) {
+            mBatteryHeaderTextPreference.setText(generateLabel(info));
         }
-
-        mBatteryUsageProgressBarPref.setUsageSummary(
-                formatBatteryPercentageText(info.batteryLevel));
-        mBatteryUsageProgressBarPref.setPercent(info.batteryLevel, BATTERY_MAX_LEVEL);
     }
 
-    /** Callback which receives text for the summary line. */
+    /** Callback which updates the battery header text with the given label. */
+    @Override
     public void updateBatteryStatus(String label, BatteryInfo info) {
+        if (mBatteryHeaderTextPreference == null) {
+            return;
+        }
+
         final CharSequence summary = label != null ? label : generateLabel(info);
-        mBatteryUsageProgressBarPref.setBottomSummary(summary);
+        mBatteryHeaderTextPreference.setText(summary);
         Log.d(TAG, "updateBatteryStatus: " + label + " summary: " + summary);
     }
 
-    /** Updates the battery header quickly. */
-    public void quickUpdateHeaderPreference() {
-        Intent batteryBroadcast =
-                com.android.settingslib.fuelgauge.BatteryUtils.getBatteryIntent(mContext);
-        final int batteryLevel = Utils.getBatteryLevel(batteryBroadcast);
-        final boolean discharging =
-                batteryBroadcast.getIntExtra(BatteryManager.EXTRA_PLUGGED, -1) == 0;
-
-        mBatteryUsageProgressBarPref.setUsageSummary(formatBatteryPercentageText(batteryLevel));
-        mBatteryUsageProgressBarPref.setPercent(batteryLevel, BATTERY_MAX_LEVEL);
-    }
-
-    /** Update summary when battery tips changed. */
-    public void updateHeaderByBatteryTips(BatteryTip batteryTip, BatteryInfo batteryInfo) {
+    /** Update summary when battery tips are changed. */
+    public void updateHeaderByBatteryTips(
+            @Nullable BatteryTip batteryTip, @NonNull BatteryInfo batteryInfo) {
         mBatteryTip = batteryTip;
 
         if (mBatteryTip != null && batteryInfo != null) {
             updateHeaderPreference(batteryInfo);
         }
     }
-
-    private CharSequence formatBatteryPercentageText(int batteryLevel) {
-        return com.android.settings.Utils.formatPercentage(batteryLevel);
-    }
 }
diff --git a/src/com/android/settings/fuelgauge/batteryusage/PowerUsageSummary.java b/src/com/android/settings/fuelgauge/batteryusage/PowerUsageSummary.java
index b5581d0..66c2ee9 100644
--- a/src/com/android/settings/fuelgauge/batteryusage/PowerUsageSummary.java
+++ b/src/com/android/settings/fuelgauge/batteryusage/PowerUsageSummary.java
@@ -36,7 +36,7 @@
 
 import com.android.settings.R;
 import com.android.settings.Utils;
-import com.android.settings.fuelgauge.BatteryHeaderPreferenceController;
+import com.android.settings.fuelgauge.BatteryHeaderTextPreferenceController;
 import com.android.settings.fuelgauge.BatteryInfo;
 import com.android.settings.fuelgauge.BatteryInfoLoader;
 import com.android.settings.fuelgauge.BatteryUtils;
@@ -67,7 +67,7 @@
     @VisibleForTesting BatteryUtils mBatteryUtils;
     @VisibleForTesting BatteryInfo mBatteryInfo;
 
-    @VisibleForTesting BatteryHeaderPreferenceController mBatteryHeaderPreferenceController;
+    @VisibleForTesting BatteryHeaderTextPreferenceController mBatteryHeaderTextPreferenceController;
     @VisibleForTesting BatteryTipPreferenceController mBatteryTipPreferenceController;
     @VisibleForTesting boolean mNeedUpdateBatteryTip;
     @VisibleForTesting Preference mHelpPreference;
@@ -93,8 +93,8 @@
 
                 @Override
                 public void onLoadFinished(Loader<BatteryInfo> loader, BatteryInfo batteryInfo) {
-                    mBatteryHeaderPreferenceController.updateHeaderPreference(batteryInfo);
-                    mBatteryHeaderPreferenceController.updateHeaderByBatteryTips(
+                    mBatteryHeaderTextPreferenceController.updateHeaderPreference(batteryInfo);
+                    mBatteryHeaderTextPreferenceController.updateHeaderByBatteryTips(
                             mBatteryTipPreferenceController.getCurrentBatteryTip(), batteryInfo);
                     mBatteryInfo = batteryInfo;
                 }
@@ -116,7 +116,7 @@
                 @Override
                 public void onLoadFinished(Loader<List<BatteryTip>> loader, List<BatteryTip> data) {
                     mBatteryTipPreferenceController.updateBatteryTips(data);
-                    mBatteryHeaderPreferenceController.updateHeaderByBatteryTips(
+                    mBatteryHeaderTextPreferenceController.updateHeaderByBatteryTips(
                             mBatteryTipPreferenceController.getCurrentBatteryTip(), mBatteryInfo);
                 }
 
@@ -129,7 +129,7 @@
         super.onAttach(context);
         final Activity activity = getActivity();
 
-        mBatteryHeaderPreferenceController = use(BatteryHeaderPreferenceController.class);
+        mBatteryHeaderTextPreferenceController = use(BatteryHeaderTextPreferenceController.class);
 
         mBatteryTipPreferenceController = use(BatteryTipPreferenceController.class);
         mBatteryTipPreferenceController.setActivity(activity);
@@ -251,15 +251,6 @@
     }
 
     @Override
-    protected void restartBatteryStatsLoader(@BatteryUpdateType int refreshType) {
-        super.restartBatteryStatsLoader(refreshType);
-        // Update battery header if battery is present.
-        if (mIsBatteryPresent) {
-            mBatteryHeaderPreferenceController.quickUpdateHeaderPreference();
-        }
-    }
-
-    @Override
     public void onSaveInstanceState(Bundle outState) {
         super.onSaveInstanceState(outState);
         mBatteryTipPreferenceController.saveInstanceState(outState);
diff --git a/src/com/android/settings/fuelgauge/batteryusage/PowerUsageSummaryScreen.kt b/src/com/android/settings/fuelgauge/batteryusage/PowerUsageSummaryScreen.kt
index b397bf3..9ff46b9 100644
--- a/src/com/android/settings/fuelgauge/batteryusage/PowerUsageSummaryScreen.kt
+++ b/src/com/android/settings/fuelgauge/batteryusage/PowerUsageSummaryScreen.kt
@@ -19,6 +19,7 @@
 import com.android.settings.R
 import com.android.settings.display.BatteryPercentageSwitchPreference
 import com.android.settings.flags.Flags
+import com.android.settings.fuelgauge.BatteryHeaderPreference
 import com.android.settingslib.metadata.PreferenceAvailabilityProvider
 import com.android.settingslib.metadata.PreferenceIconProvider
 import com.android.settingslib.metadata.ProvidePreferenceScreen
@@ -53,8 +54,10 @@
             R.drawable.ic_settings_battery_white
         }
 
-    override fun getPreferenceHierarchy(context: Context) =
-        preferenceHierarchy(this) { +BatteryPercentageSwitchPreference() }
+    override fun getPreferenceHierarchy(context: Context) = preferenceHierarchy(this) {
+        +BatteryHeaderPreference()
+        +BatteryPercentageSwitchPreference()
+    }
 
     companion object {
         const val KEY = "power_usage_summary_screen"
diff --git a/src/com/android/settings/inputmethod/PointerTouchpadFragment.java b/src/com/android/settings/inputmethod/PointerTouchpadFragment.java
index 890d9b6..441bddd 100644
--- a/src/com/android/settings/inputmethod/PointerTouchpadFragment.java
+++ b/src/com/android/settings/inputmethod/PointerTouchpadFragment.java
@@ -25,8 +25,12 @@
 import com.android.settings.R;
 import com.android.settings.dashboard.DashboardFragment;
 import com.android.settings.search.BaseSearchIndexProvider;
+import com.android.settings.widget.PreferenceCategoryController;
+import com.android.settingslib.core.AbstractPreferenceController;
 import com.android.settingslib.search.SearchIndexable;
 
+import java.util.List;
+
 /** Accessibility settings for pointer and touchpad. */
 @SearchIndexable(forTarget = SearchIndexable.ALL & ~SearchIndexable.ARC)
 public class PointerTouchpadFragment extends DashboardFragment {
@@ -34,6 +38,21 @@
     private static final String TAG = "PointerTouchpadFragment";
 
     @Override
+    protected List<AbstractPreferenceController> createPreferenceControllers(Context context) {
+        return buildPreferenceControllers(context);
+    }
+
+    private static List<AbstractPreferenceController> buildPreferenceControllers(Context context) {
+        TouchpadSystemGesturesPreferenceController systemGesturesController =
+                new TouchpadSystemGesturesPreferenceController(
+                        context, "touchpad_system_gestures_enable");
+        return List.of(
+                systemGesturesController,
+                new PreferenceCategoryController(context, "touchpad_category")
+                        .setChildren(List.of(systemGesturesController)));
+    }
+
+    @Override
     public int getMetricsCategory() {
         return SettingsEnums.ACCESSIBILITY_POINTER_TOUCHPAD;
     }
@@ -54,5 +73,11 @@
                 protected boolean isPageSearchEnabled(Context context) {
                     return isTouchpad() || isMouse();
                 }
+
+                @Override
+                public List<AbstractPreferenceController> createPreferenceControllers(
+                        Context context) {
+                    return buildPreferenceControllers(context);
+                }
             };
 }
diff --git a/src/com/android/settings/inputmethod/TouchGesturesButtonPreferenceController.java b/src/com/android/settings/inputmethod/TouchGesturesButtonPreferenceController.java
index 5154623..8b0ae4c 100644
--- a/src/com/android/settings/inputmethod/TouchGesturesButtonPreferenceController.java
+++ b/src/com/android/settings/inputmethod/TouchGesturesButtonPreferenceController.java
@@ -21,6 +21,7 @@
 import android.app.settings.SettingsEnums;
 import android.content.Context;
 import android.content.Intent;
+import android.hardware.input.InputSettings;
 import android.os.UserHandle;
 import android.util.FeatureFlagUtils;
 
@@ -75,7 +76,14 @@
     @Override
     public int getAvailabilityStatus() {
         boolean isTouchpad = InputPeripheralsSettingsUtils.isTouchpad();
-        return isTouchpad ? AVAILABLE : CONDITIONALLY_UNAVAILABLE;
+        if (isTouchpad) {
+            // If the user's disabled touchpad system gestures in the accessibility settings, the
+            // tutorial won't work or be relevant, so disable the button.
+            return InputSettings.useTouchpadSystemGestures(mContext) ? AVAILABLE
+                    : DISABLED_DEPENDENT_SETTING;
+        } else {
+            return CONDITIONALLY_UNAVAILABLE;
+        }
     }
 
     private void showTouchpadGestureEducation() {
diff --git a/src/com/android/settings/inputmethod/TouchpadSystemGesturesPreferenceController.java b/src/com/android/settings/inputmethod/TouchpadSystemGesturesPreferenceController.java
new file mode 100644
index 0000000..9f0acb1
--- /dev/null
+++ b/src/com/android/settings/inputmethod/TouchpadSystemGesturesPreferenceController.java
@@ -0,0 +1,54 @@
+/*
+ * Copyright 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.settings.inputmethod;
+
+import android.content.Context;
+import android.hardware.input.InputSettings;
+
+import com.android.settings.R;
+import com.android.settings.core.TogglePreferenceController;
+
+public class TouchpadSystemGesturesPreferenceController extends TogglePreferenceController {
+
+    public TouchpadSystemGesturesPreferenceController(Context context, String key) {
+        super(context, key);
+    }
+
+    @Override
+    public int getAvailabilityStatus() {
+        return InputSettings.isTouchpadSystemGestureDisableFeatureFlagEnabled()
+                && InputPeripheralsSettingsUtils.isTouchpad() ? AVAILABLE
+                                                              : CONDITIONALLY_UNAVAILABLE;
+    }
+
+    @Override
+    public boolean isChecked() {
+        return InputSettings.useTouchpadSystemGestures(mContext);
+    }
+
+    @Override
+    public boolean setChecked(boolean isChecked) {
+        InputSettings.setTouchpadSystemGesturesEnabled(mContext, isChecked);
+        // TODO(b/353947750): add a metric for when the setting changes.
+        return true;
+    }
+
+    @Override
+    public int getSliceHighlightMenuRes() {
+        return R.string.menu_key_accessibility;
+    }
+}
diff --git a/src/com/android/settings/inputmethod/TrackpadGesturesDisabledFooterPreferenceController.java b/src/com/android/settings/inputmethod/TrackpadGesturesDisabledFooterPreferenceController.java
new file mode 100644
index 0000000..1fed57e
--- /dev/null
+++ b/src/com/android/settings/inputmethod/TrackpadGesturesDisabledFooterPreferenceController.java
@@ -0,0 +1,35 @@
+/*
+ * Copyright 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.settings.inputmethod;
+
+import android.content.Context;
+import android.hardware.input.InputSettings;
+
+import com.android.settings.core.BasePreferenceController;
+
+public class TrackpadGesturesDisabledFooterPreferenceController extends BasePreferenceController {
+
+    public TrackpadGesturesDisabledFooterPreferenceController(Context context, String key) {
+        super(context, key);
+    }
+
+    @Override
+    public int getAvailabilityStatus() {
+        return InputSettings.useTouchpadSystemGestures(mContext) ? CONDITIONALLY_UNAVAILABLE
+                : AVAILABLE;
+    }
+}
diff --git a/src/com/android/settings/language/MoreLanguagesSettingsCategoryController.java b/src/com/android/settings/language/MoreLanguagesSettingsCategoryController.java
new file mode 100644
index 0000000..3f2f9d7
--- /dev/null
+++ b/src/com/android/settings/language/MoreLanguagesSettingsCategoryController.java
@@ -0,0 +1,42 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.settings.language;
+
+import android.content.Context;
+
+import androidx.annotation.NonNull;
+
+import com.android.settings.flags.Flags;
+import com.android.settings.widget.PreferenceCategoryController;
+
+/**
+ * Controller for the "More language settings" category in the Language & region settings.
+ */
+public class MoreLanguagesSettingsCategoryController extends PreferenceCategoryController {
+
+    public MoreLanguagesSettingsCategoryController(@NonNull Context context, @NonNull String key) {
+        super(context, key);
+    }
+
+    @Override
+    public int getAvailabilityStatus() {
+        if (Flags.regionalPreferencesApiEnabled()) {
+            return AVAILABLE;
+        }
+        return CONDITIONALLY_UNAVAILABLE;
+    }
+}
diff --git a/src/com/android/settings/network/telephony/EnabledNetworkModePreferenceController.java b/src/com/android/settings/network/telephony/EnabledNetworkModePreferenceController.java
index 1b1eb9e..8051711 100644
--- a/src/com/android/settings/network/telephony/EnabledNetworkModePreferenceController.java
+++ b/src/com/android/settings/network/telephony/EnabledNetworkModePreferenceController.java
@@ -16,9 +16,6 @@
 
 package com.android.settings.network.telephony;
 
-import static androidx.lifecycle.Lifecycle.Event.ON_START;
-import static androidx.lifecycle.Lifecycle.Event.ON_STOP;
-
 import static com.android.settings.network.telephony.EnabledNetworkModePreferenceControllerHelperKt.getNetworkModePreferenceType;
 import static com.android.settings.network.telephony.EnabledNetworkModePreferenceControllerHelperKt.setAllowedNetworkTypes;
 import static com.android.settings.network.telephony.mode.NetworkModes.addNrToLteNetworkMode;
@@ -33,15 +30,17 @@
 import android.telephony.SubscriptionManager;
 import android.telephony.TelephonyCallback;
 import android.telephony.TelephonyManager;
+import android.telephony.satellite.SatelliteManager;
+import android.telephony.satellite.SatelliteModemStateCallback;
+import android.telephony.satellite.SelectedNbIotSatelliteSubscriptionCallback;
 import android.util.Log;
 
 import androidx.annotation.NonNull;
 import androidx.annotation.VisibleForTesting;
 import androidx.fragment.app.Fragment;
 import androidx.fragment.app.FragmentManager;
-import androidx.lifecycle.LifecycleObserver;
+import androidx.lifecycle.DefaultLifecycleObserver;
 import androidx.lifecycle.LifecycleOwner;
-import androidx.lifecycle.OnLifecycleEvent;
 import androidx.preference.ListPreference;
 import androidx.preference.ListPreferenceDialogFragmentCompat;
 import androidx.preference.Preference;
@@ -67,7 +66,7 @@
  */
 public class EnabledNetworkModePreferenceController extends
         BasePreferenceController implements
-        ListPreference.OnPreferenceChangeListener, LifecycleObserver,
+        ListPreference.OnPreferenceChangeListener, DefaultLifecycleObserver,
         SubscriptionsChangeListener.SubscriptionsChangeListenerClient {
 
     private static final String LOG_TAG = "EnabledNetworkMode";
@@ -83,6 +82,43 @@
     private PhoneCallStateTelephonyCallback mTelephonyCallback;
     private FragmentManager mFragmentManager;
     private LifecycleOwner mViewLifecycleOwner;
+    private SatelliteManager mSatelliteManager;
+    private boolean mIsSatelliteSessionStarted = false;
+    private boolean mIsCurrentSubscriptionForSatellite = false;
+
+    @VisibleForTesting
+    final SelectedNbIotSatelliteSubscriptionCallback mSelectedNbIotSatelliteSubscriptionCallback =
+            new SelectedNbIotSatelliteSubscriptionCallback() {
+                @Override
+                public void onSelectedNbIotSatelliteSubscriptionChanged(int selectedSubId) {
+                    mIsCurrentSubscriptionForSatellite = selectedSubId == mSubId;
+                    updatePreference();
+                }
+            };
+
+    @VisibleForTesting
+    final SatelliteModemStateCallback mSatelliteModemStateCallback =
+            new SatelliteModemStateCallback() {
+                @Override
+                public void onSatelliteModemStateChanged(int state) {
+                    switch (state) {
+                        case SatelliteManager.SATELLITE_MODEM_STATE_OFF:
+                        case SatelliteManager.SATELLITE_MODEM_STATE_UNAVAILABLE:
+                        case SatelliteManager.SATELLITE_MODEM_STATE_UNKNOWN:
+                            if (mIsSatelliteSessionStarted) {
+                                mIsSatelliteSessionStarted = false;
+                                updatePreference();
+                            }
+                            break;
+                        default:
+                            if (!mIsSatelliteSessionStarted) {
+                                mIsSatelliteSessionStarted = true;
+                                updatePreference();
+                            }
+                            break;
+                    }
+                }
+            };
 
     public EnabledNetworkModePreferenceController(Context context, String key) {
         super(context, key);
@@ -90,6 +126,7 @@
         if (mTelephonyCallback == null) {
             mTelephonyCallback = new PhoneCallStateTelephonyCallback();
         }
+        mSatelliteManager = context.getSystemService(SatelliteManager.class);
     }
 
     @Override
@@ -103,8 +140,22 @@
         return mCallState == TelephonyManager.CALL_STATE_IDLE;
     }
 
-    @OnLifecycleEvent(ON_START)
-    public void onStart() {
+    @Override
+    public void onStart(@NonNull LifecycleOwner owner) {
+        if (com.android.settings.flags.Flags.satelliteOemSettingsUxMigration()) {
+            if (mSatelliteManager != null) {
+                try {
+                    mSatelliteManager.registerForModemStateChanged(
+                            mContext.getMainExecutor(), mSatelliteModemStateCallback);
+                    mSatelliteManager.registerForSelectedNbIotSatelliteSubscriptionChanged(
+                            mContext.getMainExecutor(),
+                            mSelectedNbIotSatelliteSubscriptionCallback);
+                } catch (IllegalStateException e) {
+                    Log.w(LOG_TAG, "IllegalStateException : " + e);
+                }
+            }
+        }
+
         mSubscriptionsListener.start();
         if (mAllowedNetworkTypesListener == null || mTelephonyCallback == null) {
             return;
@@ -113,9 +164,21 @@
         mTelephonyCallback.register(mTelephonyManager, mSubId);
     }
 
-    @OnLifecycleEvent(ON_STOP)
-    public void onStop() {
+    @Override
+    public void onStop(@NonNull LifecycleOwner owner) {
         mSubscriptionsListener.stop();
+        if (com.android.settings.flags.Flags.satelliteOemSettingsUxMigration()) {
+            if (mSatelliteManager != null) {
+                try {
+                    mSatelliteManager.unregisterForModemStateChanged(mSatelliteModemStateCallback);
+                    mSatelliteManager.unregisterForSelectedNbIotSatelliteSubscriptionChanged(
+                            mSelectedNbIotSatelliteSubscriptionCallback);
+                } catch (IllegalStateException e) {
+                    Log.w(LOG_TAG, "IllegalStateException : " + e);
+                }
+            }
+        }
+
         if (mAllowedNetworkTypesListener == null || mTelephonyCallback == null) {
             return;
         }
@@ -147,7 +210,7 @@
         listPreference.setEntryValues(mBuilder.getEntryValues());
         listPreference.setValue(Integer.toString(mBuilder.getSelectedEntryValue()));
         listPreference.setSummary(mBuilder.getSummary());
-        boolean listPreferenceEnabled = isCallStateIdle();
+        boolean listPreferenceEnabled = isPreferenceShallEnabled();
         listPreference.setEnabled(listPreferenceEnabled);
         if (!listPreferenceEnabled) {
             // If dialog is already opened when ListPreference disabled, dismiss them.
@@ -203,6 +266,14 @@
         }
     }
 
+    private boolean isPreferenceShallEnabled() {
+        Log.d(LOG_TAG, "isPreferenceShallEnabled, mIsSatelliteSessionStarted : "
+                + mIsSatelliteSessionStarted + " / mIsCurrentSubscriptionForSatellite : "
+                + mIsCurrentSubscriptionForSatellite);
+        return isCallStateIdle()
+                && !(mIsSatelliteSessionStarted && mIsCurrentSubscriptionForSatellite);
+    }
+
     private final class PreferenceEntriesBuilder {
         private CarrierConfigCache mCarrierConfigCache;
         private Context mContext;
@@ -254,7 +325,7 @@
 
                 if (flagHidePrefer3gItem) {
                     mDisplay3gOptions = carrierConfig.getBoolean(
-                        CarrierConfigManager.KEY_PREFER_3G_VISIBILITY_BOOL);
+                            CarrierConfigManager.KEY_PREFER_3G_VISIBILITY_BOOL);
                 } else {
                     mDisplay3gOptions = getResourcesForSubId().getBoolean(
                             R.bool.config_display_network_mode_3g_option);
diff --git a/src/com/android/settings/network/telephony/PreferredNetworkModePreferenceController.java b/src/com/android/settings/network/telephony/PreferredNetworkModePreferenceController.java
index d855069..4409188 100644
--- a/src/com/android/settings/network/telephony/PreferredNetworkModePreferenceController.java
+++ b/src/com/android/settings/network/telephony/PreferredNetworkModePreferenceController.java
@@ -24,10 +24,18 @@
 import android.telephony.RadioAccessFamily;
 import android.telephony.SubscriptionManager;
 import android.telephony.TelephonyManager;
+import android.telephony.satellite.SatelliteManager;
+import android.telephony.satellite.SatelliteModemStateCallback;
+import android.telephony.satellite.SelectedNbIotSatelliteSubscriptionCallback;
 import android.util.Log;
 
+import androidx.annotation.NonNull;
+import androidx.annotation.VisibleForTesting;
+import androidx.lifecycle.DefaultLifecycleObserver;
+import androidx.lifecycle.LifecycleOwner;
 import androidx.preference.ListPreference;
 import androidx.preference.Preference;
+import androidx.preference.PreferenceScreen;
 
 import com.android.settings.R;
 import com.android.settings.core.BasePreferenceController;
@@ -38,17 +46,56 @@
  * Preference controller for "Preferred network mode"
  */
 public class PreferredNetworkModePreferenceController extends BasePreferenceController
-        implements ListPreference.OnPreferenceChangeListener {
+        implements ListPreference.OnPreferenceChangeListener, DefaultLifecycleObserver {
     private static final String TAG = "PrefNetworkModeCtrl";
 
     private int mSubId = SubscriptionManager.INVALID_SUBSCRIPTION_ID;
     private CarrierConfigCache mCarrierConfigCache;
     private TelephonyManager mTelephonyManager;
     private boolean mIsGlobalCdma;
+    private SatelliteManager mSatelliteManager;
+    private Preference mPreference;
+    private boolean mIsSatelliteSessionStarted = false;
+    private boolean mIsCurrentSubscriptionForSatellite = false;
+
+    @VisibleForTesting
+    final SelectedNbIotSatelliteSubscriptionCallback mSelectedNbIotSatelliteSubscriptionCallback =
+            new SelectedNbIotSatelliteSubscriptionCallback() {
+                @Override
+                public void onSelectedNbIotSatelliteSubscriptionChanged(int selectedSubId) {
+                    mIsCurrentSubscriptionForSatellite = selectedSubId == mSubId;
+                    updateState(mPreference);
+                }
+            };
+
+    @VisibleForTesting
+    final SatelliteModemStateCallback mSatelliteModemStateCallback =
+            new SatelliteModemStateCallback() {
+                @Override
+                public void onSatelliteModemStateChanged(int state) {
+                    switch (state) {
+                        case SatelliteManager.SATELLITE_MODEM_STATE_OFF:
+                        case SatelliteManager.SATELLITE_MODEM_STATE_UNAVAILABLE:
+                        case SatelliteManager.SATELLITE_MODEM_STATE_UNKNOWN:
+                            if (mIsSatelliteSessionStarted) {
+                                mIsSatelliteSessionStarted = false;
+                                updateState(mPreference);
+                            }
+                            break;
+                        default:
+                            if (!mIsSatelliteSessionStarted) {
+                                mIsSatelliteSessionStarted = true;
+                                updateState(mPreference);
+                            }
+                            break;
+                    }
+                }
+            };
 
     public PreferredNetworkModePreferenceController(Context context, String key) {
         super(context, key);
         mCarrierConfigCache = CarrierConfigCache.getInstance(context);
+        mSatelliteManager = context.getSystemService(SatelliteManager.class);
     }
 
     @Override
@@ -59,8 +106,18 @@
     }
 
     @Override
+    public void displayPreference(PreferenceScreen screen) {
+        super.displayPreference(screen);
+        mPreference = screen.findPreference(getPreferenceKey());
+    }
+
+    @Override
     public void updateState(Preference preference) {
+        if (preference == null) {
+            return;
+        }
         super.updateState(preference);
+        preference.setEnabled(!(mIsCurrentSubscriptionForSatellite && mIsSatelliteSessionStarted));
         final ListPreference listPreference = (ListPreference) preference;
         final int networkMode = getPreferredNetworkMode();
         listPreference.setValue(Integer.toString(networkMode));
@@ -75,9 +132,9 @@
                 TelephonyManager.ALLOWED_NETWORK_TYPES_REASON_USER,
                 RadioAccessFamily.getRafFromNetworkType(newPreferredNetworkMode));
 
-            final ListPreference listPreference = (ListPreference) preference;
-            listPreference.setSummary(getPreferredNetworkModeSummaryResId(newPreferredNetworkMode));
-            return true;
+        final ListPreference listPreference = (ListPreference) preference;
+        listPreference.setSummary(getPreferredNetworkModeSummaryResId(newPreferredNetworkMode));
+        return true;
     }
 
     public void init(int subId) {
@@ -90,6 +147,38 @@
                 && carrierConfig.getBoolean(CarrierConfigManager.KEY_SHOW_CDMA_CHOICES_BOOL);
     }
 
+    @Override
+    public void onStart(@NonNull LifecycleOwner owner) {
+        if (com.android.settings.flags.Flags.satelliteOemSettingsUxMigration()) {
+            if (mSatelliteManager != null) {
+                try {
+                    mSatelliteManager.registerForModemStateChanged(
+                            mContext.getMainExecutor(), mSatelliteModemStateCallback);
+                    mSatelliteManager.registerForSelectedNbIotSatelliteSubscriptionChanged(
+                            mContext.getMainExecutor(),
+                            mSelectedNbIotSatelliteSubscriptionCallback);
+                } catch (IllegalStateException e) {
+                    Log.w(TAG, "IllegalStateException : " + e);
+                }
+            }
+        }
+    }
+
+    @Override
+    public void onStop(@NonNull LifecycleOwner owner) {
+        if (com.android.settings.flags.Flags.satelliteOemSettingsUxMigration()) {
+            if (mSatelliteManager != null) {
+                try {
+                    mSatelliteManager.unregisterForModemStateChanged(mSatelliteModemStateCallback);
+                    mSatelliteManager.unregisterForSelectedNbIotSatelliteSubscriptionChanged(
+                            mSelectedNbIotSatelliteSubscriptionCallback);
+                } catch (IllegalStateException e) {
+                    Log.w(TAG, "IllegalStateException : " + e);
+                }
+            }
+        }
+    }
+
     private int getPreferredNetworkMode() {
         if (mTelephonyManager == null) {
             Log.w(TAG, "TelephonyManager is null");
diff --git a/src/com/android/settings/network/telephony/SatelliteSetting.java b/src/com/android/settings/network/telephony/SatelliteSetting.java
index 16c56f0..a6e2f82 100644
--- a/src/com/android/settings/network/telephony/SatelliteSetting.java
+++ b/src/com/android/settings/network/telephony/SatelliteSetting.java
@@ -56,20 +56,26 @@
 /** Handle Satellite Setting Preference Layout. */
 public class SatelliteSetting extends RestrictedDashboardFragment {
     private static final String TAG = "SatelliteSetting";
-    public static final String PREF_KEY_ABOUT_SATELLITE_MESSAGING = "key_about_satellite_messaging";
-    public static final String PREF_KEY_CATEGORY_YOUR_SATELLITE_PLAN =
+    private static final String PREF_KEY_ABOUT_SATELLITE_MESSAGING =
+            "key_about_satellite_messaging";
+    private static final String PREF_KEY_CATEGORY_YOUR_SATELLITE_PLAN =
             "key_category_your_satellite_plan";
-    public static final String PREF_KEY_YOUR_SATELLITE_PLAN = "key_your_satellite_plan";
-    public static final String PREF_KEY_CATEGORY_HOW_IT_WORKS = "key_category_how_it_works";
+    private static final String PREF_KEY_YOUR_SATELLITE_PLAN = "key_your_satellite_plan";
+    private static final String PREF_KEY_CATEGORY_HOW_IT_WORKS = "key_category_how_it_works";
+    private static final String PREF_KEY_YOUR_SATELLITE_DATA_PLAN = "key_your_satellite_data_plan";
+    private static final String PREF_KEY_CATEGORY_ABOUT_SATELLITE = "key_category_about_satellite";
     private static final String KEY_FOOTER_PREFERENCE = "satellite_setting_extra_info_footer_pref";
-    public static final String SUB_ID = "sub_id";
+
+    static final String SUB_ID = "sub_id";
+    static final String EXTRA_IS_SERVICE_DATA_TYPE = "is_service_data_type";
 
     private Activity mActivity;
-    private TelephonyManager mTelephonymanager;
     private CarrierConfigManager mCarrierConfigManager;
     private SatelliteManager mSatelliteManager;
     private PersistableBundle mConfigBundle;
-    private int mSubId;
+    private int mSubId = SubscriptionManager.INVALID_SUBSCRIPTION_ID;
+    private String mSimOperatorName = "";
+    private boolean mIsServiceDataType = false;
 
     public SatelliteSetting() {
         super(UserManager.DISALLOW_CONFIG_MOBILE_NETWORKS);
@@ -111,13 +117,19 @@
             return;
         }
 
-        mTelephonymanager = mActivity.getSystemService(TelephonyManager.class);
+        mIsServiceDataType = getIntent().getBooleanExtra(EXTRA_IS_SERVICE_DATA_TYPE, false);
+        mSimOperatorName = getSystemService(TelephonyManager.class).getSimOperatorName(mSubId);
     }
 
     @Override
     public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
         super.onViewCreated(view, savedInstanceState);
-        updateDynamicPreferenceViews();
+        boolean isSatelliteEligible = isSatelliteEligible();
+        updateTitle();
+        updateAboutSatelliteContent();
+        updateMobilePlan(isSatelliteEligible);
+        updateHowItWorksContent(isSatelliteEligible);
+        updateFooterContent();
     }
 
     @Override
@@ -130,31 +142,45 @@
         return R.xml.satellite_setting;
     }
 
-    private void updateDynamicPreferenceViews() {
-        String operatorName = mTelephonymanager.getSimOperatorName(mSubId);
-        boolean isSatelliteEligible = isSatelliteEligible();
+    private void updateTitle() {
+        getActivity().setTitle(getSubjectString());
+    }
 
-        // About satellite messaging
+    // About satellite content
+    private void updateAboutSatelliteContent() {
+        Preference categoryTitle = findPreference(PREF_KEY_CATEGORY_ABOUT_SATELLITE);
+        categoryTitle.setTitle(
+                getString(R.string.category_name_about_satellite_messaging,
+                        getDescriptionString()));
+
         Preference preference = findPreference(PREF_KEY_ABOUT_SATELLITE_MESSAGING);
         preference.setTitle(
-                getResources().getString(R.string.title_about_satellite_setting, operatorName));
+                getResources().getString(R.string.title_about_satellite_setting, mSimOperatorName));
+    }
 
+    private void updateMobilePlan(boolean isSatelliteEligible) {
         // Your mobile plan
         PreferenceCategory prefCategory = findPreference(PREF_KEY_CATEGORY_YOUR_SATELLITE_PLAN);
         prefCategory.setTitle(getResources().getString(R.string.category_title_your_satellite_plan,
-                operatorName));
+                mSimOperatorName));
+        Preference messagingPreference = findPreference(PREF_KEY_YOUR_SATELLITE_PLAN);
 
-        preference = findPreference(PREF_KEY_YOUR_SATELLITE_PLAN);
-        Drawable icon;
+        Drawable icon = getContext().getDrawable(R.drawable.ic_check_circle_24px);
         if (isSatelliteEligible) {
             /* In case satellite is allowed by carrier's entitlement server, the page will show
                the check icon with guidance that satellite is included in user's mobile plan */
-            preference.setTitle(R.string.title_have_satellite_plan);
-            icon = getContext().getDrawable(R.drawable.ic_check_circle_24px);
+            messagingPreference.setTitle(R.string.title_have_satellite_plan);
+            if (com.android.settings.flags.Flags.satelliteOemSettingsUxMigration()) {
+                Preference connectivityPreference = findPreference(
+                        PREF_KEY_YOUR_SATELLITE_DATA_PLAN);
+                connectivityPreference.setTitle(R.string.title_have_satellite_data_plan);
+                connectivityPreference.setIcon(icon);
+                connectivityPreference.setVisible(true);
+            }
         } else {
             /* Or, it will show the blocked icon with the guidance that satellite is not included
                in user's mobile plan */
-            preference.setTitle(R.string.title_no_satellite_plan);
+            messagingPreference.setTitle(R.string.title_no_satellite_plan);
             /* And, the link url provides more information via web page will be shown */
             SpannableString spannable = new SpannableString(
                     getResources().getString(R.string.summary_add_satellite_setting));
@@ -162,9 +188,9 @@
                     Spanned.SPAN_INCLUSIVE_INCLUSIVE);
             spannable.setSpan(new StyleSpan(Typeface.BOLD), 0, spannable.length(),
                     Spanned.SPAN_INCLUSIVE_INCLUSIVE);
-            preference.setSummary(spannable);
+            messagingPreference.setSummary(spannable);
             /* The link will lead users to a guide page */
-            preference.setOnPreferenceClickListener(pref -> {
+            messagingPreference.setOnPreferenceClickListener(pref -> {
                 String url = readSatelliteMoreInfoString(mSubId);
                 if (!url.isEmpty()) {
                     Uri uri = Uri.parse(url);
@@ -173,11 +199,13 @@
                 }
                 return true;
             });
-            icon = getResources().getDrawable(R.drawable.ic_block_24px);
+            icon = getResources().getDrawable(R.drawable.ic_block_24px, null);
         }
         icon.setTintList(Utils.getColorAttr(getContext(), android.R.attr.textColorPrimary));
-        preference.setIcon(icon);
+        messagingPreference.setIcon(icon);
+    }
 
+    private void updateHowItWorksContent(boolean isSatelliteEligible) {
         /* Composes "How it works" section, which guides how users can use satellite messaging, when
            satellite messaging is included in user's mobile plan, or it'll will be grey out. */
         if (!isSatelliteEligible) {
@@ -185,13 +213,15 @@
             category.setEnabled(false);
             category.setShouldDisableView(true);
         }
+    }
 
+    private void updateFooterContent() {
         // More about satellite messaging
         FooterPreference footerPreference = findPreference(KEY_FOOTER_PREFERENCE);
         if (footerPreference != null) {
             footerPreference.setSummary(
                     getResources().getString(R.string.satellite_setting_summary_more_information,
-                            operatorName));
+                            getSubjectString(), mSimOperatorName));
 
             final String[] link = new String[1];
             link[0] = readSatelliteMoreInfoString(mSubId);
@@ -205,8 +235,9 @@
                         }
                     }
                 });
+
                 footerPreference.setLearnMoreText(
-                        getResources().getString(R.string.more_about_satellite_messaging));
+                        getString(R.string.more_about_satellite_messaging, getDescriptionString()));
             }
         }
     }
@@ -245,6 +276,32 @@
         return bundle.getBoolean(KEY_SATELLITE_ATTACH_SUPPORTED_BOOL, false);
     }
 
+    // This is for a word which first letter is uppercase. e.g. Satellite messaging.
+    private String getSubjectString() {
+        int result;
+        if (com.android.settings.flags.Flags.satelliteOemSettingsUxMigration()) {
+            result = mIsServiceDataType
+                    ? R.string.title_satellite_setting_connectivity
+                    : R.string.satellite_setting_title;
+        } else {
+            result = R.string.satellite_setting_title;
+        }
+        return getString(result);
+    }
+
+    // This is for a word without uppercase letter. e.g. satellite messaging.
+    private String getDescriptionString() {
+        int result;
+        if (com.android.settings.flags.Flags.satelliteOemSettingsUxMigration()) {
+            result = mIsServiceDataType
+                    ? R.string.description_satellite_setting_connectivity
+                    : R.string.description_satellite_setting_messaging;
+        } else {
+            result = R.string.satellite_setting_title;
+        }
+        return getString(result);
+    }
+
     private static void loge(String message) {
         Log.e(TAG, message);
     }
diff --git a/src/com/android/settings/network/telephony/SatelliteSettingPreferenceController.java b/src/com/android/settings/network/telephony/SatelliteSettingPreferenceController.java
index 9ca0294..017d478 100644
--- a/src/com/android/settings/network/telephony/SatelliteSettingPreferenceController.java
+++ b/src/com/android/settings/network/telephony/SatelliteSettingPreferenceController.java
@@ -16,16 +16,25 @@
 
 package com.android.settings.network.telephony;
 
+import static android.telephony.NetworkRegistrationInfo.SERVICE_TYPE_DATA;
+import static android.telephony.NetworkRegistrationInfo.SERVICE_TYPE_SMS;
+
 import android.content.Context;
 import android.content.Intent;
 import android.os.PersistableBundle;
 import android.provider.Settings;
 import android.telephony.CarrierConfigManager;
+import android.telephony.TelephonyCallback;
+import android.telephony.TelephonyManager;
+import android.telephony.satellite.NtnSignalStrength;
 import android.telephony.satellite.SatelliteManager;
 import android.util.Log;
 
 import androidx.annotation.NonNull;
 import androidx.annotation.Nullable;
+import androidx.annotation.VisibleForTesting;
+import androidx.lifecycle.DefaultLifecycleObserver;
+import androidx.lifecycle.LifecycleOwner;
 import androidx.preference.Preference;
 import androidx.preference.PreferenceScreen;
 
@@ -33,28 +42,34 @@
 import com.android.settings.R;
 import com.android.settings.SettingsActivity;
 import com.android.settings.network.CarrierConfigCache;
-import com.android.settingslib.core.lifecycle.LifecycleObserver;
-import com.android.settingslib.core.lifecycle.events.OnStart;
-import com.android.settingslib.core.lifecycle.events.OnStop;
 
+import java.util.Arrays;
+import java.util.List;
 import java.util.Set;
 
 /**
  * Preference controller for "Satellite Setting"
  */
 public class SatelliteSettingPreferenceController extends
-        TelephonyBasePreferenceController implements LifecycleObserver, OnStart, OnStop {
-
+        TelephonyBasePreferenceController implements DefaultLifecycleObserver {
     private static final String TAG = "SatelliteSettingPreferenceController";
 
     CarrierConfigCache mCarrierConfigCache;
     SatelliteManager mSatelliteManager;
-    @Nullable private Boolean mIsSatelliteEligible = null;
+    private TelephonyManager mTelephonyManager = null;
+    @VisibleForTesting
+    final CarrierRoamingNtnModeCallback mCarrierRoamingNtnModeCallback =
+            new CarrierRoamingNtnModeCallback();
+
+    @Nullable
+    private Boolean mIsSatelliteEligible = null;
+    private boolean mIsServiceDataType = false;
 
     public SatelliteSettingPreferenceController(@NonNull Context context, @NonNull String key) {
         super(context, key);
         mCarrierConfigCache = CarrierConfigCache.getInstance(context);
         mSatelliteManager = context.getSystemService(SatelliteManager.class);
+        mTelephonyManager = context.getSystemService(TelephonyManager.class);
     }
 
     @Override
@@ -76,22 +91,31 @@
     }
 
     @Override
-    public void onStart() {
+    public void onResume(@NonNull LifecycleOwner owner) {
+        if (com.android.settings.flags.Flags.satelliteOemSettingsUxMigration()) {
+            mTelephonyManager.registerTelephonyCallback(mContext.getMainExecutor(),
+                    mCarrierRoamingNtnModeCallback);
+        }
     }
 
     @Override
-    public void onStop() {
+    public void onPause(@NonNull LifecycleOwner owner) {
+        if (com.android.settings.flags.Flags.satelliteOemSettingsUxMigration()) {
+            mTelephonyManager.unregisterTelephonyCallback(mCarrierRoamingNtnModeCallback);
+        }
     }
 
     @Override
     public void displayPreference(@NonNull PreferenceScreen screen) {
         super.displayPreference(screen);
+        updateState(screen.findPreference(getPreferenceKey()));
     }
 
     @Override
     public void updateState(@Nullable Preference preference) {
         super.updateState(preference);
         if (preference != null) {
+            mCarrierRoamingNtnModeCallback.mPref = preference;
             updateSummary(preference);
         }
     }
@@ -105,6 +129,7 @@
             // This will setup the Home and Search affordance
             intent.putExtra(SettingsActivity.EXTRA_SHOW_FRAGMENT_AS_SUBSETTING, true);
             intent.putExtra(SatelliteSetting.SUB_ID, mSubId);
+            intent.putExtra(SatelliteSetting.EXTRA_IS_SERVICE_DATA_TYPE, mIsServiceDataType);
             mContext.startActivity(intent);
             return true;
         }
@@ -114,14 +139,20 @@
 
     /**
      * Set subId for Satellite Settings page.
+     *
      * @param subId subscription ID.
      */
     public void init(int subId) {
         logd("init(), subId=" + subId);
         mSubId = subId;
+        mTelephonyManager = mTelephonyManager.createForSubscriptionId(subId);
     }
 
     private void updateSummary(Preference preference) {
+        if (mSatelliteManager == null) {
+            logd("updateSummary - no SatelliteManager");
+            return;
+        }
         try {
             Set<Integer> restrictionReason =
                     mSatelliteManager.getAttachRestrictionReasonsForCarrier(mSubId);
@@ -147,4 +178,46 @@
     private static void loge(String message) {
         Log.e(TAG, message);
     }
+
+    @VisibleForTesting
+    class CarrierRoamingNtnModeCallback extends TelephonyCallback implements
+            TelephonyCallback.CarrierRoamingNtnModeListener {
+        Preference mPref = null;
+
+        @Override
+        public void onCarrierRoamingNtnAvailableServicesChanged(int[] availableServices) {
+            CarrierRoamingNtnModeListener.super.onCarrierRoamingNtnAvailableServicesChanged(
+                    availableServices);
+            List<Integer> availableServicesList = Arrays.stream(availableServices).boxed().toList();
+            boolean isSmsAvailable = availableServicesList.contains(SERVICE_TYPE_SMS);
+            boolean isDataAvailable = availableServicesList.contains(SERVICE_TYPE_DATA);
+            logd("isSmsAvailable : " + isSmsAvailable
+                    + " / isDataAvailable " + isDataAvailable);
+            if (mPref == null) {
+                logd("Satellite preference is not initialized yet");
+                return;
+            }
+            if (isDataAvailable) {
+                mIsServiceDataType = true;
+                mPref.setTitle(R.string.title_satellite_setting_connectivity);
+            } else if (isSmsAvailable) {
+                mPref.setTitle(R.string.satellite_setting_title);
+            }
+        }
+
+        @Override
+        public void onCarrierRoamingNtnEligibleStateChanged(boolean eligible) {
+            // Do nothing
+        }
+
+        @Override
+        public void onCarrierRoamingNtnModeChanged(boolean active) {
+            // Do nothing
+        }
+
+        @Override
+        public void onCarrierRoamingNtnSignalStrengthChanged(NtnSignalStrength ntnSignalStrength) {
+            // Do nothing
+        }
+    }
 }
diff --git a/src/com/android/settings/network/telephony/SatelliteSettingsPreferenceCategoryController.java b/src/com/android/settings/network/telephony/SatelliteSettingsPreferenceCategoryController.java
index 951d9ca..c182059 100644
--- a/src/com/android/settings/network/telephony/SatelliteSettingsPreferenceCategoryController.java
+++ b/src/com/android/settings/network/telephony/SatelliteSettingsPreferenceCategoryController.java
@@ -16,55 +16,127 @@
 
 package com.android.settings.network.telephony;
 
+import static android.telephony.NetworkRegistrationInfo.SERVICE_TYPE_DATA;
+import static android.telephony.NetworkRegistrationInfo.SERVICE_TYPE_SMS;
+
 import android.content.Context;
-import android.os.PersistableBundle;
-import android.telephony.CarrierConfigManager;
-import android.telephony.satellite.SatelliteManager;
+import android.telephony.TelephonyCallback;
+import android.telephony.TelephonyManager;
+import android.telephony.satellite.NtnSignalStrength;
 import android.util.Log;
 
-import com.android.internal.telephony.flags.Flags;
-import com.android.settings.network.CarrierConfigCache;
+import androidx.annotation.NonNull;
+import androidx.annotation.VisibleForTesting;
+import androidx.lifecycle.DefaultLifecycleObserver;
+import androidx.lifecycle.LifecycleOwner;
+import androidx.preference.PreferenceCategory;
+import androidx.preference.PreferenceScreen;
 
-/** Preference controller for Satellite functions in mobile network settings.*/
+import com.android.settings.R;
+import com.android.settings.flags.Flags;
+
+import java.util.Arrays;
+import java.util.List;
+
+/** Preference controller for Satellite functions in mobile network settings. */
 public class SatelliteSettingsPreferenceCategoryController
-        extends TelephonyBasePreferenceController {
+        extends TelephonyBasePreferenceController implements DefaultLifecycleObserver {
     private static final String TAG = "SatelliteSettingsPrefCategoryCon";
 
-    private CarrierConfigCache mCarrierConfigCache;
-    private SatelliteManager mSatelliteManager;
+    private PreferenceCategory mPreferenceCategory;
+    private TelephonyManager mTelephonyManager = null;
+
+    @VisibleForTesting
+    final CarrierRoamingNtnModeCallback mCarrierRoamingNtnModeCallback =
+            new CarrierRoamingNtnModeCallback();
 
     public SatelliteSettingsPreferenceCategoryController(Context context, String key) {
         super(context, key);
-        mCarrierConfigCache = CarrierConfigCache.getInstance(context);
-        mSatelliteManager = context.getSystemService(SatelliteManager.class);
+        setAvailabilityStatus(UNSUPPORTED_ON_DEVICE);
+        mTelephonyManager = context.getSystemService(TelephonyManager.class);
     }
 
     /**
      * Set subId for Satellite Settings category .
+     *
      * @param subId subscription ID.
      */
     public void init(int subId) {
         Log.d(TAG, "init(), subId=" + subId);
         mSubId = subId;
+        mTelephonyManager = mTelephonyManager.createForSubscriptionId(subId);
+    }
+
+    @Override
+    public void displayPreference(PreferenceScreen screen) {
+        super.displayPreference(screen);
+        mPreferenceCategory = screen.findPreference(getPreferenceKey());
+        if (mPreferenceCategory.getPreferenceCount() > 0) {
+            for (int i = 0; i < mPreferenceCategory.getPreferenceCount(); i++) {
+                if (mPreferenceCategory.getPreference(i).isVisible()) {
+                    setAvailabilityStatus(AVAILABLE_UNSEARCHABLE);
+                    break;
+                }
+            }
+        }
     }
 
     @Override
     public int getAvailabilityStatus(int subId) {
-        if (!Flags.carrierEnabledSatelliteFlag()) {
-            Log.d(TAG, "getAvailabilityStatus(" + subId + ") : carrierEnabledSatelliteFlag "
-                    + "is disabled");
-            return UNSUPPORTED_ON_DEVICE;
+        return isAvailable() ? AVAILABLE_UNSEARCHABLE : UNSUPPORTED_ON_DEVICE;
+    }
+
+    @Override
+    public void onResume(@NonNull LifecycleOwner owner) {
+        if (Flags.satelliteOemSettingsUxMigration()) {
+            mTelephonyManager.registerTelephonyCallback(mContext.getMainExecutor(),
+                    mCarrierRoamingNtnModeCallback);
+        }
+    }
+
+    @Override
+    public void onPause(@NonNull LifecycleOwner owner) {
+        if (Flags.satelliteOemSettingsUxMigration()) {
+            mTelephonyManager.unregisterTelephonyCallback(mCarrierRoamingNtnModeCallback);
+        }
+    }
+
+    @VisibleForTesting
+    class CarrierRoamingNtnModeCallback extends TelephonyCallback implements
+            TelephonyCallback.CarrierRoamingNtnModeListener {
+        @Override
+        public void onCarrierRoamingNtnAvailableServicesChanged(int[] availableServices) {
+            CarrierRoamingNtnModeListener.super.onCarrierRoamingNtnAvailableServicesChanged(
+                    availableServices);
+            List<Integer> availableServicesList = Arrays.stream(availableServices).boxed().toList();
+            boolean isSmsAvailable = availableServicesList.contains(SERVICE_TYPE_SMS);
+            boolean isDataAvailable = availableServicesList.contains(SERVICE_TYPE_DATA);
+            Log.i(TAG, "isSmsAvailable : " + isSmsAvailable
+                    + " / isDataAvailable " + isDataAvailable);
+            if (mPreferenceCategory == null) {
+                Log.d(TAG, "Satellite preference category is not initialized yet");
+                return;
+            }
+            if (isDataAvailable) {
+                mPreferenceCategory.setTitle(R.string.category_title_satellite_connectivity);
+            } else if (isSmsAvailable) {
+                mPreferenceCategory.setTitle(R.string.satellite_setting_title);
+            }
         }
 
-        if (mSatelliteManager == null) {
-            Log.d(TAG, "getAvailabilityStatus(" + subId + ") : SatelliteManager is null");
-            return UNSUPPORTED_ON_DEVICE;
+        @Override
+        public void onCarrierRoamingNtnEligibleStateChanged(boolean eligible) {
+            // Do nothing
         }
 
-        final PersistableBundle carrierConfig = mCarrierConfigCache.getConfigForSubId(subId);
-        final boolean isSatelliteAttachSupported = carrierConfig.getBoolean(
-                CarrierConfigManager.KEY_SATELLITE_ATTACH_SUPPORTED_BOOL);
+        @Override
+        public void onCarrierRoamingNtnModeChanged(boolean active) {
+            // Do nothing
+        }
 
-        return isSatelliteAttachSupported ? AVAILABLE : CONDITIONALLY_UNAVAILABLE;
+        @Override
+        public void onCarrierRoamingNtnSignalStrengthChanged(NtnSignalStrength ntnSignalStrength) {
+            // Do nothing
+        }
     }
 }
diff --git a/src/com/android/settings/network/telephony/gsm/AutoSelectPreferenceController.kt b/src/com/android/settings/network/telephony/gsm/AutoSelectPreferenceController.kt
index 67a2356..4bd91b2 100644
--- a/src/com/android/settings/network/telephony/gsm/AutoSelectPreferenceController.kt
+++ b/src/com/android/settings/network/telephony/gsm/AutoSelectPreferenceController.kt
@@ -25,18 +25,22 @@
 import android.telephony.ServiceState
 import android.telephony.SubscriptionManager
 import android.telephony.TelephonyManager
+import android.telephony.satellite.SatelliteManager
+import android.telephony.satellite.SatelliteModemStateCallback
+import android.telephony.satellite.SelectedNbIotSatelliteSubscriptionCallback
+import android.util.Log
 import androidx.annotation.VisibleForTesting
 import androidx.compose.runtime.Composable
 import androidx.compose.runtime.getValue
 import androidx.compose.runtime.remember
 import androidx.compose.runtime.rememberCoroutineScope
 import androidx.compose.ui.res.stringResource
+import androidx.lifecycle.DefaultLifecycleObserver
 import androidx.lifecycle.LifecycleOwner
 import androidx.lifecycle.compose.collectAsStateWithLifecycle
-import androidx.preference.Preference
-import androidx.preference.PreferenceScreen
 import com.android.settings.R
 import com.android.settings.Settings.NetworkSelectActivity
+import com.android.settings.flags.Flags
 import com.android.settings.network.CarrierConfigCache
 import com.android.settings.network.telephony.MobileNetworkUtils
 import com.android.settings.network.telephony.allowedNetworkTypesFlow
@@ -46,8 +50,6 @@
 import com.android.settingslib.spa.framework.util.collectLatestWithLifecycle
 import com.android.settingslib.spa.widget.preference.SwitchPreference
 import com.android.settingslib.spa.widget.preference.SwitchPreferenceModel
-import kotlin.properties.Delegates.notNull
-import kotlin.time.Duration.Companion.seconds
 import kotlinx.coroutines.Dispatchers
 import kotlinx.coroutines.async
 import kotlinx.coroutines.delay
@@ -59,6 +61,7 @@
 import kotlinx.coroutines.flow.stateIn
 import kotlinx.coroutines.launch
 import kotlinx.coroutines.withContext
+import kotlin.time.Duration.Companion.seconds
 
 /**
  * Preference controller for "Auto Select Network"
@@ -73,9 +76,13 @@
     private val getConfigForSubId: (subId: Int) -> PersistableBundle = { subId ->
         CarrierConfigCache.getInstance(context).getConfigForSubId(subId)
     },
-) : ComposePreferenceController(context, key) {
+) : ComposePreferenceController(context, key), DefaultLifecycleObserver {
+
+    private var isSatelliteSessionStarted = false
+    private var isSelectedSubIdForSatellite = false
 
     private lateinit var telephonyManager: TelephonyManager
+    private lateinit var satelliteManager: SatelliteManager
     private val listeners = mutableListOf<OnNetworkSelectModeListener>()
 
     @VisibleForTesting
@@ -83,6 +90,21 @@
 
     private var subId = SubscriptionManager.INVALID_SUBSCRIPTION_ID
 
+    val satelliteModemStateCallback = SatelliteModemStateCallback { state ->
+        isSatelliteSessionStarted = when (state) {
+            SatelliteManager.SATELLITE_MODEM_STATE_OFF,
+            SatelliteManager.SATELLITE_MODEM_STATE_UNAVAILABLE,
+            SatelliteManager.SATELLITE_MODEM_STATE_UNKNOWN -> false
+
+            else -> true
+        }
+    }
+
+    val selectedNbIotSatelliteSubscriptionCallback =
+        SelectedNbIotSatelliteSubscriptionCallback { selectedSubId ->
+            isSelectedSubIdForSatellite = selectedSubId == subId
+        }
+
     /**
      * Initialization based on given subscription id.
      */
@@ -90,7 +112,7 @@
         this.subId = subId
         telephonyManager = mContext.getSystemService(TelephonyManager::class.java)!!
             .createForSubscriptionId(subId)
-
+        satelliteManager = mContext.getSystemService(SatelliteManager::class.java)!!
         return this
     }
 
@@ -117,7 +139,10 @@
         SwitchPreference(object : SwitchPreferenceModel {
             override val title = stringResource(R.string.select_automatically)
             override val summary = { disallowedSummary }
-            override val changeable = { disallowedSummary.isEmpty() }
+            override val changeable = {
+                disallowedSummary.isEmpty()
+                        && !(isSatelliteSessionStarted && isSelectedSubIdForSatellite)
+            }
             override val checked = { isAuto }
             override val onCheckedChange: (Boolean) -> Unit = { newChecked ->
                 if (newChecked) {
@@ -132,6 +157,38 @@
         })
     }
 
+    override fun onStart(owner: LifecycleOwner) {
+        if (Flags.satelliteOemSettingsUxMigration()) {
+            if (satelliteManager != null) {
+                try {
+                    satelliteManager.registerForModemStateChanged(
+                        mContext.mainExecutor, satelliteModemStateCallback
+                    )
+                    satelliteManager.registerForSelectedNbIotSatelliteSubscriptionChanged(
+                        mContext.mainExecutor, selectedNbIotSatelliteSubscriptionCallback
+                    )
+                } catch (e: IllegalStateException) {
+                    Log.w(TAG, "IllegalStateException $e")
+                }
+            }
+        }
+    }
+
+    override fun onStop(owner: LifecycleOwner) {
+        if (Flags.satelliteOemSettingsUxMigration()) {
+            if (satelliteManager != null) {
+                try {
+                    satelliteManager.unregisterForModemStateChanged(satelliteModemStateCallback)
+                    satelliteManager.unregisterForSelectedNbIotSatelliteSubscriptionChanged(
+                        selectedNbIotSatelliteSubscriptionCallback
+                    )
+                } catch (e: IllegalStateException) {
+                    Log.w(TAG, "IllegalStateException $e")
+                }
+            }
+        }
+    }
+
     private suspend fun getDisallowedSummary(serviceState: ServiceState): String =
         withContext(Dispatchers.Default) {
             if (!serviceState.roaming && onlyAutoSelectInHome()) {
@@ -213,6 +270,8 @@
     }
 
     companion object {
+        private const val TAG = "AutoSelectPreferenceController"
+
         private val MINIMUM_DIALOG_TIME = 1.seconds
     }
 }
diff --git a/src/com/android/settings/spa/app/appinfo/AppInfoSettings.kt b/src/com/android/settings/spa/app/appinfo/AppInfoSettings.kt
index ddddd8c..78fb8df 100644
--- a/src/com/android/settings/spa/app/appinfo/AppInfoSettings.kt
+++ b/src/com/android/settings/spa/app/appinfo/AppInfoSettings.kt
@@ -34,6 +34,7 @@
 import com.android.settings.R
 import com.android.settings.applications.AppInfoBase
 import com.android.settings.applications.appinfo.AppInfoDashboardFragment
+import com.android.settings.development.Enable16kUtils
 import com.android.settings.flags.Flags
 import com.android.settings.spa.SpaActivity.Companion.startSpaActivity
 import com.android.settings.spa.app.appcompat.UserAspectRatioAppPreference
@@ -169,6 +170,7 @@
             InteractAcrossProfilesDetailsPreference(app)
             AlarmsAndRemindersAppListProvider.InfoPageEntryItem(app)
             WriteSystemPreferencesAppListProvider.InfoPageEntryItem(app)
+            Enable16KbAppCompatPreference(app)
         }
 
         Category(title = stringResource(R.string.app_install_details_group_title)) {
diff --git a/src/com/android/settings/spa/app/appinfo/Enable16KbAppCompatPreference.kt b/src/com/android/settings/spa/app/appinfo/Enable16KbAppCompatPreference.kt
new file mode 100644
index 0000000..b6606cf
--- /dev/null
+++ b/src/com/android/settings/spa/app/appinfo/Enable16KbAppCompatPreference.kt
@@ -0,0 +1,81 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.settings.spa.app.appinfo
+
+import android.content.Context
+import android.content.pm.ApplicationInfo
+import android.util.Log
+import androidx.compose.runtime.Composable
+import androidx.compose.runtime.remember
+import androidx.compose.ui.platform.LocalContext
+import androidx.lifecycle.compose.collectAsStateWithLifecycle
+import com.android.settings.R
+import com.android.settings.development.Enable16kUtils
+import com.android.settings.flags.Flags
+import com.android.settingslib.spa.framework.compose.OverridableFlow
+import com.android.settingslib.spa.widget.preference.SwitchPreference
+import com.android.settingslib.spa.widget.preference.SwitchPreferenceModel
+import kotlinx.coroutines.flow.flow
+
+@Composable
+fun Enable16KbAppCompatPreference(
+    app: ApplicationInfo
+) {
+    val context = LocalContext.current
+    val presenter = remember(app) { Enable16KbAppCompatSwitchPresenter(context, app) }
+    if (!presenter.isAvailable()) return
+
+    val isCheckedState = presenter.isCheckedFlow.collectAsStateWithLifecycle(initialValue = null)
+    SwitchPreference(remember {
+        object : SwitchPreferenceModel {
+            override val title =
+                context.getString(R.string.enable_16k_app_compat_title)
+
+            override val summary = {
+                context.getString(R.string.enable_16k_app_compat_details)
+            }
+
+            override val checked = {
+                isCheckedState.value
+            }
+
+            override val onCheckedChange = presenter::onCheckedChange
+        }
+    })
+}
+
+private class Enable16KbAppCompatSwitchPresenter(context: Context, private val app: ApplicationInfo) {
+    private val packageManager = context.packageManager
+    fun isAvailable(): Boolean {
+        return Enable16kUtils.isUsing16kbPages() && Flags.pageSizeAppCompatSetting()
+    }
+
+    private val isChecked = OverridableFlow(flow {
+        emit(packageManager.isPageSizeCompatEnabled(app.packageName))
+    })
+
+    val isCheckedFlow = isChecked.flow
+    fun onCheckedChange(newChecked: Boolean) {
+        try {
+            packageManager.setPageSizeAppCompatFlagsSettingsOverride(app.packageName, newChecked)
+            isChecked.override(newChecked)
+        } catch (e: RuntimeException) {
+            Log.e("Enable16KbAppCompat", "Failed to set" +
+                    "setPageSizeAppCompatModeSettingsOverride", e);
+        }
+    }
+}
diff --git a/tests/robotests/src/com/android/settings/accessibility/CaptionHelperTest.java b/tests/robotests/src/com/android/settings/accessibility/CaptionHelperTest.java
index c1a1799..7aaf71b 100644
--- a/tests/robotests/src/com/android/settings/accessibility/CaptionHelperTest.java
+++ b/tests/robotests/src/com/android/settings/accessibility/CaptionHelperTest.java
@@ -26,6 +26,9 @@
 
 import android.content.ContentResolver;
 import android.content.Context;
+import android.platform.test.annotations.DisableFlags;
+import android.platform.test.annotations.EnableFlags;
+import android.platform.test.flag.junit.SetFlagsRule;
 import android.provider.Settings;
 import android.view.View;
 import android.view.accessibility.CaptioningManager;
@@ -35,6 +38,7 @@
 
 import com.android.internal.widget.SubtitleView;
 import com.android.settings.R;
+import com.android.settings.core.BasePreferenceController;
 
 import org.junit.Before;
 import org.junit.Rule;
@@ -54,6 +58,8 @@
 
     @Rule
     public final MockitoRule mMockitoRule = MockitoJUnit.rule();
+    @Rule
+    public final SetFlagsRule mSetFlagsRule = new SetFlagsRule();
     @Mock
     private CaptioningManager mCaptioningManager;
     @Mock
@@ -182,4 +188,40 @@
                 Settings.Secure.ACCESSIBILITY_CAPTIONING_PRESET, 0);
         assertThat(style).isEqualTo(CaptionStyle.PRESET_CUSTOM);
     }
+
+    @Test
+    @DisableFlags(Flags.FLAG_FIX_A11Y_SETTINGS_SEARCH)
+    public void getAvailabilityStatus_flagOff_customCaption_shouldReturnAvailable() {
+        when(mCaptioningManager.getRawUserStyle()).thenReturn(CaptionStyle.PRESET_CUSTOM);
+
+        assertThat(mCaptionHelper.getCustomCaptionAvailability())
+                .isEqualTo(BasePreferenceController.AVAILABLE);
+    }
+
+    @Test
+    @DisableFlags(Flags.FLAG_FIX_A11Y_SETTINGS_SEARCH)
+    public void getAvailabilityStatus_flagOff_notCustom_shouldReturnAvailable() {
+        when(mCaptioningManager.getRawUserStyle()).thenReturn(0);
+
+        assertThat(mCaptionHelper.getCustomCaptionAvailability())
+                .isEqualTo(BasePreferenceController.AVAILABLE);
+    }
+
+    @Test
+    @EnableFlags(Flags.FLAG_FIX_A11Y_SETTINGS_SEARCH)
+    public void getAvailabilityStatus_customCaption_shouldReturnAvailable() {
+        when(mCaptioningManager.getRawUserStyle()).thenReturn(CaptionStyle.PRESET_CUSTOM);
+
+        assertThat(mCaptionHelper.getCustomCaptionAvailability())
+                .isEqualTo(BasePreferenceController.AVAILABLE);
+    }
+
+    @Test
+    @EnableFlags(Flags.FLAG_FIX_A11Y_SETTINGS_SEARCH)
+    public void getAvailabilityStatus_notCustom_shouldReturnUnsearchable() {
+        when(mCaptioningManager.getRawUserStyle()).thenReturn(0);
+
+        assertThat(mCaptionHelper.getCustomCaptionAvailability())
+                .isEqualTo(BasePreferenceController.AVAILABLE_UNSEARCHABLE);
+    }
 }
diff --git a/tests/robotests/src/com/android/settings/accessibility/CaptioningBackgroundColorControllerTest.java b/tests/robotests/src/com/android/settings/accessibility/CaptioningBackgroundColorControllerTest.java
index e847f43..bc7c033 100644
--- a/tests/robotests/src/com/android/settings/accessibility/CaptioningBackgroundColorControllerTest.java
+++ b/tests/robotests/src/com/android/settings/accessibility/CaptioningBackgroundColorControllerTest.java
@@ -32,8 +32,6 @@
 import androidx.preference.PreferenceScreen;
 import androidx.test.core.app.ApplicationProvider;
 
-import com.android.settings.core.BasePreferenceController;
-
 import org.junit.Before;
 import org.junit.Rule;
 import org.junit.Test;
@@ -71,12 +69,6 @@
     }
 
     @Test
-    public void getAvailabilityStatus_shouldReturnAvailable() {
-        assertThat(mController.getAvailabilityStatus())
-                .isEqualTo(BasePreferenceController.AVAILABLE);
-    }
-
-    @Test
     public void getSummary_defaultValue_shouldReturnBlack() {
         mController.displayPreference(mScreen);
 
diff --git a/tests/robotests/src/com/android/settings/accessibility/CaptioningBackgroundOpacityControllerTest.java b/tests/robotests/src/com/android/settings/accessibility/CaptioningBackgroundOpacityControllerTest.java
index 5036ba0..08a8a86 100644
--- a/tests/robotests/src/com/android/settings/accessibility/CaptioningBackgroundOpacityControllerTest.java
+++ b/tests/robotests/src/com/android/settings/accessibility/CaptioningBackgroundOpacityControllerTest.java
@@ -31,8 +31,6 @@
 import androidx.preference.PreferenceScreen;
 import androidx.test.core.app.ApplicationProvider;
 
-import com.android.settings.core.BasePreferenceController;
-
 import org.junit.Before;
 import org.junit.Rule;
 import org.junit.Test;
@@ -70,12 +68,6 @@
     }
 
     @Test
-    public void getAvailabilityStatus_shouldReturnAvailable() {
-        assertThat(mController.getAvailabilityStatus())
-                .isEqualTo(BasePreferenceController.AVAILABLE);
-    }
-
-    @Test
     public void getSummary_defaultValue_shouldReturnNonTransparent() {
         mController.displayPreference(mScreen);
 
diff --git a/tests/robotests/src/com/android/settings/accessibility/CaptioningCustomControllerTest.java b/tests/robotests/src/com/android/settings/accessibility/CaptioningCustomControllerTest.java
index e0e5d49..37ad3f8 100644
--- a/tests/robotests/src/com/android/settings/accessibility/CaptioningCustomControllerTest.java
+++ b/tests/robotests/src/com/android/settings/accessibility/CaptioningCustomControllerTest.java
@@ -23,9 +23,6 @@
 
 import android.content.ContentResolver;
 import android.content.Context;
-import android.platform.test.annotations.DisableFlags;
-import android.platform.test.annotations.EnableFlags;
-import android.platform.test.flag.junit.SetFlagsRule;
 import android.provider.Settings;
 import android.view.accessibility.CaptioningManager.CaptionStyle;
 
@@ -33,8 +30,6 @@
 import androidx.preference.PreferenceScreen;
 import androidx.test.core.app.ApplicationProvider;
 
-import com.android.settings.core.BasePreferenceController;
-
 import org.junit.Before;
 import org.junit.Rule;
 import org.junit.Test;
@@ -52,8 +47,6 @@
 
     @Rule
     public final MockitoRule mMockitoRule = MockitoJUnit.rule();
-    @Rule
-    public final SetFlagsRule mSetFlagsRule = new SetFlagsRule();
     @Mock
     private PreferenceScreen mScreen;
     @Mock
@@ -62,45 +55,17 @@
     private ContentResolver mContentResolver;
     private CaptioningCustomController mController;
     private Preference mPreference;
-    private CaptionHelper mCaptionHelper;
 
     @Before
     public void setUp() {
         mContentResolver = mContext.getContentResolver();
-        mCaptionHelper = new CaptionHelper(mContext);
-        mController = new CaptioningCustomController(mContext, PREF_KEY, mCaptionHelper,
+        mController = new CaptioningCustomController(mContext, PREF_KEY,
                 mAccessibilitySettingsContentObserver);
         mPreference = new Preference(mContext);
         when(mScreen.findPreference(mController.getPreferenceKey())).thenReturn(mPreference);
     }
 
     @Test
-    @DisableFlags(Flags.FLAG_FIX_A11Y_SETTINGS_SEARCH)
-    public void getAvailabilityStatus_shouldReturnAvailable() {
-        assertThat(mController.getAvailabilityStatus())
-                .isEqualTo(BasePreferenceController.AVAILABLE);
-    }
-
-    @Test
-    @EnableFlags(Flags.FLAG_FIX_A11Y_SETTINGS_SEARCH)
-    public void getAvailabilityStatus_customCaption_shouldReturnAvailable() {
-        mCaptionHelper.setRawUserStyle(CaptionStyle.PRESET_CUSTOM);
-
-        assertThat(mController.getAvailabilityStatus())
-                .isEqualTo(BasePreferenceController.AVAILABLE);
-    }
-
-    @Test
-    @EnableFlags(Flags.FLAG_FIX_A11Y_SETTINGS_SEARCH)
-    public void getAvailabilityStatus_notCustom_shouldReturnUnsearchable() {
-        mCaptionHelper.setRawUserStyle(0);
-
-        assertThat(mController.getAvailabilityStatus())
-                .isEqualTo(BasePreferenceController.AVAILABLE_UNSEARCHABLE);
-    }
-
-
-    @Test
     public void displayPreference_byDefault_shouldIsInvisible() {
         mController.displayPreference(mScreen);
 
diff --git a/tests/robotests/src/com/android/settings/accessibility/CaptioningEdgeColorControllerTest.java b/tests/robotests/src/com/android/settings/accessibility/CaptioningEdgeColorControllerTest.java
index c55e087..21d6dae 100644
--- a/tests/robotests/src/com/android/settings/accessibility/CaptioningEdgeColorControllerTest.java
+++ b/tests/robotests/src/com/android/settings/accessibility/CaptioningEdgeColorControllerTest.java
@@ -31,8 +31,6 @@
 import androidx.preference.PreferenceScreen;
 import androidx.test.core.app.ApplicationProvider;
 
-import com.android.settings.core.BasePreferenceController;
-
 import org.junit.Before;
 import org.junit.Rule;
 import org.junit.Test;
@@ -68,12 +66,6 @@
     }
 
     @Test
-    public void getAvailabilityStatus_shouldReturnAvailable() {
-        assertThat(mController.getAvailabilityStatus())
-                .isEqualTo(BasePreferenceController.AVAILABLE);
-    }
-
-    @Test
     public void getSummary_defaultValue_shouldReturnBlack() {
         mController.displayPreference(mScreen);
 
diff --git a/tests/robotests/src/com/android/settings/accessibility/CaptioningEdgeTypeControllerTest.java b/tests/robotests/src/com/android/settings/accessibility/CaptioningEdgeTypeControllerTest.java
index 354115f..0aab447 100644
--- a/tests/robotests/src/com/android/settings/accessibility/CaptioningEdgeTypeControllerTest.java
+++ b/tests/robotests/src/com/android/settings/accessibility/CaptioningEdgeTypeControllerTest.java
@@ -32,8 +32,6 @@
 import androidx.preference.PreferenceScreen;
 import androidx.test.core.app.ApplicationProvider;
 
-import com.android.settings.core.BasePreferenceController;
-
 import org.junit.Before;
 import org.junit.Rule;
 import org.junit.Test;
@@ -70,12 +68,6 @@
     }
 
     @Test
-    public void getAvailabilityStatus_shouldReturnAvailable() {
-        assertThat(mController.getAvailabilityStatus())
-                .isEqualTo(BasePreferenceController.AVAILABLE);
-    }
-
-    @Test
     public void getSummary_defaultValue_shouldReturnNone() {
         mController.displayPreference(mScreen);
 
diff --git a/tests/robotests/src/com/android/settings/accessibility/CaptioningFontSizeControllerTest.java b/tests/robotests/src/com/android/settings/accessibility/CaptioningFontSizeControllerTest.java
index b00d8d8..c222d3f 100644
--- a/tests/robotests/src/com/android/settings/accessibility/CaptioningFontSizeControllerTest.java
+++ b/tests/robotests/src/com/android/settings/accessibility/CaptioningFontSizeControllerTest.java
@@ -22,7 +22,6 @@
 import static com.google.common.truth.Truth.assertThat;
 
 import static org.mockito.Mockito.when;
-
 import static org.robolectric.Shadows.shadowOf;
 
 import android.content.Context;
diff --git a/tests/robotests/src/com/android/settings/accessibility/CaptioningForegroundColorControllerTest.java b/tests/robotests/src/com/android/settings/accessibility/CaptioningForegroundColorControllerTest.java
index 9e9c926..59364cd 100644
--- a/tests/robotests/src/com/android/settings/accessibility/CaptioningForegroundColorControllerTest.java
+++ b/tests/robotests/src/com/android/settings/accessibility/CaptioningForegroundColorControllerTest.java
@@ -32,8 +32,6 @@
 import androidx.preference.PreferenceScreen;
 import androidx.test.core.app.ApplicationProvider;
 
-import com.android.settings.core.BasePreferenceController;
-
 import org.junit.Before;
 import org.junit.Rule;
 import org.junit.Test;
@@ -71,12 +69,6 @@
     }
 
     @Test
-    public void getAvailabilityStatus_shouldReturnAvailable() {
-        assertThat(mController.getAvailabilityStatus())
-                .isEqualTo(BasePreferenceController.AVAILABLE);
-    }
-
-    @Test
     public void getSummary_defaultValue_shouldReturnWhite() {
         mController.displayPreference(mScreen);
 
diff --git a/tests/robotests/src/com/android/settings/accessibility/CaptioningForegroundOpacityControllerTest.java b/tests/robotests/src/com/android/settings/accessibility/CaptioningForegroundOpacityControllerTest.java
index a88b5f5..6aaa4a7 100644
--- a/tests/robotests/src/com/android/settings/accessibility/CaptioningForegroundOpacityControllerTest.java
+++ b/tests/robotests/src/com/android/settings/accessibility/CaptioningForegroundOpacityControllerTest.java
@@ -31,8 +31,6 @@
 import androidx.preference.PreferenceScreen;
 import androidx.test.core.app.ApplicationProvider;
 
-import com.android.settings.core.BasePreferenceController;
-
 import org.junit.Before;
 import org.junit.Rule;
 import org.junit.Test;
@@ -70,12 +68,6 @@
     }
 
     @Test
-    public void getAvailabilityStatus_shouldReturnAvailable() {
-        assertThat(mController.getAvailabilityStatus())
-                .isEqualTo(BasePreferenceController.AVAILABLE);
-    }
-
-    @Test
     public void getSummary_defaultValue_shouldReturnNonTransparent() {
         mController.displayPreference(mScreen);
 
diff --git a/tests/robotests/src/com/android/settings/accessibility/CaptioningTypefaceControllerTest.java b/tests/robotests/src/com/android/settings/accessibility/CaptioningTypefaceControllerTest.java
index aa7d3eb..b029f3f 100644
--- a/tests/robotests/src/com/android/settings/accessibility/CaptioningTypefaceControllerTest.java
+++ b/tests/robotests/src/com/android/settings/accessibility/CaptioningTypefaceControllerTest.java
@@ -32,7 +32,6 @@
 import androidx.test.core.app.ApplicationProvider;
 
 import com.android.settings.R;
-import com.android.settings.core.BasePreferenceController;
 
 import org.junit.Before;
 import org.junit.Rule;
@@ -71,12 +70,6 @@
     }
 
     @Test
-    public void getAvailabilityStatus_shouldReturnAvailable() {
-        assertThat(mController.getAvailabilityStatus())
-                .isEqualTo(BasePreferenceController.AVAILABLE);
-    }
-
-    @Test
     public void updateState_byDefault_shouldReturnDefault() {
         mController.updateState(mPreference);
 
diff --git a/tests/robotests/src/com/android/settings/accessibility/CaptioningWindowColorControllerTest.java b/tests/robotests/src/com/android/settings/accessibility/CaptioningWindowColorControllerTest.java
index e39c57e..2e276c5 100644
--- a/tests/robotests/src/com/android/settings/accessibility/CaptioningWindowColorControllerTest.java
+++ b/tests/robotests/src/com/android/settings/accessibility/CaptioningWindowColorControllerTest.java
@@ -24,8 +24,6 @@
 import static org.mockito.Mockito.when;
 
 import android.content.Context;
-import android.platform.test.annotations.DisableFlags;
-import android.platform.test.annotations.EnableFlags;
 import android.platform.test.flag.junit.SetFlagsRule;
 import android.provider.Settings;
 import android.util.AttributeSet;
@@ -36,7 +34,6 @@
 import androidx.test.core.app.ApplicationProvider;
 
 import com.android.settings.R;
-import com.android.settings.core.BasePreferenceController;
 
 import org.junit.Before;
 import org.junit.Rule;
@@ -64,13 +61,11 @@
     private CaptioningWindowColorController mController;
     private ColorPreference mPreference;
     private ShadowCaptioningManager mShadowCaptioningManager;
-    private CaptionHelper mCaptionHelper;
 
     @Before
     public void setUp() {
-        mCaptionHelper = new CaptionHelper(mContext);
         mController = new CaptioningWindowColorController(
-                mContext, "captioning_window_color", mCaptionHelper);
+                mContext, "captioning_window_color");
         final AttributeSet attributeSet = Robolectric.buildAttributeSet().build();
         mPreference = new ColorPreference(mContext, attributeSet);
         when(mScreen.findPreference(mController.getPreferenceKey())).thenReturn(mPreference);
@@ -79,31 +74,6 @@
     }
 
     @Test
-    @DisableFlags(Flags.FLAG_FIX_A11Y_SETTINGS_SEARCH)
-    public void getAvailabilityStatus_shouldReturnAvailable() {
-        assertThat(mController.getAvailabilityStatus())
-                .isEqualTo(BasePreferenceController.AVAILABLE);
-    }
-
-    @Test
-    @EnableFlags(Flags.FLAG_FIX_A11Y_SETTINGS_SEARCH)
-    public void getAvailabilityStatus_customCaption_shouldReturnAvailable() {
-        mCaptionHelper.setRawUserStyle(CaptionStyle.PRESET_CUSTOM);
-
-        assertThat(mController.getAvailabilityStatus())
-                .isEqualTo(BasePreferenceController.AVAILABLE);
-    }
-
-    @Test
-    @EnableFlags(Flags.FLAG_FIX_A11Y_SETTINGS_SEARCH)
-    public void getAvailabilityStatus_noCustom_shouldReturnUnsearchable() {
-        mCaptionHelper.setRawUserStyle(0);
-
-        assertThat(mController.getAvailabilityStatus())
-                .isEqualTo(BasePreferenceController.AVAILABLE_UNSEARCHABLE);
-    }
-
-    @Test
     public void getSummary_defaultValue_shouldReturnNone() {
         mController.displayPreference(mScreen);
 
diff --git a/tests/robotests/src/com/android/settings/accessibility/CaptioningWindowOpacityControllerTest.java b/tests/robotests/src/com/android/settings/accessibility/CaptioningWindowOpacityControllerTest.java
index 2b41eb0..aae53d0 100644
--- a/tests/robotests/src/com/android/settings/accessibility/CaptioningWindowOpacityControllerTest.java
+++ b/tests/robotests/src/com/android/settings/accessibility/CaptioningWindowOpacityControllerTest.java
@@ -24,8 +24,6 @@
 import static org.mockito.Mockito.when;
 
 import android.content.Context;
-import android.platform.test.annotations.DisableFlags;
-import android.platform.test.annotations.EnableFlags;
 import android.platform.test.flag.junit.SetFlagsRule;
 import android.provider.Settings;
 import android.util.AttributeSet;
@@ -34,8 +32,6 @@
 import androidx.preference.PreferenceScreen;
 import androidx.test.core.app.ApplicationProvider;
 
-import com.android.settings.core.BasePreferenceController;
-
 import org.junit.Before;
 import org.junit.Rule;
 import org.junit.Test;
@@ -62,13 +58,11 @@
     private CaptioningWindowOpacityController mController;
     private ColorPreference mPreference;
     private ShadowCaptioningManager mShadowCaptioningManager;
-    private CaptionHelper mCaptionHelper;
 
     @Before
     public void setUp() {
-        mCaptionHelper = new CaptionHelper(mContext);
         mController = new CaptioningWindowOpacityController(
-                mContext, "captioning_window_opacity", mCaptionHelper);
+                mContext, "captioning_window_opacity");
         final AttributeSet attributeSet = Robolectric.buildAttributeSet().build();
         mPreference = new ColorPreference(mContext, attributeSet);
         when(mScreen.findPreference(mController.getPreferenceKey())).thenReturn(mPreference);
@@ -77,31 +71,6 @@
     }
 
     @Test
-    @DisableFlags(Flags.FLAG_FIX_A11Y_SETTINGS_SEARCH)
-    public void getAvailabilityStatus_shouldReturnAvailable() {
-        assertThat(mController.getAvailabilityStatus())
-                .isEqualTo(BasePreferenceController.AVAILABLE);
-    }
-
-    @Test
-    @EnableFlags(Flags.FLAG_FIX_A11Y_SETTINGS_SEARCH)
-    public void getAvailabilityStatus_customCaption_shouldReturnAvailable() {
-        mCaptionHelper.setRawUserStyle(CaptioningManager.CaptionStyle.PRESET_CUSTOM);
-
-        assertThat(mController.getAvailabilityStatus()).isEqualTo(
-                BasePreferenceController.AVAILABLE);
-    }
-
-    @Test
-    @EnableFlags(Flags.FLAG_FIX_A11Y_SETTINGS_SEARCH)
-    public void getAvailabilityStatus_notCustom_shouldReturnUnsearchable() {
-        mCaptionHelper.setRawUserStyle(0);
-
-        assertThat(mController.getAvailabilityStatus()).isEqualTo(
-                BasePreferenceController.AVAILABLE_UNSEARCHABLE);
-    }
-
-    @Test
     public void getSummary_defaultValue_shouldReturnNonTransparent() {
         mController.displayPreference(mScreen);
 
diff --git a/tests/robotests/src/com/android/settings/bluetooth/BluetoothDetailsCompanionAppsControllerTest.java b/tests/robotests/src/com/android/settings/bluetooth/BluetoothDetailsCompanionAppsControllerTest.java
index d9054a8..cb891a2 100644
--- a/tests/robotests/src/com/android/settings/bluetooth/BluetoothDetailsCompanionAppsControllerTest.java
+++ b/tests/robotests/src/com/android/settings/bluetooth/BluetoothDetailsCompanionAppsControllerTest.java
@@ -104,7 +104,6 @@
                 associationId,
                 /* userId */ 0,
                 packageName,
-                /* tag */ null,
                 MacAddress.fromString(mCachedDevice.getAddress()),
                 /* displayName */ null,
                 /* deviceProfile */ "",
@@ -116,7 +115,8 @@
                 /* timeApprovedMs */ System.currentTimeMillis(),
                 /* lastTimeConnected */ Long.MAX_VALUE,
                 /* systemDataSyncFlags */ -1,
-                /* deviceIcon */ null);
+                /* deviceIcon */ null,
+                /* deviceId */ null);
 
         mAssociations.add(association);
         showScreen(mController);
diff --git a/tests/robotests/src/com/android/settings/fuelgauge/BatteryHeaderPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/fuelgauge/BatteryHeaderPreferenceControllerTest.java
index fdb075d..44d386f 100644
--- a/tests/robotests/src/com/android/settings/fuelgauge/BatteryHeaderPreferenceControllerTest.java
+++ b/tests/robotests/src/com/android/settings/fuelgauge/BatteryHeaderPreferenceControllerTest.java
@@ -17,31 +17,21 @@
 import static com.google.common.truth.Truth.assertThat;
 
 import static org.mockito.ArgumentMatchers.any;
-import static org.mockito.ArgumentMatchers.eq;
 import static org.mockito.Mockito.doReturn;
-import static org.mockito.Mockito.never;
 import static org.mockito.Mockito.spy;
 import static org.mockito.Mockito.verify;
-import static org.mockito.Mockito.verifyNoInteractions;
 import static org.mockito.Mockito.when;
 
 import android.content.Context;
 import android.content.Intent;
 import android.hardware.usb.UsbManager;
-import android.hardware.usb.UsbPort;
-import android.hardware.usb.UsbPortStatus;
 import android.os.BatteryManager;
-import android.os.PowerManager;
-import android.os.SystemProperties;
 
+import androidx.lifecycle.Lifecycle;
+import androidx.lifecycle.LifecycleOwner;
 import androidx.preference.PreferenceScreen;
 
 import com.android.settings.core.BasePreferenceController;
-import com.android.settings.fuelgauge.batterytip.tips.BatteryTip;
-import com.android.settings.fuelgauge.batterytip.tips.LowBatteryTip;
-import com.android.settings.fuelgauge.batterytip.tips.SmartBatteryTip;
-import com.android.settings.testutils.BatteryTestUtils;
-import com.android.settings.testutils.FakeFeatureFactory;
 import com.android.settings.testutils.shadow.ShadowEntityHeaderController;
 import com.android.settings.testutils.shadow.ShadowUtils;
 import com.android.settings.widget.EntityHeaderController;
@@ -56,10 +46,9 @@
 import org.mockito.MockitoAnnotations;
 import org.robolectric.RobolectricTestRunner;
 import org.robolectric.RuntimeEnvironment;
-import org.robolectric.Shadows;
 import org.robolectric.annotation.Config;
-import org.robolectric.shadows.ShadowPowerManager;
 
+// LINT.IfChange
 @RunWith(RobolectricTestRunner.class)
 @Config(shadows = {ShadowEntityHeaderController.class, ShadowUtils.class})
 public class BatteryHeaderPreferenceControllerTest {
@@ -67,23 +56,17 @@
     private static final String PREF_KEY = "battery_header";
     private static final int BATTERY_LEVEL = 60;
     private static final int BATTERY_MAX_LEVEL = 100;
-    private static final String TIME_LEFT = "2h30min";
-    private static final String BATTERY_STATUS = "Charging";
 
     @Mock private PreferenceScreen mPreferenceScreen;
-    @Mock private BatteryInfo mBatteryInfo;
+    @Mock private BatteryBroadcastReceiver mBatteryBroadcastReceiver;
     @Mock private EntityHeaderController mEntityHeaderController;
-    @Mock private UsageProgressBarPreference mBatteryUsageProgressBarPref;
-    @Mock private BatteryStatusFeatureProvider mBatteryStatusFeatureProvider;
-    @Mock private UsbPort mUsbPort;
+    @Mock private UsageProgressBarPreference mBatteryUsageProgressBarPreference;
     @Mock private UsbManager mUsbManager;
-    @Mock private UsbPortStatus mUsbPortStatus;
+    @Mock private LifecycleOwner mLifecycleOwner;
 
     private BatteryHeaderPreferenceController mController;
     private Context mContext;
-    private ShadowPowerManager mShadowPowerManager;
     private Intent mBatteryIntent;
-    private FakeFeatureFactory mFactory;
 
     @Before
     public void setUp() {
@@ -99,18 +82,12 @@
         mBatteryIntent.putExtra(BatteryManager.EXTRA_PLUGGED, 1);
         doReturn(mBatteryIntent).when(mContext).registerReceiver(any(), any());
 
-        doReturn(mBatteryUsageProgressBarPref)
+        doReturn(mBatteryUsageProgressBarPreference)
                 .when(mPreferenceScreen)
-                .findPreference(BatteryHeaderPreferenceController.KEY_BATTERY_HEADER);
-
-        mBatteryInfo.batteryLevel = BATTERY_LEVEL;
-
-        mShadowPowerManager = Shadows.shadowOf(mContext.getSystemService(PowerManager.class));
-        mFactory = FakeFeatureFactory.setupForTest();
+                .findPreference(PREF_KEY);
 
         mController = spy(new BatteryHeaderPreferenceController(mContext, PREF_KEY));
-        mController.mBatteryUsageProgressBarPref = mBatteryUsageProgressBarPref;
-        mController.mBatteryStatusFeatureProvider = mBatteryStatusFeatureProvider;
+        mController.mBatteryUsageProgressBarPreference = mBatteryUsageProgressBarPreference;
 
         BatteryUtils.setChargingStringV2Enabled(null);
     }
@@ -122,382 +99,44 @@
     }
 
     @Test
+    public void onStateChanged_onCreate_receiverCreated() {
+        mController.onStateChanged(mLifecycleOwner,  Lifecycle.Event.ON_CREATE);
+
+        assertThat(mController.mBatteryBroadcastReceiver).isNotNull();
+    }
+
+    @Test
+    public void onStateChanged_onStart_receiverRegistered() {
+        mController.mBatteryBroadcastReceiver = mBatteryBroadcastReceiver;
+
+        mController.onStateChanged(mLifecycleOwner,  Lifecycle.Event.ON_START);
+
+        verify(mBatteryBroadcastReceiver).register();
+    }
+
+    @Test
+    public void onStateChanged_onStop_receiverUnregistered() {
+        mController.mBatteryBroadcastReceiver = mBatteryBroadcastReceiver;
+
+        mController.onStateChanged(mLifecycleOwner,  Lifecycle.Event.ON_STOP);
+
+        verify(mBatteryBroadcastReceiver).unRegister();
+    }
+
+    @Test
     public void displayPreference_displayBatteryLevel() {
         mController.displayPreference(mPreferenceScreen);
 
-        verify(mBatteryUsageProgressBarPref).setUsageSummary(formatBatteryPercentageText());
-        verify(mBatteryUsageProgressBarPref).setPercent(BATTERY_LEVEL, BATTERY_MAX_LEVEL);
-    }
-
-    @Test
-    public void updatePreference_hasRemainingTime_showRemainingLabel() {
-        mBatteryInfo.remainingLabel = TIME_LEFT;
-
-        mController.updateHeaderPreference(mBatteryInfo);
-
-        verify(mBatteryUsageProgressBarPref).setBottomSummary(mBatteryInfo.remainingLabel);
-    }
-
-    @Test
-    public void updatePreference_updateBatteryInfo() {
-        setChargingState(/* isDischarging */ true, /* updatedByStatusFeature */ false);
-
-        mController.updateHeaderPreference(mBatteryInfo);
-
-        verify(mBatteryUsageProgressBarPref).setUsageSummary(formatBatteryPercentageText());
-        verify(mBatteryUsageProgressBarPref).setBottomSummary(mBatteryInfo.remainingLabel);
-        verify(mBatteryUsageProgressBarPref).setPercent(BATTERY_LEVEL, BATTERY_MAX_LEVEL);
-    }
-
-    @Test
-    public void updatePreference_noRemainingTime_showStatusLabel() {
-        mBatteryInfo.remainingLabel = null;
-        mBatteryInfo.statusLabel = BATTERY_STATUS;
-
-        mController.updateHeaderPreference(mBatteryInfo);
-
-        verify(mBatteryUsageProgressBarPref).setBottomSummary(BATTERY_STATUS);
-    }
-
-    @Test
-    public void updatePreference_statusAnomalous_showStatusLabel() {
-        mBatteryInfo.remainingLabel = TIME_LEFT;
-        mBatteryInfo.statusLabel = BATTERY_STATUS;
-        mBatteryInfo.batteryStatus = BatteryManager.BATTERY_STATUS_NOT_CHARGING;
-
-        mController.updateHeaderPreference(mBatteryInfo);
-
-        verify(mBatteryUsageProgressBarPref).setBottomSummary(BATTERY_STATUS);
-    }
-
-    @Test
-    public void updatePreference_charging_showFullText() {
-        setChargingState(/* isDischarging */ false, /* updatedByStatusFeature */ false);
-
-        mController.updateHeaderPreference(mBatteryInfo);
-
-        final String expectedResult = BATTERY_STATUS + " • " + TIME_LEFT;
-        verify(mBatteryUsageProgressBarPref).setBottomSummary(expectedResult);
-    }
-
-    @Test
-    public void updatePreference_powerSaverOn_showPowerSaverOn() {
-        setChargingState(/* isDischarging */ true, /* updatedByStatusFeature */ false);
-        mShadowPowerManager.setIsPowerSaveMode(true);
-
-        mController.updateHeaderPreference(mBatteryInfo);
-
-        final String expectedResult = "Battery Saver on • " + TIME_LEFT;
-        verify(mBatteryUsageProgressBarPref).setBottomSummary(expectedResult);
-    }
-
-    @Test
-    public void updatePreference_triggerBatteryStatusUpdateTrue_updatePercentageAndUsageOnly() {
-        setChargingState(/* isDischarging */ true, /* updatedByStatusFeature */ true);
-
-        mController.updateHeaderPreference(mBatteryInfo);
-
-        verify(mBatteryUsageProgressBarPref).setUsageSummary(formatBatteryPercentageText());
-        verify(mBatteryUsageProgressBarPref).setPercent(BATTERY_LEVEL, BATTERY_MAX_LEVEL);
-    }
-
-    @Test
-    public void updatePreference_triggerBatteryStatusUpdateFalse_updateBatteryInfo() {
-        setChargingState(/* isDischarging */ true, /* updatedByStatusFeature */ false);
-
-        mController.updateHeaderPreference(mBatteryInfo);
-
-        verify(mBatteryUsageProgressBarPref).setUsageSummary(formatBatteryPercentageText());
-        verify(mBatteryUsageProgressBarPref).setBottomSummary(mBatteryInfo.remainingLabel);
-        verify(mBatteryUsageProgressBarPref).setPercent(BATTERY_LEVEL, BATTERY_MAX_LEVEL);
-    }
-
-    @Test
-    public void updateBatteryStatus_nullLabel_updateSummaryOnly() {
-        setChargingState(/* isDischarging */ true, /* updatedByStatusFeature */ false);
-
-        mController.updateBatteryStatus(null, mBatteryInfo);
-
-        verify(mBatteryUsageProgressBarPref).setBottomSummary(mBatteryInfo.remainingLabel);
-    }
-
-    @Test
-    public void updateBatteryStatus_withLabel_showLabelText() {
-        setChargingState(/* isDischarging */ true, /* updatedByStatusFeature */ false);
-
-        final String label = "Update by battery status • " + TIME_LEFT;
-        mController.updateBatteryStatus(label, mBatteryInfo);
-
-        verify(mBatteryUsageProgressBarPref).setBottomSummary(label);
-    }
-
-    @Test
-    public void updateBatteryStatus_chargingString_statusWithRemainingLabel() {
-        var batteryInfo =
-                arrangeUpdateBatteryStatusTestWithRemainingLabel(
-                        /* remainingLabel= */ "1 hr, 40 min left until full",
-                        /* statusLabel= */ "Charging rapidly",
-                        /* isFastCharging= */ true,
-                        /* isChargingStringV2= */ false);
-        var expectedChargingString = batteryInfo.statusLabel + " • " + batteryInfo.remainingLabel;
-
-        mController.updateBatteryStatus(/* label= */ null, batteryInfo);
-
-        verify(mBatteryUsageProgressBarPref).setBottomSummary(expectedChargingString);
-    }
-
-    @Test
-    public void updateBatteryStatus_chargingStringV2FastCharging_statusWithRemainingLabel() {
-        var batteryInfo =
-                arrangeUpdateBatteryStatusTestWithRemainingLabel(
-                        /* remainingLabel= */ "Full by 1:30 PM",
-                        /* statusLabel= */ "Fast Charging",
-                        /* isFastCharging= */ true,
-                        /* isChargingStringV2= */ true);
-        var expectedChargingString = batteryInfo.statusLabel + " • " + batteryInfo.remainingLabel;
-
-        mController.updateBatteryStatus(/* label= */ null, batteryInfo);
-
-        verify(mBatteryUsageProgressBarPref).setBottomSummary(expectedChargingString);
-    }
-
-    @Test
-    public void updateBatteryStatus_chargingStringV2NonFastCharging_remainingLabel() {
-        var batteryInfo =
-                arrangeUpdateBatteryStatusTestWithRemainingLabel(
-                        /* remainingLabel= */ "Fully charged by 11:10 PM",
-                        /* statusLabel= */ "Charging",
-                        /* isFastCharging= */ false,
-                        /* isChargingStringV2= */ true);
-        var expectedChargingString = batteryInfo.remainingLabel;
-
-        mController.updateBatteryStatus(/* label= */ null, batteryInfo);
-
-        verify(mBatteryUsageProgressBarPref).setBottomSummary(expectedChargingString);
-    }
-
-    @Test
-    public void updateBatteryStatus_customizedWirelessChargingLabel_customizedLabel() {
-        var label = "Customized Wireless Charging Label";
-        var contentDescription = "Customized Wireless Charging description";
-        var batteryInfo =
-                arrangeUpdateBatteryStatusTestWithRemainingLabel(
-                        /* remainingLabel= */ "Full by 1:30 PM",
-                        /* statusLabel= */ "Fast Charging",
-                        /* isFastCharging= */ true,
-                        /* isChargingStringV2= */ true);
-        batteryInfo.pluggedStatus = BatteryManager.BATTERY_PLUGGED_WIRELESS;
-        when(mFactory.batterySettingsFeatureProvider.getWirelessChargingLabel(
-                        eq(mContext), any(BatteryInfo.class)))
-                .thenReturn(label);
-        when(mFactory.batterySettingsFeatureProvider.getWirelessChargingContentDescription(
-                        eq(mContext), any(BatteryInfo.class)))
-                .thenReturn(contentDescription);
-
-        mController.updateBatteryStatus(/* label= */ null, batteryInfo);
-
-        verify(mBatteryUsageProgressBarPref).setBottomSummary(label);
-        verify(mBatteryUsageProgressBarPref).setBottomSummaryContentDescription(contentDescription);
-    }
-
-    @Test
-    public void updateBatteryStatus_noCustomizedWirelessChargingLabel_statusWithRemainingLabel() {
-        var contentDescription = "Customized Wireless Charging description";
-        var batteryInfo =
-                arrangeUpdateBatteryStatusTestWithRemainingLabel(
-                        /* remainingLabel= */ "Full by 1:30 PM",
-                        /* statusLabel= */ "Fast Charging",
-                        /* isFastCharging= */ true,
-                        /* isChargingStringV2= */ true);
-        batteryInfo.pluggedStatus = BatteryManager.BATTERY_PLUGGED_WIRELESS;
-        var expectedChargingString = batteryInfo.statusLabel + " • " + batteryInfo.remainingLabel;
-
-        mController.updateBatteryStatus(/* label= */ null, batteryInfo);
-
-        verify(mBatteryUsageProgressBarPref).setBottomSummary(expectedChargingString);
-        verify(mBatteryUsageProgressBarPref, never())
-                .setBottomSummaryContentDescription(contentDescription);
-    }
-
-    @Test
-    public void updateBatteryStatus_noCustomizedWirelessChargingLabel_v1StatusWithRemainingLabel() {
-        var contentDescription = "Customized Wireless Charging description";
-        var batteryInfo =
-                arrangeUpdateBatteryStatusTestWithRemainingLabel(
-                        /* remainingLabel= */ "1 hr, 40 min left until full",
-                        /* statusLabel= */ "Charging wirelessly",
-                        /* isFastCharging= */ false,
-                        /* isChargingStringV2= */ false);
-        batteryInfo.pluggedStatus = BatteryManager.BATTERY_PLUGGED_WIRELESS;
-        var expectedChargingString = batteryInfo.statusLabel + " • " + batteryInfo.remainingLabel;
-
-        mController.updateBatteryStatus(/* label= */ null, batteryInfo);
-
-        verify(mBatteryUsageProgressBarPref).setBottomSummary(expectedChargingString);
-        verify(mBatteryUsageProgressBarPref, never())
-                .setBottomSummaryContentDescription(contentDescription);
-    }
-
-    @Test
-    public void updateBatteryStatus_chargingOptimizationMode_remainingLabel() {
-        var batteryInfo =
-                arrangeUpdateBatteryStatusTestWithRemainingLabel(
-                        /* remainingLabel= */ "Expected remaining label",
-                        /* statusLabel= */ "Fast Charging",
-                        /* isFastCharging= */ true,
-                        /* isChargingStringV2= */ true);
-        var expectedChargingString = batteryInfo.remainingLabel;
-        when(mFactory.batterySettingsFeatureProvider.isChargingOptimizationMode(mContext))
-                .thenReturn(true);
-
-        mController.updateBatteryStatus(/* label= */ null, batteryInfo);
-
-        verify(mBatteryUsageProgressBarPref).setBottomSummary(expectedChargingString);
-    }
-
-    @Test
-    public void updateBatteryStatus_chargingOptimizationModeNoRemainingLabel_statusLabel() {
-        var batteryInfo =
-                arrangeUpdateBatteryStatusTestWithRemainingLabel(
-                        /* remainingLabel= */ null,
-                        /* statusLabel= */ "Fast Charging",
-                        /* isFastCharging= */ true,
-                        /* isChargingStringV2= */ true);
-        var expectedChargingString = batteryInfo.statusLabel;
-        when(mFactory.batterySettingsFeatureProvider.isChargingOptimizationMode(mContext))
-                .thenReturn(true);
-
-        mController.updateBatteryStatus(/* label= */ null, batteryInfo);
-
-        verify(mBatteryUsageProgressBarPref).setBottomSummary(expectedChargingString);
-    }
-
-    @Test
-    public void updateBatteryStatus_notChargingOptimizationMode_statusWithRemainingLabel() {
-        var batteryInfo =
-                arrangeUpdateBatteryStatusTestWithRemainingLabel(
-                        /* remainingLabel= */ "Full by 1:30 PM",
-                        /* statusLabel= */ "Fast Charging",
-                        /* isFastCharging= */ true,
-                        /* isChargingStringV2= */ true);
-        var expectedChargingString = batteryInfo.statusLabel + " • " + batteryInfo.remainingLabel;
-        when(mFactory.batterySettingsFeatureProvider.isChargingOptimizationMode(mContext))
-                .thenReturn(false);
-
-        mController.updateBatteryStatus(/* label= */ null, batteryInfo);
-
-        verify(mBatteryUsageProgressBarPref).setBottomSummary(expectedChargingString);
-    }
-
-    @Test
-    public void updateBatteryStatus_dockDefend_chargingOnHold() {
-        var expected = "Charging on hold";
-        mBatteryInfo.isBatteryDefender = false;
-        when(mFactory.powerUsageFeatureProvider.isExtraDefend()).thenReturn(true);
-
-        mController.updateBatteryStatus(/* label= */ null, mBatteryInfo);
-
-        verify(mBatteryUsageProgressBarPref).setBottomSummary(expected);
-    }
-
-    @Test
-    public void updateBatteryStatus_batteryDefender_chargingOnHold() {
-        var expected = "Charging on hold";
-        mBatteryInfo.isBatteryDefender = true;
-        when(mFactory.powerUsageFeatureProvider.isExtraDefend()).thenReturn(false);
-
-        mController.updateBatteryStatus(/* label= */ null, mBatteryInfo);
-
-        verify(mBatteryUsageProgressBarPref).setBottomSummary(expected);
-    }
-
-    private BatteryInfo arrangeUpdateBatteryStatusTestWithRemainingLabel(
-            String remainingLabel,
-            String statusLabel,
-            boolean isFastCharging,
-            boolean isChargingStringV2) {
-        SystemProperties.set(
-                BatteryUtils.PROPERTY_CHARGING_STRING_V2_KEY, String.valueOf(isChargingStringV2));
-        mBatteryInfo.isBatteryDefender = false;
-        mBatteryInfo.remainingLabel = remainingLabel;
-        mBatteryInfo.statusLabel = statusLabel;
-        mBatteryInfo.discharging = false;
-        mBatteryInfo.isFastCharging = isFastCharging;
-        return mBatteryInfo;
-    }
-
-    @Test
-    public void updateHeaderByBatteryTips_lowBatteryTip_showLowBattery() {
-        setChargingState(/* isDischarging */ true, /* updatedByStatusFeature */ false);
-        BatteryTip lowBatteryTip =
-                new LowBatteryTip(BatteryTip.StateType.NEW, /* powerSaveModeOn */ false);
-
-        mController.updateHeaderByBatteryTips(lowBatteryTip, mBatteryInfo);
-
-        final String expectedResult = "Low battery • " + TIME_LEFT;
-        verify(mBatteryUsageProgressBarPref).setBottomSummary(expectedResult);
-    }
-
-    @Test
-    public void updateHeaderByBatteryTips_notLowBatteryTip_showRemainingLabel() {
-        setChargingState(/* isDischarging */ true, /* updatedByStatusFeature */ false);
-        BatteryTip lowBatteryTip = new SmartBatteryTip(BatteryTip.StateType.NEW);
-
-        mController.updateHeaderByBatteryTips(lowBatteryTip, mBatteryInfo);
-
-        verify(mBatteryUsageProgressBarPref).setBottomSummary(mBatteryInfo.remainingLabel);
-    }
-
-    @Test
-    public void updateHeaderByBatteryTips_noTip_noAction() {
-        setChargingState(/* isDischarging */ true, /* updatedByStatusFeature */ false);
-
-        mController.updateHeaderByBatteryTips(null, mBatteryInfo);
-
-        verifyNoInteractions(mBatteryUsageProgressBarPref);
-    }
-
-    @Test
-    public void updateHeaderByBatteryTips_noBatteryInfo_noAction() {
-        BatteryTip lowBatteryTip =
-                new LowBatteryTip(BatteryTip.StateType.NEW, /* powerSaveModeOn */ false);
-
-        mController.updateHeaderByBatteryTips(lowBatteryTip, null);
-
-        verifyNoInteractions(mBatteryUsageProgressBarPref);
-    }
-
-    @Test
-    public void updatePreference_isBatteryDefender_showEmptyText() {
-        mBatteryInfo.isBatteryDefender = true;
-
-        mController.updateHeaderPreference(mBatteryInfo);
-
-        verify(mBatteryUsageProgressBarPref)
-                .setBottomSummary(
-                        mContext.getString(
-                                com.android.settingslib.R.string
-                                        .battery_info_status_charging_on_hold));
-    }
-
-    @Test
-    public void updatePreference_incompatibleCharger_showNotChargingState() {
-        BatteryTestUtils.setupIncompatibleEvent(mUsbPort, mUsbManager, mUsbPortStatus);
-
-        mController.updateHeaderPreference(mBatteryInfo);
-
-        verify(mBatteryUsageProgressBarPref)
-                .setBottomSummary(
-                        mContext.getString(
-                                com.android.settingslib.R.string.battery_info_status_not_charging));
+        verify(mBatteryUsageProgressBarPreference).setUsageSummary(formatBatteryPercentageText());
+        verify(mBatteryUsageProgressBarPreference).setPercent(BATTERY_LEVEL, BATTERY_MAX_LEVEL);
     }
 
     @Test
     public void quickUpdateHeaderPreference_onlyUpdateBatteryLevelAndChargingState() {
         mController.quickUpdateHeaderPreference();
 
-        verify(mBatteryUsageProgressBarPref).setUsageSummary(formatBatteryPercentageText());
-        verify(mBatteryUsageProgressBarPref).setPercent(BATTERY_LEVEL, BATTERY_MAX_LEVEL);
+        verify(mBatteryUsageProgressBarPreference).setUsageSummary(formatBatteryPercentageText());
+        verify(mBatteryUsageProgressBarPreference).setPercent(BATTERY_LEVEL, BATTERY_MAX_LEVEL);
     }
 
     @Test
@@ -512,26 +151,18 @@
 
         mController.displayPreference(mPreferenceScreen);
 
-        assertThat(mBatteryUsageProgressBarPref.isVisible()).isFalse();
+        assertThat(mBatteryUsageProgressBarPreference.isVisible()).isFalse();
     }
 
     @Test
-    public void displayPreference_init_showEmptySpace() {
+    public void displayPreference_init_setEmptyBottomSummary() {
         mController.displayPreference(mPreferenceScreen);
 
-        verify(mBatteryUsageProgressBarPref).setBottomSummary(" ");
+        verify(mBatteryUsageProgressBarPreference).setBottomSummary("");
     }
 
     private CharSequence formatBatteryPercentageText() {
         return com.android.settings.Utils.formatPercentage(BATTERY_LEVEL);
     }
-
-    private void setChargingState(boolean isDischarging, boolean updatedByStatusFeature) {
-        mBatteryInfo.remainingLabel = TIME_LEFT;
-        mBatteryInfo.statusLabel = BATTERY_STATUS;
-        mBatteryInfo.discharging = isDischarging;
-
-        when(mBatteryStatusFeatureProvider.triggerBatteryStatusUpdate(mController, mBatteryInfo))
-                .thenReturn(updatedByStatusFeature);
-    }
 }
+// LINT.ThenChange(BatteryHeaderPreferenceTest.java)
diff --git a/tests/robotests/src/com/android/settings/fuelgauge/BatteryHeaderPreferenceTest.kt b/tests/robotests/src/com/android/settings/fuelgauge/BatteryHeaderPreferenceTest.kt
new file mode 100644
index 0000000..27e14c8
--- /dev/null
+++ b/tests/robotests/src/com/android/settings/fuelgauge/BatteryHeaderPreferenceTest.kt
@@ -0,0 +1,85 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.settings.fuelgauge
+
+import android.content.BroadcastReceiver
+import android.content.Context
+import android.content.ContextWrapper
+import android.content.Intent
+import android.content.IntentFilter
+import android.os.BatteryManager.EXTRA_LEVEL
+import android.os.BatteryManager.EXTRA_SCALE
+import androidx.test.core.app.ApplicationProvider
+import androidx.test.ext.junit.runners.AndroidJUnit4
+import com.android.settingslib.metadata.PreferenceLifecycleContext
+import com.android.settingslib.preference.createAndBindWidget
+import com.android.settingslib.widget.UsageProgressBarPreference
+import com.google.common.truth.Truth.assertThat
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.mockito.kotlin.mock
+import org.mockito.kotlin.verify
+
+// LINT.IfChange
+@RunWith(AndroidJUnit4::class)
+class BatteryHeaderPreferenceTest {
+    private val mockLifecycleContext = mock<PreferenceLifecycleContext>()
+    private val mockBatteryBroadcastReceiver = mock<BatteryBroadcastReceiver>()
+    private val batteryHeaderPreference = BatteryHeaderPreference()
+
+    private val context: Context =
+        object : ContextWrapper(ApplicationProvider.getApplicationContext()) {
+            override fun registerReceiver(receiver: BroadcastReceiver?, filter: IntentFilter?) =
+                Intent(Intent.ACTION_BATTERY_CHANGED)
+                    .putExtra(EXTRA_LEVEL, 60)
+                    .putExtra(EXTRA_SCALE, 100)
+        }
+
+    @Test
+    fun createAndBindWidget_selectableIsFalse() {
+        val usageProgressBarPreference =
+            batteryHeaderPreference.createAndBindWidget<UsageProgressBarPreference>(context)
+
+        assertThat(usageProgressBarPreference.isSelectable).isFalse()
+    }
+
+    @Test
+    fun onCreate_createBatteryBroadcastReceiver() {
+        batteryHeaderPreference.onCreate(mockLifecycleContext)
+
+        assertThat(batteryHeaderPreference.batteryBroadcastReceiver).isNotNull()
+    }
+
+    @Test
+    fun onStart_invokeRegisterMethod() {
+        batteryHeaderPreference.batteryBroadcastReceiver = mockBatteryBroadcastReceiver
+
+        batteryHeaderPreference.onStart(mockLifecycleContext)
+
+        verify(mockBatteryBroadcastReceiver).register()
+    }
+
+    @Test
+    fun onStop_invokeUnRegisterMethod() {
+        batteryHeaderPreference.batteryBroadcastReceiver = mockBatteryBroadcastReceiver
+
+        batteryHeaderPreference.onStop(mockLifecycleContext)
+
+        verify(mockBatteryBroadcastReceiver).unRegister()
+    }
+}
+// LINT.ThenChange(BatteryHeaderPreferenceControllerTest.java)
diff --git a/tests/robotests/src/com/android/settings/fuelgauge/BatteryHeaderTextPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/fuelgauge/BatteryHeaderTextPreferenceControllerTest.java
index 1c5ffc8..18fb90d 100644
--- a/tests/robotests/src/com/android/settings/fuelgauge/BatteryHeaderTextPreferenceControllerTest.java
+++ b/tests/robotests/src/com/android/settings/fuelgauge/BatteryHeaderTextPreferenceControllerTest.java
@@ -47,7 +47,6 @@
 import com.android.settings.testutils.shadow.ShadowUtils;
 import com.android.settings.widget.EntityHeaderController;
 import com.android.settingslib.fuelgauge.BatteryUtils;
-import com.android.settingslib.widget.UsageProgressBarPreference;
 
 import org.junit.After;
 import org.junit.Before;
@@ -65,22 +64,21 @@
 @Config(shadows = {ShadowEntityHeaderController.class, ShadowUtils.class})
 public class BatteryHeaderTextPreferenceControllerTest {
 
-    private static final String PREF_KEY = "battery_header";
+    private static final String PREF_KEY = "battery_header_text";
     private static final int BATTERY_LEVEL = 60;
-    private static final int BATTERY_MAX_LEVEL = 100;
     private static final String TIME_LEFT = "2h30min";
     private static final String BATTERY_STATUS = "Charging";
 
     @Mock private PreferenceScreen mPreferenceScreen;
     @Mock private BatteryInfo mBatteryInfo;
     @Mock private EntityHeaderController mEntityHeaderController;
-    @Mock private UsageProgressBarPreference mBatteryUsageProgressBarPref;
+    @Mock private BatteryHeaderTextPreference mBatteryHeaderTextPreference;
     @Mock private BatteryStatusFeatureProvider mBatteryStatusFeatureProvider;
     @Mock private UsbPort mUsbPort;
     @Mock private UsbManager mUsbManager;
     @Mock private UsbPortStatus mUsbPortStatus;
 
-    private BatteryHeaderPreferenceController mController;
+    private BatteryHeaderTextPreferenceController mController;
     private Context mContext;
     private ShadowPowerManager mShadowPowerManager;
     private Intent mBatteryIntent;
@@ -100,17 +98,17 @@
         mBatteryIntent.putExtra(BatteryManager.EXTRA_PLUGGED, 1);
         doReturn(mBatteryIntent).when(mContext).registerReceiver(any(), any());
 
-        doReturn(mBatteryUsageProgressBarPref)
+        doReturn(mBatteryHeaderTextPreference)
                 .when(mPreferenceScreen)
-                .findPreference(BatteryHeaderPreferenceController.KEY_BATTERY_HEADER);
+                .findPreference(PREF_KEY);
 
         mBatteryInfo.batteryLevel = BATTERY_LEVEL;
 
         mShadowPowerManager = Shadows.shadowOf(mContext.getSystemService(PowerManager.class));
         mFactory = FakeFeatureFactory.setupForTest();
 
-        mController = spy(new BatteryHeaderPreferenceController(mContext, PREF_KEY));
-        mController.mBatteryUsageProgressBarPref = mBatteryUsageProgressBarPref;
+        mController = spy(new BatteryHeaderTextPreferenceController(mContext, PREF_KEY));
+        mController.mBatteryHeaderTextPreference = mBatteryHeaderTextPreference;
         mController.mBatteryStatusFeatureProvider = mBatteryStatusFeatureProvider;
 
         BatteryUtils.setChargingStringV2Enabled(null);
@@ -123,20 +121,12 @@
     }
 
     @Test
-    public void displayPreference_displayBatteryLevel() {
-        mController.displayPreference(mPreferenceScreen);
-
-        verify(mBatteryUsageProgressBarPref).setUsageSummary(formatBatteryPercentageText());
-        verify(mBatteryUsageProgressBarPref).setPercent(BATTERY_LEVEL, BATTERY_MAX_LEVEL);
-    }
-
-    @Test
     public void updatePreference_hasRemainingTime_showRemainingLabel() {
         mBatteryInfo.remainingLabel = TIME_LEFT;
 
         mController.updateHeaderPreference(mBatteryInfo);
 
-        verify(mBatteryUsageProgressBarPref).setBottomSummary(mBatteryInfo.remainingLabel);
+        verify(mBatteryHeaderTextPreference).setText(mBatteryInfo.remainingLabel);
     }
 
     @Test
@@ -145,9 +135,7 @@
 
         mController.updateHeaderPreference(mBatteryInfo);
 
-        verify(mBatteryUsageProgressBarPref).setUsageSummary(formatBatteryPercentageText());
-        verify(mBatteryUsageProgressBarPref).setBottomSummary(mBatteryInfo.remainingLabel);
-        verify(mBatteryUsageProgressBarPref).setPercent(BATTERY_LEVEL, BATTERY_MAX_LEVEL);
+        verify(mBatteryHeaderTextPreference).setText(mBatteryInfo.remainingLabel);
     }
 
     @Test
@@ -157,7 +145,7 @@
 
         mController.updateHeaderPreference(mBatteryInfo);
 
-        verify(mBatteryUsageProgressBarPref).setBottomSummary(BATTERY_STATUS);
+        verify(mBatteryHeaderTextPreference).setText(BATTERY_STATUS);
     }
 
     @Test
@@ -168,7 +156,7 @@
 
         mController.updateHeaderPreference(mBatteryInfo);
 
-        verify(mBatteryUsageProgressBarPref).setBottomSummary(BATTERY_STATUS);
+        verify(mBatteryHeaderTextPreference).setText(BATTERY_STATUS);
     }
 
     @Test
@@ -178,7 +166,7 @@
         mController.updateHeaderPreference(mBatteryInfo);
 
         final String expectedResult = BATTERY_STATUS + " • " + TIME_LEFT;
-        verify(mBatteryUsageProgressBarPref).setBottomSummary(expectedResult);
+        verify(mBatteryHeaderTextPreference).setText(expectedResult);
     }
 
     @Test
@@ -189,17 +177,7 @@
         mController.updateHeaderPreference(mBatteryInfo);
 
         final String expectedResult = "Battery Saver on • " + TIME_LEFT;
-        verify(mBatteryUsageProgressBarPref).setBottomSummary(expectedResult);
-    }
-
-    @Test
-    public void updatePreference_triggerBatteryStatusUpdateTrue_updatePercentageAndUsageOnly() {
-        setChargingState(/* isDischarging */ true, /* updatedByStatusFeature */ true);
-
-        mController.updateHeaderPreference(mBatteryInfo);
-
-        verify(mBatteryUsageProgressBarPref).setUsageSummary(formatBatteryPercentageText());
-        verify(mBatteryUsageProgressBarPref).setPercent(BATTERY_LEVEL, BATTERY_MAX_LEVEL);
+        verify(mBatteryHeaderTextPreference).setText(expectedResult);
     }
 
     @Test
@@ -208,9 +186,7 @@
 
         mController.updateHeaderPreference(mBatteryInfo);
 
-        verify(mBatteryUsageProgressBarPref).setUsageSummary(formatBatteryPercentageText());
-        verify(mBatteryUsageProgressBarPref).setBottomSummary(mBatteryInfo.remainingLabel);
-        verify(mBatteryUsageProgressBarPref).setPercent(BATTERY_LEVEL, BATTERY_MAX_LEVEL);
+        verify(mBatteryHeaderTextPreference).setText(mBatteryInfo.remainingLabel);
     }
 
     @Test
@@ -219,7 +195,7 @@
 
         mController.updateBatteryStatus(null, mBatteryInfo);
 
-        verify(mBatteryUsageProgressBarPref).setBottomSummary(mBatteryInfo.remainingLabel);
+        verify(mBatteryHeaderTextPreference).setText(mBatteryInfo.remainingLabel);
     }
 
     @Test
@@ -229,7 +205,7 @@
         final String label = "Update by battery status • " + TIME_LEFT;
         mController.updateBatteryStatus(label, mBatteryInfo);
 
-        verify(mBatteryUsageProgressBarPref).setBottomSummary(label);
+        verify(mBatteryHeaderTextPreference).setText(label);
     }
 
     @Test
@@ -244,7 +220,7 @@
 
         mController.updateBatteryStatus(/* label= */ null, batteryInfo);
 
-        verify(mBatteryUsageProgressBarPref).setBottomSummary(expectedChargingString);
+        verify(mBatteryHeaderTextPreference).setText(expectedChargingString);
     }
 
     @Test
@@ -259,7 +235,7 @@
 
         mController.updateBatteryStatus(/* label= */ null, batteryInfo);
 
-        verify(mBatteryUsageProgressBarPref).setBottomSummary(expectedChargingString);
+        verify(mBatteryHeaderTextPreference).setText(expectedChargingString);
     }
 
     @Test
@@ -274,7 +250,7 @@
 
         mController.updateBatteryStatus(/* label= */ null, batteryInfo);
 
-        verify(mBatteryUsageProgressBarPref).setBottomSummary(expectedChargingString);
+        verify(mBatteryHeaderTextPreference).setText(expectedChargingString);
     }
 
     @Test
@@ -297,8 +273,8 @@
 
         mController.updateBatteryStatus(/* label= */ null, batteryInfo);
 
-        verify(mBatteryUsageProgressBarPref).setBottomSummary(label);
-        verify(mBatteryUsageProgressBarPref).setBottomSummaryContentDescription(contentDescription);
+        verify(mBatteryHeaderTextPreference).setText(label);
+        verify(mBatteryHeaderTextPreference).setContentDescription(contentDescription);
     }
 
     @Test
@@ -315,9 +291,8 @@
 
         mController.updateBatteryStatus(/* label= */ null, batteryInfo);
 
-        verify(mBatteryUsageProgressBarPref).setBottomSummary(expectedChargingString);
-        verify(mBatteryUsageProgressBarPref, never())
-                .setBottomSummaryContentDescription(contentDescription);
+        verify(mBatteryHeaderTextPreference).setText(expectedChargingString);
+        verify(mBatteryHeaderTextPreference, never()).setContentDescription(contentDescription);
     }
 
     @Test
@@ -334,9 +309,8 @@
 
         mController.updateBatteryStatus(/* label= */ null, batteryInfo);
 
-        verify(mBatteryUsageProgressBarPref).setBottomSummary(expectedChargingString);
-        verify(mBatteryUsageProgressBarPref, never())
-                .setBottomSummaryContentDescription(contentDescription);
+        verify(mBatteryHeaderTextPreference).setText(expectedChargingString);
+        verify(mBatteryHeaderTextPreference, never()).setContentDescription(contentDescription);
     }
 
     @Test
@@ -353,7 +327,7 @@
 
         mController.updateBatteryStatus(/* label= */ null, batteryInfo);
 
-        verify(mBatteryUsageProgressBarPref).setBottomSummary(expectedChargingString);
+        verify(mBatteryHeaderTextPreference).setText(expectedChargingString);
     }
 
     @Test
@@ -370,7 +344,7 @@
 
         mController.updateBatteryStatus(/* label= */ null, batteryInfo);
 
-        verify(mBatteryUsageProgressBarPref).setBottomSummary(expectedChargingString);
+        verify(mBatteryHeaderTextPreference).setText(expectedChargingString);
     }
 
     @Test
@@ -387,7 +361,7 @@
 
         mController.updateBatteryStatus(/* label= */ null, batteryInfo);
 
-        verify(mBatteryUsageProgressBarPref).setBottomSummary(expectedChargingString);
+        verify(mBatteryHeaderTextPreference).setText(expectedChargingString);
     }
 
     @Test
@@ -398,7 +372,7 @@
 
         mController.updateBatteryStatus(/* label= */ null, mBatteryInfo);
 
-        verify(mBatteryUsageProgressBarPref).setBottomSummary(expected);
+        verify(mBatteryHeaderTextPreference).setText(expected);
     }
 
     @Test
@@ -409,7 +383,7 @@
 
         mController.updateBatteryStatus(/* label= */ null, mBatteryInfo);
 
-        verify(mBatteryUsageProgressBarPref).setBottomSummary(expected);
+        verify(mBatteryHeaderTextPreference).setText(expected);
     }
 
     private BatteryInfo arrangeUpdateBatteryStatusTestWithRemainingLabel(
@@ -436,7 +410,7 @@
         mController.updateHeaderByBatteryTips(lowBatteryTip, mBatteryInfo);
 
         final String expectedResult = "Low battery • " + TIME_LEFT;
-        verify(mBatteryUsageProgressBarPref).setBottomSummary(expectedResult);
+        verify(mBatteryHeaderTextPreference).setText(expectedResult);
     }
 
     @Test
@@ -446,7 +420,7 @@
 
         mController.updateHeaderByBatteryTips(lowBatteryTip, mBatteryInfo);
 
-        verify(mBatteryUsageProgressBarPref).setBottomSummary(mBatteryInfo.remainingLabel);
+        verify(mBatteryHeaderTextPreference).setText(mBatteryInfo.remainingLabel);
     }
 
     @Test
@@ -455,7 +429,7 @@
 
         mController.updateHeaderByBatteryTips(null, mBatteryInfo);
 
-        verifyNoInteractions(mBatteryUsageProgressBarPref);
+        verifyNoInteractions(mBatteryHeaderTextPreference);
     }
 
     @Test
@@ -465,7 +439,7 @@
 
         mController.updateHeaderByBatteryTips(lowBatteryTip, null);
 
-        verifyNoInteractions(mBatteryUsageProgressBarPref);
+        verifyNoInteractions(mBatteryHeaderTextPreference);
     }
 
     @Test
@@ -474,9 +448,7 @@
 
         mController.updateHeaderPreference(mBatteryInfo);
 
-        verify(mBatteryUsageProgressBarPref)
-                .setBottomSummary(
-                        mContext.getString(
+        verify(mBatteryHeaderTextPreference).setText(mContext.getString(
                                 com.android.settingslib.R.string
                                         .battery_info_status_charging_on_hold));
     }
@@ -487,21 +459,13 @@
 
         mController.updateHeaderPreference(mBatteryInfo);
 
-        verify(mBatteryUsageProgressBarPref)
-                .setBottomSummary(
+        verify(mBatteryHeaderTextPreference)
+                .setText(
                         mContext.getString(
                                 com.android.settingslib.R.string.battery_info_status_not_charging));
     }
 
     @Test
-    public void quickUpdateHeaderPreference_onlyUpdateBatteryLevelAndChargingState() {
-        mController.quickUpdateHeaderPreference();
-
-        verify(mBatteryUsageProgressBarPref).setUsageSummary(formatBatteryPercentageText());
-        verify(mBatteryUsageProgressBarPref).setPercent(BATTERY_LEVEL, BATTERY_MAX_LEVEL);
-    }
-
-    @Test
     public void getAvailabilityStatus_returnAvailableUnsearchable() {
         assertThat(mController.getAvailabilityStatus())
                 .isEqualTo(BasePreferenceController.AVAILABLE_UNSEARCHABLE);
@@ -513,18 +477,7 @@
 
         mController.displayPreference(mPreferenceScreen);
 
-        assertThat(mBatteryUsageProgressBarPref.isVisible()).isFalse();
-    }
-
-    @Test
-    public void displayPreference_init_showEmptySpace() {
-        mController.displayPreference(mPreferenceScreen);
-
-        verify(mBatteryUsageProgressBarPref).setBottomSummary(" ");
-    }
-
-    private CharSequence formatBatteryPercentageText() {
-        return com.android.settings.Utils.formatPercentage(BATTERY_LEVEL);
+        assertThat(mBatteryHeaderTextPreference.isVisible()).isFalse();
     }
 
     private void setChargingState(boolean isDischarging, boolean updatedByStatusFeature) {
diff --git a/tests/robotests/src/com/android/settings/location/LocationInjectedServicesPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/location/LocationInjectedServicesPreferenceControllerTest.java
index 375e152..1e85fbf 100644
--- a/tests/robotests/src/com/android/settings/location/LocationInjectedServicesPreferenceControllerTest.java
+++ b/tests/robotests/src/com/android/settings/location/LocationInjectedServicesPreferenceControllerTest.java
@@ -26,6 +26,7 @@
 import static org.mockito.Mockito.when;
 
 import android.app.admin.DevicePolicyManager;
+import android.app.admin.DevicePolicyResourcesManager;
 import android.content.ComponentName;
 import android.content.Context;
 import android.content.pm.UserInfo;
@@ -83,6 +84,8 @@
     private AppSettingsInjector mSettingsInjector;
     @Mock
     private DevicePolicyManager mDevicePolicyManager;
+    @Mock
+    private DevicePolicyResourcesManager mDevicePolicyResourcesManager;
 
     private Context mContext;
     private LocationInjectedServicesPreferenceController mController;
@@ -104,6 +107,7 @@
         when(mCategoryPrimary.getKey()).thenReturn(key);
         when(mContext.getSystemService(Context.DEVICE_POLICY_SERVICE))
                 .thenReturn(mDevicePolicyManager);
+        when(mDevicePolicyManager.getResources()).thenReturn(mDevicePolicyResourcesManager);
     }
 
     @Test
@@ -276,6 +280,7 @@
                 UserHandle.of(userId),
                 enforcingUsers);
         when(mDevicePolicyManager.getDeviceOwnerComponentOnAnyUser()).thenReturn(componentName);
+        when(mDevicePolicyResourcesManager.getString(any(), any())).thenReturn(any());
 
         mController.displayPreference(mScreen);
 
diff --git a/tests/spa_unit/src/com/android/settings/network/telephony/gsm/AutoSelectPreferenceControllerTest.kt b/tests/spa_unit/src/com/android/settings/network/telephony/gsm/AutoSelectPreferenceControllerTest.kt
index f821e1a..641866d 100644
--- a/tests/spa_unit/src/com/android/settings/network/telephony/gsm/AutoSelectPreferenceControllerTest.kt
+++ b/tests/spa_unit/src/com/android/settings/network/telephony/gsm/AutoSelectPreferenceControllerTest.kt
@@ -18,10 +18,12 @@
 
 import android.content.Context
 import android.content.Intent
+import android.platform.test.annotations.EnableFlags
 import android.provider.Settings
 import android.telephony.CarrierConfigManager
 import android.telephony.ServiceState
 import android.telephony.TelephonyManager
+import android.telephony.satellite.SatelliteManager
 import androidx.compose.ui.test.assertIsEnabled
 import androidx.compose.ui.test.assertIsNotEnabled
 import androidx.compose.ui.test.assertIsOff
@@ -36,6 +38,7 @@
 import androidx.test.ext.junit.runners.AndroidJUnit4
 import com.android.settings.R
 import com.android.settings.Settings.NetworkSelectActivity
+import com.android.settings.flags.Flags
 import com.android.settings.spa.preference.ComposePreference
 import com.google.common.truth.Truth.assertThat
 import kotlinx.coroutines.delay
@@ -46,6 +49,8 @@
 import org.junit.Rule
 import org.junit.Test
 import org.junit.runner.RunWith
+import org.mockito.Mockito.`when`
+import org.mockito.junit.MockitoJUnit
 import org.mockito.kotlin.any
 import org.mockito.kotlin.argumentCaptor
 import org.mockito.kotlin.doNothing
@@ -58,6 +63,9 @@
 @RunWith(AndroidJUnit4::class)
 class AutoSelectPreferenceControllerTest {
     @get:Rule
+    val mockito = MockitoJUnit.rule()
+
+    @get:Rule
     val composeTestRule = createComposeRule()
 
     private val mockTelephonyManager = mock<TelephonyManager> {
@@ -65,8 +73,12 @@
         on { simOperatorName } doReturn OPERATOR_NAME
     }
 
+    private val mockSatelliteManager = mock<SatelliteManager> {
+    }
+
     private val context: Context = spy(ApplicationProvider.getApplicationContext()) {
         on { getSystemService(TelephonyManager::class.java) } doReturn mockTelephonyManager
+        on { getSystemService(SatelliteManager::class.java) } doReturn mockSatelliteManager
         doNothing().whenever(mock).startActivity(any())
     }
 
@@ -115,7 +127,6 @@
             .assertIsOff()
     }
 
-
     @Test
     fun isEnabled_isRoaming_enabled() {
         serviceState.roaming = true
@@ -159,6 +170,54 @@
     }
 
     @Test
+    @EnableFlags(Flags.FLAG_SATELLITE_OEM_SETTINGS_UX_MIGRATION)
+    fun isEnabled_isSatelliteSessionStartedAndSelectedSubForSatellite_disabled() {
+        controller.selectedNbIotSatelliteSubscriptionCallback
+            .onSelectedNbIotSatelliteSubscriptionChanged(SUB_ID)
+        controller.satelliteModemStateCallback
+            .onSatelliteModemStateChanged(SatelliteManager.SATELLITE_MODEM_STATE_CONNECTED)
+
+        composeTestRule.setContent {
+            controller.Content()
+        }
+
+        composeTestRule.onNodeWithText(context.getString(R.string.select_automatically))
+            .assertIsNotEnabled()
+    }
+
+    @Test
+    @EnableFlags(Flags.FLAG_SATELLITE_OEM_SETTINGS_UX_MIGRATION)
+    fun isEnabled_isSatelliteSessionNotStartedButIsSelectedSubForSatellite_enabled() {
+        controller.selectedNbIotSatelliteSubscriptionCallback
+            .onSelectedNbIotSatelliteSubscriptionChanged(SUB_ID)
+        controller.satelliteModemStateCallback
+            .onSatelliteModemStateChanged(SatelliteManager.SATELLITE_MODEM_STATE_OFF)
+
+        composeTestRule.setContent {
+            controller.Content()
+        }
+
+        composeTestRule.onNodeWithText(context.getString(R.string.select_automatically))
+            .assertIsEnabled()
+    }
+
+    @Test
+    @EnableFlags(Flags.FLAG_SATELLITE_OEM_SETTINGS_UX_MIGRATION)
+    fun isEnabled_isSatelliteSessionStartedButNotSelectedSubForSatellite_enabled() {
+        controller.selectedNbIotSatelliteSubscriptionCallback
+            .onSelectedNbIotSatelliteSubscriptionChanged(0)
+        controller.satelliteModemStateCallback
+            .onSatelliteModemStateChanged(SatelliteManager.SATELLITE_MODEM_STATE_CONNECTED)
+
+        composeTestRule.setContent {
+            controller.Content()
+        }
+
+        composeTestRule.onNodeWithText(context.getString(R.string.select_automatically))
+            .assertIsEnabled()
+    }
+
+    @Test
     fun onClick_turnOff_startNetworkSelectActivity() {
         serviceState.isManualSelection = false
 
diff --git a/tests/unit/src/com/android/settings/network/telephony/EnabledNetworkModePreferenceControllerTest.java b/tests/unit/src/com/android/settings/network/telephony/EnabledNetworkModePreferenceControllerTest.java
index 54b78c7..95ae1d1 100644
--- a/tests/unit/src/com/android/settings/network/telephony/EnabledNetworkModePreferenceControllerTest.java
+++ b/tests/unit/src/com/android/settings/network/telephony/EnabledNetworkModePreferenceControllerTest.java
@@ -16,6 +16,9 @@
 
 package com.android.settings.network.telephony;
 
+import static android.telephony.satellite.SatelliteManager.SATELLITE_MODEM_STATE_CONNECTED;
+import static android.telephony.satellite.SatelliteManager.SATELLITE_MODEM_STATE_OFF;
+
 import static androidx.lifecycle.Lifecycle.Event.ON_START;
 
 import static com.android.settings.network.telephony.TelephonyConstants.RadioAccessFamily.CDMA;
@@ -29,12 +32,15 @@
 import static com.google.common.truth.Truth.assertThat;
 
 import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
 import static org.mockito.Mockito.doReturn;
 import static org.mockito.Mockito.spy;
 import static org.mockito.Mockito.when;
 
 import android.content.Context;
 import android.os.PersistableBundle;
+import android.platform.test.annotations.EnableFlags;
 import android.telephony.CarrierConfigManager;
 import android.telephony.RadioAccessFamily;
 import android.telephony.ServiceState;
@@ -51,6 +57,7 @@
 import androidx.test.core.app.ApplicationProvider;
 import androidx.test.ext.junit.runners.AndroidJUnit4;
 
+import com.android.settings.flags.Flags;
 import com.android.settings.network.CarrierConfigCache;
 import com.android.settingslib.core.lifecycle.Lifecycle;
 
@@ -296,6 +303,48 @@
 
     @UiThreadTest
     @Test
+    @EnableFlags(Flags.FLAG_SATELLITE_OEM_SETTINGS_UX_MIGRATION)
+    public void updateState_satelliteIsStartedAndSelectedSubForSatellite_disablePreference() {
+        mController.mSatelliteModemStateCallback
+                .onSatelliteModemStateChanged(SATELLITE_MODEM_STATE_CONNECTED);
+        mController.mSelectedNbIotSatelliteSubscriptionCallback
+                .onSelectedNbIotSatelliteSubscriptionChanged(SUB_ID);
+
+        mController.updateState(mPreference);
+
+        assertFalse(mPreference.isEnabled());
+    }
+
+    @UiThreadTest
+    @Test
+    @EnableFlags(Flags.FLAG_SATELLITE_OEM_SETTINGS_UX_MIGRATION)
+    public void updateState_satelliteIsIdle_enablePreference() {
+        mController.mSatelliteModemStateCallback
+                .onSatelliteModemStateChanged(SATELLITE_MODEM_STATE_OFF);
+        mController.mSelectedNbIotSatelliteSubscriptionCallback
+                .onSelectedNbIotSatelliteSubscriptionChanged(SUB_ID);
+
+        mController.updateState(mPreference);
+
+        assertTrue(mPreference.isEnabled());
+    }
+
+    @UiThreadTest
+    @Test
+    @EnableFlags(Flags.FLAG_SATELLITE_OEM_SETTINGS_UX_MIGRATION)
+    public void updateState_notSelectedSubForSatellite_enablePreference() {
+        mController.mSatelliteModemStateCallback
+                .onSatelliteModemStateChanged(SATELLITE_MODEM_STATE_CONNECTED);
+        mController.mSelectedNbIotSatelliteSubscriptionCallback
+                .onSelectedNbIotSatelliteSubscriptionChanged(0);
+
+        mController.updateState(mPreference);
+
+        assertTrue(mPreference.isEnabled());
+    }
+
+    @UiThreadTest
+    @Test
     public void onPreferenceChange_updateSuccess() {
         mockEnabledNetworkMode(TelephonyManager.NETWORK_MODE_LTE_GSM_WCDMA);
         doReturn(true).when(mTelephonyManager).setPreferredNetworkTypeBitmask(
diff --git a/tests/unit/src/com/android/settings/network/telephony/PreferredNetworkModePreferenceControllerTest.java b/tests/unit/src/com/android/settings/network/telephony/PreferredNetworkModePreferenceControllerTest.java
index d397291..e0a5c18 100644
--- a/tests/unit/src/com/android/settings/network/telephony/PreferredNetworkModePreferenceControllerTest.java
+++ b/tests/unit/src/com/android/settings/network/telephony/PreferredNetworkModePreferenceControllerTest.java
@@ -16,12 +16,17 @@
 
 package com.android.settings.network.telephony;
 
+import static android.telephony.satellite.SatelliteManager.SATELLITE_MODEM_STATE_CONNECTED;
+import static android.telephony.satellite.SatelliteManager.SATELLITE_MODEM_STATE_OFF;
+
 import static com.android.settings.network.telephony.TelephonyConstants.RadioAccessFamily.GSM;
 import static com.android.settings.network.telephony.TelephonyConstants.RadioAccessFamily.RAF_TD_SCDMA;
 import static com.android.settings.network.telephony.TelephonyConstants.RadioAccessFamily.WCDMA;
 
 import static com.google.common.truth.Truth.assertThat;
 
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
 import static org.mockito.Mockito.doReturn;
 import static org.mockito.Mockito.spy;
 import static org.mockito.Mockito.times;
@@ -30,15 +35,18 @@
 
 import android.content.Context;
 import android.os.PersistableBundle;
+import android.platform.test.annotations.EnableFlags;
 import android.telephony.RadioAccessFamily;
 import android.telephony.ServiceState;
 import android.telephony.SubscriptionManager;
 import android.telephony.TelephonyManager;
 
 import androidx.preference.ListPreference;
+import androidx.test.annotation.UiThreadTest;
 import androidx.test.core.app.ApplicationProvider;
 import androidx.test.ext.junit.runners.AndroidJUnit4;
 
+import com.android.settings.flags.Flags;
 import com.android.settings.network.CarrierConfigCache;
 import com.android.settings.testutils.ResourcesUtils;
 
@@ -105,6 +113,48 @@
     }
 
     @Test
+    @UiThreadTest
+    @EnableFlags(Flags.FLAG_SATELLITE_OEM_SETTINGS_UX_MIGRATION)
+    public void updateState_satelliteIsStartedAndSelectedSubForSatellite_disablePreference() {
+        mController.mSatelliteModemStateCallback
+                .onSatelliteModemStateChanged(SATELLITE_MODEM_STATE_CONNECTED);
+        mController.mSelectedNbIotSatelliteSubscriptionCallback
+                .onSelectedNbIotSatelliteSubscriptionChanged(SUB_ID);
+
+        mController.updateState(mPreference);
+
+        assertFalse(mPreference.isEnabled());
+    }
+
+    @Test
+    @UiThreadTest
+    @EnableFlags(Flags.FLAG_SATELLITE_OEM_SETTINGS_UX_MIGRATION)
+    public void updateState_satelliteIsIdle_enablePreference() {
+        mController.mSatelliteModemStateCallback
+                .onSatelliteModemStateChanged(SATELLITE_MODEM_STATE_OFF);
+        mController.mSelectedNbIotSatelliteSubscriptionCallback
+                .onSelectedNbIotSatelliteSubscriptionChanged(SUB_ID);
+
+        mController.updateState(mPreference);
+
+        assertTrue(mPreference.isEnabled());
+    }
+
+    @Test
+    @UiThreadTest
+    @EnableFlags(Flags.FLAG_SATELLITE_OEM_SETTINGS_UX_MIGRATION)
+    public void updateState_notSelectedSubForSatellite_enablePreference() {
+        mController.mSatelliteModemStateCallback
+                .onSatelliteModemStateChanged(SATELLITE_MODEM_STATE_CONNECTED);
+        mController.mSelectedNbIotSatelliteSubscriptionCallback
+                .onSelectedNbIotSatelliteSubscriptionChanged(0);
+
+        mController.updateState(mPreference);
+
+        assertTrue(mPreference.isEnabled());
+    }
+
+    @Test
     public void onPreferenceChange_updateNetworkMode() {
         mController.onPreferenceChange(mPreference,
                 String.valueOf(TelephonyManager.NETWORK_MODE_LTE_TDSCDMA));
diff --git a/tests/unit/src/com/android/settings/network/telephony/SatelliteSettingsPreferenceCategoryControllerTest.java b/tests/unit/src/com/android/settings/network/telephony/SatelliteSettingsPreferenceCategoryControllerTest.java
index 3b6e943..299ea13 100644
--- a/tests/unit/src/com/android/settings/network/telephony/SatelliteSettingsPreferenceCategoryControllerTest.java
+++ b/tests/unit/src/com/android/settings/network/telephony/SatelliteSettingsPreferenceCategoryControllerTest.java
@@ -16,35 +16,32 @@
 
 package com.android.settings.network.telephony;
 
-import static com.android.settings.core.BasePreferenceController.AVAILABLE;
-import static com.android.settings.core.BasePreferenceController.CONDITIONALLY_UNAVAILABLE;
+import static android.telephony.NetworkRegistrationInfo.SERVICE_TYPE_DATA;
+import static android.telephony.NetworkRegistrationInfo.SERVICE_TYPE_SMS;
+
+import static com.android.settings.core.BasePreferenceController.AVAILABLE_UNSEARCHABLE;
 import static com.android.settings.core.BasePreferenceController.UNSUPPORTED_ON_DEVICE;
 
 import static com.google.common.truth.Truth.assertThat;
 
 import static org.mockito.Mockito.spy;
-import static org.mockito.Mockito.when;
 
 import android.content.Context;
 import android.os.Looper;
-import android.os.PersistableBundle;
-import android.platform.test.annotations.DisableFlags;
-import android.platform.test.annotations.EnableFlags;
-import android.platform.test.flag.junit.SetFlagsRule;
-import android.telephony.CarrierConfigManager;
-import android.telephony.satellite.SatelliteManager;
 
+import androidx.preference.Preference;
+import androidx.preference.PreferenceCategory;
+import androidx.preference.PreferenceManager;
+import androidx.preference.PreferenceScreen;
 import androidx.test.core.app.ApplicationProvider;
 import androidx.test.ext.junit.runners.AndroidJUnit4;
 
-import com.android.internal.telephony.flags.Flags;
-import com.android.settings.network.CarrierConfigCache;
+import com.android.settings.R;
 
 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;
 
@@ -55,16 +52,9 @@
 
     @Rule
     public final MockitoRule mMockitoRule = MockitoJUnit.rule();
-    @Rule
-    public final SetFlagsRule mSetFlagsRule = new SetFlagsRule();
-
-    @Mock
-    private CarrierConfigCache mCarrierConfigCache;
 
     private Context mContext = null;
-    private SatelliteManager mSatelliteManager = null;
     private SatelliteSettingsPreferenceCategoryController mController = null;
-    private PersistableBundle mCarrierConfig = new PersistableBundle();
 
     @Before
     public void setUp() {
@@ -72,25 +62,38 @@
             Looper.prepare();
         }
         mContext = spy(ApplicationProvider.getApplicationContext());
-        mSatelliteManager = new SatelliteManager(mContext);
-        CarrierConfigCache.setTestInstance(mContext, mCarrierConfigCache);
-        when(mContext.getSystemService(SatelliteManager.class)).thenReturn(mSatelliteManager);
         mController = new SatelliteSettingsPreferenceCategoryController(mContext, KEY);
     }
 
     @Test
-    @DisableFlags(Flags.FLAG_CARRIER_ENABLED_SATELLITE_FLAG)
-    public void getAvailabilityStatus_featureDisabled_returnUnsupport() {
+    public void getAvailabilityStatus_default_returnUnsupported() {
         int result = mController.getAvailabilityStatus(TEST_SUB_ID);
-
         assertThat(result).isEqualTo(UNSUPPORTED_ON_DEVICE);
     }
 
     @Test
-    @EnableFlags(Flags.FLAG_CARRIER_ENABLED_SATELLITE_FLAG)
-    public void getAvailabilityStatus_noSatellite_returnUnsupport() {
-        when(mContext.getSystemService(SatelliteManager.class)).thenReturn(null);
-        mController = new SatelliteSettingsPreferenceCategoryController(mContext, KEY);
+    public void getAvailabilityStatus_hasAvailablePreference_returnAvailableUnsearchable() {
+        PreferenceManager preferenceManager = new PreferenceManager(mContext);
+        PreferenceScreen preferenceScreen = preferenceManager.createPreferenceScreen(mContext);
+        PreferenceCategory preferenceCategory = new PreferenceCategory(mContext);
+        preferenceCategory.setKey(KEY);
+        preferenceScreen.addPreference(preferenceCategory);
+        preferenceCategory.addPreference(new Preference(mContext));
+        mController.displayPreference(preferenceScreen);
+
+        int result = mController.getAvailabilityStatus(TEST_SUB_ID);
+
+        assertThat(result).isEqualTo(AVAILABLE_UNSEARCHABLE);
+    }
+
+    @Test
+    public void getAvailabilityStatus_noAvailablePreference_returnUnsupported() {
+        PreferenceManager preferenceManager = new PreferenceManager(mContext);
+        PreferenceScreen preferenceScreen = preferenceManager.createPreferenceScreen(mContext);
+        PreferenceCategory preferenceCategory = new PreferenceCategory(mContext);
+        preferenceCategory.setKey(KEY);
+        preferenceScreen.addPreference(preferenceCategory);
+        mController.displayPreference(preferenceScreen);
 
         int result = mController.getAvailabilityStatus(TEST_SUB_ID);
 
@@ -98,30 +101,37 @@
     }
 
     @Test
-    @EnableFlags(Flags.FLAG_CARRIER_ENABLED_SATELLITE_FLAG)
-    public void getAvailabilityStatus_carrierIsNotSupport_returnUnavailable() {
-        when(mContext.getSystemService(SatelliteManager.class)).thenReturn(null);
-        mCarrierConfig.putBoolean(
-                CarrierConfigManager.KEY_SATELLITE_ATTACH_SUPPORTED_BOOL,
-                false);
-        when(mCarrierConfigCache.getConfigForSubId(TEST_SUB_ID)).thenReturn(mCarrierConfig);
+    public void setPreferenceTitle_hasDataService_showConnectivity() {
+        PreferenceManager preferenceManager = new PreferenceManager(mContext);
+        PreferenceScreen preferenceScreen = preferenceManager.createPreferenceScreen(mContext);
+        PreferenceCategory preferenceCategory = new PreferenceCategory(mContext);
+        preferenceCategory.setKey(KEY);
+        preferenceScreen.addPreference(preferenceCategory);
+        preferenceCategory.addPreference(new Preference(mContext));
+        mController.displayPreference(preferenceScreen);
 
-        int result = mController.getAvailabilityStatus(TEST_SUB_ID);
+        mController.mCarrierRoamingNtnModeCallback.onCarrierRoamingNtnAvailableServicesChanged(
+                new int[]{SERVICE_TYPE_DATA});
 
-        assertThat(result).isEqualTo(CONDITIONALLY_UNAVAILABLE);
+        assertThat(preferenceCategory.getTitle()).isEqualTo(
+                mContext.getString(R.string.title_satellite_setting_connectivity));
     }
 
+
     @Test
-    @EnableFlags(Flags.FLAG_CARRIER_ENABLED_SATELLITE_FLAG)
-    public void getAvailabilityStatus_carrierIsSupport_returnAvailable() {
-        when(mContext.getSystemService(SatelliteManager.class)).thenReturn(null);
-        mCarrierConfig.putBoolean(
-                CarrierConfigManager.KEY_SATELLITE_ATTACH_SUPPORTED_BOOL,
-                true);
-        when(mCarrierConfigCache.getConfigForSubId(TEST_SUB_ID)).thenReturn(mCarrierConfig);
+    public void setPreferenceTitle_hasSmsService_showMessaging() {
+        PreferenceManager preferenceManager = new PreferenceManager(mContext);
+        PreferenceScreen preferenceScreen = preferenceManager.createPreferenceScreen(mContext);
+        PreferenceCategory preferenceCategory = new PreferenceCategory(mContext);
+        preferenceCategory.setKey(KEY);
+        preferenceScreen.addPreference(preferenceCategory);
+        preferenceCategory.addPreference(new Preference(mContext));
+        mController.displayPreference(preferenceScreen);
 
-        int result = mController.getAvailabilityStatus(TEST_SUB_ID);
+        mController.mCarrierRoamingNtnModeCallback.onCarrierRoamingNtnAvailableServicesChanged(
+                new int[]{SERVICE_TYPE_SMS});
 
-        assertThat(result).isEqualTo(AVAILABLE);
+        assertThat(preferenceCategory.getTitle()).isEqualTo(
+                mContext.getString(R.string.satellite_setting_title));
     }
 }
diff --git a/tests/unit/src/com/android/settings/network/telephony/SatelliteSettingsPreferenceControllerTest.java b/tests/unit/src/com/android/settings/network/telephony/SatelliteSettingsPreferenceControllerTest.java
new file mode 100644
index 0000000..6aa48e3
--- /dev/null
+++ b/tests/unit/src/com/android/settings/network/telephony/SatelliteSettingsPreferenceControllerTest.java
@@ -0,0 +1,177 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.settings.network.telephony;
+
+import static android.telephony.NetworkRegistrationInfo.SERVICE_TYPE_DATA;
+import static android.telephony.NetworkRegistrationInfo.SERVICE_TYPE_SMS;
+
+import static com.android.settings.core.BasePreferenceController.AVAILABLE;
+import static com.android.settings.core.BasePreferenceController.CONDITIONALLY_UNAVAILABLE;
+import static com.android.settings.core.BasePreferenceController.UNSUPPORTED_ON_DEVICE;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.Mockito.spy;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+import android.content.Context;
+import android.os.Looper;
+import android.os.PersistableBundle;
+import android.platform.test.annotations.EnableFlags;
+import android.telephony.CarrierConfigManager;
+import android.telephony.TelephonyManager;
+import android.telephony.satellite.SatelliteManager;
+
+import androidx.preference.Preference;
+import androidx.test.core.app.ApplicationProvider;
+import androidx.test.ext.junit.runners.AndroidJUnit4;
+
+import com.android.internal.telephony.flags.Flags;
+import com.android.settings.R;
+import com.android.settings.network.CarrierConfigCache;
+
+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;
+
+@RunWith(AndroidJUnit4.class)
+public class SatelliteSettingsPreferenceControllerTest {
+    private static final String KEY = "key";
+    private static final int TEST_SUB_ID = 0;
+
+    @Rule
+    public final MockitoRule mMockitoRule = MockitoJUnit.rule();
+
+    @Mock
+    private CarrierConfigCache mCarrierConfigCache;
+    @Mock
+    private TelephonyManager mTelephonyManager;
+
+    private Context mContext = null;
+    private SatelliteManager mSatelliteManager;
+    private SatelliteSettingPreferenceController mController = null;
+    private PersistableBundle mCarrierConfig = new PersistableBundle();
+
+    @Before
+    public void setUp() {
+        if (Looper.myLooper() == null) {
+            Looper.prepare();
+        }
+        mContext = spy(ApplicationProvider.getApplicationContext());
+        mSatelliteManager = new SatelliteManager(mContext);
+        CarrierConfigCache.setTestInstance(mContext, mCarrierConfigCache);
+        when(mContext.getSystemService(SatelliteManager.class)).thenReturn(mSatelliteManager);
+        when(mContext.getSystemService(TelephonyManager.class)).thenReturn(mTelephonyManager);
+        when(mTelephonyManager.createForSubscriptionId(TEST_SUB_ID)).thenReturn(mTelephonyManager);
+        mController = spy(new SatelliteSettingPreferenceController(mContext, KEY));
+    }
+
+    @Test
+    @EnableFlags(Flags.FLAG_CARRIER_ENABLED_SATELLITE_FLAG)
+    public void getAvailabilityStatus_noSatellite_returnUnsupport() {
+        when(mContext.getSystemService(SatelliteManager.class)).thenReturn(null);
+        mController = new SatelliteSettingPreferenceController(mContext, KEY);
+
+        int result = mController.getAvailabilityStatus(TEST_SUB_ID);
+
+        assertThat(result).isEqualTo(UNSUPPORTED_ON_DEVICE);
+    }
+
+    @Test
+    @EnableFlags(Flags.FLAG_CARRIER_ENABLED_SATELLITE_FLAG)
+    public void getAvailabilityStatus_carrierIsNotSupport_returnUnavailable() {
+        when(mContext.getSystemService(SatelliteManager.class)).thenReturn(null);
+        mCarrierConfig.putBoolean(
+                CarrierConfigManager.KEY_SATELLITE_ATTACH_SUPPORTED_BOOL,
+                false);
+        when(mCarrierConfigCache.getConfigForSubId(TEST_SUB_ID)).thenReturn(mCarrierConfig);
+
+        int result = mController.getAvailabilityStatus(TEST_SUB_ID);
+
+        assertThat(result).isEqualTo(CONDITIONALLY_UNAVAILABLE);
+    }
+
+    @Test
+    @EnableFlags(Flags.FLAG_CARRIER_ENABLED_SATELLITE_FLAG)
+    public void getAvailabilityStatus_carrierIsSupport_returnAvailable() {
+        when(mContext.getSystemService(SatelliteManager.class)).thenReturn(null);
+        mCarrierConfig.putBoolean(
+                CarrierConfigManager.KEY_SATELLITE_ATTACH_SUPPORTED_BOOL,
+                true);
+        when(mCarrierConfigCache.getConfigForSubId(TEST_SUB_ID)).thenReturn(mCarrierConfig);
+
+        int result = mController.getAvailabilityStatus(TEST_SUB_ID);
+
+        assertThat(result).isEqualTo(AVAILABLE);
+    }
+
+    @Test
+    @EnableFlags(com.android.settings.flags.Flags.FLAG_SATELLITE_OEM_SETTINGS_UX_MIGRATION)
+    public void getAvailabilityStatus_registerTelephonyCallback_success() {
+        mController.init(TEST_SUB_ID);
+        mController.onResume(null);
+
+        verify(mTelephonyManager).registerTelephonyCallback(any(), any());
+    }
+
+    @Test
+    @EnableFlags(com.android.settings.flags.Flags.FLAG_SATELLITE_OEM_SETTINGS_UX_MIGRATION)
+    public void getAvailabilityStatus_unregisterTelephonyCallback_success() {
+        mController.init(TEST_SUB_ID);
+        mController.onPause(null);
+
+        verify(mTelephonyManager).unregisterTelephonyCallback(any());
+    }
+
+    @Test
+    @EnableFlags(com.android.settings.flags.Flags.FLAG_SATELLITE_OEM_SETTINGS_UX_MIGRATION)
+    public void getAvailabilityStatus_hasServiceDataType_showDataUi() {
+        mController.init(TEST_SUB_ID);
+        Preference preference = new Preference(mContext);
+        preference.setKey(KEY);
+        preference.setTitle("test title");
+        mController.updateState(preference);
+
+        mController.mCarrierRoamingNtnModeCallback.onCarrierRoamingNtnAvailableServicesChanged(
+                new int[]{SERVICE_TYPE_SMS, SERVICE_TYPE_DATA});
+
+        assertThat(preference.getTitle()).isEqualTo(
+                mContext.getString(R.string.title_satellite_setting_connectivity));
+    }
+
+    @Test
+    @EnableFlags(com.android.settings.flags.Flags.FLAG_SATELLITE_OEM_SETTINGS_UX_MIGRATION)
+    public void getAvailabilityStatus_onlyHasServiceSmsType_showSmsUi() {
+        mController.init(TEST_SUB_ID);
+        Preference preference = new Preference(mContext);
+        preference.setKey(KEY);
+        preference.setTitle("test title");
+        mController.updateState(preference);
+
+        mController.mCarrierRoamingNtnModeCallback.onCarrierRoamingNtnAvailableServicesChanged(
+                new int[]{SERVICE_TYPE_SMS});
+
+        assertThat(preference.getTitle()).isEqualTo(
+                mContext.getString(R.string.satellite_setting_title));
+    }
+}