Merge "Import translations. DO NOT MERGE ANYWHERE" into main
diff --git a/res-product/values-fr-feminine/strings.xml b/res-product/values-fr-feminine/strings.xml
new file mode 100644
index 0000000..4027cbd
--- /dev/null
+++ b/res-product/values-fr-feminine/strings.xml
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- 
+  ~ Copyright (C) 2022 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.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="main_clear_accounts" product="default" msgid="3604029744509330786">\n\n"Vous êtes actuellement connectée aux comptes suivants :\n"</string>
+    <string name="install_all_warning" product="tablet" msgid="1732116924846572063">"Votre tablette et vos données personnelles sont très vulnérables aux attaques provenant d\'applications inconnues. En installant des applications provenant de cette source, vous acceptez d\'être la seule responsable de tout dommage causé à votre tablette ou de toute perte de données pouvant découler de l\'utilisation de telles applications."</string>
+    <string name="install_all_warning" product="default" msgid="4597256179485325694">"Votre téléphone et vos données personnelles sont plus vulnérables aux attaques d\'applis inconnues. En installant des applis depuis cette source, vous reconnaissez être responsable de tout dommage causé à votre téléphone ou de toute perte de données pouvant découler de leur utilisation​."</string>
+    <string name="install_all_warning" product="device" msgid="6293002353591632851">"Votre appareil et vos données personnelles sont très vulnérables aux attaques provenant d\'applications inconnues. En installant des applications provenant de cette source, vous acceptez d\'être la seule responsable de tout dommage causé à votre appareil ou de toute perte de données pouvant découler de l\'utilisation de telles applications."</string>
+</resources>
diff --git a/res-product/values-fr-masculine/strings.xml b/res-product/values-fr-masculine/strings.xml
new file mode 100644
index 0000000..0bca528
--- /dev/null
+++ b/res-product/values-fr-masculine/strings.xml
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- 
+  ~ Copyright (C) 2022 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.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="main_clear_accounts" product="default" msgid="3604029744509330786">\n\n"Vous êtes actuellement connecté aux comptes suivants :\n"</string>
+    <string name="install_all_warning" product="tablet" msgid="1732116924846572063">"Votre tablette et vos données personnelles sont très vulnérables aux attaques provenant d\'applications inconnues. En installant des applications provenant de cette source, vous acceptez d\'être le seul responsable de tout dommage causé à votre tablette ou de toute perte de données pouvant découler de l\'utilisation de telles applications."</string>
+    <string name="install_all_warning" product="default" msgid="4597256179485325694">"Votre téléphone et vos données personnelles sont plus vulnérables aux attaques d\'applis inconnues. En installant des applis depuis cette source, vous reconnaissez être responsable de tout dommage causé à votre téléphone ou de toute perte de données pouvant découler de leur utilisation​."</string>
+    <string name="install_all_warning" product="device" msgid="6293002353591632851">"Votre appareil et vos données personnelles sont très vulnérables aux attaques provenant d\'applications inconnues. En installant des applications provenant de cette source, vous acceptez d\'être le seul responsable de tout dommage causé à votre appareil ou de toute perte de données pouvant découler de l\'utilisation de telles applications."</string>
+</resources>
diff --git a/res-product/values-fr-neuter/strings.xml b/res-product/values-fr-neuter/strings.xml
new file mode 100644
index 0000000..8777756
--- /dev/null
+++ b/res-product/values-fr-neuter/strings.xml
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- 
+  ~ Copyright (C) 2022 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.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="main_clear_accounts" product="default" msgid="3604029744509330786">\n\n"Vous êtes actuellement connecté·e aux comptes suivants :\n"</string>
+    <string name="install_all_warning" product="tablet" msgid="1732116924846572063">"Votre tablette et vos données personnelles sont très vulnérables aux attaques provenant d\'applications inconnues. En installant des applications provenant de cette source, vous acceptez d\'être l\'unique responsable de tout dommage causé à votre tablette ou de toute perte de données pouvant découler de l\'utilisation de telles applications."</string>
+    <string name="install_all_warning" product="default" msgid="4597256179485325694">"Votre téléphone et vos données personnelles sont plus vulnérables aux attaques d\'applis inconnues. En installant des applis depuis cette source, vous reconnaissez être responsable de tout dommage causé à votre téléphone ou de toute perte de données pouvant découler de leur utilisation​."</string>
+    <string name="install_all_warning" product="device" msgid="6293002353591632851">"Votre appareil et vos données personnelles sont très vulnérables aux attaques provenant d\'applications inconnues. En installant des applications provenant de cette source, vous acceptez d\'être l\'unique responsable de tout dommage causé à votre appareil ou de toute perte de données pouvant découler de l\'utilisation de telles applications."</string>
+</resources>
diff --git a/res/values/arrays.xml b/res/values/arrays.xml
index 0e35fed..dd2d7e3 100644
--- a/res/values/arrays.xml
+++ b/res/values/arrays.xml
@@ -1074,7 +1074,7 @@
     </string-array>
 
     <string-array name="wifi_privacy_entries">
-        <item>Use randomized MAC (default)</item>
+        <item>Use randomized MAC</item>
         <item>Use device MAC</item>
     </string-array>
 
diff --git a/res/values/strings.xml b/res/values/strings.xml
index 7ae9074..80063b6 100644
--- a/res/values/strings.xml
+++ b/res/values/strings.xml
@@ -4760,6 +4760,14 @@
     <string name="accessibility_magnification_triple_tap_warning_negative_button">Cancel</string>
     <!-- Title for the accessibility preference screen to enable screen magnification settings. [CHAR LIMIT=35] -->
     <string name="accessibility_magnification_service_settings_title">Magnification settings</string>
+    <!-- Title for accessibility magnification preference where user can move the magnification area by dragging one finger instead of two. [CHAR LIMIT=60] -->
+    <string name="accessibility_magnification_one_finger_panning_title">One-finger panning</string>
+    <!-- Summary for accessibility magnification preference when one finger panning feature is turned on.
+         The feature when enabled allows user to move the magnification area by dragging one finger instead of two. [CHAR LIMIT=60] -->
+    <string name="accessibility_magnification_one_finger_panning_summary_on">Move the magnification area by dragging one finger.</string>
+    <!-- Summary for accessibility magnification preference when one finger panning feature is turned off.
+         The feature when disabled, allows user to move the magnification area by dragging two fingers instead of one. [CHAR LIMIT=60] -->
+    <string name="accessibility_magnification_one_finger_panning_summary_off">Move the magnification area by dragging two fingers.</string>
     <!-- Title for the accessibility preference screen to enable navigation bar screen magnification. [CHAR LIMIT=35] -->
     <string name="accessibility_screen_magnification_navbar_title">Magnify with shortcut</string>
     <!-- Summary for the accessibility magnification setting indicating both "Magnify with button" and "Magnify with triple-tap" are enabled [CHAR LIMIT=50] -->
@@ -11677,6 +11685,13 @@
     <!-- Body text of automatic data switching at dual sim onboarding's primary sim page or SIMs page. [CHAR LIMIT=NONE] -->
     <string name="primary_sim_automatic_data_msg">Use data from either SIM depending on coverage and availability</string>
 
+    <!-- Title of asking the user whether to restart device after enabling DSDS. [CHAR LIMIT=NONE] -->
+    <string name="sim_action_restart_dialog_title">Restart to use 2 SIMs</string>
+    <!-- Body text of asking the user whether to restart device after enabling DSDS. [CHAR LIMIT=NONE] -->
+    <string name="sim_action_restart_dialog_msg">To use 2 SIMs at once, restart your device, then turn on both SIMs</string>
+    <!-- Button text to cancel dialog and then enable the sim -->
+    <string name="sim_action_restart_dialog_cancel">Use <xliff:g id="carrier_name" example="Google Fi">%1$s</xliff:g> only</string>
+
     <!-- Text of phone number item when the sim is data only. [CHAR LIMIT=NONE] -->
     <string name="sim_onboarding_phoneNumber_data_only">Data only</string>
 
@@ -12994,11 +13009,6 @@
     <!-- Developer settings: select Grammatical gender dialog title [CHAR LIMIT=50]-->
     <string name="grammatical_gender_dialog_title">Select Grammatical gender</string>
 
-    <!-- Do not translate. Developer settings: Title for the screen allowing user to control Quarantined apps [CHAR LIMIT=50] -->
-    <string name="quarantined_apps_title" translatable="false">Quarantined Apps</string>
-    <!-- Do not translate. Developer settings: Button to unquarantine an app [CHAR LIMIT=20] -->
-    <string name="unquarantine_app_button" translatable="false">Unquarantine app</string>
-
     <!-- Title of preference to manage content protection settings -->
     <string name="content_protection_preference_title">Scanning for deceptive apps</string>
     <!-- Summary of the preference to manage content protection settings -->
diff --git a/res/xml/development_settings.xml b/res/xml/development_settings.xml
index c0b6560..1fdfcaf 100644
--- a/res/xml/development_settings.xml
+++ b/res/xml/development_settings.xml
@@ -769,12 +769,6 @@
             android:title="@string/enable_notes_role_title"
             android:summary="@string/enable_notes_role_summary" />
 
-        <Preference
-            android:key="quarantined_apps"
-            android:title="@string/quarantined_apps_title"
-            settings:controller="com.android.settings.development.quarantine.QuarantinedAppsPreferenceController"
-            android:fragment="com.android.settings.development.quarantine.QuarantinedAppsFragment" />
-
     </PreferenceCategory>
 
     <PreferenceCategory
diff --git a/res/xml/mobile_network_settings.xml b/res/xml/mobile_network_settings.xml
index 1e43ef0..adb84b6 100644
--- a/res/xml/mobile_network_settings.xml
+++ b/res/xml/mobile_network_settings.xml
@@ -18,9 +18,8 @@
     xmlns:settings="http://schemas.android.com/apk/res-auto"
     android:key="mobile_network_pref_screen">
 
-    <com.android.settings.widget.SettingsMainSwitchPreference
+    <com.android.settings.spa.preference.ComposePreference
         android:key="use_sim_switch"
-        android:title="@string/mobile_network_use_sim_on"
         settings:controller="com.android.settings.network.telephony.MobileNetworkSwitchController"/>
 
     <PreferenceCategory
diff --git a/res/xml/quarantined_apps.xml b/res/xml/quarantined_apps.xml
deleted file mode 100644
index 69a90d6..0000000
--- a/res/xml/quarantined_apps.xml
+++ /dev/null
@@ -1,25 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-  Copyright (C) 2023 The Android Open Source Project
-
-  Licensed under the Apache License, Version 2.0 (the "License");
-  you may not use this file except in compliance with the License.
-  You may obtain a copy of the License at
-
-       http://www.apache.org/licenses/LICENSE-2.0
-
-  Unless required by applicable law or agreed to in writing, software
-  distributed under the License is distributed on an "AS IS" BASIS,
-  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-  See the License for the specific language governing permissions and
-  limitations under the License.
--->
-
-<PreferenceScreen
-    xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:settings="http://schemas.android.com/apk/res-auto"
-    android:key="quarantined_apps_screen"
-    android:title="@string/quarantined_apps_title"
-    settings:controller="com.android.settings.development.quarantine.QuarantinedAppsScreenController"
-    settings:searchable="true">
-</PreferenceScreen>
\ No newline at end of file
diff --git a/res/xml/user_aspect_ratio_details.xml b/res/xml/user_aspect_ratio_details.xml
index 44a7589..24c3271 100644
--- a/res/xml/user_aspect_ratio_details.xml
+++ b/res/xml/user_aspect_ratio_details.xml
@@ -28,7 +28,8 @@
         settings:searchable="false"/>
 
     <com.android.settingslib.widget.ActionButtonsPreference
-        android:key="header_view" />
+        android:key="header_view"
+        android:order="-999"/>
 
     <com.android.settings.applications.appcompat.RadioWithImagePreference
         android:key="app_default_pref"
diff --git a/src/com/android/settings/SettingsApplication.java b/src/com/android/settings/SettingsApplication.java
index 1a53b83..c0d2445 100644
--- a/src/com/android/settings/SettingsApplication.java
+++ b/src/com/android/settings/SettingsApplication.java
@@ -30,6 +30,7 @@
 import com.android.settings.core.instrumentation.ElapsedTimeUtils;
 import com.android.settings.fuelgauge.BatterySettingsStorage;
 import com.android.settings.homepage.SettingsHomepageActivity;
+import com.android.settings.localepicker.LocaleNotificationDataManager;
 import com.android.settings.overlay.FeatureFactory;
 import com.android.settings.overlay.FeatureFactoryImpl;
 import com.android.settings.spa.SettingsSpaEnvironment;
@@ -56,7 +57,10 @@
     public void onCreate() {
         super.onCreate();
 
-        BackupRestoreStorageManager.getInstance(this).add(new BatterySettingsStorage(this));
+        BackupRestoreStorageManager.getInstance(this)
+                .add(
+                        new BatterySettingsStorage(this),
+                        LocaleNotificationDataManager.getSharedPreferencesStorage(this));
 
         // Add null checking to avoid test case failed.
         if (getApplicationContext() != null) {
diff --git a/src/com/android/settings/SettingsInitialize.java b/src/com/android/settings/SettingsInitialize.java
index c0c0777..297bad7 100644
--- a/src/com/android/settings/SettingsInitialize.java
+++ b/src/com/android/settings/SettingsInitialize.java
@@ -118,7 +118,8 @@
     }
 
     private void privateProfileSetup(Context context, PackageManager pm, UserInfo userInfo) {
-        if (Flags.allowPrivateProfile()) {
+        if (Flags.allowPrivateProfile()
+                && android.multiuser.Flags.enablePrivateSpaceFeatures()) {
             if (userInfo == null || !userInfo.isPrivateProfile()) {
                 return;
             }
diff --git a/src/com/android/settings/Utils.java b/src/com/android/settings/Utils.java
index 108e331..6e36ee3 100644
--- a/src/com/android/settings/Utils.java
+++ b/src/com/android/settings/Utils.java
@@ -1228,6 +1228,7 @@
             UserProperties userProperties = userManager.getUserProperties(userHandle);
             if (userProperties.getShowInSettings() == UserProperties.SHOW_IN_SETTINGS_SEPARATE) {
                 if (Flags.allowPrivateProfile()
+                        && android.multiuser.Flags.enablePrivateSpaceFeatures()
                         && userProperties.getShowInQuietMode()
                         == UserProperties.SHOW_IN_QUIET_MODE_HIDDEN) {
                     if (!userManager.isQuietModeEnabled(userHandle)) {
diff --git a/src/com/android/settings/accessibility/KeyboardVibrationTogglePreferenceController.java b/src/com/android/settings/accessibility/KeyboardVibrationTogglePreferenceController.java
index 869443c..58aa0cc 100644
--- a/src/com/android/settings/accessibility/KeyboardVibrationTogglePreferenceController.java
+++ b/src/com/android/settings/accessibility/KeyboardVibrationTogglePreferenceController.java
@@ -47,7 +47,7 @@
 
 
 /**
- *  A preference controller to turn on/off keyboard vibration state with a single toggle.
+ * A preference controller to turn on/off keyboard vibration state with a single toggle.
  */
 public class KeyboardVibrationTogglePreferenceController extends TogglePreferenceController
         implements DefaultLifecycleObserver {
@@ -110,7 +110,9 @@
     @Override
     public int getAvailabilityStatus() {
         if (Flags.keyboardCategoryEnabled()
-                && mContext.getResources().getBoolean(R.bool.config_keyboard_vibration_supported)) {
+                && mContext.getResources().getBoolean(R.bool.config_keyboard_vibration_supported)
+                && mContext.getResources().getFloat(
+                com.android.internal.R.dimen.config_keyboardHapticFeedbackFixedAmplitude) > 0) {
             return AVAILABLE;
         }
         return UNSUPPORTED_ON_DEVICE;
diff --git a/src/com/android/settings/accessibility/MagnificationOneFingerPanningPreferenceController.java b/src/com/android/settings/accessibility/MagnificationOneFingerPanningPreferenceController.java
new file mode 100644
index 0000000..a2ce948
--- /dev/null
+++ b/src/com/android/settings/accessibility/MagnificationOneFingerPanningPreferenceController.java
@@ -0,0 +1,102 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.settings.accessibility;
+
+import static com.android.settings.accessibility.AccessibilityUtil.State.OFF;
+import static com.android.settings.accessibility.AccessibilityUtil.State.ON;
+
+import android.content.Context;
+import android.content.res.Resources;
+import android.provider.Settings;
+
+import androidx.annotation.Nullable;
+import androidx.annotation.VisibleForTesting;
+import androidx.preference.PreferenceScreen;
+import androidx.preference.TwoStatePreference;
+
+import com.android.server.accessibility.Flags;
+import com.android.settings.R;
+import com.android.settings.core.TogglePreferenceController;
+
+public class MagnificationOneFingerPanningPreferenceController
+        extends TogglePreferenceController {
+    static final String PREF_KEY = Settings.Secure.ACCESSIBILITY_SINGLE_FINGER_PANNING_ENABLED;
+
+    @Nullable
+    private TwoStatePreference mSwitchPreference;
+
+    @VisibleForTesting
+    final boolean mDefaultValue;
+
+    public MagnificationOneFingerPanningPreferenceController(Context context) {
+        super(context, PREF_KEY);
+        boolean defaultValue;
+        try {
+            defaultValue = context.getResources().getBoolean(
+                    com.android.internal.R.bool.config_enable_a11y_magnification_single_panning);
+        } catch (Resources.NotFoundException e) {
+            defaultValue = false;
+        }
+        mDefaultValue = defaultValue;
+    }
+
+    @Override
+    public int getAvailabilityStatus() {
+        return (Flags.enableMagnificationOneFingerPanningGesture())
+                ? AVAILABLE : DISABLED_FOR_USER;
+    }
+
+    @Override
+    public boolean isChecked() {
+        return Settings.Secure.getInt(
+                mContext.getContentResolver(),
+                PREF_KEY,
+                (mDefaultValue) ? ON : OFF) == ON;
+    }
+
+    @Override
+    public boolean setChecked(boolean isChecked) {
+        var toReturn = Settings.Secure.putInt(mContext.getContentResolver(),
+                PREF_KEY,
+                (isChecked ? ON : OFF));
+        if (mSwitchPreference != null) {
+            refreshSummary(mSwitchPreference);
+        }
+        return toReturn;
+    }
+
+    @Override
+    public CharSequence getSummary() {
+        return (isChecked())
+                ? mContext.getString(
+                        R.string.accessibility_magnification_one_finger_panning_summary_on)
+                : mContext.getString(
+                        R.string.accessibility_magnification_one_finger_panning_summary_off);
+    }
+
+    @Override
+    public int getSliceHighlightMenuRes() {
+        return R.string.menu_key_accessibility;
+    }
+
+    @Override
+    public void displayPreference(PreferenceScreen screen) {
+        super.displayPreference(screen);
+        mSwitchPreference = screen.findPreference(getPreferenceKey());
+        refreshSummary(mSwitchPreference);
+    }
+}
diff --git a/src/com/android/settings/accessibility/ToggleScreenMagnificationPreferenceFragment.java b/src/com/android/settings/accessibility/ToggleScreenMagnificationPreferenceFragment.java
index d9baa03..985d45d 100644
--- a/src/com/android/settings/accessibility/ToggleScreenMagnificationPreferenceFragment.java
+++ b/src/com/android/settings/accessibility/ToggleScreenMagnificationPreferenceFragment.java
@@ -200,6 +200,7 @@
         final PreferenceCategory generalCategory = findPreference(KEY_GENERAL_CATEGORY);
         generalCategory.addPreference(mSettingsPreference);
 
+        addOneFingerPanningSetting(generalCategory);
         final MagnificationModePreferenceController magnificationModePreferenceController =
                 new MagnificationModePreferenceController(getContext(),
                         MagnificationModePreferenceController.PREF_KEY);
@@ -283,6 +284,24 @@
         addPreferenceController(alwaysOnPreferenceController);
     }
 
+    private void addOneFingerPanningSetting(PreferenceCategory generalCategory) {
+        if (!Flags.enableMagnificationOneFingerPanningGesture()) {
+            return;
+        }
+
+        var oneFingerPanningPreference = new SwitchPreferenceCompat(getPrefContext());
+        oneFingerPanningPreference.setTitle(
+                R.string.accessibility_magnification_one_finger_panning_title);
+        oneFingerPanningPreference.setKey(
+                MagnificationOneFingerPanningPreferenceController.PREF_KEY);
+        generalCategory.addPreference(oneFingerPanningPreference);
+
+        var oneFingerPanningPreferenceController =
+                new MagnificationOneFingerPanningPreferenceController(getContext());
+        oneFingerPanningPreferenceController.displayPreference(getPreferenceScreen());
+        addPreferenceController(oneFingerPanningPreferenceController);
+    }
+
     private void addJoystickSetting(PreferenceCategory generalCategory) {
         if (!DeviceConfig.getBoolean(
                 DeviceConfig.NAMESPACE_WINDOW_MANAGER,
diff --git a/src/com/android/settings/accounts/AccountPreferenceController.java b/src/com/android/settings/accounts/AccountPreferenceController.java
index 2d862d6..4f03303 100644
--- a/src/com/android/settings/accounts/AccountPreferenceController.java
+++ b/src/com/android/settings/accounts/AccountPreferenceController.java
@@ -311,11 +311,10 @@
                 // should be shown or not.
                 if (((profile.isManagedProfile()
                         && (mType & ProfileSelectFragment.ProfileType.WORK) != 0)
-                        || (Flags.allowPrivateProfile()
-                            && profile.isPrivateProfile()
+                        || (isPrivateProfile(profile)
                             && (mType & ProfileSelectFragment.ProfileType.PRIVATE) != 0)
                         || (!profile.isManagedProfile()
-                            && !(Flags.allowPrivateProfile() && profile.isPrivateProfile())
+                            && !isPrivateProfile(profile)
                             && (mType & ProfileSelectFragment.ProfileType.PERSONAL) != 0))
                         && !(mUm.getUserProperties(profile.getUserHandle())
                             .getShowInQuietMode() == UserProperties.SHOW_IN_QUIET_MODE_HIDDEN
@@ -338,6 +337,12 @@
         mFragment.forceUpdatePreferences();
     }
 
+    private static boolean isPrivateProfile(UserInfo profile) {
+        return Flags.allowPrivateProfile()
+                && android.multiuser.Flags.enablePrivateSpaceFeatures()
+                && profile.isPrivateProfile();
+    }
+
     private void updateProfileUi(final UserInfo userInfo) {
         if (mFragment.getPreferenceManager() == null) {
             return;
diff --git a/src/com/android/settings/applications/appcompat/UserAspectRatioDetails.java b/src/com/android/settings/applications/appcompat/UserAspectRatioDetails.java
index ef054df..cbc5a7b 100644
--- a/src/com/android/settings/applications/appcompat/UserAspectRatioDetails.java
+++ b/src/com/android/settings/applications/appcompat/UserAspectRatioDetails.java
@@ -66,7 +66,8 @@
     private static final String TAG = UserAspectRatioDetails.class.getSimpleName();
 
     private static final String KEY_HEADER_SUMMARY = "app_aspect_ratio_summary";
-    private static final String KEY_HEADER_BUTTONS = "header_view";
+    @VisibleForTesting
+    static final String KEY_HEADER_BUTTONS = "header_view";
 
     private static final String KEY_PREF_HALF_SCREEN = "half_screen_pref";
     private static final String KEY_PREF_DISPLAY_SIZE = "display_size_pref";
@@ -237,6 +238,7 @@
             return;
         }
         pref.setTitle(mUserAspectRatioManager.getAccessibleEntry(aspectRatio, mPackageName));
+        pref.setOrder(getAspectRatioManager().getUserMinAspectRatioOrder(aspectRatio));
         pref.setOnClickListener(this);
         mKeyToAspectRatioMap.put(key, aspectRatio);
         mAspectRatioPreferences.add(pref);
diff --git a/src/com/android/settings/applications/appcompat/UserAspectRatioManager.java b/src/com/android/settings/applications/appcompat/UserAspectRatioManager.java
index 3bf6109..0550a9a 100644
--- a/src/com/android/settings/applications/appcompat/UserAspectRatioManager.java
+++ b/src/com/android/settings/applications/appcompat/UserAspectRatioManager.java
@@ -44,6 +44,7 @@
 import android.os.UserHandle;
 import android.provider.DeviceConfig;
 import android.util.ArrayMap;
+import android.util.SparseIntArray;
 
 import androidx.annotation.NonNull;
 import androidx.annotation.Nullable;
@@ -76,6 +77,7 @@
     /** Apps that have launcher entry defined in manifest */
     private final Map<Integer, String> mUserAspectRatioMap;
     private final Map<Integer, CharSequence> mUserAspectRatioA11yMap;
+    private final SparseIntArray mUserAspectRatioOrder;
 
     public UserAspectRatioManager(@NonNull Context context) {
         this(context, AppGlobals.getPackageManager());
@@ -86,6 +88,7 @@
         mContext = context;
         mIPm = pm;
         mUserAspectRatioA11yMap = new ArrayMap<>();
+        mUserAspectRatioOrder = new SparseIntArray();
         mUserAspectRatioMap = getUserMinAspectRatioMapping();
     }
 
@@ -153,6 +156,14 @@
     }
 
     /**
+     * @return the order of the aspect ratio option corresponding to
+     * config_userAspectRatioOverrideValues
+     */
+    int getUserMinAspectRatioOrder(@PackageManager.UserMinAspectRatio int option) {
+        return mUserAspectRatioOrder.get(option);
+    }
+
+    /**
      * Whether user aspect ratio option is specified in
      * {@link R.array.config_userAspectRatioOverrideValues}
      * and is enabled by device config
@@ -224,7 +235,6 @@
                 && isFullscreenCompatChangeEnabled(pkgName, userId);
     }
 
-    @VisibleForTesting
     boolean isFullscreenCompatChangeEnabled(String pkgName, int userId) {
         return CompatChanges.isChangeEnabled(
                 OVERRIDE_ANY_ORIENTATION_TO_USER, pkgName, UserHandle.of(userId));
@@ -281,6 +291,7 @@
                         mUserAspectRatioA11yMap.put(aspectRatioVal, accessibleSequence);
                     }
                     userMinAspectRatioMap.put(aspectRatioVal, aspectRatioString);
+                    mUserAspectRatioOrder.put(aspectRatioVal, i);
             }
         }
         if (!userMinAspectRatioMap.containsKey(USER_MIN_ASPECT_RATIO_UNSET)) {
@@ -290,6 +301,8 @@
         if (mIsUserMinAspectRatioAppDefaultFlagEnabled) {
             userMinAspectRatioMap.put(USER_MIN_ASPECT_RATIO_APP_DEFAULT,
                     userMinAspectRatioMap.get(USER_MIN_ASPECT_RATIO_UNSET));
+            mUserAspectRatioOrder.put(USER_MIN_ASPECT_RATIO_APP_DEFAULT,
+                    mUserAspectRatioOrder.get(USER_MIN_ASPECT_RATIO_UNSET));
             if (mUserAspectRatioA11yMap.containsKey(USER_MIN_ASPECT_RATIO_UNSET)) {
                 mUserAspectRatioA11yMap.put(USER_MIN_ASPECT_RATIO_APP_DEFAULT,
                         mUserAspectRatioA11yMap.get(USER_MIN_ASPECT_RATIO_UNSET));
diff --git a/src/com/android/settings/applications/specialaccess/deviceadmin/DeviceAdminListPreferenceController.java b/src/com/android/settings/applications/specialaccess/deviceadmin/DeviceAdminListPreferenceController.java
index 640f21d..86c11c2 100644
--- a/src/com/android/settings/applications/specialaccess/deviceadmin/DeviceAdminListPreferenceController.java
+++ b/src/com/android/settings/applications/specialaccess/deviceadmin/DeviceAdminListPreferenceController.java
@@ -167,8 +167,9 @@
     }
 
     private boolean shouldSkipProfile(UserHandle profile) {
-        return  android.os.Flags.allowPrivateProfile()
+        return android.os.Flags.allowPrivateProfile()
                 && android.multiuser.Flags.handleInterleavedSettingsForPrivateSpace()
+                && android.multiuser.Flags.enablePrivateSpaceFeatures()
                 && mUm.isQuietModeEnabled(profile)
                 && mUm.getUserProperties(profile).getShowInQuietMode()
                         == UserProperties.SHOW_IN_QUIET_MODE_HIDDEN;
diff --git a/src/com/android/settings/backup/SettingsBackupHelper.java b/src/com/android/settings/backup/SettingsBackupHelper.java
index 0861af2..556ab72 100644
--- a/src/com/android/settings/backup/SettingsBackupHelper.java
+++ b/src/com/android/settings/backup/SettingsBackupHelper.java
@@ -16,10 +16,8 @@
 
 package com.android.settings.backup;
 
-import static com.android.settings.localepicker.LocaleNotificationDataManager.LOCALE_NOTIFICATION;
 
 import android.app.backup.BackupAgentHelper;
-import android.app.backup.SharedPreferencesBackupHelper;
 
 import com.android.settings.flags.Flags;
 import com.android.settings.onboarding.OnboardingFeatureProvider;
@@ -29,15 +27,12 @@
 
 /** Backup agent for Settings APK */
 public class SettingsBackupHelper extends BackupAgentHelper {
-    private static final String PREF_LOCALE_NOTIFICATION = "localeNotificationSharedPref";
     public static final String SOUND_BACKUP_HELPER = "SoundSettingsBackup";
 
     @Override
     public void onCreate() {
         super.onCreate();
         BackupRestoreStorageManager.getInstance(this).addBackupAgentHelpers(this);
-        addHelper(PREF_LOCALE_NOTIFICATION,
-                new SharedPreferencesBackupHelper(this, LOCALE_NOTIFICATION));
         if (Flags.enableSoundBackup()) {
             OnboardingFeatureProvider onboardingFeatureProvider =
                     FeatureFactory.getFeatureFactory().getOnboardingFeatureProvider();
diff --git a/src/com/android/settings/biometrics/fingerprint/FingerprintEnrollIntroduction.java b/src/com/android/settings/biometrics/fingerprint/FingerprintEnrollIntroduction.java
index f92cfbf..26965fa 100644
--- a/src/com/android/settings/biometrics/fingerprint/FingerprintEnrollIntroduction.java
+++ b/src/com/android/settings/biometrics/fingerprint/FingerprintEnrollIntroduction.java
@@ -340,6 +340,9 @@
             final List<FingerprintSensorPropertiesInternal> props =
                     mFingerprintManager.getSensorPropertiesInternal();
             // This will need to be updated for devices with multiple fingerprint sensors
+            if (props == null || props.isEmpty()) {
+                return R.string.fingerprint_intro_error_unknown;
+            }
             final int max = props.get(0).maxEnrollmentsPerUser;
             final int numEnrolledFingerprints =
                     mFingerprintManager.getEnrolledFingerprints(mUserId).size();
diff --git a/src/com/android/settings/dashboard/profileselector/ProfileSelectFragment.java b/src/com/android/settings/dashboard/profileselector/ProfileSelectFragment.java
index 8279588..e8f407b 100644
--- a/src/com/android/settings/dashboard/profileselector/ProfileSelectFragment.java
+++ b/src/com/android/settings/dashboard/profileselector/ProfileSelectFragment.java
@@ -230,7 +230,8 @@
         if (bundle != null) {
             final int extraTab = bundle.getInt(SettingsActivity.EXTRA_SHOW_FRAGMENT_TAB, -1);
             if (extraTab != -1) {
-                return ((ViewPagerAdapter) mViewPager.getAdapter()).getTabForPosition(extraTab);
+                return ((ViewPagerAdapter) mViewPager.getAdapter())
+                        .getPositionForProfileTab(extraTab);
             }
             final int userId = bundle.getInt(EXTRA_USER_ID, UserHandle.SYSTEM.getIdentifier());
             final boolean isWorkProfile = UserManager.get(activity).isManagedProfile(userId);
@@ -238,7 +239,9 @@
                 return WORK_TAB;
             }
             UserInfo userInfo = UserManager.get(activity).getUserInfo(userId);
-            if (Flags.allowPrivateProfile() && userInfo != null && userInfo.isPrivateProfile()) {
+            if (Flags.allowPrivateProfile()
+                    && android.multiuser.Flags.enablePrivateSpaceFeatures()
+                    && userInfo != null && userInfo.isPrivateProfile()) {
                 return PRIVATE_TAB;
             }
         }
@@ -248,7 +251,9 @@
             return WORK_TAB;
         }
         UserInfo userInfo = UserManager.get(activity).getUserInfo(intentUser);
-        if (Flags.allowPrivateProfile() && userInfo != null && userInfo.isPrivateProfile()) {
+        if (Flags.allowPrivateProfile()
+                && android.multiuser.Flags.enablePrivateSpaceFeatures()
+                && userInfo != null && userInfo.isPrivateProfile()) {
             return PRIVATE_TAB;
         }
 
@@ -259,7 +264,7 @@
         final DevicePolicyManager devicePolicyManager =
                 getContext().getSystemService(DevicePolicyManager.class);
 
-        if (Flags.allowPrivateProfile()) {
+        if (Flags.allowPrivateProfile() && android.multiuser.Flags.enablePrivateSpaceFeatures()) {
             int tabForPosition =
                     ((ViewPagerAdapter) mViewPager.getAdapter()).getTabForPosition(position);
 
@@ -330,7 +335,9 @@
                             ProfileType.WORK,
                             bundle != null ? bundle.deepCopy() : new Bundle(),
                             workFragmentConstructor));
-                } else if (Flags.allowPrivateProfile() && userInfo.isPrivateProfile()) {
+                } else if (Flags.allowPrivateProfile()
+                        && android.multiuser.Flags.enablePrivateSpaceFeatures()
+                        && userInfo.isPrivateProfile()) {
                     if (!privateSpaceInfoProvider.isPrivateSpaceLocked(context)) {
                         fragments.add(createAndGetFragment(
                                 ProfileType.PRIVATE,
@@ -410,7 +417,22 @@
             }
             @ProfileType
             int profileType = mChildFragments[position].getArguments().getInt(EXTRA_PROFILE);
+            return profileTypeToTab(profileType);
+        }
 
+        private int getPositionForProfileTab(int profileTab) {
+            for (int i = 0; i < mChildFragments.length; ++i) {
+                Bundle arguments = mChildFragments[i].getArguments();
+                if (arguments != null
+                        && profileTypeToTab(arguments.getInt(EXTRA_PROFILE)) == profileTab) {
+                    return i;
+                }
+            }
+            Log.e(TAG, "position requested for an unknown profile tab " + profileTab);
+            return 0;
+        }
+
+        private int profileTypeToTab(@ProfileType int profileType) {
             if (profileType == ProfileType.WORK) {
                 return WORK_TAB;
             }
diff --git a/src/com/android/settings/dashboard/profileselector/UserAdapter.java b/src/com/android/settings/dashboard/profileselector/UserAdapter.java
index c9e49f1..40d1a93 100644
--- a/src/com/android/settings/dashboard/profileselector/UserAdapter.java
+++ b/src/com/android/settings/dashboard/profileselector/UserAdapter.java
@@ -87,6 +87,7 @@
                 return resources.getString(WORK_CATEGORY_HEADER,
                         () -> context.getString(com.android.settingslib.R.string.category_work));
             } else if (android.os.Flags.allowPrivateProfile()
+                    && android.multiuser.Flags.enablePrivateSpaceFeatures()
                     && mUserManager.getUserInfo(userId).isPrivateProfile()) {
                 return resources.getString(PRIVATE_CATEGORY_HEADER,
                         () -> context.getString(com.android.settingslib.R.string.category_private));
diff --git a/src/com/android/settings/development/quarantine/OWNERS b/src/com/android/settings/development/quarantine/OWNERS
deleted file mode 100644
index d4de31a..0000000
--- a/src/com/android/settings/development/quarantine/OWNERS
+++ /dev/null
@@ -1,4 +0,0 @@
-# Bug component: 316234
-
-sudheersai@google.com
-yamasani@google.com
\ No newline at end of file
diff --git a/src/com/android/settings/development/quarantine/QuarantinedAppPreference.java b/src/com/android/settings/development/quarantine/QuarantinedAppPreference.java
deleted file mode 100644
index 6ad1f86..0000000
--- a/src/com/android/settings/development/quarantine/QuarantinedAppPreference.java
+++ /dev/null
@@ -1,76 +0,0 @@
-/*
- * Copyright (C) 2023 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.settings.development.quarantine;
-
-import android.content.Context;
-import android.graphics.drawable.Drawable;
-
-import androidx.preference.PreferenceViewHolder;
-
-import com.android.settings.R;
-import com.android.settingslib.applications.AppUtils;
-import com.android.settingslib.applications.ApplicationsState.AppEntry;
-import com.android.settingslib.utils.ThreadUtils;
-import com.android.settingslib.widget.AppSwitchPreference;
-
-public class QuarantinedAppPreference extends AppSwitchPreference {
-    private final AppEntry mEntry;
-    private Drawable mCacheIcon;
-
-    public QuarantinedAppPreference(Context context, AppEntry entry) {
-        super(context);
-        mEntry = entry;
-        mCacheIcon = AppUtils.getIconFromCache(mEntry);
-
-        mEntry.ensureLabel(context);
-        setKey(generateKey(mEntry));
-        if (mCacheIcon != null) {
-            setIcon(mCacheIcon);
-        } else {
-            setIcon(R.drawable.empty_icon);
-        }
-        updateState();
-    }
-
-    static String generateKey(AppEntry entry) {
-        return entry.info.packageName + "|" + entry.info.uid;
-    }
-
-    public AppEntry getEntry() {
-        return mEntry;
-    }
-
-    @Override
-    public void onBindViewHolder(PreferenceViewHolder holder) {
-        if (mCacheIcon == null) {
-            ThreadUtils.postOnBackgroundThread(() -> {
-                final Drawable icon = AppUtils.getIcon(getContext(), mEntry);
-                ThreadUtils.postOnMainThread(() -> {
-                    setIcon(icon);
-                    mCacheIcon = icon;
-                });
-            });
-        }
-        super.onBindViewHolder(holder);
-    }
-
-    void updateState() {
-        setTitle(mEntry.label);
-        setChecked((boolean) mEntry.extraInfo);
-        notifyChanged();
-    }
-}
diff --git a/src/com/android/settings/development/quarantine/QuarantinedAppStateBridge.java b/src/com/android/settings/development/quarantine/QuarantinedAppStateBridge.java
deleted file mode 100644
index 206b922..0000000
--- a/src/com/android/settings/development/quarantine/QuarantinedAppStateBridge.java
+++ /dev/null
@@ -1,61 +0,0 @@
-/*
- * Copyright (C) 2023 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.settings.development.quarantine;
-
-import android.content.Context;
-import android.content.pm.PackageManager;
-import android.os.UserHandle;
-
-import com.android.settings.applications.AppStateBaseBridge;
-import com.android.settingslib.applications.ApplicationsState;
-import com.android.settingslib.applications.ApplicationsState.AppEntry;
-
-import java.util.ArrayList;
-
-public class QuarantinedAppStateBridge extends AppStateBaseBridge {
-    private Context mContext;
-
-    public QuarantinedAppStateBridge(Context context,
-            ApplicationsState appState, Callback callback) {
-        super(appState, callback);
-        mContext = context;
-    }
-
-    @Override
-    protected void loadAllExtraInfo() {
-        final ArrayList<AppEntry> apps = mAppSession.getAllApps();
-        for (int i = 0; i < apps.size(); i++) {
-            final AppEntry app = apps.get(i);
-            updateExtraInfo(app, app.info.packageName, app.info.uid);
-        }
-    }
-
-    @Override
-    protected void updateExtraInfo(AppEntry app, String pkg, int uid) {
-        app.extraInfo = isPackageQuarantined(pkg, uid);
-    }
-
-    private boolean isPackageQuarantined(String pkg, int uid) {
-        final PackageManager pm = mContext.createContextAsUser(
-                UserHandle.getUserHandleForUid(uid), 0).getPackageManager();
-        try {
-            return pm.isPackageQuarantined(pkg);
-        } catch (PackageManager.NameNotFoundException e) {
-            return false;
-        }
-    }
-}
diff --git a/src/com/android/settings/development/quarantine/QuarantinedAppsFragment.java b/src/com/android/settings/development/quarantine/QuarantinedAppsFragment.java
deleted file mode 100644
index 985e962..0000000
--- a/src/com/android/settings/development/quarantine/QuarantinedAppsFragment.java
+++ /dev/null
@@ -1,172 +0,0 @@
-/*
- * Copyright (C) 2023 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.settings.development.quarantine;
-
-import static android.view.MenuItem.SHOW_AS_ACTION_ALWAYS;
-import static android.view.MenuItem.SHOW_AS_ACTION_COLLAPSE_ACTION_VIEW;
-
-import android.app.settings.SettingsEnums;
-import android.os.Bundle;
-import android.text.TextUtils;
-import android.view.Menu;
-import android.view.MenuInflater;
-import android.view.MenuItem;
-import android.widget.SearchView;
-
-import com.android.settings.R;
-import com.android.settings.dashboard.DashboardFragment;
-import com.android.settings.search.BaseSearchIndexProvider;
-import com.android.settingslib.applications.AppIconCacheManager;
-import com.android.settingslib.applications.ApplicationsState;
-import com.android.settingslib.applications.ApplicationsState.AppFilter;
-import com.android.settingslib.search.SearchIndexable;
-
-import com.google.android.material.appbar.AppBarLayout;
-
-// TODO: b/297934650 - Update this to use SPA framework
-@SearchIndexable
-public class QuarantinedAppsFragment extends DashboardFragment implements
-        SearchView.OnQueryTextListener, SearchView.OnCloseListener,
-        MenuItem.OnActionExpandListener {
-    private static final String TAG = "QuarantinedApps";
-
-    private static final int MENU_SEARCH_APPS = Menu.FIRST + 42;
-    private static final int MENU_SHOW_SYSTEM = Menu.FIRST + 43;
-    private static final String EXTRA_SHOW_SYSTEM = "show_system";
-
-    private boolean mShowSystem;
-    private SearchView mSearchView;
-    private String mCurQuery;
-
-    @Override
-    public void onCreate(Bundle icicle) {
-        super.onCreate(icicle);
-        mShowSystem = icicle != null && icicle.getBoolean(EXTRA_SHOW_SYSTEM);
-        use(QuarantinedAppsScreenController.class).setFilter(mCustomFilter);
-        use(QuarantinedAppsScreenController.class).setSession(getSettingsLifecycle());
-    }
-
-    @Override
-    public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
-        mSearchView = new SearchView(getContext());
-        mSearchView.setOnQueryTextListener(this);
-        mSearchView.setOnCloseListener(this);
-        mSearchView.setIconifiedByDefault(true);
-
-        menu.add(Menu.NONE, MENU_SEARCH_APPS, Menu.NONE, R.string.search_settings)
-                .setIcon(R.drawable.ic_find_in_page_24px)
-                .setActionView(mSearchView)
-                .setOnActionExpandListener(this)
-                .setShowAsAction(SHOW_AS_ACTION_ALWAYS | SHOW_AS_ACTION_COLLAPSE_ACTION_VIEW);
-        menu.add(Menu.NONE, MENU_SHOW_SYSTEM, Menu.NONE,
-                mShowSystem ? R.string.menu_hide_system : R.string.menu_show_system);
-        super.onCreateOptionsMenu(menu, inflater);
-    }
-
-    @Override
-    public boolean onOptionsItemSelected(MenuItem item) {
-        if (item.getItemId() == MENU_SHOW_SYSTEM) {
-            mShowSystem = !mShowSystem;
-            item.setTitle(mShowSystem ? R.string.menu_hide_system : R.string.menu_show_system);
-            use(QuarantinedAppsScreenController.class).setFilter(mCustomFilter);
-            use(QuarantinedAppsScreenController.class).rebuild();
-            return true;
-        }
-        return super.onOptionsItemSelected(item);
-    }
-
-    @Override
-    public boolean onQueryTextChange(String newText) {
-        mCurQuery = !TextUtils.isEmpty(newText) ? newText : null;
-        use(QuarantinedAppsScreenController.class).rebuild();
-        return true;
-    }
-
-    @Override
-    public boolean onQueryTextSubmit(String query) {
-        // Don't care about this.
-        return true;
-    }
-
-    @Override
-    public boolean onClose() {
-        if (!TextUtils.isEmpty(mSearchView.getQuery())) {
-            mSearchView.setQuery(null, true);
-        }
-        return true;
-    }
-
-    public final AppFilter mCustomFilter = new AppFilter() {
-        @Override
-        public void init() {
-        }
-
-        @Override
-        public boolean filterApp(ApplicationsState.AppEntry entry) {
-            final AppFilter defaultFilter = mShowSystem ? ApplicationsState.FILTER_ALL_ENABLED
-                    : ApplicationsState.FILTER_DOWNLOADED_AND_LAUNCHER;
-            return defaultFilter.filterApp(entry) && (mCurQuery == null
-                    || entry.label.toLowerCase().contains(mCurQuery.toLowerCase()));
-        }
-    };
-
-    @Override
-    public boolean onMenuItemActionExpand(MenuItem item) {
-        final AppBarLayout mAppBarLayout = getActivity().findViewById(R.id.app_bar);
-        // To prevent a large space on tool bar.
-        mAppBarLayout.setExpanded(false /*expanded*/, false /*animate*/);
-        return true;
-    }
-
-    @Override
-    public boolean onMenuItemActionCollapse(MenuItem item) {
-        final AppBarLayout mAppBarLayout = getActivity().findViewById(R.id.app_bar);
-        // To prevent a large space on tool bar.
-        mAppBarLayout.setExpanded(false /*expanded*/, false /*animate*/);
-        return true;
-    }
-
-    @Override
-    public int getPreferenceScreenResId() {
-        return R.xml.quarantined_apps;
-    }
-
-    @Override
-    public void onSaveInstanceState(Bundle outState) {
-        super.onSaveInstanceState(outState);
-        outState.putBoolean(EXTRA_SHOW_SYSTEM, mShowSystem);
-    }
-
-    @Override
-    protected String getLogTag() {
-        return TAG;
-    }
-
-    @Override
-    public int getMetricsCategory() {
-        return SettingsEnums.QUARANTINED_APPS_DEV_CONTROL;
-    }
-
-    @Override
-    public void onDestroyView() {
-        super.onDestroyView();
-        AppIconCacheManager.getInstance().release();
-    }
-
-    public static final BaseSearchIndexProvider SEARCH_INDEX_DATA_PROVIDER =
-            new BaseSearchIndexProvider(R.xml.quarantined_apps);
-}
diff --git a/src/com/android/settings/development/quarantine/QuarantinedAppsPreferenceController.java b/src/com/android/settings/development/quarantine/QuarantinedAppsPreferenceController.java
deleted file mode 100644
index de3b18b..0000000
--- a/src/com/android/settings/development/quarantine/QuarantinedAppsPreferenceController.java
+++ /dev/null
@@ -1,33 +0,0 @@
-/*
- * Copyright (C) 2023 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.settings.development.quarantine;
-
-import android.content.Context;
-import android.content.pm.Flags;
-
-import com.android.settings.core.BasePreferenceController;
-
-public class QuarantinedAppsPreferenceController extends BasePreferenceController {
-    public QuarantinedAppsPreferenceController(Context context, String preferenceKey) {
-        super(context, preferenceKey);
-    }
-
-    @Override
-    public int getAvailabilityStatus() {
-        return Flags.quarantinedEnabled() ? AVAILABLE : CONDITIONALLY_UNAVAILABLE;
-    }
-}
diff --git a/src/com/android/settings/development/quarantine/QuarantinedAppsScreenController.java b/src/com/android/settings/development/quarantine/QuarantinedAppsScreenController.java
deleted file mode 100644
index 4d4834b..0000000
--- a/src/com/android/settings/development/quarantine/QuarantinedAppsScreenController.java
+++ /dev/null
@@ -1,232 +0,0 @@
-/*
- * Copyright (C) 2023 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.settings.development.quarantine;
-
-import android.app.Application;
-import android.content.Context;
-import android.content.pm.Flags;
-import android.content.pm.PackageManager;
-import android.content.pm.SuspendDialogInfo;
-import android.os.UserHandle;
-
-import androidx.annotation.VisibleForTesting;
-import androidx.preference.Preference;
-import androidx.preference.PreferenceScreen;
-
-import com.android.settings.R;
-import com.android.settings.applications.AppStateBaseBridge;
-import com.android.settings.core.BasePreferenceController;
-import com.android.settingslib.applications.AppUtils;
-import com.android.settingslib.applications.ApplicationsState;
-import com.android.settingslib.applications.ApplicationsState.AppEntry;
-import com.android.settingslib.applications.ApplicationsState.AppFilter;
-import com.android.settingslib.core.lifecycle.Lifecycle;
-import com.android.settingslib.core.lifecycle.LifecycleObserver;
-import com.android.settingslib.core.lifecycle.events.OnDestroy;
-import com.android.settingslib.core.lifecycle.events.OnStart;
-import com.android.settingslib.core.lifecycle.events.OnStop;
-
-import java.util.ArrayList;
-import java.util.Set;
-import java.util.TreeSet;
-
-public class QuarantinedAppsScreenController extends BasePreferenceController implements
-        LifecycleObserver, OnStart, OnStop, OnDestroy,
-        ApplicationsState.Callbacks, Preference.OnPreferenceChangeListener,
-        AppStateBaseBridge.Callback {
-    private final ApplicationsState mApplicationsState;
-    private final QuarantinedAppStateBridge mQuarantinedAppStateBridge;
-    private ApplicationsState.Session mSession;
-    private PreferenceScreen mScreen;
-    private AppFilter mFilter;
-    private boolean mExtraLoaded;
-
-    public QuarantinedAppsScreenController(Context context, String preferenceKey) {
-        super(context, preferenceKey);
-        mApplicationsState = ApplicationsState.getInstance(
-                (Application) context.getApplicationContext());
-        mQuarantinedAppStateBridge = new QuarantinedAppStateBridge(context,
-                mApplicationsState, this);
-    }
-
-    @Override
-    public void onStart() {
-        mQuarantinedAppStateBridge.resume(true /* forceLoadAllApps */);
-    }
-
-    @Override
-    public void onStop() {
-        mQuarantinedAppStateBridge.pause();
-    }
-
-    @Override
-    public void onDestroy() {
-        mQuarantinedAppStateBridge.release();
-    }
-
-    @Override
-    public void displayPreference(PreferenceScreen screen) {
-        super.displayPreference(screen);
-        mScreen = screen;
-    }
-
-    public void setFilter(AppFilter filter) {
-        mFilter = filter;
-    }
-
-    public void setSession(Lifecycle lifecycle) {
-        mSession = mApplicationsState.newSession(this, lifecycle);
-    }
-
-    @Override
-    public void onExtraInfoUpdated() {
-        mExtraLoaded = true;
-        rebuild();
-    }
-
-    public void rebuild() {
-        if (!mExtraLoaded || mSession == null) {
-            return;
-        }
-
-        final ArrayList<AppEntry> apps = mSession.rebuild(mFilter,
-                ApplicationsState.ALPHA_COMPARATOR);
-        if (apps != null) {
-            onRebuildComplete(apps);
-        }
-    }
-
-    @Override
-    public void onRebuildComplete(ArrayList<AppEntry> apps) {
-        if (apps == null) {
-            return;
-        }
-
-        // Preload top visible icons of app list.
-        AppUtils.preloadTopIcons(mContext, apps,
-                mContext.getResources().getInteger(R.integer.config_num_visible_app_icons));
-
-        // Create apps key set for removing useless preferences
-        final Set<String> appsKeySet = new TreeSet<>();
-        // Add or update preferences
-        final int count = apps.size();
-        for (int i = 0; i < count; i++) {
-            final AppEntry entry = apps.get(i);
-            if (!shouldAddPreference(entry)) {
-                continue;
-            }
-            final String prefkey = QuarantinedAppPreference.generateKey(entry);
-            appsKeySet.add(prefkey);
-            QuarantinedAppPreference preference = mScreen.findPreference(prefkey);
-            if (preference == null) {
-                preference = new QuarantinedAppPreference(mScreen.getContext(), entry);
-                preference.setOnPreferenceChangeListener(this);
-                mScreen.addPreference(preference);
-            } else {
-                preference.updateState();
-            }
-            preference.setOrder(i);
-        }
-
-        // Remove useless preferences
-        removeUselessPrefs(appsKeySet);
-    }
-
-    private void removeUselessPrefs(final Set<String> appsKeySet) {
-        final int prefCount = mScreen.getPreferenceCount();
-        String prefKey;
-        if (prefCount > 0) {
-            for (int i = prefCount - 1; i >= 0; i--) {
-                final Preference pref = mScreen.getPreference(i);
-                prefKey = pref.getKey();
-                if (!appsKeySet.isEmpty() && appsKeySet.contains(prefKey)) {
-                    continue;
-                }
-                mScreen.removePreference(pref);
-            }
-        }
-    }
-
-    @VisibleForTesting
-    static boolean shouldAddPreference(AppEntry app) {
-        return app != null && UserHandle.isApp(app.info.uid);
-    }
-
-    @Override
-    public boolean onPreferenceChange(Preference preference, Object newValue) {
-        if (preference instanceof QuarantinedAppPreference) {
-            final QuarantinedAppPreference quarantinedPreference =
-                    (QuarantinedAppPreference) preference;
-            final boolean quarantined = newValue == Boolean.TRUE;
-            setPackageQuarantined(quarantinedPreference.getEntry().info.packageName,
-                    quarantinedPreference.getEntry().info.uid, quarantined);
-            quarantinedPreference.getEntry().extraInfo = quarantined;
-            return true;
-        }
-        return false;
-    }
-
-    private void setPackageQuarantined(String pkg, int uid, boolean quarantined) {
-        final PackageManager pm = mContext.createContextAsUser(
-                UserHandle.getUserHandleForUid(uid), 0).getPackageManager();
-        final SuspendDialogInfo dialogInfo;
-        if (quarantined) {
-            dialogInfo = new SuspendDialogInfo.Builder()
-                    .setNeutralButtonText(R.string.unquarantine_app_button)
-                    .setNeutralButtonAction(SuspendDialogInfo.BUTTON_ACTION_UNSUSPEND)
-                    .build();
-        } else {
-            dialogInfo = null;
-        }
-        pm.setPackagesSuspended(new String[] {pkg}, quarantined, null /* appExtras */,
-                null /* launcherExtras */, dialogInfo,
-                PackageManager.FLAG_SUSPEND_QUARANTINED);
-    }
-
-    @Override
-    public int getAvailabilityStatus() {
-        return Flags.quarantinedEnabled() ? AVAILABLE : CONDITIONALLY_UNAVAILABLE;
-    }
-
-    @Override
-    public void onRunningStateChanged(boolean running) {
-    }
-
-    @Override
-    public void onPackageListChanged() {
-    }
-
-    @Override
-    public void onPackageIconChanged() {
-    }
-
-    @Override
-    public void onPackageSizeChanged(String packageName) {
-    }
-
-    @Override
-    public void onAllSizesComputed() {
-    }
-
-    @Override
-    public void onLauncherInfoChanged() {
-    }
-
-    @Override
-    public void onLoadEntriesCompleted() {
-    }
-}
diff --git a/src/com/android/settings/enterprise/EnterprisePrivacyFeatureProviderImpl.java b/src/com/android/settings/enterprise/EnterprisePrivacyFeatureProviderImpl.java
index 887fc32..ef542a3 100644
--- a/src/com/android/settings/enterprise/EnterprisePrivacyFeatureProviderImpl.java
+++ b/src/com/android/settings/enterprise/EnterprisePrivacyFeatureProviderImpl.java
@@ -257,6 +257,7 @@
     private boolean shouldSkipProfile(UserInfo userInfo) {
         return android.os.Flags.allowPrivateProfile()
                 && android.multiuser.Flags.handleInterleavedSettingsForPrivateSpace()
+                && android.multiuser.Flags.enablePrivateSpaceFeatures()
                 && userInfo.isQuietModeEnabled()
                 && mUm.getUserProperties(userInfo.getUserHandle()).getShowInQuietMode()
                         == UserProperties.SHOW_IN_QUIET_MODE_HIDDEN;
diff --git a/src/com/android/settings/fuelgauge/BatterySettingsStorage.java b/src/com/android/settings/fuelgauge/BatterySettingsStorage.java
index ff3223f..36fa5bb 100644
--- a/src/com/android/settings/fuelgauge/BatterySettingsStorage.java
+++ b/src/com/android/settings/fuelgauge/BatterySettingsStorage.java
@@ -26,7 +26,6 @@
 import android.content.pm.ApplicationInfo;
 import android.os.Build;
 import android.os.IDeviceIdleController;
-import android.os.ParcelFileDescriptor;
 import android.os.RemoteException;
 import android.os.ServiceManager;
 import android.os.UserHandle;
@@ -39,6 +38,7 @@
 
 import com.android.settings.fuelgauge.BatteryOptimizeHistoricalLogEntry.Action;
 import com.android.settings.overlay.FeatureFactory;
+import com.android.settingslib.datastore.BackupCodec;
 import com.android.settingslib.datastore.BackupContext;
 import com.android.settingslib.datastore.BackupRestoreEntity;
 import com.android.settingslib.datastore.BackupRestoreStorageManager;
@@ -159,8 +159,24 @@
         return Arrays.asList(allowlistedApps);
     }
 
+    @NonNull
     @Override
-    public void writeNewStateDescription(@NonNull ParcelFileDescriptor newState) {
+    public OutputStream wrapBackupOutputStream(
+            @NonNull BackupCodec codec, @NonNull OutputStream outputStream) {
+        // not using any codec for backward compatibility
+        return outputStream;
+    }
+
+    @NonNull
+    @Override
+    public InputStream wrapRestoreInputStream(
+            @NonNull BackupCodec codec, @NonNull InputStream inputStream) {
+        // not using any codec for backward compatibility
+        return inputStream;
+    }
+
+    @Override
+    public void onRestoreFinished() {
         BatterySettingsMigrateChecker.verifySaverConfiguration(mApplication);
         performRestoreIfNeeded();
     }
diff --git a/src/com/android/settings/localepicker/LocaleNotificationDataManager.java b/src/com/android/settings/localepicker/LocaleNotificationDataManager.java
index 0e89366..6ec578d 100644
--- a/src/com/android/settings/localepicker/LocaleNotificationDataManager.java
+++ b/src/com/android/settings/localepicker/LocaleNotificationDataManager.java
@@ -19,8 +19,11 @@
 import android.content.Context;
 import android.content.SharedPreferences;
 
+import androidx.annotation.NonNull;
 import androidx.annotation.VisibleForTesting;
 
+import com.android.settingslib.datastore.SharedPreferencesStorage;
+
 import com.google.gson.Gson;
 
 import java.util.HashMap;
@@ -43,6 +46,12 @@
         this.mContext = context;
     }
 
+    /** Returns the underlying {@link SharedPreferences} storage. */
+    @NonNull
+    public static SharedPreferencesStorage getSharedPreferencesStorage(@NonNull Context context) {
+        return new SharedPreferencesStorage(context, LOCALE_NOTIFICATION, Context.MODE_PRIVATE);
+    }
+
     private static SharedPreferences getSharedPreferences(Context context) {
         return context.getSharedPreferences(LOCALE_NOTIFICATION, Context.MODE_PRIVATE);
     }
diff --git a/src/com/android/settings/network/SimOnboardingActivity.kt b/src/com/android/settings/network/SimOnboardingActivity.kt
index 98bb5d7..350f5b8 100644
--- a/src/com/android/settings/network/SimOnboardingActivity.kt
+++ b/src/com/android/settings/network/SimOnboardingActivity.kt
@@ -21,7 +21,6 @@
 import android.os.Bundle
 import android.telephony.SubscriptionManager
 import android.util.Log
-import androidx.activity.compose.setContent
 import androidx.compose.foundation.layout.Column
 import androidx.compose.foundation.layout.Row
 import androidx.compose.foundation.layout.fillMaxWidth
@@ -45,7 +44,6 @@
 import androidx.compose.runtime.Composable
 import androidx.compose.runtime.LaunchedEffect
 import androidx.compose.runtime.MutableState
-import androidx.compose.runtime.mutableIntStateOf
 import androidx.compose.runtime.mutableStateOf
 import androidx.compose.runtime.remember
 import androidx.compose.runtime.rememberCoroutineScope
@@ -67,7 +65,6 @@
 import com.android.settingslib.spa.widget.dialog.AlertDialogButton
 import com.android.settingslib.spa.widget.dialog.getDialogWidth
 import com.android.settingslib.spa.widget.dialog.rememberAlertDialogPresenter
-import com.android.settingslib.spa.widget.editor.SettingsOutlinedTextField
 import com.android.settingslib.spa.widget.ui.SettingsTitle
 import com.android.settingslib.spaprivileged.framework.common.userManager
 import kotlinx.coroutines.CoroutineScope
@@ -83,6 +80,8 @@
     lateinit var showBottomSheet: MutableState<Boolean>
     lateinit var showError: MutableState<ErrorType>
     lateinit var showProgressDialog: MutableState<Boolean>
+    lateinit var showDsdsProgressDialog: MutableState<Boolean>
+    lateinit var showRestartDialog: MutableState<Boolean>
 
     private var switchToEuiccSubscriptionSidecar: SwitchToEuiccSubscriptionSidecar? = null
     private var switchToRemovableSlotSidecar: SwitchToRemovableSlotSidecar? = null
@@ -132,6 +131,12 @@
                 setProgressDialog(false)
             }
 
+            CallbackType.CALLBACK_ENABLE_DSDS-> {
+                scope.launch {
+                    onboardingService.startEnableDsds(this@SimOnboardingActivity)
+                }
+            }
+
             CallbackType.CALLBACK_ONBOARDING_COMPLETE -> {
                 showBottomSheet.value = false
                 setProgressDialog(true)
@@ -179,12 +184,14 @@
         showBottomSheet = remember { mutableStateOf(false) }
         showError = remember { mutableStateOf(ErrorType.ERROR_NONE) }
         showProgressDialog = remember { mutableStateOf(false) }
+        showDsdsProgressDialog = remember { mutableStateOf(false) }
+        showRestartDialog = remember { mutableStateOf(false) }
         scope = rememberCoroutineScope()
 
         registerSidecarReceiverFlow()
 
         ErrorDialogImpl()
-
+        RestartDialogImpl()
         LaunchedEffect(Unit) {
             if (onboardingService.activeSubInfoList.isNotEmpty()) {
                 showBottomSheet.value = true
@@ -196,29 +203,76 @@
             BottomSheetImpl(
                 sheetState = sheetState,
                 nextAction = {
-                    // TODO: if the phone is SS mode and the isDsdsConditionSatisfied is true, then
-                    //  enable the DSDS mode.
-                    //  case#1: the device need the reboot after enabling DSDS. Showing the confirm
-                    //          dialog to user whether reboot device or not.
-                    //  case#2: The device don't need the reboot. Enabling DSDS and then showing
-                    //          the SIM onboarding UI.
-
-                    // case#2
-                    val route = getRoute(onboardingService.targetSubId)
-                    startSpaActivity(route)
+                    if (onboardingService.isDsdsConditionSatisfied()) {
+                        // TODO: if the phone is SS mode and the isDsdsConditionSatisfied is true,
+                        //  then enable the DSDS mode.
+                        //  case#1: the device need the reboot after enabling DSDS. Showing the
+                        //          confirm dialog to user whether reboot device or not.
+                        //  case#2: The device don't need the reboot. Enabling DSDS and then showing
+                        //          the SIM onboarding UI.
+                        if (onboardingService.doesSwitchMultiSimConfigTriggerReboot) {
+                            // case#1
+                            Log.d(TAG, "Device does not support reboot free DSDS.")
+                            showRestartDialog.value = true
+                        } else {
+                            // case#2
+                            Log.d(TAG, "Enable DSDS mode")
+                            showDsdsProgressDialog.value = true
+                            enableMultiSimSidecar?.run(SimOnboardingService.NUM_OF_SIMS_FOR_DSDS)
+                        }
+                    } else {
+                        startSimOnboardingProvider()
+                    }
                 },
                 cancelAction = { finish() },
             )
         }
 
-        if(showProgressDialog.value) {
-            ProgressDialogImpl()
+        if (showProgressDialog.value) {
+            ProgressDialogImpl(
+                stringResource(
+                    R.string.sim_onboarding_progressbar_turning_sim_on,
+                    onboardingService.targetSubInfo?.displayName ?: ""
+                )
+            )
+        }
+        if (showDsdsProgressDialog.value) {
+            ProgressDialogImpl(
+                stringResource(R.string.sim_action_enabling_sim_without_carrier_name)
+            )
+        }
+    }
+    @Composable
+    private fun RestartDialogImpl() {
+        val restartDialogPresenter = rememberAlertDialogPresenter(
+            confirmButton = AlertDialogButton(
+                stringResource(R.string.sim_action_reboot)
+            ) {
+                callbackListener(CallbackType.CALLBACK_ENABLE_DSDS)
+            },
+            dismissButton = AlertDialogButton(
+                stringResource(
+                    R.string.sim_action_restart_dialog_cancel,
+                    onboardingService.targetSubInfo?.displayName ?: "")
+            ) {
+                callbackListener(CallbackType.CALLBACK_ONBOARDING_COMPLETE)
+            },
+            title = stringResource(R.string.sim_action_restart_dialog_title),
+            text = {
+                Text(stringResource(R.string.sim_action_restart_dialog_msg))
+            },
+        )
+
+        if(showRestartDialog.value){
+            LaunchedEffect(Unit) {
+                restartDialogPresenter.open()
+            }
         }
     }
 
     @OptIn(ExperimentalMaterial3Api::class)
     @Composable
-    fun ProgressDialogImpl() {
+    fun ProgressDialogImpl(title: String) {
         // TODO: Create the SPA's ProgressDialog and using SPA's widget
         BasicAlertDialog(
             onDismissRequest = {},
@@ -232,19 +286,14 @@
             ) {
                 Row(
                     modifier = Modifier
-                            .fillMaxWidth()
-                            .padding(SettingsDimension.itemPaddingStart),
+                        .fillMaxWidth()
+                        .padding(SettingsDimension.itemPaddingStart),
                     verticalAlignment = Alignment.CenterVertically
                 ) {
                     CircularProgressIndicator()
                     Column(modifier = Modifier
                             .padding(start = SettingsDimension.itemPaddingStart)) {
-                        SettingsTitle(
-                            stringResource(
-                                R.string.sim_onboarding_progressbar_turning_sim_on,
-                                onboardingService.targetSubInfo?.displayName ?: ""
-                            )
-                        )
+                        SettingsTitle(title)
                     }
                 }
             }
@@ -329,7 +378,7 @@
         Log.e(TAG, "Error while sidecarReceiverFlow", e)
     }.conflate()
 
-    fun startSimSwitching(){
+    fun startSimSwitching() {
         Log.d(TAG, "startSimSwitching:")
 
         var targetSubInfo = onboardingService.targetSubInfo
@@ -376,8 +425,6 @@
                 switchToEuiccSubscriptionSidecar!!.reset()
                 showError.value = ErrorType.ERROR_EUICC_SLOT
                 callbackListener(CallbackType.CALLBACK_ERROR)
-                // TODO: showErrorDialog and using privileged_action_disable_fail_title and
-                //       privileged_action_disable_fail_text
             }
         }
     }
@@ -396,18 +443,19 @@
                 switchToRemovableSlotSidecar!!.reset()
                 showError.value = ErrorType.ERROR_REMOVABLE_SLOT
                 callbackListener(CallbackType.CALLBACK_ERROR)
-                // TODO: showErrorDialog and using sim_action_enable_sim_fail_title and
-                //       sim_action_enable_sim_fail_text
             }
         }
     }
 
     fun handleEnableMultiSimSidecarStateChange() {
+        showDsdsProgressDialog.value = false
         when (enableMultiSimSidecar!!.state) {
             SidecarFragment.State.SUCCESS -> {
                 enableMultiSimSidecar!!.reset()
                 Log.i(TAG, "Successfully switched to DSDS without reboot.")
-                handleEnableSubscriptionAfterEnablingDsds()
+                // refresh data
+                initServiceData(this, onboardingService.targetSubId, callbackListener)
+                startSimOnboardingProvider()
             }
 
             SidecarFragment.State.ERROR -> {
@@ -415,34 +463,14 @@
                 Log.i(TAG, "Failed to switch to DSDS without rebooting.")
                 showError.value = ErrorType.ERROR_ENABLE_DSDS
                 callbackListener(CallbackType.CALLBACK_ERROR)
-                // TODO: showErrorDialog and using dsds_activation_failure_title and
-                //       dsds_activation_failure_body_msg2
             }
         }
     }
 
-    fun handleEnableSubscriptionAfterEnablingDsds() {
-        var targetSubInfo = onboardingService.targetSubInfo
-        if (targetSubInfo?.isEmbedded == true) {
-            Log.i(TAG,
-                    "DSDS enabled, start to enable profile: " + targetSubInfo.getSubscriptionId()
-            )
-            // For eSIM operations, we simply switch to the selected eSIM profile.
-            switchToEuiccSubscriptionSidecar!!.run(
-                targetSubInfo.subscriptionId,
-                UiccSlotUtil.INVALID_PORT_ID,
-                null
-            )
-            return
-        }
-        Log.i(TAG, "DSDS enabled, start to enable pSIM profile.")
-        onboardingService.handleTogglePsimAction()
-        callbackListener(CallbackType.CALLBACK_FINISH)
-    }
-
     @Composable
     fun BottomSheetBody(nextAction: () -> Unit) {
-        Column(horizontalAlignment = Alignment.CenterHorizontally, modifier = Modifier.padding(bottom = SettingsDimension.itemPaddingVertical)) {
+        Column(horizontalAlignment = Alignment.CenterHorizontally,
+            modifier = Modifier.padding(bottom = SettingsDimension.itemPaddingVertical)) {
             Icon(
                 imageVector = Icons.Outlined.SignalCellularAlt,
                 contentDescription = null,
@@ -497,6 +525,11 @@
         onboardingService.initData(targetSubId, context,callback)
     }
 
+    private fun startSimOnboardingProvider() {
+        val route = getRoute(onboardingService.targetSubId)
+        startSpaActivity(route)
+    }
+
     companion object {
         @JvmStatic
         fun startSimOnboardingActivity(
@@ -523,9 +556,10 @@
         enum class CallbackType(val value:Int){
             CALLBACK_ERROR(-1),
             CALLBACK_ONBOARDING_COMPLETE(1),
-            CALLBACK_SETUP_NAME(2),
-            CALLBACK_SETUP_PRIMARY_SIM(3),
-            CALLBACK_FINISH(4)
+            CALLBACK_ENABLE_DSDS(2),
+            CALLBACK_SETUP_NAME(3),
+            CALLBACK_SETUP_PRIMARY_SIM(4),
+            CALLBACK_FINISH(5)
         }
     }
 }
\ No newline at end of file
diff --git a/src/com/android/settings/network/SimOnboardingService.kt b/src/com/android/settings/network/SimOnboardingService.kt
index 962741f..2ec1ad3 100644
--- a/src/com/android/settings/network/SimOnboardingService.kt
+++ b/src/com/android/settings/network/SimOnboardingService.kt
@@ -24,6 +24,7 @@
 import android.telephony.UiccSlotInfo
 import android.util.Log
 import com.android.settings.network.SimOnboardingActivity.Companion.CallbackType
+import com.android.settings.sim.SimActivationNotifier
 import com.android.settings.spa.network.setAutomaticData
 import com.android.settings.spa.network.setDefaultData
 import com.android.settings.spa.network.setDefaultSms
@@ -32,9 +33,6 @@
 import kotlinx.coroutines.Dispatchers
 import kotlinx.coroutines.withContext
 
-private const val TAG = "SimOnboardingService"
-private const val INVALID = SubscriptionManager.INVALID_SUBSCRIPTION_ID
-
 class SimOnboardingService {
     var subscriptionManager:SubscriptionManager? = null
     var telephonyManager:TelephonyManager? = null
@@ -70,7 +68,7 @@
             }
             return  uiccCardInfoList.any { it.isMultipleEnabledProfilesSupported }
         }
-    var isRemovableSimEnabled: Boolean = false
+    var isRemovablePsimProfileEnabled: Boolean = false
         get() {
             if(slotInfoList.isEmpty()) {
                 Log.w(TAG, "UICC Slot info list is empty.")
@@ -78,7 +76,11 @@
             }
             return UiccSlotUtil.isRemovableSimEnabled(slotInfoList)
         }
-
+    var isEsimProfileEnabled: Boolean = false
+        get() {
+            activeSubInfoList.stream().anyMatch { it.isEmbedded }
+            return false
+        }
     var doesTargetSimHaveEsimOperation = false
         get() {
             return targetSubInfo?.isEmbedded ?: false
@@ -109,6 +111,19 @@
             }
             return getActiveModemCount != 0 && activeSubInfoList.size == getActiveModemCount
         }
+    var isMultiSimEnabled = false
+        get() {
+            return getActiveModemCount > 1
+        }
+    var isMultiSimSupported = false
+        get() {
+            return telephonyManager?.isMultiSimSupported == TelephonyManager.MULTISIM_ALLOWED
+        }
+
+    var doesSwitchMultiSimConfigTriggerReboot = false
+        get() {
+            return telephonyManager?.doesSwitchMultiSimConfigTriggerReboot() ?: false
+        }
 
     fun isValid(): Boolean {
         return targetSubId != INVALID
@@ -161,9 +176,10 @@
             targetPrimarySimCalls = SubscriptionManager.getDefaultVoiceSubscriptionId()
             targetPrimarySimTexts = SubscriptionManager.getDefaultSmsSubscriptionId()
             targetPrimarySimMobileData = SubscriptionManager.getDefaultDataSubscriptionId()
+
             Log.d(
                 TAG,"doesTargetSimHaveEsimOperation: $doesTargetSimHaveEsimOperation" +
-                    ", isRemovableSimEnabled: $isRemovableSimEnabled" +
+                    ", isRemovableSimEnabled: $isRemovablePsimProfileEnabled" +
                     ", isMultipleEnabledProfilesSupported: $isMultipleEnabledProfilesSupported" +
                     ", targetPrimarySimCalls: $targetPrimarySimCalls" +
                     ", targetPrimarySimTexts: $targetPrimarySimTexts" +
@@ -261,6 +277,45 @@
         }
     }
 
+    fun isDsdsConditionSatisfied(): Boolean {
+        if (isMultiSimEnabled) {
+            Log.d(
+                TAG,
+                "DSDS is already enabled. Condition not satisfied."
+            )
+            return false
+        }
+        if (!isMultiSimSupported) {
+            Log.d(TAG, "Hardware does not support DSDS.")
+            return false
+        }
+        val isActiveSim = activeSubInfoList.isNotEmpty()
+        if (isMultipleEnabledProfilesSupported && isActiveSim) {
+            Log.d(TAG,
+                "Device supports MEP and eSIM operation and eSIM profile is enabled."
+                        + " DSDS condition satisfied."
+            )
+            return true
+        }
+
+        if (doesTargetSimHaveEsimOperation && isRemovablePsimProfileEnabled) {
+            Log.d(TAG,
+                "eSIM operation and removable PSIM is enabled. DSDS condition satisfied."
+            )
+            return true
+        }
+
+        if (!doesTargetSimHaveEsimOperation && isEsimProfileEnabled) {
+            Log.d(TAG,
+                "Removable SIM operation and eSIM profile is enabled. DSDS condition"
+                        + " satisfied."
+            )
+            return true
+        }
+        Log.d(TAG, "DSDS condition not satisfied.")
+        return false
+    }
+
     fun startActivatingSim(){
         // TODO: start to activate sim
         callback(CallbackType.CALLBACK_FINISH)
@@ -281,30 +336,50 @@
 
     suspend fun startSetupPrimarySim(context: Context) {
         withContext(Dispatchers.Default) {
-            setDefaultVoice(subscriptionManager,targetPrimarySimCalls)
-            setDefaultSms(subscriptionManager,targetPrimarySimTexts)
-            setDefaultData(
-                context,
-                subscriptionManager,
-                null,
-                targetPrimarySimMobileData
-            )
+            if (SubscriptionUtil.getActiveSubscriptions(subscriptionManager).size <= 1) {
+                Log.d(TAG,
+                    "startSetupPrimarySim: number of active subscriptionInfo is less than 2"
+                )
+            } else {
+                setDefaultVoice(subscriptionManager, targetPrimarySimCalls)
+                setDefaultSms(subscriptionManager, targetPrimarySimTexts)
+                setDefaultData(
+                    context,
+                    subscriptionManager,
+                    null,
+                    targetPrimarySimMobileData
+                )
 
-            var nonDds = targetNonDds
-            Log.d(
-                TAG,
-                "setAutomaticData: targetNonDds: $nonDds," +
-                    " targetPrimarySimAutoDataSwitch: $targetPrimarySimAutoDataSwitch"
-            )
-            if (nonDds != SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
-                val telephonyManagerForNonDds: TelephonyManager? =
-                    context.getSystemService(TelephonyManager::class.java)
-                        ?.createForSubscriptionId(nonDds)
-                setAutomaticData(telephonyManagerForNonDds, targetPrimarySimAutoDataSwitch)
+                var nonDds = targetNonDds
+                Log.d(
+                    TAG,
+                    "setAutomaticData: targetNonDds: $nonDds," +
+                            " targetPrimarySimAutoDataSwitch: $targetPrimarySimAutoDataSwitch"
+                )
+                if (nonDds != SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
+                    val telephonyManagerForNonDds: TelephonyManager? =
+                        context.getSystemService(TelephonyManager::class.java)
+                            ?.createForSubscriptionId(nonDds)
+                    setAutomaticData(telephonyManagerForNonDds, targetPrimarySimAutoDataSwitch)
+                }
             }
-
             // no next action, send finish
             callback(CallbackType.CALLBACK_FINISH)
         }
     }
+
+    suspend fun startEnableDsds(context: Context) {
+        withContext(Dispatchers.Default) {
+            Log.d(TAG, "User confirmed reboot to enable DSDS.")
+            SimActivationNotifier.setShowSimSettingsNotification(context, true)
+            telephonyManager?.switchMultiSimConfig(NUM_OF_SIMS_FOR_DSDS)
+            callback(CallbackType.CALLBACK_FINISH)
+        }
+    }
+
+    companion object{
+        private const val TAG = "SimOnboardingService"
+        private const val INVALID = SubscriptionManager.INVALID_SUBSCRIPTION_ID
+        const val NUM_OF_SIMS_FOR_DSDS = 2
+    }
 }
\ No newline at end of file
diff --git a/src/com/android/settings/network/SubscriptionInfoListViewModel.kt b/src/com/android/settings/network/SubscriptionInfoListViewModel.kt
index f682002..df3b8ba 100644
--- a/src/com/android/settings/network/SubscriptionInfoListViewModel.kt
+++ b/src/com/android/settings/network/SubscriptionInfoListViewModel.kt
@@ -20,6 +20,7 @@
 import android.telephony.SubscriptionManager
 import androidx.lifecycle.AndroidViewModel
 import androidx.lifecycle.viewModelScope
+import com.android.settings.network.telephony.getSelectableSubscriptionInfoList
 import com.android.settings.network.telephony.subscriptionsChangedFlow
 import kotlinx.coroutines.Dispatchers
 import kotlinx.coroutines.flow.SharingStarted
@@ -41,10 +42,10 @@
     }.stateIn(scope, SharingStarted.Eagerly, initialValue = emptyList())
 
     /**
-     * Getting the Selectable SubscriptionInfo List from the SubscriptionManager's
+     * Getting the Selectable SubscriptionInfo List from the SubscriptionRepository's
      * getAvailableSubscriptionInfoList
      */
     val selectableSubscriptionInfoListFlow = application.subscriptionsChangedFlow().map {
-        SubscriptionUtil.getSelectableSubscriptionInfoList(application)
+        application.getSelectableSubscriptionInfoList()
     }.stateIn(scope, SharingStarted.Eagerly, initialValue = emptyList())
 }
diff --git a/src/com/android/settings/network/SubscriptionUtil.java b/src/com/android/settings/network/SubscriptionUtil.java
index 83f6c38..497af25 100644
--- a/src/com/android/settings/network/SubscriptionUtil.java
+++ b/src/com/android/settings/network/SubscriptionUtil.java
@@ -50,12 +50,12 @@
 import com.android.settings.network.helper.SubscriptionAnnotation;
 import com.android.settings.network.telephony.DeleteEuiccSubscriptionDialogActivity;
 import com.android.settings.network.telephony.EuiccRacConnectivityDialogActivity;
+import com.android.settings.network.telephony.SubscriptionRepositoryKt;
 import com.android.settings.network.telephony.ToggleSubscriptionDialogActivity;
 
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.Collections;
-import java.util.HashMap;
 import java.util.HashSet;
 import java.util.List;
 import java.util.Locale;
@@ -499,40 +499,7 @@
      * @return list of user selectable subscriptions.
      */
     public static List<SubscriptionInfo> getSelectableSubscriptionInfoList(Context context) {
-        SubscriptionManager subManager = context.getSystemService(SubscriptionManager.class);
-        List<SubscriptionInfo> availableList = subManager.getAvailableSubscriptionInfoList();
-        if (availableList == null) {
-            return null;
-        } else {
-            // Multiple subscriptions in a group should only have one representative.
-            // It should be the current active primary subscription if any, or any
-            // primary subscription.
-            List<SubscriptionInfo> selectableList = new ArrayList<>();
-            Map<ParcelUuid, SubscriptionInfo> groupMap = new HashMap<>();
-
-            for (SubscriptionInfo info : availableList) {
-                // Opportunistic subscriptions are considered invisible
-                // to users so they should never be returned.
-                if (!isSubscriptionVisible(subManager, context, info)) continue;
-
-                ParcelUuid groupUuid = info.getGroupUuid();
-                if (groupUuid == null) {
-                    // Doesn't belong to any group. Add in the list.
-                    selectableList.add(info);
-                } else if (!groupMap.containsKey(groupUuid)
-                        || (groupMap.get(groupUuid).getSimSlotIndex() == INVALID_SIM_SLOT_INDEX
-                        && info.getSimSlotIndex() != INVALID_SIM_SLOT_INDEX)) {
-                    // If it belongs to a group that has never been recorded or it's the current
-                    // active subscription, add it in the list.
-                    selectableList.remove(groupMap.get(groupUuid));
-                    selectableList.add(info);
-                    groupMap.put(groupUuid, info);
-                }
-
-            }
-            Log.d(TAG, "getSelectableSubscriptionInfoList: " + selectableList);
-            return selectableList;
-        }
+        return SubscriptionRepositoryKt.getSelectableSubscriptionInfoList(context);
     }
 
     /**
diff --git a/src/com/android/settings/network/telephony/CellInfoUtil.kt b/src/com/android/settings/network/telephony/CellInfoUtil.kt
index c7b6b24..51f60e7 100644
--- a/src/com/android/settings/network/telephony/CellInfoUtil.kt
+++ b/src/com/android/settings/network/telephony/CellInfoUtil.kt
@@ -82,7 +82,7 @@
      */
     @JvmStatic
     fun cellInfoListToString(cellInfos: List<CellInfo>): String =
-        cellInfos.joinToString { cellInfo -> cellInfo.readableString() }
+        cellInfos.joinToString(System.lineSeparator()) { cellInfo -> cellInfo.readableString() }
 
     /**
      * Convert [CellInfo] to a readable string without sensitive info.
diff --git a/src/com/android/settings/network/telephony/DataUsagePreferenceController.kt b/src/com/android/settings/network/telephony/DataUsagePreferenceController.kt
index 240843d..6d326e0 100644
--- a/src/com/android/settings/network/telephony/DataUsagePreferenceController.kt
+++ b/src/com/android/settings/network/telephony/DataUsagePreferenceController.kt
@@ -33,6 +33,7 @@
 import com.android.settings.datausage.lib.DataUsageLib
 import com.android.settings.datausage.lib.NetworkCycleDataRepository
 import com.android.settings.datausage.lib.NetworkStatsRepository.Companion.AllTimeRange
+import com.android.settingslib.spaprivileged.framework.compose.getPlaceholder
 import kotlinx.coroutines.Dispatchers
 import kotlinx.coroutines.launch
 import kotlinx.coroutines.withContext
@@ -63,6 +64,7 @@
     }
 
     override fun onViewCreated(viewLifecycleOwner: LifecycleOwner) {
+        preference.summary = mContext.getPlaceholder()
         viewLifecycleOwner.lifecycleScope.launch {
             viewLifecycleOwner.repeatOnLifecycle(Lifecycle.State.STARTED) {
                 update()
@@ -113,7 +115,6 @@
         }
 
         val allTimeUsage = repository.queryUsage(AllTimeRange)
-        if (allTimeUsage.usage > 0) return allTimeUsage.getDataUsedString(mContext) to true
-        return null to false
+        return allTimeUsage.getDataUsedString(mContext) to (allTimeUsage.usage > 0)
     }
 }
diff --git a/src/com/android/settings/network/telephony/MobileNetworkSwitchController.java b/src/com/android/settings/network/telephony/MobileNetworkSwitchController.java
deleted file mode 100644
index 20a3d89..0000000
--- a/src/com/android/settings/network/telephony/MobileNetworkSwitchController.java
+++ /dev/null
@@ -1,147 +0,0 @@
-/*
- * Copyright (C) 2019 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.settings.network.telephony;
-
-import static android.telephony.TelephonyManager.CALL_STATE_IDLE;
-
-import static androidx.lifecycle.Lifecycle.Event.ON_PAUSE;
-import static androidx.lifecycle.Lifecycle.Event.ON_RESUME;
-
-import android.content.Context;
-import android.telephony.SubscriptionInfo;
-import android.telephony.SubscriptionManager;
-import android.telephony.TelephonyCallback;
-import android.telephony.TelephonyManager;
-
-import androidx.lifecycle.LifecycleObserver;
-import androidx.lifecycle.OnLifecycleEvent;
-import androidx.preference.PreferenceScreen;
-
-import com.android.settings.core.BasePreferenceController;
-import com.android.settings.network.SubscriptionUtil;
-import com.android.settings.network.SubscriptionsChangeListener;
-import com.android.settings.widget.SettingsMainSwitchPreference;
-
-/** This controls a switch to allow enabling/disabling a mobile network */
-public class MobileNetworkSwitchController extends BasePreferenceController implements
-        SubscriptionsChangeListener.SubscriptionsChangeListenerClient, LifecycleObserver {
-    private static final String TAG = "MobileNetworkSwitchCtrl";
-    private SettingsMainSwitchPreference mSwitchBar;
-    private int mSubId;
-    private SubscriptionsChangeListener mChangeListener;
-    private SubscriptionManager mSubscriptionManager;
-    private TelephonyManager mTelephonyManager;
-    private CallStateTelephonyCallback mCallStateCallback;
-
-    public MobileNetworkSwitchController(Context context, String preferenceKey) {
-        super(context, preferenceKey);
-        mSubId = SubscriptionManager.INVALID_SUBSCRIPTION_ID;
-        mSubscriptionManager = mContext.getSystemService(SubscriptionManager.class);
-        mTelephonyManager = mContext.getSystemService(TelephonyManager.class);
-        mChangeListener = new SubscriptionsChangeListener(context, this);
-    }
-
-    void init(int subId) {
-        mSubId = subId;
-        mTelephonyManager = mTelephonyManager.createForSubscriptionId(mSubId);
-    }
-
-    @OnLifecycleEvent(ON_RESUME)
-    public void onResume() {
-        mChangeListener.start();
-
-        if (mCallStateCallback == null) {
-            mCallStateCallback = new CallStateTelephonyCallback();
-            mTelephonyManager.registerTelephonyCallback(
-                    mContext.getMainExecutor(), mCallStateCallback);
-        }
-        update();
-    }
-
-    @OnLifecycleEvent(ON_PAUSE)
-    public void onPause() {
-        if (mCallStateCallback != null) {
-            mTelephonyManager.unregisterTelephonyCallback(mCallStateCallback);
-            mCallStateCallback = null;
-        }
-        mChangeListener.stop();
-    }
-
-    @Override
-    public void displayPreference(PreferenceScreen screen) {
-        super.displayPreference(screen);
-        mSwitchBar = (SettingsMainSwitchPreference) screen.findPreference(mPreferenceKey);
-
-        mSwitchBar.setOnBeforeCheckedChangeListener((isChecked) -> {
-            // TODO b/135222940: re-evaluate whether to use
-            // mSubscriptionManager#isSubscriptionEnabled
-            if (mSubscriptionManager.isActiveSubscriptionId(mSubId) != isChecked) {
-                SubscriptionUtil.startToggleSubscriptionDialogActivity(mContext, mSubId, isChecked);
-                return true;
-            }
-            return false;
-        });
-        update();
-    }
-
-    private void update() {
-        if (mSwitchBar == null) {
-            return;
-        }
-
-        SubscriptionInfo subInfo = null;
-        for (SubscriptionInfo info : SubscriptionUtil.getAvailableSubscriptions(mContext)) {
-            if (info.getSubscriptionId() == mSubId) {
-                subInfo = info;
-                break;
-            }
-        }
-
-        // For eSIM, we always want the toggle. If telephony stack support disabling a pSIM
-        // directly, we show the toggle.
-        if (subInfo == null || (!subInfo.isEmbedded() && !SubscriptionUtil.showToggleForPhysicalSim(
-                mSubscriptionManager))) {
-            mSwitchBar.hide();
-        } else {
-            mSwitchBar.show();
-            mSwitchBar.setCheckedInternal(mSubscriptionManager.isActiveSubscriptionId(mSubId));
-        }
-    }
-
-    @Override
-    public int getAvailabilityStatus() {
-        return AVAILABLE_UNSEARCHABLE;
-
-    }
-
-    @Override
-    public void onAirplaneModeChanged(boolean airplaneModeEnabled) {
-    }
-
-    @Override
-    public void onSubscriptionsChanged() {
-        update();
-    }
-
-    private class CallStateTelephonyCallback extends TelephonyCallback implements
-            TelephonyCallback.CallStateListener {
-        @Override
-        public void onCallStateChanged(int state) {
-            mSwitchBar.setSwitchBarEnabled(state == CALL_STATE_IDLE);
-        }
-    }
-}
diff --git a/src/com/android/settings/network/telephony/MobileNetworkSwitchController.kt b/src/com/android/settings/network/telephony/MobileNetworkSwitchController.kt
new file mode 100644
index 0000000..dcac74f
--- /dev/null
+++ b/src/com/android/settings/network/telephony/MobileNetworkSwitchController.kt
@@ -0,0 +1,77 @@
+/*
+ * 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 androidx.compose.runtime.Composable
+import androidx.compose.runtime.getValue
+import androidx.compose.runtime.remember
+import androidx.compose.ui.platform.LocalContext
+import androidx.compose.ui.res.stringResource
+import androidx.lifecycle.compose.collectAsStateWithLifecycle
+import com.android.settings.R
+import com.android.settings.network.SubscriptionUtil
+import com.android.settings.spa.preference.ComposePreferenceController
+import com.android.settingslib.spa.widget.preference.MainSwitchPreference
+import com.android.settingslib.spa.widget.preference.SwitchPreferenceModel
+import kotlinx.coroutines.flow.map
+
+class MobileNetworkSwitchController @JvmOverloads constructor(
+    context: Context,
+    preferenceKey: String,
+    private val subscriptionRepository: SubscriptionRepository = SubscriptionRepository(context),
+) : ComposePreferenceController(context, preferenceKey) {
+
+    private var subId = SubscriptionManager.INVALID_SUBSCRIPTION_ID
+
+    override fun getAvailabilityStatus() = AVAILABLE_UNSEARCHABLE
+
+    fun init(subId: Int) {
+        this.subId = subId
+    }
+
+    @Composable
+    override fun Content() {
+        val context = LocalContext.current
+        if (remember { !context.isVisible() }) return
+        val checked by remember {
+            subscriptionRepository.isSubscriptionEnabledFlow(subId)
+        }.collectAsStateWithLifecycle(initialValue = null)
+        val changeable by remember {
+            context.callStateFlow(subId).map { it == TelephonyManager.CALL_STATE_IDLE }
+        }.collectAsStateWithLifecycle(initialValue = true)
+        MainSwitchPreference(model = object : SwitchPreferenceModel {
+            override val title = stringResource(R.string.mobile_network_use_sim_on)
+            override val changeable = { changeable }
+            override val checked = { checked }
+            override val onCheckedChange = { newChecked: Boolean ->
+                SubscriptionUtil.startToggleSubscriptionDialogActivity(mContext, subId, newChecked)
+            }
+        })
+    }
+
+    private fun Context.isVisible(): Boolean {
+        val subInfo = subscriptionRepository.getSelectableSubscriptionInfoList()
+            .firstOrNull { it.subscriptionId == subId }
+            ?: return false
+        // For eSIM, we always want the toggle. If telephony stack support disabling a pSIM
+        // directly, we show the toggle.
+        return subInfo.isEmbedded || requireSubscriptionManager().canDisablePhysicalSubscription()
+    }
+}
diff --git a/src/com/android/settings/network/telephony/NetworkScanHelper.java b/src/com/android/settings/network/telephony/NetworkScanHelper.java
deleted file mode 100644
index 1961329..0000000
--- a/src/com/android/settings/network/telephony/NetworkScanHelper.java
+++ /dev/null
@@ -1,346 +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.annotation.IntDef;
-import android.content.Context;
-import android.telephony.AccessNetworkConstants.AccessNetworkType;
-import android.telephony.CellInfo;
-import android.telephony.NetworkScan;
-import android.telephony.NetworkScanRequest;
-import android.telephony.PhoneCapability;
-import android.telephony.RadioAccessSpecifier;
-import android.telephony.TelephonyManager;
-import android.telephony.TelephonyScanManager;
-import android.util.Log;
-
-import androidx.annotation.VisibleForTesting;
-
-import com.android.internal.telephony.CellNetworkScanResult;
-
-import com.android.settings.R;
-
-import com.google.common.util.concurrent.FutureCallback;
-import com.google.common.util.concurrent.Futures;
-import com.google.common.util.concurrent.ListenableFuture;
-import com.google.common.util.concurrent.MoreExecutors;
-import com.google.common.util.concurrent.SettableFuture;
-
-import java.lang.annotation.Retention;
-import java.lang.annotation.RetentionPolicy;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.List;
-import java.util.concurrent.CancellationException;
-import java.util.concurrent.Executor;
-import java.util.stream.Collectors;
-
-/**
- * A helper class that builds the common interface and performs the network scan for two different
- * network scan APIs.
- */
-public class NetworkScanHelper {
-    public static final String TAG = "NetworkScanHelper";
-
-    /**
-     * Callbacks interface to inform the network scan results.
-     */
-    public interface NetworkScanCallback {
-        /**
-         * Called when the results is returned from {@link TelephonyManager}. This method will be
-         * called at least one time if there is no error occurred during the network scan.
-         *
-         * <p> This method can be called multiple times in one network scan, until
-         * {@link #onComplete()} or {@link #onError(int)} is called.
-         *
-         * @param results
-         */
-        void onResults(List<CellInfo> results);
-
-        /**
-         * Called when the current network scan process is finished. No more
-         * {@link #onResults(List)} will be called for the current network scan after this method is
-         * called.
-         */
-        void onComplete();
-
-        /**
-         * Called when an error occurred during the network scan process.
-         *
-         * <p> There is no more result returned from {@link TelephonyManager} if an error occurred.
-         *
-         * <p> {@link #onComplete()} will not be called if an error occurred.
-         *
-         * @see {@link NetworkScan.ScanErrorCode}
-         */
-        void onError(int errorCode);
-    }
-
-    @Retention(RetentionPolicy.SOURCE)
-    @IntDef({NETWORK_SCAN_TYPE_WAIT_FOR_ALL_RESULTS, NETWORK_SCAN_TYPE_INCREMENTAL_RESULTS})
-    public @interface NetworkQueryType {}
-
-    /**
-     * Performs the network scan using {@link TelephonyManager#getAvailableNetworks()}. The network
-     * scan results won't be returned to the caller until the network scan is completed.
-     *
-     * <p> This is typically used when the modem doesn't support the new network scan api
-     * {@link TelephonyManager#requestNetworkScan(
-     * NetworkScanRequest, Executor, TelephonyScanManager.NetworkScanCallback)}.
-     */
-    public static final int NETWORK_SCAN_TYPE_WAIT_FOR_ALL_RESULTS = 1;
-
-    /**
-     * Performs the network scan using {@link TelephonyManager#requestNetworkScan(
-     * NetworkScanRequest, Executor, TelephonyScanManager.NetworkScanCallback)} The network scan
-     * results will be returned to the caller periodically in a small time window until the network
-     * scan is completed. The complete results should be returned in the last called of
-     * {@link NetworkScanCallback#onResults(List)}.
-     *
-     * <p> This is recommended to be used if modem supports the new network scan api
-     * {@link TelephonyManager#requestNetworkScan(
-     * NetworkScanRequest, Executor, TelephonyScanManager.NetworkScanCallback)}
-     */
-    public static final int NETWORK_SCAN_TYPE_INCREMENTAL_RESULTS = 2;
-
-    /** The constants below are used in the async network scan. */
-    @VisibleForTesting
-    static final boolean INCREMENTAL_RESULTS = true;
-    @VisibleForTesting
-    static final int SEARCH_PERIODICITY_SEC = 5;
-    @VisibleForTesting
-    static final int MAX_SEARCH_TIME_SEC = 300;
-    @VisibleForTesting
-    static final int INCREMENTAL_RESULTS_PERIODICITY_SEC = 3;
-
-    private final NetworkScanCallback mNetworkScanCallback;
-    private final TelephonyManager mTelephonyManager;
-    private final TelephonyScanManager.NetworkScanCallback mInternalNetworkScanCallback;
-    private final Executor mExecutor;
-
-    private int mMaxSearchTimeSec = MAX_SEARCH_TIME_SEC;
-    private NetworkScan mNetworkScanRequester;
-
-    /** Callbacks for sync network scan */
-    private ListenableFuture<List<CellInfo>> mNetworkScanFuture;
-
-    public NetworkScanHelper(TelephonyManager tm, NetworkScanCallback callback, Executor executor) {
-        mTelephonyManager = tm;
-        mNetworkScanCallback = callback;
-        mInternalNetworkScanCallback = new NetworkScanCallbackImpl();
-        mExecutor = executor;
-    }
-
-    public NetworkScanHelper(Context context, TelephonyManager tm, NetworkScanCallback callback,
-            Executor executor) {
-        this(tm, callback, executor);
-        mMaxSearchTimeSec = context.getResources().getInteger(
-                R.integer.config_network_scan_helper_max_search_time_sec);
-    }
-
-    @VisibleForTesting
-    NetworkScanRequest createNetworkScanForPreferredAccessNetworks() {
-        long networkTypeBitmap3gpp = mTelephonyManager.getPreferredNetworkTypeBitmask()
-                & TelephonyManager.NETWORK_STANDARDS_FAMILY_BITMASK_3GPP;
-
-        List<RadioAccessSpecifier> radioAccessSpecifiers = new ArrayList<>();
-        // If the allowed network types are unknown or if they are of the right class, scan for
-        // them; otherwise, skip them to save scan time and prevent users from being shown networks
-        // that they can't connect to.
-        if (networkTypeBitmap3gpp == 0
-                || (networkTypeBitmap3gpp & TelephonyManager.NETWORK_CLASS_BITMASK_2G) != 0) {
-            radioAccessSpecifiers.add(
-                    new RadioAccessSpecifier(AccessNetworkType.GERAN, null, null));
-        }
-        if (networkTypeBitmap3gpp == 0
-                || (networkTypeBitmap3gpp & TelephonyManager.NETWORK_CLASS_BITMASK_3G) != 0) {
-            radioAccessSpecifiers.add(
-                    new RadioAccessSpecifier(AccessNetworkType.UTRAN, null, null));
-        }
-        if (networkTypeBitmap3gpp == 0
-                || (networkTypeBitmap3gpp & TelephonyManager.NETWORK_CLASS_BITMASK_4G) != 0) {
-            radioAccessSpecifiers.add(
-                    new RadioAccessSpecifier(AccessNetworkType.EUTRAN, null, null));
-        }
-        // If a device supports 5G stand-alone then the code below should be re-enabled; however
-        // a device supporting only non-standalone mode cannot perform PLMN selection and camp on
-        // a 5G network, which means that it shouldn't scan for 5G at the expense of battery as
-        // part of the manual network selection process.
-        //
-        if (networkTypeBitmap3gpp == 0
-                || (hasNrSaCapability()
-                && (networkTypeBitmap3gpp & TelephonyManager.NETWORK_CLASS_BITMASK_5G) != 0)) {
-            radioAccessSpecifiers.add(
-                    new RadioAccessSpecifier(AccessNetworkType.NGRAN, null, null));
-            Log.d(TAG, "radioAccessSpecifiers add NGRAN.");
-        }
-
-        return new NetworkScanRequest(
-                NetworkScanRequest.SCAN_TYPE_ONE_SHOT,
-                radioAccessSpecifiers.toArray(
-                        new RadioAccessSpecifier[radioAccessSpecifiers.size()]),
-                SEARCH_PERIODICITY_SEC,
-                mMaxSearchTimeSec,
-                INCREMENTAL_RESULTS,
-                INCREMENTAL_RESULTS_PERIODICITY_SEC,
-                null /* List of PLMN ids (MCC-MNC) */);
-    }
-
-    /**
-     * Performs a network scan for the given type {@code type}.
-     * {@link #NETWORK_SCAN_TYPE_INCREMENTAL_RESULTS} is recommended if modem supports
-     * {@link TelephonyManager#requestNetworkScan(
-     * NetworkScanRequest, Executor, TelephonyScanManager.NetworkScanCallback)}.
-     *
-     * @param type used to tell which network scan API should be used.
-     */
-    public void startNetworkScan(@NetworkQueryType int type) {
-        if (type == NETWORK_SCAN_TYPE_WAIT_FOR_ALL_RESULTS) {
-            mNetworkScanFuture = SettableFuture.create();
-            Futures.addCallback(mNetworkScanFuture, new FutureCallback<List<CellInfo>>() {
-                @Override
-                public void onSuccess(List<CellInfo> result) {
-                    onResults(result);
-                    onComplete();
-                }
-
-                @Override
-                public void onFailure(Throwable t) {
-                    if (t instanceof CancellationException) {
-                        return;
-                    }
-                    int errCode = Integer.parseInt(t.getMessage());
-                    onError(errCode);
-                }
-            }, MoreExecutors.directExecutor());
-            mExecutor.execute(new NetworkScanSyncTask(
-                    mTelephonyManager, (SettableFuture) mNetworkScanFuture));
-        } else if (type == NETWORK_SCAN_TYPE_INCREMENTAL_RESULTS) {
-            if (mNetworkScanRequester != null) {
-                return;
-            }
-            mNetworkScanRequester = mTelephonyManager.requestNetworkScan(
-                    createNetworkScanForPreferredAccessNetworks(),
-                    mExecutor,
-                    mInternalNetworkScanCallback);
-            if (mNetworkScanRequester == null) {
-                onError(NetworkScan.ERROR_RADIO_INTERFACE_ERROR);
-            }
-        }
-    }
-
-    /**
-     * The network scan of type {@link #NETWORK_SCAN_TYPE_WAIT_FOR_ALL_RESULTS} can't be stopped,
-     * however, the result of the current network scan won't be returned to the callback after
-     * calling this method.
-     */
-    public void stopNetworkQuery() {
-        if (mNetworkScanRequester != null) {
-            mNetworkScanRequester.stopScan();
-            mNetworkScanRequester = null;
-        }
-
-        if (mNetworkScanFuture != null) {
-            mNetworkScanFuture.cancel(true /* mayInterruptIfRunning */);
-            mNetworkScanFuture = null;
-        }
-    }
-
-    private void onResults(List<CellInfo> cellInfos) {
-        mNetworkScanCallback.onResults(cellInfos);
-    }
-
-    private void onComplete() {
-        mNetworkScanCallback.onComplete();
-    }
-
-    private void onError(int errCode) {
-        mNetworkScanCallback.onError(errCode);
-    }
-
-    private boolean hasNrSaCapability() {
-        return Arrays.stream(
-                mTelephonyManager.getPhoneCapability().getDeviceNrCapabilities())
-                .anyMatch(i -> i == PhoneCapability.DEVICE_NR_CAPABILITY_SA);
-    }
-
-    /**
-     * Converts the status code of {@link CellNetworkScanResult} to one of the
-     * {@link NetworkScan.ScanErrorCode}.
-     * @param errCode status code from {@link CellNetworkScanResult}.
-     *
-     * @return one of the scan error code from {@link NetworkScan.ScanErrorCode}.
-     */
-    private static int convertToScanErrorCode(int errCode) {
-        switch (errCode) {
-            case CellNetworkScanResult.STATUS_RADIO_NOT_AVAILABLE:
-                return NetworkScan.ERROR_RADIO_INTERFACE_ERROR;
-            case CellNetworkScanResult.STATUS_RADIO_GENERIC_FAILURE:
-            default:
-                return NetworkScan.ERROR_MODEM_ERROR;
-        }
-    }
-
-    private final class NetworkScanCallbackImpl extends TelephonyScanManager.NetworkScanCallback {
-        public void onResults(List<CellInfo> results) {
-            Log.d(TAG, "Async scan onResults() results = "
-                    + CellInfoUtil.cellInfoListToString(results));
-            NetworkScanHelper.this.onResults(results);
-        }
-
-        public void onComplete() {
-            Log.d(TAG, "async scan onComplete()");
-            NetworkScanHelper.this.onComplete();
-        }
-
-        public void onError(@NetworkScan.ScanErrorCode int errCode) {
-            Log.d(TAG, "async scan onError() errorCode = " + errCode);
-            NetworkScanHelper.this.onError(errCode);
-        }
-    }
-
-    private static final class NetworkScanSyncTask implements Runnable {
-        private final SettableFuture<List<CellInfo>> mCallback;
-        private final TelephonyManager mTelephonyManager;
-
-        NetworkScanSyncTask(
-                TelephonyManager telephonyManager, SettableFuture<List<CellInfo>> callback) {
-            mTelephonyManager = telephonyManager;
-            mCallback = callback;
-        }
-
-        @Override
-        public void run() {
-            final CellNetworkScanResult result = mTelephonyManager.getAvailableNetworks();
-            if (result.getStatus() == CellNetworkScanResult.STATUS_SUCCESS) {
-                final List<CellInfo> cellInfos = result.getOperators()
-                        .stream()
-                        .map(operatorInfo
-                                -> CellInfoUtil.convertOperatorInfoToCellInfo(operatorInfo))
-                        .collect(Collectors.toList());
-                Log.d(TAG, "Sync network scan completed, cellInfos = "
-                        + CellInfoUtil.cellInfoListToString(cellInfos));
-                mCallback.set(cellInfos);
-            } else {
-                final Throwable error = new Throwable(
-                        Integer.toString(convertToScanErrorCode(result.getStatus())));
-                mCallback.setException(error);
-                Log.d(TAG, "Sync network scan error, ex = " + error);
-            }
-        }
-    }
-}
diff --git a/src/com/android/settings/network/telephony/NetworkSelectSettings.java b/src/com/android/settings/network/telephony/NetworkSelectSettings.java
index 461930b..eb89d9e 100644
--- a/src/com/android/settings/network/telephony/NetworkSelectSettings.java
+++ b/src/com/android/settings/network/telephony/NetworkSelectSettings.java
@@ -16,7 +16,6 @@
 
 package com.android.settings.network.telephony;
 
-import android.app.Activity;
 import android.app.settings.SettingsEnums;
 import android.content.Context;
 import android.content.Intent;
@@ -39,6 +38,7 @@
 import android.view.View;
 
 import androidx.annotation.Keep;
+import androidx.annotation.NonNull;
 import androidx.annotation.Nullable;
 import androidx.annotation.VisibleForTesting;
 import androidx.preference.Preference;
@@ -48,14 +48,21 @@
 import com.android.internal.telephony.OperatorInfo;
 import com.android.settings.R;
 import com.android.settings.dashboard.DashboardFragment;
+import com.android.settings.network.telephony.scan.NetworkScanRepository;
+import com.android.settings.network.telephony.scan.NetworkScanRepository.NetworkScanCellInfos;
+import com.android.settings.network.telephony.scan.NetworkScanRepository.NetworkScanComplete;
+import com.android.settings.network.telephony.scan.NetworkScanRepository.NetworkScanError;
+import com.android.settings.network.telephony.scan.NetworkScanRepository.NetworkScanResult;
 import com.android.settings.overlay.FeatureFactory;
 import com.android.settingslib.core.instrumentation.MetricsFeatureProvider;
 import com.android.settingslib.utils.ThreadUtils;
 
+import kotlin.Unit;
+import kotlin.jvm.functions.Function1;
+
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.List;
-import java.util.Optional;
 import java.util.concurrent.ExecutorService;
 import java.util.concurrent.Executors;
 import java.util.concurrent.atomic.AtomicBoolean;
@@ -70,12 +77,8 @@
     private static final String TAG = "NetworkSelectSettings";
 
     private static final int EVENT_SET_NETWORK_SELECTION_MANUALLY_DONE = 1;
-    private static final int EVENT_NETWORK_SCAN_RESULTS = 2;
-    private static final int EVENT_NETWORK_SCAN_ERROR = 3;
-    private static final int EVENT_NETWORK_SCAN_COMPLETED = 4;
 
     private static final String PREF_KEY_NETWORK_OPERATORS = "network_operators_preference";
-    private static final int MIN_NUMBER_OF_SCAN_REQUIRED = 2;
 
     private PreferenceCategory mPreferenceCategory;
     @VisibleForTesting
@@ -90,18 +93,14 @@
     private CarrierConfigManager mCarrierConfigManager;
     private List<String> mForbiddenPlmns;
     private boolean mShow4GForLTE = false;
-    private NetworkScanHelper mNetworkScanHelper;
     private final ExecutorService mNetworkScanExecutor = Executors.newFixedThreadPool(1);
     private MetricsFeatureProvider mMetricsFeatureProvider;
-    private boolean mUseNewApi;
-    private long mRequestIdManualNetworkSelect;
-    private long mRequestIdManualNetworkScan;
-    private long mWaitingForNumberOfScanResults;
-    @VisibleForTesting
-    boolean mIsAggregationEnabled = false;
     private CarrierConfigManager.CarrierConfigChangeListener mCarrierConfigChangeListener;
     private AtomicBoolean mShouldFilterOutSatellitePlmn = new AtomicBoolean();
 
+    private NetworkScanRepository mNetworkScanRepository;
+    private boolean mUpdateScanResult = false;
+
     @Override
     public void onCreate(Bundle icicle) {
         super.onCreate(icicle);
@@ -113,7 +112,6 @@
     @Initializer
     protected void onCreateInitialization() {
         Context context = getContext();
-        mUseNewApi = enableNewAutoSelectNetworkUI(context);
         mSubId = getSubId();
 
         mPreferenceCategory = getPreferenceCategory(PREF_KEY_NETWORK_OPERATORS);
@@ -123,8 +121,6 @@
         mTelephonyManager = getTelephonyManager(context, mSubId);
         mSatelliteManager = getSatelliteManager(context);
         mCarrierConfigManager = getCarrierConfigManager(context);
-        mNetworkScanHelper = new NetworkScanHelper(
-                mTelephonyManager, mCallback, mNetworkScanExecutor);
         PersistableBundle bundle = mCarrierConfigManager.getConfigForSubId(mSubId,
                 CarrierConfigManager.KEY_SHOW_4G_FOR_LTE_DATA_ICON_BOOL,
                 CarrierConfigManager.KEY_REMOVE_SATELLITE_PLMN_IN_MANUAL_NETWORK_SCAN_BOOL);
@@ -135,30 +131,13 @@
                 true));
 
         mMetricsFeatureProvider = getMetricsFeatureProvider(context);
-        mIsAggregationEnabled = enableAggregation(context);
-        Log.d(TAG, "init: mUseNewApi:" + mUseNewApi
-                + " ,mIsAggregationEnabled:" + mIsAggregationEnabled + " ,mSubId:" + mSubId);
 
         mCarrierConfigChangeListener =
                 (slotIndex, subId, carrierId, specificCarrierId) -> handleCarrierConfigChanged(
                         subId);
         mCarrierConfigManager.registerCarrierConfigChangeListener(mNetworkScanExecutor,
                 mCarrierConfigChangeListener);
-
-    }
-
-    @Keep
-    @VisibleForTesting
-    protected boolean enableNewAutoSelectNetworkUI(Context context) {
-        return context.getResources().getBoolean(
-                com.android.internal.R.bool.config_enableNewAutoSelectNetworkUI);
-    }
-
-    @Keep
-    @VisibleForTesting
-    protected boolean enableAggregation(Context context) {
-        return context.getResources().getBoolean(
-                R.bool.config_network_selection_list_aggregation_enabled);
+        mNetworkScanRepository = new NetworkScanRepository(context, mSubId);
     }
 
     @Keep
@@ -217,17 +196,42 @@
     }
 
     @Override
-    public void onViewCreated(View view, Bundle savedInstanceState) {
+    public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
         super.onViewCreated(view, savedInstanceState);
 
-        final Activity activity = getActivity();
-        if (activity != null) {
-            mProgressHeader = setPinnedHeaderView(
-                    com.android.settingslib.widget.progressbar.R.layout.progress_header)
-                    .findViewById(com.android.settingslib.widget.progressbar.R.id.progress_bar_animation);
-            setProgressBarVisible(false);
-        }
+        mProgressHeader = setPinnedHeaderView(
+                com.android.settingslib.widget.progressbar.R.layout.progress_header
+        ).findViewById(com.android.settingslib.widget.progressbar.R.id.progress_bar_animation);
         forceUpdateConnectedPreferenceCategory();
+        launchNetworkScan();
+    }
+
+    private void launchNetworkScan() {
+        mNetworkScanRepository.launchNetworkScan(getViewLifecycleOwner(), new Function1<>() {
+            @Override
+            public Unit invoke(@NonNull NetworkScanResult networkScanResult) {
+                if (!mUpdateScanResult) {
+                    // Not update UI if not in scan mode.
+                    return Unit.INSTANCE;
+                }
+                if (networkScanResult instanceof NetworkScanCellInfos networkScanCellInfos) {
+                    scanResultHandler(networkScanCellInfos.getCellInfos());
+                    return Unit.INSTANCE;
+                }
+                if (!isPreferenceScreenEnabled()) {
+                    clearPreferenceSummary();
+                    enablePreferenceScreen(true);
+                } else if (networkScanResult instanceof NetworkScanComplete
+                        && mCellInfoList == null) {
+                    // In case the scan timeout before getting any results
+                    addMessagePreference(R.string.empty_networks_list);
+                } else if (networkScanResult instanceof NetworkScanError) {
+                    addMessagePreference(R.string.network_query_error);
+                }
+
+                return Unit.INSTANCE;
+            }
+        });
     }
 
     @Override
@@ -235,12 +239,8 @@
         super.onStart();
 
         updateForbiddenPlmns();
-        if (isProgressBarVisible()) {
-            return;
-        }
-        if (mWaitingForNumberOfScanResults <= 0) {
-            startNetworkQuery();
-        }
+        setProgressBarVisible(true);
+        mUpdateScanResult = true;
     }
 
     /**
@@ -256,14 +256,6 @@
     }
 
     @Override
-    public void onStop() {
-        if (mWaitingForNumberOfScanResults <= 0) {
-            stopNetworkQuery();
-        }
-        super.onStop();
-    }
-
-    @Override
     public boolean onPreferenceTreeClick(Preference preference) {
         if (preference == mSelectedPreference) {
             Log.d(TAG, "onPreferenceTreeClick: preference is mSelectedPreference. Do nothing.");
@@ -274,7 +266,7 @@
             return false;
         }
 
-        stopNetworkQuery();
+        mUpdateScanResult = false;
 
         // Refresh the last selected item in case users reselect network.
         clearPreferenceSummary();
@@ -293,8 +285,6 @@
         // Disable the screen until network is manually set
         enablePreferenceScreen(false);
 
-        mRequestIdManualNetworkSelect = getNewRequestId();
-        mWaitingForNumberOfScanResults = MIN_NUMBER_OF_SCAN_REQUIRED;
         final OperatorInfo operator = mSelectedPreference.getOperatorInfo();
         ThreadUtils.postOnBackgroundThread(() -> {
             final Message msg = mHandler.obtainMessage(
@@ -328,7 +318,6 @@
             switch (msg.what) {
                 case EVENT_SET_NETWORK_SELECTION_MANUALLY_DONE:
                     final boolean isSucceed = (boolean) msg.obj;
-                    stopNetworkQuery();
                     setProgressBarVisible(false);
                     enablePreferenceScreen(true);
 
@@ -340,86 +329,15 @@
                         Log.e(TAG, "No preference to update!");
                     }
                     break;
-                case EVENT_NETWORK_SCAN_RESULTS:
-                    scanResultHandler((List<CellInfo>) msg.obj);
-                    break;
-
-                case EVENT_NETWORK_SCAN_ERROR:
-                    stopNetworkQuery();
-                    Log.i(TAG, "Network scan failure " + msg.arg1 + ":"
-                            + " scan request 0x" + Long.toHexString(mRequestIdManualNetworkScan)
-                            + ", waiting for scan results = " + mWaitingForNumberOfScanResults
-                            + ", select request 0x"
-                            + Long.toHexString(mRequestIdManualNetworkSelect));
-                    if (mRequestIdManualNetworkScan < mRequestIdManualNetworkSelect) {
-                        break;
-                    }
-                    if (!isPreferenceScreenEnabled()) {
-                        clearPreferenceSummary();
-                        enablePreferenceScreen(true);
-                    } else {
-                        addMessagePreference(R.string.network_query_error);
-                    }
-                    break;
-
-                case EVENT_NETWORK_SCAN_COMPLETED:
-                    stopNetworkQuery();
-                    Log.d(TAG, "Network scan complete:"
-                            + " scan request 0x" + Long.toHexString(mRequestIdManualNetworkScan)
-                            + ", waiting for scan results = " + mWaitingForNumberOfScanResults
-                            + ", select request 0x"
-                            + Long.toHexString(mRequestIdManualNetworkSelect));
-                    if (mRequestIdManualNetworkScan < mRequestIdManualNetworkSelect) {
-                        break;
-                    }
-                    if (!isPreferenceScreenEnabled()) {
-                        clearPreferenceSummary();
-                        enablePreferenceScreen(true);
-                    } else if (mCellInfoList == null) {
-                        // In case the scan timeout before getting any results
-                        addMessagePreference(R.string.empty_networks_list);
-                    }
-                    break;
             }
-            return;
         }
     };
 
-    @VisibleForTesting
-    List<CellInfo> doAggregation(List<CellInfo> cellInfoListInput) {
-        if (!mIsAggregationEnabled) {
-            Log.d(TAG, "no aggregation");
-            return new ArrayList<>(cellInfoListInput);
-        }
-        ArrayList<CellInfo> aggregatedList = new ArrayList<>();
-        for (CellInfo cellInfo : cellInfoListInput) {
-            String plmn = CellInfoUtil.getNetworkTitle(cellInfo.getCellIdentity());
-            Class className = cellInfo.getClass();
-
-            Optional<CellInfo> itemInTheList = aggregatedList.stream().filter(
-                    item -> {
-                        String itemPlmn = CellInfoUtil.getNetworkTitle(item.getCellIdentity());
-                        return itemPlmn.equals(plmn) && item.getClass().equals(className);
-                    })
-                    .findFirst();
-            if (itemInTheList.isPresent()) {
-                if (cellInfo.isRegistered() && !itemInTheList.get().isRegistered()) {
-                    // Adding the registered cellinfo item into list. If there are two registered
-                    // cellinfo items, then select first one from source list.
-                    aggregatedList.set(aggregatedList.indexOf(itemInTheList.get()), cellInfo);
-                }
-                continue;
-            }
-            aggregatedList.add(cellInfo);
-        }
-
-        return filterOutSatellitePlmn(aggregatedList);
-    }
-
     /* We do not want to expose carrier satellite plmns to the user when manually scan the
        cellular network. Therefore, it is needed to filter out satellite plmns from current cell
        info list  */
-    private List<CellInfo> filterOutSatellitePlmn(List<CellInfo> cellInfoList) {
+    @VisibleForTesting
+    List<CellInfo> filterOutSatellitePlmn(List<CellInfo> cellInfoList) {
         List<String> aggregatedSatellitePlmn = getSatellitePlmnsForCarrierWrapper();
         if (!mShouldFilterOutSatellitePlmn.get() || aggregatedSatellitePlmn.isEmpty()) {
             return cellInfoList;
@@ -451,39 +369,10 @@
         }
     }
 
-    private final NetworkScanHelper.NetworkScanCallback mCallback =
-            new NetworkScanHelper.NetworkScanCallback() {
-                public void onResults(List<CellInfo> results) {
-                    final Message msg = mHandler.obtainMessage(EVENT_NETWORK_SCAN_RESULTS, results);
-                    msg.sendToTarget();
-                }
-
-                public void onComplete() {
-                    final Message msg = mHandler.obtainMessage(EVENT_NETWORK_SCAN_COMPLETED);
-                    msg.sendToTarget();
-                }
-
-                public void onError(int error) {
-                    final Message msg = mHandler.obtainMessage(EVENT_NETWORK_SCAN_ERROR, error,
-                            0 /* arg2 */);
-                    msg.sendToTarget();
-                }
-            };
-
     @Keep
     @VisibleForTesting
     protected void scanResultHandler(List<CellInfo> results) {
-        if (mRequestIdManualNetworkScan < mRequestIdManualNetworkSelect) {
-            Log.d(TAG, "CellInfoList (drop): "
-                    + CellInfoUtil.cellInfoListToString(new ArrayList<>(results)));
-            return;
-        }
-        mWaitingForNumberOfScanResults--;
-        if ((mWaitingForNumberOfScanResults <= 0) && (!isResumed())) {
-            stopNetworkQuery();
-        }
-
-        mCellInfoList = doAggregation(results);
+        mCellInfoList = filterOutSatellitePlmn(results);
         Log.d(TAG, "CellInfoList: " + CellInfoUtil.cellInfoListToString(mCellInfoList));
         if (mCellInfoList != null && mCellInfoList.size() != 0) {
             final NetworkOperatorPreference connectedPref = updateAllPreferenceCategory();
@@ -642,11 +531,6 @@
         }
     }
 
-    private long getNewRequestId() {
-        return Math.max(mRequestIdManualNetworkSelect,
-                mRequestIdManualNetworkScan) + 1;
-    }
-
     private boolean isProgressBarVisible() {
         if (mProgressHeader == null) {
             return false;
@@ -667,29 +551,8 @@
         mPreferenceCategory.addPreference(mStatusMessagePreference);
     }
 
-    private void startNetworkQuery() {
-        setProgressBarVisible(true);
-        if (mNetworkScanHelper != null) {
-            mRequestIdManualNetworkScan = getNewRequestId();
-            mWaitingForNumberOfScanResults = MIN_NUMBER_OF_SCAN_REQUIRED;
-            mNetworkScanHelper.startNetworkScan(
-                    mUseNewApi
-                            ? NetworkScanHelper.NETWORK_SCAN_TYPE_INCREMENTAL_RESULTS
-                            : NetworkScanHelper.NETWORK_SCAN_TYPE_WAIT_FOR_ALL_RESULTS);
-        }
-    }
-
-    private void stopNetworkQuery() {
-        setProgressBarVisible(false);
-        if (mNetworkScanHelper != null) {
-            mWaitingForNumberOfScanResults = 0;
-            mNetworkScanHelper.stopNetworkQuery();
-        }
-    }
-
     @Override
     public void onDestroy() {
-        stopNetworkQuery();
         mNetworkScanExecutor.shutdown();
         super.onDestroy();
     }
diff --git a/src/com/android/settings/network/telephony/SubscriptionRepository.kt b/src/com/android/settings/network/telephony/SubscriptionRepository.kt
index e44b577..1da6a96 100644
--- a/src/com/android/settings/network/telephony/SubscriptionRepository.kt
+++ b/src/com/android/settings/network/telephony/SubscriptionRepository.kt
@@ -32,9 +32,24 @@
 
 private const val TAG = "SubscriptionRepository"
 
-fun Context.isSubscriptionEnabledFlow(subId: Int) = subscriptionsChangedFlow().map {
-    val subscriptionManager = getSystemService(SubscriptionManager::class.java)
+class SubscriptionRepository(private val context: Context) {
+    /**
+     * Return a list of subscriptions that are available and visible to the user.
+     *
+     * @return list of user selectable subscriptions.
+     */
+    fun getSelectableSubscriptionInfoList(): List<SubscriptionInfo> =
+        context.getSelectableSubscriptionInfoList()
 
+    fun isSubscriptionEnabledFlow(subId: Int) = context.isSubscriptionEnabledFlow(subId)
+}
+
+val Context.subscriptionManager: SubscriptionManager?
+    get() = getSystemService(SubscriptionManager::class.java)
+
+fun Context.requireSubscriptionManager(): SubscriptionManager = subscriptionManager!!
+
+fun Context.isSubscriptionEnabledFlow(subId: Int) = subscriptionsChangedFlow().map {
     subscriptionManager?.isSubscriptionEnabled(subId) ?: false
 }.flowOn(Dispatchers.Default)
 
@@ -43,7 +58,7 @@
 }.flowOn(Dispatchers.Default)
 
 fun Context.subscriptionsChangedFlow() = callbackFlow {
-    val subscriptionManager = getSystemService(SubscriptionManager::class.java)!!
+    val subscriptionManager = requireSubscriptionManager()
 
     val listener = object : SubscriptionManager.OnSubscriptionsChangedListener() {
         override fun onSubscriptionsChanged() {
@@ -58,3 +73,35 @@
 
     awaitClose { subscriptionManager.removeOnSubscriptionsChangedListener(listener) }
 }.conflate().onEach { Log.d(TAG, "subscriptions changed") }.flowOn(Dispatchers.Default)
+
+/**
+ * Return a list of subscriptions that are available and visible to the user.
+ *
+ * @return list of user selectable subscriptions.
+ */
+fun Context.getSelectableSubscriptionInfoList(): List<SubscriptionInfo> {
+    val subscriptionManager = requireSubscriptionManager()
+    val availableList = subscriptionManager.getAvailableSubscriptionInfoList() ?: return emptyList()
+    val visibleList = availableList.filter { subInfo ->
+        // Opportunistic subscriptions are considered invisible
+        // to users so they should never be returned.
+        SubscriptionUtil.isSubscriptionVisible(subscriptionManager, this, subInfo)
+    }
+    // Multiple subscriptions in a group should only have one representative.
+    // It should be the current active primary subscription if any, or any primary subscription.
+    val groupUuidToSelectedIdMap = visibleList
+        .groupBy { it.groupUuid }
+        .mapValues { (_, subInfos) ->
+            subInfos.filter { it.simSlotIndex != SubscriptionManager.INVALID_SIM_SLOT_INDEX }
+                .ifEmpty { subInfos }
+                .minOf { it.subscriptionId }
+        }
+
+    return visibleList
+        .filter { subInfo ->
+            val groupUuid = subInfo.groupUuid ?: return@filter true
+            groupUuidToSelectedIdMap[groupUuid] == subInfo.subscriptionId
+        }
+        .sortedBy { it.subscriptionId }
+        .also { Log.d(TAG, "getSelectableSubscriptionInfoList: $it") }
+}
diff --git a/src/com/android/settings/network/telephony/WifiCallingPreferenceController.kt b/src/com/android/settings/network/telephony/WifiCallingPreferenceController.kt
index b0ea6a6..0ee1d87 100644
--- a/src/com/android/settings/network/telephony/WifiCallingPreferenceController.kt
+++ b/src/com/android/settings/network/telephony/WifiCallingPreferenceController.kt
@@ -22,10 +22,7 @@
 import android.telephony.SubscriptionManager
 import android.telephony.TelephonyManager
 import android.telephony.ims.ImsMmTelManager
-import androidx.lifecycle.Lifecycle
 import androidx.lifecycle.LifecycleOwner
-import androidx.lifecycle.lifecycleScope
-import androidx.lifecycle.repeatOnLifecycle
 import androidx.preference.Preference
 import androidx.preference.PreferenceScreen
 import com.android.settings.R
@@ -33,7 +30,6 @@
 import com.android.settingslib.spa.framework.util.collectLatestWithLifecycle
 import kotlinx.coroutines.Dispatchers
 import kotlinx.coroutines.flow.Flow
-import kotlinx.coroutines.launch
 import kotlinx.coroutines.withContext
 
 /**
@@ -81,17 +77,12 @@
 
     override fun onViewCreated(viewLifecycleOwner: LifecycleOwner) {
         wifiCallingRepositoryFactory(mSubId).wifiCallingReadyFlow()
-            .collectLatestWithLifecycle(viewLifecycleOwner) {
-                preference.isVisible = it
-                callingPreferenceCategoryController.updateChildVisible(preferenceKey, it)
+            .collectLatestWithLifecycle(viewLifecycleOwner) { isReady ->
+                preference.isVisible = isReady
+                callingPreferenceCategoryController.updateChildVisible(preferenceKey, isReady)
+                if (isReady) update()
             }
 
-        viewLifecycleOwner.lifecycleScope.launch {
-            viewLifecycleOwner.repeatOnLifecycle(Lifecycle.State.STARTED) {
-                update()
-            }
-        }
-
         callStateFlowFactory(mSubId).collectLatestWithLifecycle(viewLifecycleOwner) {
             preference.isEnabled = (it == TelephonyManager.CALL_STATE_IDLE)
         }
diff --git a/src/com/android/settings/network/telephony/scan/NetworkScanRepository.kt b/src/com/android/settings/network/telephony/scan/NetworkScanRepository.kt
new file mode 100644
index 0000000..2067b8c
--- /dev/null
+++ b/src/com/android/settings/network/telephony/scan/NetworkScanRepository.kt
@@ -0,0 +1,167 @@
+/*
+ * 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.scan
+
+import android.content.Context
+import android.telephony.AccessNetworkConstants.AccessNetworkType
+import android.telephony.CellInfo
+import android.telephony.NetworkScanRequest
+import android.telephony.PhoneCapability
+import android.telephony.RadioAccessSpecifier
+import android.telephony.TelephonyManager
+import android.telephony.TelephonyScanManager
+import android.util.Log
+import androidx.annotation.VisibleForTesting
+import androidx.lifecycle.LifecycleOwner
+import com.android.settings.network.telephony.CellInfoUtil
+import com.android.settings.network.telephony.CellInfoUtil.getNetworkTitle
+import com.android.settingslib.spa.framework.util.collectLatestWithLifecycle
+import kotlinx.coroutines.Dispatchers
+import kotlinx.coroutines.asExecutor
+import kotlinx.coroutines.channels.awaitClose
+import kotlinx.coroutines.flow.Flow
+import kotlinx.coroutines.flow.callbackFlow
+import kotlinx.coroutines.flow.flowOn
+
+class NetworkScanRepository(context: Context, subId: Int) {
+    sealed interface NetworkScanResult
+
+    data class NetworkScanCellInfos(val cellInfos: List<CellInfo>) : NetworkScanResult
+    data object NetworkScanComplete : NetworkScanResult
+    data class NetworkScanError(val error: Int) : NetworkScanResult
+
+    private val telephonyManager =
+        context.getSystemService(TelephonyManager::class.java)!!.createForSubscriptionId(subId)
+
+    /** TODO: Move this to UI layer, when UI layer migrated to Kotlin. */
+    fun launchNetworkScan(lifecycleOwner: LifecycleOwner, onResult: (NetworkScanResult) -> Unit) {
+        networkScanFlow().collectLatestWithLifecycle(lifecycleOwner, action = onResult)
+    }
+
+    data class CellInfoScanKey(
+        val title: String?,
+        val className: String,
+        val isRegistered: Boolean,
+    ) {
+        constructor(cellInfo: CellInfo) : this(
+            title = cellInfo.cellIdentity.getNetworkTitle(),
+            className = cellInfo.javaClass.name,
+            isRegistered = cellInfo.isRegistered,
+        )
+    }
+
+    fun networkScanFlow(): Flow<NetworkScanResult> = callbackFlow {
+        val callback = object : TelephonyScanManager.NetworkScanCallback() {
+            override fun onResults(results: List<CellInfo>) {
+                val cellInfos = results.distinctBy { CellInfoScanKey(it) }
+                trySend(NetworkScanCellInfos(cellInfos))
+                Log.d(TAG, "CellInfoList: ${CellInfoUtil.cellInfoListToString(cellInfos)}")
+            }
+
+            override fun onComplete() {
+                trySend(NetworkScanComplete)
+                close()
+                Log.d(TAG, "onComplete")
+            }
+
+            override fun onError(error: Int) {
+                trySend(NetworkScanError(error))
+                close()
+                Log.d(TAG, "onError: $error")
+            }
+        }
+
+        val networkScan = telephonyManager.requestNetworkScan(
+            createNetworkScan(),
+            Dispatchers.Default.asExecutor(),
+            callback,
+        )
+
+        awaitClose { networkScan.stopScan() }
+    }.flowOn(Dispatchers.Default)
+
+    /** Create network scan for allowed network types. */
+    private fun createNetworkScan(): NetworkScanRequest {
+        val allowedNetworkTypes = getAllowedNetworkTypes()
+        Log.d(TAG, "createNetworkScan: allowedNetworkTypes = $allowedNetworkTypes")
+        val radioAccessSpecifiers = allowedNetworkTypes
+            .map { RadioAccessSpecifier(it, null, null) }
+            .toTypedArray()
+        return NetworkScanRequest(
+            NetworkScanRequest.SCAN_TYPE_ONE_SHOT,
+            radioAccessSpecifiers,
+            NetworkScanRequest.MIN_SEARCH_PERIODICITY_SEC, // one shot, not used
+            MAX_SEARCH_TIME_SEC,
+            true,
+            INCREMENTAL_RESULTS_PERIODICITY_SEC,
+            null,
+        )
+    }
+
+    private fun getAllowedNetworkTypes(): List<Int> {
+        val networkTypeBitmap3gpp: Long =
+            telephonyManager.getAllowedNetworkTypesBitmask() and
+                TelephonyManager.NETWORK_STANDARDS_FAMILY_BITMASK_3GPP
+        return buildList {
+            // If the allowed network types are unknown or if they are of the right class, scan for
+            // them; otherwise, skip them to save scan time and prevent users from being shown
+            // networks that they can't connect to.
+            if (networkTypeBitmap3gpp == 0L
+                || networkTypeBitmap3gpp and TelephonyManager.NETWORK_CLASS_BITMASK_2G != 0L
+            ) {
+                add(AccessNetworkType.GERAN)
+            }
+            if (networkTypeBitmap3gpp == 0L
+                || networkTypeBitmap3gpp and TelephonyManager.NETWORK_CLASS_BITMASK_3G != 0L
+            ) {
+                add(AccessNetworkType.UTRAN)
+            }
+            if (networkTypeBitmap3gpp == 0L
+                || networkTypeBitmap3gpp and TelephonyManager.NETWORK_CLASS_BITMASK_4G != 0L
+            ) {
+                add(AccessNetworkType.EUTRAN)
+            }
+            // If a device supports 5G stand-alone then the code below should be re-enabled; however
+            // a device supporting only non-standalone mode cannot perform PLMN selection and camp
+            // on a 5G network, which means that it shouldn't scan for 5G at the expense of battery
+            // as part of the manual network selection process.
+            //
+            if (networkTypeBitmap3gpp == 0L
+                || (networkTypeBitmap3gpp and TelephonyManager.NETWORK_CLASS_BITMASK_5G != 0L &&
+                    hasNrSaCapability())
+            ) {
+                add(AccessNetworkType.NGRAN)
+                Log.d(TAG, "radioAccessSpecifiers add NGRAN.")
+            }
+        }
+    }
+
+    private fun hasNrSaCapability(): Boolean {
+        val phoneCapability = telephonyManager.getPhoneCapability()
+        return PhoneCapability.DEVICE_NR_CAPABILITY_SA in phoneCapability.deviceNrCapabilities
+    }
+
+    companion object {
+        private const val TAG = "NetworkScanRepository"
+
+        @VisibleForTesting
+        val MAX_SEARCH_TIME_SEC = 300
+
+        @VisibleForTesting
+        val INCREMENTAL_RESULTS_PERIODICITY_SEC = 3
+    }
+}
diff --git a/src/com/android/settings/password/ChooseLockPassword.java b/src/com/android/settings/password/ChooseLockPassword.java
index 631c735..a645300 100644
--- a/src/com/android/settings/password/ChooseLockPassword.java
+++ b/src/com/android/settings/password/ChooseLockPassword.java
@@ -416,6 +416,7 @@
             public String getHint(Context context, boolean isAlpha, int type, ProfileType profile) {
                 if (isAlpha) {
                     if (android.os.Flags.allowPrivateProfile()
+                            && android.multiuser.Flags.enablePrivateSpaceFeatures()
                             && profile.equals(ProfileType.Private)) {
                         return context.getString(alphaHintForPrivateProfile);
                     } else if (type == TYPE_FINGERPRINT) {
@@ -433,6 +434,7 @@
                     }
                 } else {
                     if (android.os.Flags.allowPrivateProfile()
+                            && android.multiuser.Flags.enablePrivateSpaceFeatures()
                             && profile.equals(ProfileType.Private)) {
                         return context.getString(numericHintForPrivateProfile);
                     } else if (type == TYPE_FINGERPRINT) {
@@ -1147,7 +1149,9 @@
                     /*flags=*/0).getSystemService(UserManager.class);
             if (userManager.isManagedProfile()) {
                 return ProfileType.Managed;
-            } else if (android.os.Flags.allowPrivateProfile() && userManager.isPrivateProfile()) {
+            } else if (android.os.Flags.allowPrivateProfile()
+                    && android.multiuser.Flags.enablePrivateSpaceFeatures()
+                    && userManager.isPrivateProfile()) {
                 return ProfileType.Private;
             } else if (userManager.isProfile()) {
                 return ProfileType.Other;
diff --git a/src/com/android/settings/password/ChooseLockPattern.java b/src/com/android/settings/password/ChooseLockPattern.java
index 8d0aebe..c331991 100644
--- a/src/com/android/settings/password/ChooseLockPattern.java
+++ b/src/com/android/settings/password/ChooseLockPattern.java
@@ -478,7 +478,9 @@
                         .getString(SET_WORK_PROFILE_PATTERN_HEADER,
                                 () -> getString(
                                         R.string.lockpassword_choose_your_profile_pattern_header));
-            } else if (android.os.Flags.allowPrivateProfile() && isPrivateProfile()) {
+            } else if (android.os.Flags.allowPrivateProfile()
+                    && android.multiuser.Flags.enablePrivateSpaceFeatures()
+                    && isPrivateProfile()) {
                 msg = getString(R.string.private_space_choose_your_pattern_header);
             } else {
                 msg = getString(R.string.lockpassword_choose_your_pattern_header);
diff --git a/src/com/android/settings/password/ConfirmDeviceCredentialActivity.java b/src/com/android/settings/password/ConfirmDeviceCredentialActivity.java
index f2ebd1f..cf80513 100644
--- a/src/com/android/settings/password/ConfirmDeviceCredentialActivity.java
+++ b/src/com/android/settings/password/ConfirmDeviceCredentialActivity.java
@@ -300,6 +300,7 @@
                 launchedCDC = true;
             }
         } else if (android.os.Flags.allowPrivateProfile()
+                && android.multiuser.Flags.enablePrivateSpaceFeatures()
                 && userProperties != null
                 && userProperties.isAuthAlwaysRequiredToDisableQuietMode()
                 && isInternalActivity()) {
@@ -413,7 +414,8 @@
 
     private boolean doesUserStateEnforceStrongAuth(int userId) {
         if (android.os.Flags.allowPrivateProfile()
-                && android.multiuser.Flags.enableBiometricsToUnlockPrivateSpace()) {
+                && android.multiuser.Flags.enableBiometricsToUnlockPrivateSpace()
+                && android.multiuser.Flags.enablePrivateSpaceFeatures()) {
             // Check if CE storage for user is locked since biometrics can't unlock fbe/keystore of
             // the profile user using verifyTiedProfileChallenge. Biometrics can still be used if
             // the user is stopped with delayed locking (i.e., with storage unlocked), so the user
diff --git a/src/com/android/settings/password/ConfirmDeviceCredentialUtils.java b/src/com/android/settings/password/ConfirmDeviceCredentialUtils.java
index 32e7489..e3182a4 100644
--- a/src/com/android/settings/password/ConfirmDeviceCredentialUtils.java
+++ b/src/com/android/settings/password/ConfirmDeviceCredentialUtils.java
@@ -105,7 +105,8 @@
 
     private static boolean isBiometricUnlockEnabledForPrivateSpace() {
         return android.os.Flags.allowPrivateProfile()
-                && android.multiuser.Flags.enableBiometricsToUnlockPrivateSpace();
+                && android.multiuser.Flags.enableBiometricsToUnlockPrivateSpace()
+                && android.multiuser.Flags.enablePrivateSpaceFeatures();
     }
 
     /**
diff --git a/src/com/android/settings/privatespace/AutoAdvanceSetupFragment.java b/src/com/android/settings/privatespace/AutoAdvanceSetupFragment.java
index 1f0f7bb..7f0118c 100644
--- a/src/com/android/settings/privatespace/AutoAdvanceSetupFragment.java
+++ b/src/com/android/settings/privatespace/AutoAdvanceSetupFragment.java
@@ -104,7 +104,8 @@
 
     @Override
     public void onCreate(@Nullable Bundle savedInstanceState) {
-        if (android.os.Flags.allowPrivateProfile()) {
+        if (android.os.Flags.allowPrivateProfile()
+                && android.multiuser.Flags.enablePrivateSpaceFeatures()) {
             super.onCreate(savedInstanceState);
         }
     }
diff --git a/src/com/android/settings/privatespace/HidePrivateSpaceController.java b/src/com/android/settings/privatespace/HidePrivateSpaceController.java
index a53055c..903defa 100644
--- a/src/com/android/settings/privatespace/HidePrivateSpaceController.java
+++ b/src/com/android/settings/privatespace/HidePrivateSpaceController.java
@@ -38,7 +38,10 @@
     @Override
     @AvailabilityStatus
     public int getAvailabilityStatus() {
-        return android.os.Flags.allowPrivateProfile() ? AVAILABLE : UNSUPPORTED_ON_DEVICE;
+        return android.os.Flags.allowPrivateProfile()
+                && android.multiuser.Flags.enablePrivateSpaceFeatures()
+                ? AVAILABLE
+                : UNSUPPORTED_ON_DEVICE;
     }
 
     @Override
diff --git a/src/com/android/settings/privatespace/HidePrivateSpaceSensitiveNotificationsController.java b/src/com/android/settings/privatespace/HidePrivateSpaceSensitiveNotificationsController.java
index 1a89d37..6cb54a1 100644
--- a/src/com/android/settings/privatespace/HidePrivateSpaceSensitiveNotificationsController.java
+++ b/src/com/android/settings/privatespace/HidePrivateSpaceSensitiveNotificationsController.java
@@ -52,6 +52,7 @@
     public int getAvailabilityStatus() {
         if (!android.os.Flags.allowPrivateProfile()
                 || !android.multiuser.Flags.enablePsSensitiveNotificationsToggle()
+                || !android.multiuser.Flags.enablePrivateSpaceFeatures()
                 || !mPrivateSpaceMaintainer.doesPrivateSpaceExist()) {
             return UNSUPPORTED_ON_DEVICE;
         }
diff --git a/src/com/android/settings/privatespace/HidePrivateSpaceSettings.java b/src/com/android/settings/privatespace/HidePrivateSpaceSettings.java
index 124978a..c41267f 100644
--- a/src/com/android/settings/privatespace/HidePrivateSpaceSettings.java
+++ b/src/com/android/settings/privatespace/HidePrivateSpaceSettings.java
@@ -27,7 +27,8 @@
 
     @Override
     public void onCreate(Bundle icicle) {
-        if (android.os.Flags.allowPrivateProfile()) {
+        if (android.os.Flags.allowPrivateProfile()
+                && android.multiuser.Flags.enablePrivateSpaceFeatures()) {
             super.onCreate(icicle);
         }
     }
diff --git a/src/com/android/settings/privatespace/HidePrivateSpaceSummaryController.java b/src/com/android/settings/privatespace/HidePrivateSpaceSummaryController.java
index 42627af..a366b70 100644
--- a/src/com/android/settings/privatespace/HidePrivateSpaceSummaryController.java
+++ b/src/com/android/settings/privatespace/HidePrivateSpaceSummaryController.java
@@ -36,7 +36,10 @@
 
     @Override
     public int getAvailabilityStatus() {
-        return android.os.Flags.allowPrivateProfile() ? AVAILABLE : UNSUPPORTED_ON_DEVICE;
+        return android.os.Flags.allowPrivateProfile()
+                && android.multiuser.Flags.enablePrivateSpaceFeatures()
+                ? AVAILABLE
+                : UNSUPPORTED_ON_DEVICE;
     }
 
     @Override
diff --git a/src/com/android/settings/privatespace/PrivateProfileContextHelperActivity.java b/src/com/android/settings/privatespace/PrivateProfileContextHelperActivity.java
index 12a7440..f2a50dc 100644
--- a/src/com/android/settings/privatespace/PrivateProfileContextHelperActivity.java
+++ b/src/com/android/settings/privatespace/PrivateProfileContextHelperActivity.java
@@ -59,7 +59,8 @@
 
     @Override
     protected void onCreate(Bundle savedInstanceState) {
-        if (!android.os.Flags.allowPrivateProfile()) {
+        if (!android.os.Flags.allowPrivateProfile()
+                || !android.multiuser.Flags.enablePrivateSpaceFeatures()) {
             return;
         }
         setTheme(SetupWizardUtils.getTheme(this, getIntent()));
diff --git a/src/com/android/settings/privatespace/PrivateSpaceAuthenticationActivity.java b/src/com/android/settings/privatespace/PrivateSpaceAuthenticationActivity.java
index 63b1dc9..53d6b22 100644
--- a/src/com/android/settings/privatespace/PrivateSpaceAuthenticationActivity.java
+++ b/src/com/android/settings/privatespace/PrivateSpaceAuthenticationActivity.java
@@ -77,7 +77,8 @@
     protected void onCreate(Bundle savedInstanceState) {
         super.onCreate(savedInstanceState);
 
-        if (Flags.allowPrivateProfile()) {
+        if (Flags.allowPrivateProfile()
+                && android.multiuser.Flags.enablePrivateSpaceFeatures()) {
             ThemeHelper.trySetDynamicColor(this);
             mPrivateSpaceMaintainer =
                     new Injector().injectPrivateSpaceMaintainer(getApplicationContext());
diff --git a/src/com/android/settings/privatespace/PrivateSpaceDashboardFragment.java b/src/com/android/settings/privatespace/PrivateSpaceDashboardFragment.java
index 726567e..32db8b6 100644
--- a/src/com/android/settings/privatespace/PrivateSpaceDashboardFragment.java
+++ b/src/com/android/settings/privatespace/PrivateSpaceDashboardFragment.java
@@ -32,7 +32,8 @@
 
     @Override
     public void onCreate(Bundle icicle) {
-        if (android.os.Flags.allowPrivateProfile()) {
+        if (android.os.Flags.allowPrivateProfile()
+                && android.multiuser.Flags.enablePrivateSpaceFeatures()) {
             super.onCreate(icicle);
             if (icicle == null
                     && getIntent().getBooleanExtra(EXTRA_SHOW_PRIVATE_SPACE_UNLOCKED, false)) {
diff --git a/src/com/android/settings/privatespace/PrivateSpaceEducation.java b/src/com/android/settings/privatespace/PrivateSpaceEducation.java
index 4c99873..cf22895 100644
--- a/src/com/android/settings/privatespace/PrivateSpaceEducation.java
+++ b/src/com/android/settings/privatespace/PrivateSpaceEducation.java
@@ -43,7 +43,8 @@
             LayoutInflater inflater,
             @Nullable ViewGroup container,
             @Nullable Bundle savedInstanceState) {
-        if (!android.os.Flags.allowPrivateProfile()) {
+        if (!android.os.Flags.allowPrivateProfile()
+                || !android.multiuser.Flags.enablePrivateSpaceFeatures()) {
             return null;
         }
         GlifLayout rootView =
diff --git a/src/com/android/settings/privatespace/PrivateSpaceMaintainer.java b/src/com/android/settings/privatespace/PrivateSpaceMaintainer.java
index 2d38ae2..3fb9b15 100644
--- a/src/com/android/settings/privatespace/PrivateSpaceMaintainer.java
+++ b/src/com/android/settings/privatespace/PrivateSpaceMaintainer.java
@@ -78,7 +78,8 @@
      */
     @VisibleForTesting
     public final synchronized boolean createPrivateSpace() {
-        if (!Flags.allowPrivateProfile()) {
+        if (!Flags.allowPrivateProfile()
+                || !android.multiuser.Flags.enablePrivateSpaceFeatures()) {
             return false;
         }
         // Check if Private space already exists
@@ -146,7 +147,8 @@
 
     /** Returns true if the Private space exists. */
     public synchronized boolean doesPrivateSpaceExist() {
-        if (!Flags.allowPrivateProfile()) {
+        if (!Flags.allowPrivateProfile()
+                || !android.multiuser.Flags.enablePrivateSpaceFeatures()) {
             return false;
         }
         if (mUserHandle != null) {
@@ -322,6 +324,7 @@
 
     private boolean isPrivateSpaceAutoLockSupported() {
         return android.os.Flags.allowPrivateProfile()
-                && android.multiuser.Flags.supportAutolockForPrivateSpace();
+                && android.multiuser.Flags.supportAutolockForPrivateSpace()
+                && android.multiuser.Flags.enablePrivateSpaceFeatures();
     }
 }
diff --git a/src/com/android/settings/privatespace/PrivateSpaceSafetySource.java b/src/com/android/settings/privatespace/PrivateSpaceSafetySource.java
index 6729830..4e1741a 100644
--- a/src/com/android/settings/privatespace/PrivateSpaceSafetySource.java
+++ b/src/com/android/settings/privatespace/PrivateSpaceSafetySource.java
@@ -51,7 +51,8 @@
             return;
         }
 
-        if (!Flags.allowPrivateProfile()) {
+        if (!Flags.allowPrivateProfile()
+                || !android.multiuser.Flags.enablePrivateSpaceFeatures()) {
             // Setting null safetySourceData so that an old entry gets cleared out and this way
             // provide a response since SC always expects one on rescan.
             SafetyCenterManagerWrapper.get().setSafetySourceData(
diff --git a/src/com/android/settings/privatespace/PrivateSpaceSetLockFragment.java b/src/com/android/settings/privatespace/PrivateSpaceSetLockFragment.java
index 4a1e29b..399c2c8 100644
--- a/src/com/android/settings/privatespace/PrivateSpaceSetLockFragment.java
+++ b/src/com/android/settings/privatespace/PrivateSpaceSetLockFragment.java
@@ -51,7 +51,8 @@
             LayoutInflater inflater,
             @Nullable ViewGroup container,
             @Nullable Bundle savedInstanceState) {
-        if (!android.os.Flags.allowPrivateProfile()) {
+        if (!android.os.Flags.allowPrivateProfile()
+                || !android.multiuser.Flags.enablePrivateSpaceFeatures()) {
             return null;
         }
         GlifLayout rootView =
diff --git a/src/com/android/settings/privatespace/PrivateSpaceSetupActivity.java b/src/com/android/settings/privatespace/PrivateSpaceSetupActivity.java
index 78c96dc..ec7132a 100644
--- a/src/com/android/settings/privatespace/PrivateSpaceSetupActivity.java
+++ b/src/com/android/settings/privatespace/PrivateSpaceSetupActivity.java
@@ -42,7 +42,8 @@
 
     @Override
     protected void onCreate(Bundle savedInstanceState) {
-        if (!android.os.Flags.allowPrivateProfile()) {
+        if (!android.os.Flags.allowPrivateProfile()
+                || !android.multiuser.Flags.enablePrivateSpaceFeatures()) {
             return;
         }
         setTheme(SetupWizardUtils.getTheme(this, getIntent()));
diff --git a/src/com/android/settings/privatespace/SetupSuccessFragment.java b/src/com/android/settings/privatespace/SetupSuccessFragment.java
index 13de1fc..cf63b22 100644
--- a/src/com/android/settings/privatespace/SetupSuccessFragment.java
+++ b/src/com/android/settings/privatespace/SetupSuccessFragment.java
@@ -47,7 +47,8 @@
             LayoutInflater inflater,
             @Nullable ViewGroup container,
             @Nullable Bundle savedInstanceState) {
-        if (!android.os.Flags.allowPrivateProfile()) {
+        if (!android.os.Flags.allowPrivateProfile()
+                || !android.multiuser.Flags.enablePrivateSpaceFeatures()) {
             return null;
         }
         GlifLayout rootView =
diff --git a/src/com/android/settings/privatespace/autolock/AutoLockPreferenceController.java b/src/com/android/settings/privatespace/autolock/AutoLockPreferenceController.java
index a7a12a4..3416e14 100644
--- a/src/com/android/settings/privatespace/autolock/AutoLockPreferenceController.java
+++ b/src/com/android/settings/privatespace/autolock/AutoLockPreferenceController.java
@@ -40,7 +40,8 @@
     @Override
     public int getAvailabilityStatus() {
         return android.os.Flags.allowPrivateProfile()
-                        && android.multiuser.Flags.supportAutolockForPrivateSpace()
+                && android.multiuser.Flags.supportAutolockForPrivateSpace()
+                && android.multiuser.Flags.enablePrivateSpaceFeatures()
                 ? AVAILABLE
                 : UNSUPPORTED_ON_DEVICE;
     }
diff --git a/src/com/android/settings/privatespace/autolock/AutoLockSettingsFragment.java b/src/com/android/settings/privatespace/autolock/AutoLockSettingsFragment.java
index 4380c53..cb332d1 100644
--- a/src/com/android/settings/privatespace/autolock/AutoLockSettingsFragment.java
+++ b/src/com/android/settings/privatespace/autolock/AutoLockSettingsFragment.java
@@ -47,7 +47,8 @@
     @Override
     public void onCreate(@NonNull Bundle icicle) {
         if (android.os.Flags.allowPrivateProfile()
-                && android.multiuser.Flags.supportAutolockForPrivateSpace()) {
+                && android.multiuser.Flags.supportAutolockForPrivateSpace()
+                && android.multiuser.Flags.enablePrivateSpaceFeatures()) {
             super.onCreate(icicle);
         }
     }
diff --git a/src/com/android/settings/privatespace/delete/DeletePrivateSpaceController.java b/src/com/android/settings/privatespace/delete/DeletePrivateSpaceController.java
index af4535e..a2fc6f8 100644
--- a/src/com/android/settings/privatespace/delete/DeletePrivateSpaceController.java
+++ b/src/com/android/settings/privatespace/delete/DeletePrivateSpaceController.java
@@ -34,7 +34,10 @@
 
     @Override
     public int getAvailabilityStatus() {
-        return android.os.Flags.allowPrivateProfile() ? AVAILABLE : UNSUPPORTED_ON_DEVICE;
+        return android.os.Flags.allowPrivateProfile()
+                && android.multiuser.Flags.enablePrivateSpaceFeatures()
+                ? AVAILABLE
+                : UNSUPPORTED_ON_DEVICE;
     }
 
     @Override
diff --git a/src/com/android/settings/privatespace/delete/PrivateSpaceDeleteActivity.java b/src/com/android/settings/privatespace/delete/PrivateSpaceDeleteActivity.java
index a4109b8..b483aa3 100644
--- a/src/com/android/settings/privatespace/delete/PrivateSpaceDeleteActivity.java
+++ b/src/com/android/settings/privatespace/delete/PrivateSpaceDeleteActivity.java
@@ -35,7 +35,8 @@
 
     @Override
     protected void onCreate(Bundle savedInstanceState) {
-        if (!android.os.Flags.allowPrivateProfile()) {
+        if (!android.os.Flags.allowPrivateProfile()
+                || !android.multiuser.Flags.enablePrivateSpaceFeatures()) {
             return;
         }
         setTheme(SetupWizardUtils.getTheme(this, getIntent()));
diff --git a/src/com/android/settings/privatespace/delete/PrivateSpaceDeleteFragment.java b/src/com/android/settings/privatespace/delete/PrivateSpaceDeleteFragment.java
index 7dd3a5b..bcc220f 100644
--- a/src/com/android/settings/privatespace/delete/PrivateSpaceDeleteFragment.java
+++ b/src/com/android/settings/privatespace/delete/PrivateSpaceDeleteFragment.java
@@ -56,7 +56,8 @@
 
     @Override
     public void onCreate(@Nullable Bundle icicle) {
-        if (android.os.Flags.allowPrivateProfile()) {
+        if (android.os.Flags.allowPrivateProfile()
+                && android.multiuser.Flags.enablePrivateSpaceFeatures()) {
             super.onCreate(icicle);
         }
     }
diff --git a/src/com/android/settings/privatespace/delete/PrivateSpaceDeletionProgressFragment.java b/src/com/android/settings/privatespace/delete/PrivateSpaceDeletionProgressFragment.java
index 3a16641..33f0a3e 100644
--- a/src/com/android/settings/privatespace/delete/PrivateSpaceDeletionProgressFragment.java
+++ b/src/com/android/settings/privatespace/delete/PrivateSpaceDeletionProgressFragment.java
@@ -62,7 +62,8 @@
 
     @Override
     public void onCreate(@Nullable Bundle savedInstanceState) {
-        if (android.os.Flags.allowPrivateProfile()) {
+        if (android.os.Flags.allowPrivateProfile()
+                && android.multiuser.Flags.enablePrivateSpaceFeatures()) {
             super.onCreate(savedInstanceState);
         }
     }
diff --git a/src/com/android/settings/privatespace/onelock/FaceFingerprintUnlockController.java b/src/com/android/settings/privatespace/onelock/FaceFingerprintUnlockController.java
index 2e3f284..04f4894 100644
--- a/src/com/android/settings/privatespace/onelock/FaceFingerprintUnlockController.java
+++ b/src/com/android/settings/privatespace/onelock/FaceFingerprintUnlockController.java
@@ -42,6 +42,7 @@
     protected boolean isUserSupported() {
         return android.os.Flags.allowPrivateProfile()
                 && android.multiuser.Flags.enableBiometricsToUnlockPrivateSpace()
+                && android.multiuser.Flags.enablePrivateSpaceFeatures()
                 && mProfileUserId != UserHandle.USER_NULL;
     }
 
diff --git a/src/com/android/settings/privatespace/onelock/PrivateSpaceBiometricSettings.java b/src/com/android/settings/privatespace/onelock/PrivateSpaceBiometricSettings.java
index dc00885..827f0b7 100644
--- a/src/com/android/settings/privatespace/onelock/PrivateSpaceBiometricSettings.java
+++ b/src/com/android/settings/privatespace/onelock/PrivateSpaceBiometricSettings.java
@@ -34,7 +34,8 @@
     @Override
     public void onAttach(Context context) {
         if (android.os.Flags.allowPrivateProfile()
-                && android.multiuser.Flags.enableBiometricsToUnlockPrivateSpace()) {
+                && android.multiuser.Flags.enableBiometricsToUnlockPrivateSpace()
+                && android.multiuser.Flags.enablePrivateSpaceFeatures()) {
             super.onAttach(context);
             UserHandle privateProfileHandle =
                     PrivateSpaceMaintainer.getInstance(context).getPrivateProfileHandle();
diff --git a/src/com/android/settings/privatespace/onelock/PrivateSpaceFacePreferenceController.java b/src/com/android/settings/privatespace/onelock/PrivateSpaceFacePreferenceController.java
index b841d9a..583a093 100644
--- a/src/com/android/settings/privatespace/onelock/PrivateSpaceFacePreferenceController.java
+++ b/src/com/android/settings/privatespace/onelock/PrivateSpaceFacePreferenceController.java
@@ -45,6 +45,7 @@
     protected boolean isUserSupported() {
         return android.os.Flags.allowPrivateProfile()
                 && android.multiuser.Flags.enableBiometricsToUnlockPrivateSpace()
+                && android.multiuser.Flags.enablePrivateSpaceFeatures()
                 && getUserId() != UserHandle.USER_NULL;
     }
 
@@ -63,7 +64,8 @@
     @Override
     public int getAvailabilityStatus() {
         return android.os.Flags.allowPrivateProfile()
-                        && android.multiuser.Flags.enableBiometricsToUnlockPrivateSpace()
+                && android.multiuser.Flags.enableBiometricsToUnlockPrivateSpace()
+                && android.multiuser.Flags.enablePrivateSpaceFeatures()
                 ? AVAILABLE
                 : UNSUPPORTED_ON_DEVICE;
     }
diff --git a/src/com/android/settings/privatespace/onelock/PrivateSpaceFingerprintPreferenceController.java b/src/com/android/settings/privatespace/onelock/PrivateSpaceFingerprintPreferenceController.java
index d484904..f88c9fa 100644
--- a/src/com/android/settings/privatespace/onelock/PrivateSpaceFingerprintPreferenceController.java
+++ b/src/com/android/settings/privatespace/onelock/PrivateSpaceFingerprintPreferenceController.java
@@ -47,6 +47,7 @@
     protected boolean isUserSupported() {
         return android.os.Flags.allowPrivateProfile()
                 && android.multiuser.Flags.enableBiometricsToUnlockPrivateSpace()
+                && android.multiuser.Flags.enablePrivateSpaceFeatures()
                 && getUserId() != UserHandle.USER_NULL;
     }
 
@@ -65,7 +66,8 @@
     @Override
     public int getAvailabilityStatus() {
         return android.os.Flags.allowPrivateProfile()
-                        && android.multiuser.Flags.enableBiometricsToUnlockPrivateSpace()
+                && android.multiuser.Flags.enableBiometricsToUnlockPrivateSpace()
+                && android.multiuser.Flags.enablePrivateSpaceFeatures()
                 ? AVAILABLE
                 : UNSUPPORTED_ON_DEVICE;
     }
diff --git a/src/com/android/settings/privatespace/onelock/PrivateSpaceLockController.java b/src/com/android/settings/privatespace/onelock/PrivateSpaceLockController.java
index efbe9f9..e0f376e 100644
--- a/src/com/android/settings/privatespace/onelock/PrivateSpaceLockController.java
+++ b/src/com/android/settings/privatespace/onelock/PrivateSpaceLockController.java
@@ -74,7 +74,8 @@
 
     @Override
     public boolean isAvailable() {
-        return android.os.Flags.allowPrivateProfile();
+        return android.os.Flags.allowPrivateProfile()
+                && android.multiuser.Flags.enablePrivateSpaceFeatures();
     }
 
     @Override
diff --git a/src/com/android/settings/privatespace/onelock/UseOneLockController.java b/src/com/android/settings/privatespace/onelock/UseOneLockController.java
index 31634b9..1af36b3 100644
--- a/src/com/android/settings/privatespace/onelock/UseOneLockController.java
+++ b/src/com/android/settings/privatespace/onelock/UseOneLockController.java
@@ -45,7 +45,10 @@
     }
     @Override
     public int getAvailabilityStatus() {
-        return android.os.Flags.allowPrivateProfile() ? AVAILABLE : UNSUPPORTED_ON_DEVICE;
+        return android.os.Flags.allowPrivateProfile()
+                && android.multiuser.Flags.enablePrivateSpaceFeatures()
+                ? AVAILABLE
+                : UNSUPPORTED_ON_DEVICE;
     }
 
     @Override
diff --git a/src/com/android/settings/privatespace/onelock/UseOneLockControllerSwitch.java b/src/com/android/settings/privatespace/onelock/UseOneLockControllerSwitch.java
index fd7d02b..680f5c7 100644
--- a/src/com/android/settings/privatespace/onelock/UseOneLockControllerSwitch.java
+++ b/src/com/android/settings/privatespace/onelock/UseOneLockControllerSwitch.java
@@ -95,7 +95,8 @@
 
     @Override
     public boolean isAvailable() {
-        return android.os.Flags.allowPrivateProfile();
+        return android.os.Flags.allowPrivateProfile()
+                && android.multiuser.Flags.enablePrivateSpaceFeatures();
     }
 
     @Override
diff --git a/src/com/android/settings/privatespace/onelock/UseOneLockSettingsFragment.java b/src/com/android/settings/privatespace/onelock/UseOneLockSettingsFragment.java
index 413e02a..ce017e3 100644
--- a/src/com/android/settings/privatespace/onelock/UseOneLockSettingsFragment.java
+++ b/src/com/android/settings/privatespace/onelock/UseOneLockSettingsFragment.java
@@ -39,7 +39,8 @@
 
     @Override
     public void onCreate(Bundle icicle) {
-        if (android.os.Flags.allowPrivateProfile()) {
+        if (android.os.Flags.allowPrivateProfile()
+                && android.multiuser.Flags.enablePrivateSpaceFeatures()) {
             super.onCreate(icicle);
         }
     }
diff --git a/src/com/android/settings/safetycenter/BiometricsSafetySource.java b/src/com/android/settings/safetycenter/BiometricsSafetySource.java
index 8e1c786..c93ced1 100644
--- a/src/com/android/settings/safetycenter/BiometricsSafetySource.java
+++ b/src/com/android/settings/safetycenter/BiometricsSafetySource.java
@@ -62,7 +62,9 @@
         }
         final Context profileParentContext =
                 context.createContextAsUser(profileParentUserHandle, 0);
-        if (android.os.Flags.allowPrivateProfile() && userManager.isPrivateProfile()) {
+        if (android.os.Flags.allowPrivateProfile()
+                && android.multiuser.Flags.enablePrivateSpaceFeatures()
+                && userManager.isPrivateProfile()) {
             // SC always expects a response from the source if the broadcast has been sent for this
             // source, therefore, we need to send a null SafetySourceData.
             SafetyCenterManagerWrapper.get().setSafetySourceData(
diff --git a/src/com/android/settings/spa/app/appcompat/UserAspectRatioAppsPageProvider.kt b/src/com/android/settings/spa/app/appcompat/UserAspectRatioAppsPageProvider.kt
index 15cd1ba..3241d71 100644
--- a/src/com/android/settings/spa/app/appcompat/UserAspectRatioAppsPageProvider.kt
+++ b/src/com/android/settings/spa/app/appcompat/UserAspectRatioAppsPageProvider.kt
@@ -62,6 +62,7 @@
 import com.android.settingslib.spaprivileged.template.app.AppListItemModel
 import com.android.settingslib.spaprivileged.template.app.AppListPage
 import com.google.common.annotations.VisibleForTesting
+import kotlinx.coroutines.CoroutineDispatcher
 import kotlinx.coroutines.Dispatchers
 import kotlinx.coroutines.flow.Flow
 import kotlinx.coroutines.flow.combine
@@ -130,8 +131,10 @@
     val canDisplay: Boolean,
 ) : AppRecord
 
-class UserAspectRatioAppListModel(private val context: Context)
-    : AppListModel<UserAspectRatioAppListItemModel> {
+class UserAspectRatioAppListModel(
+    private val context: Context,
+    private val ioDispatcher: CoroutineDispatcher = Dispatchers.IO
+) : AppListModel<UserAspectRatioAppListItemModel> {
 
     private val packageManager = context.packageManager
     private val userAspectRatioManager = UserAspectRatioManager(context)
@@ -203,7 +206,7 @@
             flow {
                 emit(userAspectRatioManager.getUserMinAspectRatioEntry(record.userOverride,
                     record.app.packageName, record.app.userId))
-            }.flowOn(Dispatchers.IO)
+            }.flowOn(ioDispatcher)
         }.collectAsStateWithLifecycle(initialValue = stringResource(R.string.summary_placeholder))
         return { summary }
     }
diff --git a/tests/robotests/src/com/android/settings/accessibility/KeyboardVibrationTogglePreferenceControllerTest.java b/tests/robotests/src/com/android/settings/accessibility/KeyboardVibrationTogglePreferenceControllerTest.java
index cf12e34..2d5905e 100644
--- a/tests/robotests/src/com/android/settings/accessibility/KeyboardVibrationTogglePreferenceControllerTest.java
+++ b/tests/robotests/src/com/android/settings/accessibility/KeyboardVibrationTogglePreferenceControllerTest.java
@@ -84,6 +84,9 @@
     public void getAvailabilityStatus_featureSupported_available() {
         mSetFlagsRule.enableFlags(Flags.FLAG_KEYBOARD_CATEGORY_ENABLED);
         when(mResources.getBoolean(R.bool.config_keyboard_vibration_supported)).thenReturn(true);
+        when(mResources.getFloat(
+                com.android.internal.R.dimen.config_keyboardHapticFeedbackFixedAmplitude))
+                .thenReturn(0.8f);
 
         assertThat(mController.getAvailabilityStatus()).isEqualTo(AVAILABLE);
     }
diff --git a/tests/robotests/src/com/android/settings/accessibility/MagnificationOneFingerPanningPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/accessibility/MagnificationOneFingerPanningPreferenceControllerTest.java
new file mode 100644
index 0000000..326a7a0
--- /dev/null
+++ b/tests/robotests/src/com/android/settings/accessibility/MagnificationOneFingerPanningPreferenceControllerTest.java
@@ -0,0 +1,187 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.settings.accessibility;
+
+import static com.android.server.accessibility.Flags.enableMagnificationOneFingerPanningGesture;
+import static com.android.settings.accessibility.AccessibilityUtil.State.OFF;
+import static com.android.settings.accessibility.AccessibilityUtil.State.ON;
+import static com.android.settings.core.BasePreferenceController.AVAILABLE;
+import static com.android.settings.core.BasePreferenceController.DISABLED_FOR_USER;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import static org.mockito.Mockito.spy;
+import static org.mockito.Mockito.verify;
+
+import android.content.Context;
+import android.platform.test.flag.junit.SetFlagsRule;
+import android.provider.Settings;
+
+import androidx.preference.PreferenceManager;
+import androidx.preference.PreferenceScreen;
+import androidx.preference.SwitchPreference;
+import androidx.test.core.app.ApplicationProvider;
+
+import com.android.server.accessibility.Flags;
+import com.android.settings.R;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.robolectric.RobolectricTestRunner;
+
+@RunWith(RobolectricTestRunner.class)
+public class MagnificationOneFingerPanningPreferenceControllerTest {
+    private static final String ONE_FINGER_PANNING_KEY =
+            Settings.Secure.ACCESSIBILITY_SINGLE_FINGER_PANNING_ENABLED;
+
+    @Rule public final SetFlagsRule mSetFlagsRule =
+            new SetFlagsRule(SetFlagsRule.DefaultInitValueType.DEVICE_DEFAULT);
+
+    private final Context mContext = ApplicationProvider.getApplicationContext();
+    private final SwitchPreference mSwitchPreference = spy(new SwitchPreference(mContext));
+    private final MagnificationOneFingerPanningPreferenceController mController =
+            new MagnificationOneFingerPanningPreferenceController(mContext);
+
+    private PreferenceScreen mScreen;
+
+    @Before
+    public void setUp() {
+        final PreferenceManager preferenceManager = new PreferenceManager(mContext);
+        mScreen = preferenceManager.createPreferenceScreen(mContext);
+        mSwitchPreference.setKey(MagnificationOneFingerPanningPreferenceController.PREF_KEY);
+        mScreen.addPreference(mSwitchPreference);
+        mController.displayPreference(mScreen);
+    }
+
+    @After
+    public void cleanup() {
+        // Can't use resetToDefaults as it NPE with
+        // "Cannot invoke "android.content.IContentProvider.call"
+        Settings.Secure.putInt(
+                mContext.getContentResolver(),
+                MagnificationOneFingerPanningPreferenceController.PREF_KEY,
+                (mController.mDefaultValue) ? ON : OFF);
+    }
+
+    @Test
+    public void displayPreference_defaultState_correctSummarySet() {
+        assertThat(mSwitchPreference.getSummary())
+                .isEqualTo(mContext.getString(
+                        R.string.accessibility_magnification_one_finger_panning_summary_off));
+    }
+
+    @Test
+    public void getAvailabilityStatus_defaultState_disabled() {
+        int status = mController.getAvailabilityStatus();
+
+        assertThat(status).isEqualTo(DISABLED_FOR_USER);
+    }
+
+    @Test
+    public void getAvailabilityStatus_featureFlagEnabled_enabled() {
+        enableFlag();
+
+        int status = mController.getAvailabilityStatus();
+
+        assertThat(status).isEqualTo(AVAILABLE);
+    }
+
+    @Test
+    public void isChecked_defaultState_returnFalse() {
+        assertThat(mController.isChecked()).isFalse();
+        assertThat(mSwitchPreference.isChecked()).isFalse();
+    }
+
+    @Test
+    public void isChecked_settingsEnabled_returnTrue() {
+        Settings.Secure.putInt(mContext.getContentResolver(), ONE_FINGER_PANNING_KEY, ON);
+
+        assertThat(mController.isChecked()).isTrue();
+    }
+
+    @Test
+    public void isChecked_settingsDisabled_returnTrue() {
+        Settings.Secure.putInt(mContext.getContentResolver(), ONE_FINGER_PANNING_KEY, OFF);
+
+        assertThat(mController.isChecked()).isFalse();
+    }
+
+    @Test
+    public void setChecked_enabled_enabledSummarySet() {
+        mController.setChecked(true);
+
+        assertThat(mSwitchPreference.getSummary()).isEqualTo(enabledSummary());
+        assertThat(mController.isChecked()).isTrue();
+    }
+
+    @Test
+    public void setChecked_disabled_disabledSummarySet() {
+        mController.setChecked(false);
+
+        assertThat(mController.isChecked()).isFalse();
+        assertThat(mSwitchPreference.getSummary()).isEqualTo(disabledSummary());
+    }
+
+    @Test
+    public void getSummary_disable_disableSummaryTextUsed() {
+        Settings.Secure.putInt(mContext.getContentResolver(), ONE_FINGER_PANNING_KEY, OFF);
+
+        var summary = mController.getSummary();
+
+        assertThat(summary).isEqualTo(disabledSummary());
+    }
+
+    @Test
+    public void getSummary_enable_enabledSummaryTextUsed() {
+        Settings.Secure.putInt(mContext.getContentResolver(), ONE_FINGER_PANNING_KEY, ON);
+
+        var summary = mController.getSummary();
+
+        assertThat(summary).isEqualTo(enabledSummary());
+    }
+
+    @Test
+    public void performClick_switchDefaultState_shouldReturnTrue() {
+        enableFlag();
+
+        mSwitchPreference.performClick();
+
+        verify(mSwitchPreference).setChecked(true);
+        assertThat(mController.isChecked()).isTrue();
+        assertThat(mSwitchPreference.isChecked()).isTrue();
+    }
+
+    private void enableFlag() {
+        mSetFlagsRule.enableFlags(Flags.FLAG_ENABLE_MAGNIFICATION_ONE_FINGER_PANNING_GESTURE);
+        assertThat(enableMagnificationOneFingerPanningGesture()).isTrue();
+        // This ensures that preference change listeners are added correctly.
+        mController.displayPreference(mScreen);
+    }
+
+    private String enabledSummary() {
+        return mContext.getString(
+                R.string.accessibility_magnification_one_finger_panning_summary_on);
+    }
+
+    private String disabledSummary() {
+        return mContext.getString(
+                R.string.accessibility_magnification_one_finger_panning_summary_off);
+    }
+}
diff --git a/tests/robotests/src/com/android/settings/applications/appcompat/UserAspectRatioDetailsTest.java b/tests/robotests/src/com/android/settings/applications/appcompat/UserAspectRatioDetailsTest.java
index f3b105b..ce03a6d 100644
--- a/tests/robotests/src/com/android/settings/applications/appcompat/UserAspectRatioDetailsTest.java
+++ b/tests/robotests/src/com/android/settings/applications/appcompat/UserAspectRatioDetailsTest.java
@@ -16,16 +16,19 @@
 
 package com.android.settings.applications.appcompat;
 
+import static android.content.pm.PackageManager.USER_MIN_ASPECT_RATIO_3_2;
 import static android.content.pm.PackageManager.USER_MIN_ASPECT_RATIO_APP_DEFAULT;
 import static android.content.pm.PackageManager.USER_MIN_ASPECT_RATIO_FULLSCREEN;
 import static android.content.pm.PackageManager.USER_MIN_ASPECT_RATIO_UNSET;
 
 import static com.android.settings.applications.AppInfoBase.ARG_PACKAGE_NAME;
+import static com.android.settings.applications.appcompat.UserAspectRatioDetails.KEY_HEADER_BUTTONS;
 import static com.android.settings.applications.appcompat.UserAspectRatioDetails.KEY_PREF_3_2;
 import static com.android.settings.applications.appcompat.UserAspectRatioDetails.KEY_PREF_DEFAULT;
 import static com.android.settings.applications.appcompat.UserAspectRatioDetails.KEY_PREF_FULLSCREEN;
 
 import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
 import static org.mockito.ArgumentMatchers.any;
 import static org.mockito.ArgumentMatchers.anyInt;
 import static org.mockito.ArgumentMatchers.anyString;
@@ -99,6 +102,31 @@
     }
 
     @Test
+    public void testOrderOfOptionsFollowsConfig() {
+        doReturn(true).when(mUserAspectRatioManager)
+                .hasAspectRatioOption(anyInt(), anyString());
+        doReturn(0).when(mUserAspectRatioManager)
+                .getUserMinAspectRatioOrder(USER_MIN_ASPECT_RATIO_3_2);
+        doReturn(1).when(mUserAspectRatioManager)
+                .getUserMinAspectRatioOrder(USER_MIN_ASPECT_RATIO_FULLSCREEN);
+        doReturn(2).when(mUserAspectRatioManager)
+                .getUserMinAspectRatioOrder(USER_MIN_ASPECT_RATIO_UNSET);
+        rule.getScenario().onActivity(a -> doReturn(a).when(mFragment).getActivity());
+        final Bundle args = new Bundle();
+        args.putString(ARG_PACKAGE_NAME, anyString());
+        mFragment.setArguments(args);
+        mFragment.onCreate(Bundle.EMPTY);
+
+        final int topOfList = mFragment.findPreference(KEY_HEADER_BUTTONS).getOrder();
+
+        assertTrue(topOfList < mFragment.findPreference(KEY_PREF_3_2).getOrder());
+        assertTrue(mFragment.findPreference(KEY_PREF_3_2).getOrder()
+                < mFragment.findPreference(KEY_PREF_FULLSCREEN).getOrder());
+        assertTrue(mFragment.findPreference(KEY_PREF_FULLSCREEN).getOrder()
+                < mFragment.findPreference(KEY_PREF_DEFAULT).getOrder());
+    }
+
+    @Test
     public void onRadioButtonClicked_prefChange_shouldStopActivity() throws RemoteException {
         doReturn(USER_MIN_ASPECT_RATIO_UNSET).when(mFragment)
                 .getSelectedUserMinAspectRatio(anyString());
diff --git a/tests/robotests/src/com/android/settings/biometrics/fingerprint/FingerprintEnrollIntroductionTest.java b/tests/robotests/src/com/android/settings/biometrics/fingerprint/FingerprintEnrollIntroductionTest.java
index 1aedce5..6df8b8e 100644
--- a/tests/robotests/src/com/android/settings/biometrics/fingerprint/FingerprintEnrollIntroductionTest.java
+++ b/tests/robotests/src/com/android/settings/biometrics/fingerprint/FingerprintEnrollIntroductionTest.java
@@ -253,6 +253,24 @@
     }
 
     @Test
+    public void intro_CheckNullPropsReturnsErrorString() {
+        setupFingerprintEnrollIntroWith(newTokenOnlyIntent());
+        when(mFingerprintManager.getSensorPropertiesInternal()).thenReturn(null);
+        final int result = mFingerprintEnrollIntroduction.checkMaxEnrolled();
+
+        assertThat(result).isEqualTo(R.string.fingerprint_intro_error_unknown);
+    }
+
+    @Test
+    public void intro_CheckEmptyPropsReturnsErrorString() {
+        setupFingerprintEnrollIntroWith(newTokenOnlyIntent());
+        when(mFingerprintManager.getSensorPropertiesInternal()).thenReturn(List.of());
+        final int result = mFingerprintEnrollIntroduction.checkMaxEnrolled();
+
+        assertThat(result).isEqualTo(R.string.fingerprint_intro_error_unknown);
+    }
+
+    @Test
     public void intro_CheckGenerateChallenge() {
         setupFingerprintEnrollIntroWith(newGkPwHandleAndFromSettingsIntent());
 
diff --git a/tests/robotests/src/com/android/settings/dashboard/profileselector/ProfileSelectFragmentTest.java b/tests/robotests/src/com/android/settings/dashboard/profileselector/ProfileSelectFragmentTest.java
index 17e0d1c..46e4ea5 100644
--- a/tests/robotests/src/com/android/settings/dashboard/profileselector/ProfileSelectFragmentTest.java
+++ b/tests/robotests/src/com/android/settings/dashboard/profileselector/ProfileSelectFragmentTest.java
@@ -118,7 +118,9 @@
         profileSelectFragment.setViewPager(viewPager);
         mFragmentManager.beginTransaction().add(profileSelectFragment, "tag");
 
-        assertThat(mFragment.getTabId(mActivity, bundle)).isEqualTo(WORK_TAB);
+        // The expected position '2' comes from the order in which fragments are added in
+        // TestProfileSelectFragment#getFragments()
+        assertThat(mFragment.getTabId(mActivity, bundle)).isEqualTo(2);
     }
 
     @Test
@@ -136,7 +138,9 @@
         profileSelectFragment.setViewPager(viewPager);
         mFragmentManager.beginTransaction().add(profileSelectFragment, "tag");
 
-        assertThat(mFragment.getTabId(mActivity, bundle)).isEqualTo(PRIVATE_TAB);
+        // The expected position '1' comes from the order in which fragments are added in
+        // TestProfileSelectFragment#getFragments()
+        assertThat(mFragment.getTabId(mActivity, bundle)).isEqualTo(1);
     }
 
     @Test
@@ -170,7 +174,8 @@
 
     @Test
     public void getTabId_setPrivateId_getCorrectTab() {
-        mSetFlagsRule.enableFlags(Flags.FLAG_ALLOW_PRIVATE_PROFILE);
+        mSetFlagsRule.enableFlags(Flags.FLAG_ALLOW_PRIVATE_PROFILE,
+                android.multiuser.Flags.FLAG_ENABLE_PRIVATE_SPACE_FEATURES);
         final Bundle bundle = new Bundle();
         bundle.putInt(EXTRA_USER_ID, 11);
         mUserManager.setPrivateProfile(11, "private", 0);
@@ -200,7 +205,8 @@
 
     @Test
     public void testGetFragments_whenOnlyPersonal_returnsOneFragment() {
-        mSetFlagsRule.disableFlags(Flags.FLAG_ALLOW_PRIVATE_PROFILE);
+        mSetFlagsRule.disableFlags(Flags.FLAG_ALLOW_PRIVATE_PROFILE,
+                android.multiuser.Flags.FLAG_ENABLE_PRIVATE_SPACE_FEATURES);
         mUserManager.addProfile(
                 new UserInfo(0, PRIMARY_USER_NAME, null, 0, USER_TYPE_FULL_SYSTEM));
         Fragment[] fragments = ProfileSelectFragment.getFragments(
@@ -235,7 +241,8 @@
 
     @Test
     public void testGetFragments_whenPrivateEnabled_returnsTwoFragments() {
-        mSetFlagsRule.enableFlags(Flags.FLAG_ALLOW_PRIVATE_PROFILE);
+        mSetFlagsRule.enableFlags(Flags.FLAG_ALLOW_PRIVATE_PROFILE,
+                android.multiuser.Flags.FLAG_ENABLE_PRIVATE_SPACE_FEATURES);
         mUserManager.addProfile(
                 new UserInfo(0, PRIMARY_USER_NAME, null, 0, USER_TYPE_FULL_SYSTEM));
         mUserManager.addProfile(
@@ -257,7 +264,8 @@
 
     @Test
     public void testGetFragments_whenManagedProfile_returnsTwoFragments() {
-        mSetFlagsRule.disableFlags(Flags.FLAG_ALLOW_PRIVATE_PROFILE);
+        mSetFlagsRule.disableFlags(Flags.FLAG_ALLOW_PRIVATE_PROFILE,
+                android.multiuser.Flags.FLAG_ENABLE_PRIVATE_SPACE_FEATURES);
         mUserManager.addProfile(
                 new UserInfo(0, PRIMARY_USER_NAME, null, 0, USER_TYPE_FULL_SYSTEM));
         mUserManager.addProfile(
@@ -279,7 +287,8 @@
 
     @Test
     public void testGetFragments_whenAllProfiles_returnsThreeFragments() {
-        mSetFlagsRule.enableFlags(Flags.FLAG_ALLOW_PRIVATE_PROFILE);
+        mSetFlagsRule.enableFlags(Flags.FLAG_ALLOW_PRIVATE_PROFILE,
+                android.multiuser.Flags.FLAG_ENABLE_PRIVATE_SPACE_FEATURES);
         mUserManager.addProfile(
                 new UserInfo(0, PRIMARY_USER_NAME, null, 0, USER_TYPE_FULL_SYSTEM));
         mUserManager.addProfile(
@@ -303,7 +312,8 @@
 
     @Test
     public void testGetFragments_whenAvailableBundle_returnsFragmentsWithCorrectBundles() {
-        mSetFlagsRule.enableFlags(Flags.FLAG_ALLOW_PRIVATE_PROFILE);
+        mSetFlagsRule.enableFlags(Flags.FLAG_ALLOW_PRIVATE_PROFILE,
+                android.multiuser.Flags.FLAG_ENABLE_PRIVATE_SPACE_FEATURES);
         mUserManager.addProfile(
                 new UserInfo(0, PRIMARY_USER_NAME, null, 0, USER_TYPE_FULL_SYSTEM));
         mUserManager.addProfile(
@@ -343,10 +353,25 @@
 
         @Override
         public Fragment[] getFragments() {
+            Fragment personalFragment = new SettingsPreferenceFragmentTest.TestFragment();
+            Bundle personalBundle = new Bundle();
+            personalBundle.putInt(EXTRA_PROFILE, ProfileType.PERSONAL);
+            personalFragment.setArguments(personalBundle);
+
+            Fragment workFragment = new SettingsPreferenceFragmentTest.TestFragment();
+            Bundle workBundle = new Bundle();
+            workBundle.putInt(EXTRA_PROFILE, ProfileType.WORK);
+            workFragment.setArguments(workBundle);
+
+            Fragment privateFragment = new SettingsPreferenceFragmentTest.TestFragment();
+            Bundle privateBundle = new Bundle();
+            privateBundle.putInt(EXTRA_PROFILE, ProfileType.PRIVATE);
+            privateFragment.setArguments(privateBundle);
+
             return new Fragment[]{
-                    new SettingsPreferenceFragmentTest.TestFragment(), //0
-                    new SettingsPreferenceFragmentTest.TestFragment(),
-                    new SettingsPreferenceFragmentTest.TestFragment()
+                    personalFragment, //0
+                    privateFragment,
+                    workFragment
             };
         }
     }
diff --git a/tests/robotests/src/com/android/settings/development/quarantine/QuarantinedAppsScreenControllerTest.java b/tests/robotests/src/com/android/settings/development/quarantine/QuarantinedAppsScreenControllerTest.java
deleted file mode 100644
index a93e529..0000000
--- a/tests/robotests/src/com/android/settings/development/quarantine/QuarantinedAppsScreenControllerTest.java
+++ /dev/null
@@ -1,97 +0,0 @@
-/*
- * Copyright (C) 2023 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.settings.development.quarantine;
-
-import static org.mockito.AdditionalMatchers.aryEq;
-import static org.mockito.ArgumentMatchers.any;
-import static org.mockito.ArgumentMatchers.anyInt;
-import static org.mockito.ArgumentMatchers.eq;
-import static org.mockito.ArgumentMatchers.isNull;
-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.Context;
-import android.content.pm.ApplicationInfo;
-import android.content.pm.PackageManager;
-import android.content.pm.SuspendDialogInfo;
-import android.os.UserHandle;
-
-import androidx.test.core.app.ApplicationProvider;
-
-import com.android.settingslib.applications.ApplicationsState.AppEntry;
-
-import org.junit.Before;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.mockito.MockitoAnnotations;
-import org.robolectric.RobolectricTestRunner;
-
-@RunWith(RobolectricTestRunner.class)
-public class QuarantinedAppsScreenControllerTest {
-    private static final String PREF_KEY = "quarantined_apps_screen";
-    private static final String TEST_PACKAGE = "com.example.test.pkg";
-    private static final int TEST_APP_ID = 1234;
-    private static final int TEST_USER_ID = 10;
-
-    private Context mContext;
-    private QuarantinedAppsScreenController mController;
-
-    @Before
-    public void setUp() {
-        MockitoAnnotations.initMocks(this);
-        mContext = spy(ApplicationProvider.getApplicationContext());
-        mController = new QuarantinedAppsScreenController(mContext, PREF_KEY);
-    }
-
-    @Test
-    public void testOnPreferenceChange() {
-        final Context userContext = mock(Context.class);
-        doReturn(userContext).when(mContext).createContextAsUser(
-                eq(UserHandle.of(TEST_USER_ID)), anyInt());
-        final PackageManager packageManager = mock(PackageManager.class);
-        doReturn(packageManager).when(userContext).getPackageManager();
-
-        final AppEntry entry = createAppEntry(TEST_PACKAGE, TEST_APP_ID, TEST_USER_ID);
-        final QuarantinedAppPreference preference = new QuarantinedAppPreference(mContext, entry);
-
-        mController.onPreferenceChange(preference, true);
-        verify(packageManager).setPackagesSuspended(aryEq(new String[] {TEST_PACKAGE}), eq(true),
-                isNull(), isNull(), any(SuspendDialogInfo.class),
-                eq(PackageManager.FLAG_SUSPEND_QUARANTINED));
-
-        mController.onPreferenceChange(preference, false);
-        verify(packageManager).setPackagesSuspended(aryEq(new String[] {TEST_PACKAGE}), eq(false),
-                isNull(), isNull(), isNull(),
-                eq(PackageManager.FLAG_SUSPEND_QUARANTINED));
-    }
-
-    private AppEntry createAppEntry(String packageName, int appId, int userId) {
-        final AppEntry entry = mock(AppEntry.class);
-        entry.info = createApplicationInfo(packageName, appId, userId);
-        entry.extraInfo = false;
-        return entry;
-    }
-
-    private ApplicationInfo createApplicationInfo(String packageName, int appId, int userId) {
-        final ApplicationInfo info = new ApplicationInfo();
-        info.packageName = packageName;
-        info.uid = UserHandle.getUid(userId, appId);
-        return info;
-    }
-}
diff --git a/tests/spa_unit/src/com/android/settings/network/telephony/DataUsagePreferenceControllerTest.kt b/tests/spa_unit/src/com/android/settings/network/telephony/DataUsagePreferenceControllerTest.kt
index 5f80855..7124b6a 100644
--- a/tests/spa_unit/src/com/android/settings/network/telephony/DataUsagePreferenceControllerTest.kt
+++ b/tests/spa_unit/src/com/android/settings/network/telephony/DataUsagePreferenceControllerTest.kt
@@ -120,7 +120,7 @@
             on { loadFirstCycle() } doReturn usageData
         }
         controller.onViewCreated(TestLifecycleOwner())
-        waitUntil { preference.summary != null }
+        waitUntil { !preference.summary.isNullOrBlank() }
 
         controller.handlePreferenceTreeClick(preference)
 
diff --git a/tests/spa_unit/src/com/android/settings/network/telephony/MobileNetworkSwitchControllerTest.kt b/tests/spa_unit/src/com/android/settings/network/telephony/MobileNetworkSwitchControllerTest.kt
new file mode 100644
index 0000000..ca37082
--- /dev/null
+++ b/tests/spa_unit/src/com/android/settings/network/telephony/MobileNetworkSwitchControllerTest.kt
@@ -0,0 +1,168 @@
+/*
+ * 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.SubscriptionInfo
+import android.telephony.SubscriptionManager
+import androidx.compose.runtime.CompositionLocalProvider
+import androidx.compose.ui.platform.LocalContext
+import androidx.compose.ui.test.assertIsDisplayed
+import androidx.compose.ui.test.hasText
+import androidx.compose.ui.test.isOff
+import androidx.compose.ui.test.isOn
+import androidx.compose.ui.test.junit4.createComposeRule
+import androidx.compose.ui.test.onNodeWithText
+import androidx.test.core.app.ApplicationProvider
+import androidx.test.ext.junit.runners.AndroidJUnit4
+import com.android.settings.R
+import com.android.settingslib.spa.testutils.waitUntilExists
+import kotlinx.coroutines.flow.flowOf
+import org.junit.Rule
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.mockito.kotlin.any
+import org.mockito.kotlin.doNothing
+import org.mockito.kotlin.doReturn
+import org.mockito.kotlin.mock
+import org.mockito.kotlin.spy
+import org.mockito.kotlin.stub
+import org.mockito.kotlin.whenever
+
+@RunWith(AndroidJUnit4::class)
+class MobileNetworkSwitchControllerTest {
+    @get:Rule
+    val composeTestRule = createComposeRule()
+
+    private val mockSubscriptionManager = mock<SubscriptionManager> {
+        on { isSubscriptionEnabled(SUB_ID) } doReturn true
+    }
+
+    private val context: Context = spy(ApplicationProvider.getApplicationContext()) {
+        on { subscriptionManager } doReturn mockSubscriptionManager
+        doNothing().whenever(mock).startActivity(any())
+    }
+
+    private val mockSubscriptionRepository = mock<SubscriptionRepository> {
+        on { getSelectableSubscriptionInfoList() } doReturn listOf(SubInfo)
+        on { isSubscriptionEnabledFlow(SUB_ID) } doReturn flowOf(false)
+    }
+
+    private val controller = MobileNetworkSwitchController(
+        context = context,
+        preferenceKey = TEST_KEY,
+        subscriptionRepository = mockSubscriptionRepository,
+    ).apply { init(SUB_ID) }
+
+    @Test
+    fun isVisible_pSimAndCanDisablePhysicalSubscription_returnTrue() {
+        val pSimSubInfo = SubscriptionInfo.Builder().apply {
+            setId(SUB_ID)
+            setEmbedded(false)
+        }.build()
+        mockSubscriptionManager.stub {
+            on { canDisablePhysicalSubscription() } doReturn true
+        }
+        mockSubscriptionRepository.stub {
+            on { getSelectableSubscriptionInfoList() } doReturn listOf(pSimSubInfo)
+        }
+
+        setContent()
+
+        composeTestRule.onNodeWithText(context.getString(R.string.mobile_network_use_sim_on))
+            .assertIsDisplayed()
+    }
+
+    @Test
+    fun isVisible_pSimAndCannotDisablePhysicalSubscription_returnFalse() {
+        val pSimSubInfo = SubscriptionInfo.Builder().apply {
+            setId(SUB_ID)
+            setEmbedded(false)
+        }.build()
+        mockSubscriptionManager.stub {
+            on { canDisablePhysicalSubscription() } doReturn false
+        }
+        mockSubscriptionRepository.stub {
+            on { getSelectableSubscriptionInfoList() } doReturn listOf(pSimSubInfo)
+        }
+
+        setContent()
+
+        composeTestRule.onNodeWithText(context.getString(R.string.mobile_network_use_sim_on))
+            .assertDoesNotExist()
+    }
+
+    @Test
+    fun isVisible_eSim_returnTrue() {
+        val eSimSubInfo = SubscriptionInfo.Builder().apply {
+            setId(SUB_ID)
+            setEmbedded(true)
+        }.build()
+        mockSubscriptionRepository.stub {
+            on { getSelectableSubscriptionInfoList() } doReturn listOf(eSimSubInfo)
+        }
+
+        setContent()
+
+        composeTestRule.onNodeWithText(context.getString(R.string.mobile_network_use_sim_on))
+            .assertIsDisplayed()
+    }
+
+    @Test
+    fun isChecked_subscriptionEnabled_switchIsOn() {
+        mockSubscriptionRepository.stub {
+            on { isSubscriptionEnabledFlow(SUB_ID) } doReturn flowOf(true)
+        }
+
+        setContent()
+
+        composeTestRule.waitUntilExists(
+            hasText(context.getString(R.string.mobile_network_use_sim_on)) and isOn()
+        )
+    }
+
+    @Test
+    fun isChecked_subscriptionNotEnabled_switchIsOff() {
+        mockSubscriptionRepository.stub {
+            on { isSubscriptionEnabledFlow(SUB_ID) } doReturn flowOf(false)
+        }
+
+        setContent()
+
+        composeTestRule.waitUntilExists(
+            hasText(context.getString(R.string.mobile_network_use_sim_on)) and isOff()
+        )
+    }
+
+    private fun setContent() {
+        composeTestRule.setContent {
+            CompositionLocalProvider(LocalContext provides context) {
+                controller.Content()
+            }
+        }
+    }
+
+    private companion object {
+        const val TEST_KEY = "test_key"
+        const val SUB_ID = 123
+
+        val SubInfo: SubscriptionInfo = SubscriptionInfo.Builder().apply {
+            setId(SUB_ID)
+            setEmbedded(true)
+        }.build()
+    }
+}
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 a59bf93..80b3175 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
@@ -17,12 +17,14 @@
 package com.android.settings.network.telephony
 
 import android.content.Context
+import android.telephony.SubscriptionInfo
 import android.telephony.SubscriptionManager
 import androidx.test.core.app.ApplicationProvider
 import androidx.test.ext.junit.runners.AndroidJUnit4
 import com.android.settingslib.spa.testutils.firstWithTimeoutOrNull
 import com.android.settingslib.spa.testutils.toListWithTimeout
 import com.google.common.truth.Truth.assertThat
+import java.util.UUID
 import kotlinx.coroutines.async
 import kotlinx.coroutines.delay
 import kotlinx.coroutines.runBlocking
@@ -47,16 +49,16 @@
     }
 
     private val context: Context = spy(ApplicationProvider.getApplicationContext()) {
-        on { getSystemService(SubscriptionManager::class.java) } doReturn mockSubscriptionManager
+        on { subscriptionManager } doReturn mockSubscriptionManager
     }
 
     @Test
     fun isSubscriptionEnabledFlow() = runBlocking {
         mockSubscriptionManager.stub {
-            on { isSubscriptionEnabled(SUB_ID) } doReturn true
+            on { isSubscriptionEnabled(SUB_ID_1) } doReturn true
         }
 
-        val isEnabled = context.isSubscriptionEnabledFlow(SUB_ID).firstWithTimeoutOrNull()
+        val isEnabled = context.isSubscriptionEnabledFlow(SUB_ID_1).firstWithTimeoutOrNull()
 
         assertThat(isEnabled).isTrue()
     }
@@ -80,7 +82,69 @@
         assertThat(listDeferred.await()).hasSize(2)
     }
 
+    @Test
+    fun getSelectableSubscriptionInfoList_sortedBySubId() {
+        mockSubscriptionManager.stub {
+            on { getAvailableSubscriptionInfoList() } doReturn listOf(
+                SubscriptionInfo.Builder().apply {
+                    setId(SUB_ID_2)
+                }.build(),
+                SubscriptionInfo.Builder().apply {
+                    setId(SUB_ID_1)
+                }.build(),
+            )
+        }
+
+        val subInfos = context.getSelectableSubscriptionInfoList()
+
+        assertThat(subInfos.map { it.subscriptionId }).containsExactly(SUB_ID_1, SUB_ID_2).inOrder()
+    }
+
+    @Test
+    fun getSelectableSubscriptionInfoList_sameGroupAndOneHasSlot_returnTheOneWithSimSlotIndex() {
+        mockSubscriptionManager.stub {
+            on { getAvailableSubscriptionInfoList() } doReturn listOf(
+                SubscriptionInfo.Builder().apply {
+                    setId(SUB_ID_1)
+                    setGroupUuid(GROUP_UUID)
+                }.build(),
+                SubscriptionInfo.Builder().apply {
+                    setId(SUB_ID_2)
+                    setGroupUuid(GROUP_UUID)
+                    setSimSlotIndex(SIM_SLOT_INDEX)
+                }.build(),
+            )
+        }
+
+        val subInfos = context.getSelectableSubscriptionInfoList()
+
+        assertThat(subInfos.map { it.subscriptionId }).containsExactly(SUB_ID_2)
+    }
+
+    @Test
+    fun getSelectableSubscriptionInfoList_sameGroupAndNonHasSlot_returnTheOneWithMinimumSubId() {
+        mockSubscriptionManager.stub {
+            on { getAvailableSubscriptionInfoList() } doReturn listOf(
+                SubscriptionInfo.Builder().apply {
+                    setId(SUB_ID_2)
+                    setGroupUuid(GROUP_UUID)
+                }.build(),
+                SubscriptionInfo.Builder().apply {
+                    setId(SUB_ID_1)
+                    setGroupUuid(GROUP_UUID)
+                }.build(),
+            )
+        }
+
+        val subInfos = context.getSelectableSubscriptionInfoList()
+
+        assertThat(subInfos.map { it.subscriptionId }).containsExactly(SUB_ID_1)
+    }
+
     private companion object {
-        const val SUB_ID = 1
+        const val SUB_ID_1 = 1
+        const val SUB_ID_2 = 2
+        val GROUP_UUID = UUID.randomUUID().toString()
+        const val SIM_SLOT_INDEX = 1
     }
 }
diff --git a/tests/spa_unit/src/com/android/settings/network/telephony/scan/NetworkScanRepositoryTest.kt b/tests/spa_unit/src/com/android/settings/network/telephony/scan/NetworkScanRepositoryTest.kt
new file mode 100644
index 0000000..070c779
--- /dev/null
+++ b/tests/spa_unit/src/com/android/settings/network/telephony/scan/NetworkScanRepositoryTest.kt
@@ -0,0 +1,265 @@
+/*
+ * 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.scan
+
+import android.content.Context
+import android.telephony.AccessNetworkConstants.AccessNetworkType
+import android.telephony.CellIdentityCdma
+import android.telephony.CellIdentityGsm
+import android.telephony.CellIdentityLte
+import android.telephony.CellInfoCdma
+import android.telephony.CellInfoGsm
+import android.telephony.CellInfoLte
+import android.telephony.NetworkScan
+import android.telephony.NetworkScanRequest
+import android.telephony.PhoneCapability
+import android.telephony.TelephonyManager
+import android.telephony.TelephonyManager.NETWORK_CLASS_BITMASK_5G
+import android.telephony.TelephonyScanManager
+import androidx.test.core.app.ApplicationProvider
+import androidx.test.ext.junit.runners.AndroidJUnit4
+import com.android.settings.network.telephony.scan.NetworkScanRepository.NetworkScanCellInfos
+import com.android.settings.network.telephony.scan.NetworkScanRepository.NetworkScanComplete
+import com.android.settings.network.telephony.scan.NetworkScanRepository.NetworkScanError
+import com.android.settingslib.spa.testutils.firstWithTimeoutOrNull
+import com.android.settingslib.spa.testutils.toListWithTimeout
+import com.google.common.truth.Truth.assertThat
+import kotlinx.coroutines.async
+import kotlinx.coroutines.delay
+import kotlinx.coroutines.runBlocking
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.mockito.kotlin.any
+import org.mockito.kotlin.argThat
+import org.mockito.kotlin.doAnswer
+import org.mockito.kotlin.doReturn
+import org.mockito.kotlin.mock
+import org.mockito.kotlin.spy
+import org.mockito.kotlin.stub
+import org.mockito.kotlin.verify
+
+@RunWith(AndroidJUnit4::class)
+class NetworkScanRepositoryTest {
+
+    private var callback: TelephonyScanManager.NetworkScanCallback? = null
+
+    private val mockTelephonyManager = mock<TelephonyManager> {
+        on { createForSubscriptionId(SUB_ID) } doReturn mock
+        on { requestNetworkScan(any(), any(), any()) } doAnswer {
+            callback = it.arguments[2] as TelephonyScanManager.NetworkScanCallback
+            mock<NetworkScan>()
+        }
+    }
+
+    private val context: Context = spy(ApplicationProvider.getApplicationContext()) {
+        on { getSystemService(TelephonyManager::class.java) } doReturn mockTelephonyManager
+    }
+
+    private val repository = NetworkScanRepository(context, SUB_ID)
+
+    @Test
+    fun networkScanFlow_initial() = runBlocking {
+        val result = repository.networkScanFlow().firstWithTimeoutOrNull()
+
+        assertThat(result).isNull()
+    }
+
+    @Test
+    fun networkScanFlow_onResults(): Unit = runBlocking {
+        val cellInfos = listOf(CellInfoCdma().apply { cellIdentity = CELL_IDENTITY_CDMA })
+        val listDeferred = async {
+            repository.networkScanFlow().toListWithTimeout()
+        }
+        delay(100)
+
+        callback?.onResults(cellInfos)
+
+        assertThat(listDeferred.await()).containsExactly(NetworkScanCellInfos(cellInfos))
+    }
+
+    @Test
+    fun networkScanFlow_onComplete(): Unit = runBlocking {
+        val listDeferred = async {
+            repository.networkScanFlow().toListWithTimeout()
+        }
+        delay(100)
+
+        callback?.onComplete()
+
+        assertThat(listDeferred.await()).containsExactly(NetworkScanComplete)
+    }
+
+    @Test
+    fun networkScanFlow_onError(): Unit = runBlocking {
+        val listDeferred = async {
+            repository.networkScanFlow().toListWithTimeout()
+        }
+        delay(100)
+
+        callback?.onError(1)
+
+        assertThat(listDeferred.await()).containsExactly(NetworkScanError(1))
+    }
+
+    @Test
+    fun networkScanFlow_hasDuplicateItems(): Unit = runBlocking {
+        val cellInfos = listOf(
+            createCellInfoLte("123", false),
+            createCellInfoLte("123", false),
+            createCellInfoLte("124", true),
+            createCellInfoLte("124", true),
+            createCellInfoGsm("123", false),
+            createCellInfoGsm("123", false),
+        )
+        val listDeferred = async {
+            repository.networkScanFlow().toListWithTimeout()
+        }
+        delay(100)
+
+        callback?.onResults(cellInfos)
+
+        assertThat(listDeferred.await()).containsExactly(
+            NetworkScanCellInfos(
+                listOf(
+                    createCellInfoLte("123", false),
+                    createCellInfoLte("124", true),
+                    createCellInfoGsm("123", false),
+                )
+            )
+        )
+    }
+
+
+    @Test
+    fun networkScanFlow_noDuplicateItems(): Unit = runBlocking {
+        val cellInfos = listOf(
+            createCellInfoLte("123", false),
+            createCellInfoLte("123", true),
+            createCellInfoLte("124", false),
+            createCellInfoLte("124", true),
+            createCellInfoGsm("456", false),
+            createCellInfoGsm("456", true),
+        )
+        val listDeferred = async {
+            repository.networkScanFlow().toListWithTimeout()
+        }
+        delay(100)
+
+        callback?.onResults(cellInfos)
+
+        assertThat(listDeferred.await()).containsExactly(
+            NetworkScanCellInfos(
+                listOf(
+                    createCellInfoLte("123", false),
+                    createCellInfoLte("123", true),
+                    createCellInfoLte("124", false),
+                    createCellInfoLte("124", true),
+                    createCellInfoGsm("456", false),
+                    createCellInfoGsm("456", true),
+                )
+            )
+        )
+    }
+
+    @Test
+    fun createNetworkScan_deviceHasNrSa_requestNgran(): Unit = runBlocking {
+        mockTelephonyManager.stub {
+            on { getAllowedNetworkTypesBitmask() } doReturn NETWORK_CLASS_BITMASK_5G
+            on { getPhoneCapability() } doReturn
+                createPhoneCapability(intArrayOf(PhoneCapability.DEVICE_NR_CAPABILITY_SA))
+        }
+
+        repository.networkScanFlow().firstWithTimeoutOrNull()
+
+        verify(mockTelephonyManager).requestNetworkScan(argThat<NetworkScanRequest> {
+            specifiers.any { it.radioAccessNetwork == AccessNetworkType.NGRAN }
+        }, any(), any())
+    }
+
+    @Test
+    fun createNetworkScan_deviceNoNrSa_noNgran(): Unit = runBlocking {
+        mockTelephonyManager.stub {
+            on { getAllowedNetworkTypesBitmask() } doReturn NETWORK_CLASS_BITMASK_5G
+            on { getPhoneCapability() } doReturn
+                createPhoneCapability(intArrayOf(PhoneCapability.DEVICE_NR_CAPABILITY_NSA))
+        }
+
+        repository.networkScanFlow().firstWithTimeoutOrNull()
+
+        verify(mockTelephonyManager).requestNetworkScan(argThat<NetworkScanRequest> {
+            specifiers.none { it.radioAccessNetwork == AccessNetworkType.NGRAN }
+        }, any(), any())
+    }
+
+    private companion object {
+        const val SUB_ID = 1
+        const val LONG = "Long"
+        const val SHORT = "Short"
+
+        val CELL_IDENTITY_CDMA = CellIdentityCdma(
+            /* nid = */ 1,
+            /* sid = */ 2,
+            /* bid = */ 3,
+            /* lon = */ 4,
+            /* lat = */ 5,
+            /* alphal = */ LONG,
+            /* alphas = */ SHORT,
+        )
+
+        private fun createCellInfoLte(alphaLong: String, registered: Boolean): CellInfoLte {
+            val cellIdentityLte = CellIdentityLte(
+                /* ci = */ 1,
+                /* pci = */ 2,
+                /* tac = */ 3,
+                /* earfcn = */ 4,
+                /* bands = */ intArrayOf(1, 2),
+                /* bandwidth = */ 10000,
+                /* mccStr = */ null,
+                /* mncStr = */ null,
+                /* alphal = */ alphaLong,
+                /* alphas = */ null,
+                /* additionalPlmns = */ emptyList(),
+                /* csgInfo = */ null,
+            )
+            return CellInfoLte().apply {
+                cellIdentity = cellIdentityLte
+                isRegistered = registered
+            }
+        }
+
+        private fun createCellInfoGsm(alphaLong: String, registered: Boolean): CellInfoGsm {
+            val cellIdentityGsm = CellIdentityGsm(
+                /* lac = */ 1,
+                /* cid = */ 2,
+                /* arfcn = */ 3,
+                /* bsic = */ 4,
+                /* mccStr = */ "123",
+                /* mncStr = */ "01",
+                /* alphal = */ alphaLong,
+                /* alphas = */ null,
+                /* additionalPlmns = */ emptyList(),
+            )
+            return CellInfoGsm().apply {
+                cellIdentity = cellIdentityGsm
+                isRegistered = registered
+            }
+        }
+
+        private fun createPhoneCapability(deviceNrCapabilities: IntArray) =
+            PhoneCapability.Builder().setDeviceNrCapabilities(deviceNrCapabilities).build()
+    }
+}
diff --git a/tests/spa_unit/src/com/android/settings/spa/app/appcompat/UserAspectRatioAppsPageProviderTest.kt b/tests/spa_unit/src/com/android/settings/spa/app/appcompat/UserAspectRatioAppsPageProviderTest.kt
index dfacca8..b859df4 100644
--- a/tests/spa_unit/src/com/android/settings/spa/app/appcompat/UserAspectRatioAppsPageProviderTest.kt
+++ b/tests/spa_unit/src/com/android/settings/spa/app/appcompat/UserAspectRatioAppsPageProviderTest.kt
@@ -32,7 +32,11 @@
 import com.android.settingslib.spa.testutils.firstWithTimeoutOrNull
 import com.android.settingslib.spaprivileged.template.app.AppListItemModel
 import com.google.common.truth.Truth.assertThat
+import kotlinx.coroutines.ExperimentalCoroutinesApi
 import kotlinx.coroutines.flow.flowOf
+import kotlinx.coroutines.test.StandardTestDispatcher
+import kotlinx.coroutines.test.TestScope
+import kotlinx.coroutines.test.advanceUntilIdle
 import kotlinx.coroutines.test.runTest
 import org.junit.Rule
 import org.junit.Test
@@ -45,6 +49,8 @@
 class UserAspectRatioAppsPageProviderTest {
     @get:Rule
     val composeTestRule = createComposeRule()
+    private val testDispatcher = StandardTestDispatcher()
+    private val testScope = TestScope(testDispatcher)
 
     private val context: Context = ApplicationProvider.getApplicationContext()
     private val fakeNavControllerWrapper = FakeNavControllerWrapper()
@@ -137,33 +143,37 @@
         }
     }
 
+    @OptIn(ExperimentalCoroutinesApi::class)
     @Test
-    fun aspectRatioAppListModel_getSummaryDefault() {
-        val summary = getSummary(USER_MIN_ASPECT_RATIO_UNSET)
+    fun aspectRatioAppListModel_getSummaryDefault() = testScope.runTest {
+        val summary = setSummary(USER_MIN_ASPECT_RATIO_UNSET)
+        advanceUntilIdle()
 
-        assertThat(summary).isEqualTo(context.getString(R.string.user_aspect_ratio_app_default))
+        assertThat(summary()).isEqualTo(context.getString(R.string.user_aspect_ratio_app_default))
     }
 
+    @OptIn(ExperimentalCoroutinesApi::class)
     @Test
-    fun aspectRatioAppListModel_getSummaryWhenSplitScreen() {
-        val summary = getSummary(USER_MIN_ASPECT_RATIO_SPLIT_SCREEN)
+    fun aspectRatioAppListModel_getSummaryWhenSplitScreen() = testScope.runTest {
+        val summary = setSummary(USER_MIN_ASPECT_RATIO_SPLIT_SCREEN)
+        advanceUntilIdle()
 
-        assertThat(summary).isEqualTo(context.getString(R.string.user_aspect_ratio_half_screen))
+        assertThat(summary()).isEqualTo(context.getString(R.string.user_aspect_ratio_half_screen))
     }
 
-    private fun getSummary(userOverride: Int): String {
-        val listModel = UserAspectRatioAppListModel(context)
+    private fun setSummary(userOverride: Int): () -> String {
+        val listModel = UserAspectRatioAppListModel(context, testDispatcher)
+        val record = UserAspectRatioAppListItemModel(
+            app = APP,
+            userOverride = userOverride,
+            suggested = false,
+            canDisplay = true,
+        )
         lateinit var summary: () -> String
         composeTestRule.setContent {
-            summary = listModel.getSummary(option = 0,
-                record = UserAspectRatioAppListItemModel(
-                    app = APP,
-                    userOverride = userOverride,
-                    suggested = false,
-                    canDisplay = true,
-                ))
+            summary =  listModel.getSummary(option = 0, record = record)
         }
-        return summary()
+        return summary
     }
 
 
diff --git a/tests/uitests/src/com/android/settings/ui/SecuritySettingsTest.kt b/tests/uitests/src/com/android/settings/ui/SecuritySettingsTest.kt
index b5a4fe9..b792959 100644
--- a/tests/uitests/src/com/android/settings/ui/SecuritySettingsTest.kt
+++ b/tests/uitests/src/com/android/settings/ui/SecuritySettingsTest.kt
@@ -49,7 +49,8 @@
     }
 
     @Test
-    @RequiresFlagsEnabled(Flags.FLAG_ALLOW_PRIVATE_PROFILE)
+    @RequiresFlagsEnabled(Flags.FLAG_ALLOW_PRIVATE_PROFILE,
+            android.multiuser.Flags.FLAG_ENABLE_PRIVATE_SPACE_FEATURES)
     fun privateSpace_ifFlagON() {
         device.assertHasTexts(listOf("Private Space"))
     }
diff --git a/tests/uitests/src/com/android/settings/ui/privatespace/PrivateSpaceAuthenticationActivityTest.kt b/tests/uitests/src/com/android/settings/ui/privatespace/PrivateSpaceAuthenticationActivityTest.kt
index 8eadd9d..14feb49 100644
--- a/tests/uitests/src/com/android/settings/ui/privatespace/PrivateSpaceAuthenticationActivityTest.kt
+++ b/tests/uitests/src/com/android/settings/ui/privatespace/PrivateSpaceAuthenticationActivityTest.kt
@@ -38,7 +38,8 @@
 
 
 @RunWith(AndroidJUnit4::class)
-@RequiresFlagsEnabled(Flags.FLAG_ALLOW_PRIVATE_PROFILE)
+@RequiresFlagsEnabled(Flags.FLAG_ALLOW_PRIVATE_PROFILE,
+        android.multiuser.Flags.FLAG_ENABLE_PRIVATE_SPACE_FEATURES)
 class PrivateSpaceAuthenticationActivityTest {
     private val device = UiDevice.getInstance(InstrumentationRegistry.getInstrumentation())
 
diff --git a/tests/unit/src/com/android/settings/biometrics/combination/CombinedBiometricStatusUtilsTest.java b/tests/unit/src/com/android/settings/biometrics/combination/CombinedBiometricStatusUtilsTest.java
index a671a45..3a330f2 100644
--- a/tests/unit/src/com/android/settings/biometrics/combination/CombinedBiometricStatusUtilsTest.java
+++ b/tests/unit/src/com/android/settings/biometrics/combination/CombinedBiometricStatusUtilsTest.java
@@ -310,7 +310,8 @@
         when(mFaceManager.hasEnrolledTemplates(anyInt())).thenReturn(false);
         mSetFlagsRule.enableFlags(
                 android.os.Flags.FLAG_ALLOW_PRIVATE_PROFILE,
-                android.multiuser.Flags.FLAG_ENABLE_BIOMETRICS_TO_UNLOCK_PRIVATE_SPACE);
+                android.multiuser.Flags.FLAG_ENABLE_BIOMETRICS_TO_UNLOCK_PRIVATE_SPACE,
+                android.multiuser.Flags.FLAG_ENABLE_PRIVATE_SPACE_FEATURES);
 
         assertThat(mCombinedBiometricStatusUtils.getPrivateProfileSettingsClassName())
                 .isEqualTo(Settings.PrivateSpaceBiometricSettingsActivity.class.getName());
diff --git a/tests/unit/src/com/android/settings/development/quarantine/QuarantinedAppStateBridgeTest.java b/tests/unit/src/com/android/settings/development/quarantine/QuarantinedAppStateBridgeTest.java
deleted file mode 100644
index 707d2b9..0000000
--- a/tests/unit/src/com/android/settings/development/quarantine/QuarantinedAppStateBridgeTest.java
+++ /dev/null
@@ -1,90 +0,0 @@
-/*
- * Copyright (C) 2023 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.settings.development.quarantine;
-
-import static com.google.common.truth.Truth.assertThat;
-
-import static org.mockito.ArgumentMatchers.anyInt;
-import static org.mockito.ArgumentMatchers.eq;
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.when;
-
-import android.content.Context;
-import android.content.pm.PackageManager;
-import android.os.UserHandle;
-
-import androidx.test.ext.junit.runners.AndroidJUnit4;
-
-import com.android.settingslib.applications.ApplicationsState.AppEntry;
-
-import org.junit.Before;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.mockito.Mock;
-import org.mockito.MockitoAnnotations;
-
-@RunWith(AndroidJUnit4.class)
-public class QuarantinedAppStateBridgeTest {
-    private static final String TEST_PACKAGE = "com.example.test.pkg";
-    private static final int TEST_APP_ID = 1234;
-    private static final int TEST_USER_ID_1 = 0;
-    private static final int TEST_USER_ID_2 = 10;
-
-    @Mock
-    private Context mContext;
-
-    @Before
-    public void setUp() {
-        MockitoAnnotations.initMocks(this);
-    }
-
-    @Test
-    public void updateExtraInfo_packageQuarantined() throws Exception {
-        setPackageQuarantined(TEST_PACKAGE, TEST_USER_ID_1, false);
-        setPackageQuarantined(TEST_PACKAGE, TEST_USER_ID_2, true);
-
-        final QuarantinedAppStateBridge bridge =
-                new QuarantinedAppStateBridge(mContext, null, null);
-        final AppEntry entry = mock(AppEntry.class);
-
-        bridge.updateExtraInfo(entry, TEST_PACKAGE, UserHandle.getUid(TEST_USER_ID_2, TEST_APP_ID));
-        assertThat(entry.extraInfo).isEqualTo(true);
-    }
-
-    @Test
-    public void updateExtraInfo_packageNotQuarantined() throws Exception {
-        setPackageQuarantined(TEST_PACKAGE, TEST_USER_ID_1, false);
-        setPackageQuarantined(TEST_PACKAGE, TEST_USER_ID_2, false);
-
-        final QuarantinedAppStateBridge bridge =
-                new QuarantinedAppStateBridge(mContext, null, null);
-        final AppEntry entry = mock(AppEntry.class);
-
-        bridge.updateExtraInfo(entry, TEST_PACKAGE, UserHandle.getUid(TEST_USER_ID_2, TEST_APP_ID));
-        assertThat(entry.extraInfo).isEqualTo(false);
-    }
-
-    private void setPackageQuarantined(String packageName, int userId, boolean quarantined)
-            throws Exception {
-        final Context userContext = mock(Context.class);
-        when(mContext.createContextAsUser(eq(UserHandle.of(userId)), anyInt()))
-                .thenReturn(userContext);
-        final PackageManager packageManager = mock(PackageManager.class);
-        when(userContext.getPackageManager()).thenReturn(packageManager);
-        when(packageManager.isPackageQuarantined(packageName)).thenReturn(quarantined);
-    }
-}
diff --git a/tests/unit/src/com/android/settings/development/quarantine/QuarantinedAppsPreferenceControllerTest.java b/tests/unit/src/com/android/settings/development/quarantine/QuarantinedAppsPreferenceControllerTest.java
deleted file mode 100644
index 33e4392..0000000
--- a/tests/unit/src/com/android/settings/development/quarantine/QuarantinedAppsPreferenceControllerTest.java
+++ /dev/null
@@ -1,69 +0,0 @@
-/*
- * Copyright (C) 2023 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.settings.development.quarantine;
-
-import static com.android.settings.core.BasePreferenceController.AVAILABLE;
-import static com.android.settings.core.BasePreferenceController.CONDITIONALLY_UNAVAILABLE;
-
-import static org.junit.Assert.assertEquals;
-
-import android.content.Context;
-import android.content.pm.Flags;
-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;
-
-import androidx.test.ext.junit.runners.AndroidJUnit4;
-
-import org.junit.Before;
-import org.junit.Rule;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.mockito.Mock;
-import org.mockito.MockitoAnnotations;
-
-@RunWith(AndroidJUnit4.class)
-public class QuarantinedAppsPreferenceControllerTest {
-
-    private static final String PREF_KEY = "quarantined_apps";
-
-    @Rule
-    public final CheckFlagsRule mCheckFlagsRule = DeviceFlagsValueProvider.createCheckFlagsRule();
-
-    @Mock
-    private Context mContext;
-    private QuarantinedAppsPreferenceController mController;
-
-    @Before
-    public void setUp() {
-        MockitoAnnotations.initMocks(this);
-        mController = new QuarantinedAppsPreferenceController(mContext, PREF_KEY);
-    }
-
-    @Test
-    @RequiresFlagsEnabled(Flags.FLAG_QUARANTINED_ENABLED)
-    public void testAvailabilityStatus_flagEnabled() {
-        assertEquals(mController.getAvailabilityStatus(), AVAILABLE);
-    }
-
-    @Test
-    @RequiresFlagsDisabled(Flags.FLAG_QUARANTINED_ENABLED)
-    public void testAvailabilityStatus_flagDisabled() {
-        assertEquals(mController.getAvailabilityStatus(), CONDITIONALLY_UNAVAILABLE);
-    }
-}
diff --git a/tests/unit/src/com/android/settings/network/telephony/MobileNetworkSwitchControllerTest.java b/tests/unit/src/com/android/settings/network/telephony/MobileNetworkSwitchControllerTest.java
deleted file mode 100644
index ae10ca8..0000000
--- a/tests/unit/src/com/android/settings/network/telephony/MobileNetworkSwitchControllerTest.java
+++ /dev/null
@@ -1,275 +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.telephony;
-
-import static com.google.common.truth.Truth.assertThat;
-
-import static org.mockito.ArgumentMatchers.any;
-import static org.mockito.ArgumentMatchers.anyBoolean;
-import static org.mockito.ArgumentMatchers.eq;
-import static org.mockito.Mockito.doNothing;
-import static org.mockito.Mockito.doReturn;
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.spy;
-import static org.mockito.Mockito.times;
-import static org.mockito.Mockito.verify;
-import static org.mockito.Mockito.when;
-
-import android.content.Context;
-import android.content.Intent;
-import android.os.Bundle;
-import android.os.Looper;
-import android.platform.test.flag.junit.SetFlagsRule;
-import android.telephony.SubscriptionInfo;
-import android.telephony.SubscriptionManager;
-import android.telephony.TelephonyCallback;
-import android.telephony.TelephonyManager;
-import android.view.LayoutInflater;
-import android.view.View;
-import android.widget.LinearLayout;
-
-import androidx.preference.PreferenceManager;
-import androidx.preference.PreferenceScreen;
-import androidx.preference.PreferenceViewHolder;
-import androidx.test.annotation.UiThreadTest;
-import androidx.test.core.app.ApplicationProvider;
-
-import com.android.settings.flags.Flags;
-import com.android.settings.network.SubscriptionUtil;
-import com.android.settings.widget.SettingsMainSwitchPreference;
-
-import org.junit.After;
-import org.junit.Before;
-import org.junit.Rule;
-import org.junit.Test;
-import org.mockito.ArgumentCaptor;
-import org.mockito.Mock;
-import org.mockito.junit.MockitoJUnit;
-import org.mockito.junit.MockitoRule;
-
-import java.util.Arrays;
-import java.util.concurrent.Executor;
-
-public class MobileNetworkSwitchControllerTest {
-    @Rule
-    public final SetFlagsRule mSetFlagsRule = new SetFlagsRule();
-    @Rule
-    public final MockitoRule mMockitoRule = MockitoJUnit.rule();
-
-    @Mock
-    private SubscriptionManager mSubscriptionManager;
-    @Mock
-    private SubscriptionInfo mSubscription;
-    @Mock
-    private TelephonyManager mTelephonyManager;
-
-    private PreferenceScreen mScreen;
-    private PreferenceManager mPreferenceManager;
-    private SettingsMainSwitchPreference mSwitchBar;
-    private Context mContext;
-    private MobileNetworkSwitchController mController;
-    private int mSubId = 123;
-
-    @Before
-    public void setUp() {
-        mSetFlagsRule.disableFlags(Flags.FLAG_IS_DUAL_SIM_ONBOARDING_ENABLED);
-
-        if (Looper.myLooper() == null) {
-            Looper.prepare();
-        }
-        mContext = spy(ApplicationProvider.getApplicationContext());
-        when(mContext.getSystemService(SubscriptionManager.class)).thenReturn(mSubscriptionManager);
-        when(mSubscriptionManager.setSubscriptionEnabled(eq(mSubId), anyBoolean()))
-                .thenReturn(true);
-
-        when(mSubscription.isEmbedded()).thenReturn(true);
-        when(mSubscription.getSubscriptionId()).thenReturn(mSubId);
-        // Most tests want to have 2 available subscriptions so that the switch bar will show.
-        final SubscriptionInfo sub2 = mock(SubscriptionInfo.class);
-        when(sub2.getSubscriptionId()).thenReturn(456);
-        SubscriptionUtil.setAvailableSubscriptionsForTesting(Arrays.asList(mSubscription, sub2));
-
-        when(mContext.getSystemService(TelephonyManager.class)).thenReturn(mTelephonyManager);
-        when(mTelephonyManager.createForSubscriptionId(mSubId))
-                .thenReturn(mTelephonyManager);
-
-        final String key = "prefKey";
-        mController = new MobileNetworkSwitchController(mContext, key);
-        mController.init(mSubscription.getSubscriptionId());
-
-        mPreferenceManager = new PreferenceManager(mContext);
-        mScreen = mPreferenceManager.createPreferenceScreen(mContext);
-        mSwitchBar = new SettingsMainSwitchPreference(mContext);
-        mSwitchBar.setKey(key);
-        mSwitchBar.setTitle("123");
-        mScreen.addPreference(mSwitchBar);
-
-        final LayoutInflater inflater = LayoutInflater.from(mContext);
-        final View view = inflater.inflate(mSwitchBar.getLayoutResource(),
-                new LinearLayout(mContext), false);
-        final PreferenceViewHolder holder = PreferenceViewHolder.createInstanceForTests(view);
-        mSwitchBar.onBindViewHolder(holder);
-    }
-
-    @After
-    public void cleanUp() {
-        SubscriptionUtil.setAvailableSubscriptionsForTesting(null);
-    }
-
-    @Test
-    @UiThreadTest
-    public void isAvailable_pSIM_isNotAvailable() {
-        when(mSubscription.isEmbedded()).thenReturn(false);
-        mController.displayPreference(mScreen);
-        assertThat(mSwitchBar.isShowing()).isFalse();
-
-        when(mSubscriptionManager.canDisablePhysicalSubscription()).thenReturn(true);
-        mController.displayPreference(mScreen);
-        assertThat(mSwitchBar.isShowing()).isTrue();
-    }
-
-    @Test
-    @UiThreadTest
-    public void displayPreference_oneEnabledSubscription_switchBarNotHidden() {
-        doReturn(true).when(mSubscriptionManager).isActiveSubscriptionId(mSubId);
-        SubscriptionUtil.setAvailableSubscriptionsForTesting(Arrays.asList(mSubscription));
-        mController.displayPreference(mScreen);
-        assertThat(mSwitchBar.isShowing()).isTrue();
-    }
-
-    @Test
-    @UiThreadTest
-    public void displayPreference_oneDisabledSubscription_switchBarNotHidden() {
-        doReturn(false).when(mSubscriptionManager).isActiveSubscriptionId(mSubId);
-        SubscriptionUtil.setAvailableSubscriptionsForTesting(Arrays.asList(mSubscription));
-
-        mController.displayPreference(mScreen);
-
-        assertThat(mSwitchBar.isShowing()).isTrue();
-    }
-
-    @Test
-    @UiThreadTest
-    public void displayPreference_subscriptionEnabled_switchIsOn() {
-        when(mSubscriptionManager.isActiveSubscriptionId(mSubId)).thenReturn(true);
-        mController.displayPreference(mScreen);
-        assertThat(mSwitchBar.isShowing()).isTrue();
-        assertThat(mSwitchBar.isChecked()).isTrue();
-    }
-
-    @Test
-    @UiThreadTest
-    public void displayPreference_subscriptionDisabled_switchIsOff() {
-        when(mSubscriptionManager.isActiveSubscriptionId(mSubId)).thenReturn(false);
-
-        mController.displayPreference(mScreen);
-
-        assertThat(mSwitchBar.isShowing()).isTrue();
-        assertThat(mSwitchBar.isChecked()).isFalse();
-    }
-
-    @Test
-    @UiThreadTest
-    public void switchChangeListener_fromEnabledToDisabled_setSubscriptionEnabledCalledCorrectly() {
-        when(mSubscriptionManager.isActiveSubscriptionId(mSubId)).thenReturn(true);
-        mController.displayPreference(mScreen);
-        assertThat(mSwitchBar.isShowing()).isTrue();
-        assertThat(mSwitchBar.isChecked()).isTrue();
-
-        final ArgumentCaptor<Intent> intentCaptor = ArgumentCaptor.forClass(Intent.class);
-        doNothing().when(mContext).startActivity(intentCaptor.capture());
-
-        // set switch off then should start a Activity.
-        mSwitchBar.setChecked(false);
-
-        when(mSubscriptionManager.isActiveSubscriptionId(mSubId)).thenReturn(false);
-        // Simulate action of back from previous activity.
-        mController.displayPreference(mScreen);
-        Bundle extra = intentCaptor.getValue().getExtras();
-
-        verify(mContext, times(1)).startActivity(any());
-        assertThat(extra.getInt(ToggleSubscriptionDialogActivity.ARG_SUB_ID)).isEqualTo(mSubId);
-        assertThat(extra.getBoolean(ToggleSubscriptionDialogActivity.ARG_enable))
-                .isEqualTo(false);
-        assertThat(mSwitchBar.isChecked()).isFalse();
-    }
-
-    @Test
-    @UiThreadTest
-    public void switchChangeListener_fromEnabledToDisabled_setSubscriptionEnabledFailed() {
-        when(mSubscriptionManager.setSubscriptionEnabled(eq(mSubId), anyBoolean()))
-                .thenReturn(false);
-        when(mSubscriptionManager.isActiveSubscriptionId(mSubId)).thenReturn(true);
-        mController.displayPreference(mScreen);
-        assertThat(mSwitchBar.isShowing()).isTrue();
-        assertThat(mSwitchBar.isChecked()).isTrue();
-
-        final ArgumentCaptor<Intent> intentCaptor = ArgumentCaptor.forClass(Intent.class);
-        doNothing().when(mContext).startActivity(intentCaptor.capture());
-
-        // set switch off then should start a Activity.
-        mSwitchBar.setChecked(false);
-
-        // Simulate action of back from previous activity.
-        mController.displayPreference(mScreen);
-        Bundle extra = intentCaptor.getValue().getExtras();
-
-        verify(mContext, times(1)).startActivity(any());
-        assertThat(extra.getInt(ToggleSubscriptionDialogActivity.ARG_SUB_ID)).isEqualTo(mSubId);
-        assertThat(extra.getBoolean(ToggleSubscriptionDialogActivity.ARG_enable))
-                .isEqualTo(false);
-        assertThat(mSwitchBar.isChecked()).isTrue();
-    }
-
-    @Test
-    @UiThreadTest
-    public void switchChangeListener_fromDisabledToEnabled_setSubscriptionEnabledCalledCorrectly() {
-        when(mSubscriptionManager.isActiveSubscriptionId(mSubId)).thenReturn(false);
-        mController.displayPreference(mScreen);
-        assertThat(mSwitchBar.isShowing()).isTrue();
-        assertThat(mSwitchBar.isChecked()).isFalse();
-
-        final ArgumentCaptor<Intent> intentCaptor = ArgumentCaptor.forClass(Intent.class);
-        doNothing().when(mContext).startActivity(intentCaptor.capture());
-        mSwitchBar.setChecked(true);
-        Bundle extra = intentCaptor.getValue().getExtras();
-
-        verify(mContext, times(1)).startActivity(any());
-        assertThat(extra.getInt(ToggleSubscriptionDialogActivity.ARG_SUB_ID)).isEqualTo(mSubId);
-        assertThat(extra.getBoolean(ToggleSubscriptionDialogActivity.ARG_enable)).isEqualTo(true);
-    }
-    @Test
-    @UiThreadTest
-    public void onResumeAndonPause_registerAndUnregisterTelephonyCallback() {
-        mController.onResume();
-
-        verify(mTelephonyManager)
-                .registerTelephonyCallback(any(Executor.class), any(TelephonyCallback.class));
-
-        mController.onPause();
-        verify(mTelephonyManager)
-                .unregisterTelephonyCallback(any(TelephonyCallback.class));
-    }
-
-    @Test
-    @UiThreadTest
-    public void onPause_doNotRegisterAndUnregisterTelephonyCallback() {
-        mController.onPause();
-        verify(mTelephonyManager, times(0))
-                .unregisterTelephonyCallback(any(TelephonyCallback.class));
-    }
-}
diff --git a/tests/unit/src/com/android/settings/network/telephony/NetworkScanHelperTest.java b/tests/unit/src/com/android/settings/network/telephony/NetworkScanHelperTest.java
deleted file mode 100644
index f046c9a..0000000
--- a/tests/unit/src/com/android/settings/network/telephony/NetworkScanHelperTest.java
+++ /dev/null
@@ -1,260 +0,0 @@
-/*
- * Copyright (C) 2021 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.settings.network.telephony;
-
-import static com.google.common.truth.Truth.assertThat;
-
-import static org.junit.Assert.assertEquals;
-import static org.mockito.ArgumentMatchers.any;
-import static org.mockito.ArgumentMatchers.anyInt;
-import static org.mockito.Mockito.doAnswer;
-import static org.mockito.Mockito.doReturn;
-import static org.mockito.Mockito.spy;
-import static org.mockito.Mockito.times;
-import static org.mockito.Mockito.verify;
-import static org.mockito.Mockito.when;
-
-import android.telephony.AccessNetworkConstants;
-import android.telephony.CellInfo;
-import android.telephony.ModemInfo;
-import android.telephony.NetworkScan;
-import android.telephony.NetworkScanRequest;
-import android.telephony.PhoneCapability;
-import android.telephony.RadioAccessSpecifier;
-import android.telephony.TelephonyManager;
-import android.telephony.TelephonyScanManager;
-
-import androidx.test.ext.junit.runners.AndroidJUnit4;
-
-import org.junit.Before;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.mockito.ArgumentCaptor;
-import org.mockito.Mock;
-import org.mockito.MockitoAnnotations;
-import org.mockito.invocation.InvocationOnMock;
-import org.mockito.stubbing.Answer;
-
-import java.util.ArrayList;
-import java.util.List;
-import java.util.concurrent.Executor;
-import java.util.concurrent.ExecutorService;
-import java.util.concurrent.Executors;
-
-@RunWith(AndroidJUnit4.class)
-public class NetworkScanHelperTest {
-
-    @Mock
-    private TelephonyManager mTelephonyManager;
-    @Mock
-    private List<CellInfo> mCellInfos;
-    @Mock
-    private NetworkScanHelper.NetworkScanCallback mNetworkScanCallback;
-
-    private static final long THREAD_EXECUTION_TIMEOUT_MS = 3000L;
-
-    private ExecutorService mNetworkScanExecutor;
-    private NetworkScanHelper mNetworkScanHelper;
-
-    private static final int SCAN_ID = 1234;
-    private static final int SUB_ID = 1;
-
-    private NetworkScan mNetworkScan;
-
-    public class NetworkScanMock extends NetworkScan {
-        NetworkScanMock(int scanId, int subId) {
-            super(scanId, subId);
-        }
-
-        @Override
-        public void stopScan() {
-            return;
-        }
-    }
-
-    @Before
-    public void setUp() {
-        MockitoAnnotations.initMocks(this);
-
-        mNetworkScanExecutor = Executors.newFixedThreadPool(1);
-
-        mNetworkScanHelper = new NetworkScanHelper(mTelephonyManager,
-                mNetworkScanCallback, mNetworkScanExecutor);
-
-        mNetworkScan = spy(new NetworkScanMock(SCAN_ID, SUB_ID));
-    }
-
-    @Test
-    public void startNetworkScan_incrementalAndSuccess_completionWithResult() {
-        when(mCellInfos.size()).thenReturn(1);
-
-        doAnswer(new Answer() {
-            @Override
-            public Object answer(InvocationOnMock invocation) throws Throwable {
-                TelephonyScanManager.NetworkScanCallback callback =
-                        (TelephonyScanManager.NetworkScanCallback)
-                        (invocation.getArguments()[2]);
-                callback.onResults(mCellInfos);
-                callback.onComplete();
-                return mNetworkScan;
-            }
-        }).when(mTelephonyManager).requestNetworkScan(
-                any(NetworkScanRequest.class), any(Executor.class),
-                any(TelephonyScanManager.NetworkScanCallback.class));
-
-        ArgumentCaptor<List<CellInfo>> argument = ArgumentCaptor.forClass(List.class);
-
-        startNetworkScan_incremental(true);
-
-        verify(mNetworkScanCallback, times(1)).onResults(argument.capture());
-        List<CellInfo> actualResult = argument.getValue();
-        assertThat(actualResult.size()).isEqualTo(mCellInfos.size());
-        verify(mNetworkScanCallback, times(1)).onComplete();
-    }
-
-    @Test
-    public void startNetworkScan_incrementalAndImmediateFailure_failureWithErrorCode() {
-        doReturn(null).when(mTelephonyManager).requestNetworkScan(
-                any(NetworkScanRequest.class), any(Executor.class),
-                any(TelephonyScanManager.NetworkScanCallback.class));
-
-        startNetworkScan_incremental(true);
-
-        verify(mNetworkScanCallback, times(1)).onError(anyInt());
-    }
-
-    @Test
-    public void startNetworkScan_incrementalAndFailure_failureWithErrorCode() {
-        doAnswer(new Answer() {
-            @Override
-            public Object answer(InvocationOnMock invocation) throws Throwable {
-                TelephonyScanManager.NetworkScanCallback callback =
-                        (TelephonyScanManager.NetworkScanCallback)
-                        (invocation.getArguments()[2]);
-                callback.onError(NetworkScan.ERROR_MODEM_ERROR);
-                return mNetworkScan;
-            }
-        }).when(mTelephonyManager).requestNetworkScan(
-                any(NetworkScanRequest.class), any(Executor.class),
-                any(TelephonyScanManager.NetworkScanCallback.class));
-
-        startNetworkScan_incremental(true);
-
-        verify(mNetworkScanCallback, times(1)).onError(anyInt());
-    }
-
-    @Test
-    public void startNetworkScan_incrementalAndAbort_doStop() {
-        doReturn(mNetworkScan).when(mTelephonyManager).requestNetworkScan(
-                any(NetworkScanRequest.class), any(Executor.class),
-                any(TelephonyScanManager.NetworkScanCallback.class));
-
-        startNetworkScan_incremental(false);
-
-        verify(mNetworkScan, times(1)).stopScan();
-    }
-
-    @Test
-    public void createNetworkScanForPreferredAccessNetworks_deviceNoNrSa_noNgran() {
-        int[] deviceNrCapabilities = new int[]{PhoneCapability.DEVICE_NR_CAPABILITY_NSA};
-        PhoneCapability phoneCapability = createPhoneCapability(deviceNrCapabilities);
-        doReturn(TelephonyManager.NETWORK_CLASS_BITMASK_2G
-                | TelephonyManager.NETWORK_CLASS_BITMASK_3G
-                | TelephonyManager.NETWORK_CLASS_BITMASK_4G
-                | TelephonyManager.NETWORK_CLASS_BITMASK_5G).when(
-                mTelephonyManager).getPreferredNetworkTypeBitmask();
-        doReturn(phoneCapability).when(mTelephonyManager).getPhoneCapability();
-        List<RadioAccessSpecifier> radioAccessSpecifiers = new ArrayList<>();
-        radioAccessSpecifiers.add(
-                new RadioAccessSpecifier(AccessNetworkConstants.AccessNetworkType.GERAN, null,
-                        null));
-        radioAccessSpecifiers.add(
-                new RadioAccessSpecifier(AccessNetworkConstants.AccessNetworkType.UTRAN, null,
-                        null));
-        radioAccessSpecifiers.add(
-                new RadioAccessSpecifier(AccessNetworkConstants.AccessNetworkType.EUTRAN, null,
-                        null));
-        NetworkScanRequest expectedNetworkScanRequest = createNetworkScanRequest(
-                radioAccessSpecifiers);
-
-        assertEquals(expectedNetworkScanRequest,
-                mNetworkScanHelper.createNetworkScanForPreferredAccessNetworks());
-    }
-
-    @Test
-    public void createNetworkScanForPreferredAccessNetworks_deviceHasNrSa_hasNgran() {
-        int[] deviceNrCapabilities = new int[]{PhoneCapability.DEVICE_NR_CAPABILITY_NSA,
-                PhoneCapability.DEVICE_NR_CAPABILITY_SA};
-        PhoneCapability phoneCapability = createPhoneCapability(deviceNrCapabilities);
-        doReturn(TelephonyManager.NETWORK_CLASS_BITMASK_2G
-                | TelephonyManager.NETWORK_CLASS_BITMASK_3G
-                | TelephonyManager.NETWORK_CLASS_BITMASK_4G
-                | TelephonyManager.NETWORK_CLASS_BITMASK_5G).when(
-                mTelephonyManager).getPreferredNetworkTypeBitmask();
-        doReturn(phoneCapability).when(mTelephonyManager).getPhoneCapability();
-        List<RadioAccessSpecifier> radioAccessSpecifiers = new ArrayList<>();
-        radioAccessSpecifiers.add(
-                new RadioAccessSpecifier(AccessNetworkConstants.AccessNetworkType.GERAN, null,
-                        null));
-        radioAccessSpecifiers.add(
-                new RadioAccessSpecifier(AccessNetworkConstants.AccessNetworkType.UTRAN, null,
-                        null));
-        radioAccessSpecifiers.add(
-                new RadioAccessSpecifier(AccessNetworkConstants.AccessNetworkType.EUTRAN, null,
-                        null));
-        radioAccessSpecifiers.add(
-                new RadioAccessSpecifier(AccessNetworkConstants.AccessNetworkType.NGRAN, null,
-                        null));
-        NetworkScanRequest expectedNetworkScanRequest = createNetworkScanRequest(
-                radioAccessSpecifiers);
-
-        assertEquals(expectedNetworkScanRequest,
-                mNetworkScanHelper.createNetworkScanForPreferredAccessNetworks());
-    }
-
-    private PhoneCapability createPhoneCapability(int[] deviceNrCapabilities) {
-        int maxActiveVoiceCalls = 1;
-        int maxActiveData = 2;
-        ModemInfo modemInfo = new ModemInfo(1, 2, true, false);
-        List<ModemInfo> logicalModemList = new ArrayList<>();
-        logicalModemList.add(modemInfo);
-        return new PhoneCapability(maxActiveVoiceCalls, maxActiveData,
-                logicalModemList, false, deviceNrCapabilities);
-    }
-
-    private NetworkScanRequest createNetworkScanRequest(
-            List<RadioAccessSpecifier> radioAccessSpecifiers) {
-        return new NetworkScanRequest(
-                NetworkScanRequest.SCAN_TYPE_ONE_SHOT,
-                radioAccessSpecifiers.toArray(
-                        new RadioAccessSpecifier[radioAccessSpecifiers.size()]),
-                mNetworkScanHelper.SEARCH_PERIODICITY_SEC,
-                mNetworkScanHelper.MAX_SEARCH_TIME_SEC,
-                mNetworkScanHelper.INCREMENTAL_RESULTS,
-                mNetworkScanHelper.INCREMENTAL_RESULTS_PERIODICITY_SEC,
-                null /* List of PLMN ids (MCC-MNC) */);
-    }
-
-    private void startNetworkScan_incremental(boolean waitForCompletion) {
-        mNetworkScanHelper.startNetworkScan(
-                NetworkScanHelper.NETWORK_SCAN_TYPE_INCREMENTAL_RESULTS);
-        if (!waitForCompletion) {
-            mNetworkScanHelper.stopNetworkQuery();
-        }
-    }
-
-}
diff --git a/tests/unit/src/com/android/settings/network/telephony/NetworkSelectSettingsTest.java b/tests/unit/src/com/android/settings/network/telephony/NetworkSelectSettingsTest.java
index 512e484..a4657ce 100644
--- a/tests/unit/src/com/android/settings/network/telephony/NetworkSelectSettingsTest.java
+++ b/tests/unit/src/com/android/settings/network/telephony/NetworkSelectSettingsTest.java
@@ -83,7 +83,6 @@
 
     public Context mContext;
     public PreferenceCategory mPreferenceCategory;
-    public boolean mIsAggregationEnabled = true;
 
     private TargetClass mNetworkSelectSettings;
 
@@ -104,7 +103,6 @@
         doReturn(mCellId2).when(mCellInfo2).getCellIdentity();
         doReturn(mock(CellSignalStrength.class)).when(mCellInfo2).getCellSignalStrength();
         doReturn(CARRIER_NAME2).when(mCellId2).getOperatorAlphaLong();
-        mIsAggregationEnabled = true;
         mNetworkSelectSettings = spy(new TargetClass(this));
 
         PersistableBundle config = new PersistableBundle();
@@ -177,11 +175,6 @@
         }
 
         @Override
-        protected boolean enableAggregation(Context context) {
-            return mTestEnv.mIsAggregationEnabled;
-        }
-
-        @Override
         protected int getSubId() {
             return SUB_ID;
         }
@@ -212,84 +205,7 @@
     }
 
     @Test
-    public void doAggregation_hasDuplicateItemsDiffCellIdCase1_removeSamePlmnRatItem() {
-        mNetworkSelectSettings.onCreateInitialization();
-        List<CellInfo> testList = Arrays.asList(
-                createLteCellInfo(true, 123, "123", "232", "CarrierA"),
-                createLteCellInfo(true, 1234, "123", "232", "CarrierA"),
-                createGsmCellInfo(false, 123, "123", "232", "CarrierB"));
-        List<CellInfo> expected = Arrays.asList(
-                createLteCellInfo(true, 123, "123", "232", "CarrierA"),
-                createGsmCellInfo(false, 123, "123", "232", "CarrierB"));
-        assertThat(mNetworkSelectSettings.doAggregation(testList)).isEqualTo(expected);
-    }
-
-    @Test
-    public void doAggregation_hasDuplicateItemsDiffCellIdCase2_removeSamePlmnRatItem() {
-        mNetworkSelectSettings.onCreateInitialization();
-        List<CellInfo> testList = Arrays.asList(
-                createLteCellInfo(true, 123, "123", "232", "CarrierA"),
-                createGsmCellInfo(false, 123, "123", "232", "CarrierB"),
-                createLteCellInfo(false, 1234, "123", "232", "CarrierB"),
-                createGsmCellInfo(false, 1234, "123", "232", "CarrierB"));
-        List<CellInfo> expected = Arrays.asList(
-                createLteCellInfo(true, 123, "123", "232", "CarrierA"),
-                createGsmCellInfo(false, 123, "123", "232", "CarrierB"),
-                createLteCellInfo(false, 1234, "123", "232", "CarrierB"));
-        assertThat(mNetworkSelectSettings.doAggregation(testList)).isEqualTo(expected);
-    }
-
-    @Test
-    public void doAggregation_hasDuplicateItemsDiffMccMncCase1_removeSamePlmnRatItem() {
-        mNetworkSelectSettings.onCreateInitialization();
-        List<CellInfo> testList = Arrays.asList(
-                createLteCellInfo(true, 123, "123", "232", "CarrierA"),
-                createLteCellInfo(true, 123, "456", "232", "CarrierA"),
-                createGsmCellInfo(false, 123, "123", "232", "CarrierB"));
-        List<CellInfo> expected = Arrays.asList(
-                createLteCellInfo(true, 123, "123", "232", "CarrierA"),
-                createGsmCellInfo(false, 123, "123", "232", "CarrierB"));
-        assertThat(mNetworkSelectSettings.doAggregation(testList)).isEqualTo(expected);
-    }
-
-    @Test
-    public void doAggregation_hasDuplicateItemsDiffMccMncCase2_removeSamePlmnRatItem() {
-        mNetworkSelectSettings.onCreateInitialization();
-        List<CellInfo> testList = Arrays.asList(
-                createLteCellInfo(true, 123, "123", "232", "CarrierA"),
-                createGsmCellInfo(false, 123, "123", "232", "CarrierB"),
-                createLteCellInfo(false, 1234, "123", "232", "CarrierB"),
-                createGsmCellInfo(false, 123, "456", "232", "CarrierB"));
-        List<CellInfo> expected = Arrays.asList(
-                createLteCellInfo(true, 123, "123", "232", "CarrierA"),
-                createGsmCellInfo(false, 123, "123", "232", "CarrierB"),
-                createLteCellInfo(false, 1234, "123", "232", "CarrierB"));
-        assertThat(mNetworkSelectSettings.doAggregation(testList)).isEqualTo(expected);
-    }
-
-    @Test
-    public void doAggregation_hasDuplicateItemsDiffMccMncCase3_removeSamePlmnRatItem() {
-        PersistableBundle config = new PersistableBundle();
-        config.putBoolean(
-                CarrierConfigManager.KEY_REMOVE_SATELLITE_PLMN_IN_MANUAL_NETWORK_SCAN_BOOL, false);
-        doReturn(config).when(mCarrierConfigManager).getConfigForSubId(eq(SUB_ID),
-                eq(CarrierConfigManager.KEY_SHOW_4G_FOR_LTE_DATA_ICON_BOOL),
-                eq(CarrierConfigManager.KEY_REMOVE_SATELLITE_PLMN_IN_MANUAL_NETWORK_SCAN_BOOL));
-
-        mNetworkSelectSettings.onCreateInitialization();
-        List<CellInfo> testList = Arrays.asList(
-                createLteCellInfo(false, 123, "123", "232", "CarrierA"),
-                createLteCellInfo(false, 124, "123", "233", "CarrierA"),
-                createLteCellInfo(true, 125, "123", "234", "CarrierA"),
-                createGsmCellInfo(false, 126, "456", "232", "CarrierA"));
-        List<CellInfo> expected = Arrays.asList(
-                createLteCellInfo(true, 125, "123", "234", "CarrierA"),
-                createGsmCellInfo(false, 126, "456", "232", "CarrierA"));
-        assertThat(mNetworkSelectSettings.doAggregation(testList)).isEqualTo(expected);
-    }
-
-    @Test
-    public void doAggregation_filterOutSatellitePlmn_whenKeyIsTrue() {
+    public void filterOutSatellitePlmn_filterOutSatellitePlmn_whenKeyIsTrue() {
         PersistableBundle config = new PersistableBundle();
         config.putBoolean(
                 CarrierConfigManager.KEY_REMOVE_SATELLITE_PLMN_IN_MANUAL_NETWORK_SCAN_BOOL, true);
@@ -313,11 +229,11 @@
         List<CellInfo> expected = Arrays.asList(
                 createGsmCellInfo(false, 123, "123", "233", "CarrierB"),
                 createLteCellInfo(false, 1234, "123", "234", "CarrierC"));
-        assertThat(mNetworkSelectSettings.doAggregation(testList)).isEqualTo(expected);
+        assertThat(mNetworkSelectSettings.filterOutSatellitePlmn(testList)).isEqualTo(expected);
     }
 
     @Test
-    public void doAggregation_filterOutSatellitePlmn_whenNoSatellitePlmnIsAvailable() {
+    public void filterOutSatellitePlmn_filterOutSatellitePlmn_whenNoSatellitePlmnIsAvailable() {
         PersistableBundle config = new PersistableBundle();
         config.putBoolean(
                 CarrierConfigManager.KEY_REMOVE_SATELLITE_PLMN_IN_MANUAL_NETWORK_SCAN_BOOL, true);
@@ -345,17 +261,17 @@
                 createGsmCellInfo(false, 123, "123", "233", "CarrierB"),
                 createLteCellInfo(false, 1234, "123", "234", "CarrierC"),
                 createGsmCellInfo(false, 12345, "123", "235", "CarrierD"));
-        assertThat(mNetworkSelectSettings.doAggregation(testList)).isEqualTo(expected);
+        assertThat(mNetworkSelectSettings.filterOutSatellitePlmn(testList)).isEqualTo(expected);
 
         // Expect no filter out when KEY_REMOVE_SATELLITE_PLMN_IN_MANUAL_NETWORK_SCAN_BOOL is false.
         config.putBoolean(
                 CarrierConfigManager.KEY_REMOVE_SATELLITE_PLMN_IN_MANUAL_NETWORK_SCAN_BOOL, false);
         mNetworkSelectSettings.onCreateInitialization();
-        assertThat(mNetworkSelectSettings.doAggregation(testList)).isEqualTo(expected);
+        assertThat(mNetworkSelectSettings.filterOutSatellitePlmn(testList)).isEqualTo(expected);
     }
 
     @Test
-    public void doAggregation_filterOutSatellitePlmn_whenKeyIsFalse() {
+    public void filterOutSatellitePlmn_filterOutSatellitePlmn_whenKeyIsFalse() {
         PersistableBundle config = new PersistableBundle();
         config.putBoolean(
                 CarrierConfigManager.KEY_REMOVE_SATELLITE_PLMN_IN_MANUAL_NETWORK_SCAN_BOOL, true);
@@ -381,7 +297,7 @@
                 createGsmCellInfo(false, 123, "123", "233", "CarrierB"),
                 createLteCellInfo(false, 1234, "123", "234", "CarrierC"),
                 createGsmCellInfo(false, 12345, "123", "235", "CarrierD"));
-        assertThat(mNetworkSelectSettings.doAggregation(testList)).isEqualTo(expected);
+        assertThat(mNetworkSelectSettings.filterOutSatellitePlmn(testList)).isEqualTo(expected);
     }
 
     private CellInfoLte createLteCellInfo(boolean registered, int cellId, String mcc, String mnc,
diff --git a/tests/unit/src/com/android/settings/privatespace/FaceFingerprintUnlockControllerTest.java b/tests/unit/src/com/android/settings/privatespace/FaceFingerprintUnlockControllerTest.java
index f1da363..857135f 100644
--- a/tests/unit/src/com/android/settings/privatespace/FaceFingerprintUnlockControllerTest.java
+++ b/tests/unit/src/com/android/settings/privatespace/FaceFingerprintUnlockControllerTest.java
@@ -75,7 +75,8 @@
     public void getAvailabilityStatus_whenFlagsEnabled_returnsAvailable() {
         mSetFlagsRule.enableFlags(
                 android.os.Flags.FLAG_ALLOW_PRIVATE_PROFILE,
-                android.multiuser.Flags.FLAG_ENABLE_BIOMETRICS_TO_UNLOCK_PRIVATE_SPACE);
+                android.multiuser.Flags.FLAG_ENABLE_BIOMETRICS_TO_UNLOCK_PRIVATE_SPACE,
+                android.multiuser.Flags.FLAG_ENABLE_PRIVATE_SPACE_FEATURES);
 
         assertThat(mFaceFingerprintUnlockController.isAvailable()).isEqualTo(true);
     }
@@ -83,18 +84,33 @@
     /** Tests that the controller is not available when Biometrics flag is not enabled. */
     @Test
     public void getAvailabilityStatus_whenBiometricFlagDisabled_returnsFalse() {
-        mSetFlagsRule.enableFlags(android.os.Flags.FLAG_ALLOW_PRIVATE_PROFILE);
+        mSetFlagsRule.enableFlags(android.os.Flags.FLAG_ALLOW_PRIVATE_PROFILE,
+                android.multiuser.Flags.FLAG_ENABLE_PRIVATE_SPACE_FEATURES);
         mSetFlagsRule.disableFlags(
                 android.multiuser.Flags.FLAG_ENABLE_BIOMETRICS_TO_UNLOCK_PRIVATE_SPACE);
 
         assertThat(mFaceFingerprintUnlockController.isAvailable()).isEqualTo(false);
     }
 
-    /** Tests that the controller is not available when private feature flag is not enabled. */
+    /**
+     * Tests that the controller is not available when the main private space flag is not
+     * enabled.
+     */
     @Test
-    public void getAvailabilityStatus_whenPrivateFlagDisabled_returnsFalse() {
+    public void getAvailabilityStatus_whenPsMainFlagDisabled_returnsFalse() {
         mSetFlagsRule.disableFlags(android.os.Flags.FLAG_ALLOW_PRIVATE_PROFILE);
         mSetFlagsRule.enableFlags(
+                android.multiuser.Flags.FLAG_ENABLE_BIOMETRICS_TO_UNLOCK_PRIVATE_SPACE,
+                android.multiuser.Flags.FLAG_ENABLE_PRIVATE_SPACE_FEATURES);
+
+        assertThat(mFaceFingerprintUnlockController.isAvailable()).isEqualTo(false);
+    }
+
+    /** Tests that the controller is not available when private features flag is not enabled. */
+    @Test
+    public void getAvailabilityStatus_whenPsFeaturesFlagDisabled_returnsFalse() {
+        mSetFlagsRule.disableFlags(android.multiuser.Flags.FLAG_ENABLE_PRIVATE_SPACE_FEATURES);
+        mSetFlagsRule.enableFlags(android.os.Flags.FLAG_ALLOW_PRIVATE_PROFILE,
                 android.multiuser.Flags.FLAG_ENABLE_BIOMETRICS_TO_UNLOCK_PRIVATE_SPACE);
 
         assertThat(mFaceFingerprintUnlockController.isAvailable()).isEqualTo(false);
@@ -106,7 +122,8 @@
         doReturn(false).when(mLockPatternUtils).isSeparateProfileChallengeEnabled(anyInt());
         mSetFlagsRule.enableFlags(
                 android.os.Flags.FLAG_ALLOW_PRIVATE_PROFILE,
-                android.multiuser.Flags.FLAG_ENABLE_BIOMETRICS_TO_UNLOCK_PRIVATE_SPACE);
+                android.multiuser.Flags.FLAG_ENABLE_BIOMETRICS_TO_UNLOCK_PRIVATE_SPACE,
+                android.multiuser.Flags.FLAG_ENABLE_PRIVATE_SPACE_FEATURES);
 
         mFaceFingerprintUnlockController.updateState(mPreference);
         assertThat(mPreference.isEnabled()).isFalse();
@@ -119,7 +136,8 @@
         doReturn(true).when(mLockPatternUtils).isSeparateProfileChallengeEnabled(anyInt());
         mSetFlagsRule.enableFlags(
                 android.os.Flags.FLAG_ALLOW_PRIVATE_PROFILE,
-                android.multiuser.Flags.FLAG_ENABLE_BIOMETRICS_TO_UNLOCK_PRIVATE_SPACE);
+                android.multiuser.Flags.FLAG_ENABLE_BIOMETRICS_TO_UNLOCK_PRIVATE_SPACE,
+                android.multiuser.Flags.FLAG_ENABLE_PRIVATE_SPACE_FEATURES);
 
         mFaceFingerprintUnlockController.updateState(mPreference);
         assertThat(mPreference.isEnabled()).isTrue();
diff --git a/tests/unit/src/com/android/settings/privatespace/HidePrivateSpaceControllerTest.java b/tests/unit/src/com/android/settings/privatespace/HidePrivateSpaceControllerTest.java
index 0abe314..b71547b 100644
--- a/tests/unit/src/com/android/settings/privatespace/HidePrivateSpaceControllerTest.java
+++ b/tests/unit/src/com/android/settings/privatespace/HidePrivateSpaceControllerTest.java
@@ -40,7 +40,8 @@
 import org.junit.runner.RunWith;
 
 @RunWith(AndroidJUnit4.class)
-@RequiresFlagsEnabled(Flags.FLAG_ALLOW_PRIVATE_PROFILE)
+@RequiresFlagsEnabled({Flags.FLAG_ALLOW_PRIVATE_PROFILE,
+        android.multiuser.Flags.FLAG_ENABLE_PRIVATE_SPACE_FEATURES})
 public class HidePrivateSpaceControllerTest {
     @Rule
     public final CheckFlagsRule mCheckFlagsRule =
diff --git a/tests/unit/src/com/android/settings/privatespace/HidePrivateSpaceSensitiveNotificationsControllerTest.java b/tests/unit/src/com/android/settings/privatespace/HidePrivateSpaceSensitiveNotificationsControllerTest.java
index 1430dfd..88503a5 100644
--- a/tests/unit/src/com/android/settings/privatespace/HidePrivateSpaceSensitiveNotificationsControllerTest.java
+++ b/tests/unit/src/com/android/settings/privatespace/HidePrivateSpaceSensitiveNotificationsControllerTest.java
@@ -67,7 +67,8 @@
 
         mSetFlagsRule.enableFlags(
                 android.multiuser.Flags.FLAG_ENABLE_PS_SENSITIVE_NOTIFICATIONS_TOGGLE);
-        mSetFlagsRule.enableFlags(android.os.Flags.FLAG_ALLOW_PRIVATE_PROFILE);
+        mSetFlagsRule.enableFlags(android.os.Flags.FLAG_ALLOW_PRIVATE_PROFILE,
+                android.multiuser.Flags.FLAG_ENABLE_PRIVATE_SPACE_FEATURES);
 
         mPrivateProfileId = PrivateSpaceMaintainer.getInstance(
                 mContext).getPrivateProfileHandle().getIdentifier();
@@ -143,7 +144,8 @@
     public void getAvailabilityStatus_flagDisabled() {
         mSetFlagsRule.disableFlags(
                 android.multiuser.Flags.FLAG_ENABLE_PS_SENSITIVE_NOTIFICATIONS_TOGGLE);
-        mSetFlagsRule.disableFlags(android.os.Flags.FLAG_ALLOW_PRIVATE_PROFILE);
+        mSetFlagsRule.disableFlags(android.os.Flags.FLAG_ALLOW_PRIVATE_PROFILE,
+                android.multiuser.Flags.FLAG_ENABLE_PRIVATE_SPACE_FEATURES);
         Settings.Secure.putInt(mContext.getContentResolver(),
                 Settings.Secure.LOCK_SCREEN_SHOW_NOTIFICATIONS, 1);
         Settings.Secure.putInt(mContext.getContentResolver(),
diff --git a/tests/unit/src/com/android/settings/privatespace/HidePrivateSpaceSummaryControllerTest.java b/tests/unit/src/com/android/settings/privatespace/HidePrivateSpaceSummaryControllerTest.java
index 39f7b9c..ed072d3 100644
--- a/tests/unit/src/com/android/settings/privatespace/HidePrivateSpaceSummaryControllerTest.java
+++ b/tests/unit/src/com/android/settings/privatespace/HidePrivateSpaceSummaryControllerTest.java
@@ -40,7 +40,8 @@
 import org.junit.runner.RunWith;
 
 @RunWith(AndroidJUnit4.class)
-@RequiresFlagsEnabled(Flags.FLAG_ALLOW_PRIVATE_PROFILE)
+@RequiresFlagsEnabled({Flags.FLAG_ALLOW_PRIVATE_PROFILE,
+        android.multiuser.Flags.FLAG_ENABLE_PRIVATE_SPACE_FEATURES})
 public class HidePrivateSpaceSummaryControllerTest {
     @Rule
     public final CheckFlagsRule mCheckFlagsRule =
diff --git a/tests/unit/src/com/android/settings/privatespace/PrivateSpaceAuthenticationActivityTest.java b/tests/unit/src/com/android/settings/privatespace/PrivateSpaceAuthenticationActivityTest.java
index 4c6feea..8a7bd70 100644
--- a/tests/unit/src/com/android/settings/privatespace/PrivateSpaceAuthenticationActivityTest.java
+++ b/tests/unit/src/com/android/settings/privatespace/PrivateSpaceAuthenticationActivityTest.java
@@ -88,7 +88,8 @@
     /** Tests that when Private does not exist setup flow is started. */
     //TODO(b/307729746) Plan to add more tests for complete setup flow
     @Test
-    @RequiresFlagsEnabled(Flags.FLAG_ALLOW_PRIVATE_PROFILE)
+    @RequiresFlagsEnabled({Flags.FLAG_ALLOW_PRIVATE_PROFILE,
+            android.multiuser.Flags.FLAG_ENABLE_PRIVATE_SPACE_FEATURES})
     public void whenPrivateProfileDoesNotExist_triggersSetupFlow() {
         when(mPrivateSpaceMaintainer.doesPrivateSpaceExist()).thenReturn(false);
 
diff --git a/tests/unit/src/com/android/settings/privatespace/PrivateSpaceLockControllerTest.java b/tests/unit/src/com/android/settings/privatespace/PrivateSpaceLockControllerTest.java
index 0d9db7e..c203a3c 100644
--- a/tests/unit/src/com/android/settings/privatespace/PrivateSpaceLockControllerTest.java
+++ b/tests/unit/src/com/android/settings/privatespace/PrivateSpaceLockControllerTest.java
@@ -80,7 +80,8 @@
     /** Tests that the controller is always available. */
     @Test
     public void getAvailabilityStatus_returnsAvailable() {
-        mSetFlagsRule.enableFlags(Flags.FLAG_ALLOW_PRIVATE_PROFILE);
+        mSetFlagsRule.enableFlags(Flags.FLAG_ALLOW_PRIVATE_PROFILE,
+                android.multiuser.Flags.FLAG_ENABLE_PRIVATE_SPACE_FEATURES);
 
         assertThat(mPrivateSpaceLockController.isAvailable()).isEqualTo(true);
     }
@@ -89,7 +90,8 @@
     @Test
     public void getSummary_whenScreenLock() {
         doReturn(false).when(mLockPatternUtils).isSeparateProfileChallengeEnabled(anyInt());
-        mSetFlagsRule.enableFlags(Flags.FLAG_ALLOW_PRIVATE_PROFILE);
+        mSetFlagsRule.enableFlags(Flags.FLAG_ALLOW_PRIVATE_PROFILE,
+                android.multiuser.Flags.FLAG_ENABLE_PRIVATE_SPACE_FEATURES);
 
         mPrivateSpaceLockController.updateState(mPreference);
         assertThat(mPreference.isEnabled()).isFalse();
@@ -103,7 +105,8 @@
                 .when(mLockPatternUtils).isSeparateProfileChallengeEnabled(anyInt());
         doReturn(CREDENTIAL_TYPE_PATTERN)
                 .when(mLockPatternUtils).getCredentialTypeForUser(anyInt());
-        mSetFlagsRule.enableFlags(Flags.FLAG_ALLOW_PRIVATE_PROFILE);
+        mSetFlagsRule.enableFlags(Flags.FLAG_ALLOW_PRIVATE_PROFILE,
+                android.multiuser.Flags.FLAG_ENABLE_PRIVATE_SPACE_FEATURES);
 
         mPrivateSpaceLockController.updateState(mPreference);
         assertThat(mPreference.isEnabled()).isTrue();
@@ -115,7 +118,8 @@
     public void getSummary_whenProfileLockPin() {
         doReturn(true).when(mLockPatternUtils).isSeparateProfileChallengeEnabled(anyInt());
         doReturn(CREDENTIAL_TYPE_PIN).when(mLockPatternUtils).getCredentialTypeForUser(anyInt());
-        mSetFlagsRule.enableFlags(Flags.FLAG_ALLOW_PRIVATE_PROFILE);
+        mSetFlagsRule.enableFlags(Flags.FLAG_ALLOW_PRIVATE_PROFILE,
+                android.multiuser.Flags.FLAG_ENABLE_PRIVATE_SPACE_FEATURES);
 
         mPrivateSpaceLockController.updateState(mPreference);
         assertThat(mPreference.isEnabled()).isTrue();
@@ -129,7 +133,8 @@
                 .when(mLockPatternUtils).isSeparateProfileChallengeEnabled(anyInt());
         doReturn(CREDENTIAL_TYPE_PASSWORD)
                 .when(mLockPatternUtils).getCredentialTypeForUser(anyInt());
-        mSetFlagsRule.enableFlags(Flags.FLAG_ALLOW_PRIVATE_PROFILE);
+        mSetFlagsRule.enableFlags(Flags.FLAG_ALLOW_PRIVATE_PROFILE,
+                android.multiuser.Flags.FLAG_ENABLE_PRIVATE_SPACE_FEATURES);
 
         mPrivateSpaceLockController.updateState(mPreference);
         assertThat(mPreference.isEnabled()).isTrue();
diff --git a/tests/unit/src/com/android/settings/privatespace/PrivateSpaceMaintainerTest.java b/tests/unit/src/com/android/settings/privatespace/PrivateSpaceMaintainerTest.java
index 8510b11..50f67d3 100644
--- a/tests/unit/src/com/android/settings/privatespace/PrivateSpaceMaintainerTest.java
+++ b/tests/unit/src/com/android/settings/privatespace/PrivateSpaceMaintainerTest.java
@@ -148,7 +148,8 @@
     public void createPrivateSpace_psDoesNotExist_setsDefaultPsSensitiveNotificationsValue() {
         mSetFlagsRule.enableFlags(
                 Flags.FLAG_ALLOW_PRIVATE_PROFILE,
-                android.multiuser.Flags.FLAG_ENABLE_PS_SENSITIVE_NOTIFICATIONS_TOGGLE);
+                android.multiuser.Flags.FLAG_ENABLE_PS_SENSITIVE_NOTIFICATIONS_TOGGLE,
+                android.multiuser.Flags.FLAG_ENABLE_PRIVATE_SPACE_FEATURES);
         PrivateSpaceMaintainer privateSpaceMaintainer =
                 PrivateSpaceMaintainer.getInstance(mContext);
         privateSpaceMaintainer.deletePrivateSpace();
@@ -259,7 +260,8 @@
     public void createPrivateSpace_psDoesNotExist_resetsPSAutoLockSettings() {
         mSetFlagsRule.enableFlags(
                 Flags.FLAG_ALLOW_PRIVATE_PROFILE,
-                android.multiuser.Flags.FLAG_SUPPORT_AUTOLOCK_FOR_PRIVATE_SPACE);
+                android.multiuser.Flags.FLAG_SUPPORT_AUTOLOCK_FOR_PRIVATE_SPACE,
+                android.multiuser.Flags.FLAG_ENABLE_PRIVATE_SPACE_FEATURES);
         final int autoLockOption = 2;
         PrivateSpaceMaintainer privateSpaceMaintainer =
                 PrivateSpaceMaintainer.getInstance(mContext);
@@ -282,7 +284,8 @@
     public void createPrivateSpace_psExists_doesNotResetPSAutoLockSettings() {
         mSetFlagsRule.enableFlags(
                 Flags.FLAG_ALLOW_PRIVATE_PROFILE,
-                android.multiuser.Flags.FLAG_SUPPORT_AUTOLOCK_FOR_PRIVATE_SPACE);
+                android.multiuser.Flags.FLAG_SUPPORT_AUTOLOCK_FOR_PRIVATE_SPACE,
+                android.multiuser.Flags.FLAG_ENABLE_PRIVATE_SPACE_FEATURES);
         final int privateSpaceAutLockValue = 1;
         PrivateSpaceMaintainer privateSpaceMaintainer =
                 PrivateSpaceMaintainer.getInstance(mContext);
diff --git a/tests/unit/src/com/android/settings/privatespace/PrivateSpaceSafetySourceTest.java b/tests/unit/src/com/android/settings/privatespace/PrivateSpaceSafetySourceTest.java
index cf9ea05..940f70d 100644
--- a/tests/unit/src/com/android/settings/privatespace/PrivateSpaceSafetySourceTest.java
+++ b/tests/unit/src/com/android/settings/privatespace/PrivateSpaceSafetySourceTest.java
@@ -86,7 +86,8 @@
     @Test
     public void onDeviceRebootedEvent_whenSafetyCenterEnabled_setsData() {
         when(mSafetyCenterManagerWrapper.isEnabled(mContext)).thenReturn(true);
-        mSetFlagsRule.enableFlags(Flags.FLAG_ALLOW_PRIVATE_PROFILE);
+        mSetFlagsRule.enableFlags(Flags.FLAG_ALLOW_PRIVATE_PROFILE,
+                android.multiuser.Flags.FLAG_ENABLE_PRIVATE_SPACE_FEATURES);
 
         PrivateSpaceSafetySource.setSafetySourceData(mContext, EVENT_TYPE_DEVICE_REBOOTED);
 
@@ -98,7 +99,8 @@
     @Test
     public void setSafetySourceData_whenFeatureDisabled_setsNullData() {
         when(mSafetyCenterManagerWrapper.isEnabled(mContext)).thenReturn(true);
-        mSetFlagsRule.disableFlags(Flags.FLAG_ALLOW_PRIVATE_PROFILE);
+        mSetFlagsRule.disableFlags(Flags.FLAG_ALLOW_PRIVATE_PROFILE,
+                android.multiuser.Flags.FLAG_ENABLE_PRIVATE_SPACE_FEATURES);
 
         PrivateSpaceSafetySource.setSafetySourceData(mContext, EVENT_TYPE_DEVICE_REBOOTED);
 
@@ -113,7 +115,8 @@
     @Test
     public void setSafetySourceData_setsEnabled() {
         when(mSafetyCenterManagerWrapper.isEnabled(mContext)).thenReturn(true);
-        mSetFlagsRule.enableFlags(Flags.FLAG_ALLOW_PRIVATE_PROFILE);
+        mSetFlagsRule.enableFlags(Flags.FLAG_ALLOW_PRIVATE_PROFILE,
+                android.multiuser.Flags.FLAG_ENABLE_PRIVATE_SPACE_FEATURES);
 
         PrivateSpaceSafetySource.setSafetySourceData(mContext, EVENT_TYPE_DEVICE_REBOOTED);
 
@@ -129,7 +132,8 @@
     @Test
     public void setSafetySourceData_setsPsAuthenticatorIntent() {
         when(mSafetyCenterManagerWrapper.isEnabled(mContext)).thenReturn(true);
-        mSetFlagsRule.enableFlags(Flags.FLAG_ALLOW_PRIVATE_PROFILE);
+        mSetFlagsRule.enableFlags(Flags.FLAG_ALLOW_PRIVATE_PROFILE,
+                android.multiuser.Flags.FLAG_ENABLE_PRIVATE_SPACE_FEATURES);
 
         PrivateSpaceSafetySource.setSafetySourceData(mContext, EVENT_TYPE_DEVICE_REBOOTED);
 
diff --git a/tests/unit/src/com/android/settings/privatespace/UseOneLockControllerTest.java b/tests/unit/src/com/android/settings/privatespace/UseOneLockControllerTest.java
index 744a8ec..5c2a15c 100644
--- a/tests/unit/src/com/android/settings/privatespace/UseOneLockControllerTest.java
+++ b/tests/unit/src/com/android/settings/privatespace/UseOneLockControllerTest.java
@@ -74,7 +74,8 @@
     /** Tests that the controller is always available. */
     @Test
     public void getAvailabilityStatus_returnsAvailable() {
-        mSetFlagsRule.enableFlags(Flags.FLAG_ALLOW_PRIVATE_PROFILE);
+        mSetFlagsRule.enableFlags(Flags.FLAG_ALLOW_PRIVATE_PROFILE,
+                android.multiuser.Flags.FLAG_ENABLE_PRIVATE_SPACE_FEATURES);
 
         assertThat(mUseOneLockController.getAvailabilityStatus()).isEqualTo(AVAILABLE);
     }
@@ -87,7 +88,8 @@
                 .when(mLockPatternUtils).isSeparateProfileChallengeEnabled(anyInt());
         doReturn(CREDENTIAL_TYPE_PATTERN)
                 .when(mLockPatternUtils).getCredentialTypeForUser(anyInt());
-        mSetFlagsRule.enableFlags(Flags.FLAG_ALLOW_PRIVATE_PROFILE);
+        mSetFlagsRule.enableFlags(Flags.FLAG_ALLOW_PRIVATE_PROFILE,
+                android.multiuser.Flags.FLAG_ENABLE_PRIVATE_SPACE_FEATURES);
 
         mUseOneLockController.updateState(mPreference);
         assertThat(mUseOneLockController.getSummary().toString()).isEqualTo("Pattern");
@@ -99,7 +101,8 @@
         doReturn(true)
                 .when(mLockPatternUtils).isSeparateProfileChallengeEnabled(anyInt());
         doReturn(CREDENTIAL_TYPE_PIN).when(mLockPatternUtils).getCredentialTypeForUser(anyInt());
-        mSetFlagsRule.enableFlags(Flags.FLAG_ALLOW_PRIVATE_PROFILE);
+        mSetFlagsRule.enableFlags(Flags.FLAG_ALLOW_PRIVATE_PROFILE,
+                android.multiuser.Flags.FLAG_ENABLE_PRIVATE_SPACE_FEATURES);
 
         mUseOneLockController.updateState(mPreference);
         assertThat(mUseOneLockController.getSummary().toString()).isEqualTo("PIN");
@@ -112,7 +115,8 @@
                 .when(mLockPatternUtils).isSeparateProfileChallengeEnabled(anyInt());
         doReturn(CREDENTIAL_TYPE_PASSWORD)
                 .when(mLockPatternUtils).getCredentialTypeForUser(anyInt());
-        mSetFlagsRule.enableFlags(Flags.FLAG_ALLOW_PRIVATE_PROFILE);
+        mSetFlagsRule.enableFlags(Flags.FLAG_ALLOW_PRIVATE_PROFILE,
+                android.multiuser.Flags.FLAG_ENABLE_PRIVATE_SPACE_FEATURES);
 
         mUseOneLockController.updateState(mPreference);
         assertThat(mUseOneLockController.getSummary().toString()).isEqualTo("Password");
diff --git a/tests/unit/src/com/android/settings/privatespace/autolock/AutoLockPreferenceControllerTest.java b/tests/unit/src/com/android/settings/privatespace/autolock/AutoLockPreferenceControllerTest.java
index 01381d8..45c2c75 100644
--- a/tests/unit/src/com/android/settings/privatespace/autolock/AutoLockPreferenceControllerTest.java
+++ b/tests/unit/src/com/android/settings/privatespace/autolock/AutoLockPreferenceControllerTest.java
@@ -75,7 +75,8 @@
     public void getAvailabilityStatus_withAutoLockFlagEnabled_returnsAvailable() {
         mSetFlagsRule.enableFlags(
                 Flags.FLAG_ALLOW_PRIVATE_PROFILE,
-                android.multiuser.Flags.FLAG_SUPPORT_AUTOLOCK_FOR_PRIVATE_SPACE);
+                android.multiuser.Flags.FLAG_SUPPORT_AUTOLOCK_FOR_PRIVATE_SPACE,
+                android.multiuser.Flags.FLAG_ENABLE_PRIVATE_SPACE_FEATURES);
 
         assertThat(mAutoLockPreferenceController.getAvailabilityStatus()).isEqualTo(AVAILABLE);
     }
@@ -83,7 +84,8 @@
     /** Tests that the controller is not available when auto lock flag is off. */
     @Test
     public void getAvailabilityStatus_withAutoLockFlagDisabled_returnsNull() {
-        mSetFlagsRule.enableFlags(Flags.FLAG_ALLOW_PRIVATE_PROFILE);
+        mSetFlagsRule.enableFlags(Flags.FLAG_ALLOW_PRIVATE_PROFILE,
+                android.multiuser.Flags.FLAG_ENABLE_PRIVATE_SPACE_FEATURES);
         mSetFlagsRule.disableFlags(android.multiuser.Flags.FLAG_SUPPORT_AUTOLOCK_FOR_PRIVATE_SPACE);
 
         assertThat(mAutoLockPreferenceController.getAvailabilityStatus())
@@ -98,7 +100,8 @@
     public void getSummary_whenOptionEveryTimeDeviceLocks_returnsEveryTimeDeviceLocks() {
         mSetFlagsRule.enableFlags(
                 Flags.FLAG_ALLOW_PRIVATE_PROFILE,
-                android.multiuser.Flags.FLAG_SUPPORT_AUTOLOCK_FOR_PRIVATE_SPACE);
+                android.multiuser.Flags.FLAG_SUPPORT_AUTOLOCK_FOR_PRIVATE_SPACE,
+                android.multiuser.Flags.FLAG_ENABLE_PRIVATE_SPACE_FEATURES);
 
         Settings.Secure.putInt(
                 mContentResolver,
@@ -116,7 +119,8 @@
     public void getSummary_whenOptionAfter5MinutesOfInactivity_returnsAfter5MinutesOfInactivity() {
         mSetFlagsRule.enableFlags(
                 Flags.FLAG_ALLOW_PRIVATE_PROFILE,
-                android.multiuser.Flags.FLAG_SUPPORT_AUTOLOCK_FOR_PRIVATE_SPACE);
+                android.multiuser.Flags.FLAG_SUPPORT_AUTOLOCK_FOR_PRIVATE_SPACE,
+                android.multiuser.Flags.FLAG_ENABLE_PRIVATE_SPACE_FEATURES);
 
         Settings.Secure.putInt(
                 mContentResolver,
@@ -131,7 +135,8 @@
     public void getSummary_whenOptionNever_returnsNever() {
         mSetFlagsRule.enableFlags(
                 Flags.FLAG_ALLOW_PRIVATE_PROFILE,
-                android.multiuser.Flags.FLAG_SUPPORT_AUTOLOCK_FOR_PRIVATE_SPACE);
+                android.multiuser.Flags.FLAG_SUPPORT_AUTOLOCK_FOR_PRIVATE_SPACE,
+                android.multiuser.Flags.FLAG_ENABLE_PRIVATE_SPACE_FEATURES);
 
         Settings.Secure.putInt(
                 mContentResolver,
diff --git a/tests/unit/src/com/android/settings/privatespace/autolock/AutoLockSettingsFragmentTest.java b/tests/unit/src/com/android/settings/privatespace/autolock/AutoLockSettingsFragmentTest.java
index 971ca40..1c620c0 100644
--- a/tests/unit/src/com/android/settings/privatespace/autolock/AutoLockSettingsFragmentTest.java
+++ b/tests/unit/src/com/android/settings/privatespace/autolock/AutoLockSettingsFragmentTest.java
@@ -94,7 +94,8 @@
     public void verifyMetricsConstant() {
         mSetFlagsRule.enableFlags(
                 Flags.FLAG_ALLOW_PRIVATE_PROFILE,
-                android.multiuser.Flags.FLAG_SUPPORT_AUTOLOCK_FOR_PRIVATE_SPACE);
+                android.multiuser.Flags.FLAG_SUPPORT_AUTOLOCK_FOR_PRIVATE_SPACE,
+                android.multiuser.Flags.FLAG_ENABLE_PRIVATE_SPACE_FEATURES);
         assertThat(mFragment.getMetricsCategory()).isEqualTo(SettingsEnums.PRIVATE_SPACE_SETTINGS);
     }
 
@@ -103,7 +104,8 @@
     public void getCandidates_returnsCandidateInfoListWithAllKeys() {
         mSetFlagsRule.enableFlags(
                 Flags.FLAG_ALLOW_PRIVATE_PROFILE,
-                android.multiuser.Flags.FLAG_SUPPORT_AUTOLOCK_FOR_PRIVATE_SPACE);
+                android.multiuser.Flags.FLAG_SUPPORT_AUTOLOCK_FOR_PRIVATE_SPACE,
+                android.multiuser.Flags.FLAG_ENABLE_PRIVATE_SPACE_FEATURES);
         mFragment.onAttach(mContext);
 
         final List<? extends CandidateInfo> candidates = mFragment.getCandidates();
@@ -120,7 +122,8 @@
     public void getDefaultKey_returnsStoredAutoLockOptionsValue() {
         mSetFlagsRule.enableFlags(
                 Flags.FLAG_ALLOW_PRIVATE_PROFILE,
-                android.multiuser.Flags.FLAG_SUPPORT_AUTOLOCK_FOR_PRIVATE_SPACE);
+                android.multiuser.Flags.FLAG_SUPPORT_AUTOLOCK_FOR_PRIVATE_SPACE,
+                android.multiuser.Flags.FLAG_ENABLE_PRIVATE_SPACE_FEATURES);
 
         mFragment.onAttach(mContext);
 
@@ -144,7 +147,8 @@
     public void setDefaultKey_storesCorrectAutoLockOptionValue() {
         mSetFlagsRule.enableFlags(
                 Flags.FLAG_ALLOW_PRIVATE_PROFILE,
-                android.multiuser.Flags.FLAG_SUPPORT_AUTOLOCK_FOR_PRIVATE_SPACE);
+                android.multiuser.Flags.FLAG_SUPPORT_AUTOLOCK_FOR_PRIVATE_SPACE,
+                android.multiuser.Flags.FLAG_ENABLE_PRIVATE_SPACE_FEATURES);
 
         mFragment.onAttach(mContext);
         mFragment.setDefaultKey("2");
diff --git a/tests/unit/src/com/android/settings/privatespace/delete/DeletePrivateSpaceControllerTest.java b/tests/unit/src/com/android/settings/privatespace/delete/DeletePrivateSpaceControllerTest.java
index 371ca24..ed8decd 100644
--- a/tests/unit/src/com/android/settings/privatespace/delete/DeletePrivateSpaceControllerTest.java
+++ b/tests/unit/src/com/android/settings/privatespace/delete/DeletePrivateSpaceControllerTest.java
@@ -58,7 +58,8 @@
     /** Tests that the controller is available when private space flag is enabled. */
     @Test
     public void getAvailabilityStatus_whenPrivateFlagEnabled_returnsAvailable() {
-        mSetFlagsRule.enableFlags(android.os.Flags.FLAG_ALLOW_PRIVATE_PROFILE);
+        mSetFlagsRule.enableFlags(android.os.Flags.FLAG_ALLOW_PRIVATE_PROFILE,
+                android.multiuser.Flags.FLAG_ENABLE_PRIVATE_SPACE_FEATURES);
 
         assertThat(mDeletePrivateSpaceController.getAvailabilityStatus()).isEqualTo(AVAILABLE);
     }
@@ -66,7 +67,8 @@
     /** Tests that the controller is not available when private space flag is disabled. */
     @Test
     public void getAvailabilityStatus_whenPrivateFlagDisabled_returnsUnsupportedOnDevice() {
-        mSetFlagsRule.disableFlags(android.os.Flags.FLAG_ALLOW_PRIVATE_PROFILE);
+        mSetFlagsRule.disableFlags(android.os.Flags.FLAG_ALLOW_PRIVATE_PROFILE,
+                android.multiuser.Flags.FLAG_ENABLE_PRIVATE_SPACE_FEATURES);
 
         assertThat(mDeletePrivateSpaceController.getAvailabilityStatus())
                 .isEqualTo(UNSUPPORTED_ON_DEVICE);
diff --git a/tests/unit/src/com/android/settings/privatespace/delete/PrivateSpaceDeleteFragmentTest.java b/tests/unit/src/com/android/settings/privatespace/delete/PrivateSpaceDeleteFragmentTest.java
index 16ccbc4..5c48375 100644
--- a/tests/unit/src/com/android/settings/privatespace/delete/PrivateSpaceDeleteFragmentTest.java
+++ b/tests/unit/src/com/android/settings/privatespace/delete/PrivateSpaceDeleteFragmentTest.java
@@ -39,7 +39,8 @@
     @Test
     @UiThreadTest
     public void verifyMetricsConstant() {
-        mSetFlagsRule.enableFlags(Flags.FLAG_ALLOW_PRIVATE_PROFILE);
+        mSetFlagsRule.enableFlags(Flags.FLAG_ALLOW_PRIVATE_PROFILE,
+                android.multiuser.Flags.FLAG_ENABLE_PRIVATE_SPACE_FEATURES);
         mFragment = spy(new PrivateSpaceDeleteFragment());
         assertThat(mFragment.getMetricsCategory()).isEqualTo(SettingsEnums.PRIVATE_SPACE_SETTINGS);
     }
diff --git a/tests/unit/src/com/android/settings/privatespace/delete/PrivateSpaceDeletionProgressFragmentTest.java b/tests/unit/src/com/android/settings/privatespace/delete/PrivateSpaceDeletionProgressFragmentTest.java
index 5c2ef23..ffc1edf 100644
--- a/tests/unit/src/com/android/settings/privatespace/delete/PrivateSpaceDeletionProgressFragmentTest.java
+++ b/tests/unit/src/com/android/settings/privatespace/delete/PrivateSpaceDeletionProgressFragmentTest.java
@@ -77,7 +77,8 @@
     @Test
     @UiThreadTest
     public void verifyMetricsConstant() {
-        mSetFlagsRule.enableFlags(Flags.FLAG_ALLOW_PRIVATE_PROFILE);
+        mSetFlagsRule.enableFlags(Flags.FLAG_ALLOW_PRIVATE_PROFILE,
+                android.multiuser.Flags.FLAG_ENABLE_PRIVATE_SPACE_FEATURES);
         assertThat(mFragment.getMetricsCategory()).isEqualTo(SettingsEnums.PRIVATE_SPACE_SETTINGS);
     }
 
@@ -87,7 +88,8 @@
     public void deletePrivateSpace_deletesPS() {
         PrivateSpaceDeletionProgressFragment spyFragment = spy(mFragment);
         doNothing().when(spyFragment).showSuccessfulDeletionToast();
-        mSetFlagsRule.enableFlags(Flags.FLAG_ALLOW_PRIVATE_PROFILE);
+        mSetFlagsRule.enableFlags(Flags.FLAG_ALLOW_PRIVATE_PROFILE,
+                android.multiuser.Flags.FLAG_ENABLE_PRIVATE_SPACE_FEATURES);
 
         mPrivateSpaceMaintainer.createPrivateSpace();
         spyFragment.deletePrivateSpace();
@@ -100,7 +102,8 @@
     public void deletePrivateSpace_onDeletion_showsDeletedToast() {
         PrivateSpaceDeletionProgressFragment spyFragment = spy(mFragment);
         doNothing().when(spyFragment).showSuccessfulDeletionToast();
-        mSetFlagsRule.enableFlags(Flags.FLAG_ALLOW_PRIVATE_PROFILE);
+        mSetFlagsRule.enableFlags(Flags.FLAG_ALLOW_PRIVATE_PROFILE,
+                android.multiuser.Flags.FLAG_ENABLE_PRIVATE_SPACE_FEATURES);
 
         mPrivateSpaceMaintainer.createPrivateSpace();
         spyFragment.deletePrivateSpace();
@@ -123,7 +126,8 @@
         spyFragment.setPrivateSpaceMaintainer(injector);
         doReturn(DELETE_PS_ERROR_INTERNAL).when(mPrivateSpaceMaintainerMock).deletePrivateSpace();
         doNothing().when(spyFragment).showDeletionInternalErrorToast();
-        mSetFlagsRule.enableFlags(Flags.FLAG_ALLOW_PRIVATE_PROFILE);
+        mSetFlagsRule.enableFlags(Flags.FLAG_ALLOW_PRIVATE_PROFILE,
+                android.multiuser.Flags.FLAG_ENABLE_PRIVATE_SPACE_FEATURES);
 
         spyFragment.deletePrivateSpace();
 
diff --git a/tests/unit/src/com/android/settings/safetycenter/SafetySourceBroadcastReceiverTest.java b/tests/unit/src/com/android/settings/safetycenter/SafetySourceBroadcastReceiverTest.java
index 85bd0e2..cd4c3c6 100644
--- a/tests/unit/src/com/android/settings/safetycenter/SafetySourceBroadcastReceiverTest.java
+++ b/tests/unit/src/com/android/settings/safetycenter/SafetySourceBroadcastReceiverTest.java
@@ -247,7 +247,8 @@
     @Test
     public void onReceive_onRefresh_withPrivateSpaceFeatureDisabled_setsNullData() {
         when(mSafetyCenterManagerWrapper.isEnabled(mApplicationContext)).thenReturn(true);
-        mSetFlagsRule.disableFlags(Flags.FLAG_ALLOW_PRIVATE_PROFILE);
+        mSetFlagsRule.disableFlags(Flags.FLAG_ALLOW_PRIVATE_PROFILE,
+                android.multiuser.Flags.FLAG_ENABLE_PRIVATE_SPACE_FEATURES);
 
         Intent intent =
                 new Intent()