Merge "[Audiosharing] Add new strings" into main
diff --git a/aconfig/settings_biometrics_framework_flag_declarations.aconfig b/aconfig/settings_biometrics_framework_flag_declarations.aconfig
index e787da0..e81c68e 100644
--- a/aconfig/settings_biometrics_framework_flag_declarations.aconfig
+++ b/aconfig/settings_biometrics_framework_flag_declarations.aconfig
@@ -14,3 +14,10 @@
   description: "This flag enables or disables the Fingerprint v2 enrollment"
   bug: "295206723"
 }
+
+flag {
+  name: "active_unlock_finish_parent"
+  namespace: "biometrics_framework"
+  description: "This flag enables the Active Unlock settings activity to finish its parent activity"
+  bug: "343576960"
+}
diff --git a/aconfig/settings_connecteddevice_flag_declarations.aconfig b/aconfig/settings_connecteddevice_flag_declarations.aconfig
index b255096..ee0c233 100644
--- a/aconfig/settings_connecteddevice_flag_declarations.aconfig
+++ b/aconfig/settings_connecteddevice_flag_declarations.aconfig
@@ -2,13 +2,6 @@
 container: "system_ext"
 
 flag {
-  name: "enable_subsequent_pair_settings_integration"
-  namespace: "pixel_cross_device_control"
-  description: "Gates whether to enable subsequent pair Settings integration."
-  bug: "299405720"
-}
-
-flag {
   name: "rotation_connected_display_setting"
   namespace: "display_manager"
   description: "Allow changing rotation of the connected display."
@@ -47,4 +40,4 @@
     metadata {
         purpose: PURPOSE_BUGFIX
     }
-}
\ No newline at end of file
+}
diff --git a/aconfig/settings_experience_flag_declarations.aconfig b/aconfig/settings_experience_flag_declarations.aconfig
index e79b515..d5caccf 100644
--- a/aconfig/settings_experience_flag_declarations.aconfig
+++ b/aconfig/settings_experience_flag_declarations.aconfig
@@ -17,13 +17,3 @@
         purpose: PURPOSE_BUGFIX
     }
 }
-
-flag {
-    name: "internet_preference_controller_v2"
-    namespace: "settings_experience"
-    description: "New InternetPreferenceControllerV2."
-    bug: "339884322"
-    metadata {
-        purpose: PURPOSE_BUGFIX
-    }
-}
diff --git a/res/layout/dialog_custom_title_audio_sharing.xml b/res/layout/dialog_custom_title_audio_sharing.xml
index 86e0010..692cbc7 100644
--- a/res/layout/dialog_custom_title_audio_sharing.xml
+++ b/res/layout/dialog_custom_title_audio_sharing.xml
@@ -35,7 +35,8 @@
         android:layout_width="match_parent"
         android:layout_height="wrap_content"
         android:layout_gravity="center"
-        android:maxLines="2"
+        android:maxLines="3"
+        android:ellipsize="end"
         android:paddingTop="14dp"
         android:textAlignment="center"
         android:textSize="24sp" />
diff --git a/res/values/arrays.xml b/res/values/arrays.xml
index 8cbf5dc..8e5519f 100644
--- a/res/values/arrays.xml
+++ b/res/values/arrays.xml
@@ -1536,6 +1536,7 @@
         <item>@*android:drawable/ic_zen_mode_icon_group_of_people</item>
         <item>@*android:drawable/ic_zen_mode_icon_lightbulb</item>
         <item>@*android:drawable/ic_zen_mode_type_schedule_calendar</item>
+        <item>@*android:drawable/ic_zen_mode_type_special_dnd</item>
         <!-- Sports -->
         <item>@*android:drawable/ic_zen_mode_icon_running</item>
         <item>@*android:drawable/ic_zen_mode_icon_golf</item>
@@ -1561,7 +1562,6 @@
         <!-- Other activities -->
         <item>@*android:drawable/ic_zen_mode_icon_train</item>
         <item>@*android:drawable/ic_zen_mode_type_driving</item> <!-- Car -->
-        <item>@*android:drawable/ic_zen_mode_icon_croissant</item>
         <item>@*android:drawable/ic_zen_mode_icon_fork_and_knife</item>
         <item>@*android:drawable/ic_zen_mode_icon_shopping_cart</item>
         <item>@*android:drawable/ic_zen_mode_icon_child</item>
@@ -1587,6 +1587,7 @@
         <item>Group of people</item>
         <item>Lightbulb</item>
         <item>Calendar</item>
+        <item>Do Not Disturb</item>
         <!-- Sports -->
         <item>Person running</item>
         <item>Golf</item>
@@ -1612,7 +1613,6 @@
         <!-- Other activities -->
         <item>Train</item>
         <item>Car</item>
-        <item>Croissant</item>
         <item>Fork and knife</item>
         <item>Shopping cart</item>
         <item>Child</item>
diff --git a/res/values/strings.xml b/res/values/strings.xml
index 5a4f55b..3ec5904 100644
--- a/res/values/strings.xml
+++ b/res/values/strings.xml
@@ -937,7 +937,7 @@
     <!-- Message showing that multiple fingerprints, face, and the current watch is set up. Shown for a menu item that launches fingerprint, face,  and active unlock settings or enrollment. [CHAR LIMIT=80]-->
     <string name="security_settings_fingerprint_multiple_face_watch_preference_summary">Face, fingerprints, and <xliff:g id="watch" example="Dani's Watch">%s</xliff:g> added</string>
     <!-- Description for mandatory biometrics prompt-->
-    <string name="mandatory_biometrics_prompt_description">Identity Check is on</string>
+    <string name="mandatory_biometrics_prompt_description">Identity Check is on and requires a biometric</string>
     <!-- RemoteAuth unlock enrollment and settings --><skip />
     <!-- Title shown for menu item that launches watch unlock settings. [CHAR LIMIT=40] -->
     <string name ="security_settings_remoteauth_preference_title">Remote Authenticator Unlock</string>
@@ -7979,7 +7979,7 @@
     <string name="zen_mode_settings_title">Do Not Disturb</string>
 
     <!-- Zen Modes: Title for the Modes option and associated settings page. [CHAR LIMIT=50]-->
-    <string name="zen_modes_list_title">Priority Modes</string>
+    <string name="zen_modes_list_title">Modes</string>
 
     <!-- Zen Modes: Intro text describing the feature. [CHAR LIMIT=NONE]-->
     <string name="zen_modes_list_intro">Minimize distractions and take control of your attention with modes for sleep, work, driving, and everything in between.</string>
@@ -7993,18 +7993,18 @@
     <!-- Zen Modes: Option to add an automatic schedule for a mode. [CHAR_LIMIT=40] -->
     <string name="zen_mode_select_schedule">Set a schedule</string>
 
-    <!-- Priority Modes: Title of the dialog used to choose an automatic schedule for a mode. [CHAR_LIMIT=40] -->
+    <!-- Modes: Title of the dialog used to choose an automatic schedule for a mode. [CHAR_LIMIT=40] -->
     <string name="zen_mode_select_schedule_title">Schedule based on</string>
 
-    <!-- Priority Modes: Option to choose a time-based schedule for a mode. [CHAR_LIMIT=40] -->
+    <!-- Modes: Option to choose a time-based schedule for a mode. [CHAR_LIMIT=40] -->
     <string name="zen_mode_select_schedule_time">Day and time</string>
-    <!-- Priority Modes: Example text for the option to choose a time-based schedule for a mode. [CHAR_LIMIT=60] -->
+    <!-- Modes: Example text for the option to choose a time-based schedule for a mode. [CHAR_LIMIT=60] -->
     <string name="zen_mode_select_schedule_time_example">\"9 AM - 5 PM weekdays\"</string>
 
-    <!-- Priority Modes: Option to choose a calendar-events-based schedule for a mode. [CHAR_LIMIT=40] -->
+    <!-- Modes: Option to choose a calendar-events-based schedule for a mode. [CHAR_LIMIT=40] -->
     <string name="zen_mode_select_schedule_calendar">Calendar events</string>
 
-    <!-- Priority Modes: Summary for the modes segment, when at least one mode is active. [CHAR LIMIT=NONE]-->
+    <!-- Modes: Summary for the modes segment, when at least one mode is active. [CHAR LIMIT=NONE]-->
     <string name="zen_modes_summary_some_active">
         {count, plural, offset:2
             =0    {}
@@ -8015,7 +8015,7 @@
         }
     </string>
 
-    <!-- Priority Modes: Summary for the modes segment, when no modes are active. [CHAR LIMIT=NONE]-->
+    <!-- Modes: Summary for the modes segment, when no modes are active. [CHAR LIMIT=NONE]-->
     <string name="zen_modes_summary_none_active">
         {count, plural,
             =0    {}
@@ -8024,40 +8024,40 @@
         }
     </string>
 
-    <!-- Priority Modes: Short text that indicates that a mode is currently on (active). [CHAR_LIMIT=10] -->
+    <!-- Modes: Short text that indicates that a mode is currently on (active). [CHAR_LIMIT=10] -->
     <string name="zen_mode_active_text">ON</string>
 
-    <!-- Priority Modes: Format string for the "current state + trigger description summary for rules in the list. [CHAR_LIMIT=10] -->
+    <!-- Modes: Format string for the "current state + trigger description summary for rules in the list. [CHAR_LIMIT=10] -->
     <string name="zen_mode_format_status_and_trigger" translatable="false"><xliff:g id="current_status" example="ON">%1$s</xliff:g> • <xliff:g id="trigger_description" example="Mon-Fri, 23:00-7:00">%2$s</xliff:g></string>
 
-    <!-- Priority Modes: Indicates that a mode is disabled and needs to be configured. [CHAR_LIMIT=40] -->
+    <!-- Modes: Indicates that a mode is disabled and needs to be configured. [CHAR_LIMIT=40] -->
     <string name="zen_mode_disabled_needs_setup">Not set</string>
 
-    <!-- Priority Modes: Indicates that a mode is disabled by the user. [CHAR_LIMIT=40] -->
+    <!-- Modes: Indicates that a mode is disabled by the user. [CHAR_LIMIT=40] -->
     <string name="zen_mode_disabled_by_user">Disabled</string>
 
-    <!-- Priority Modes: Title of the "Create a mode" dialog, to choose the mode type. [CHAR_LIMIT=30] -->
+    <!-- Modes: Title of the "Create a mode" dialog, to choose the mode type. [CHAR_LIMIT=30] -->
     <string name="zen_mode_new_title">Create a mode</string>
 
-    <!-- Priority Modes: Option to add a "custom" mode in the "Add a mode" dialog. [CHAR_LIMIT=20] -->
+    <!-- Modes: Option to add a "custom" mode in the "Add a mode" dialog. [CHAR_LIMIT=20] -->
     <string name="zen_mode_new_option_custom">Custom</string>
 
-    <!-- Priority Modes: Caption of the button to turn on a mode [CHAR LIMIT=20] -->
+    <!-- Modes: Caption of the button to turn on a mode [CHAR LIMIT=20] -->
     <string name="zen_mode_action_activate">Turn on now</string>
 
-    <!-- Priority Modes: Caption of the button to turn off a currently active mode [CHAR LIMIT=20] -->
+    <!-- Modes: Caption of the button to turn off a currently active mode [CHAR LIMIT=20] -->
     <string name="zen_mode_action_deactivate">Turn off</string>
 
-    <!-- Priority Modes: Text to display if a mode isn't found [CHAR LIMIT=40] -->
+    <!-- Modes: Text to display if a mode isn't found [CHAR LIMIT=40] -->
     <string name="zen_mode_not_found_text">Mode not found</string>
 
     <!-- Subtitle for the Do not Disturb slice. [CHAR LIMIT=50]-->
     <string name="zen_mode_slice_subtitle">Limit interruptions</string>
 
-    <!-- Priority Modes: Summary on a page prompting the user to set up/enable a mode [CHAR_LIMIT=NONE] -->
+    <!-- Modes: Summary on a page prompting the user to set up/enable a mode [CHAR_LIMIT=NONE] -->
     <string name="zen_mode_setup_page_summary">Block interruptions and distractions</string>
 
-    <!-- Priority Modes: Label on a button prompting the user to set up the mode with the given name. [CHAR_LIMIT=40] -->
+    <!-- Modes: Label on a button prompting the user to set up the mode with the given name. [CHAR_LIMIT=40] -->
     <string name="zen_mode_setup_button_label">Set up <xliff:g id="mode" example="My Mode">%1$s</xliff:g></string>
 
     <!-- Do not disturb: Title for the Do not Disturb dialog to turn on Do not disturb. [CHAR LIMIT=50]-->
@@ -8075,7 +8075,7 @@
     <!-- Do not disturb: Delete text button presented in a dialog to confirm the user would like to delete the selected DND rules. [CHAR LIMIT=30] -->
     <string name="zen_mode_schedule_delete">Delete</string>
 
-    <!-- Priority Modes: Menu option for renaming a mode on its configuration page [CHAR LIMIT=40] -->
+    <!-- Modes: Menu option for renaming a mode on its configuration page [CHAR LIMIT=40] -->
     <string name="zen_mode_menu_rename_mode">Rename</string>
 
     <!-- Do not disturb: Menu option for deleting a mode on its configuration page [CHAR LIMIT=40] -->
@@ -8096,11 +8096,11 @@
     <!-- Do not disturb: Title for settings section describing when the rule turns on automatically [CHAR LIMIT=30] -->
     <string name="zen_mode_automatic_trigger_title">When to turn on automatically</string>
 
-    <!-- Priority Modes: Title prompting a user to choose a calendar to use for an automatic rule [CHAR LIMIT=30] -->
+    <!-- Modes: Title prompting a user to choose a calendar to use for an automatic rule [CHAR LIMIT=30] -->
     <string name="zen_mode_set_calendar_title">Event schedule</string>
-    <!-- Priority Modes: Title prompting a user to choose a calendar to use for an automatic rule [CHAR LIMIT=30] -->
+    <!-- Modes: Title prompting a user to choose a calendar to use for an automatic rule [CHAR LIMIT=30] -->
     <string name="zen_mode_set_calendar_which_calendar">Turn on during events for</string>
-    <!-- Priority Modes: Title prompting a user to choose a calendar to use for an automatic rule [CHAR LIMIT=30] -->
+    <!-- Modes: Title prompting a user to choose a calendar to use for an automatic rule [CHAR LIMIT=30] -->
     <string name="zen_mode_set_calendar_which_reply">Where invite reply is</string>
 
     <!-- Do not disturb: Title prompting a user to set a time-based schedule to use for an automatic rule [CHAR LIMIT=30] -->
@@ -8139,9 +8139,9 @@
     <!--  Do not disturb: Subtitle for the Visual signals option to toggle on/off visual signals/alerts when the screen is on/when screen is off. [CHAR LIMIT=30] -->
     <string name="zen_mode_visual_signals_settings_subtitle">Allow visual signals</string>
 
-    <!-- Priority Modes: mode page section title [CHAR LIMIT=80] -->
+    <!-- Modes: mode page section title [CHAR LIMIT=80] -->
     <string name="mode_interruption_filter_title">Notification filters</string>
-    <!-- Priority Modes: mode page section title [CHAR LIMIT=80] -->
+    <!-- Modes: mode page section title [CHAR LIMIT=80] -->
     <string name="mode_device_effects_title">More settings</string>
 
     <!-- Summary for the Sound Do not Disturb option when DND isn't currently on. [CHAR LIMIT=NONE]-->
@@ -8859,12 +8859,12 @@
     <string name="nls_feature_reply_summary">It can reply to messages and take action on buttons in notifications, including snoozing or dismissing notifications and answering calls.</string>
     <string name="nls_feature_settings_title">Change settings</string>
     <string name="nls_feature_settings_summary">It can turn Do Not Disturb on or off and change related settings.</string>
-    <string name="nls_feature_modes_settings_summary">It can manage and activate Priority Modes, and change related settings.</string>
+    <string name="nls_feature_modes_settings_summary">It can manage and activate Modes, and change related settings.</string>
     <string name="notification_listener_disable_warning_summary">
         If you turn off notification access for <xliff:g id="notification_listener_name">%1$s</xliff:g>, Do Not Disturb access may also be turned off.
     </string>
     <string name="notification_listener_disable_modes_warning_summary">
-        If you turn off notification access for <xliff:g id="notification_listener_name">%1$s</xliff:g>, Priority Modes access may also be turned off.
+        If you turn off notification access for <xliff:g id="notification_listener_name">%1$s</xliff:g>, Modes access may also be turned off.
     </string>
     <string name="notification_listener_disable_warning_confirm">Turn off</string>
     <string name="notification_listener_disable_warning_cancel">Cancel</string>
@@ -9042,14 +9042,14 @@
     <!-- Sound & notification > Do Not Disturb access > Text to display when the list is empty. [CHAR LIMIT=NONE] -->
     <string name="zen_access_empty_text">No installed apps have requested Do Not Disturb access</string>
 
-    <!-- Special App Access: Title for managing Priority Modes access option. [CHAR LIMIT=40] -->
-    <string name="manage_zen_modes_access_title">Priority Modes access</string>
+    <!-- Special App Access: Title for managing Modes access option. [CHAR LIMIT=40] -->
+    <string name="manage_zen_modes_access_title">Modes access</string>
 
-    <!-- Button title that grants 'Priority Modes' permission to an app [CHAR_LIMIT=60]-->
-    <string name="zen_modes_access_detail_switch">Allow Priority Modes access</string>
+    <!-- Button title that grants 'Modes' permission to an app [CHAR_LIMIT=60]-->
+    <string name="zen_modes_access_detail_switch">Allow Modes access</string>
 
     <!-- Special App Access > Do Not Disturb access > Text to display when the list is empty. [CHAR LIMIT=NONE] -->
-    <string name="zen_modes_access_empty_text">No installed apps have requested Priority Modes access</string>
+    <string name="zen_modes_access_empty_text">No installed apps have requested Modes access</string>
 
     <!-- [CHAR LIMIT=NONE] Text appearing when app notifications are off -->
     <string name="app_notifications_off_desc">You haven\'t allowed notifications from this app</string>
@@ -9392,11 +9392,11 @@
             other {{app_1}, {app_2}, and # more can interrupt}
         }
     </string>
-    <!-- Priority Modes: Entry in the "apps that can bypass DND" list that corresponds to a work profile app (e.g. "Chrome (Work)" [CHAR LIMIT=15]. -->
+    <!-- Modes: Entry in the "apps that can bypass DND" list that corresponds to a work profile app (e.g. "Chrome (Work)" [CHAR LIMIT=15]. -->
     <string name="zen_mode_apps_work_app"><xliff:g id="app_label" example="Chrome">%s</xliff:g> (Work)</string>
     <!-- Text displayed (for a brief time) while the list of bypassing apps is being fetched. Will be replaced by a zen_mode_apps_subtext. [CHAR_LIMIT=60] -->
     <string name="zen_mode_apps_calculating">Calculating\u2026</string>
-    <!-- Priority Modes: Format for a string displayed when there are more items (e.g. apps, contacts) that can be shown. For example, we show (A)(B)(C)(+5), where this string represents the "+5" value. Needs to be as compact as possible, since it will be drawn in a really small area. [CHAR_LIMIT=4] -->
+    <!-- Modes: Format for a string displayed when there are more items (e.g. apps, contacts) that can be shown. For example, we show (A)(B)(C)(+5), where this string represents the "+5" value. Needs to be as compact as possible, since it will be drawn in a really small area. [CHAR_LIMIT=4] -->
     <string name="zen_mode_plus_n_items">+<xliff:g id="number" example="42">%d</xliff:g></string>
 
     <!-- [CHAR LIMIT=100] Zen mode settings: Allow apps to bypass DND -->
@@ -9501,76 +9501,76 @@
     <!-- [CHAR LIMIT=NONE] Zen mode summary spoken when changing mode by voice: Turn on all notifications. -->
     <string name="zen_mode_summary_always">Change to always interrupt</string>
 
-    <!-- Priority Modes: Title for the "rename mode" screen [CHAR LIMIT=20] -->
+    <!-- Modes: Title for the "rename mode" screen [CHAR LIMIT=20] -->
     <string name="zen_mode_rename_title">Edit mode</string>
 
-    <!-- Priority Modes: Title for the "add mode" screen [CHAR LIMIT=20] -->
+    <!-- Modes: Title for the "add mode" screen [CHAR LIMIT=20] -->
     <string name="zen_mode_new_custom_title">Create a mode</string>
 
-    <!-- Priority Modes: Default name for new custom modes [CHAR LIMIT=30] -->
+    <!-- Modes: Default name for new custom modes [CHAR LIMIT=30] -->
     <string name="zen_mode_new_custom_default_name">Custom mode</string>
 
-    <!-- Priority Modes: Hint for the EditText for editing a mode's name [CHAR LIMIT=30] -->
+    <!-- Modes: Hint for the EditText for editing a mode's name [CHAR LIMIT=30] -->
     <string name="zen_mode_edit_name_hint">Mode name</string>
 
-    <!-- Priority Modes: Trigger title for modes of type SCHEDULE_CALENDAR. [CHAR LIMIT=30] -->
+    <!-- Modes: Trigger title for modes of type SCHEDULE_CALENDAR. [CHAR LIMIT=30] -->
     <string name="zen_mode_trigger_title_schedule_calendar">Calendar events</string>
-    <!-- Priority Modes: Trigger title for modes of type BEDTIME. [CHAR LIMIT=30] -->
+    <!-- Modes: Trigger title for modes of type BEDTIME. [CHAR LIMIT=30] -->
     <string name="zen_mode_trigger_title_bedtime">Bedtime routine</string>
-    <!-- Priority Modes: Trigger title for modes of type DRIVING. [CHAR LIMIT=30] -->
+    <!-- Modes: Trigger title for modes of type DRIVING. [CHAR LIMIT=30] -->
     <string name="zen_mode_trigger_title_driving">While driving</string>
-    <!-- Priority Modes: Generic trigger title for modes of other types [CHAR LIMIT=30] -->
+    <!-- Modes: Generic trigger title for modes of other types [CHAR LIMIT=30] -->
     <string name="zen_mode_trigger_title_generic">App settings</string>
-    <!-- Priority Modes: Generic trigger summary for modes where the owner app did not provide a triggerDescription but did provide a configurationActivity to call [CHAR LIMIT=60] -->
+    <!-- Modes: Generic trigger summary for modes where the owner app did not provide a triggerDescription but did provide a configurationActivity to call [CHAR LIMIT=60] -->
     <string name="zen_mode_trigger_summary_settings_in_app">Info and settings in <xliff:g id="app_name" example="The Awesome App">%1$s</xliff:g></string>
-    <!-- Priority Modes: Generic trigger summary for modes where the owner app did not provide neither a triggerDescription nor a configurationActivity to call [CHAR LIMIT=60] -->
+    <!-- Modes: Generic trigger summary for modes where the owner app did not provide neither a triggerDescription nor a configurationActivity to call [CHAR LIMIT=60] -->
     <string name="zen_mode_trigger_summary_managed_by_app">Managed by <xliff:g id="app_name" example="The Awesome App">%1$s</xliff:g></string>
 
-    <!-- Priority Modes: Title of the confirmation dialog for disabling an enabled mode [CHAR LIMIT=20] -->
+    <!-- Modes: Title of the confirmation dialog for disabling an enabled mode [CHAR LIMIT=20] -->
     <string name="zen_mode_confirm_disable_mode_title">Disable <xliff:g id="mode_name" example="Driving Mode">%1$s</xliff:g>?</string>
-    <!-- Priority Modes: Message body of the confirmation dialog for disabling an enabled mode [CHAR LIMIT=NONE] -->
+    <!-- Modes: Message body of the confirmation dialog for disabling an enabled mode [CHAR LIMIT=NONE] -->
     <string name="zen_mode_confirm_disable_message">This mode will never turn on when disabled</string>
-    <!-- Priority Modes: Button to disable a mode [CHAR LIMIT=20] -->
+    <!-- Modes: Button to disable a mode [CHAR LIMIT=20] -->
     <string name="zen_mode_action_disable">Disable</string>
-    <!-- Priority Modes: Title of the confirmation dialog for enabling a disabled mode [CHAR LIMIT=20] -->
+    <!-- Modes: Title of the confirmation dialog for enabling a disabled mode [CHAR LIMIT=20] -->
     <string name="zen_mode_confirm_enable_mode_title">Enable <xliff:g id="mode_name" example="Driving Mode">%1$s</xliff:g>?</string>
-    <!-- Priority Modes: Message body of the confirmation dialog for enabling a disabled mode [CHAR LIMIT=NONE] -->
+    <!-- Modes: Message body of the confirmation dialog for enabling a disabled mode [CHAR LIMIT=NONE] -->
     <string name="zen_mode_confirm_enable_message">This mode may turn on automatically based on its settings</string>
-    <!-- Priority Modes: Button to disable a mode [CHAR LIMIT=20] -->
+    <!-- Modes: Button to disable a mode [CHAR LIMIT=20] -->
     <string name="zen_mode_action_enable">Enable</string>
 
-    <!-- Priority Modes: Blurb for a mode that activates during a fixed time schedule (e.g. 9:00-17:00). [CHAR LIMIT=NONE] -->
+    <!-- Modes: Blurb for a mode that activates during a fixed time schedule (e.g. 9:00-17:00). [CHAR LIMIT=NONE] -->
     <string name="zen_mode_blurb_schedule_time">Set a mode that follows a regular schedule</string>
-    <!-- Priority Modes: Blurb for a mode that activates during calendar events. [CHAR LIMIT=NONE] -->
+    <!-- Modes: Blurb for a mode that activates during calendar events. [CHAR LIMIT=NONE] -->
     <string name="zen_mode_blurb_schedule_calendar">Set a mode to sync with calendar events and invite responses</string>
-    <!-- Priority Modes: Blurb for a mode of type BEDTIME. [CHAR LIMIT=NONE] -->
+    <!-- Modes: Blurb for a mode of type BEDTIME. [CHAR LIMIT=NONE] -->
     <string name="zen_mode_blurb_bedtime">Design a calming sleep routine. Set alarms, dim the screen, and block notifications.</string>
-    <!-- Priority Modes: Blurb for a mode of type DRIVING. [CHAR LIMIT=NONE] -->
+    <!-- Modes: Blurb for a mode of type DRIVING. [CHAR LIMIT=NONE] -->
     <string name="zen_mode_blurb_driving">Prioritize safety on the road for a focused and distraction-free drive</string>
-    <!-- Priority Modes: Blurb for a mode of type IMMERSIVE. [CHAR LIMIT=NONE] -->
+    <!-- Modes: Blurb for a mode of type IMMERSIVE. [CHAR LIMIT=NONE] -->
     <string name="zen_mode_blurb_immersive">Block distractions or interruptions from your device to gain focus</string>
-    <!-- Priority Modes: Blurb for a mode of type THEATER. [CHAR LIMIT=NONE] -->
+    <!-- Modes: Blurb for a mode of type THEATER. [CHAR LIMIT=NONE] -->
     <string name="zen_mode_blurb_theater">Eliminate all distractions for a quiet environment</string>
-    <!-- Priority Modes: Blurb for a mode of type MANAGED. [CHAR LIMIT=NONE] -->
+    <!-- Modes: Blurb for a mode of type MANAGED. [CHAR LIMIT=NONE] -->
     <string name="zen_mode_blurb_managed">Personalize device experiences and settings for different users</string>
-    <!-- Priority Modes: Blurb for modes that are not of a specific type (OTHER, UNKNOWN). [CHAR LIMIT=NONE] -->
+    <!-- Modes: Blurb for modes that are not of a specific type (OTHER, UNKNOWN). [CHAR LIMIT=NONE] -->
     <string name="zen_mode_blurb_generic">Minimize interruptions by only allowing important people and apps to reach you</string>
 
-    <!-- Priority Modes: Inspirational text for a mode that activates during a fixed time schedule (e.g. 9:00-17:00). [CHAR LIMIT=NONE] -->
+    <!-- Modes: Inspirational text for a mode that activates during a fixed time schedule (e.g. 9:00-17:00). [CHAR LIMIT=NONE] -->
     <string name="zen_mode_inspiration_schedule_time">Set a mode that follows a regular schedule</string>
-    <!-- Priority Modes: Inspirational text for a mode that activates during calendar events. [CHAR LIMIT=NONE] -->
+    <!-- Modes: Inspirational text for a mode that activates during calendar events. [CHAR LIMIT=NONE] -->
     <string name="zen_mode_inspiration_schedule_calendar">Keep your device in sync with your day’s events</string>
-    <!-- Priority Modes: Inspirational text for a mode of type BEDTIME. [CHAR LIMIT=NONE] -->
+    <!-- Modes: Inspirational text for a mode of type BEDTIME. [CHAR LIMIT=NONE] -->
     <string name="zen_mode_inspiration_bedtime">Wake up feeling like 100%</string>
-    <!-- Priority Modes: Inspirational text for a mode of type DRIVING. [CHAR LIMIT=NONE] -->
+    <!-- Modes: Inspirational text for a mode of type DRIVING. [CHAR LIMIT=NONE] -->
     <string name="zen_mode_inspiration_driving">Put safety first while on the road</string>
-    <!-- Priority Modes: Inspirational text for a mode of type IMMERSIVE. [CHAR LIMIT=NONE] -->
+    <!-- Modes: Inspirational text for a mode of type IMMERSIVE. [CHAR LIMIT=NONE] -->
     <string name="zen_mode_inspiration_immersive">Gain focus to get in the zone</string>
-    <!-- Priority Modes: Inspirational text for a mode of type THEATER. [CHAR LIMIT=NONE] -->
+    <!-- Modes: Inspirational text for a mode of type THEATER. [CHAR LIMIT=NONE] -->
     <string name="zen_mode_inspiration_theater">For moments when courtesy counts</string>
-    <!-- Priority Modes: Inspirational text for a mode of type MANAGED. [CHAR LIMIT=NONE] -->
+    <!-- Modes: Inspirational text for a mode of type MANAGED. [CHAR LIMIT=NONE] -->
     <string name="zen_mode_inspiration_managed">Guided usage to help you stay in good hands</string>
-    <!-- Priority Modes: Inspirational text for modes that are not of a specific type (OTHER, UNKNOWN). [CHAR LIMIT=NONE] -->
+    <!-- Modes: Inspirational text for modes that are not of a specific type (OTHER, UNKNOWN). [CHAR LIMIT=NONE] -->
     <string name="zen_mode_inspiration_generic">Take control of your attention</string>
 
     <!-- Content description for help icon button [CHAR LIMIT=20] -->
@@ -10172,16 +10172,16 @@
     <!-- Zen mode access settings - summary for warning dialog when revoking access [CHAR LIMIT=NONE] -->
     <string name="zen_access_revoke_warning_dialog_summary">All Do Not Disturb rules created by this app will be removed.</string>
 
-    <!-- Priority modes access settings - title for warning dialog when enabling access [CHAR LIMIT=NONE] -->
-    <string name="zen_modes_access_warning_dialog_title">Allow access to Priority Modes for <xliff:g id="app" example="Tasker">%1$s</xliff:g>?</string>
+    <!-- Modes access settings - title for warning dialog when enabling access [CHAR LIMIT=NONE] -->
+    <string name="zen_modes_access_warning_dialog_title">Allow access to Modes for <xliff:g id="app" example="Tasker">%1$s</xliff:g>?</string>
 
-    <!-- Priority modes access settings - summary for warning dialog when enabling access [CHAR LIMIT=NONE] -->
-    <string name="zen_modes_access_warning_dialog_summary">The app will be able to turn on/off Do Not Disturb, manage and activate Priority Modes, and make changes to related settings.</string>
+    <!-- Modes access settings - summary for warning dialog when enabling access [CHAR LIMIT=NONE] -->
+    <string name="zen_modes_access_warning_dialog_summary">The app will be able to turn on/off Do Not Disturb, manage and activate Modes, and make changes to related settings.</string>
 
-    <!-- Priority modes access settings - title for warning dialog when revoking access [CHAR LIMIT=NONE] -->
-    <string name="zen_modes_access_revoke_warning_dialog_title">Revoke access Priority Modes for <xliff:g id="app" example="Tasker">%1$s</xliff:g>?</string>
+    <!-- Modes access settings - title for warning dialog when revoking access [CHAR LIMIT=NONE] -->
+    <string name="zen_modes_access_revoke_warning_dialog_title">Revoke access Modes for <xliff:g id="app" example="Tasker">%1$s</xliff:g>?</string>
 
-    <!-- Priority modes access settings - summary for warning dialog when revoking access [CHAR LIMIT=NONE] -->
+    <!-- Modes access settings - summary for warning dialog when revoking access [CHAR LIMIT=NONE] -->
     <string name="zen_modes_access_revoke_warning_dialog_summary">All modes created by this app will be removed.</string>
 
     <!-- Ignore battery optimizations on label [CHAR LIMIT=30] -->
diff --git a/res/xml/mobile_network_settings.xml b/res/xml/mobile_network_settings.xml
index 4f16e12..fc99ae2 100644
--- a/res/xml/mobile_network_settings.xml
+++ b/res/xml/mobile_network_settings.xml
@@ -221,10 +221,11 @@
                 </intent>
             </Preference>
 
+            <!-- Settings search is handled by WifiCallingSearchItem. -->
             <SwitchPreferenceCompat
                 android:key="video_calling_key"
                 android:title="@string/video_calling_settings_title"
-                android:persistent="true"
+                settings:searchable="false"
                 settings:controller="com.android.settings.network.telephony.VideoCallingPreferenceController"/>
 
         </PreferenceCategory>
diff --git a/res/xml/network_provider_internet.xml b/res/xml/network_provider_internet.xml
index 2a08aae..e4ebe788 100644
--- a/res/xml/network_provider_internet.xml
+++ b/res/xml/network_provider_internet.xml
@@ -29,7 +29,8 @@
         android:order="-30"
         settings:allowDividerAbove="true"
         settings:keywords="@string/keywords_internet"
-        settings:useAdminDisabledSummary="true" />
+        settings:useAdminDisabledSummary="true"
+        settings:controller="com.android.settings.network.InternetPreferenceControllerV2" />
 
     <com.android.settingslib.RestrictedPreference
         android:key="calls_and_sms"
diff --git a/src/com/android/settings/Utils.java b/src/com/android/settings/Utils.java
index 3646938..62a4ce3 100644
--- a/src/com/android/settings/Utils.java
+++ b/src/com/android/settings/Utils.java
@@ -1543,19 +1543,42 @@
      */
     public static void launchBiometricPromptForMandatoryBiometrics(@NonNull Fragment fragment,
             int requestCode, int userId, boolean hideBackground) {
+        fragment.startActivityForResult(getIntentForBiometricAuthentication(fragment.getResources(),
+                userId, hideBackground), requestCode);
+    }
+
+    /**
+     * Launch biometric prompt for mandatory biometrics. Call
+     * {@link #requestBiometricAuthenticationForMandatoryBiometrics(Context, boolean, int)}
+     * to check if all requirements for mandatory biometrics is satisfied
+     * before launching biometric prompt.
+     *
+     * @param activity       corresponding activity of the surface
+     * @param requestCode    for starting the new activity
+     * @param userId         user id for the authentication request
+     * @param hideBackground if the background activity screen needs to be hidden
+     */
+    public static void launchBiometricPromptForMandatoryBiometrics(@NonNull Activity activity,
+            int requestCode, int userId, boolean hideBackground) {
+        activity.startActivityForResult(getIntentForBiometricAuthentication(
+                activity.getResources(), userId, hideBackground), requestCode);
+    }
+
+    private static Intent getIntentForBiometricAuthentication(Resources resources, int userId,
+            boolean hideBackground) {
         final Intent intent = new Intent();
         intent.putExtra(BIOMETRIC_PROMPT_AUTHENTICATORS,
                 BiometricManager.Authenticators.MANDATORY_BIOMETRICS);
         intent.putExtra(BIOMETRIC_PROMPT_NEGATIVE_BUTTON_TEXT,
-                fragment.getString(R.string.cancel));
+                resources.getString(R.string.cancel));
         intent.putExtra(KeyguardManager.EXTRA_DESCRIPTION,
-                fragment.getString(R.string.mandatory_biometrics_prompt_description));
+                resources.getString(R.string.mandatory_biometrics_prompt_description));
         intent.putExtra(ChooseLockSettingsHelper.EXTRA_KEY_ALLOW_ANY_USER, true);
         intent.putExtra(EXTRA_USER_ID, userId);
         intent.putExtra(BIOMETRIC_PROMPT_HIDE_BACKGROUND, hideBackground);
         intent.setClassName(SETTINGS_PACKAGE_NAME,
                 ConfirmDeviceCredentialActivity.InternalActivity.class.getName());
-        fragment.startActivityForResult(intent, requestCode);
+        return intent;
     }
 
     private static void disableComponent(PackageManager pm, ComponentName componentName) {
diff --git a/src/com/android/settings/applications/AppInfoBase.java b/src/com/android/settings/applications/AppInfoBase.java
index c056add..1d77482 100644
--- a/src/com/android/settings/applications/AppInfoBase.java
+++ b/src/com/android/settings/applications/AppInfoBase.java
@@ -136,14 +136,14 @@
                 mPackageName = intent.getData().getSchemeSpecificPart();
             }
         }
-        if (!hasInteractAcrossUsersPermission()) {
-            Log.w(TAG, "Intent not valid.");
-            finish();
-            return "";
-        }
         if (intent != null && intent.hasExtra(Intent.EXTRA_USER_HANDLE)) {
-            mUserId = ((UserHandle) intent.getParcelableExtra(
-                    Intent.EXTRA_USER_HANDLE)).getIdentifier();
+            mUserId = ((UserHandle) intent.getParcelableExtra(Intent.EXTRA_USER_HANDLE))
+                    .getIdentifier();
+            if (mUserId != UserHandle.myUserId() && !hasInteractAcrossUsersFullPermission()) {
+                Log.w(TAG, "Intent not valid.");
+                finish();
+                return "";
+            }
         } else {
             mUserId = UserHandle.myUserId();
         }
@@ -171,7 +171,7 @@
     }
 
     @VisibleForTesting
-    protected boolean hasInteractAcrossUsersPermission() {
+    protected boolean hasInteractAcrossUsersFullPermission() {
         Activity activity = getActivity();
         if (!(activity instanceof SettingsActivity)) {
             return false;
diff --git a/src/com/android/settings/biometrics/BiometricEnrollActivity.java b/src/com/android/settings/biometrics/BiometricEnrollActivity.java
index c9616f1..dbbe30b 100644
--- a/src/com/android/settings/biometrics/BiometricEnrollActivity.java
+++ b/src/com/android/settings/biometrics/BiometricEnrollActivity.java
@@ -19,6 +19,7 @@
 import static android.provider.Settings.ACTION_BIOMETRIC_ENROLL;
 import static android.provider.Settings.EXTRA_BIOMETRIC_AUTHENTICATORS_ALLOWED;
 
+import static com.android.settings.biometrics.BiometricEnrollBase.BIOMETRIC_AUTH_REQUEST;
 import static com.android.settings.biometrics.BiometricEnrollBase.RESULT_CONSENT_DENIED;
 import static com.android.settings.biometrics.BiometricEnrollBase.RESULT_CONSENT_GRANTED;
 
@@ -51,6 +52,7 @@
 import com.android.internal.widget.LockPatternUtils;
 import com.android.settings.R;
 import com.android.settings.SetupWizardUtils;
+import com.android.settings.Utils;
 import com.android.settings.core.InstrumentedActivity;
 import com.android.settings.overlay.FeatureFactory;
 import com.android.settings.password.ChooseLockGeneric;
@@ -442,6 +444,16 @@
                     if (!mParentalConsentHelper.launchNext(this, REQUEST_CHOOSE_OPTIONS)) {
                         Log.e(TAG, "Nothing to prompt for consent (no modalities enabled)!");
                         finish();
+                    } else {
+                        final Utils.BiometricStatus biometricStatus =
+                                Utils.requestBiometricAuthenticationForMandatoryBiometrics(this,
+                                        false /* biometricsAuthenticationRequested */, mUserId);
+                        if (biometricStatus == Utils.BiometricStatus.OK) {
+                            Utils.launchBiometricPromptForMandatoryBiometrics(this,
+                                    BIOMETRIC_AUTH_REQUEST, mUserId, true /* hideBackground */);
+                        } else if (biometricStatus != Utils.BiometricStatus.NOT_ACTIVE) {
+                            finish();
+                        }
                     }
                 } else {
                     Log.d(TAG, "Unknown result for set/choose lock: " + resultCode);
@@ -473,6 +485,10 @@
                     finish();
                 }
                 break;
+            case BIOMETRIC_AUTH_REQUEST:
+                if (resultCode != RESULT_OK) {
+                    finish();
+                }
             default:
                 Log.w(TAG, "Unknown consenting requestCode: " + requestCode + ", finishing");
                 finish();
diff --git a/src/com/android/settings/biometrics/BiometricEnrollBase.java b/src/com/android/settings/biometrics/BiometricEnrollBase.java
index 37ada23..3285a95 100644
--- a/src/com/android/settings/biometrics/BiometricEnrollBase.java
+++ b/src/com/android/settings/biometrics/BiometricEnrollBase.java
@@ -117,7 +117,6 @@
     public static final int LEARN_MORE_REQUEST = 3;
     public static final int CONFIRM_REQUEST = 4;
     public static final int ENROLL_REQUEST = 5;
-    public static final int BIOMETRIC_AUTH_REQUEST = 6;
 
     /**
      * Request code when starting another biometric enrollment from within a biometric flow. For
@@ -125,6 +124,7 @@
      */
     public static final int ENROLL_NEXT_BIOMETRIC_REQUEST = 6;
     public static final int REQUEST_POSTURE_GUIDANCE = 7;
+    public static final int BIOMETRIC_AUTH_REQUEST = 8;
 
     protected boolean mLaunchedConfirmLock;
     protected boolean mLaunchedPostureGuidance;
diff --git a/src/com/android/settings/biometrics/BiometricEnrollIntroduction.java b/src/com/android/settings/biometrics/BiometricEnrollIntroduction.java
index 5ebe9c7..6f9b94a 100644
--- a/src/com/android/settings/biometrics/BiometricEnrollIntroduction.java
+++ b/src/com/android/settings/biometrics/BiometricEnrollIntroduction.java
@@ -36,6 +36,7 @@
 import com.android.internal.widget.LockPatternUtils;
 import com.android.settings.R;
 import com.android.settings.SetupWizardUtils;
+import com.android.settings.Utils;
 import com.android.settings.password.ChooseLockGeneric;
 import com.android.settings.password.ChooseLockSettingsHelper;
 import com.android.settings.password.SetupSkipDialog;
@@ -417,6 +418,15 @@
                         getNextButton().setEnabled(true);
                     }));
                 }
+                final Utils.BiometricStatus biometricStatus =
+                        Utils.requestBiometricAuthenticationForMandatoryBiometrics(this,
+                                false /* biometricsAuthenticationRequested */, mUserId);
+                if (biometricStatus == Utils.BiometricStatus.OK) {
+                    Utils.launchBiometricPromptForMandatoryBiometrics(this,
+                            BIOMETRIC_AUTH_REQUEST, mUserId, true /* hideBackground */);
+                } else if (biometricStatus != Utils.BiometricStatus.NOT_ACTIVE) {
+                    finish();
+                }
             } else {
                 setResult(resultCode, data);
                 finish();
@@ -445,6 +455,10 @@
                 setResult(resultCode, data);
                 finish();
             }
+        } else if (requestCode == BIOMETRIC_AUTH_REQUEST) {
+            if (resultCode != RESULT_OK) {
+                finish();
+            }
         }
         super.onActivityResult(requestCode, resultCode, data);
     }
diff --git a/src/com/android/settings/biometrics/combination/CombinedBiometricSettings.java b/src/com/android/settings/biometrics/combination/CombinedBiometricSettings.java
index 671a5b6..7b3a724 100644
--- a/src/com/android/settings/biometrics/combination/CombinedBiometricSettings.java
+++ b/src/com/android/settings/biometrics/combination/CombinedBiometricSettings.java
@@ -24,14 +24,19 @@
 import android.os.Bundle;
 import android.os.UserHandle;
 
+import androidx.activity.result.ActivityResult;
+import androidx.activity.result.ActivityResultLauncher;
+import androidx.activity.result.contract.ActivityResultContracts;
 import androidx.annotation.Nullable;
 import androidx.preference.Preference;
 
 import com.android.settings.R;
+import com.android.settings.biometrics.BiometricEnrollBase;
 import com.android.settings.biometrics.activeunlock.ActiveUnlockContentListener.OnContentChangedListener;
 import com.android.settings.biometrics.activeunlock.ActiveUnlockDeviceNameListener;
 import com.android.settings.biometrics.activeunlock.ActiveUnlockRequireBiometricSetup;
 import com.android.settings.biometrics.activeunlock.ActiveUnlockStatusUtils;
+import com.android.settings.flags.Flags;
 import com.android.settings.search.BaseSearchIndexProvider;
 import com.android.settingslib.search.SearchIndexable;
 
@@ -52,6 +57,10 @@
     private CombinedBiometricStatusUtils mCombinedBiometricStatusUtils;
     @Nullable private ActiveUnlockDeviceNameListener mActiveUnlockDeviceNameListener;
 
+    private final ActivityResultLauncher<Intent> mActiveUnlockPreferenceLauncher =
+            registerForActivityResult(new ActivityResultContracts.StartActivityForResult(),
+                    this::onActiveUnlockPreferenceResult);
+
     @Override
     public void onAttach(Context context) {
         super.onAttach(context);
@@ -158,12 +167,25 @@
             intent = mActiveUnlockStatusUtils.getIntent();
         }
         if (intent != null) {
-            startActivityForResult(intent, ACTIVE_UNLOCK_REQUEST);
+            if (Flags.activeUnlockFinishParent()) {
+                mActiveUnlockPreferenceLauncher.launch(intent);
+            } else {
+                startActivityForResult(intent, ACTIVE_UNLOCK_REQUEST);
+            }
         }
         return true;
 
     }
 
+    private void onActiveUnlockPreferenceResult(@Nullable ActivityResult result) {
+        if (result != null && result.getResultCode() == BiometricEnrollBase.RESULT_TIMEOUT) {
+            mDoNotFinishActivity = false;
+            // When "Watch Unlock" is closed due to entering onStop(),
+            // "Face & Fingerprint Unlock" shall also close itself and back to "Security" page.
+            finish();
+        }
+    }
+
     @Override
     protected String getUseAnyBiometricSummary() {
         // either Active Unlock is not enabled or no device is enrolled.
diff --git a/src/com/android/settings/bluetooth/AvailableMediaBluetoothDeviceUpdater.java b/src/com/android/settings/bluetooth/AvailableMediaBluetoothDeviceUpdater.java
index bb56c50..22a39c8 100644
--- a/src/com/android/settings/bluetooth/AvailableMediaBluetoothDeviceUpdater.java
+++ b/src/com/android/settings/bluetooth/AvailableMediaBluetoothDeviceUpdater.java
@@ -26,6 +26,7 @@
 import com.android.settingslib.bluetooth.BluetoothUtils;
 import com.android.settingslib.bluetooth.CachedBluetoothDevice;
 import com.android.settingslib.bluetooth.LocalBluetoothManager;
+import com.android.settingslib.utils.ThreadUtils;
 
 /** Controller to maintain available media Bluetooth devices */
 public class AvailableMediaBluetoothDeviceUpdater extends BluetoothDeviceUpdater
@@ -135,7 +136,9 @@
     @Override
     public boolean onPreferenceClick(Preference preference) {
         mMetricsFeatureProvider.logClickedPreference(preference, mMetricsCategory);
-        mDevicePreferenceCallback.onDeviceClick(preference);
+        var unused =
+                ThreadUtils.postOnBackgroundThread(
+                        () -> mDevicePreferenceCallback.onDeviceClick(preference));
         return true;
     }
 
diff --git a/src/com/android/settings/connecteddevice/audiosharing/AudioSharingDevicePreferenceController.java b/src/com/android/settings/connecteddevice/audiosharing/AudioSharingDevicePreferenceController.java
index d6ad4bc..8b4c7f2 100644
--- a/src/com/android/settings/connecteddevice/audiosharing/AudioSharingDevicePreferenceController.java
+++ b/src/com/android/settings/connecteddevice/audiosharing/AudioSharingDevicePreferenceController.java
@@ -59,6 +59,7 @@
 import com.android.settingslib.bluetooth.LocalBluetoothManager;
 import com.android.settingslib.bluetooth.LocalBluetoothProfileManager;
 import com.android.settingslib.core.instrumentation.MetricsFeatureProvider;
+import com.android.settingslib.utils.ThreadUtils;
 
 import java.util.Locale;
 import java.util.concurrent.Executor;
@@ -287,7 +288,8 @@
             if (AudioSharingUtils.isAudioSharingProfileReady(mProfileManager)) {
                 if (!mIntentHandled.get()) {
                     Log.d(TAG, "displayPreference: profile ready, handleDeviceClickFromIntent");
-                    handleDeviceClickFromIntent();
+                    var unused =
+                            ThreadUtils.postOnBackgroundThread(() -> handleDeviceClickFromIntent());
                     mIntentHandled.set(true);
                 }
             }
diff --git a/src/com/android/settings/connecteddevice/audiosharing/AudioSharingDialogHandler.java b/src/com/android/settings/connecteddevice/audiosharing/AudioSharingDialogHandler.java
index 6f55a13..396144a 100644
--- a/src/com/android/settings/connecteddevice/audiosharing/AudioSharingDialogHandler.java
+++ b/src/com/android/settings/connecteddevice/audiosharing/AudioSharingDialogHandler.java
@@ -25,6 +25,7 @@
 import android.bluetooth.BluetoothLeBroadcastMetadata;
 import android.bluetooth.BluetoothLeBroadcastReceiveState;
 import android.content.Context;
+import android.media.AudioManager;
 import android.os.Bundle;
 import android.util.Log;
 import android.util.Pair;
@@ -64,6 +65,7 @@
     @Nullable private final CachedBluetoothDeviceManager mDeviceManager;
     @Nullable private final LocalBluetoothLeBroadcast mBroadcast;
     @Nullable private final LocalBluetoothLeBroadcastAssistant mAssistant;
+    @Nullable private final AudioManager mAudioManager;
     private final MetricsFeatureProvider mMetricsFeatureProvider;
     private boolean mIsStoppingBroadcast = false;
 
@@ -157,6 +159,7 @@
                 mLocalBtManager != null
                         ? mLocalBtManager.getProfileManager().getLeAudioBroadcastAssistantProfile()
                         : null;
+        mAudioManager = context.getSystemService(AudioManager.class);
         mMetricsFeatureProvider = FeatureFactory.getFeatureFactory().getMetricsFeatureProvider();
     }
 
@@ -178,6 +181,22 @@
     public void handleDeviceConnected(
             @NonNull CachedBluetoothDevice cachedDevice, boolean userTriggered) {
         String anonymizedAddress = cachedDevice.getDevice().getAnonymizedAddress();
+        if (mAudioManager != null) {
+            int audioMode = mAudioManager.getMode();
+            if (audioMode == AudioManager.MODE_RINGTONE
+                    || audioMode == AudioManager.MODE_IN_CALL
+                    || audioMode == AudioManager.MODE_IN_COMMUNICATION) {
+                Log.d(TAG, "Skip handleDeviceConnected, audio mode = " + audioMode);
+                // TODO: add metric for this case
+                if (userTriggered) {
+                    // If this method is called with user triggered, e.g. manual click on the
+                    // "Connected devices" page, we need call setActive for the device, since user
+                    // intend to switch active device for the call.
+                    cachedDevice.setActive();
+                }
+                return;
+            }
+        }
         boolean isBroadcasting = isBroadcasting();
         boolean isLeAudioSupported = AudioSharingUtils.isLeAudioSupported(cachedDevice);
         if (!isLeAudioSupported) {
diff --git a/src/com/android/settings/connecteddevice/fastpair/FastPairDeviceGroupController.java b/src/com/android/settings/connecteddevice/fastpair/FastPairDeviceGroupController.java
index 52ad91c..6b77b47 100644
--- a/src/com/android/settings/connecteddevice/fastpair/FastPairDeviceGroupController.java
+++ b/src/com/android/settings/connecteddevice/fastpair/FastPairDeviceGroupController.java
@@ -35,7 +35,6 @@
 import com.android.settings.connecteddevice.DevicePreferenceCallback;
 import com.android.settings.core.BasePreferenceController;
 import com.android.settings.core.PreferenceControllerMixin;
-import com.android.settings.flags.Flags;
 import com.android.settings.overlay.FeatureFactory;
 
 /**
@@ -66,15 +65,11 @@
 
     public FastPairDeviceGroupController(Context context) {
         super(context, KEY);
-        if (Flags.enableSubsequentPairSettingsIntegration()) {
-            FastPairFeatureProvider fastPairFeatureProvider =
-                    FeatureFactory.getFeatureFactory().getFastPairFeatureProvider();
-            mFastPairDeviceUpdater =
-                    fastPairFeatureProvider.getFastPairDeviceUpdater(context, this);
-        } else {
-            Log.d(TAG, "Flag disabled. Ignored.");
-            mFastPairDeviceUpdater = null;
-        }
+        FastPairFeatureProvider fastPairFeatureProvider =
+                FeatureFactory.getFeatureFactory().getFastPairFeatureProvider();
+        mFastPairDeviceUpdater =
+                fastPairFeatureProvider.getFastPairDeviceUpdater(context, this);
+
         mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
         mIntentFilter = new IntentFilter(BluetoothAdapter.ACTION_STATE_CHANGED);
     }
diff --git a/src/com/android/settings/connecteddevice/fastpair/FastPairDevicePreferenceController.java b/src/com/android/settings/connecteddevice/fastpair/FastPairDevicePreferenceController.java
index a1c6d18..cb365a5 100644
--- a/src/com/android/settings/connecteddevice/fastpair/FastPairDevicePreferenceController.java
+++ b/src/com/android/settings/connecteddevice/fastpair/FastPairDevicePreferenceController.java
@@ -34,8 +34,8 @@
 
 import com.android.settings.connecteddevice.DevicePreferenceCallback;
 import com.android.settings.core.BasePreferenceController;
-import com.android.settings.flags.Flags;
 import com.android.settings.overlay.FeatureFactory;
+import com.android.settingslib.utils.ThreadUtils;
 
 import java.util.ArrayList;
 import java.util.Collections;
@@ -75,43 +75,22 @@
     public FastPairDevicePreferenceController(Context context, String preferenceKey) {
         super(context, preferenceKey);
 
-        if (Flags.enableSubsequentPairSettingsIntegration()) {
-            FastPairFeatureProvider fastPairFeatureProvider =
-                    FeatureFactory.getFeatureFactory().getFastPairFeatureProvider();
-            mFastPairDeviceUpdater =
-                    fastPairFeatureProvider.getFastPairDeviceUpdater(context, this);
-        } else {
-            Log.d(TAG, "Flag disabled. Ignore.");
-            mFastPairDeviceUpdater = null;
-        }
+        FastPairFeatureProvider fastPairFeatureProvider =
+                FeatureFactory.getFeatureFactory().getFastPairFeatureProvider();
+        mFastPairDeviceUpdater =
+                fastPairFeatureProvider.getFastPairDeviceUpdater(context, this);
         mIntentFilter = new IntentFilter(BluetoothAdapter.ACTION_STATE_CHANGED);
         mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
     }
 
     @Override
     public void onStart(@NonNull LifecycleOwner owner) {
-        if (mFastPairDeviceUpdater != null) {
-            mFastPairDeviceUpdater.setPreferenceContext(mContext);
-            mFastPairDeviceUpdater.registerCallback();
-        } else {
-            if (DEBUG) {
-                Log.d(TAG, "Callback register: Fast Pair device updater is null. Ignore.");
-            }
-        }
-        mContext.registerReceiver(mReceiver, mIntentFilter, Context.RECEIVER_EXPORTED_UNAUDITED);
+        var unused = ThreadUtils.postOnBackgroundThread(() -> registerCallbacks());
     }
 
     @Override
     public void onStop(@NonNull LifecycleOwner owner) {
-        if (mFastPairDeviceUpdater != null) {
-            mFastPairDeviceUpdater.setPreferenceContext(null);
-            mFastPairDeviceUpdater.unregisterCallback();
-        } else {
-            if (DEBUG) {
-                Log.d(TAG, "Callback unregister: Fast Pair device updater is null. Ignore.");
-            }
-        }
-        mContext.unregisterReceiver(mReceiver);
+        var unused = ThreadUtils.postOnBackgroundThread(() -> unregisterCallbacks());
     }
 
     @Override
@@ -208,4 +187,28 @@
             mSeeAllPreference.setVisible(false);
         }
     }
+
+    private void registerCallbacks() {
+        if (mFastPairDeviceUpdater != null) {
+            mFastPairDeviceUpdater.setPreferenceContext(mContext);
+            mFastPairDeviceUpdater.registerCallback();
+        } else {
+            if (DEBUG) {
+                Log.d(TAG, "Callback register: Fast Pair device updater is null. Ignore.");
+            }
+        }
+        mContext.registerReceiver(mReceiver, mIntentFilter, Context.RECEIVER_EXPORTED_UNAUDITED);
+    }
+
+    private void unregisterCallbacks() {
+        if (mFastPairDeviceUpdater != null) {
+            mFastPairDeviceUpdater.setPreferenceContext(null);
+            mFastPairDeviceUpdater.unregisterCallback();
+        } else {
+            if (DEBUG) {
+                Log.d(TAG, "Callback unregister: Fast Pair device updater is null. Ignore.");
+            }
+        }
+        mContext.unregisterReceiver(mReceiver);
+    }
 }
diff --git a/src/com/android/settings/datetime/AutoTimeZonePreferenceController.java b/src/com/android/settings/datetime/AutoTimeZonePreferenceController.java
index 3a1f995..8eccf31 100644
--- a/src/com/android/settings/datetime/AutoTimeZonePreferenceController.java
+++ b/src/com/android/settings/datetime/AutoTimeZonePreferenceController.java
@@ -27,6 +27,8 @@
 import android.app.time.TimeZoneConfiguration;
 import android.content.Context;
 
+import androidx.preference.Preference;
+
 import com.android.internal.annotations.VisibleForTesting;
 import com.android.settings.R;
 import com.android.settings.core.TogglePreferenceController;
@@ -116,6 +118,12 @@
     }
 
     @Override
+    public void updateState(Preference preference) {
+        super.updateState(preference);
+        refreshSummary(preference);
+    }
+
+    @Override
     public CharSequence getSummary() {
         // If auto time zone cannot enable telephony fallback and is capable of location, then auto
         // time zone must use location.
diff --git a/src/com/android/settings/fuelgauge/batteryusage/DataProcessor.java b/src/com/android/settings/fuelgauge/batteryusage/DataProcessor.java
index da8481d..ebe7996 100644
--- a/src/com/android/settings/fuelgauge/batteryusage/DataProcessor.java
+++ b/src/com/android/settings/fuelgauge/batteryusage/DataProcessor.java
@@ -172,13 +172,21 @@
     /** Gets the {@link BatteryUsageStats} from system service. */
     @Nullable
     public static BatteryUsageStats getBatteryUsageStats(final Context context) {
+        final long startTime = System.currentTimeMillis();
         final BatteryUsageStatsQuery batteryUsageStatsQuery =
                 new BatteryUsageStatsQuery.Builder()
                         .includeBatteryHistory()
                         .includeProcessStateData()
                         .build();
-        return context.getSystemService(BatteryStatsManager.class)
-                .getBatteryUsageStats(batteryUsageStatsQuery);
+        final BatteryUsageStats batteryUsageStats =
+                context.getSystemService(BatteryStatsManager.class)
+                        .getBatteryUsageStats(batteryUsageStatsQuery);
+        Log.d(
+                TAG,
+                String.format(
+                        "getBatteryUsageStats() from BatteryStatsManager in %d/ms",
+                        System.currentTimeMillis() - startTime));
+        return batteryUsageStats;
     }
 
     /** Gets the {@link UsageEvents} from system service for all unlocked users. */
@@ -1693,8 +1701,14 @@
         final UserManager userManager = context.getSystemService(UserManager.class);
         final SparseArray<BatteryEntry> batteryEntryList = new SparseArray<>();
         final ArrayList<BatteryEntry> results = new ArrayList<>();
+        final long startTime = System.currentTimeMillis();
         final List<UidBatteryConsumer> uidBatteryConsumers =
                 batteryUsageStats.getUidBatteryConsumers();
+        Log.d(
+                TAG,
+                String.format(
+                        "get %d uidBatteryConsumers from BatteryUsageStats in %d/ms",
+                        uidBatteryConsumers.size(), (System.currentTimeMillis() - startTime)));
 
         // Sort to have all apps with "real" UIDs first, followed by apps that are supposed
         // to be combined with the real ones.
@@ -1763,9 +1777,11 @@
                             deviceConsumer.getConsumedPowerForCustomComponent(componentId)));
         }
 
+        final int numComponentEntries = batteryEntryList.size();
         final List<UserBatteryConsumer> userBatteryConsumers =
                 batteryUsageStats.getUserBatteryConsumers();
-        for (int i = 0, size = userBatteryConsumers.size(); i < size; i++) {
+        final int numUserEntries = userBatteryConsumers.size();
+        for (int i = 0; i < numUserEntries; i++) {
             final UserBatteryConsumer consumer = userBatteryConsumers.get(i);
             results.add(
                     new BatteryEntry(
@@ -1785,6 +1801,13 @@
             results.add(batteryEntryList.valueAt(i));
         }
 
+        Log.d(
+                TAG,
+                String.format(
+                        "getCoalescedUsageList(): uidEntries = %d, "
+                                + "userEntries = %d, componentEntries = %d",
+                        numUidSippers, numUserEntries, numComponentEntries));
+
         // The sort order must have changed, so re-sort based on total power use.
         results.sort(BatteryEntry.COMPARATOR);
         return results;
diff --git a/src/com/android/settings/network/InternetPreferenceController.java b/src/com/android/settings/network/InternetPreferenceController.java
deleted file mode 100644
index aed44d5..0000000
--- a/src/com/android/settings/network/InternetPreferenceController.java
+++ /dev/null
@@ -1,316 +0,0 @@
-/*
- * Copyright (C) 2020 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;
-
-import static androidx.lifecycle.Lifecycle.Event.ON_PAUSE;
-import static androidx.lifecycle.Lifecycle.Event.ON_RESUME;
-
-import static com.android.settings.network.InternetUpdater.INTERNET_CELLULAR;
-import static com.android.settings.network.InternetUpdater.INTERNET_ETHERNET;
-import static com.android.settings.network.InternetUpdater.INTERNET_NETWORKS_AVAILABLE;
-import static com.android.settings.network.InternetUpdater.INTERNET_OFF;
-import static com.android.settings.network.InternetUpdater.INTERNET_WIFI;
-import static com.android.settingslib.wifi.WifiUtils.getHotspotIconResource;
-
-import android.content.Context;
-import android.graphics.drawable.Drawable;
-import android.telephony.SubscriptionManager;
-
-import androidx.annotation.IdRes;
-import androidx.annotation.VisibleForTesting;
-import androidx.lifecycle.Lifecycle;
-import androidx.lifecycle.LifecycleObserver;
-import androidx.lifecycle.LifecycleOwner;
-import androidx.lifecycle.OnLifecycleEvent;
-import androidx.preference.Preference;
-import androidx.preference.PreferenceScreen;
-
-import com.android.settings.R;
-import com.android.settings.widget.SummaryUpdater;
-import com.android.settings.wifi.WifiPickerTrackerHelper;
-import com.android.settings.wifi.WifiSummaryUpdater;
-import com.android.settings.wifi.repository.SharedConnectivityRepository;
-import com.android.settingslib.Utils;
-import com.android.settingslib.core.AbstractPreferenceController;
-import com.android.settingslib.mobile.dataservice.SubscriptionInfoEntity;
-import com.android.settingslib.utils.ThreadUtils;
-import com.android.wifitrackerlib.HotspotNetworkEntry;
-import com.android.wifitrackerlib.WifiEntry;
-import com.android.wifitrackerlib.WifiPickerTracker;
-
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-
-/**
- * PreferenceController to update the internet state.
- */
-public class InternetPreferenceController extends AbstractPreferenceController implements
-        LifecycleObserver, SummaryUpdater.OnSummaryChangeListener,
-        InternetUpdater.InternetChangeListener, MobileNetworkRepository.MobileNetworkCallback,
-        DefaultSubscriptionReceiver.DefaultSubscriptionListener,
-        WifiPickerTracker.WifiPickerTrackerCallback {
-
-    public static final String KEY = "internet_settings";
-
-    private Preference mPreference;
-    @VisibleForTesting
-    WifiSummaryUpdater mSummaryHelper;
-    private InternetUpdater mInternetUpdater;
-    private @InternetUpdater.InternetType int mInternetType;
-    private LifecycleOwner mLifecycleOwner;
-    private MobileNetworkRepository mMobileNetworkRepository;
-    private List<SubscriptionInfoEntity> mSubInfoEntityList = new ArrayList<>();
-    private int mDefaultDataSubId = SubscriptionManager.INVALID_SUBSCRIPTION_ID;
-    private DefaultSubscriptionReceiver mDataSubscriptionChangedReceiver;
-    private boolean mIsHotspotNetworkEnabled = SharedConnectivityRepository.isDeviceConfigEnabled();
-    @VisibleForTesting
-    WifiPickerTrackerHelper mWifiPickerTrackerHelper;
-
-    @VisibleForTesting
-    static Map<Integer, Integer> sIconMap = new HashMap<>();
-    static {
-        sIconMap.put(INTERNET_OFF, R.drawable.ic_no_internet_unavailable);
-        sIconMap.put(INTERNET_NETWORKS_AVAILABLE, R.drawable.ic_no_internet_available);
-        sIconMap.put(INTERNET_WIFI, R.drawable.ic_wifi_signal_4);
-        sIconMap.put(INTERNET_CELLULAR, R.drawable.ic_network_cell);
-        sIconMap.put(INTERNET_ETHERNET, R.drawable.ic_settings_ethernet);
-    }
-
-    private static Map<Integer, Integer> sSummaryMap = new HashMap<>();
-    static {
-        sSummaryMap.put(INTERNET_OFF, R.string.condition_airplane_title);
-        sSummaryMap.put(INTERNET_NETWORKS_AVAILABLE, R.string.networks_available);
-        sSummaryMap.put(INTERNET_WIFI, 0);
-        sSummaryMap.put(INTERNET_CELLULAR, 0);
-        sSummaryMap.put(INTERNET_ETHERNET, R.string.to_switch_networks_disconnect_ethernet);
-    }
-
-    public InternetPreferenceController(Context context, Lifecycle lifecycle,
-            LifecycleOwner lifecycleOwner) {
-        super(context);
-        if (lifecycle == null) {
-            throw new IllegalArgumentException("Lifecycle must be set");
-        }
-        mSummaryHelper = new WifiSummaryUpdater(mContext, this);
-        mInternetUpdater = new InternetUpdater(context, lifecycle, this);
-        mInternetType = mInternetUpdater.getInternetType();
-        mLifecycleOwner = lifecycleOwner;
-        mMobileNetworkRepository = MobileNetworkRepository.getInstance(context);
-        mDataSubscriptionChangedReceiver = new DefaultSubscriptionReceiver(context, this);
-        if (mIsHotspotNetworkEnabled) {
-            mWifiPickerTrackerHelper = new WifiPickerTrackerHelper(lifecycle, context, this);
-        }
-        lifecycle.addObserver(this);
-    }
-
-    @Override
-    public void displayPreference(PreferenceScreen screen) {
-        super.displayPreference(screen);
-        mPreference = screen.findPreference(KEY);
-    }
-
-    private void drawIcon(int iconResId) {
-        Drawable drawable = mContext.getDrawable(iconResId);
-        if (drawable != null) {
-            drawable.setTintList(Utils.getColorAttr(mContext, android.R.attr.colorControlNormal));
-            mPreference.setIcon(drawable);
-        }
-    }
-
-    @Override
-    public void updateState(Preference preference) {
-        if (mPreference == null) {
-            return;
-        }
-
-        if (mInternetType == INTERNET_WIFI && updateHotspotNetwork()) {
-            return;
-        }
-
-        final @IdRes int icon = sIconMap.get(mInternetType);
-        if (icon != 0) {
-            drawIcon(icon);
-        }
-
-        if (mInternetType == INTERNET_WIFI) {
-            mPreference.setSummary(mSummaryHelper.getSummary());
-            return;
-        }
-
-        if (mInternetType == INTERNET_CELLULAR) {
-            updateCellularSummary();
-            return;
-        }
-
-        final @IdRes int summary = sSummaryMap.get(mInternetType);
-        if (summary != 0) {
-            mPreference.setSummary(summary);
-        }
-    }
-
-    @VisibleForTesting
-    boolean updateHotspotNetwork() {
-        if (mWifiPickerTrackerHelper == null) {
-            return false;
-        }
-        WifiEntry entry = mWifiPickerTrackerHelper.getWifiPickerTracker().getConnectedWifiEntry();
-        if (!(entry instanceof HotspotNetworkEntry)) {
-            return false;
-        }
-        drawIcon(getHotspotIconResource(((HotspotNetworkEntry) entry).getDeviceType()));
-        mPreference.setSummary(((HotspotNetworkEntry) entry).getAlternateSummary());
-        return true;
-    }
-
-    @Override
-    public boolean isAvailable() {
-        return mContext.getResources().getBoolean(R.bool.config_show_internet_settings);
-    }
-
-    @Override
-    public String getPreferenceKey() {
-        return KEY;
-    }
-
-    /** @OnLifecycleEvent(ON_RESUME) */
-    @OnLifecycleEvent(ON_RESUME)
-    public void onResume() {
-        mMobileNetworkRepository.addRegister(mLifecycleOwner, this,
-                SubscriptionManager.INVALID_SUBSCRIPTION_ID);
-        mMobileNetworkRepository.updateEntity();
-        mSummaryHelper.register(true);
-        mDataSubscriptionChangedReceiver.registerReceiver();
-        mDefaultDataSubId = SubscriptionManager.getDefaultDataSubscriptionId();
-    }
-
-    /** @OnLifecycleEvent(ON_PAUSE) */
-    @OnLifecycleEvent(ON_PAUSE)
-    public void onPause() {
-        mMobileNetworkRepository.removeRegister(this);
-        mSummaryHelper.register(false);
-        mDataSubscriptionChangedReceiver.unRegisterReceiver();
-    }
-
-    /**
-     * Called when internet type is changed.
-     *
-     * @param internetType the internet type
-     */
-    @Override
-    public void onInternetTypeChanged(@InternetUpdater.InternetType int internetType) {
-        final boolean needUpdate = (internetType != mInternetType);
-        mInternetType = internetType;
-        if (needUpdate) {
-            ThreadUtils.postOnMainThread(() -> {
-                updateState(mPreference);
-            });
-        }
-    }
-
-    /**
-     * Called when airplane mode state is changed.
-     */
-    @Override
-    public void onAirplaneModeChanged(boolean isAirplaneModeOn) {
-        ThreadUtils.postOnMainThread(() -> {
-            updateState(mPreference);
-        });
-    }
-
-    @Override
-    public void onSummaryChanged(String summary) {
-        if (mInternetType == INTERNET_WIFI) {
-            updateState(mPreference);
-        }
-    }
-
-    @VisibleForTesting
-    void updateCellularSummary() {
-        CharSequence summary = null;
-        SubscriptionInfoEntity activeSubInfo = null;
-        SubscriptionInfoEntity defaultSubInfo = null;
-
-        for (SubscriptionInfoEntity subInfo : getSubscriptionInfoList()) {
-            if (subInfo.isActiveDataSubscriptionId) {
-                activeSubInfo = subInfo;
-            }
-            if (subInfo.getSubId() == getDefaultDataSubscriptionId()) {
-                defaultSubInfo = subInfo;
-            }
-        }
-        if (activeSubInfo == null || defaultSubInfo == null) {
-            return;
-        }
-        activeSubInfo = activeSubInfo.isSubscriptionVisible ? activeSubInfo : defaultSubInfo;
-
-        if (activeSubInfo.equals(defaultSubInfo)) {
-            // DDS is active
-            summary = activeSubInfo.uniqueName;
-        } else {
-            summary = mContext.getString(
-                    R.string.mobile_data_temp_using, activeSubInfo.uniqueName);
-        }
-
-        mPreference.setSummary(summary);
-    }
-
-    @VisibleForTesting
-    protected List<SubscriptionInfoEntity> getSubscriptionInfoList() {
-        return mSubInfoEntityList;
-    }
-
-    @VisibleForTesting
-    protected int getDefaultDataSubscriptionId() {
-        return mDefaultDataSubId;
-    }
-
-    @Override
-    public void onAvailableSubInfoChanged(List<SubscriptionInfoEntity> subInfoEntityList) {
-        mSubInfoEntityList = subInfoEntityList;
-        updateState(mPreference);
-    }
-
-    @Override
-    public void onDefaultDataChanged(int defaultDataSubId) {
-        mDefaultDataSubId = defaultDataSubId;
-        updateState(mPreference);
-    }
-
-    @Override
-    public void onWifiEntriesChanged() {
-        if (mInternetType == INTERNET_WIFI) {
-            updateState(mPreference);
-        }
-    }
-
-    @Override
-    public void onWifiStateChanged() {
-        // Do nothing
-    }
-
-    @Override
-    public void onNumSavedNetworksChanged() {
-        // Do nothing
-    }
-
-    @Override
-    public void onNumSavedSubscriptionsChanged() {
-        // Do nothing
-    }
-}
diff --git a/src/com/android/settings/network/MobileNetworkListFragment.kt b/src/com/android/settings/network/MobileNetworkListFragment.kt
index eb0d16c..bb88330 100644
--- a/src/com/android/settings/network/MobileNetworkListFragment.kt
+++ b/src/com/android/settings/network/MobileNetworkListFragment.kt
@@ -27,7 +27,7 @@
 import com.android.settings.SettingsPreferenceFragment
 import com.android.settings.dashboard.DashboardFragment
 import com.android.settings.flags.Flags
-import com.android.settings.network.telephony.MobileNetworkUtils
+import com.android.settings.network.telephony.euicc.EuiccRepository
 import com.android.settings.search.BaseSearchIndexProvider
 import com.android.settings.spa.SpaActivity.Companion.startSpaActivity
 import com.android.settings.spa.network.NetworkCellularGroupProvider
@@ -58,7 +58,7 @@
         listView.itemAnimator = null
 
         findPreference<Preference>(KEY_ADD_SIM)!!.isVisible =
-            MobileNetworkUtils.showEuiccSettings(context)
+            EuiccRepository(requireContext()).showEuiccSettings()
     }
 
     override fun getPreferenceScreenResId() = R.xml.network_provider_sims_list
diff --git a/src/com/android/settings/network/MobileNetworkSummaryController.java b/src/com/android/settings/network/MobileNetworkSummaryController.java
index 4627a25..9bf6915 100644
--- a/src/com/android/settings/network/MobileNetworkSummaryController.java
+++ b/src/com/android/settings/network/MobileNetworkSummaryController.java
@@ -35,7 +35,7 @@
 import com.android.settings.R;
 import com.android.settings.core.PreferenceControllerMixin;
 import com.android.settings.dashboard.DashboardFragment;
-import com.android.settings.network.telephony.MobileNetworkUtils;
+import com.android.settings.network.telephony.euicc.EuiccRepository;
 import com.android.settings.overlay.FeatureFactory;
 import com.android.settingslib.RestrictedPreference;
 import com.android.settingslib.Utils;
@@ -118,7 +118,7 @@
         if ((mSubInfoEntityList == null || mSubInfoEntityList.isEmpty()) || (
                 mUiccInfoEntityList == null || mUiccInfoEntityList.isEmpty()) || (
                 mMobileNetworkInfoEntityList == null || mMobileNetworkInfoEntityList.isEmpty())) {
-            if (MobileNetworkUtils.showEuiccSettingsDetecting(mContext)) {
+            if (new EuiccRepository(mContext).showEuiccSettings()) {
                 return mContext.getResources().getString(
                         R.string.mobile_network_summary_add_a_network);
             }
@@ -168,7 +168,7 @@
                 || (mUiccInfoEntityList == null || mUiccInfoEntityList.isEmpty())
                 || (mMobileNetworkInfoEntityList == null
                 || mMobileNetworkInfoEntityList.isEmpty()))) {
-            if (MobileNetworkUtils.showEuiccSettingsDetecting(mContext)) {
+            if (new EuiccRepository(mContext).showEuiccSettings()) {
                 mPreference.setOnPreferenceClickListener((Preference pref) -> {
                     logPreferenceClick(pref);
                     startAddSimFlow();
diff --git a/src/com/android/settings/network/NetworkDashboardFragment.java b/src/com/android/settings/network/NetworkDashboardFragment.java
index 3bc5358..aff9130 100644
--- a/src/com/android/settings/network/NetworkDashboardFragment.java
+++ b/src/com/android/settings/network/NetworkDashboardFragment.java
@@ -25,7 +25,6 @@
 import com.android.settings.SettingsDumpService;
 import com.android.settings.core.OnActivityResultListener;
 import com.android.settings.dashboard.DashboardFragment;
-import com.android.settings.flags.Flags;
 import com.android.settings.search.BaseSearchIndexProvider;
 import com.android.settingslib.core.AbstractPreferenceController;
 import com.android.settingslib.core.lifecycle.Lifecycle;
@@ -90,14 +89,6 @@
 
         controllers.add(new MobileNetworkSummaryController(context, lifecycle, lifecycleOwner));
         controllers.add(vpnPreferenceController);
-
-        if (Flags.internetPreferenceControllerV2()) {
-            controllers.add(
-                    new InternetPreferenceControllerV2(context, InternetPreferenceController.KEY));
-        } else {
-            controllers.add(new InternetPreferenceController(context, lifecycle, lifecycleOwner));
-        }
-
         controllers.add(privateDnsPreferenceController);
 
         // Start SettingsDumpService after the MobileNetworkRepository is created.
diff --git a/src/com/android/settings/network/apn/ApnRepository.kt b/src/com/android/settings/network/apn/ApnRepository.kt
index 8433715..7ed0c86 100644
--- a/src/com/android/settings/network/apn/ApnRepository.kt
+++ b/src/com/android/settings/network/apn/ApnRepository.kt
@@ -21,10 +21,10 @@
 import android.database.Cursor
 import android.net.Uri
 import android.provider.Telephony
-import android.telephony.SubscriptionManager
 import android.telephony.TelephonyManager
 import android.util.Log
 import com.android.settings.R
+import com.android.settings.network.telephony.telephonyManager
 import com.android.settingslib.utils.ThreadUtils
 import java.util.Locale
 
@@ -178,12 +178,11 @@
 }
 
 fun Context.getApnIdMap(subId: Int): Map<String, Any> {
-    val subInfo = getSystemService(SubscriptionManager::class.java)!!
-        .getActiveSubscriptionInfo(subId)
-    val carrierId = subInfo.carrierId
+    val telephonyManager = telephonyManager(subId)
+    val carrierId = telephonyManager.simSpecificCarrierId
     return if (carrierId != TelephonyManager.UNKNOWN_CARRIER_ID) {
         mapOf(Telephony.Carriers.CARRIER_ID to carrierId)
     } else {
-        mapOf(Telephony.Carriers.NUMERIC to subInfo.mccString + subInfo.mncString)
+        mapOf(Telephony.Carriers.NUMERIC to telephonyManager.simOperator)
     }.also { Log.d(TAG, "[$subId] New APN item with id: $it") }
 }
diff --git a/src/com/android/settings/network/ims/VtQueryImsState.java b/src/com/android/settings/network/ims/VtQueryImsState.java
index 5c48ff0..7351b83 100644
--- a/src/com/android/settings/network/ims/VtQueryImsState.java
+++ b/src/com/android/settings/network/ims/VtQueryImsState.java
@@ -18,24 +18,17 @@
 
 import android.content.Context;
 import android.telecom.TelecomManager;
-import android.telephony.AccessNetworkConstants;
 import android.telephony.SubscriptionManager;
-import android.telephony.ims.ImsException;
-import android.telephony.ims.feature.MmTelFeature;
-import android.telephony.ims.stub.ImsRegistrationImplBase;
-import android.util.Log;
 
 import androidx.annotation.VisibleForTesting;
 
 /**
  * Controller class for querying VT status
  */
-public class VtQueryImsState extends ImsQueryController {
+public class VtQueryImsState {
 
-    private static final String LOG_TAG = "VtQueryImsState";
-
-    private Context mContext;
-    private int mSubId;
+    private final Context mContext;
+    private final int mSubId;
 
     /**
      * Constructor
@@ -44,9 +37,6 @@
      * @param subId subscription's id
      */
     public VtQueryImsState(Context context, int subId) {
-        super(MmTelFeature.MmTelCapabilities.CAPABILITY_TYPE_VIDEO,
-                ImsRegistrationImplBase.REGISTRATION_TECH_LTE,
-                AccessNetworkConstants.TRANSPORT_TYPE_WWAN);
         mContext = context;
         mSubId = subId;
     }
@@ -63,24 +53,6 @@
     }
 
     /**
-     * Check whether Video Call can be perform or not on this subscription
-     *
-     * @return true when Video Call can be performed, otherwise false
-     */
-    public boolean isReadyToVideoCall() {
-        if (!isProvisionedOnDevice(mSubId)) {
-            return false;
-        }
-
-        try {
-            return isEnabledByPlatform(mSubId) && isServiceStateReady(mSubId);
-        } catch (InterruptedException | IllegalArgumentException | ImsException exception) {
-            Log.w(LOG_TAG, "fail to get Vt ready. subId=" + mSubId, exception);
-        }
-        return false;
-    }
-
-    /**
      * Get allowance status for user to alter configuration
      *
      * @return true when changing configuration by user is allowed.
@@ -89,8 +61,7 @@
         if (!SubscriptionManager.isValidSubscriptionId(mSubId)) {
             return false;
         }
-        return ((!isTtyEnabled(mContext))
-                || (isTtyOnVolteEnabled(mSubId)));
+        return !isTtyEnabled(mContext) || new ImsQueryTtyOnVolteStat(mSubId).query();
     }
 
     @VisibleForTesting
diff --git a/src/com/android/settings/network/telephony/CarrierConfigRepository.kt b/src/com/android/settings/network/telephony/CarrierConfigRepository.kt
index 3f5c06e..8852540 100644
--- a/src/com/android/settings/network/telephony/CarrierConfigRepository.kt
+++ b/src/com/android/settings/network/telephony/CarrierConfigRepository.kt
@@ -50,7 +50,7 @@
         private val keysToRetrieve = mutableMapOf<String, KeyType>()
 
         override fun getBoolean(key: String): Boolean {
-            check(key.endsWith("_bool")) { "Boolean key should ends with _bool" }
+            checkBooleanKey(key)
             val value = cache[key]
             return if (value == null) {
                 keysToRetrieve += key to KeyType.BOOLEAN
@@ -186,9 +186,18 @@
             ListenerRegistered.getAndSet(false)
         }
 
+        private val BooleanKeysWhichNotFollowingsNamingConventions =
+            listOf(CarrierConfigManager.KEY_IGNORE_DATA_ENABLED_CHANGED_FOR_VIDEO_CALLS)
+
+        private fun checkBooleanKey(key: String) {
+            check(key.endsWith("_bool") || key in BooleanKeysWhichNotFollowingsNamingConventions) {
+                "Boolean key should ends with _bool"
+            }
+        }
+
         @VisibleForTesting
         fun setBooleanForTest(subId: Int, key: String, value: Boolean) {
-            check(key.endsWith("_bool")) { "Boolean key should ends with _bool" }
+            checkBooleanKey(key)
             getPerSubCache(subId)[key] = BooleanConfigValue(value)
         }
 
diff --git a/src/com/android/settings/network/telephony/MobileNetworkSettings.java b/src/com/android/settings/network/telephony/MobileNetworkSettings.java
index a5cdb95..91874c4 100644
--- a/src/com/android/settings/network/telephony/MobileNetworkSettings.java
+++ b/src/com/android/settings/network/telephony/MobileNetworkSettings.java
@@ -41,6 +41,7 @@
 import androidx.annotation.NonNull;
 import androidx.annotation.Nullable;
 import androidx.annotation.VisibleForTesting;
+import androidx.lifecycle.LifecycleOwner;
 import androidx.lifecycle.ViewModelProvider;
 import androidx.preference.Preference;
 
@@ -66,6 +67,8 @@
 import com.android.settingslib.search.SearchIndexable;
 import com.android.settingslib.utils.ThreadUtils;
 
+import kotlin.Unit;
+
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.List;
@@ -359,6 +362,16 @@
     public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
         super.onViewCreated(view, savedInstanceState);
         collectAirplaneModeAndFinishIfOn(this);
+
+        LifecycleOwner viewLifecycleOwner = getViewLifecycleOwner();
+        new SubscriptionRepository(requireContext())
+                .collectSubscriptionVisible(mSubId, viewLifecycleOwner, (isVisible) -> {
+                    if (!isVisible) {
+                        Log.d(LOG_TAG, "Due to subscription not visible, closes page");
+                        finishFragment();
+                    }
+                    return Unit.INSTANCE;
+                });
     }
 
     @Override
@@ -532,11 +545,6 @@
                 Log.d(LOG_TAG, "Set subInfo to default subInfo.");
             }
         }
-        if (mSubscriptionInfoEntity == null && getActivity() != null) {
-            // If the current subId is not existed, finish it.
-            finishFragment();
-            return;
-        }
         onSubscriptionDetailChanged();
     }
 }
diff --git a/src/com/android/settings/network/telephony/MobileNetworkSettingsSearchIndex.kt b/src/com/android/settings/network/telephony/MobileNetworkSettingsSearchIndex.kt
index c63e7d2..4f31e0f 100644
--- a/src/com/android/settings/network/telephony/MobileNetworkSettingsSearchIndex.kt
+++ b/src/com/android/settings/network/telephony/MobileNetworkSettingsSearchIndex.kt
@@ -26,6 +26,7 @@
 import com.android.settings.network.telephony.MmsMessagePreferenceController.Companion.MmsMessageSearchItem
 import com.android.settings.network.telephony.NrAdvancedCallingPreferenceController.Companion.NrAdvancedCallingSearchItem
 import com.android.settings.network.telephony.RoamingPreferenceController.Companion.RoamingSearchItem
+import com.android.settings.network.telephony.VideoCallingPreferenceController.Companion.VideoCallingSearchItem
 import com.android.settings.network.telephony.WifiCallingPreferenceController.Companion.WifiCallingSearchItem
 import com.android.settings.spa.SpaSearchLanding.BundleValue
 import com.android.settings.spa.SpaSearchLanding.SpaSearchLandingFragment
@@ -122,6 +123,7 @@
                 NrAdvancedCallingSearchItem(context),
                 PreferredNetworkModeSearchItem(context),
                 RoamingSearchItem(context),
+                VideoCallingSearchItem(context),
                 WifiCallingSearchItem(context),
             )
     }
diff --git a/src/com/android/settings/network/telephony/MobileNetworkUtils.java b/src/com/android/settings/network/telephony/MobileNetworkUtils.java
index 517f66a..235418e 100644
--- a/src/com/android/settings/network/telephony/MobileNetworkUtils.java
+++ b/src/com/android/settings/network/telephony/MobileNetworkUtils.java
@@ -32,7 +32,6 @@
 import static com.android.settings.network.telephony.TelephonyConstants.TelephonyManagerConstants.NETWORK_MODE_NR_LTE_GSM_WCDMA;
 
 import android.app.KeyguardManager;
-import android.content.ContentResolver;
 import android.content.Context;
 import android.content.Intent;
 import android.content.pm.PackageManager;
@@ -51,8 +50,6 @@
 import android.os.Handler;
 import android.os.Looper;
 import android.os.PersistableBundle;
-import android.os.SystemClock;
-import android.os.SystemProperties;
 import android.os.UserHandle;
 import android.os.UserManager;
 import android.provider.Settings;
@@ -89,32 +86,17 @@
 import com.android.settings.network.telephony.TelephonyConstants.TelephonyManagerConstants;
 import com.android.settings.network.telephony.wificalling.WifiCallingRepository;
 import com.android.settingslib.core.instrumentation.Instrumentable;
-import com.android.settingslib.development.DevelopmentSettingsEnabler;
 import com.android.settingslib.graph.SignalDrawable;
 import com.android.settingslib.mobile.dataservice.SubscriptionInfoEntity;
-import com.android.settingslib.utils.ThreadUtils;
 
-import java.util.Arrays;
 import java.util.HashSet;
 import java.util.List;
 import java.util.Set;
-import java.util.concurrent.ExecutionException;
-import java.util.concurrent.Future;
-import java.util.concurrent.TimeUnit;
-import java.util.concurrent.TimeoutException;
 
 public class MobileNetworkUtils {
 
     private static final String TAG = "MobileNetworkUtils";
 
-    // CID of the device.
-    private static final String KEY_CID = "ro.boot.cid";
-    // CIDs of devices which should not show anything related to eSIM.
-    private static final String KEY_ESIM_CID_IGNORE = "ro.setupwizard.esim_cid_ignore";
-    // System Property which is used to decide whether the default eSIM UI will be shown,
-    // the default value is false.
-    private static final String KEY_ENABLE_ESIM_UI_BY_DEFAULT =
-            "esim.enable_esim_system_ui_by_default";
     private static final String LEGACY_ACTION_CONFIGURE_PHONE_ACCOUNT =
             "android.telecom.action.CONNECTION_SERVICE_CONFIGURE";
     private static final String RTL_MARK = "\u200F";
@@ -283,64 +265,6 @@
     }
 
     /**
-     * Whether to show the entry point to eUICC settings.
-     *
-     * <p>We show the entry point on any device which supports eUICC as long as either the eUICC
-     * was ever provisioned (that is, at least one profile was ever downloaded onto it), or if
-     * the user has enabled development mode.
-     */
-    public static boolean showEuiccSettings(Context context) {
-        if (!SubscriptionUtil.isSimHardwareVisible(context)) {
-            return false;
-        }
-        long timeForAccess = SystemClock.elapsedRealtime();
-        try {
-            Boolean isShow = ((Future<Boolean>) ThreadUtils.postOnBackgroundThread(() -> {
-                        try {
-                            return showEuiccSettingsDetecting(context);
-                        } catch (Exception threadException) {
-                            Log.w(TAG, "Accessing Euicc failure", threadException);
-                        }
-                        return Boolean.FALSE;
-                    })).get(3, TimeUnit.SECONDS);
-            return ((isShow != null) && isShow.booleanValue());
-        } catch (ExecutionException | InterruptedException | TimeoutException exception) {
-            timeForAccess = SystemClock.elapsedRealtime() - timeForAccess;
-            Log.w(TAG, "Accessing Euicc takes too long: +" + timeForAccess + "ms");
-        }
-        return false;
-    }
-
-    // The same as #showEuiccSettings(Context context)
-    public static Boolean showEuiccSettingsDetecting(Context context) {
-        final EuiccManager euiccManager =
-                (EuiccManager) context.getSystemService(EuiccManager.class);
-        if (euiccManager == null || !euiccManager.isEnabled()) {
-            Log.w(TAG, "EuiccManager is not enabled.");
-            return false;
-        }
-
-        final ContentResolver cr = context.getContentResolver();
-        final boolean esimIgnoredDevice =
-                Arrays.asList(TextUtils.split(SystemProperties.get(KEY_ESIM_CID_IGNORE, ""), ","))
-                        .contains(SystemProperties.get(KEY_CID));
-        final boolean enabledEsimUiByDefault =
-                SystemProperties.getBoolean(KEY_ENABLE_ESIM_UI_BY_DEFAULT, true);
-        final boolean euiccProvisioned =
-                Settings.Global.getInt(cr, Settings.Global.EUICC_PROVISIONED, 0) != 0;
-        final boolean inDeveloperMode =
-                DevelopmentSettingsEnabler.isDevelopmentSettingsEnabled(context);
-        Log.i(TAG,
-                String.format("showEuiccSettings: esimIgnoredDevice: %b, enabledEsimUiByDefault: "
-                        + "%b, euiccProvisioned: %b, inDeveloperMode: %b.",
-                esimIgnoredDevice, enabledEsimUiByDefault, euiccProvisioned, inDeveloperMode));
-        return (euiccProvisioned
-                || (!esimIgnoredDevice && inDeveloperMode)
-                || (!esimIgnoredDevice && enabledEsimUiByDefault
-                        && isCurrentCountrySupported(context)));
-    }
-
-    /**
      * Return {@code true} if mobile data is enabled
      */
     public static boolean isMobileDataEnabled(Context context) {
diff --git a/src/com/android/settings/network/telephony/SubscriptionRepository.kt b/src/com/android/settings/network/telephony/SubscriptionRepository.kt
index cc8c8b4..26ea9b3 100644
--- a/src/com/android/settings/network/telephony/SubscriptionRepository.kt
+++ b/src/com/android/settings/network/telephony/SubscriptionRepository.kt
@@ -50,6 +50,31 @@
     fun getSelectableSubscriptionInfoList(): List<SubscriptionInfo> =
         context.getSelectableSubscriptionInfoList()
 
+    /** Flow of whether the subscription visible for the given [subId]. */
+    fun isSubscriptionVisibleFlow(subId: Int): Flow<Boolean> {
+        return subscriptionsChangedFlow()
+            .map {
+                val subInfo =
+                    subscriptionManager.availableSubscriptionInfoList?.firstOrNull { subInfo ->
+                        subInfo.subscriptionId == subId
+                    }
+                subInfo != null &&
+                    SubscriptionUtil.isSubscriptionVisible(subscriptionManager, context, subInfo)
+            }
+            .conflate()
+            .onEach { Log.d(TAG, "[$subId] isSubscriptionVisibleFlow: $it") }
+            .flowOn(Dispatchers.Default)
+    }
+
+    /** TODO: Move this to UI layer, when UI layer migrated to Kotlin. */
+    fun collectSubscriptionVisible(
+        subId: Int,
+        lifecycleOwner: LifecycleOwner,
+        action: (Boolean) -> Unit,
+    ) {
+        isSubscriptionVisibleFlow(subId).collectLatestWithLifecycle(lifecycleOwner, action = action)
+    }
+
     /** Flow of whether the subscription enabled for the given [subId]. */
     fun isSubscriptionEnabledFlow(subId: Int): Flow<Boolean> {
         if (!SubscriptionManager.isValidSubscriptionId(subId)) return flowOf(false)
diff --git a/src/com/android/settings/network/telephony/VideoCallingPreferenceController.java b/src/com/android/settings/network/telephony/VideoCallingPreferenceController.java
deleted file mode 100644
index f803efd..0000000
--- a/src/com/android/settings/network/telephony/VideoCallingPreferenceController.java
+++ /dev/null
@@ -1,234 +0,0 @@
-/*
- * Copyright (C) 2018 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 android.content.Context;
-import android.content.pm.PackageManager;
-import android.os.PersistableBundle;
-import android.telephony.CarrierConfigManager;
-import android.telephony.SubscriptionManager;
-import android.telephony.TelephonyCallback;
-import android.telephony.TelephonyManager;
-import android.telephony.ims.ImsMmTelManager;
-import android.util.Log;
-
-import androidx.annotation.VisibleForTesting;
-import androidx.preference.Preference;
-import androidx.preference.PreferenceScreen;
-import androidx.preference.TwoStatePreference;
-
-import com.android.internal.telephony.flags.Flags;
-import com.android.settings.network.CarrierConfigCache;
-import com.android.settings.network.MobileDataEnabledListener;
-import com.android.settings.network.ims.VolteQueryImsState;
-import com.android.settings.network.ims.VtQueryImsState;
-import com.android.settingslib.core.lifecycle.LifecycleObserver;
-import com.android.settingslib.core.lifecycle.events.OnStart;
-import com.android.settingslib.core.lifecycle.events.OnStop;
-
-/**
- * Preference controller for "Video Calling"
- */
-public class VideoCallingPreferenceController extends TelephonyTogglePreferenceController implements
-        LifecycleObserver, OnStart, OnStop,
-        MobileDataEnabledListener.Client,
-        Enhanced4gBasePreferenceController.On4gLteUpdateListener {
-
-    private static final String TAG = "VideoCallingPreference";
-
-    private Preference mPreference;
-    private PhoneTelephonyCallback mTelephonyCallback;
-    @VisibleForTesting
-    Integer mCallState;
-    private MobileDataEnabledListener mDataContentObserver;
-    private CallingPreferenceCategoryController mCallingPreferenceCategoryController;
-
-    public VideoCallingPreferenceController(Context context, String key) {
-        super(context, key);
-        mDataContentObserver = new MobileDataEnabledListener(context, this);
-        mTelephonyCallback = new PhoneTelephonyCallback();
-    }
-
-    @Override
-    public int getAvailabilityStatus(int subId) {
-        return SubscriptionManager.isValidSubscriptionId(subId)
-                && isVideoCallEnabled(subId)
-                ? AVAILABLE
-                : CONDITIONALLY_UNAVAILABLE;
-    }
-
-    @Override
-    public void displayPreference(PreferenceScreen screen) {
-        super.displayPreference(screen);
-        mPreference = screen.findPreference(getPreferenceKey());
-    }
-
-    @Override
-    public void onStart() {
-        mTelephonyCallback.register(mContext, mSubId);
-        mDataContentObserver.start(mSubId);
-    }
-
-    @Override
-    public void onStop() {
-        mTelephonyCallback.unregister();
-        mDataContentObserver.stop();
-    }
-
-    @Override
-    public void updateState(Preference preference) {
-        super.updateState(preference);
-        if ((mCallState == null) || (preference == null)) {
-            Log.d(TAG, "Skip update under mCallState=" + mCallState);
-            return;
-        }
-        final TwoStatePreference switchPreference = (TwoStatePreference) preference;
-        final boolean videoCallEnabled = isVideoCallEnabled(mSubId);
-        switchPreference.setVisible(videoCallEnabled);
-        mCallingPreferenceCategoryController
-                .updateChildVisible(getPreferenceKey(), videoCallEnabled);
-        if (videoCallEnabled) {
-            final boolean videoCallEditable = queryVoLteState(mSubId).isEnabledByUser()
-                    && queryImsState(mSubId).isAllowUserControl();
-            preference.setEnabled(videoCallEditable
-                    && mCallState == TelephonyManager.CALL_STATE_IDLE);
-            switchPreference.setChecked(videoCallEditable && isChecked());
-        }
-    }
-
-    @Override
-    public boolean setChecked(boolean isChecked) {
-        if (!SubscriptionManager.isValidSubscriptionId(mSubId)) {
-            return false;
-        }
-        final ImsMmTelManager imsMmTelManager = ImsMmTelManager.createForSubscriptionId(mSubId);
-        if (imsMmTelManager == null) {
-            return false;
-        }
-        try {
-            imsMmTelManager.setVtSettingEnabled(isChecked);
-            return true;
-        } catch (IllegalArgumentException exception) {
-            Log.w(TAG, "Unable to set VT status " + isChecked + ". subId=" + mSubId,
-                    exception);
-        }
-        return false;
-    }
-
-    @Override
-    public boolean isChecked() {
-        return queryImsState(mSubId).isEnabledByUser();
-    }
-
-    @VisibleForTesting
-    protected boolean isImsSupported() {
-        return mContext.getPackageManager().hasSystemFeature(
-                PackageManager.FEATURE_TELEPHONY_IMS);
-    }
-
-    /**
-     * Init instance of VideoCallingPreferenceController.
-     */
-    public VideoCallingPreferenceController init(
-            int subId, CallingPreferenceCategoryController callingPreferenceCategoryController) {
-        mSubId = subId;
-        mCallingPreferenceCategoryController = callingPreferenceCategoryController;
-
-        return this;
-    }
-
-    @VisibleForTesting
-    boolean isVideoCallEnabled(int subId) {
-        if (!SubscriptionManager.isValidSubscriptionId(subId)) {
-            return false;
-        }
-
-        final PersistableBundle carrierConfig =
-                CarrierConfigCache.getInstance(mContext).getConfigForSubId(subId);
-        if (carrierConfig == null) {
-            return false;
-        }
-
-        if (!carrierConfig.getBoolean(
-                CarrierConfigManager.KEY_IGNORE_DATA_ENABLED_CHANGED_FOR_VIDEO_CALLS)
-                && (!mContext.getSystemService(TelephonyManager.class)
-                    .createForSubscriptionId(subId).isDataEnabled())) {
-            return false;
-        }
-
-        return isImsSupported() && queryImsState(subId).isReadyToVideoCall();
-    }
-
-    @Override
-    public void on4gLteUpdated() {
-        updateState(mPreference);
-    }
-
-    private class PhoneTelephonyCallback extends TelephonyCallback implements
-            TelephonyCallback.CallStateListener {
-
-        private TelephonyManager mTelephonyManager;
-
-        @Override
-        public void onCallStateChanged(int state) {
-            mCallState = state;
-            updateState(mPreference);
-        }
-
-        public void register(Context context, int subId) {
-            mTelephonyManager = context.getSystemService(TelephonyManager.class);
-            if (SubscriptionManager.isValidSubscriptionId(subId)) {
-                mTelephonyManager = mTelephonyManager.createForSubscriptionId(subId);
-            }
-            // assign current call state so that it helps to show correct preference state even
-            // before first onCallStateChanged() by initial registration.
-            if (Flags.enforceTelephonyFeatureMappingForPublicApis()) {
-                try {
-                    mCallState = mTelephonyManager.getCallState(subId);
-                } catch (UnsupportedOperationException e) {
-                    // Device doesn't support FEATURE_TELEPHONY_CALLING
-                    mCallState = TelephonyManager.CALL_STATE_IDLE;
-                }
-            } else {
-                mCallState = mTelephonyManager.getCallState(subId);
-            }
-            mTelephonyManager.registerTelephonyCallback(context.getMainExecutor(), this);
-        }
-
-        public void unregister() {
-            mCallState = null;
-            mTelephonyManager.unregisterTelephonyCallback(this);
-        }
-    }
-
-    /**
-     * Implementation of MobileDataEnabledListener.Client
-     */
-    public void onMobileDataEnabledChange() {
-        updateState(mPreference);
-    }
-
-    @VisibleForTesting
-    VtQueryImsState queryImsState(int subId) {
-        return new VtQueryImsState(mContext, subId);
-    }
-
-    @VisibleForTesting
-    VolteQueryImsState queryVoLteState(int subId) {
-        return new VolteQueryImsState(mContext, subId);
-    }
-}
diff --git a/src/com/android/settings/network/telephony/VideoCallingPreferenceController.kt b/src/com/android/settings/network/telephony/VideoCallingPreferenceController.kt
new file mode 100644
index 0000000..e6b3f31
--- /dev/null
+++ b/src/com/android/settings/network/telephony/VideoCallingPreferenceController.kt
@@ -0,0 +1,147 @@
+/*
+ * 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 android.content.Context
+import android.telephony.SubscriptionManager
+import android.telephony.TelephonyManager
+import android.telephony.ims.ImsManager
+import android.util.Log
+import androidx.annotation.VisibleForTesting
+import androidx.lifecycle.LifecycleOwner
+import androidx.preference.Preference
+import androidx.preference.PreferenceScreen
+import androidx.preference.TwoStatePreference
+import com.android.settings.R
+import com.android.settings.core.TogglePreferenceController
+import com.android.settings.network.ims.VolteQueryImsState
+import com.android.settings.network.ims.VtQueryImsState
+import com.android.settings.network.telephony.Enhanced4gBasePreferenceController.On4gLteUpdateListener
+import com.android.settings.network.telephony.MobileNetworkSettingsSearchIndex.MobileNetworkSettingsSearchItem
+import com.android.settings.network.telephony.MobileNetworkSettingsSearchIndex.MobileNetworkSettingsSearchResult
+import com.android.settingslib.spa.framework.util.collectLatestWithLifecycle
+import kotlinx.coroutines.flow.first
+import kotlinx.coroutines.runBlocking
+
+/** Preference controller for "Video Calling" */
+class VideoCallingPreferenceController
+@JvmOverloads
+constructor(
+    context: Context,
+    key: String,
+    private val callStateRepository: CallStateRepository = CallStateRepository(context),
+) : TogglePreferenceController(context, key), On4gLteUpdateListener {
+
+    private var subId = SubscriptionManager.INVALID_SUBSCRIPTION_ID
+    private var preference: TwoStatePreference? = null
+    private var callingPreferenceCategoryController: CallingPreferenceCategoryController? = null
+    private val repository = VideoCallingRepository(context)
+
+    private var videoCallEditable = false
+    private var isInCall = false
+
+    /** Init instance of VideoCallingPreferenceController. */
+    fun init(
+        subId: Int,
+        callingPreferenceCategoryController: CallingPreferenceCategoryController?,
+    ): VideoCallingPreferenceController {
+        this.subId = subId
+        this.callingPreferenceCategoryController = callingPreferenceCategoryController
+
+        return this
+    }
+
+    // Availability is controlled in onViewCreated() and VideoCallingSearchItem.
+    override fun getAvailabilityStatus() = AVAILABLE
+
+    override fun displayPreference(screen: PreferenceScreen) {
+        super.displayPreference(screen)
+        preference = screen.findPreference(preferenceKey)
+    }
+
+    override fun onViewCreated(viewLifecycleOwner: LifecycleOwner) {
+        repository.isVideoCallReadyFlow(subId).collectLatestWithLifecycle(viewLifecycleOwner) {
+            isReady ->
+            preference?.isVisible = isReady
+            callingPreferenceCategoryController?.updateChildVisible(preferenceKey, isReady)
+        }
+        callStateRepository.callStateFlow(subId).collectLatestWithLifecycle(viewLifecycleOwner) {
+            callState ->
+            isInCall = callState != TelephonyManager.CALL_STATE_IDLE
+            updatePreference()
+        }
+    }
+
+    override fun updateState(preference: Preference) {
+        super.updateState(preference)
+        videoCallEditable =
+            queryVoLteState(subId).isEnabledByUser && queryImsState(subId).isAllowUserControl
+        updatePreference()
+    }
+
+    private fun updatePreference() {
+        preference?.isEnabled = videoCallEditable && !isInCall
+        preference?.isChecked = videoCallEditable && isChecked
+    }
+
+    override fun getSliceHighlightMenuRes() = NO_RES
+
+    override fun setChecked(isChecked: Boolean): Boolean {
+        if (!SubscriptionManager.isValidSubscriptionId(subId)) {
+            return false
+        }
+        val imsMmTelManager = ImsManager(mContext).getImsMmTelManager(subId)
+        try {
+            imsMmTelManager.isVtSettingEnabled = isChecked
+            return true
+        } catch (exception: IllegalArgumentException) {
+            Log.w(TAG, "[$subId] Unable to set VT status $isChecked", exception)
+        }
+        return false
+    }
+
+    override fun isChecked(): Boolean = queryImsState(subId).isEnabledByUser
+
+    override fun on4gLteUpdated() {
+        preference?.let { updateState(it) }
+    }
+
+    @VisibleForTesting fun queryImsState(subId: Int) = VtQueryImsState(mContext, subId)
+
+    @VisibleForTesting fun queryVoLteState(subId: Int) = VolteQueryImsState(mContext, subId)
+
+    companion object {
+        private const val TAG = "VideoCallingPreferenceController"
+
+        class VideoCallingSearchItem(private val context: Context) :
+            MobileNetworkSettingsSearchItem {
+            private val repository = VideoCallingRepository(context)
+
+            private fun isAvailable(subId: Int): Boolean = runBlocking {
+                repository.isVideoCallReadyFlow(subId).first()
+            }
+
+            override fun getSearchResult(subId: Int): MobileNetworkSettingsSearchResult? {
+                if (!isAvailable(subId)) return null
+                return MobileNetworkSettingsSearchResult(
+                    key = "video_calling_key",
+                    title = context.getString(R.string.video_calling_settings_title),
+                )
+            }
+        }
+    }
+}
diff --git a/src/com/android/settings/network/telephony/VideoCallingRepository.kt b/src/com/android/settings/network/telephony/VideoCallingRepository.kt
new file mode 100644
index 0000000..634eb28
--- /dev/null
+++ b/src/com/android/settings/network/telephony/VideoCallingRepository.kt
@@ -0,0 +1,65 @@
+/*
+ * 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 android.content.Context
+import android.telephony.AccessNetworkConstants
+import android.telephony.CarrierConfigManager
+import android.telephony.SubscriptionManager
+import android.telephony.ims.feature.MmTelFeature
+import android.telephony.ims.stub.ImsRegistrationImplBase
+import com.android.settings.network.telephony.ims.ImsFeatureRepository
+import kotlinx.coroutines.ExperimentalCoroutinesApi
+import kotlinx.coroutines.flow.Flow
+import kotlinx.coroutines.flow.flatMapLatest
+import kotlinx.coroutines.flow.flowOf
+
+@OptIn(ExperimentalCoroutinesApi::class)
+class VideoCallingRepository(
+    context: Context,
+    private val mobileDataRepository: MobileDataRepository = MobileDataRepository(context),
+    private val imsFeatureRepositoryFactory: (Int) -> ImsFeatureRepository = { subId ->
+        ImsFeatureRepository(context, subId)
+    },
+) {
+    private val carrierConfigRepository = CarrierConfigRepository(context)
+
+    fun isVideoCallReadyFlow(subId: Int): Flow<Boolean> {
+        if (!SubscriptionManager.isValidSubscriptionId(subId)) return flowOf(false)
+
+        return isPreconditionMeetFlow(subId).flatMapLatest { isPreconditionMeet ->
+            if (isPreconditionMeet) {
+                imsFeatureRepositoryFactory(subId)
+                    .isReadyFlow(
+                        capability = MmTelFeature.MmTelCapabilities.CAPABILITY_TYPE_VIDEO,
+                        tech = ImsRegistrationImplBase.REGISTRATION_TECH_LTE,
+                        transportType = AccessNetworkConstants.TRANSPORT_TYPE_WWAN,
+                    )
+            } else {
+                flowOf(false)
+            }
+        }
+    }
+
+    private fun isPreconditionMeetFlow(subId: Int): Flow<Boolean> =
+        if (carrierConfigRepository.getBoolean(
+            subId, CarrierConfigManager.KEY_IGNORE_DATA_ENABLED_CHANGED_FOR_VIDEO_CALLS)) {
+            flowOf(true)
+        } else {
+            mobileDataRepository.isMobileDataEnabledFlow(subId)
+        }
+}
diff --git a/src/com/android/settings/network/telephony/WifiCallingPreferenceController.kt b/src/com/android/settings/network/telephony/WifiCallingPreferenceController.kt
index e04763a..9b68970 100644
--- a/src/com/android/settings/network/telephony/WifiCallingPreferenceController.kt
+++ b/src/com/android/settings/network/telephony/WifiCallingPreferenceController.kt
@@ -81,6 +81,12 @@
     }
 
     override fun onViewCreated(viewLifecycleOwner: LifecycleOwner) {
+        if (!SubscriptionManager.isValidSubscriptionId(subId)) {
+            // Sub id could invalid, if this page is opened from external action and no sim is
+            // active.
+            // Ignore this case, since this page will be finished soon.
+            return
+        }
         wifiCallingRepositoryFactory(subId).wifiCallingReadyFlow()
             .collectLatestWithLifecycle(viewLifecycleOwner) { isReady ->
                 preference.isVisible = isReady
diff --git a/src/com/android/settings/network/telephony/euicc/EuiccRepository.kt b/src/com/android/settings/network/telephony/euicc/EuiccRepository.kt
new file mode 100644
index 0000000..74b5313
--- /dev/null
+++ b/src/com/android/settings/network/telephony/euicc/EuiccRepository.kt
@@ -0,0 +1,129 @@
+/*
+ * 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.euicc
+
+import android.content.Context
+import android.os.SystemProperties
+import android.provider.Settings
+import android.telephony.TelephonyManager
+import android.telephony.euicc.EuiccManager
+import android.util.Log
+import com.android.settings.network.SubscriptionUtil
+import com.android.settingslib.development.DevelopmentSettingsEnabler
+import com.android.settingslib.spaprivileged.settingsprovider.settingsGlobalBoolean
+import kotlinx.coroutines.Dispatchers
+import kotlinx.coroutines.flow.conflate
+import kotlinx.coroutines.flow.distinctUntilChanged
+import kotlinx.coroutines.flow.flow
+import kotlinx.coroutines.flow.flowOn
+
+class EuiccRepository
+@JvmOverloads
+constructor(
+    private val context: Context,
+    private val isEuiccProvisioned: () -> Boolean = {
+        val euiccProvisioned by context.settingsGlobalBoolean(Settings.Global.EUICC_PROVISIONED)
+        euiccProvisioned
+    },
+    private val isDevelopmentSettingsEnabled: () -> Boolean = {
+        DevelopmentSettingsEnabler.isDevelopmentSettingsEnabled(context)
+    },
+) {
+
+    private val euiccManager = context.getSystemService(EuiccManager::class.java)
+    private val telephonyManager = context.getSystemService(TelephonyManager::class.java)
+
+    fun showEuiccSettingsFlow() =
+        flow { emit(showEuiccSettings()) }
+            .distinctUntilChanged()
+            .conflate()
+            .flowOn(Dispatchers.Default)
+
+    /**
+     * Whether to show the entry point to eUICC settings.
+     *
+     * We show the entry point on any device which supports eUICC as long as either the eUICC was
+     * ever provisioned (that is, at least one profile was ever downloaded onto it), or if the user
+     * has enabled development mode.
+     */
+    fun showEuiccSettings(): Boolean {
+        if (!SubscriptionUtil.isSimHardwareVisible(context)) return false
+        if (euiccManager == null || !euiccManager.isEnabled) {
+            Log.w(TAG, "EuiccManager is not enabled.")
+            return false
+        }
+        if (isEuiccProvisioned()) {
+            Log.i(TAG, "showEuiccSettings: euicc provisioned")
+            return true
+        }
+        val ignoredCids =
+            SystemProperties.get(KEY_ESIM_CID_IGNORE).split(',').filter { it.isNotEmpty() }
+        val cid = SystemProperties.get(KEY_CID)
+        if (cid in ignoredCids) {
+            Log.i(TAG, "showEuiccSettings: cid ignored")
+            return false
+        }
+        if (isDevelopmentSettingsEnabled()) {
+            Log.i(TAG, "showEuiccSettings: development settings enabled")
+            return true
+        }
+        val enabledEsimUiByDefault =
+            SystemProperties.getBoolean(KEY_ENABLE_ESIM_UI_BY_DEFAULT, true)
+        Log.i(TAG, "showEuiccSettings: enabledEsimUiByDefault=$enabledEsimUiByDefault")
+        return enabledEsimUiByDefault && isCurrentCountrySupported()
+    }
+
+    /**
+     * Loop through all the device logical slots to check whether the user's current country
+     * supports eSIM.
+     */
+    private fun isCurrentCountrySupported(): Boolean {
+        val euiccManager = euiccManager ?: return false
+        val telephonyManager = telephonyManager ?: return false
+        val visitedCountrySet = mutableSetOf<String>()
+        for (slotIndex in 0 until telephonyManager.getActiveModemCount()) {
+            val countryCode = telephonyManager.getNetworkCountryIso(slotIndex)
+            if (
+                countryCode.isNotEmpty() &&
+                    visitedCountrySet.add(countryCode) &&
+                    euiccManager.isSupportedCountry(countryCode)
+            ) {
+                Log.i(TAG, "isCurrentCountrySupported: $countryCode is supported")
+                return true
+            }
+        }
+        Log.i(TAG, "isCurrentCountrySupported: no country is supported")
+        return false
+    }
+
+    companion object {
+        private const val TAG = "EuiccRepository"
+
+        /** CID of the device. */
+        private const val KEY_CID: String = "ro.boot.cid"
+
+        /** CIDs of devices which should not show anything related to eSIM. */
+        private const val KEY_ESIM_CID_IGNORE: String = "ro.setupwizard.esim_cid_ignore"
+
+        /**
+         * System Property which is used to decide whether the default eSIM UI will be shown, the
+         * default value is false.
+         */
+        private const val KEY_ENABLE_ESIM_UI_BY_DEFAULT: String =
+            "esim.enable_esim_system_ui_by_default"
+    }
+}
diff --git a/src/com/android/settings/network/telephony/ims/ImsMmTelRepository.kt b/src/com/android/settings/network/telephony/ims/ImsMmTelRepository.kt
index c5d1200..e891204 100644
--- a/src/com/android/settings/network/telephony/ims/ImsMmTelRepository.kt
+++ b/src/com/android/settings/network/telephony/ims/ImsMmTelRepository.kt
@@ -27,6 +27,7 @@
 import android.telephony.ims.RegistrationManager
 import android.telephony.ims.feature.MmTelFeature
 import android.util.Log
+import androidx.annotation.VisibleForTesting
 import kotlin.coroutines.resume
 import kotlinx.coroutines.Dispatchers
 import kotlinx.coroutines.asExecutor
@@ -53,11 +54,6 @@
         @AccessNetworkConstants.TransportType transportType: Int,
     ): Flow<Boolean>
 
-    suspend fun isSupported(
-        @MmTelFeature.MmTelCapabilities.MmTelCapability capability: Int,
-        @AccessNetworkConstants.TransportType transportType: Int,
-    ): Boolean
-
     suspend fun setCrossSimCallingEnabled(enabled: Boolean)
 }
 
@@ -143,7 +139,8 @@
     override fun isSupportedFlow(capability: Int, transportType: Int): Flow<Boolean> =
         imsReadyFlow().map { imsReady -> imsReady && isSupported(capability, transportType) }
 
-    override suspend fun isSupported(
+    @VisibleForTesting
+    suspend fun isSupported(
         @MmTelFeature.MmTelCapabilities.MmTelCapability capability: Int,
         @AccessNetworkConstants.TransportType transportType: Int,
     ): Boolean = withContext(Dispatchers.Default) {
diff --git a/src/com/android/settings/network/telephony/wificalling/CrossSimCallingViewModel.kt b/src/com/android/settings/network/telephony/wificalling/CrossSimCallingViewModel.kt
index dda147b..cab27ca 100644
--- a/src/com/android/settings/network/telephony/wificalling/CrossSimCallingViewModel.kt
+++ b/src/com/android/settings/network/telephony/wificalling/CrossSimCallingViewModel.kt
@@ -21,6 +21,7 @@
 import android.telephony.CarrierConfigManager
 import android.telephony.SubscriptionManager
 import android.telephony.TelephonyManager
+import android.util.Log
 import androidx.lifecycle.AndroidViewModel
 import androidx.lifecycle.viewModelScope
 import com.android.settings.R
@@ -34,6 +35,7 @@
 import kotlinx.coroutines.ExperimentalCoroutinesApi
 import kotlinx.coroutines.flow.Flow
 import kotlinx.coroutines.flow.combine
+import kotlinx.coroutines.flow.conflate
 import kotlinx.coroutines.flow.distinctUntilChanged
 import kotlinx.coroutines.flow.flatMapLatest
 import kotlinx.coroutines.flow.flowOf
@@ -43,9 +45,8 @@
 import kotlinx.coroutines.plus
 
 @OptIn(ExperimentalCoroutinesApi::class)
-class CrossSimCallingViewModel(
-    private val application: Application,
-) : AndroidViewModel(application) {
+class CrossSimCallingViewModel(private val application: Application) :
+    AndroidViewModel(application) {
 
     private val subscriptionRepository = SubscriptionRepository(application)
     private val dataSubscriptionRepository = DataSubscriptionRepository(application)
@@ -61,38 +62,45 @@
                     subscriptionRepository.activeSubscriptionIdListFlow(),
                     dataSubscriptionRepository.defaultDataSubscriptionIdFlow(),
                 ) { activeSubIds, defaultDataSubId ->
-                    activeSubIds to crossSimCallNewEnabled(activeSubIds, defaultDataSubId)
+                    updatableSubIdsFlow(activeSubIds) to
+                        crossSimCallNewEnabledFlow(activeSubIds, defaultDataSubId)
                 }
-                .flatMapLatest { (activeSubIds, newEnabledFlow) ->
-                    newEnabledFlow.map { newEnabled -> activeSubIds to newEnabled }
+                .flatMapLatest { (updatableSubIdsFlow, crossSimCallNewEnabledFlow) ->
+                    combine(updatableSubIdsFlow, crossSimCallNewEnabledFlow) {
+                        updatableSubIds,
+                        newEnabled ->
+                        updatableSubIds to newEnabled
+                    }
                 }
                 .distinctUntilChanged()
-                .onEach { (activeSubIds, newEnabled) ->
-                    updateCrossSimCalling(activeSubIds, newEnabled)
+                .conflate()
+                .onEach { (updatableSubIds, newEnabled) ->
+                    Log.d(TAG, "updatableSubIds: $updatableSubIds newEnabled: $newEnabled")
+                    updateCrossSimCalling(updatableSubIds, newEnabled)
                 }
                 .launchIn(scope)
         }
     }
 
-    private suspend fun updateCrossSimCalling(activeSubIds: List<Int>, newEnabled: Boolean) {
-        metricsFeatureProvider.action(
-            application,
-            SettingsEnums.ACTION_UPDATE_CROSS_SIM_CALLING_ON_AUTO_DATA_SWITCH_EVENT,
-            newEnabled,
-        )
-        activeSubIds
-            .filter { subId -> crossSimAvailable(subId) }
-            .forEach { subId ->
-                ImsMmTelRepositoryImpl(application, subId).setCrossSimCallingEnabled(newEnabled)
+    private fun updatableSubIdsFlow(activeSubIds: List<Int>): Flow<List<Int>> {
+        val updatableSubIdFlows =
+            activeSubIds.map { subId ->
+                WifiCallingRepository(application, subId).wifiCallingReadyFlow().map { isReady ->
+                    subId.takeIf { isReady && isCrossSimImsAvailable(subId) }
+                }
             }
+        return combine(updatableSubIdFlows) { subIds -> subIds.filterNotNull() }
+            .distinctUntilChanged()
+            .conflate()
     }
 
-    private suspend fun crossSimAvailable(subId: Int): Boolean =
-        WifiCallingRepository(application, subId).isWifiCallingSupported() &&
-            carrierConfigRepository.getBoolean(
-                subId, CarrierConfigManager.KEY_CARRIER_CROSS_SIM_IMS_AVAILABLE_BOOL)
+    private fun isCrossSimImsAvailable(subId: Int) =
+        carrierConfigRepository.getBoolean(
+            subId,
+            CarrierConfigManager.KEY_CARRIER_CROSS_SIM_IMS_AVAILABLE_BOOL,
+        )
 
-    private fun crossSimCallNewEnabled(
+    private fun crossSimCallNewEnabledFlow(
         activeSubscriptionIdList: List<Int>,
         defaultDataSubId: Int,
     ): Flow<Boolean> {
@@ -102,8 +110,27 @@
                 .filter { subId -> subId != defaultDataSubId }
                 .map { subId ->
                     mobileDataRepository.isMobileDataPolicyEnabledFlow(
-                        subId, TelephonyManager.MOBILE_DATA_POLICY_AUTO_DATA_SWITCH)
+                        subId,
+                        TelephonyManager.MOBILE_DATA_POLICY_AUTO_DATA_SWITCH,
+                    )
                 }
         return combine(isMobileDataPolicyEnabledFlows) { true in it }
+            .distinctUntilChanged()
+            .conflate()
+    }
+
+    private suspend fun updateCrossSimCalling(subIds: List<Int>, newEnabled: Boolean) {
+        metricsFeatureProvider.action(
+            application,
+            SettingsEnums.ACTION_UPDATE_CROSS_SIM_CALLING_ON_AUTO_DATA_SWITCH_EVENT,
+            newEnabled,
+        )
+        for (subId in subIds) {
+            ImsMmTelRepositoryImpl(application, subId).setCrossSimCallingEnabled(newEnabled)
+        }
+    }
+
+    companion object {
+        private const val TAG = "CrossSimCallingVM"
     }
 }
diff --git a/src/com/android/settings/network/telephony/wificalling/WifiCallingRepository.kt b/src/com/android/settings/network/telephony/wificalling/WifiCallingRepository.kt
index 6af0559..a6a47fa 100644
--- a/src/com/android/settings/network/telephony/wificalling/WifiCallingRepository.kt
+++ b/src/com/android/settings/network/telephony/wificalling/WifiCallingRepository.kt
@@ -29,9 +29,7 @@
 import com.android.settings.network.telephony.ims.ImsMmTelRepositoryImpl
 import com.android.settings.network.telephony.telephonyManager
 import com.android.settingslib.spa.framework.util.collectLatestWithLifecycle
-import kotlinx.coroutines.Dispatchers
 import kotlinx.coroutines.flow.Flow
-import kotlinx.coroutines.withContext
 
 interface IWifiCallingRepository {
     /** TODO: Move this to UI layer, when UI layer migrated to Kotlin. */
@@ -75,11 +73,4 @@
             tech = ImsRegistrationImplBase.REGISTRATION_TECH_IWLAN,
             transportType = AccessNetworkConstants.TRANSPORT_TYPE_WLAN,
         )
-
-    suspend fun isWifiCallingSupported(): Boolean = withContext(Dispatchers.Default) {
-        imsMmTelRepository.isSupported(
-            capability = MmTelFeature.MmTelCapabilities.CAPABILITY_TYPE_VOICE,
-            transportType = AccessNetworkConstants.TRANSPORT_TYPE_WLAN,
-        )
-    }
 }
diff --git a/src/com/android/settings/notification/modes/AbstractZenModeHeaderController.java b/src/com/android/settings/notification/modes/AbstractZenModeHeaderController.java
index af64231..1d1b07d 100644
--- a/src/com/android/settings/notification/modes/AbstractZenModeHeaderController.java
+++ b/src/com/android/settings/notification/modes/AbstractZenModeHeaderController.java
@@ -43,15 +43,18 @@
 abstract class AbstractZenModeHeaderController extends AbstractZenModePreferenceController {
 
     private final DashboardFragment mFragment;
+    private final ZenIconLoader mIconLoader;
     private EntityHeaderController mHeaderController;
     @Nullable private ZenIcon.Key mCurrentIconKey;
 
     AbstractZenModeHeaderController(
             @NonNull Context context,
+            @NonNull ZenIconLoader iconLoader,
             @NonNull String key,
             @NonNull DashboardFragment fragment) {
         super(context, key);
         mFragment = fragment;
+        mIconLoader = iconLoader;
     }
 
     @Override
@@ -90,7 +93,7 @@
         if (!Objects.equal(mCurrentIconKey, zenMode.getIconKey())) {
             mCurrentIconKey = zenMode.getIconKey();
             FutureUtil.whenDone(
-                    ZenIconLoader.getInstance().getIcon(mContext, zenMode),
+                    mIconLoader.getIcon(mContext, zenMode),
                     icon -> {
                         checkNotNull(mHeaderController)
                                 .setIcon(iconStylist.apply(icon.drawable()))
diff --git a/src/com/android/settings/notification/modes/ZenModeEditNameIconFragmentBase.java b/src/com/android/settings/notification/modes/ZenModeEditNameIconFragmentBase.java
index 96cbf91..6dd9076 100644
--- a/src/com/android/settings/notification/modes/ZenModeEditNameIconFragmentBase.java
+++ b/src/com/android/settings/notification/modes/ZenModeEditNameIconFragmentBase.java
@@ -30,6 +30,7 @@
 import com.android.settings.R;
 import com.android.settings.dashboard.DashboardFragment;
 import com.android.settingslib.core.AbstractPreferenceController;
+import com.android.settingslib.notification.modes.ZenIconLoader;
 import com.android.settingslib.notification.modes.ZenMode;
 import com.android.settingslib.notification.modes.ZenModesBackend;
 
@@ -102,7 +103,8 @@
     protected final List<AbstractPreferenceController> createPreferenceControllers(
             Context context) {
         return ImmutableList.of(
-                new ZenModeIconPickerIconPreferenceController(context, "chosen_icon", this),
+                new ZenModeIconPickerIconPreferenceController(context, ZenIconLoader.getInstance(),
+                        "chosen_icon", this),
                 new ZenModeEditNamePreferenceController(context, "name", this::setModeName),
                 new ZenModeIconPickerListPreferenceController(context, "icon_list",
                         this::setModeIcon),
diff --git a/src/com/android/settings/notification/modes/ZenModeFragment.java b/src/com/android/settings/notification/modes/ZenModeFragment.java
index 6889cac..8eef708 100644
--- a/src/com/android/settings/notification/modes/ZenModeFragment.java
+++ b/src/com/android/settings/notification/modes/ZenModeFragment.java
@@ -32,6 +32,7 @@
 
 import com.android.settings.R;
 import com.android.settingslib.core.AbstractPreferenceController;
+import com.android.settingslib.notification.modes.ZenIconLoader;
 import com.android.settingslib.notification.modes.ZenMode;
 
 import java.util.ArrayList;
@@ -54,7 +55,8 @@
     @Override
     protected List<AbstractPreferenceController> createPreferenceControllers(Context context) {
         List<AbstractPreferenceController> prefControllers = new ArrayList<>();
-        prefControllers.add(new ZenModeHeaderController(context, "header", this));
+        prefControllers.add(
+                new ZenModeHeaderController(context, ZenIconLoader.getInstance(), "header", this));
         prefControllers.add(new ZenModeBlurbPreferenceController(context, "mode_blurb"));
         prefControllers.add(
                 new ZenModeButtonPreferenceController(context, "activate", this, mBackend));
diff --git a/src/com/android/settings/notification/modes/ZenModeHeaderController.java b/src/com/android/settings/notification/modes/ZenModeHeaderController.java
index ae6eacc..e901b9f 100644
--- a/src/com/android/settings/notification/modes/ZenModeHeaderController.java
+++ b/src/com/android/settings/notification/modes/ZenModeHeaderController.java
@@ -23,15 +23,14 @@
 
 import com.android.settings.R;
 import com.android.settings.dashboard.DashboardFragment;
+import com.android.settingslib.notification.modes.ZenIconLoader;
 import com.android.settingslib.notification.modes.ZenMode;
 
 class ZenModeHeaderController extends AbstractZenModeHeaderController {
 
-    ZenModeHeaderController(
-            @NonNull  Context context,
-            @NonNull String key,
-            @NonNull DashboardFragment fragment) {
-        super(context, key, fragment);
+    ZenModeHeaderController(@NonNull Context context, @NonNull ZenIconLoader iconLoader,
+            @NonNull String key, @NonNull DashboardFragment fragment) {
+        super(context, iconLoader, key, fragment);
     }
 
     @Override
diff --git a/src/com/android/settings/notification/modes/ZenModeIconPickerIconPreferenceController.java b/src/com/android/settings/notification/modes/ZenModeIconPickerIconPreferenceController.java
index 6c8d41f..dc0be10 100644
--- a/src/com/android/settings/notification/modes/ZenModeIconPickerIconPreferenceController.java
+++ b/src/com/android/settings/notification/modes/ZenModeIconPickerIconPreferenceController.java
@@ -24,14 +24,16 @@
 
 import com.android.settings.R;
 import com.android.settings.dashboard.DashboardFragment;
+import com.android.settingslib.notification.modes.ZenIconLoader;
 import com.android.settingslib.notification.modes.ZenMode;
 
 /** Controller used for displaying the currently-chosen icon at the top of the icon picker. */
 class ZenModeIconPickerIconPreferenceController extends AbstractZenModeHeaderController {
 
-    ZenModeIconPickerIconPreferenceController(@NonNull Context context, @NonNull String key,
+    ZenModeIconPickerIconPreferenceController(@NonNull Context context,
+            @NonNull ZenIconLoader iconLoader, @NonNull String key,
             @NonNull DashboardFragment fragment) {
-        super(context, key, fragment);
+        super(context, iconLoader, key, fragment);
     }
 
     @Override
diff --git a/src/com/android/settings/notification/modes/ZenModeScheduleChooserDialog.java b/src/com/android/settings/notification/modes/ZenModeScheduleChooserDialog.java
index d129aad..370199a 100644
--- a/src/com/android/settings/notification/modes/ZenModeScheduleChooserDialog.java
+++ b/src/com/android/settings/notification/modes/ZenModeScheduleChooserDialog.java
@@ -81,6 +81,17 @@
         dialog.show(parent.getParentFragmentManager(), TAG);
     }
 
+    @Override
+    public void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+        if (mOptionListener == null) {
+            // Probably the dialog fragment was recreated after its activity being destroyed.
+            // It's pointless to re-show the dialog if we can't do anything when its options are
+            // selected, so we don't.
+            dismiss();
+        }
+    }
+
     @NonNull
     @Override
     public Dialog onCreateDialog(@Nullable Bundle savedInstanceState) {
diff --git a/src/com/android/settings/notification/modes/ZenModesListAddModeTypeChooserDialog.java b/src/com/android/settings/notification/modes/ZenModesListAddModeTypeChooserDialog.java
index e7905a8..0bf9c5b 100644
--- a/src/com/android/settings/notification/modes/ZenModesListAddModeTypeChooserDialog.java
+++ b/src/com/android/settings/notification/modes/ZenModesListAddModeTypeChooserDialog.java
@@ -70,6 +70,17 @@
         dialog.show(parent.getParentFragmentManager(), TAG);
     }
 
+    @Override
+    public void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+        if (mChooseModeTypeListener == null) {
+            // Probably the dialog fragment was recreated after its activity being destroyed.
+            // It's pointless to re-show the dialog if we can't do anything when its options are
+            // selected, so we don't.
+            dismiss();
+        }
+    }
+
     @NonNull
     @Override
     public Dialog onCreateDialog(@Nullable Bundle savedInstanceState) {
diff --git a/src/com/android/settings/notification/modes/ZenModesListFragment.java b/src/com/android/settings/notification/modes/ZenModesListFragment.java
index 588b320..37772b3 100644
--- a/src/com/android/settings/notification/modes/ZenModesListFragment.java
+++ b/src/com/android/settings/notification/modes/ZenModesListFragment.java
@@ -31,6 +31,7 @@
 import com.android.settings.notification.modes.ZenModesListAddModePreferenceController.OnAddModeListener;
 import com.android.settings.search.BaseSearchIndexProvider;
 import com.android.settingslib.core.AbstractPreferenceController;
+import com.android.settingslib.notification.modes.ZenIconLoader;
 import com.android.settingslib.notification.modes.ZenMode;
 import com.android.settingslib.notification.modes.ZenModesBackend;
 import com.android.settingslib.search.SearchIndexable;
@@ -56,7 +57,7 @@
     private static List<AbstractPreferenceController> buildPreferenceControllers(Context context,
             ZenModesBackend backend, OnAddModeListener onAddModeListener) {
         return ImmutableList.of(
-                new ZenModesListPreferenceController(context, backend),
+                new ZenModesListPreferenceController(context, backend, ZenIconLoader.getInstance()),
                 new ZenModesListAddModePreferenceController(context, onAddModeListener)
         );
     }
diff --git a/src/com/android/settings/notification/modes/ZenModesListItemPreference.java b/src/com/android/settings/notification/modes/ZenModesListItemPreference.java
index 0c31d8f..0909c6f 100644
--- a/src/com/android/settings/notification/modes/ZenModesListItemPreference.java
+++ b/src/com/android/settings/notification/modes/ZenModesListItemPreference.java
@@ -31,6 +31,8 @@
 
 import com.google.common.base.Strings;
 
+import java.util.concurrent.Executor;
+
 /**
  * Preference representing a single mode item on the modes aggregator page. Clicking on this
  * preference leads to an individual mode's configuration page.
@@ -38,18 +40,29 @@
 class ZenModesListItemPreference extends RestrictedPreference {
 
     private final Context mContext;
+    private final ZenIconLoader mIconLoader;
+    private final Executor mUiExecutor;
     private ZenMode mZenMode;
 
     private TextView mTitleView;
     private TextView mSummaryView;
 
-    ZenModesListItemPreference(Context context, ZenMode zenMode) {
+    ZenModesListItemPreference(Context context, ZenIconLoader iconLoader, ZenMode zenMode) {
+        this(context, iconLoader, context.getMainExecutor(), zenMode);
+    }
+
+    @VisibleForTesting
+    ZenModesListItemPreference(Context context, ZenIconLoader iconLoader, Executor uiExecutor,
+            ZenMode zenMode) {
         super(context);
         mContext = context;
+        mIconLoader = iconLoader;
+        mUiExecutor = uiExecutor;
         setZenMode(zenMode);
         setKey(zenMode.getId());
     }
 
+
     @Override
     public void onBindViewHolder(PreferenceViewHolder holder) {
         super.onBindViewHolder(holder);
@@ -93,12 +106,12 @@
 
         setIconSize(ICON_SIZE_SMALL);
         FutureUtil.whenDone(
-                ZenIconLoader.getInstance().getIcon(mContext, mZenMode),
+                mIconLoader.getIcon(mContext, mZenMode),
                 icon -> setIcon(
                         zenMode.isActive()
                                 ? IconUtil.applyAccentTint(mContext, icon.drawable())
                                 : IconUtil.applyNormalTint(mContext, icon.drawable())),
-                mContext.getMainExecutor());
+                mUiExecutor);
 
         updateTextColor(zenMode);
     }
diff --git a/src/com/android/settings/notification/modes/ZenModesListPreferenceController.java b/src/com/android/settings/notification/modes/ZenModesListPreferenceController.java
index 12b7278..5e36469 100644
--- a/src/com/android/settings/notification/modes/ZenModesListPreferenceController.java
+++ b/src/com/android/settings/notification/modes/ZenModesListPreferenceController.java
@@ -25,6 +25,7 @@
 
 import com.android.settings.R;
 import com.android.settings.core.BasePreferenceController;
+import com.android.settingslib.notification.modes.ZenIconLoader;
 import com.android.settingslib.notification.modes.ZenMode;
 import com.android.settingslib.notification.modes.ZenModesBackend;
 import com.android.settingslib.search.SearchIndexableRaw;
@@ -42,11 +43,14 @@
         implements BasePreferenceController.UiBlocker {
     protected static final String KEY = "zen_modes_list";
 
-    protected ZenModesBackend mBackend;
+    private final ZenModesBackend mBackend;
+    private final ZenIconLoader mIconLoader;
 
-    ZenModesListPreferenceController(Context context, @NonNull ZenModesBackend backend) {
+    ZenModesListPreferenceController(Context context, @NonNull ZenModesBackend backend, @NonNull
+            ZenIconLoader iconLoader) {
         super(context, KEY);
         mBackend = backend;
+        mIconLoader = iconLoader;
     }
 
     @Override
@@ -82,7 +86,7 @@
                 modePreference.setZenMode(mode);
             } else {
                 // new rule; create a new ZenRulePreference & add it to the preference category
-                modePreference = new ZenModesListItemPreference(mContext, mode);
+                modePreference = new ZenModesListItemPreference(mContext, mIconLoader, mode);
                 category.addPreference(modePreference);
             }
             modePreference.setOrder(modes.indexOf(mode));
diff --git a/src/com/android/settings/spa/network/SimsSection.kt b/src/com/android/settings/spa/network/SimsSection.kt
index 842656e..276d121 100644
--- a/src/com/android/settings/spa/network/SimsSection.kt
+++ b/src/com/android/settings/spa/network/SimsSection.kt
@@ -40,6 +40,7 @@
 import com.android.settings.network.telephony.MobileNetworkUtils
 import com.android.settings.network.telephony.SubscriptionActivationRepository
 import com.android.settings.network.telephony.SubscriptionRepository
+import com.android.settings.network.telephony.euicc.EuiccRepository
 import com.android.settings.network.telephony.phoneNumberFlow
 import com.android.settingslib.spa.widget.preference.PreferenceModel
 import com.android.settingslib.spa.widget.preference.SwitchPreferenceModel
@@ -120,13 +121,17 @@
 @Composable
 private fun AddSim() {
     val context = LocalContext.current
-    if (remember { MobileNetworkUtils.showEuiccSettings(context) }) {
+    val isShow by
+        remember { EuiccRepository(context).showEuiccSettingsFlow() }
+            .collectAsStateWithLifecycle(initialValue = false)
+    if (isShow) {
         RestrictedPreference(
-            model = object : PreferenceModel {
-                override val title = stringResource(id = R.string.mobile_network_list_add_more)
-                override val icon = @Composable { SettingsIcon(Icons.Outlined.Add) }
-                override val onClick = { startAddSimFlow(context) }
-            },
+            model =
+                object : PreferenceModel {
+                    override val title = stringResource(id = R.string.mobile_network_list_add_more)
+                    override val icon = @Composable { SettingsIcon(Icons.Outlined.Add) }
+                    override val onClick = { startAddSimFlow(context) }
+                },
             restrictions = Restrictions(keys = listOf(UserManager.DISALLOW_CONFIG_MOBILE_NETWORKS)),
         )
     }
diff --git a/src/com/android/settings/wifi/WifiSummaryUpdater.java b/src/com/android/settings/wifi/WifiSummaryUpdater.java
deleted file mode 100644
index 645d2ea..0000000
--- a/src/com/android/settings/wifi/WifiSummaryUpdater.java
+++ /dev/null
@@ -1,110 +0,0 @@
-/*
- * Copyright (C) 2017 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.settings.wifi;
-
-import android.content.BroadcastReceiver;
-import android.content.Context;
-import android.content.Intent;
-import android.content.IntentFilter;
-import android.net.ConnectivityManager;
-import android.net.NetworkScoreManager;
-import android.net.wifi.WifiInfo;
-import android.net.wifi.WifiManager;
-import android.text.TextUtils;
-
-import androidx.annotation.VisibleForTesting;
-
-import com.android.settings.R;
-import com.android.settings.widget.SummaryUpdater;
-import com.android.settingslib.wifi.WifiStatusTracker;
-
-/**
- * Helper class that listeners to wifi callback and notify client when there is update in
- * wifi summary info.
- */
-public class WifiSummaryUpdater extends SummaryUpdater {
-
-    private final WifiStatusTracker mWifiTracker;
-    private final BroadcastReceiver mReceiver;
-
-    private static final IntentFilter INTENT_FILTER;
-    static {
-        INTENT_FILTER = new IntentFilter();
-        INTENT_FILTER.addAction(WifiManager.WIFI_STATE_CHANGED_ACTION);
-        INTENT_FILTER.addAction(WifiManager.NETWORK_STATE_CHANGED_ACTION);
-        INTENT_FILTER.addAction(WifiManager.RSSI_CHANGED_ACTION);
-    }
-
-    public WifiSummaryUpdater(Context context, OnSummaryChangeListener listener) {
-        this(context, listener, null);
-    }
-
-    @VisibleForTesting
-    public WifiSummaryUpdater(Context context, OnSummaryChangeListener listener,
-        WifiStatusTracker wifiTracker) {
-        super(context, listener);
-        mWifiTracker = wifiTracker != null ? wifiTracker :
-                new WifiStatusTracker(context, context.getSystemService(WifiManager.class),
-                context.getSystemService(NetworkScoreManager.class),
-                context.getSystemService(ConnectivityManager.class),
-                        this::notifyChangeIfNeeded);
-        mReceiver = new BroadcastReceiver() {
-            @Override
-            public void onReceive(Context context, Intent intent) {
-                mWifiTracker.handleBroadcast(intent);
-                notifyChangeIfNeeded();
-            }
-        };
-    }
-
-    @Override
-    public void register(boolean register) {
-        if (register) {
-            mWifiTracker.fetchInitialState();
-            notifyChangeIfNeeded();
-            mContext.registerReceiver(mReceiver, INTENT_FILTER,
-                    Context.RECEIVER_EXPORTED_UNAUDITED);
-        } else {
-            mContext.unregisterReceiver(mReceiver);
-        }
-        mWifiTracker.setListening(register);
-    }
-
-    @Override
-    public String getSummary() {
-        if (!mWifiTracker.enabled) {
-            return mContext.getString(R.string.switch_off_text);
-        }
-        if (!mWifiTracker.connected) {
-            return mContext.getString(R.string.disconnected);
-        }
-        String ssid = WifiInfo.sanitizeSsid(mWifiTracker.ssid);
-        if (TextUtils.isEmpty(mWifiTracker.statusLabel)) {
-            return ssid;
-        }
-        return mContext.getResources().getString(
-                com.android.settingslib.R.string.preference_summary_default_combination,
-                ssid, mWifiTracker.statusLabel);
-    }
-
-    /**
-     * return true if Wi-Fi connected.
-     */
-    public boolean isWifiConnected() {
-        return mWifiTracker.connected;
-    }
-}
diff --git a/src/com/android/settings/wifi/details2/WifiDetailPreferenceController2.java b/src/com/android/settings/wifi/details2/WifiDetailPreferenceController2.java
index 9992cc0..927d2ee 100644
--- a/src/com/android/settings/wifi/details2/WifiDetailPreferenceController2.java
+++ b/src/com/android/settings/wifi/details2/WifiDetailPreferenceController2.java
@@ -556,6 +556,7 @@
             return mContext.getDrawable(getHotspotIconResource(deviceType));
         }
         if (mWifiEntry.getLevel() == WifiEntry.WIFI_LEVEL_UNREACHABLE) {
+            Log.w(TAG, "WiFi level is WIFI_LEVEL_UNREACHABLE(-1)");
             return mContext.getDrawable(R.drawable.empty_icon);
         }
         return mIconInjector.getIcon(wifiEntry.shouldShowXLevelIcon(), wifiEntry.getLevel());
diff --git a/src/com/android/settings/wifi/details2/WifiPrivacyPageProvider.kt b/src/com/android/settings/wifi/details2/WifiPrivacyPageProvider.kt
index 7744a73..8888f0d 100644
--- a/src/com/android/settings/wifi/details2/WifiPrivacyPageProvider.kt
+++ b/src/com/android/settings/wifi/details2/WifiPrivacyPageProvider.kt
@@ -55,6 +55,7 @@
 import com.android.wifitrackerlib.WifiEntry
 import java.time.Clock
 import java.time.ZoneOffset
+import java.util.Base64
 
 const val WIFI_ENTRY_KEY = "wifiEntryKey"
 
@@ -68,7 +69,8 @@
 
     @Composable
     override fun Page(arguments: Bundle?) {
-        val wifiEntryKey = arguments!!.getString(WIFI_ENTRY_KEY)
+        val wifiEntryKey =
+            String(Base64.getUrlDecoder().decode(arguments!!.getString(WIFI_ENTRY_KEY)))
         if (wifiEntryKey != null) {
             val context = LocalContext.current
             val lifecycle = LocalLifecycleOwner.current.lifecycle
@@ -81,7 +83,7 @@
 
     fun getRoute(
         wifiEntryKey: String,
-    ): String = "${name}/$wifiEntryKey"
+    ): String = "${name}/${Base64.getUrlEncoder().encodeToString(wifiEntryKey.toByteArray())}"
 }
 
 @Composable
diff --git a/tests/robotests/src/com/android/settings/applications/AppInfoWithHeaderTest.java b/tests/robotests/src/com/android/settings/applications/AppInfoWithHeaderTest.java
index cb121ea..0ed56c0 100644
--- a/tests/robotests/src/com/android/settings/applications/AppInfoWithHeaderTest.java
+++ b/tests/robotests/src/com/android/settings/applications/AppInfoWithHeaderTest.java
@@ -250,7 +250,7 @@
         }
 
         @Override
-        protected boolean hasInteractAcrossUsersPermission() {
+        protected boolean hasInteractAcrossUsersFullPermission() {
             return true;
         }
 
@@ -267,7 +267,7 @@
 
     private static final class TestFragmentWithoutPermission extends TestFragment {
         @Override
-        protected boolean hasInteractAcrossUsersPermission() {
+        protected boolean hasInteractAcrossUsersFullPermission() {
             return false;
         }
     }
diff --git a/tests/robotests/src/com/android/settings/connecteddevice/ConnectedDeviceDashboardFragmentTest.java b/tests/robotests/src/com/android/settings/connecteddevice/ConnectedDeviceDashboardFragmentTest.java
index 33292af..ecf6d00 100644
--- a/tests/robotests/src/com/android/settings/connecteddevice/ConnectedDeviceDashboardFragmentTest.java
+++ b/tests/robotests/src/com/android/settings/connecteddevice/ConnectedDeviceDashboardFragmentTest.java
@@ -36,7 +36,6 @@
 import com.android.settings.connecteddevice.fastpair.FastPairDeviceUpdater;
 import com.android.settings.core.BasePreferenceController;
 import com.android.settings.core.PreferenceControllerListHelper;
-import com.android.settings.flags.Flags;
 import com.android.settings.slices.SlicePreferenceController;
 import com.android.settings.testutils.FakeFeatureFactory;
 import com.android.settings.testutils.shadow.ShadowBluetoothAdapter;
@@ -94,7 +93,6 @@
 
         mContext = spy(RuntimeEnvironment.application);
         mFragment = new ConnectedDeviceDashboardFragment();
-        mSetFlagsRule.enableFlags(Flags.FLAG_ENABLE_SUBSEQUENT_PAIR_SETTINGS_INTEGRATION);
         mSetFlagsRule.enableFlags(com.android.settingslib.flags.Flags.FLAG_ENABLE_LE_AUDIO_SHARING);
         mFeatureFactory = FakeFeatureFactory.setupForTest();
         when(mFeatureFactory
diff --git a/tests/robotests/src/com/android/settings/connecteddevice/audiosharing/AudioSharingDialogHandlerTest.java b/tests/robotests/src/com/android/settings/connecteddevice/audiosharing/AudioSharingDialogHandlerTest.java
index 4933c43..ad6dd7f 100644
--- a/tests/robotests/src/com/android/settings/connecteddevice/audiosharing/AudioSharingDialogHandlerTest.java
+++ b/tests/robotests/src/com/android/settings/connecteddevice/audiosharing/AudioSharingDialogHandlerTest.java
@@ -39,6 +39,7 @@
 import android.bluetooth.BluetoothStatusCodes;
 import android.content.Context;
 import android.content.Intent;
+import android.media.AudioManager;
 import android.os.Bundle;
 import android.os.Looper;
 import android.platform.test.flag.junit.SetFlagsRule;
@@ -113,6 +114,7 @@
     @Mock private CachedBluetoothDeviceManager mCacheManager;
     @Mock private LocalBluetoothLeBroadcast mBroadcast;
     @Mock private LocalBluetoothLeBroadcastAssistant mAssistant;
+    @Mock private AudioManager mAudioManager;
     @Mock private CachedBluetoothDevice mCachedDevice1;
     @Mock private CachedBluetoothDevice mCachedDevice2;
     @Mock private CachedBluetoothDevice mCachedDevice3;
@@ -152,6 +154,8 @@
         when(mLocalBtManager.getProfileManager()).thenReturn(mLocalBtProfileManager);
         when(mLocalBtProfileManager.getLeAudioBroadcastProfile()).thenReturn(mBroadcast);
         when(mLocalBtProfileManager.getLeAudioBroadcastAssistantProfile()).thenReturn(mAssistant);
+        when(mContext.getSystemService(AudioManager.class)).thenReturn(mAudioManager);
+        when(mAudioManager.getMode()).thenReturn(AudioManager.MODE_NORMAL);
         List<Long> bisSyncState = new ArrayList<>();
         bisSyncState.add(1L);
         when(mState.getBisSyncState()).thenReturn(bisSyncState);
@@ -188,6 +192,18 @@
     }
 
     @Test
+    public void handleUserTriggeredDeviceConnected_inCall_setActive() {
+        when(mAudioManager.getMode()).thenReturn(AudioManager.MODE_IN_CALL);
+        setUpBroadcast(true);
+        ImmutableList<BluetoothDevice> deviceList = ImmutableList.of(mDevice1);
+        when(mAssistant.getAllConnectedDevices()).thenReturn(deviceList);
+        when(mAssistant.getAllSources(any())).thenReturn(ImmutableList.of());
+        mHandler.handleDeviceConnected(mCachedDevice1, /* userTriggered= */ true);
+        shadowOf(Looper.getMainLooper()).idle();
+        verify(mCachedDevice1).setActive();
+    }
+
+    @Test
     public void handleUserTriggeredNonLeaDeviceConnected_noSharing_setActive() {
         setUpBroadcast(false);
         ImmutableList<BluetoothDevice> deviceList = ImmutableList.of(mDevice2);
@@ -404,6 +420,18 @@
     }
 
     @Test
+    public void handleDeviceConnected_inCall_doNothing() {
+        when(mAudioManager.getMode()).thenReturn(AudioManager.MODE_IN_CALL);
+        setUpBroadcast(true);
+        when(mAssistant.getAllConnectedDevices()).thenReturn(ImmutableList.of());
+        mHandler.handleDeviceConnected(mCachedDevice2, /* userTriggered= */ false);
+        shadowOf(Looper.getMainLooper()).idle();
+        verify(mCachedDevice2, never()).setActive();
+        List<Fragment> childFragments = mParentFragment.getChildFragmentManager().getFragments();
+        assertThat(childFragments).isEmpty();
+    }
+
+    @Test
     public void handleNonLeaDeviceConnected_noSharing_doNothing() {
         setUpBroadcast(false);
         ImmutableList<BluetoothDevice> deviceList = ImmutableList.of(mDevice2);
diff --git a/tests/robotests/src/com/android/settings/connecteddevice/fastpair/FastPairDeviceGroupControllerTest.java b/tests/robotests/src/com/android/settings/connecteddevice/fastpair/FastPairDeviceGroupControllerTest.java
index 25e927b..2b140ea 100644
--- a/tests/robotests/src/com/android/settings/connecteddevice/fastpair/FastPairDeviceGroupControllerTest.java
+++ b/tests/robotests/src/com/android/settings/connecteddevice/fastpair/FastPairDeviceGroupControllerTest.java
@@ -33,8 +33,6 @@
 import android.content.Intent;
 import android.content.pm.PackageManager;
 import android.os.Looper;
-import android.platform.test.annotations.RequiresFlagsDisabled;
-import android.platform.test.annotations.RequiresFlagsEnabled;
 import android.platform.test.flag.junit.CheckFlagsRule;
 import android.platform.test.flag.junit.DeviceFlagsValueProvider;
 
@@ -45,7 +43,6 @@
 import androidx.preference.PreferenceScreen;
 
 import com.android.settings.dashboard.DashboardFragment;
-import com.android.settings.flags.Flags;
 import com.android.settings.testutils.FakeFeatureFactory;
 import com.android.settings.testutils.shadow.ShadowBluetoothAdapter;
 import com.android.settings.widget.GearPreference;
@@ -107,7 +104,6 @@
     }
 
     @Test
-    @RequiresFlagsEnabled(Flags.FLAG_ENABLE_SUBSEQUENT_PAIR_SETTINGS_INTEGRATION)
     public void onStart_flagOn_registerCallback() {
         // register the callback in onStart()
         mFastPairDeviceGroupController.onStart(mLifecycleOwner);
@@ -120,7 +116,6 @@
     }
 
     @Test
-    @RequiresFlagsEnabled(Flags.FLAG_ENABLE_SUBSEQUENT_PAIR_SETTINGS_INTEGRATION)
     public void onStop_flagOn_unregisterCallback() {
         // register broadcast first
         mContext.registerReceiver(
@@ -133,51 +128,6 @@
     }
 
     @Test
-    @RequiresFlagsDisabled(Flags.FLAG_ENABLE_SUBSEQUENT_PAIR_SETTINGS_INTEGRATION)
-    public void onStart_flagOff_registerCallback() {
-        // register the callback in onStart()
-        mFastPairDeviceGroupController.onStart(mLifecycleOwner);
-        assertThat(mFastPairDeviceUpdater).isNull();
-        verify(mContext)
-                .registerReceiver(
-                        mFastPairDeviceGroupController.mReceiver,
-                        mFastPairDeviceGroupController.mIntentFilter,
-                        Context.RECEIVER_EXPORTED);
-    }
-
-    @Test
-    @RequiresFlagsDisabled(Flags.FLAG_ENABLE_SUBSEQUENT_PAIR_SETTINGS_INTEGRATION)
-    public void onStop_flagOff_unregisterCallback() {
-        // register broadcast first
-        mContext.registerReceiver(
-                mFastPairDeviceGroupController.mReceiver, null, Context.RECEIVER_EXPORTED);
-
-        // unregister the callback in onStop()
-        mFastPairDeviceGroupController.onStop(mLifecycleOwner);
-        assertThat(mFastPairDeviceUpdater).isNull();
-        verify(mContext).unregisterReceiver(mFastPairDeviceGroupController.mReceiver);
-    }
-
-    @Test
-    @RequiresFlagsDisabled(Flags.FLAG_ENABLE_SUBSEQUENT_PAIR_SETTINGS_INTEGRATION)
-    public void getAvailabilityStatus_noFastPairFeature_returnUnSupported() {
-        doReturn(true).when(mPackageManager).hasSystemFeature(PackageManager.FEATURE_BLUETOOTH);
-
-        assertThat(mFastPairDeviceGroupController.getAvailabilityStatus())
-                .isEqualTo(UNSUPPORTED_ON_DEVICE);
-    }
-
-    @Test
-    @RequiresFlagsDisabled(Flags.FLAG_ENABLE_SUBSEQUENT_PAIR_SETTINGS_INTEGRATION)
-    public void getAvailabilityStatus_noBluetoothFastPairFeature_returnUnSupported() {
-        doReturn(false).when(mPackageManager).hasSystemFeature(PackageManager.FEATURE_BLUETOOTH);
-
-        assertThat(mFastPairDeviceGroupController.getAvailabilityStatus())
-                .isEqualTo(UNSUPPORTED_ON_DEVICE);
-    }
-
-    @Test
-    @RequiresFlagsEnabled(Flags.FLAG_ENABLE_SUBSEQUENT_PAIR_SETTINGS_INTEGRATION)
     public void getAvailabilityStatus_noBluetoothFeature_returnUnSupported() {
         doReturn(false).when(mPackageManager).hasSystemFeature(PackageManager.FEATURE_BLUETOOTH);
 
@@ -186,7 +136,6 @@
     }
 
     @Test
-    @RequiresFlagsEnabled(Flags.FLAG_ENABLE_SUBSEQUENT_PAIR_SETTINGS_INTEGRATION)
     public void getAvailabilityStatus_withBluetoothFastPairFeature_returnSupported() {
         doReturn(true).when(mPackageManager).hasSystemFeature(PackageManager.FEATURE_BLUETOOTH);
 
@@ -231,14 +180,6 @@
     }
 
     @Test
-    @RequiresFlagsDisabled(Flags.FLAG_ENABLE_SUBSEQUENT_PAIR_SETTINGS_INTEGRATION)
-    public void displayPreference_notAvailable_doNothing() {
-        mFastPairDeviceGroupController.displayPreference(mScreen);
-        assertThat(mPreferenceGroup.isVisible()).isFalse();
-    }
-
-    @Test
-    @RequiresFlagsEnabled(Flags.FLAG_ENABLE_SUBSEQUENT_PAIR_SETTINGS_INTEGRATION)
     public void displayPreference_isAvailable_fetchFastPairDevices() {
         doReturn(true).when(mPackageManager).hasSystemFeature(PackageManager.FEATURE_BLUETOOTH);
 
diff --git a/tests/robotests/src/com/android/settings/connecteddevice/fastpair/FastPairDevicePreferenceControllerTest.java b/tests/robotests/src/com/android/settings/connecteddevice/fastpair/FastPairDevicePreferenceControllerTest.java
index be2ed56..8a84e23 100644
--- a/tests/robotests/src/com/android/settings/connecteddevice/fastpair/FastPairDevicePreferenceControllerTest.java
+++ b/tests/robotests/src/com/android/settings/connecteddevice/fastpair/FastPairDevicePreferenceControllerTest.java
@@ -32,8 +32,6 @@
 import android.content.Intent;
 import android.content.pm.PackageManager;
 import android.os.Looper;
-import android.platform.test.annotations.RequiresFlagsDisabled;
-import android.platform.test.annotations.RequiresFlagsEnabled;
 import android.platform.test.flag.junit.CheckFlagsRule;
 import android.platform.test.flag.junit.DeviceFlagsValueProvider;
 
@@ -44,7 +42,6 @@
 import androidx.preference.PreferenceManager;
 
 import com.android.settings.dashboard.DashboardFragment;
-import com.android.settings.flags.Flags;
 import com.android.settings.testutils.FakeFeatureFactory;
 import com.android.settings.testutils.shadow.ShadowBluetoothAdapter;
 import com.android.settings.widget.GearPreference;
@@ -108,7 +105,6 @@
     }
 
     @Test
-    @RequiresFlagsEnabled(Flags.FLAG_ENABLE_SUBSEQUENT_PAIR_SETTINGS_INTEGRATION)
     public void onStart_flagOn_registerCallback() {
         // register the callback in onStart()
         mFastPairDevicePrefController.onStart(mLifecycleOwner);
@@ -121,20 +117,6 @@
     }
 
     @Test
-    @RequiresFlagsDisabled(Flags.FLAG_ENABLE_SUBSEQUENT_PAIR_SETTINGS_INTEGRATION)
-    public void onStart_flagOff_registerCallback() {
-        // register the callback in onStart()
-        mFastPairDevicePrefController.onStart(mLifecycleOwner);
-        assertThat(mFastPairDeviceUpdater).isNull();
-        verify(mContext)
-                .registerReceiver(
-                        mFastPairDevicePrefController.mReceiver,
-                        mFastPairDevicePrefController.mIntentFilter,
-                        Context.RECEIVER_EXPORTED_UNAUDITED);
-    }
-
-    @Test
-    @RequiresFlagsEnabled(Flags.FLAG_ENABLE_SUBSEQUENT_PAIR_SETTINGS_INTEGRATION)
     public void onStop_flagOn_unregisterCallback() {
         // register broadcast first
         mContext.registerReceiver(
@@ -147,20 +129,6 @@
     }
 
     @Test
-    @RequiresFlagsDisabled(Flags.FLAG_ENABLE_SUBSEQUENT_PAIR_SETTINGS_INTEGRATION)
-    public void onStop_flagOff_unregisterCallback() {
-        // register broadcast first
-        mContext.registerReceiver(
-                mFastPairDevicePrefController.mReceiver, null, Context.RECEIVER_EXPORTED_UNAUDITED);
-
-        // unregister the callback in onStop()
-        mFastPairDevicePrefController.onStop(mLifecycleOwner);
-        assertThat(mFastPairDeviceUpdater).isNull();
-        verify(mContext).unregisterReceiver(mFastPairDevicePrefController.mReceiver);
-    }
-
-    @Test
-    @RequiresFlagsEnabled(Flags.FLAG_ENABLE_SUBSEQUENT_PAIR_SETTINGS_INTEGRATION)
     public void getAvailabilityStatus_noBluetoothFeature_returnUnsupported() {
         doReturn(false).when(mPackageManager).hasSystemFeature(PackageManager.FEATURE_BLUETOOTH);
 
@@ -169,25 +137,6 @@
     }
 
     @Test
-    @RequiresFlagsDisabled(Flags.FLAG_ENABLE_SUBSEQUENT_PAIR_SETTINGS_INTEGRATION)
-    public void getAvailabilityStatus_noFastPairFeature_returnUnsupported() {
-        doReturn(true).when(mPackageManager).hasSystemFeature(PackageManager.FEATURE_BLUETOOTH);
-
-        assertThat(mFastPairDevicePrefController.getAvailabilityStatus())
-                .isEqualTo(UNSUPPORTED_ON_DEVICE);
-    }
-
-    @Test
-    @RequiresFlagsDisabled(Flags.FLAG_ENABLE_SUBSEQUENT_PAIR_SETTINGS_INTEGRATION)
-    public void getAvailabilityStatus_noBluetoothFastPairFeature_returnUnsupported() {
-        doReturn(false).when(mPackageManager).hasSystemFeature(PackageManager.FEATURE_BLUETOOTH);
-
-        assertThat(mFastPairDevicePrefController.getAvailabilityStatus())
-                .isEqualTo(UNSUPPORTED_ON_DEVICE);
-    }
-
-    @Test
-    @RequiresFlagsEnabled(Flags.FLAG_ENABLE_SUBSEQUENT_PAIR_SETTINGS_INTEGRATION)
     public void getAvailabilityStatus_bothBluetoothFastPairFeature_returnSupported() {
         doReturn(true).when(mPackageManager).hasSystemFeature(PackageManager.FEATURE_BLUETOOTH);
 
diff --git a/tests/robotests/src/com/android/settings/fuelgauge/batteryusage/PeriodicJobReceiverTest.java b/tests/robotests/src/com/android/settings/fuelgauge/batteryusage/PeriodicJobReceiverTest.java
index ea3c04c..8212166 100644
--- a/tests/robotests/src/com/android/settings/fuelgauge/batteryusage/PeriodicJobReceiverTest.java
+++ b/tests/robotests/src/com/android/settings/fuelgauge/batteryusage/PeriodicJobReceiverTest.java
@@ -108,7 +108,7 @@
 
         mReceiver.onReceive(mContext, JOB_UPDATE_INTENT);
 
-        TimeUnit.MILLISECONDS.sleep(100);
+        TimeUnit.MILLISECONDS.sleep(1000);
         assertThat(mDao.getAllAfter(0)).hasSize(1);
     }
 
@@ -119,7 +119,7 @@
 
         mReceiver.onReceive(mContext, JOB_UPDATE_INTENT);
 
-        TimeUnit.MILLISECONDS.sleep(100);
+        TimeUnit.MILLISECONDS.sleep(1000);
         assertThat(mDao.getAllAfter(0)).hasSize(3);
     }
 
diff --git a/tests/robotests/src/com/android/settings/network/ims/MockVolteQueryImsState.java b/tests/robotests/src/com/android/settings/network/ims/MockVolteQueryImsState.java
deleted file mode 100644
index 515ab5b..0000000
--- a/tests/robotests/src/com/android/settings/network/ims/MockVolteQueryImsState.java
+++ /dev/null
@@ -1,105 +0,0 @@
-/*
- * Copyright (C) 2020 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.ims;
-
-import android.content.Context;
-import android.telephony.ims.ImsException;
-
-/**
- * Controller class for mock VoLte status
- */
-public class MockVolteQueryImsState extends VolteQueryImsState {
-
-    private Boolean mIsTtyOnVolteEnabled;
-    private Boolean mIsSupported;
-    private Boolean mIsProvisionedOnDevice;
-    private Boolean mIsServiceStateReady;
-    private Boolean mIsEnabledByUser;
-
-    /**
-     * Constructor
-     *
-     * @param context {@link Context}
-     * @param subId subscription's id
-     */
-    public MockVolteQueryImsState(Context context, int subId) {
-        super(context, subId);
-    }
-
-    public void setIsTtyOnVolteEnabled(boolean enabled) {
-        mIsTtyOnVolteEnabled = enabled;
-    }
-
-    @Override
-    boolean isTtyOnVolteEnabled(int subId) {
-        if (mIsTtyOnVolteEnabled != null) {
-            return mIsTtyOnVolteEnabled;
-        }
-        return super.isTtyOnVolteEnabled(subId);
-    }
-
-    public void setEnabledByPlatform(boolean isSupported) {
-        mIsSupported = isSupported;
-    }
-
-    @Override
-    boolean isEnabledByPlatform(int subId) throws InterruptedException, ImsException,
-            IllegalArgumentException {
-        if (mIsSupported != null) {
-            return mIsSupported;
-        }
-        return super.isEnabledByPlatform(subId);
-    }
-
-    public void setIsProvisionedOnDevice(boolean isProvisioned) {
-        mIsProvisionedOnDevice = isProvisioned;
-    }
-
-    @Override
-    boolean isProvisionedOnDevice(int subId) {
-        if (mIsProvisionedOnDevice != null) {
-            return mIsProvisionedOnDevice;
-        }
-        return super.isProvisionedOnDevice(subId);
-    }
-
-    public void setServiceStateReady(boolean isReady) {
-        mIsServiceStateReady = isReady;
-    }
-
-    @Override
-    boolean isServiceStateReady(int subId) throws InterruptedException, ImsException,
-            IllegalArgumentException {
-        if (mIsServiceStateReady != null) {
-            return mIsServiceStateReady;
-        }
-        return super.isServiceStateReady(subId);
-    }
-
-    public void setIsEnabledByUser(boolean enabled) {
-        mIsEnabledByUser = enabled;
-    }
-
-    @Override
-    boolean isEnabledByUser(int subId) {
-        if (mIsEnabledByUser != null) {
-            return mIsEnabledByUser;
-        }
-        return super.isEnabledByUser(subId);
-    }
-
-}
diff --git a/tests/robotests/src/com/android/settings/network/ims/MockVtQueryImsState.java b/tests/robotests/src/com/android/settings/network/ims/MockVtQueryImsState.java
deleted file mode 100644
index 0949f1c..0000000
--- a/tests/robotests/src/com/android/settings/network/ims/MockVtQueryImsState.java
+++ /dev/null
@@ -1,104 +0,0 @@
-/*
- * Copyright (C) 2020 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.ims;
-
-import android.content.Context;
-import android.telephony.ims.ImsException;
-
-/**
- * Controller class for mock VT status
- */
-public class MockVtQueryImsState extends VtQueryImsState {
-
-    private Boolean mIsTtyOnVolteEnabled;
-    private Boolean mIsEnabledOnPlatform;
-    private Boolean mIsProvisionedOnDevice;
-    private Boolean mIsEnabledByUser;
-    private Boolean mIsServiceStateReady;
-
-    /**
-     * Constructor
-     *
-     * @param context {@link Context}
-     * @param subId subscription's id
-     */
-    public MockVtQueryImsState(Context context, int subId) {
-        super(context, subId);
-    }
-
-    public void setIsTtyOnVolteEnabled(boolean enabled) {
-        mIsTtyOnVolteEnabled = enabled;
-    }
-
-    @Override
-    boolean isTtyOnVolteEnabled(int subId) {
-        if (mIsTtyOnVolteEnabled != null) {
-            return mIsTtyOnVolteEnabled;
-        }
-        return super.isTtyOnVolteEnabled(subId);
-    }
-
-    public void setIsEnabledByPlatform(boolean isEnabled) {
-        mIsEnabledOnPlatform = isEnabled;
-    }
-
-    @Override
-    boolean isEnabledByPlatform(int subId) throws InterruptedException, ImsException,
-            IllegalArgumentException {
-        if (mIsEnabledOnPlatform != null) {
-            return mIsEnabledOnPlatform;
-        }
-        return super.isEnabledByPlatform(subId);
-    }
-
-    public void setIsProvisionedOnDevice(boolean isProvisioned) {
-        mIsProvisionedOnDevice = isProvisioned;
-    }
-
-    @Override
-    boolean isProvisionedOnDevice(int subId) {
-        if (mIsProvisionedOnDevice != null) {
-            return mIsProvisionedOnDevice;
-        }
-        return super.isProvisionedOnDevice(subId);
-    }
-
-    public void setServiceStateReady(boolean isReady) {
-        mIsServiceStateReady = isReady;
-    }
-
-    @Override
-    boolean isServiceStateReady(int subId) throws InterruptedException, ImsException,
-            IllegalArgumentException {
-        if (mIsServiceStateReady != null) {
-            return mIsServiceStateReady;
-        }
-        return super.isServiceStateReady(subId);
-    }
-
-    public void setIsEnabledByUser(boolean enabled) {
-        mIsEnabledByUser = enabled;
-    }
-
-    @Override
-    boolean isEnabledByUser(int subId) {
-        if (mIsEnabledByUser != null) {
-            return mIsEnabledByUser;
-        }
-        return super.isEnabledByUser(subId);
-    }
-}
diff --git a/tests/robotests/src/com/android/settings/network/telephony/VideoCallingPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/network/telephony/VideoCallingPreferenceControllerTest.java
deleted file mode 100644
index da8958d..0000000
--- a/tests/robotests/src/com/android/settings/network/telephony/VideoCallingPreferenceControllerTest.java
+++ /dev/null
@@ -1,160 +0,0 @@
-/*
- * Copyright (C) 2018 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 com.google.common.truth.Truth.assertThat;
-
-import static org.mockito.ArgumentMatchers.anyInt;
-import static org.mockito.Mockito.doReturn;
-import static org.mockito.Mockito.spy;
-
-import android.content.Context;
-import android.os.PersistableBundle;
-import android.telephony.CarrierConfigManager;
-import android.telephony.TelephonyManager;
-import android.telephony.ims.ProvisioningManager;
-
-import androidx.preference.PreferenceScreen;
-import androidx.preference.SwitchPreference;
-
-import com.android.settings.network.CarrierConfigCache;
-import com.android.settings.network.ims.MockVolteQueryImsState;
-import com.android.settings.network.ims.MockVtQueryImsState;
-
-import org.junit.Before;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.mockito.Mock;
-import org.mockito.MockitoAnnotations;
-import org.robolectric.RobolectricTestRunner;
-import org.robolectric.RuntimeEnvironment;
-
-@RunWith(RobolectricTestRunner.class)
-public class VideoCallingPreferenceControllerTest {
-    private static final int SUB_ID = 2;
-
-    @Mock
-    private TelephonyManager mTelephonyManager;
-    @Mock
-    private ProvisioningManager mProvisioningManager;
-    @Mock
-    private CarrierConfigCache mCarrierConfigCache;
-    @Mock
-    private PreferenceScreen mPreferenceScreen;
-
-    private MockVtQueryImsState mQueryImsState;
-    private MockVolteQueryImsState mQueryVoLteState;
-
-    private VideoCallingPreferenceController mController;
-    private PersistableBundle mCarrierConfig;
-    private SwitchPreference mPreference;
-    private Context mContext;
-
-    @Before
-    public void setUp() throws Exception {
-        MockitoAnnotations.initMocks(this);
-
-        mContext = spy(RuntimeEnvironment.application);
-        doReturn(mTelephonyManager).when(mContext).getSystemService(TelephonyManager.class);
-        CarrierConfigCache.setTestInstance(mContext, mCarrierConfigCache);
-        doReturn(mTelephonyManager).when(mTelephonyManager).createForSubscriptionId(SUB_ID);
-
-        mCarrierConfig = new PersistableBundle();
-        mCarrierConfig.putBoolean(
-                CarrierConfigManager.KEY_IGNORE_DATA_ENABLED_CHANGED_FOR_VIDEO_CALLS, true);
-        doReturn(mCarrierConfig).when(mCarrierConfigCache).getConfigForSubId(SUB_ID);
-
-        mQueryImsState = new MockVtQueryImsState(mContext, SUB_ID);
-        mQueryImsState.setIsEnabledByUser(true);
-
-        mQueryVoLteState = new MockVolteQueryImsState(mContext, SUB_ID);
-        mQueryVoLteState.setIsEnabledByUser(true);
-
-        mPreference = new SwitchPreference(mContext);
-        mController = spy(new VideoCallingPreferenceController(mContext, "wifi_calling"));
-        mController.init(
-                SUB_ID, new CallingPreferenceCategoryController(mContext, "calling_category"));
-        doReturn(mQueryImsState).when(mController).queryImsState(anyInt());
-        doReturn(mQueryVoLteState).when(mController).queryVoLteState(anyInt());
-        doReturn(true).when(mController).isImsSupported();
-        mPreference.setKey(mController.getPreferenceKey());
-
-        mQueryImsState.setIsEnabledByPlatform(true);
-        mQueryImsState.setIsProvisionedOnDevice(true);
-        mQueryImsState.setServiceStateReady(true);
-        doReturn(true).when(mTelephonyManager).isDataEnabled();
-
-        mController.mCallState = TelephonyManager.CALL_STATE_IDLE;
-    }
-
-    @Test
-    public void isVideoCallEnabled_allFlagsOn_returnTrue() {
-        assertThat(mController.isVideoCallEnabled(SUB_ID)).isTrue();
-    }
-
-    @Test
-    public void isVideoCallEnabled_disabledByPlatform_returnFalse() {
-        mQueryImsState.setIsProvisionedOnDevice(false);
-        mQueryImsState.setIsEnabledByPlatform(false);
-
-        assertThat(mController.isVideoCallEnabled(SUB_ID)).isFalse();
-    }
-
-    @Test
-    public void isVideoCallEnabled_dataDisabled_returnFalse() {
-        mCarrierConfig.putBoolean(
-                CarrierConfigManager.KEY_IGNORE_DATA_ENABLED_CHANGED_FOR_VIDEO_CALLS, false);
-        doReturn(false).when(mTelephonyManager).isDataEnabled();
-
-        assertThat(mController.isVideoCallEnabled(SUB_ID)).isFalse();
-    }
-
-    @Test
-    public void updateState_4gLteOff_disabled() {
-        mQueryImsState.setIsEnabledByUser(false);
-        mQueryVoLteState.setIsEnabledByUser(false);
-
-        mController.updateState(mPreference);
-
-        assertThat(mPreference.isEnabled()).isFalse();
-        assertThat(mPreference.isChecked()).isFalse();
-    }
-
-    @Test
-    public void updateState_4gLteOnWithoutCall_checked() {
-        mQueryImsState.setIsEnabledByUser(true);
-        mQueryVoLteState.setIsEnabledByUser(true);
-        mQueryImsState.setIsTtyOnVolteEnabled(true);
-        mController.mCallState = TelephonyManager.CALL_STATE_IDLE;
-
-        mController.updateState(mPreference);
-
-        assertThat(mPreference.isEnabled()).isTrue();
-        assertThat(mPreference.isChecked()).isTrue();
-    }
-
-
-    @Test
-    public void displayPreference_notAvailable_setPreferenceInvisible() {
-        mQueryImsState.setIsEnabledByPlatform(false);
-
-        mController.displayPreference(mPreferenceScreen);
-
-        assertThat(mPreferenceScreen.isVisible()).isFalse();
-    }
-
-}
diff --git a/tests/robotests/src/com/android/settings/notification/modes/ZenModesListItemPreferenceTest.java b/tests/robotests/src/com/android/settings/notification/modes/ZenModesListItemPreferenceTest.java
index f5d5160..3722e41 100644
--- a/tests/robotests/src/com/android/settings/notification/modes/ZenModesListItemPreferenceTest.java
+++ b/tests/robotests/src/com/android/settings/notification/modes/ZenModesListItemPreferenceTest.java
@@ -36,7 +36,6 @@
 import org.mockito.MockitoAnnotations;
 import org.robolectric.RobolectricTestRunner;
 import org.robolectric.RuntimeEnvironment;
-import org.robolectric.shadows.ShadowLooper;
 
 @RunWith(RobolectricTestRunner.class)
 @EnableFlags(Flags.FLAG_MODES_UI)
@@ -45,18 +44,18 @@
     public final SetFlagsRule mSetFlagsRule = new SetFlagsRule();
 
     private Context mContext;
+    private final ZenIconLoader mIconLoader = new ZenIconLoader(
+            MoreExecutors.newDirectExecutorService());
 
     @Before
     public void setup() {
         MockitoAnnotations.initMocks(this);
         mContext = RuntimeEnvironment.application;
-        ZenIconLoader.setInstance(new ZenIconLoader(MoreExecutors.newDirectExecutorService()));
     }
 
     @Test
     public void constructor_setsMode() {
-        ZenModesListItemPreference preference = new ZenModesListItemPreference(mContext,
-                TestModeBuilder.EXAMPLE);
+        ZenModesListItemPreference preference = newPreference(TestModeBuilder.EXAMPLE);
 
         assertThat(preference.getKey()).isEqualTo(TestModeBuilder.EXAMPLE.getId());
         assertThat(preference.getZenMode()).isEqualTo(TestModeBuilder.EXAMPLE);
@@ -70,8 +69,7 @@
                 .setEnabled(true)
                 .build();
 
-        ZenModesListItemPreference preference = new ZenModesListItemPreference(mContext, mode);
-        ShadowLooper.idleMainLooper(); // To load icon.
+        ZenModesListItemPreference preference = newPreference(mode);
 
         assertThat(preference.getTitle()).isEqualTo("Enabled mode");
         assertThat(preference.getSummary()).isEqualTo("When the thrush knocks");
@@ -87,8 +85,7 @@
                 .setActive(true)
                 .build();
 
-        ZenModesListItemPreference preference = new ZenModesListItemPreference(mContext, mode);
-        ShadowLooper.idleMainLooper();
+        ZenModesListItemPreference preference = newPreference(mode);
 
         assertThat(preference.getTitle()).isEqualTo("Active mode");
         assertThat(preference.getSummary()).isEqualTo("ON • When Birnam forest comes to Dunsinane");
@@ -103,8 +100,7 @@
                 .setEnabled(false, /* byUser= */ false)
                 .build();
 
-        ZenModesListItemPreference preference = new ZenModesListItemPreference(mContext, mode);
-        ShadowLooper.idleMainLooper();
+        ZenModesListItemPreference preference = newPreference(mode);
 
         assertThat(preference.getTitle()).isEqualTo("Mode disabled by app");
         assertThat(preference.getSummary()).isEqualTo("Not set");
@@ -119,11 +115,15 @@
                 .setEnabled(false, /* byUser= */ true)
                 .build();
 
-        ZenModesListItemPreference preference = new ZenModesListItemPreference(mContext, mode);
-        ShadowLooper.idleMainLooper();
+        ZenModesListItemPreference preference = newPreference(mode);
 
         assertThat(preference.getTitle()).isEqualTo("Mode disabled by user");
         assertThat(preference.getSummary()).isEqualTo("Disabled");
         assertThat(preference.getIcon()).isNotNull();
     }
+
+    private ZenModesListItemPreference newPreference(ZenMode zenMode) {
+        return new ZenModesListItemPreference(mContext, mIconLoader, MoreExecutors.directExecutor(),
+                zenMode);
+    }
 }
diff --git a/tests/robotests/src/com/android/settings/notification/modes/ZenModesListPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/notification/modes/ZenModesListPreferenceControllerTest.java
index 4fa8b8a..69568ce 100644
--- a/tests/robotests/src/com/android/settings/notification/modes/ZenModesListPreferenceControllerTest.java
+++ b/tests/robotests/src/com/android/settings/notification/modes/ZenModesListPreferenceControllerTest.java
@@ -40,11 +40,13 @@
 import androidx.preference.PreferenceScreen;
 
 import com.android.settingslib.notification.modes.TestModeBuilder;
+import com.android.settingslib.notification.modes.ZenIconLoader;
 import com.android.settingslib.notification.modes.ZenMode;
 import com.android.settingslib.notification.modes.ZenModesBackend;
 import com.android.settingslib.search.SearchIndexableRaw;
 
 import com.google.common.collect.ImmutableList;
+import com.google.common.util.concurrent.MoreExecutors;
 
 import org.junit.Before;
 import org.junit.Rule;
@@ -95,7 +97,8 @@
         PreferenceScreen preferenceScreen = preferenceManager.createPreferenceScreen(mContext);
         preferenceScreen.addPreference(mPreference);
 
-        mPrefController = new ZenModesListPreferenceController(mContext, mBackend);
+        mPrefController = new ZenModesListPreferenceController(mContext, mBackend,
+                new ZenIconLoader(MoreExecutors.newDirectExecutorService()));
     }
 
     @Test
diff --git a/tests/robotests/src/com/android/settings/wifi/WifiSummaryUpdaterTest.java b/tests/robotests/src/com/android/settings/wifi/WifiSummaryUpdaterTest.java
deleted file mode 100644
index 99040db..0000000
--- a/tests/robotests/src/com/android/settings/wifi/WifiSummaryUpdaterTest.java
+++ /dev/null
@@ -1,152 +0,0 @@
-/*
- * Copyright (C) 2017 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.settings.wifi;
-
-import static com.google.common.truth.Truth.assertThat;
-
-import static org.mockito.ArgumentMatchers.any;
-import static org.mockito.ArgumentMatchers.anyInt;
-import static org.mockito.ArgumentMatchers.anyString;
-import static org.mockito.Mockito.doNothing;
-import static org.mockito.Mockito.doReturn;
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.spy;
-import static org.mockito.Mockito.verify;
-
-import android.content.BroadcastReceiver;
-import android.content.Context;
-import android.content.Intent;
-import android.content.IntentFilter;
-import android.net.wifi.WifiManager;
-
-import com.android.settings.R;
-import com.android.settings.widget.SummaryUpdater.OnSummaryChangeListener;
-import com.android.settingslib.wifi.WifiStatusTracker;
-
-import org.junit.Before;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.mockito.Mock;
-import org.mockito.MockitoAnnotations;
-import org.robolectric.RobolectricTestRunner;
-import org.robolectric.RuntimeEnvironment;
-
-@RunWith(RobolectricTestRunner.class)
-public class WifiSummaryUpdaterTest {
-    @Mock private WifiStatusTracker mWifiTracker;
-    @Mock private SummaryListener mListener;
-
-    private Context mContext;
-    private WifiSummaryUpdater mSummaryUpdater;
-
-    @Before
-    public void setUp() {
-        MockitoAnnotations.initMocks(this);
-        mContext = spy(RuntimeEnvironment.application.getApplicationContext());
-        doReturn(mock(Intent.class)).when(mContext).registerReceiver(any(), any(), anyInt());
-        doNothing().when(mContext).unregisterReceiver(any(BroadcastReceiver.class));
-
-        mSummaryUpdater = new WifiSummaryUpdater(mContext, mListener, mWifiTracker);
-    }
-
-    @Test
-    public void register_true_shouldRegisterListenerAndTracker() {
-        mSummaryUpdater.register(true);
-
-        verify(mContext).registerReceiver(any(BroadcastReceiver.class), any(IntentFilter.class),
-                anyInt());
-        verify(mWifiTracker).setListening(true);
-    }
-
-    @Test
-    public void register_true_shouldFetchInitialStateAndSendSummaryChange() {
-        mSummaryUpdater.register(true);
-
-        verify(mWifiTracker).fetchInitialState();
-        verify(mListener).onSummaryChanged(anyString());
-    }
-
-    @Test
-    public void register_false_shouldUnregisterListenerAndTracker() {
-        mSummaryUpdater.register(true);
-        mSummaryUpdater.register(false);
-
-        verify(mContext).unregisterReceiver(any(BroadcastReceiver.class));
-        verify(mWifiTracker).setListening(false);
-    }
-
-    @Test
-    public void onReceive_networkStateChanged_shouldSendSummaryChange() {
-        mSummaryUpdater.register(true);
-        mContext.sendBroadcast(new Intent(WifiManager.NETWORK_STATE_CHANGED_ACTION));
-
-        verify(mListener).onSummaryChanged(anyString());
-    }
-
-    @Test
-    public void onReceive_rssiChanged_shouldSendSummaryChange() {
-        mSummaryUpdater.register(true);
-        mContext.sendBroadcast(new Intent(WifiManager.RSSI_CHANGED_ACTION));
-
-        verify(mListener).onSummaryChanged(anyString());
-    }
-
-    @Test
-    public void getSummary_wifiDisabled_shouldReturnDisabled() {
-        mWifiTracker.enabled = false;
-
-        assertThat(mSummaryUpdater.getSummary())
-            .isEqualTo(mContext.getString(R.string.switch_off_text));
-    }
-
-    @Test
-    public void getSummary_wifiDisconnected_shouldReturnDisconnected() {
-        mWifiTracker.enabled = true;
-        mWifiTracker.connected = false;
-
-        assertThat(mSummaryUpdater.getSummary())
-            .isEqualTo(mContext.getString(R.string.disconnected));
-    }
-
-    @Test
-    public void getSummary_wifiConnected_shouldReturnSsid() {
-        mWifiTracker.enabled = true;
-        mWifiTracker.connected = true;
-        mWifiTracker.ssid = "Test Ssid";
-
-        assertThat(mSummaryUpdater.getSummary()).isEqualTo("Test Ssid");
-    }
-
-    @Test
-    public void getSummary_wifiConnected_withSpeedLabel_shouldReturnSsid_withSpeedLabel() {
-        mWifiTracker.enabled = true;
-        mWifiTracker.connected = true;
-        mWifiTracker.ssid = "Test Ssid";
-        mWifiTracker.statusLabel = "Very Fast";
-
-        assertThat(mSummaryUpdater.getSummary()).isEqualTo("Test Ssid / Very Fast");
-    }
-
-    private class SummaryListener implements OnSummaryChangeListener {
-        private String summary;
-
-        @Override
-        public void onSummaryChanged(String summary) {
-            this.summary = summary;
-        }
-    }
-}
diff --git a/tests/spa_unit/src/com/android/settings/network/apn/ApnRepositoryTest.kt b/tests/spa_unit/src/com/android/settings/network/apn/ApnRepositoryTest.kt
index 4155318..d2f16d7 100644
--- a/tests/spa_unit/src/com/android/settings/network/apn/ApnRepositoryTest.kt
+++ b/tests/spa_unit/src/com/android/settings/network/apn/ApnRepositoryTest.kt
@@ -21,8 +21,6 @@
 import android.database.MatrixCursor
 import android.net.Uri
 import android.provider.Telephony
-import android.telephony.SubscriptionInfo
-import android.telephony.SubscriptionManager
 import android.telephony.TelephonyManager
 import androidx.test.core.app.ApplicationProvider
 import androidx.test.ext.junit.runners.AndroidJUnit4
@@ -40,19 +38,15 @@
 
     private val contentResolver = mock<ContentResolver>()
 
-    private val mockSubscriptionInfo = mock<SubscriptionInfo> {
-        on { mccString } doReturn MCC
-        on { mncString } doReturn MNC
-    }
+    private val mockTelephonyManager =
+        mock<TelephonyManager> { on { createForSubscriptionId(SUB_ID) } doReturn mock }
 
-    private val mockSubscriptionManager = mock<SubscriptionManager> {
-        on { getActiveSubscriptionInfo(SUB_ID) } doReturn mockSubscriptionInfo
-    }
+    private val context: Context =
+        spy(ApplicationProvider.getApplicationContext()) {
+            on { contentResolver } doReturn contentResolver
+            on { getSystemService(TelephonyManager::class.java) } doReturn mockTelephonyManager
+        }
 
-    private val context: Context = spy(ApplicationProvider.getApplicationContext()) {
-        on { contentResolver } doReturn contentResolver
-        on { getSystemService(SubscriptionManager::class.java) } doReturn mockSubscriptionManager
-    }
     private val uri = mock<Uri> {}
 
     @Test
@@ -91,9 +85,7 @@
 
     @Test
     fun getApnIdMap_knownCarrierId() {
-        mockSubscriptionInfo.stub {
-            on { carrierId } doReturn CARRIER_ID
-        }
+        mockTelephonyManager.stub { on { simSpecificCarrierId } doReturn CARRIER_ID }
 
         val idMap = context.getApnIdMap(SUB_ID)
 
@@ -102,19 +94,19 @@
 
     @Test
     fun getApnIdMap_unknownCarrierId() {
-        mockSubscriptionInfo.stub {
-            on { carrierId } doReturn TelephonyManager.UNKNOWN_CARRIER_ID
+        mockTelephonyManager.stub {
+            on { simSpecificCarrierId } doReturn TelephonyManager.UNKNOWN_CARRIER_ID
+            on { simOperator } doReturn SIM_OPERATOR
         }
 
         val idMap = context.getApnIdMap(SUB_ID)
 
-        assertThat(idMap).containsExactly(Telephony.Carriers.NUMERIC, MCC + MNC)
+        assertThat(idMap).containsExactly(Telephony.Carriers.NUMERIC, SIM_OPERATOR)
     }
 
     private companion object {
         const val SUB_ID = 2
         const val CARRIER_ID = 10
-        const val MCC = "310"
-        const val MNC = "101"
+        const val SIM_OPERATOR = "310101"
     }
 }
diff --git a/tests/spa_unit/src/com/android/settings/network/telephony/SubscriptionRepositoryTest.kt b/tests/spa_unit/src/com/android/settings/network/telephony/SubscriptionRepositoryTest.kt
index f75c14a..5dbc534 100644
--- a/tests/spa_unit/src/com/android/settings/network/telephony/SubscriptionRepositoryTest.kt
+++ b/tests/spa_unit/src/com/android/settings/network/telephony/SubscriptionRepositoryTest.kt
@@ -190,6 +190,32 @@
     }
 
     @Test
+    fun isSubscriptionVisibleFlow_available_returnTrue() = runBlocking {
+        mockSubscriptionManager.stub {
+            on { getAvailableSubscriptionInfoList() } doReturn
+                listOf(SubscriptionInfo.Builder().apply { setId(SUB_ID_IN_SLOT_0) }.build())
+        }
+
+        val isVisible =
+            repository.isSubscriptionVisibleFlow(SUB_ID_IN_SLOT_0).firstWithTimeoutOrNull()
+
+        assertThat(isVisible).isTrue()
+    }
+
+    @Test
+    fun isSubscriptionVisibleFlow_unavailable_returnFalse() = runBlocking {
+        mockSubscriptionManager.stub {
+            on { getAvailableSubscriptionInfoList() } doReturn
+                listOf(SubscriptionInfo.Builder().apply { setId(SUB_ID_IN_SLOT_0) }.build())
+        }
+
+        val isVisible =
+            repository.isSubscriptionVisibleFlow(SUB_ID_IN_SLOT_1).firstWithTimeoutOrNull()
+
+        assertThat(isVisible).isFalse()
+    }
+
+    @Test
     fun phoneNumberFlow() = runBlocking {
         mockSubscriptionManager.stub {
             on { getPhoneNumber(SUB_ID_IN_SLOT_1) } doReturn NUMBER_1
diff --git a/tests/spa_unit/src/com/android/settings/network/telephony/VideoCallingPreferenceControllerTest.kt b/tests/spa_unit/src/com/android/settings/network/telephony/VideoCallingPreferenceControllerTest.kt
new file mode 100644
index 0000000..4babfaa
--- /dev/null
+++ b/tests/spa_unit/src/com/android/settings/network/telephony/VideoCallingPreferenceControllerTest.kt
@@ -0,0 +1,125 @@
+/*
+ * 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 android.content.Context
+import android.telephony.TelephonyManager
+import androidx.lifecycle.testing.TestLifecycleOwner
+import androidx.preference.PreferenceManager
+import androidx.preference.SwitchPreferenceCompat
+import androidx.test.core.app.ApplicationProvider
+import androidx.test.ext.junit.runners.AndroidJUnit4
+import com.android.settings.network.ims.VolteQueryImsState
+import com.android.settings.network.ims.VtQueryImsState
+import com.google.common.truth.Truth.assertThat
+import kotlinx.coroutines.delay
+import kotlinx.coroutines.flow.flowOf
+import kotlinx.coroutines.runBlocking
+import org.junit.Before
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.mockito.kotlin.doReturn
+import org.mockito.kotlin.mock
+import org.mockito.kotlin.spy
+import org.mockito.kotlin.stub
+
+@RunWith(AndroidJUnit4::class)
+class VideoCallingPreferenceControllerTest {
+
+    private val mockVtQueryImsState = mock<VtQueryImsState> {}
+
+    private var mockQueryVoLteState = mock<VolteQueryImsState> {}
+
+    private val context: Context = ApplicationProvider.getApplicationContext()
+
+    private val mockCallStateRepository = mock<CallStateRepository> {}
+
+    private var controller =
+        spy(
+            VideoCallingPreferenceController(
+                context = context,
+                key = TEST_KEY,
+                callStateRepository = mockCallStateRepository,
+            )
+        ) {
+            on { queryImsState(SUB_ID) } doReturn mockVtQueryImsState
+            on { queryVoLteState(SUB_ID) } doReturn mockQueryVoLteState
+        }
+
+    private val preference = SwitchPreferenceCompat(context).apply { key = TEST_KEY }
+    private val preferenceScreen = PreferenceManager(context).createPreferenceScreen(context)
+
+    @Before
+    fun setUp() {
+        controller.init(SUB_ID, CallingPreferenceCategoryController(context, "calling_category"))
+        preferenceScreen.addPreference(preference)
+        controller.displayPreference(preferenceScreen)
+    }
+
+    @Test
+    fun updateState_4gLteOff_disabledAndUnchecked() {
+        mockQueryVoLteState.stub { on { isEnabledByUser } doReturn false }
+
+        controller.updateState(preference)
+
+        assertThat(preference.isEnabled).isFalse()
+        assertThat(preference.isChecked).isFalse()
+    }
+
+    @Test
+    fun updateState_4gLteOnWithoutCall_enabledAndChecked() = runBlocking {
+        mockVtQueryImsState.stub {
+            on { isEnabledByUser } doReturn true
+            on { isAllowUserControl } doReturn true
+        }
+        mockQueryVoLteState.stub { on { isEnabledByUser } doReturn true }
+        mockCallStateRepository.stub {
+            on { callStateFlow(SUB_ID) } doReturn flowOf(TelephonyManager.CALL_STATE_IDLE)
+        }
+
+        controller.onViewCreated(TestLifecycleOwner())
+        delay(100)
+        controller.updateState(preference)
+
+        assertThat(preference.isEnabled).isTrue()
+        assertThat(preference.isChecked).isTrue()
+    }
+
+    @Test
+    fun updateState_4gLteOnWithCall_disabledAndChecked() = runBlocking {
+        mockVtQueryImsState.stub {
+            on { isEnabledByUser } doReturn true
+            on { isAllowUserControl } doReturn true
+        }
+        mockQueryVoLteState.stub { on { isEnabledByUser } doReturn true }
+        mockCallStateRepository.stub {
+            on { callStateFlow(SUB_ID) } doReturn flowOf(TelephonyManager.CALL_STATE_RINGING)
+        }
+
+        controller.onViewCreated(TestLifecycleOwner())
+        delay(100)
+        controller.updateState(preference)
+
+        assertThat(preference.isEnabled).isFalse()
+        assertThat(preference.isChecked).isTrue()
+    }
+
+    private companion object {
+        const val TEST_KEY = "test_key"
+        const val SUB_ID = 10
+    }
+}
diff --git a/tests/spa_unit/src/com/android/settings/network/telephony/VideoCallingRepositoryTest.kt b/tests/spa_unit/src/com/android/settings/network/telephony/VideoCallingRepositoryTest.kt
new file mode 100644
index 0000000..063e191
--- /dev/null
+++ b/tests/spa_unit/src/com/android/settings/network/telephony/VideoCallingRepositoryTest.kt
@@ -0,0 +1,166 @@
+/*
+ * 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 android.content.Context
+import android.telephony.AccessNetworkConstants
+import android.telephony.CarrierConfigManager
+import android.telephony.SubscriptionManager
+import android.telephony.ims.feature.MmTelFeature
+import android.telephony.ims.stub.ImsRegistrationImplBase
+import androidx.test.core.app.ApplicationProvider
+import androidx.test.ext.junit.runners.AndroidJUnit4
+import com.android.settings.network.telephony.ims.ImsFeatureRepository
+import com.android.settingslib.spa.testutils.firstWithTimeoutOrNull
+import com.google.common.truth.Truth.assertThat
+import kotlinx.coroutines.flow.flowOf
+import kotlinx.coroutines.runBlocking
+import org.junit.Before
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.mockito.kotlin.doReturn
+import org.mockito.kotlin.mock
+import org.mockito.kotlin.stub
+
+@RunWith(AndroidJUnit4::class)
+class VideoCallingRepositoryTest {
+
+    private val context: Context = ApplicationProvider.getApplicationContext()
+
+    private val mockMobileDataRepository = mock<MobileDataRepository>()
+    private val mockImsFeatureRepository = mock<ImsFeatureRepository>()
+
+    private val repository =
+        VideoCallingRepository(
+            context = context,
+            mobileDataRepository = mockMobileDataRepository,
+            imsFeatureRepositoryFactory = { mockImsFeatureRepository },
+        )
+
+    @Before
+    fun setUp() {
+        CarrierConfigRepository.resetForTest()
+    }
+
+    @Test
+    fun isVideoCallReadyFlow_invalidSubId() = runBlocking {
+        val isVideoCallReady =
+            repository
+                .isVideoCallReadyFlow(subId = SubscriptionManager.INVALID_SUBSCRIPTION_ID)
+                .firstWithTimeoutOrNull()
+
+        assertThat(isVideoCallReady).isFalse()
+    }
+
+    @Test
+    fun isVideoCallReadyFlow_ignoreDataEnabledChangedAndIsReady_returnTrue() = runBlocking {
+        CarrierConfigRepository.setBooleanForTest(
+            subId = SUB_ID,
+            key = CarrierConfigManager.KEY_IGNORE_DATA_ENABLED_CHANGED_FOR_VIDEO_CALLS,
+            value = true,
+        )
+        mockImsFeatureRepository.stub {
+            on {
+                isReadyFlow(
+                    capability = MmTelFeature.MmTelCapabilities.CAPABILITY_TYPE_VIDEO,
+                    tech = ImsRegistrationImplBase.REGISTRATION_TECH_LTE,
+                    transportType = AccessNetworkConstants.TRANSPORT_TYPE_WWAN,
+                )
+            } doReturn flowOf(true)
+        }
+
+        val isVideoCallReady = repository.isVideoCallReadyFlow(SUB_ID).firstWithTimeoutOrNull()
+
+        assertThat(isVideoCallReady).isTrue()
+    }
+
+    @Test
+    fun isVideoCallReadyFlow_ignoreDataEnabledChangedAndNotReady_returnFalse() = runBlocking {
+        CarrierConfigRepository.setBooleanForTest(
+            subId = SUB_ID,
+            key = CarrierConfigManager.KEY_IGNORE_DATA_ENABLED_CHANGED_FOR_VIDEO_CALLS,
+            value = true,
+        )
+        mockImsFeatureRepository.stub {
+            on {
+                isReadyFlow(
+                    capability = MmTelFeature.MmTelCapabilities.CAPABILITY_TYPE_VIDEO,
+                    tech = ImsRegistrationImplBase.REGISTRATION_TECH_LTE,
+                    transportType = AccessNetworkConstants.TRANSPORT_TYPE_WWAN,
+                )
+            } doReturn flowOf(false)
+        }
+
+        val isVideoCallReady = repository.isVideoCallReadyFlow(SUB_ID).firstWithTimeoutOrNull()
+
+        assertThat(isVideoCallReady).isFalse()
+    }
+
+    @Test
+    fun isVideoCallReadyFlow_mobileDataEnabledAndIsReady_returnTrue() = runBlocking {
+        CarrierConfigRepository.setBooleanForTest(
+            subId = SUB_ID,
+            key = CarrierConfigManager.KEY_IGNORE_DATA_ENABLED_CHANGED_FOR_VIDEO_CALLS,
+            value = false,
+        )
+        mockMobileDataRepository.stub {
+            on { isMobileDataEnabledFlow(SUB_ID) } doReturn flowOf(true)
+        }
+        mockImsFeatureRepository.stub {
+            on {
+                isReadyFlow(
+                    capability = MmTelFeature.MmTelCapabilities.CAPABILITY_TYPE_VIDEO,
+                    tech = ImsRegistrationImplBase.REGISTRATION_TECH_LTE,
+                    transportType = AccessNetworkConstants.TRANSPORT_TYPE_WWAN,
+                )
+            } doReturn flowOf(true)
+        }
+
+        val isVideoCallReady = repository.isVideoCallReadyFlow(SUB_ID).firstWithTimeoutOrNull()
+
+        assertThat(isVideoCallReady).isTrue()
+    }
+
+    @Test
+    fun isVideoCallReadyFlow_ignoreDataEnabledChangedAndIsReady_returnFalse() = runBlocking {
+        CarrierConfigRepository.setBooleanForTest(
+            subId = SUB_ID,
+            key = CarrierConfigManager.KEY_IGNORE_DATA_ENABLED_CHANGED_FOR_VIDEO_CALLS,
+            value = false,
+        )
+        mockMobileDataRepository.stub {
+            on { isMobileDataEnabledFlow(SUB_ID) } doReturn flowOf(false)
+        }
+        mockImsFeatureRepository.stub {
+            on {
+                isReadyFlow(
+                    capability = MmTelFeature.MmTelCapabilities.CAPABILITY_TYPE_VIDEO,
+                    tech = ImsRegistrationImplBase.REGISTRATION_TECH_LTE,
+                    transportType = AccessNetworkConstants.TRANSPORT_TYPE_WWAN,
+                )
+            } doReturn flowOf(true)
+        }
+
+        val isVideoCallReady = repository.isVideoCallReadyFlow(SUB_ID).firstWithTimeoutOrNull()
+
+        assertThat(isVideoCallReady).isFalse()
+    }
+
+    private companion object {
+        const val SUB_ID = 10
+    }
+}
diff --git a/tests/spa_unit/src/com/android/settings/network/telephony/euicc/EuiccRepositoryTest.kt b/tests/spa_unit/src/com/android/settings/network/telephony/euicc/EuiccRepositoryTest.kt
new file mode 100644
index 0000000..24e6fd6
--- /dev/null
+++ b/tests/spa_unit/src/com/android/settings/network/telephony/euicc/EuiccRepositoryTest.kt
@@ -0,0 +1,117 @@
+/*
+ * 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.euicc
+
+import android.content.Context
+import android.telephony.TelephonyManager
+import android.telephony.euicc.EuiccManager
+import androidx.test.core.app.ApplicationProvider
+import androidx.test.ext.junit.runners.AndroidJUnit4
+import com.android.settings.R
+import com.google.common.truth.Truth.assertThat
+import org.junit.Before
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.mockito.kotlin.any
+import org.mockito.kotlin.doReturn
+import org.mockito.kotlin.mock
+import org.mockito.kotlin.spy
+import org.mockito.kotlin.stub
+
+@RunWith(AndroidJUnit4::class)
+class EuiccRepositoryTest {
+
+    private val mockEuiccManager = mock<EuiccManager> { on { isEnabled } doReturn true }
+
+    private val mockTelephonyManager =
+        mock<TelephonyManager> {
+            on { activeModemCount } doReturn 1
+            on { getNetworkCountryIso(any()) } doReturn COUNTRY_CODE
+        }
+
+    private val context: Context =
+        spy(ApplicationProvider.getApplicationContext()) {
+            on { getSystemService(EuiccManager::class.java) } doReturn mockEuiccManager
+            on { getSystemService(TelephonyManager::class.java) } doReturn mockTelephonyManager
+        }
+
+    private val resources =
+        spy(context.resources) { on { getBoolean(R.bool.config_show_sim_info) } doReturn true }
+
+    private var euiccProvisioned = false
+
+    private val repository =
+        EuiccRepository(
+            context,
+            isEuiccProvisioned = { euiccProvisioned },
+            isDevelopmentSettingsEnabled = { false },
+        )
+
+    @Before
+    fun setUp() {
+        context.stub { on { resources } doReturn resources }
+    }
+
+    @Test
+    fun showEuiccSettings_noSim_returnFalse() {
+        resources.stub { on { getBoolean(R.bool.config_show_sim_info) } doReturn false }
+
+        val showEuiccSettings = repository.showEuiccSettings()
+
+        assertThat(showEuiccSettings).isFalse()
+    }
+
+    @Test
+    fun showEuiccSettings_euiccDisabled_returnFalse() {
+        mockEuiccManager.stub { on { isEnabled } doReturn false }
+
+        val showEuiccSettings = repository.showEuiccSettings()
+
+        assertThat(showEuiccSettings).isFalse()
+    }
+
+    @Test
+    fun showEuiccSettings_euiccProvisioned_returnTrue() {
+        euiccProvisioned = true
+
+        val showEuiccSettings = repository.showEuiccSettings()
+
+        assertThat(showEuiccSettings).isTrue()
+    }
+
+    @Test
+    fun showEuiccSettings_countryNotSupported_returnFalse() {
+        mockEuiccManager.stub { on { isSupportedCountry(COUNTRY_CODE) } doReturn false }
+
+        val showEuiccSettings = repository.showEuiccSettings()
+
+        assertThat(showEuiccSettings).isFalse()
+    }
+
+    @Test
+    fun showEuiccSettings_countrySupported_returnTrue() {
+        mockEuiccManager.stub { on { isSupportedCountry(COUNTRY_CODE) } doReturn true }
+
+        val showEuiccSettings = repository.showEuiccSettings()
+
+        assertThat(showEuiccSettings).isTrue()
+    }
+
+    private companion object {
+        const val COUNTRY_CODE = "us"
+    }
+}
diff --git a/tests/spa_unit/src/com/android/settings/network/telephony/wificalling/WifiCallingRepositoryTest.kt b/tests/spa_unit/src/com/android/settings/network/telephony/wificalling/WifiCallingRepositoryTest.kt
index f0a23eb..9b71465 100644
--- a/tests/spa_unit/src/com/android/settings/network/telephony/wificalling/WifiCallingRepositoryTest.kt
+++ b/tests/spa_unit/src/com/android/settings/network/telephony/wificalling/WifiCallingRepositoryTest.kt
@@ -102,22 +102,6 @@
         assertThat(wiFiCallingMode).isEqualTo(ImsMmTelManager.WIFI_MODE_WIFI_PREFERRED)
     }
 
-    @Test
-    fun isWifiCallingSupported() = runBlocking {
-        mockImsMmTelRepository.stub {
-            onBlocking {
-                isSupported(
-                    capability = MmTelFeature.MmTelCapabilities.CAPABILITY_TYPE_VOICE,
-                    transportType = AccessNetworkConstants.TRANSPORT_TYPE_WLAN,
-                )
-            } doReturn true
-        }
-
-        val isSupported = repository.isWifiCallingSupported()
-
-        assertThat(isSupported).isTrue()
-    }
-
     private fun mockUseWfcHomeModeForRoaming(config: Boolean) {
         mockCarrierConfigManager.stub {
             on {
diff --git a/tests/unit/src/com/android/settings/network/InternetPreferenceControllerTest.java b/tests/unit/src/com/android/settings/network/InternetPreferenceControllerTest.java
deleted file mode 100644
index 1c482ef..0000000
--- a/tests/unit/src/com/android/settings/network/InternetPreferenceControllerTest.java
+++ /dev/null
@@ -1,297 +0,0 @@
-/*
- * Copyright (C) 2020 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;
-
-import static com.android.settings.network.InternetUpdater.INTERNET_NETWORKS_AVAILABLE;
-import static com.android.settings.network.InternetUpdater.INTERNET_WIFI;
-
-import static com.google.common.truth.Truth.assertThat;
-
-import static org.mockito.ArgumentMatchers.any;
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.times;
-import static org.mockito.Mockito.verify;
-import static org.mockito.Mockito.when;
-
-import android.content.BroadcastReceiver;
-import android.content.Context;
-import android.content.IntentFilter;
-import android.net.ConnectivityManager;
-import android.net.NetworkRequest;
-import android.net.NetworkScoreManager;
-import android.net.wifi.WifiManager;
-import android.os.Handler;
-import android.os.Looper;
-
-import androidx.lifecycle.Lifecycle;
-import androidx.lifecycle.LifecycleOwner;
-import androidx.lifecycle.LifecycleRegistry;
-import androidx.preference.Preference;
-import androidx.preference.PreferenceManager;
-import androidx.preference.PreferenceScreen;
-import androidx.test.annotation.UiThreadTest;
-import androidx.test.core.app.ApplicationProvider;
-import androidx.test.ext.junit.runners.AndroidJUnit4;
-
-import com.android.settings.R;
-import com.android.settings.testutils.ResourcesUtils;
-import com.android.settings.wifi.WifiPickerTrackerHelper;
-import com.android.settings.wifi.WifiSummaryUpdater;
-import com.android.settingslib.mobile.dataservice.SubscriptionInfoEntity;
-import com.android.wifitrackerlib.HotspotNetworkEntry;
-import com.android.wifitrackerlib.StandardWifiEntry;
-import com.android.wifitrackerlib.WifiPickerTracker;
-
-import org.junit.Before;
-import org.junit.Rule;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.mockito.Mock;
-import org.mockito.Spy;
-import org.mockito.junit.MockitoJUnit;
-import org.mockito.junit.MockitoRule;
-
-import java.util.ArrayList;
-import java.util.List;
-
-@RunWith(AndroidJUnit4.class)
-public class InternetPreferenceControllerTest {
-
-    private static final String TEST_SUMMARY = "test summary";
-    private static final String TEST_ALTERNATE_SUMMARY = "test alternate summary";
-    private static final String NOT_CONNECTED = "Not connected";
-    private static final String SUB_ID_1 = "1";
-    private static final String SUB_ID_2 = "2";
-    private static final String DISPLAY_NAME_1 = "Sub 1";
-    private static final String DISPLAY_NAME_2 = "Sub 2";
-
-    @Rule
-    public final MockitoRule mMockitoRule = MockitoJUnit.rule();
-    @Spy
-    private Context mContext = ApplicationProvider.getApplicationContext();
-    @Mock
-    private SubscriptionInfoEntity mActiveSubInfo;
-    @Mock
-    private SubscriptionInfoEntity mDefaultDataSubInfo;
-    @Mock
-    private ConnectivityManager mConnectivityManager;
-    @Mock
-    private LifecycleOwner mLifecycleOwner;
-    @Mock
-    private WifiManager mWifiManager;
-    @Mock
-    private WifiSummaryUpdater mSummaryHelper;
-    @Mock
-    private WifiPickerTrackerHelper mWifiPickerTrackerHelper;
-    @Mock
-    private WifiPickerTracker mWifiPickerTracker;
-    @Mock
-    private HotspotNetworkEntry mHotspotNetworkEntry;
-
-    private LifecycleRegistry mLifecycleRegistry;
-
-    private MockInternetPreferenceController mController;
-    private PreferenceScreen mScreen;
-    private Preference mPreference;
-    private List<SubscriptionInfoEntity> mSubscriptionInfoEntityList = new ArrayList<>();
-
-    @Before
-    public void setUp() {
-        when(mContext.getSystemService(ConnectivityManager.class)).thenReturn(mConnectivityManager);
-        when(mContext.getSystemService(NetworkScoreManager.class))
-                .thenReturn(mock(NetworkScoreManager.class));
-        when(mContext.getSystemService(Context.WIFI_SERVICE)).thenReturn(mWifiManager);
-        when(mWifiManager.getWifiState()).thenReturn(WifiManager.WIFI_STATE_DISABLED);
-        when(mWifiPickerTrackerHelper.getWifiPickerTracker()).thenReturn(mWifiPickerTracker);
-        when(mWifiPickerTracker.getConnectedWifiEntry()).thenReturn(null /* WifiEntry */);
-        when(mHotspotNetworkEntry.getAlternateSummary()).thenReturn(TEST_ALTERNATE_SUMMARY);
-
-        if (Looper.myLooper() == null) {
-            Looper.prepare();
-        }
-        mLifecycleRegistry = new LifecycleRegistry(mLifecycleOwner);
-        when(mLifecycleOwner.getLifecycle()).thenReturn(mLifecycleRegistry);
-        mController = new MockInternetPreferenceController(mContext, mock(Lifecycle.class),
-                mLifecycleOwner);
-        mController.sIconMap.put(INTERNET_WIFI, 0);
-        mController.mWifiPickerTrackerHelper = mWifiPickerTrackerHelper;
-
-        final PreferenceManager preferenceManager = new PreferenceManager(mContext);
-        mScreen = preferenceManager.createPreferenceScreen(mContext);
-        mPreference = new Preference(mContext);
-        mPreference.setKey(InternetPreferenceController.KEY);
-        mScreen.addPreference(mPreference);
-    }
-
-    private class MockInternetPreferenceController extends
-            com.android.settings.network.InternetPreferenceController {
-
-        private int mDefaultDataSubscriptionId;
-        public MockInternetPreferenceController(Context context, Lifecycle lifecycle,
-                LifecycleOwner lifecycleOwner) {
-            super(context, lifecycle, lifecycleOwner);
-        }
-
-        private List<SubscriptionInfoEntity> mSubscriptionInfoEntity;
-
-        @Override
-        protected List<SubscriptionInfoEntity> getSubscriptionInfoList() {
-            return mSubscriptionInfoEntity;
-        }
-
-        public void setSubscriptionInfoList(List<SubscriptionInfoEntity> list) {
-            mSubscriptionInfoEntity = list;
-        }
-
-        @Override
-        protected int getDefaultDataSubscriptionId() {
-            return mDefaultDataSubscriptionId;
-        }
-
-        public void setDefaultDataSubscriptionId(int subscriptionId) {
-            mDefaultDataSubscriptionId = subscriptionId;
-        }
-
-    }
-
-    private SubscriptionInfoEntity setupSubscriptionInfoEntity(String subId, int slotId,
-            String displayName, boolean isVisible, boolean isValid, boolean isActive,
-            boolean isActiveData) {
-        return new SubscriptionInfoEntity(subId, slotId, false, false, displayName, isVisible,
-                false, isValid, isActive, isActiveData);
-    }
-
-    @Test
-    public void isAvailable_shouldMatchPrefFlag() {
-        assertThat(mController.isAvailable()).isEqualTo(
-                mContext.getResources().getBoolean(R.bool.config_show_internet_settings));
-    }
-
-    @Test
-    @UiThreadTest
-    public void onResume_shouldRegisterCallback() {
-        mController.onResume();
-
-        verify(mContext).registerReceiver(any(BroadcastReceiver.class), any(IntentFilter.class),
-                any(int.class));
-        verify(mConnectivityManager).registerNetworkCallback(
-                any(NetworkRequest.class),
-                any(ConnectivityManager.NetworkCallback.class),
-                any(Handler.class));
-    }
-
-    @Test
-    @UiThreadTest
-    public void onPause_shouldUnregisterCallback() {
-        mController.onResume();
-        mController.onPause();
-
-        verify(mContext, times(2)).unregisterReceiver(any(BroadcastReceiver.class));
-        verify(mConnectivityManager, times(2)).unregisterNetworkCallback(
-                any(ConnectivityManager.NetworkCallback.class));
-    }
-
-    @Test
-    public void onSummaryChanged_internetWifi_updateSummary() {
-        when(mSummaryHelper.getSummary()).thenReturn(TEST_SUMMARY);
-        mController.mSummaryHelper = mSummaryHelper;
-        mController.onInternetTypeChanged(INTERNET_WIFI);
-        mController.displayPreference(mScreen);
-
-        mController.onSummaryChanged(TEST_SUMMARY);
-
-        assertThat(mPreference.getSummary()).isEqualTo(TEST_SUMMARY);
-    }
-
-    @Test
-    public void onSummaryChanged_internetNetworksAvailable_notUpdateSummary() {
-        when(mSummaryHelper.getSummary()).thenReturn(TEST_SUMMARY);
-        mController.mSummaryHelper = mSummaryHelper;
-        mController.onInternetTypeChanged(INTERNET_NETWORKS_AVAILABLE);
-        mController.displayPreference(mScreen);
-        mPreference.setSummary(NOT_CONNECTED);
-
-        mController.onSummaryChanged(TEST_SUMMARY);
-
-        assertThat(mPreference.getSummary()).isNotEqualTo(TEST_SUMMARY);
-    }
-
-    @Test
-    public void updateCellularSummary_getNullSubscriptionInfo_shouldNotCrash() {
-        mController.setSubscriptionInfoList(mSubscriptionInfoEntityList);
-
-        mController.updateCellularSummary();
-    }
-
-    @Test
-    public void updateCellularSummary_getActiveSubscriptionInfo_cbrs() {
-        mController.setDefaultDataSubscriptionId(Integer.parseInt(SUB_ID_2));
-        mActiveSubInfo = setupSubscriptionInfoEntity(SUB_ID_1, 1, DISPLAY_NAME_1,
-                false, true, true, true);
-        mDefaultDataSubInfo = setupSubscriptionInfoEntity(SUB_ID_2, 1, DISPLAY_NAME_2,
-                false, true, true, false);
-        mSubscriptionInfoEntityList.add(mActiveSubInfo);
-        mSubscriptionInfoEntityList.add(mDefaultDataSubInfo);
-        mController.setSubscriptionInfoList(mSubscriptionInfoEntityList);
-        mController.displayPreference(mScreen);
-
-        mController.updateCellularSummary();
-        assertThat(mPreference.getSummary()).isEqualTo(DISPLAY_NAME_2);
-
-        mActiveSubInfo = setupSubscriptionInfoEntity(SUB_ID_1, 1, DISPLAY_NAME_1,
-                true, true, true, true);
-        mSubscriptionInfoEntityList.add(mActiveSubInfo);
-        mController.setSubscriptionInfoList(mSubscriptionInfoEntityList);
-        mController.onAvailableSubInfoChanged(mSubscriptionInfoEntityList);
-        final String expectedSummary =
-                ResourcesUtils.getResourcesString(mContext, "mobile_data_temp_using",
-                        DISPLAY_NAME_1);
-        mController.updateCellularSummary();
-        assertThat(mPreference.getSummary()).isEqualTo(expectedSummary);
-    }
-
-    @Test
-    public void updateHotspotNetwork_isHotspotNetworkEntry_updateAlternateSummary() {
-        when(mWifiPickerTracker.getConnectedWifiEntry()).thenReturn(mHotspotNetworkEntry);
-        mController.onInternetTypeChanged(INTERNET_WIFI);
-        mController.displayPreference(mScreen);
-        mPreference.setSummary(TEST_SUMMARY);
-
-        mController.updateHotspotNetwork();
-
-        assertThat(mPreference.getSummary().toString()).isEqualTo(TEST_ALTERNATE_SUMMARY);
-    }
-
-    @Test
-    public void updateHotspotNetwork_notHotspotNetworkEntry_notChangeSummary() {
-        when(mWifiPickerTracker.getConnectedWifiEntry()).thenReturn(mock(StandardWifiEntry.class));
-        mController.onInternetTypeChanged(INTERNET_WIFI);
-        mController.displayPreference(mScreen);
-        mPreference.setSummary(TEST_SUMMARY);
-
-        mController.updateHotspotNetwork();
-
-        assertThat(mPreference.getSummary().toString()).isEqualTo(TEST_SUMMARY);
-    }
-
-    @Test
-    public void updateHotspotNetwork_hotspotNetworkNotEnabled_returnFalse() {
-        mController.mWifiPickerTrackerHelper = null;
-
-        assertThat(mController.updateHotspotNetwork()).isFalse();
-    }
-}
diff --git a/tests/unit/src/com/android/settings/network/ims/MockVtQueryImsState.java b/tests/unit/src/com/android/settings/network/ims/MockVtQueryImsState.java
deleted file mode 100644
index 0949f1c..0000000
--- a/tests/unit/src/com/android/settings/network/ims/MockVtQueryImsState.java
+++ /dev/null
@@ -1,104 +0,0 @@
-/*
- * Copyright (C) 2020 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.ims;
-
-import android.content.Context;
-import android.telephony.ims.ImsException;
-
-/**
- * Controller class for mock VT status
- */
-public class MockVtQueryImsState extends VtQueryImsState {
-
-    private Boolean mIsTtyOnVolteEnabled;
-    private Boolean mIsEnabledOnPlatform;
-    private Boolean mIsProvisionedOnDevice;
-    private Boolean mIsEnabledByUser;
-    private Boolean mIsServiceStateReady;
-
-    /**
-     * Constructor
-     *
-     * @param context {@link Context}
-     * @param subId subscription's id
-     */
-    public MockVtQueryImsState(Context context, int subId) {
-        super(context, subId);
-    }
-
-    public void setIsTtyOnVolteEnabled(boolean enabled) {
-        mIsTtyOnVolteEnabled = enabled;
-    }
-
-    @Override
-    boolean isTtyOnVolteEnabled(int subId) {
-        if (mIsTtyOnVolteEnabled != null) {
-            return mIsTtyOnVolteEnabled;
-        }
-        return super.isTtyOnVolteEnabled(subId);
-    }
-
-    public void setIsEnabledByPlatform(boolean isEnabled) {
-        mIsEnabledOnPlatform = isEnabled;
-    }
-
-    @Override
-    boolean isEnabledByPlatform(int subId) throws InterruptedException, ImsException,
-            IllegalArgumentException {
-        if (mIsEnabledOnPlatform != null) {
-            return mIsEnabledOnPlatform;
-        }
-        return super.isEnabledByPlatform(subId);
-    }
-
-    public void setIsProvisionedOnDevice(boolean isProvisioned) {
-        mIsProvisionedOnDevice = isProvisioned;
-    }
-
-    @Override
-    boolean isProvisionedOnDevice(int subId) {
-        if (mIsProvisionedOnDevice != null) {
-            return mIsProvisionedOnDevice;
-        }
-        return super.isProvisionedOnDevice(subId);
-    }
-
-    public void setServiceStateReady(boolean isReady) {
-        mIsServiceStateReady = isReady;
-    }
-
-    @Override
-    boolean isServiceStateReady(int subId) throws InterruptedException, ImsException,
-            IllegalArgumentException {
-        if (mIsServiceStateReady != null) {
-            return mIsServiceStateReady;
-        }
-        return super.isServiceStateReady(subId);
-    }
-
-    public void setIsEnabledByUser(boolean enabled) {
-        mIsEnabledByUser = enabled;
-    }
-
-    @Override
-    boolean isEnabledByUser(int subId) {
-        if (mIsEnabledByUser != null) {
-            return mIsEnabledByUser;
-        }
-        return super.isEnabledByUser(subId);
-    }
-}