Merge "Fix certX509 has not been initialized." into main
diff --git a/res/layout/homepage_preference.xml b/res/layout/homepage_preference.xml
index f0b1b71..38cb491 100644
--- a/res/layout/homepage_preference.xml
+++ b/res/layout/homepage_preference.xml
@@ -17,6 +17,7 @@
 
 <LinearLayout
     xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:androidprv="http://schemas.android.com/apk/prv/res/android"
     xmlns:app="http://schemas.android.com/apk/res-auto"
     android:layout_width="match_parent"
     android:layout_height="wrap_content"
@@ -77,7 +78,7 @@
             android:layout_gravity="start"
             android:textAlignment="viewStart"
             android:textAppearance="?android:attr/textAppearanceSmall"
-            android:textColor="?android:attr/textColorSecondary"
+            android:textColor="?androidprv:attr/materialColorOnSurfaceVariant"
             android:maxLines="4"
             android:hyphenationFrequency="normalFast"
             android:lineBreakWordStyle="phrase"
diff --git a/res/layout/wifi_network_config.xml b/res/layout/wifi_network_config.xml
index 3de1a38..dbd3e67 100644
--- a/res/layout/wifi_network_config.xml
+++ b/res/layout/wifi_network_config.xml
@@ -708,6 +708,13 @@
                      style="@style/wifi_item_spinner"
                      android:prompt="@string/wifi_privacy_settings"
                      android:entries="@array/wifi_privacy_entries"/>
+
+            <Spinner android:id="@+id/dhcp_settings"
+                android:layout_width="match_parent"
+                android:layout_height="wrap_content"
+                style="@style/wifi_item_spinner"
+                android:prompt="@string/wifi_privacy_device_name_settings"
+                android:entries="@array/wifi_dhcp_entries"/>
         </LinearLayout>
 
         <LinearLayout
diff --git a/res/values-night/colors.xml b/res/values-night/colors.xml
index a572841..a27fbaa 100644
--- a/res/values-night/colors.xml
+++ b/res/values-night/colors.xml
@@ -19,7 +19,7 @@
     <color name="homepage_accessibility_background">#783BE5</color>
     <color name="homepage_support_background">#3F5FBD</color>
     <color name="contextual_card_background">@*android:color/material_grey_900</color>
-    <color name="search_bar_background">?androidprv:attr/materialColorSurfaceContainerHigh</color>
+    <color name="search_bar_background">?androidprv:attr/materialColorSurfaceBright</color>
     <color name="notification_importance_button_unselected">#5F6368</color>
 
     <!-- Palette list preference colors. -->
diff --git a/res/values/arrays.xml b/res/values/arrays.xml
index fe3f429..6122e0d 100644
--- a/res/values/arrays.xml
+++ b/res/values/arrays.xml
@@ -1095,6 +1095,11 @@
         <item>Use device MAC</item>
     </string-array>
 
+    <string-array name="wifi_dhcp_entries">
+        <item>Send device name to network</item>
+        <item>Don\u0027t send device name to network</item>
+    </string-array>
+
     <string-array name="wifi_hidden_entries">
         <item>No</item>
         <item>Yes</item>
diff --git a/res/values/strings.xml b/res/values/strings.xml
index 2037323..d5fd621 100644
--- a/res/values/strings.xml
+++ b/res/values/strings.xml
@@ -150,14 +150,14 @@
     <string name="bluetooth_pair_other_ear_dialog_right_ear_positive_button">Pair right ear</string>
     <!-- Connected devices settings. Positive button of the dialog to help user to pair left ear of the hearing aid device. Dialog shows when only one of the hearing aid device set is connected. [CHAR LIMIT=20] -->
     <string name="bluetooth_pair_other_ear_dialog_left_ear_positive_button">Pair left ear</string>
-    <!-- Title for all hearing devices related controls section. [CHAR LIMIT=60] -->
-    <string name="bluetooth_device_controls_general">For all available hearing devices</string>
-    <!-- Connected devices settings. Title of the preference to show the entrance of the hearing device settings related page. [CHAR LIMIT=65] -->
-    <string name="bluetooth_device_controls_title">More hearing device settings</string>
-    <!-- Connected devices settings. Summary of the preference to show the item in the hearing device settings related page. [CHAR LIMIT=120] -->
-    <string name="bluetooth_device_controls_summary">Change cross-device settings like shortcut, and telecoil controls</string>
-    <!-- Title for this device specific controls section. [CHAR LIMIT=30] -->
-    <string name="bluetooth_device_controls_specific">For this device</string>
+    <!-- Connected devices settings. Title of the preference to show the entrance of the hearing device settings page. [CHAR LIMIT=65 BACKUP_MESSAGE_ID=1895676556354697234] -->
+    <string name="bluetooth_hearing_device_settings_title">Hearing device settings</string>
+    <!-- Connected devices settings. Summary of the preference to show the entrance of the hearing device settings page. [CHAR LIMIT=65 BACKUP_MESSAGE_ID=8115767735418425663] -->
+    <string name="bluetooth_hearing_device_settings_summary">Shortcut, hearing aid compatibility</string>
+    <!-- Connected devices settings. Title for hearing aids presets. A preset is a set of hearing aid settings. User can apply different settings in different environments (e.g. Outdoor, Restaurant, Home) [CHAR LIMIT=60] -->
+    <string name="bluetooth_hearing_aids_presets">Presets</string>
+    <!-- Message when selecting hearing aids presets failed. [CHAR LIMIT=NONE] -->
+    <string name="bluetooth_hearing_aids_presets_error">Couldn\u2019t update preset</string>
     <!-- Connected devices settings. Title of the preference to show the entrance of the audio output page. It can change different types of audio are played on phone or other bluetooth devices. [CHAR LIMIT=35] -->
     <string name="bluetooth_audio_routing_title">Audio output</string>
     <!-- Title for bluetooth audio routing page footer. [CHAR LIMIT=30] -->
@@ -1263,6 +1263,12 @@
     <string name="privatespace_hide_off_summary">Off</string>
     <!-- Used to describe the off state of Private space hidden [CHAR LIMIT=30] -->
     <string name="privatespace_hide_on_summary">On</string>
+    <!-- Title for the dialog shown when Private space hidden setting is turned on. [CHAR LIMIT=60] -->
+    <string name="private_space_hide_dialog_title">Private space will hide when you lock it next</string>
+    <!-- Text message in the dialog shown when Private space hidden setting is turned on. [CHAR LIMIT=90] -->
+    <string name="private_space_hide_dialog_message">To access your space when it’s hidden, enter \“private space\” in the search bar on your apps list</string>
+    <!-- Label for the dialog shown when Private space hidden setting is turned on. [CHAR LIMIT=90] -->
+    <string name="private_space_hide_dialog_button">Got it</string>
     <!-- System category for the Private Space page. [CHAR LIMIT=30] -->
     <string name="private_space_category_system">System</string>
     <!-- Title for the preference to delete Private Space. [CHAR LIMIT=40] -->
@@ -1847,11 +1853,6 @@
     <!-- Bluetooth developer settings: Maximum number of connected audio devices -->
     <string name="bluetooth_max_connected_audio_devices_dialog_title">Select maximum number of connected Bluetooth audio devices</string>
 
-    <!-- Nfc developer settings: The title of the setting. [CHAR LIMIT=60] -->
-    <string name="nfc_stack_debuglog_title">NFC stack debug log</string>
-    <!-- Nfc developer settings: The description of the setting. -->
-    <string name="nfc_stack_debuglog_summary">Increase NFC stack logging level</string>
-
     <!-- Nfc developer settings: The title of the setting to enable nfc verbose vendor log. [CHAR LIMIT=60] -->
     <string name="nfc_verbose_vendor_log_title">NFC verbose vendor debug log</string>
     <!-- Nfc developer settings: The description of the setting to enable nfc verbose vendor log. [CHAR_LIMIT=NONE] -->
diff --git a/res/values/styles.xml b/res/values/styles.xml
index 0a28b01..fe2084f 100644
--- a/res/values/styles.xml
+++ b/res/values/styles.xml
@@ -249,7 +249,7 @@
         <item name="android:layout_gravity">center</item>
         <item name="android:fontFamily">@*android:string/config_headlineFontFamily</item>
         <item name="android:textSize">@dimen/search_bar_text_size</item>
-        <item name="android:textColor">?android:attr/textColorSecondary</item>
+        <item name="android:textColor">?androidprv:attr/materialColorOnSurfaceVariant</item>
         <item name="android:singleLine">true</item>
     </style>
 
diff --git a/res/xml/bluetooth_device_details_fragment.xml b/res/xml/bluetooth_device_details_fragment.xml
index d260554..91f73a7 100644
--- a/res/xml/bluetooth_device_details_fragment.xml
+++ b/res/xml/bluetooth_device_details_fragment.xml
@@ -69,7 +69,7 @@
         android:key="device_companion_apps"/>
 
     <PreferenceCategory
-        android:key="device_controls_general" />
+        android:key="hearing_device_group" />
 
     <PreferenceCategory
         android:key="bluetooth_audio_device_type_group"/>
diff --git a/res/xml/development_settings.xml b/res/xml/development_settings.xml
index b1ebbb8..23eb1f2 100644
--- a/res/xml/development_settings.xml
+++ b/res/xml/development_settings.xml
@@ -470,11 +470,6 @@
             android:entryValues="@array/bluetooth_max_connected_audio_devices_values" />
 
         <SwitchPreferenceCompat
-            android:key="nfc_stack_debuglog_enabled"
-            android:title="@string/nfc_stack_debuglog_title"
-            android:summary="@string/nfc_stack_debuglog_summary" />
-
-        <SwitchPreferenceCompat
             android:key="nfc_verbose_vendor_log"
             android:title="@string/nfc_verbose_vendor_log_title"
             android:summary="@string/nfc_verbose_vendor_log_summary" />
diff --git a/src/com/android/settings/Utils.java b/src/com/android/settings/Utils.java
index 6e36ee3..c38ebfe 100644
--- a/src/com/android/settings/Utils.java
+++ b/src/com/android/settings/Utils.java
@@ -1289,7 +1289,8 @@
      */
     @ColorInt
     public static int getHomepageIconColor(Context context) {
-        return getColorAttrDefaultColor(context, android.R.attr.textColorPrimary);
+        return getColorAttrDefaultColor(
+                context, com.android.internal.R.attr.materialColorOnSurface);
     }
 
     /**
diff --git a/src/com/android/settings/applications/AppStoreUtil.java b/src/com/android/settings/applications/AppStoreUtil.java
index b73b14a..636669c 100644
--- a/src/com/android/settings/applications/AppStoreUtil.java
+++ b/src/com/android/settings/applications/AppStoreUtil.java
@@ -83,6 +83,7 @@
     }
 
     /** Convenience method that looks up the installerPackageName for you. */
+    @Nullable
     public static Intent getAppStoreLink(Context context, String packageName) {
       String installerPackageName = getInstallerPackageName(context, packageName);
       return getAppStoreLink(context, installerPackageName, packageName);
diff --git a/src/com/android/settings/applications/specialaccess/interactacrossprofiles/InteractAcrossProfilesDetails.java b/src/com/android/settings/applications/specialaccess/interactacrossprofiles/InteractAcrossProfilesDetails.java
index faa1b51..81e8439 100644
--- a/src/com/android/settings/applications/specialaccess/interactacrossprofiles/InteractAcrossProfilesDetails.java
+++ b/src/com/android/settings/applications/specialaccess/interactacrossprofiles/InteractAcrossProfilesDetails.java
@@ -384,20 +384,21 @@
     }
 
     private void handleInstallBannerClick() {
-        if (mInstallAppIntent == null) {
-            logEvent(
-                    DevicePolicyEnums.CROSS_PROFILE_SETTINGS_PAGE_INSTALL_BANNER_NO_INTENT_CLICKED);
-            return;
-        }
-        if (!mInstalledInWork) {
+        if (mInstallAppIntent != null
+                && !mInstalledInWork
+                && isInstallableInProfile(mInstallAppIntent, mWorkProfile)) {
             logEvent(DevicePolicyEnums.CROSS_PROFILE_SETTINGS_PAGE_INSTALL_BANNER_CLICKED);
             mContext.startActivityAsUser(mInstallAppIntent, mWorkProfile);
             return;
         }
-        if (!mInstalledInPersonal) {
+        if (mInstallAppIntent != null
+                && !mInstalledInPersonal
+                && isInstallableInProfile(mInstallAppIntent, mPersonalProfile)) {
             logEvent(DevicePolicyEnums.CROSS_PROFILE_SETTINGS_PAGE_INSTALL_BANNER_CLICKED);
             mContext.startActivityAsUser(mInstallAppIntent, mPersonalProfile);
+            return;
         }
+        logEvent(DevicePolicyEnums.CROSS_PROFILE_SETTINGS_PAGE_INSTALL_BANNER_NO_INTENT_CLICKED);
     }
 
     /**
@@ -447,7 +448,8 @@
                                     R.string.interact_across_profiles_install_personal_app_title,
                                     mAppLabel),
                             mAppLabel));
-            if (mInstallAppIntent != null) {
+            if (mInstallAppIntent != null
+                    && isInstallableInProfile(mInstallAppIntent, mPersonalProfile)) {
                 mInstallBanner.setSummary(
                         R.string.interact_across_profiles_install_app_summary);
             }
@@ -461,7 +463,8 @@
                                     R.string.interact_across_profiles_install_work_app_title,
                                     mAppLabel),
                             mAppLabel));
-            if (mInstallAppIntent != null) {
+            if (mInstallAppIntent != null
+                    && isInstallableInProfile(mInstallAppIntent, mWorkProfile)) {
                 mInstallBanner.setSummary(
                         R.string.interact_across_profiles_install_app_summary);
             }
@@ -488,6 +491,12 @@
         return info != null;
     }
 
+    private boolean isInstallableInProfile(Intent intent, UserHandle profile) {
+        return !mContext.getPackageManager()
+                .queryIntentActivitiesAsUser(intent, /* flags= */ 0, profile)
+                .isEmpty();
+    }
+
     private void refreshUiForConfigurableApps() {
         mInstallBanner.setVisible(false);
         mSwitchPref.setEnabled(true);
diff --git a/src/com/android/settings/bluetooth/BluetoothDetailsHearingAidsPresetsController.java b/src/com/android/settings/bluetooth/BluetoothDetailsHearingAidsPresetsController.java
new file mode 100644
index 0000000..43721f4
--- /dev/null
+++ b/src/com/android/settings/bluetooth/BluetoothDetailsHearingAidsPresetsController.java
@@ -0,0 +1,308 @@
+/*
+ * 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.bluetooth;
+
+import static com.android.settings.bluetooth.BluetoothDetailsHearingDeviceController.KEY_HEARING_DEVICE_GROUP;
+import static com.android.settings.bluetooth.BluetoothDetailsHearingDeviceController.ORDER_HEARING_AIDS_PRESETS;
+
+import android.bluetooth.BluetoothCsipSetCoordinator;
+import android.bluetooth.BluetoothDevice;
+import android.bluetooth.BluetoothHapClient;
+import android.bluetooth.BluetoothHapPresetInfo;
+import android.content.Context;
+import android.text.TextUtils;
+import android.util.Log;
+import android.widget.Toast;
+
+import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
+import androidx.annotation.VisibleForTesting;
+import androidx.preference.ListPreference;
+import androidx.preference.Preference;
+import androidx.preference.PreferenceCategory;
+import androidx.preference.PreferenceFragmentCompat;
+import androidx.preference.PreferenceScreen;
+
+import com.android.settings.R;
+import com.android.settingslib.bluetooth.CachedBluetoothDevice;
+import com.android.settingslib.bluetooth.HapClientProfile;
+import com.android.settingslib.bluetooth.LocalBluetoothManager;
+import com.android.settingslib.core.lifecycle.Lifecycle;
+import com.android.settingslib.core.lifecycle.events.OnPause;
+import com.android.settingslib.core.lifecycle.events.OnResume;
+import com.android.settingslib.utils.ThreadUtils;
+
+import java.util.List;
+
+/**
+ * The controller of the hearing aid presets.
+ */
+public class BluetoothDetailsHearingAidsPresetsController extends
+        BluetoothDetailsController implements Preference.OnPreferenceChangeListener,
+        BluetoothHapClient.Callback, OnResume, OnPause {
+
+    private static final boolean DEBUG = true;
+    private static final String TAG = "BluetoothDetailsHearingAidsPresetsController";
+    static final String KEY_HEARING_AIDS_PRESETS = "hearing_aids_presets";
+
+    private final HapClientProfile mHapClientProfile;
+    @Nullable
+    private ListPreference mPreference;
+
+    public BluetoothDetailsHearingAidsPresetsController(@NonNull Context context,
+            @NonNull PreferenceFragmentCompat fragment,
+            @NonNull LocalBluetoothManager manager,
+            @NonNull CachedBluetoothDevice device,
+            @NonNull Lifecycle lifecycle) {
+        super(context, fragment, device, lifecycle);
+        mHapClientProfile = manager.getProfileManager().getHapClientProfile();
+    }
+
+    @Override
+    public void onResume() {
+        super.onResume();
+        if (mHapClientProfile != null) {
+            mHapClientProfile.registerCallback(ThreadUtils.getBackgroundExecutor(), this);
+        }
+    }
+
+    @Override
+    public void onPause() {
+        if (mHapClientProfile != null) {
+            mHapClientProfile.unregisterCallback(this);
+        }
+        super.onPause();
+    }
+
+    @Override
+    public boolean onPreferenceChange(@NonNull Preference preference, @Nullable Object newValue) {
+        if (TextUtils.equals(preference.getKey(), getPreferenceKey())) {
+            if (newValue instanceof final String value
+                    && preference instanceof final ListPreference listPreference) {
+                final int index = listPreference.findIndexOfValue(value);
+                final String presetName = listPreference.getEntries()[index].toString();
+                final int presetIndex = Integer.parseInt(
+                        listPreference.getEntryValues()[index].toString());
+                listPreference.setSummary(presetName);
+                boolean supportSynchronizedPresets = mHapClientProfile.supportsSynchronizedPresets(
+                        mCachedDevice.getDevice());
+                int hapGroupId = mHapClientProfile.getHapGroup(mCachedDevice.getDevice());
+                if (supportSynchronizedPresets
+                        && hapGroupId != BluetoothCsipSetCoordinator.GROUP_ID_INVALID) {
+                    if (DEBUG) {
+                        Log.d(TAG, "onPreferenceChange, selectPresetForGroup "
+                                + ", presetName: " + presetName
+                                + ", presetIndex: " + presetIndex
+                                + ", hapGroupId: "  + hapGroupId
+                                + ", device: " + mCachedDevice.getAddress());
+                    }
+                    mHapClientProfile.selectPresetForGroup(hapGroupId, presetIndex);
+                } else {
+                    if (DEBUG) {
+                        Log.d(TAG, "onPreferenceChange, selectPreset "
+                                + ", presetName: " + presetName
+                                + ", presetIndex: " + presetIndex
+                                + ", device: " + mCachedDevice.getAddress());
+                    }
+                    mHapClientProfile.selectPreset(mCachedDevice.getDevice(), presetIndex);
+                    final CachedBluetoothDevice subDevice = mCachedDevice.getSubDevice();
+                    if (subDevice != null) {
+                        if (DEBUG) {
+                            Log.d(TAG, "onPreferenceChange, selectPreset for subDevice"
+                                    + ", device: " + subDevice.getAddress());
+                        }
+                        mHapClientProfile.selectPreset(subDevice.getDevice(), presetIndex);
+                    }
+                    for (final CachedBluetoothDevice memberDevice :
+                            mCachedDevice.getMemberDevice()) {
+                        if (DEBUG) {
+                            Log.d(TAG, "onPreferenceChange, selectPreset for memberDevice"
+                                    + ", device: " + memberDevice.getAddress());
+                        }
+                        mHapClientProfile.selectPreset(memberDevice.getDevice(), presetIndex);
+                    }
+                }
+                return true;
+            }
+        }
+        return false;
+    }
+
+    @Nullable
+    @Override
+    public String getPreferenceKey() {
+        return KEY_HEARING_AIDS_PRESETS;
+    }
+
+    @Override
+    protected void init(PreferenceScreen screen) {
+        PreferenceCategory deviceControls = screen.findPreference(KEY_HEARING_DEVICE_GROUP);
+        if (deviceControls != null) {
+            mPreference = createPresetPreference(deviceControls.getContext());
+            deviceControls.addPreference(mPreference);
+        }
+    }
+
+    @Override
+    protected void refresh() {
+        if (!isAvailable() || mPreference == null) {
+            return;
+        }
+        mPreference.setEnabled(mCachedDevice.isConnectedHapClientDevice());
+
+        loadAllPresetInfo();
+        if (mPreference.getEntries().length == 0) {
+            mPreference.setEnabled(false);
+        } else {
+            int activePresetIndex = mHapClientProfile.getActivePresetIndex(
+                    mCachedDevice.getDevice());
+            if (activePresetIndex != BluetoothHapClient.PRESET_INDEX_UNAVAILABLE) {
+                mPreference.setValue(Integer.toString(activePresetIndex));
+                mPreference.setSummary(mPreference.getEntry());
+            } else {
+                mPreference.setSummary(null);
+            }
+        }
+    }
+
+    @Override
+    public boolean isAvailable() {
+        if (mHapClientProfile == null) {
+            return false;
+        }
+        return mCachedDevice.getProfiles().stream().anyMatch(
+                profile -> profile instanceof HapClientProfile);
+    }
+
+    @Override
+    public void onPresetSelected(@NonNull BluetoothDevice device, int presetIndex, int reason) {
+        if (device.equals(mCachedDevice.getDevice())) {
+            if (DEBUG) {
+                Log.d(TAG, "onPresetSelected, device: " + device.getAddress()
+                        + ", presetIndex: " + presetIndex + ", reason: " + reason);
+            }
+            mContext.getMainExecutor().execute(this::refresh);
+        }
+    }
+
+    @Override
+    public void onPresetSelectionFailed(@NonNull BluetoothDevice device, int reason) {
+        if (device.equals(mCachedDevice.getDevice())) {
+            if (DEBUG) {
+                Log.d(TAG,
+                        "onPresetSelectionFailed, device: " + device.getAddress()
+                                + ", reason: " + reason);
+            }
+            mContext.getMainExecutor().execute(() -> {
+                refresh();
+                showErrorToast();
+            });
+        }
+    }
+
+    @Override
+    public void onPresetSelectionForGroupFailed(int hapGroupId, int reason) {
+        if (hapGroupId == mHapClientProfile.getHapGroup(mCachedDevice.getDevice())) {
+            if (DEBUG) {
+                Log.d(TAG, "onPresetSelectionForGroupFailed, group: " + hapGroupId
+                        + ", reason: " + reason);
+            }
+            mContext.getMainExecutor().execute(() -> {
+                refresh();
+                showErrorToast();
+            });
+        }
+    }
+
+    @Override
+    public void onPresetInfoChanged(@NonNull BluetoothDevice device,
+            @NonNull List<BluetoothHapPresetInfo> presetInfoList, int reason) {
+        if (device.equals(mCachedDevice.getDevice())) {
+            if (DEBUG) {
+                Log.d(TAG, "onPresetInfoChanged, device: " + device.getAddress()
+                        + ", reason: " + reason
+                        + ", infoList: " + presetInfoList);
+            }
+            mContext.getMainExecutor().execute(this::refresh);
+        }
+    }
+
+    @Override
+    public void onSetPresetNameFailed(@NonNull BluetoothDevice device, int reason) {
+        if (device.equals(mCachedDevice.getDevice())) {
+            if (DEBUG) {
+                Log.d(TAG,
+                        "onSetPresetNameFailed, device: " + device.getAddress()
+                                + ", reason: " + reason);
+            }
+            mContext.getMainExecutor().execute(() -> {
+                refresh();
+                showErrorToast();
+            });
+        }
+    }
+
+    @Override
+    public void onSetPresetNameForGroupFailed(int hapGroupId, int reason) {
+        if (hapGroupId == mHapClientProfile.getHapGroup(mCachedDevice.getDevice())) {
+            if (DEBUG) {
+                Log.d(TAG, "onSetPresetNameForGroupFailed, group: " + hapGroupId
+                        + ", reason: " + reason);
+            }
+            mContext.getMainExecutor().execute(() -> {
+                refresh();
+                showErrorToast();
+            });
+        }
+    }
+
+    private ListPreference createPresetPreference(Context context) {
+        ListPreference preference = new ListPreference(context);
+        preference.setKey(KEY_HEARING_AIDS_PRESETS);
+        preference.setOrder(ORDER_HEARING_AIDS_PRESETS);
+        preference.setTitle(context.getString(R.string.bluetooth_hearing_aids_presets));
+        preference.setOnPreferenceChangeListener(this);
+        return preference;
+    }
+
+    private void loadAllPresetInfo() {
+        if (mPreference == null) {
+            return;
+        }
+        List<BluetoothHapPresetInfo> infoList = mHapClientProfile.getAllPresetInfo(
+                mCachedDevice.getDevice());
+        CharSequence[] presetNames = new CharSequence[infoList.size()];
+        CharSequence[] presetIndexes = new CharSequence[infoList.size()];
+        for (int i = 0; i < infoList.size(); i++) {
+            presetNames[i] = infoList.get(i).getName();
+            presetIndexes[i] = Integer.toString(infoList.get(i).getIndex());
+        }
+        mPreference.setEntries(presetNames);
+        mPreference.setEntryValues(presetIndexes);
+    }
+
+    @VisibleForTesting
+    @Nullable
+    ListPreference getPreference() {
+        return mPreference;
+    }
+
+    void showErrorToast() {
+        Toast.makeText(mContext, R.string.bluetooth_hearing_aids_presets_error,
+                Toast.LENGTH_SHORT).show();
+    }
+}
diff --git a/src/com/android/settings/bluetooth/BluetoothDetailsHearingDeviceController.java b/src/com/android/settings/bluetooth/BluetoothDetailsHearingDeviceController.java
new file mode 100644
index 0000000..3703b71
--- /dev/null
+++ b/src/com/android/settings/bluetooth/BluetoothDetailsHearingDeviceController.java
@@ -0,0 +1,116 @@
+/*
+ * 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.bluetooth;
+
+import android.content.Context;
+
+import androidx.annotation.NonNull;
+import androidx.preference.PreferenceFragmentCompat;
+import androidx.preference.PreferenceScreen;
+
+import com.android.settings.accessibility.Flags;
+import com.android.settingslib.bluetooth.CachedBluetoothDevice;
+import com.android.settingslib.bluetooth.LocalBluetoothManager;
+import com.android.settingslib.core.lifecycle.Lifecycle;
+
+import com.google.common.annotations.VisibleForTesting;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * The controller of the hearing device controls.
+ *
+ * <p><b>Note:</b> It is responsible for creating the sub-controllers inside this preference
+ * category controller.
+ */
+public class BluetoothDetailsHearingDeviceController extends BluetoothDetailsController {
+
+    public static final int ORDER_HEARING_DEVICE_SETTINGS = 1;
+    public static final int ORDER_HEARING_AIDS_PRESETS = 2;
+    static final String KEY_HEARING_DEVICE_GROUP = "hearing_device_group";
+
+    private final List<BluetoothDetailsController> mControllers = new ArrayList<>();
+    private Lifecycle mLifecycle;
+    private LocalBluetoothManager mManager;
+
+    public BluetoothDetailsHearingDeviceController(@NonNull Context context,
+            @NonNull PreferenceFragmentCompat fragment,
+            @NonNull LocalBluetoothManager manager,
+            @NonNull CachedBluetoothDevice device,
+            @NonNull Lifecycle lifecycle) {
+        super(context, fragment, device, lifecycle);
+        mManager = manager;
+        mLifecycle = lifecycle;
+    }
+
+    @VisibleForTesting
+    void setSubControllers(
+            BluetoothDetailsHearingDeviceSettingsController hearingDeviceSettingsController,
+            BluetoothDetailsHearingAidsPresetsController presetsController) {
+        mControllers.clear();
+        mControllers.add(hearingDeviceSettingsController);
+        mControllers.add(presetsController);
+    }
+
+    @Override
+    public boolean isAvailable() {
+        return mControllers.stream().anyMatch(BluetoothDetailsController::isAvailable);
+    }
+
+    @Override
+    @NonNull
+    public String getPreferenceKey() {
+        return KEY_HEARING_DEVICE_GROUP;
+    }
+
+    @Override
+    protected void init(PreferenceScreen screen) {
+
+    }
+
+    @Override
+    protected void refresh() {
+
+    }
+
+    /**
+     * Initiates the sub controllers controlled by this group controller.
+     *
+     * <p><b>Note:</b> The caller must call this method when creating this class.
+     *
+     * @param isLaunchFromHearingDevicePage a boolean that determines if the caller is launch from
+     *                                      hearing device page
+     */
+    void initSubControllers(boolean isLaunchFromHearingDevicePage) {
+        mControllers.clear();
+        // Don't need to show the entrance to hearing device page when launched from the same page
+        if (!isLaunchFromHearingDevicePage) {
+            mControllers.add(new BluetoothDetailsHearingDeviceSettingsController(mContext,
+                    mFragment, mCachedDevice, mLifecycle));
+        }
+        if (Flags.enableHearingAidPresetControl()) {
+            mControllers.add(new BluetoothDetailsHearingAidsPresetsController(mContext, mFragment,
+                    mManager, mCachedDevice, mLifecycle));
+        }
+    }
+
+    @NonNull
+    public List<BluetoothDetailsController> getSubControllers() {
+        return mControllers;
+    }
+}
diff --git a/src/com/android/settings/bluetooth/BluetoothDetailsHearingDeviceControlsController.java b/src/com/android/settings/bluetooth/BluetoothDetailsHearingDeviceSettingsController.java
similarity index 71%
rename from src/com/android/settings/bluetooth/BluetoothDetailsHearingDeviceControlsController.java
rename to src/com/android/settings/bluetooth/BluetoothDetailsHearingDeviceSettingsController.java
index 162abc7..7e5f3b1 100644
--- a/src/com/android/settings/bluetooth/BluetoothDetailsHearingDeviceControlsController.java
+++ b/src/com/android/settings/bluetooth/BluetoothDetailsHearingDeviceSettingsController.java
@@ -16,6 +16,9 @@
 
 package com.android.settings.bluetooth;
 
+import static com.android.settings.bluetooth.BluetoothDetailsHearingDeviceController.KEY_HEARING_DEVICE_GROUP;
+import static com.android.settings.bluetooth.BluetoothDetailsHearingDeviceController.ORDER_HEARING_DEVICE_SETTINGS;
+
 import android.content.Context;
 import android.text.TextUtils;
 
@@ -36,15 +39,13 @@
 /**
  * The controller of the hearing device settings to launch Hearing device page.
  */
-public class BluetoothDetailsHearingDeviceControlsController extends BluetoothDetailsController
+public class BluetoothDetailsHearingDeviceSettingsController extends BluetoothDetailsController
         implements Preference.OnPreferenceClickListener {
 
     @VisibleForTesting
-    static final String KEY_DEVICE_CONTROLS_GENERAL_GROUP = "device_controls_general";
-    @VisibleForTesting
-    static final String KEY_HEARING_DEVICE_CONTROLS = "hearing_device_controls";
+    static final String KEY_HEARING_DEVICE_SETTINGS = "hearing_device_settings";
 
-    public BluetoothDetailsHearingDeviceControlsController(Context context,
+    public BluetoothDetailsHearingDeviceSettingsController(Context context,
             PreferenceFragmentCompat fragment, CachedBluetoothDevice device, Lifecycle lifecycle) {
         super(context, fragment, device, lifecycle);
         lifecycle.addObserver(this);
@@ -57,37 +58,40 @@
 
     @Override
     protected void init(PreferenceScreen screen) {
-        if (!mCachedDevice.isHearingAidDevice()) {
+        if (!isAvailable()) {
             return;
         }
-
-        final PreferenceCategory prefCategory = screen.findPreference(getPreferenceKey());
-        final Preference pref = createHearingDeviceControlsPreference(prefCategory.getContext());
-        prefCategory.addPreference(pref);
+        final PreferenceCategory group = screen.findPreference(KEY_HEARING_DEVICE_GROUP);
+        final Preference pref = createHearingDeviceSettingsPreference(group.getContext());
+        group.addPreference(pref);
     }
 
     @Override
-    protected void refresh() {}
+    protected void refresh() {
+
+    }
 
     @Override
     public String getPreferenceKey() {
-        return KEY_DEVICE_CONTROLS_GENERAL_GROUP;
+        return KEY_HEARING_DEVICE_SETTINGS;
     }
 
     @Override
     public boolean onPreferenceClick(Preference preference) {
-        if (TextUtils.equals(preference.getKey(), KEY_HEARING_DEVICE_CONTROLS)) {
+        if (TextUtils.equals(preference.getKey(), KEY_HEARING_DEVICE_SETTINGS)) {
             launchAccessibilityHearingDeviceSettings();
             return true;
         }
         return false;
     }
 
-    private Preference createHearingDeviceControlsPreference(Context context) {
+    private Preference createHearingDeviceSettingsPreference(Context context) {
         final ArrowPreference preference = new ArrowPreference(context);
-        preference.setKey(KEY_HEARING_DEVICE_CONTROLS);
-        preference.setTitle(context.getString(R.string.bluetooth_device_controls_title));
-        preference.setSummary(context.getString(R.string.bluetooth_device_controls_summary));
+        preference.setKey(KEY_HEARING_DEVICE_SETTINGS);
+        preference.setOrder(ORDER_HEARING_DEVICE_SETTINGS);
+        preference.setTitle(context.getString(R.string.bluetooth_hearing_device_settings_title));
+        preference.setSummary(
+                context.getString(R.string.bluetooth_hearing_device_settings_summary));
         preference.setOnPreferenceClickListener(this);
 
         return preference;
diff --git a/src/com/android/settings/bluetooth/BluetoothDeviceDetailsFragment.java b/src/com/android/settings/bluetooth/BluetoothDeviceDetailsFragment.java
index 9c68c9c..87b2c6b 100644
--- a/src/com/android/settings/bluetooth/BluetoothDeviceDetailsFragment.java
+++ b/src/com/android/settings/bluetooth/BluetoothDeviceDetailsFragment.java
@@ -326,16 +326,16 @@
                     lifecycle));
             controllers.add(new BluetoothDetailsPairOtherController(context, this, mCachedDevice,
                     lifecycle));
-            // Don't need to show hearing device again when launched from the same page.
-            if (!isLaunchFromHearingDevicePage()) {
-                controllers.add(new BluetoothDetailsHearingDeviceControlsController(context, this,
-                        mCachedDevice, lifecycle));
-            }
-            controllers.add(new BluetoothDetailsDataSyncController(context, this,
-                    mCachedDevice, lifecycle));
-            controllers.add(
-                    new BluetoothDetailsExtraOptionsController(
-                            context, this, mCachedDevice, lifecycle));
+            controllers.add(new BluetoothDetailsDataSyncController(context, this, mCachedDevice,
+                    lifecycle));
+            controllers.add(new BluetoothDetailsExtraOptionsController(context, this, mCachedDevice,
+                    lifecycle));
+            BluetoothDetailsHearingDeviceController hearingDeviceController =
+                    new BluetoothDetailsHearingDeviceController(context, this, mManager,
+                            mCachedDevice, lifecycle);
+            controllers.add(hearingDeviceController);
+            hearingDeviceController.initSubControllers(isLaunchFromHearingDevicePage());
+            controllers.addAll(hearingDeviceController.getSubControllers());
         }
         return controllers;
     }
diff --git a/src/com/android/settings/fuelgauge/AdvancedPowerUsageDetail.java b/src/com/android/settings/fuelgauge/AdvancedPowerUsageDetail.java
index 6ef5aa8..42e6d9c 100644
--- a/src/com/android/settings/fuelgauge/AdvancedPowerUsageDetail.java
+++ b/src/com/android/settings/fuelgauge/AdvancedPowerUsageDetail.java
@@ -52,7 +52,6 @@
 import com.android.settingslib.applications.ApplicationsState;
 import com.android.settingslib.core.AbstractPreferenceController;
 import com.android.settingslib.core.instrumentation.Instrumentable;
-import com.android.settingslib.datastore.ChangeReason;
 import com.android.settingslib.widget.LayoutPreference;
 
 import java.util.ArrayList;
@@ -272,7 +271,6 @@
     public void onPause() {
         super.onPause();
 
-        notifyBackupManager();
         final int currentOptimizeMode = mBatteryOptimizeUtils.getAppOptimizationMode();
         mLogStringBuilder.append(", onPause mode = ").append(currentOptimizeMode);
         logMetricCategory(currentOptimizeMode);
@@ -290,13 +288,6 @@
     }
 
     @VisibleForTesting
-    void notifyBackupManager() {
-        if (mOptimizationMode != mBatteryOptimizeUtils.getAppOptimizationMode()) {
-            BatterySettingsStorage.get(getContext()).notifyChange(ChangeReason.UPDATE);
-        }
-    }
-
-    @VisibleForTesting
     void initHeader() {
         final View appSnippet = mHeaderPreference.findViewById(R.id.entity_header);
         final Activity context = getActivity();
diff --git a/src/com/android/settings/fuelgauge/BatteryOptimizeUtils.java b/src/com/android/settings/fuelgauge/BatteryOptimizeUtils.java
index dc4aade..001876c3 100644
--- a/src/com/android/settings/fuelgauge/BatteryOptimizeUtils.java
+++ b/src/com/android/settings/fuelgauge/BatteryOptimizeUtils.java
@@ -33,6 +33,7 @@
 
 import com.android.settings.R;
 import com.android.settings.fuelgauge.BatteryOptimizeHistoricalLogEntry.Action;
+import com.android.settingslib.datastore.ChangeReason;
 import com.android.settingslib.fuelgauge.PowerAllowlistBackend;
 
 import java.lang.annotation.Retention;
@@ -222,6 +223,10 @@
             return;
         }
 
+        // App preferences are already clear when code reach here, and there may be no
+        // setAppUsageStateInternal call to notifyChange. So always trigger notifyChange here.
+        BatterySettingsStorage.get(context).notifyChange(ChangeReason.DELETE);
+
         allowlistBackend.refreshList();
         // Resets optimization mode for each application.
         for (ApplicationInfo info : applications) {
@@ -351,6 +356,9 @@
         }
         BatteryOptimizeLogUtils.writeLog(
                 context, action, packageNameKey, createLogEvent(appStandbyMode, allowListed));
+        if (action != Action.RESET) { // reset has been notified in resetAppOptimizationMode
+            BatterySettingsStorage.get(context).notifyChange(toChangeReason(action));
+        }
     }
 
     private static String createLogEvent(int appStandbyMode, boolean allowListed) {
@@ -362,4 +370,8 @@
                         allowListed,
                         getAppOptimizationMode(appStandbyMode, allowListed));
     }
+
+    private static @ChangeReason int toChangeReason(Action action) {
+        return action == Action.RESTORE ? ChangeReason.RESTORE : ChangeReason.UPDATE;
+    }
 }
diff --git a/src/com/android/settings/fuelgauge/PowerBackgroundUsageDetail.java b/src/com/android/settings/fuelgauge/PowerBackgroundUsageDetail.java
index 56702cf..b662d3e 100644
--- a/src/com/android/settings/fuelgauge/PowerBackgroundUsageDetail.java
+++ b/src/com/android/settings/fuelgauge/PowerBackgroundUsageDetail.java
@@ -41,7 +41,6 @@
 import com.android.settingslib.applications.AppUtils;
 import com.android.settingslib.applications.ApplicationsState;
 import com.android.settingslib.core.AbstractPreferenceController;
-import com.android.settingslib.datastore.ChangeReason;
 import com.android.settingslib.widget.FooterPreference;
 import com.android.settingslib.widget.LayoutPreference;
 import com.android.settingslib.widget.MainSwitchPreference;
@@ -116,7 +115,6 @@
     public void onPause() {
         super.onPause();
 
-        notifyBackupManager();
         final int currentOptimizeMode = mBatteryOptimizeUtils.getAppOptimizationMode();
         mLogStringBuilder.append(", onPause mode = ").append(currentOptimizeMode);
         logMetricCategory(currentOptimizeMode);
@@ -184,13 +182,6 @@
     }
 
     @VisibleForTesting
-    void notifyBackupManager() {
-        if (mOptimizationMode != mBatteryOptimizeUtils.getAppOptimizationMode()) {
-            BatterySettingsStorage.get(getContext()).notifyChange(ChangeReason.UPDATE);
-        }
-    }
-
-    @VisibleForTesting
     int getSelectedPreference() {
         if (!mMainSwitchPreference.isChecked()) {
             return BatteryOptimizeUtils.MODE_RESTRICTED;
diff --git a/src/com/android/settings/inputmethod/TrackpadTapDraggingPreferenceController.java b/src/com/android/settings/inputmethod/TrackpadTapDraggingPreferenceController.java
index 28c2915..30253a8 100644
--- a/src/com/android/settings/inputmethod/TrackpadTapDraggingPreferenceController.java
+++ b/src/com/android/settings/inputmethod/TrackpadTapDraggingPreferenceController.java
@@ -16,16 +16,22 @@
 
 package com.android.settings.inputmethod;
 
+import android.app.settings.SettingsEnums;
 import android.content.Context;
 import android.hardware.input.InputSettings;
 
 import com.android.settings.R;
 import com.android.settings.core.TogglePreferenceController;
+import com.android.settings.overlay.FeatureFactory;
+import com.android.settingslib.core.instrumentation.MetricsFeatureProvider;
 
 public class TrackpadTapDraggingPreferenceController extends TogglePreferenceController {
 
+    private MetricsFeatureProvider mMetricsFeatureProvider;
+
     public TrackpadTapDraggingPreferenceController(Context context, String key) {
         super(context, key);
+        mMetricsFeatureProvider = FeatureFactory.getFeatureFactory().getMetricsFeatureProvider();
     }
 
     @Override
@@ -36,7 +42,8 @@
     @Override
     public boolean setChecked(boolean isChecked) {
         InputSettings.setTouchpadTapDragging(mContext, isChecked);
-        // TODO(b/321978150): add a metric for tap dragging settings changes.
+        mMetricsFeatureProvider.action(
+                mContext, SettingsEnums.ACTION_GESTURE_TAP_DRAGGING_CHANGED, isChecked);
         return true;
     }
 
diff --git a/src/com/android/settings/network/EraseEuiccDataController.java b/src/com/android/settings/network/EraseEuiccDataController.java
index 9892f0d..782ab7d 100644
--- a/src/com/android/settings/network/EraseEuiccDataController.java
+++ b/src/com/android/settings/network/EraseEuiccDataController.java
@@ -25,7 +25,6 @@
 
 import com.android.settings.Utils;
 import com.android.settings.core.BasePreferenceController;
-import com.android.settings.core.PreferenceControllerMixin;
 import com.android.settings.network.telephony.MobileNetworkUtils;
 import com.android.settings.system.ResetDashboardFragment;
 
@@ -51,7 +50,12 @@
         if (!TextUtils.equals(preference.getKey(), getPreferenceKey())) {
             return false;
         }
-        EraseEuiccDataDialogFragment.show(mHostFragment);
+        if (SubscriptionUtil.hasSubscriptionWithRacCarrier(mContext)
+                && !SubscriptionUtil.isConnectedToWifi(mContext)) {
+            EuiccRacConnectivityDialogFragment.show(mHostFragment);
+        } else {
+            EraseEuiccDataDialogFragment.show(mHostFragment);
+        }
         return true;
     }
 
diff --git a/src/com/android/settings/network/EuiccRacConnectivityDialogFragment.java b/src/com/android/settings/network/EuiccRacConnectivityDialogFragment.java
new file mode 100644
index 0000000..76a587e
--- /dev/null
+++ b/src/com/android/settings/network/EuiccRacConnectivityDialogFragment.java
@@ -0,0 +1,115 @@
+/*
+ * 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;
+
+import android.app.AlertDialog;
+import android.app.Dialog;
+import android.app.settings.SettingsEnums;
+import android.content.DialogInterface;
+import android.os.Bundle;
+import android.text.TextUtils;
+import android.util.Log;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.widget.TextView;
+
+import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
+import androidx.fragment.app.Fragment;
+import androidx.fragment.app.FragmentManager;
+
+import com.android.settings.R;
+import com.android.settings.core.instrumentation.InstrumentedDialogFragment;
+import com.android.settings.system.ResetDashboardFragment;
+
+public class EuiccRacConnectivityDialogFragment extends InstrumentedDialogFragment
+        implements DialogInterface.OnClickListener {
+    public static final String TAG = "EuiccRacConnectivityDlg";
+
+    static void show(ResetDashboardFragment host) {
+        final EuiccRacConnectivityDialogFragment dialog = new EuiccRacConnectivityDialogFragment();
+        dialog.setTargetFragment(host, /* requestCode= */ 0);
+        final FragmentManager manager = host.getActivity().getSupportFragmentManager();
+        dialog.show(manager, TAG);
+    }
+
+    @Override
+    public int getMetricsCategory() {
+        return SettingsEnums.RESET_EUICC;
+    }
+
+    @NonNull
+    @Override
+    public Dialog onCreateDialog(@Nullable Bundle savedInstanceState) {
+        String title = getString(R.string.wifi_warning_dialog_title);
+        String message = getString(R.string.wifi_warning_dialog_text);
+
+        AlertDialog.Builder builder =
+                new AlertDialog.Builder(getContext())
+                        .setOnDismissListener(this)
+                        // Return is on the right side
+                        .setPositiveButton(R.string.wifi_warning_return_button, null)
+                        // Continue is on the left side
+                        .setNegativeButton(R.string.wifi_warning_continue_button, this);
+
+        View content =
+                LayoutInflater.from(getContext())
+                        .inflate(R.layout.sim_warning_dialog_wifi_connectivity, null);
+
+        // Found the layout resource
+        if (content != null) {
+            TextView dialogTitle = content.findViewById(R.id.title);
+            if (!TextUtils.isEmpty(title) && dialogTitle != null) {
+                dialogTitle.setText(title);
+                dialogTitle.setVisibility(View.VISIBLE);
+            }
+            TextView dialogMessage = content.findViewById(R.id.msg);
+            if (!TextUtils.isEmpty(message) && dialogMessage != null) {
+                dialogMessage.setText(message);
+                dialogMessage.setVisibility(View.VISIBLE);
+            }
+
+            builder.setView(content);
+        } else { // Not found the layout resource, use standard layout
+            if (!TextUtils.isEmpty(title)) {
+                builder.setTitle(title);
+            }
+            if (!TextUtils.isEmpty(message)) {
+                builder.setMessage(message);
+            }
+        }
+
+        AlertDialog dialog = builder.create();
+        dialog.setCanceledOnTouchOutside(false);
+        return dialog;
+    }
+
+    @Override
+    public void onClick(@NonNull DialogInterface dialog, int which) {
+        final Fragment fragment = getTargetFragment();
+        if (!(fragment instanceof ResetDashboardFragment)) {
+            Log.e(TAG, "getTargetFragment return unexpected type");
+            return;
+        }
+
+        // Positions of the buttons have been switch:
+        // negative button = left button = the button to continue
+        if (which == DialogInterface.BUTTON_NEGATIVE) {
+            EraseEuiccDataDialogFragment.show(((ResetDashboardFragment) fragment));
+        }
+    }
+}
diff --git a/src/com/android/settings/network/SubscriptionUtil.java b/src/com/android/settings/network/SubscriptionUtil.java
index 497af25..6d6f4c5 100644
--- a/src/com/android/settings/network/SubscriptionUtil.java
+++ b/src/com/android/settings/network/SubscriptionUtil.java
@@ -523,20 +523,21 @@
 
     /**
      * Starts a dialog activity to handle eSIM deletion.
+     *
      * @param context {@code Context}
      * @param subId The id of subscription need to be deleted.
+     * @param carrierId The carrier id of the subscription.
      */
-    public static void startDeleteEuiccSubscriptionDialogActivity(Context context, int subId,
-            int carrierId) {
+    public static void startDeleteEuiccSubscriptionDialogActivity(
+            @NonNull Context context, int subId, int carrierId) {
         if (!SubscriptionManager.isUsableSubscriptionId(subId)) {
             Log.i(TAG, "Unable to delete subscription due to invalid subscription ID.");
             return;
         }
-        final int[] carriersThatUseRAC = context.getResources().getIntArray(
-                R.array.config_carrier_use_rac);
-        boolean isCarrierRac = Arrays.stream(carriersThatUseRAC).anyMatch(cid -> cid == carrierId);
 
-        if (isCarrierRac && !isConnectedToWifiOrDifferentSubId(context, subId)) {
+        if (isCarrierRac(context, carrierId)
+                && (!isConnectedToWifi(context)
+                        || isConnectedToMobileDataWithDifferentSubId(context, subId))) {
             context.startActivity(EuiccRacConnectivityDialogActivity.getIntent(context, subId));
         } else {
             context.startActivity(DeleteEuiccSubscriptionDialogActivity.getIntent(context, subId));
@@ -814,27 +815,75 @@
     }
 
     /**
-     * Returns {@code true} if device is connected to Wi-Fi or mobile data provided by a different
-     * subId.
+     * Checks if the device is connected to Wi-Fi.
+     *
+     * @param context context
+     * @return {@code true} if connected to Wi-Fi
+     */
+    static boolean isConnectedToWifi(@NonNull Context context) {
+        NetworkCapabilities capabilities = getNetworkCapabilities(context);
+
+        return capabilities != null
+                && capabilities.hasTransport(NetworkCapabilities.TRANSPORT_WIFI);
+    }
+
+    /**
+     * Checks if the device is connected to mobile data provided by a different subId.
      *
      * @param context context
      * @param targetSubId subscription that is going to be deleted
+     * @return {@code true} if connected to mobile data provided by a different subId
      */
     @VisibleForTesting
-    static boolean isConnectedToWifiOrDifferentSubId(@NonNull Context context, int targetSubId) {
+    static boolean isConnectedToMobileDataWithDifferentSubId(
+            @NonNull Context context, int targetSubId) {
+        NetworkCapabilities capabilities = getNetworkCapabilities(context);
+
+        return capabilities != null
+                && capabilities.hasTransport(NetworkCapabilities.TRANSPORT_CELLULAR)
+                && targetSubId != SubscriptionManager.getActiveDataSubscriptionId();
+    }
+
+    /**
+     * Checks if any subscription carrier use reusable activation codes.
+     *
+     * @param context The context used to retrieve carriers that uses reusable activation codes.
+     * @return {@code true} if any subscription has a matching carrier that uses reusable activation
+     *     codes
+     */
+    static boolean hasSubscriptionWithRacCarrier(@NonNull Context context) {
+        List<SubscriptionInfo> subs = getAvailableSubscriptions(context);
+        final int[] carriersThatUseRac =
+                context.getResources().getIntArray(R.array.config_carrier_use_rac);
+
+        return Arrays.stream(carriersThatUseRac)
+                .anyMatch(cid -> subs.stream().anyMatch(sub -> sub.getCarrierId() == cid));
+    }
+
+    /**
+     * Checks if a carrier use reusable activation codes.
+     *
+     * @param context The context used to retrieve carriers that uses reusable activation codes.
+     * @param carrierId The carrier id to check if it use reusable activation codes.
+     * @return {@code true} if carrier id use reusable activation codes.
+     */
+    @VisibleForTesting
+    static boolean isCarrierRac(@NonNull Context context, int carrierId) {
+        final int[] carriersThatUseRAC =
+                context.getResources().getIntArray(R.array.config_carrier_use_rac);
+
+        return Arrays.stream(carriersThatUseRAC).anyMatch(cid -> cid == carrierId);
+    }
+
+    /**
+     * Retrieves NetworkCapabilities for the active network.
+     *
+     * @param context context
+     * @return NetworkCapabilities or null if not available
+     */
+    private static NetworkCapabilities getNetworkCapabilities(@NonNull Context context) {
         ConnectivityManager connectivityManager =
                 context.getSystemService(ConnectivityManager.class);
-        NetworkCapabilities capabilities =
-                connectivityManager.getNetworkCapabilities(connectivityManager.getActiveNetwork());
-
-        if (capabilities != null) {
-            if (capabilities.hasTransport(NetworkCapabilities.TRANSPORT_WIFI)) {
-                // Connected to WiFi
-                return true;
-            } else if (capabilities.hasTransport(NetworkCapabilities.TRANSPORT_CELLULAR)) {
-                return targetSubId != SubscriptionManager.getActiveDataSubscriptionId();
-            }
-        }
-        return false;
+        return connectivityManager.getNetworkCapabilities(connectivityManager.getActiveNetwork());
     }
 }
diff --git a/src/com/android/settings/privatespace/HidePrivateSpaceController.java b/src/com/android/settings/privatespace/HidePrivateSpaceController.java
index 903defa..81814ad 100644
--- a/src/com/android/settings/privatespace/HidePrivateSpaceController.java
+++ b/src/com/android/settings/privatespace/HidePrivateSpaceController.java
@@ -19,13 +19,21 @@
 import static com.android.settings.privatespace.PrivateSpaceMaintainer.HIDE_PRIVATE_SPACE_ENTRY_POINT_DISABLED_VAL;
 import static com.android.settings.privatespace.PrivateSpaceMaintainer.HIDE_PRIVATE_SPACE_ENTRY_POINT_ENABLED_VAL;
 
+import android.app.AlertDialog;
 import android.content.Context;
+import android.content.DialogInterface;
 
+import com.android.settings.R;
 import com.android.settings.core.TogglePreferenceController;
 
 /**
- *  A class that is used to show details page for the setting to hide private space entry point
- *  in All Apps.
+ * Toggle Preference Controller responsible for managing the visibility of private space entry point
+ * in the "All Apps" section. This includes:
+ *
+ * <p>Toggling the entry point's visibility (hiding/unhiding)
+ *
+ * <p>Displaying a dialog to inform the user that the entry point will be hidden when private space
+ * is locked (if the hide option is enabled)
  */
 public class HidePrivateSpaceController extends TogglePreferenceController {
     private final PrivateSpaceMaintainer mPrivateSpaceMaintainer;
@@ -39,7 +47,7 @@
     @AvailabilityStatus
     public int getAvailabilityStatus() {
         return android.os.Flags.allowPrivateProfile()
-                && android.multiuser.Flags.enablePrivateSpaceFeatures()
+                        && android.multiuser.Flags.enablePrivateSpaceFeatures()
                 ? AVAILABLE
                 : UNSUPPORTED_ON_DEVICE;
     }
@@ -55,6 +63,9 @@
         mPrivateSpaceMaintainer.setHidePrivateSpaceEntryPointSetting(
                 isChecked ? HIDE_PRIVATE_SPACE_ENTRY_POINT_ENABLED_VAL
                         : HIDE_PRIVATE_SPACE_ENTRY_POINT_DISABLED_VAL);
+        if (isChecked) {
+            showAlertDialog();
+        }
         return true;
     }
 
@@ -62,4 +73,16 @@
     public int getSliceHighlightMenuRes() {
         return 0;
     }
+
+    private void showAlertDialog() {
+        new AlertDialog.Builder(mContext)
+                .setTitle(R.string.private_space_hide_dialog_title)
+                .setMessage(R.string.private_space_hide_dialog_message)
+                .setPositiveButton(
+                        R.string.private_space_hide_dialog_button,
+                        (DialogInterface dialog, int which) -> {
+                            dialog.dismiss();
+                        })
+                .show();
+    }
 }
diff --git a/src/com/android/settings/security/ContentProtectionPreferenceUtils.java b/src/com/android/settings/security/ContentProtectionPreferenceUtils.java
index d84d7c5..b1167ea 100644
--- a/src/com/android/settings/security/ContentProtectionPreferenceUtils.java
+++ b/src/com/android/settings/security/ContentProtectionPreferenceUtils.java
@@ -15,15 +15,23 @@
  */
 package com.android.settings.security;
 
+import static android.view.contentprotection.flags.Flags.manageDevicePolicyEnabled;
+
 import static com.android.internal.R.string.config_defaultContentProtectionService;
 
+import android.app.admin.DevicePolicyManager;
 import android.content.ComponentName;
 import android.content.Context;
+import android.content.pm.PackageManager;
+import android.os.UserHandle;
+import android.os.UserManager;
 import android.provider.DeviceConfig;
 import android.view.contentcapture.ContentCaptureManager;
 
-import androidx.annotation.Nullable;
 import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
+
+import com.android.settings.Utils;
 
 /** Util class for content protection preference. */
 public class ContentProtectionPreferenceUtils {
@@ -60,4 +68,49 @@
                 ContentCaptureManager.DEVICE_CONFIG_PROPERTY_ENABLE_CONTENT_PROTECTION_RECEIVER,
                 ContentCaptureManager.DEFAULT_ENABLE_CONTENT_PROTECTION_RECEIVER);
     }
+
+    /** Returns the managed profile or null if none exists. */
+    @Nullable
+    public static UserHandle getManagedProfile(@NonNull Context context) {
+        UserManager userManager = context.getSystemService(UserManager.class);
+        if (userManager == null) {
+            return null;
+        }
+        return Utils.getManagedProfile(userManager);
+    }
+
+    /** Returns the current content protection policy. */
+    @DevicePolicyManager.ContentProtectionPolicy
+    public static int getContentProtectionPolicy(
+            @NonNull Context context, @Nullable UserHandle managedProfile) {
+        if (!manageDevicePolicyEnabled()) {
+            return DevicePolicyManager.CONTENT_PROTECTION_DISABLED;
+        }
+        Context policyContext = createContentProtectionPolicyContext(context, managedProfile);
+        return getContentProtectionPolicyWithGivenContext(policyContext);
+    }
+
+    @NonNull
+    private static Context createContentProtectionPolicyContext(
+            @NonNull Context context, @Nullable UserHandle managedProfile) {
+        if (managedProfile == null) {
+            return context;
+        }
+        try {
+            return context.createPackageContextAsUser(
+                    context.getPackageName(), /* flags= */ 0, managedProfile);
+        } catch (PackageManager.NameNotFoundException ex) {
+            throw new IllegalStateException(ex);
+        }
+    }
+
+    @DevicePolicyManager.ContentProtectionPolicy
+    private static int getContentProtectionPolicyWithGivenContext(@NonNull Context context) {
+        DevicePolicyManager devicePolicyManager =
+                context.getSystemService(DevicePolicyManager.class);
+        if (devicePolicyManager == null) {
+            return DevicePolicyManager.CONTENT_PROTECTION_DISABLED;
+        }
+        return devicePolicyManager.getContentProtectionPolicy(/* admin= */ null);
+    }
 }
diff --git a/src/com/android/settings/security/ContentProtectionTogglePreferenceController.java b/src/com/android/settings/security/ContentProtectionTogglePreferenceController.java
index 101364b..9203d61 100644
--- a/src/com/android/settings/security/ContentProtectionTogglePreferenceController.java
+++ b/src/com/android/settings/security/ContentProtectionTogglePreferenceController.java
@@ -15,12 +15,17 @@
  */
 package com.android.settings.security;
 
+import static android.view.contentprotection.flags.Flags.manageDevicePolicyEnabled;
+
+import android.app.admin.DevicePolicyManager;
 import android.content.ContentResolver;
 import android.content.Context;
+import android.os.UserHandle;
 import android.provider.Settings;
 import android.widget.CompoundButton;
 import android.widget.CompoundButton.OnCheckedChangeListener;
 
+import androidx.annotation.NonNull;
 import androidx.annotation.Nullable;
 import androidx.annotation.VisibleForTesting;
 import androidx.preference.Preference;
@@ -40,12 +45,22 @@
     static final String KEY_CONTENT_PROTECTION_PREFERENCE = "content_protection_user_consent";
 
     @Nullable private SettingsMainSwitchPreference mSwitchBar;
+
     @Nullable private RestrictedLockUtils.EnforcedAdmin mEnforcedAdmin;
-    private final ContentResolver mContentResolver;
+
+    @NonNull private final ContentResolver mContentResolver;
+
+    @DevicePolicyManager.ContentProtectionPolicy
+    private int mContentProtectionPolicy = DevicePolicyManager.CONTENT_PROTECTION_DISABLED;
 
     public ContentProtectionTogglePreferenceController(Context context, String preferenceKey) {
         super(context, preferenceKey);
         mContentResolver = context.getContentResolver();
+
+        if (manageDevicePolicyEnabled()) {
+            mEnforcedAdmin = getEnforcedAdmin();
+            mContentProtectionPolicy = getContentProtectionPolicy(getManagedProfile());
+        }
     }
 
     @Override
@@ -56,14 +71,30 @@
     @Override
     public boolean isChecked() {
         if (mEnforcedAdmin != null) {
-            // If fully managed device, it should always unchecked
-            return false;
+            if (!manageDevicePolicyEnabled()) {
+                // If fully managed device, it should always unchecked
+                return false;
+            }
+
+            if (mContentProtectionPolicy == DevicePolicyManager.CONTENT_PROTECTION_DISABLED) {
+                return false;
+            }
+            if (mContentProtectionPolicy == DevicePolicyManager.CONTENT_PROTECTION_ENABLED) {
+                return true;
+            }
         }
         return Settings.Global.getInt(mContentResolver, KEY_CONTENT_PROTECTION_PREFERENCE, 0) >= 0;
     }
 
     @Override
     public boolean setChecked(boolean isChecked) {
+        if (manageDevicePolicyEnabled()) {
+            if (mEnforcedAdmin != null
+                    && mContentProtectionPolicy
+                            != DevicePolicyManager.CONTENT_PROTECTION_NOT_CONTROLLED_BY_POLICY) {
+                return false;
+            }
+        }
         Settings.Global.putInt(
                 mContentResolver, KEY_CONTENT_PROTECTION_PREFERENCE, isChecked ? 1 : -1);
         return true;
@@ -80,16 +111,20 @@
         }
     }
 
-    /**
-     * Temporary workaround for SettingsMainSwitchPreference.setDisabledByAdmin without user
-     * restriction.
-     */
+    // Workaround for SettingsMainSwitchPreference.setDisabledByAdmin without user restriction.
     @Override
     public void updateState(Preference preference) {
         super.updateState(preference);
-        // Assign the value to mEnforcedAdmin since it's needed in isChecked()
-        mEnforcedAdmin = getEnforcedAdmin();
-        if (mSwitchBar != null && mEnforcedAdmin != null) {
+
+        if (!manageDevicePolicyEnabled()) {
+            // Assign the value to mEnforcedAdmin since it's needed in isChecked()
+            mEnforcedAdmin = getEnforcedAdmin();
+            mContentProtectionPolicy = DevicePolicyManager.CONTENT_PROTECTION_DISABLED;
+        }
+        if (mSwitchBar != null
+                && mEnforcedAdmin != null
+                && mContentProtectionPolicy
+                        != DevicePolicyManager.CONTENT_PROTECTION_NOT_CONTROLLED_BY_POLICY) {
             mSwitchBar.setDisabledByAdmin(mEnforcedAdmin);
         }
     }
@@ -107,7 +142,20 @@
     }
 
     @VisibleForTesting
+    @Nullable
+    protected UserHandle getManagedProfile() {
+        return ContentProtectionPreferenceUtils.getManagedProfile(mContext);
+    }
+
+    @VisibleForTesting
+    @Nullable
     protected RestrictedLockUtils.EnforcedAdmin getEnforcedAdmin() {
         return RestrictedLockUtilsInternal.getDeviceOwner(mContext);
     }
+
+    @VisibleForTesting
+    @DevicePolicyManager.ContentProtectionPolicy
+    protected int getContentProtectionPolicy(@Nullable UserHandle userHandle) {
+        return ContentProtectionPreferenceUtils.getContentProtectionPolicy(mContext, userHandle);
+    }
 }
diff --git a/src/com/android/settings/security/ContentProtectionWorkSwitchController.java b/src/com/android/settings/security/ContentProtectionWorkSwitchController.java
index 0404dcd..b9119ee 100644
--- a/src/com/android/settings/security/ContentProtectionWorkSwitchController.java
+++ b/src/com/android/settings/security/ContentProtectionWorkSwitchController.java
@@ -15,9 +15,11 @@
  */
 package com.android.settings.security;
 
+import static android.view.contentprotection.flags.Flags.manageDevicePolicyEnabled;
+
+import android.app.admin.DevicePolicyManager;
 import android.content.Context;
 import android.os.UserHandle;
-import android.os.UserManager;
 
 import androidx.annotation.NonNull;
 import androidx.annotation.Nullable;
@@ -25,7 +27,6 @@
 import androidx.preference.PreferenceScreen;
 
 import com.android.settings.R;
-import com.android.settings.Utils;
 import com.android.settings.core.TogglePreferenceController;
 import com.android.settingslib.RestrictedLockUtils;
 import com.android.settingslib.RestrictedSwitchPreference;
@@ -33,25 +34,49 @@
 /** Preference controller for content protection work profile switch bar. */
 public class ContentProtectionWorkSwitchController extends TogglePreferenceController {
 
+    @Nullable private UserHandle mManagedProfile;
+
+    @DevicePolicyManager.ContentProtectionPolicy
+    private int mContentProtectionPolicy = DevicePolicyManager.CONTENT_PROTECTION_DISABLED;
+
     public ContentProtectionWorkSwitchController(
             @NonNull Context context, @NonNull String preferenceKey) {
         super(context, preferenceKey);
+
+        if (manageDevicePolicyEnabled()) {
+            mManagedProfile = getManagedProfile();
+            if (mManagedProfile != null) {
+                mContentProtectionPolicy = getContentProtectionPolicy(mManagedProfile);
+            }
+        }
     }
 
     @Override
     public int getAvailabilityStatus() {
-        return getManagedProfile() != null ? AVAILABLE : CONDITIONALLY_UNAVAILABLE;
+        if (!manageDevicePolicyEnabled()) {
+            return getManagedProfile() != null ? AVAILABLE : CONDITIONALLY_UNAVAILABLE;
+        }
+        if (mManagedProfile == null) {
+            return CONDITIONALLY_UNAVAILABLE;
+        }
+        if (mContentProtectionPolicy
+                == DevicePolicyManager.CONTENT_PROTECTION_NOT_CONTROLLED_BY_POLICY) {
+            return CONDITIONALLY_UNAVAILABLE;
+        }
+        return AVAILABLE;
     }
 
-    // The switch is always set to unchecked until Android V by design
     @Override
     public boolean isChecked() {
-        return false;
+        if (!manageDevicePolicyEnabled()) {
+            return false;
+        }
+        return mContentProtectionPolicy == DevicePolicyManager.CONTENT_PROTECTION_ENABLED;
     }
 
-    // The switch is disabled until Android V by design
     @Override
     public boolean setChecked(boolean isChecked) {
+        // Controlled by the admin API
         return false;
     }
 
@@ -59,10 +84,13 @@
     public void displayPreference(PreferenceScreen screen) {
         super.displayPreference(screen);
 
-        RestrictedSwitchPreference switchPreference = screen.findPreference(getPreferenceKey());
-        UserHandle managedProfile = getManagedProfile();
+        UserHandle managedProfile =
+                manageDevicePolicyEnabled() ? mManagedProfile : getManagedProfile();
         if (managedProfile != null) {
-            switchPreference.setDisabledByAdmin(getEnforcedAdmin(managedProfile));
+            RestrictedSwitchPreference switchPreference = screen.findPreference(getPreferenceKey());
+            if (switchPreference != null) {
+                switchPreference.setDisabledByAdmin(getEnforcedAdmin(managedProfile));
+            }
         }
     }
 
@@ -74,13 +102,18 @@
     @VisibleForTesting
     @Nullable
     protected UserHandle getManagedProfile() {
-        return Utils.getManagedProfile(mContext.getSystemService(UserManager.class));
+        return ContentProtectionPreferenceUtils.getManagedProfile(mContext);
     }
 
     @VisibleForTesting
     @Nullable
-    protected RestrictedLockUtils.EnforcedAdmin getEnforcedAdmin(
-            @NonNull UserHandle managedProfile) {
-        return RestrictedLockUtils.getProfileOrDeviceOwner(mContext, managedProfile);
+    protected RestrictedLockUtils.EnforcedAdmin getEnforcedAdmin(@NonNull UserHandle userHandle) {
+        return RestrictedLockUtils.getProfileOrDeviceOwner(mContext, userHandle);
+    }
+
+    @VisibleForTesting
+    @DevicePolicyManager.ContentProtectionPolicy
+    protected int getContentProtectionPolicy(@Nullable UserHandle userHandle) {
+        return ContentProtectionPreferenceUtils.getContentProtectionPolicy(mContext, userHandle);
     }
 }
diff --git a/src/com/android/settings/spa/network/NetworkCellularGroupProvider.kt b/src/com/android/settings/spa/network/NetworkCellularGroupProvider.kt
index a0c363a..5a2a394 100644
--- a/src/com/android/settings/spa/network/NetworkCellularGroupProvider.kt
+++ b/src/com/android/settings/spa/network/NetworkCellularGroupProvider.kt
@@ -44,13 +44,13 @@
 import com.android.settings.R
 import com.android.settings.network.SubscriptionInfoListViewModel
 import com.android.settings.network.telephony.MobileNetworkUtils
+import com.android.settings.spa.network.PrimarySimRepository.PrimarySimInfo
 import com.android.settings.wifi.WifiPickerTrackerHelper
 import com.android.settingslib.spa.framework.common.SettingsEntryBuilder
 import com.android.settingslib.spa.framework.common.SettingsPageProvider
 import com.android.settingslib.spa.framework.common.createSettingsPage
 import com.android.settingslib.spa.framework.compose.navigator
 import com.android.settingslib.spa.framework.util.collectLatestWithLifecycle
-import com.android.settingslib.spa.widget.preference.ListPreferenceOption
 import com.android.settingslib.spa.widget.preference.Preference
 import com.android.settingslib.spa.widget.preference.PreferenceModel
 import com.android.settingslib.spa.widget.preference.SwitchPreference
@@ -173,27 +173,23 @@
 ) {
     val selectableSubscriptionInfoList by selectableSubscriptionInfoListFlow
         .collectAsStateWithLifecycle(initialValue = emptyList())
-    val activeSubscriptionInfoList: List<SubscriptionInfo> =
-        selectableSubscriptionInfoList.filter { subscriptionInfo ->
-            subscriptionInfo.simSlotIndex != -1
-        }
 
     val stringSims = stringResource(R.string.provider_network_settings_title)
     RegularScaffold(title = stringSims) {
         SimsSection(selectableSubscriptionInfoList)
         PrimarySimSectionImpl(
-                activeSubscriptionInfoList,
-                defaultVoiceSubId,
-                defaultSmsSubId,
-                defaultDataSubId,
-                nonDds
+            selectableSubscriptionInfoListFlow,
+            defaultVoiceSubId,
+            defaultSmsSubId,
+            defaultDataSubId,
+            nonDds
         )
     }
 }
 
 @Composable
 fun PrimarySimImpl(
-    subscriptionInfoList: List<SubscriptionInfo>,
+    primarySimInfo: PrimarySimInfo,
     callsSelectedId: MutableIntState,
     textsSelectedId: MutableIntState,
     mobileDataSelectedId: MutableIntState,
@@ -237,108 +233,83 @@
         }
     },
 ) {
-    var state = rememberSaveable { mutableStateOf(false) }
-    var callsAndSmsList = remember {
-        mutableListOf(ListPreferenceOption(id = -1, text = "Loading"))
-    }
-    var dataList = remember {
-        mutableListOf(ListPreferenceOption(id = -1, text = "Loading"))
+    val telephonyManagerForNonDds: TelephonyManager? =
+            context.getSystemService(TelephonyManager::class.java)
+                    ?.createForSubscriptionId(nonDds.intValue)
+    val automaticDataChecked = rememberSaveable() {
+        mutableStateOf(false)
     }
 
-    if (subscriptionInfoList.size >= 2) {
-        state.value = true
-        callsAndSmsList.clear()
-        dataList.clear()
-        for (info in subscriptionInfoList) {
-            var item = ListPreferenceOption(
-                    id = info.subscriptionId,
-                    text = "${info.displayName}",
-                    summary = "${info.number}"
-            )
-            callsAndSmsList.add(item)
-            dataList.add(item)
-        }
-        callsAndSmsList.add(
-            ListPreferenceOption(
-                id = SubscriptionManager.INVALID_SUBSCRIPTION_ID,
-                text = stringResource(id = R.string.sim_calls_ask_first_prefs_title)
-            )
-        )
-    } else {
-        // hide the primary sim
-        state.value = false
-        Log.d(NetworkCellularGroupProvider.name, "Hide primary sim")
-    }
+    CreatePrimarySimListPreference(
+        stringResource(id = R.string.primary_sim_calls_title),
+        primarySimInfo.callsAndSmsList,
+        callsSelectedId,
+        ImageVector.vectorResource(R.drawable.ic_phone),
+        actionSetCalls
+    )
+    CreatePrimarySimListPreference(
+        stringResource(id = R.string.primary_sim_texts_title),
+        primarySimInfo.callsAndSmsList,
+        textsSelectedId,
+        Icons.AutoMirrored.Outlined.Message,
+        actionSetTexts
+    )
+    CreatePrimarySimListPreference(
+        stringResource(id = R.string.mobile_data_settings_title),
+        primarySimInfo.dataList,
+        mobileDataSelectedId,
+        Icons.Outlined.DataUsage,
+        actionSetMobileData
+    )
 
-    if (state.value) {
-        val telephonyManagerForNonDds: TelephonyManager? =
-                context.getSystemService(TelephonyManager::class.java)
-                        ?.createForSubscriptionId(nonDds.intValue)
-        val automaticDataChecked = rememberSaveable() {
-            mutableStateOf(false)
-        }
-
-        CreatePrimarySimListPreference(
-            stringResource(id = R.string.primary_sim_calls_title),
-            callsAndSmsList,
-            callsSelectedId,
-            ImageVector.vectorResource(R.drawable.ic_phone),
-            actionSetCalls
-        )
-        CreatePrimarySimListPreference(
-            stringResource(id = R.string.primary_sim_texts_title),
-            callsAndSmsList,
-            textsSelectedId,
-            Icons.AutoMirrored.Outlined.Message,
-            actionSetTexts
-        )
-        CreatePrimarySimListPreference(
-            stringResource(id = R.string.mobile_data_settings_title),
-            dataList,
-            mobileDataSelectedId,
-            Icons.Outlined.DataUsage,
-            actionSetMobileData
-        )
-
-        val autoDataTitle = stringResource(id = R.string.primary_sim_automatic_data_title)
-        val autoDataSummary = stringResource(id = R.string.primary_sim_automatic_data_msg)
-        SwitchPreference(
-            object : SwitchPreferenceModel {
-                override val title = autoDataTitle
-                override val summary = { autoDataSummary }
-                override val checked = {
-                    if (nonDds.intValue != SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
-                        coroutineScope.launch {
-                            automaticDataChecked.value = getAutomaticData(telephonyManagerForNonDds)
-                            Log.d(
-                                NetworkCellularGroupProvider.name,
-                                "NonDds:${nonDds.intValue}" +
-                                    "getAutomaticData:${automaticDataChecked.value}"
-                            )
-                        }
+    val autoDataTitle = stringResource(id = R.string.primary_sim_automatic_data_title)
+    val autoDataSummary = stringResource(id = R.string.primary_sim_automatic_data_msg)
+    SwitchPreference(
+        object : SwitchPreferenceModel {
+            override val title = autoDataTitle
+            override val summary = { autoDataSummary }
+            override val checked = {
+                if (nonDds.intValue != SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
+                    coroutineScope.launch {
+                        automaticDataChecked.value = getAutomaticData(telephonyManagerForNonDds)
+                        Log.d(
+                            NetworkCellularGroupProvider.name,
+                            "NonDds:${nonDds.intValue}" +
+                                "getAutomaticData:${automaticDataChecked.value}"
+                        )
                     }
-                    automaticDataChecked.value
                 }
-                override val onCheckedChange: ((Boolean) -> Unit)? = {
-                    automaticDataChecked.value = it
-                    actionSetAutoDataSwitch(it)
-                }
+                automaticDataChecked.value
             }
-        )
-    }
+            override val onCheckedChange: ((Boolean) -> Unit)? = {
+                automaticDataChecked.value = it
+                actionSetAutoDataSwitch(it)
+            }
+        }
+    )
 }
 
 @Composable
 fun PrimarySimSectionImpl(
-    subscriptionInfoList: List<SubscriptionInfo>,
+    subscriptionInfoListFlow: Flow<List<SubscriptionInfo>>,
     callsSelectedId: MutableIntState,
     textsSelectedId: MutableIntState,
     mobileDataSelectedId: MutableIntState,
     nonDds: MutableIntState,
 ) {
+    val context = LocalContext.current
+    val primarySimInfo = remember(subscriptionInfoListFlow) {
+        subscriptionInfoListFlow
+            .map { subscriptionInfoList ->
+                subscriptionInfoList.filter { subInfo -> subInfo.simSlotIndex != -1 }
+            }
+            .map(PrimarySimRepository(context)::getPrimarySimInfo)
+            .flowOn(Dispatchers.Default)
+    }.collectAsStateWithLifecycle(initialValue = null).value ?: return
+
     Category(title = stringResource(id = R.string.primary_sim_title)) {
         PrimarySimImpl(
-            subscriptionInfoList,
+            primarySimInfo,
             callsSelectedId,
             textsSelectedId,
             mobileDataSelectedId,
diff --git a/src/com/android/settings/spa/network/PrimarySimRepository.kt b/src/com/android/settings/spa/network/PrimarySimRepository.kt
new file mode 100644
index 0000000..b9eb3ff
--- /dev/null
+++ b/src/com/android/settings/spa/network/PrimarySimRepository.kt
@@ -0,0 +1,62 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.settings.spa.network
+
+import android.content.Context
+import android.telephony.SubscriptionInfo
+import android.telephony.SubscriptionManager
+import android.util.Log
+import com.android.settings.R
+import com.android.settings.network.SubscriptionUtil
+import com.android.settingslib.spa.widget.preference.ListPreferenceOption
+
+class PrimarySimRepository(private val context: Context) {
+
+    data class PrimarySimInfo(
+        val callsAndSmsList: List<ListPreferenceOption>,
+        val dataList: List<ListPreferenceOption>,
+    )
+
+    fun getPrimarySimInfo(selectableSubscriptionInfoList: List<SubscriptionInfo>): PrimarySimInfo? {
+        if (selectableSubscriptionInfoList.size < 2) {
+            Log.d(TAG, "Hide primary sim")
+            return null
+        }
+
+        val callsAndSmsList = mutableListOf<ListPreferenceOption>()
+        val dataList = mutableListOf<ListPreferenceOption>()
+        for (info in selectableSubscriptionInfoList) {
+            val item = ListPreferenceOption(
+                id = info.subscriptionId,
+                text = "${info.displayName}",
+                summary = SubscriptionUtil.getFormattedPhoneNumber(context, info) ?: "",
+            )
+            callsAndSmsList += item
+            dataList += item
+        }
+        callsAndSmsList += ListPreferenceOption(
+            id = SubscriptionManager.INVALID_SUBSCRIPTION_ID,
+            text = context.getString(R.string.sim_calls_ask_first_prefs_title),
+        )
+
+        return PrimarySimInfo(callsAndSmsList, dataList)
+    }
+
+    private companion object {
+        private const val TAG = "PrimarySimRepository"
+    }
+}
diff --git a/src/com/android/settings/spa/network/SimOnboardingPrimarySim.kt b/src/com/android/settings/spa/network/SimOnboardingPrimarySim.kt
index b984966..a8c0575 100644
--- a/src/com/android/settings/spa/network/SimOnboardingPrimarySim.kt
+++ b/src/com/android/settings/spa/network/SimOnboardingPrimarySim.kt
@@ -24,10 +24,13 @@
 import androidx.compose.runtime.Composable
 import androidx.compose.runtime.MutableIntState
 import androidx.compose.runtime.mutableIntStateOf
+import androidx.compose.runtime.remember
 import androidx.compose.runtime.saveable.rememberSaveable
 import androidx.compose.ui.Modifier
 import androidx.compose.ui.graphics.vector.ImageVector
+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.SimOnboardingService
 import com.android.settingslib.spa.framework.theme.SettingsDimension
@@ -38,6 +41,9 @@
 import com.android.settingslib.spa.widget.scaffold.SuwScaffold
 import com.android.settingslib.spa.widget.ui.SettingsBody
 import com.android.settingslib.spa.widget.ui.SettingsIcon
+import kotlinx.coroutines.Dispatchers
+import kotlinx.coroutines.flow.flow
+import kotlinx.coroutines.flow.flowOn
 
 /**
  * the sim onboarding primary sim compose
@@ -77,13 +83,19 @@
             SettingsBody(stringResource(id = R.string.sim_onboarding_primary_sim_msg))
         }
 
-        var selectedSubscriptionInfoList =
-                onboardingService.getSelectedSubscriptionInfoListWithRenaming()
+        val context = LocalContext.current
+        val primarySimInfo = remember {
+            flow {
+                val selectableSubInfoList =
+                    onboardingService.getSelectedSubscriptionInfoListWithRenaming()
+                emit(PrimarySimRepository(context).getPrimarySimInfo(selectableSubInfoList))
+            }.flowOn(Dispatchers.Default)
+        }.collectAsStateWithLifecycle(initialValue = null).value ?: return@SuwScaffold
         callsSelectedId.intValue = onboardingService.targetPrimarySimCalls
         textsSelectedId.intValue = onboardingService.targetPrimarySimTexts
         mobileDataSelectedId.intValue = onboardingService.targetPrimarySimMobileData
         PrimarySimImpl(
-            subscriptionInfoList = selectedSubscriptionInfoList,
+            primarySimInfo = primarySimInfo,
             callsSelectedId = callsSelectedId,
             textsSelectedId = textsSelectedId,
             mobileDataSelectedId = mobileDataSelectedId,
diff --git a/src/com/android/settings/spa/network/SimsSection.kt b/src/com/android/settings/spa/network/SimsSection.kt
index 334ca61..9e4cf9f 100644
--- a/src/com/android/settings/spa/network/SimsSection.kt
+++ b/src/com/android/settings/spa/network/SimsSection.kt
@@ -36,10 +36,10 @@
 import com.android.settings.network.telephony.phoneNumberFlow
 import com.android.settingslib.spa.widget.preference.PreferenceModel
 import com.android.settingslib.spa.widget.preference.SwitchPreferenceModel
-import com.android.settingslib.spa.widget.preference.TwoTargetSwitchPreference
 import com.android.settingslib.spa.widget.ui.SettingsIcon
 import com.android.settingslib.spaprivileged.model.enterprise.Restrictions
 import com.android.settingslib.spaprivileged.template.preference.RestrictedPreference
+import com.android.settingslib.spaprivileged.template.preference.RestrictedTwoTargetSwitchPreference
 
 @Composable
 fun SimsSection(subscriptionInfoList: List<SubscriptionInfo>) {
@@ -61,9 +61,8 @@
     val phoneNumber = remember(subInfo) {
         context.phoneNumberFlow(subInfo)
     }.collectAsStateWithLifecycle(initialValue = null)
-    //TODO: Add the Restricted TwoTargetSwitchPreference in SPA
-    TwoTargetSwitchPreference(
-        object : SwitchPreferenceModel {
+    RestrictedTwoTargetSwitchPreference(
+        model = object : SwitchPreferenceModel {
             override val title = subInfo.displayName.toString()
             override val summary = { phoneNumber.value ?: "" }
             override val checked = { checked.value }
@@ -74,7 +73,8 @@
                     newChecked,
                 )
             }
-        }
+        },
+        restrictions = Restrictions(keys = listOf(UserManager.DISALLOW_CONFIG_MOBILE_NETWORKS)),
     ) {
         MobileNetworkUtils.launchMobileNetworkSettings(context, subInfo)
     }
diff --git a/src/com/android/settings/wifi/WifiConfigController.java b/src/com/android/settings/wifi/WifiConfigController.java
index 5d45cb2..39c77a1 100644
--- a/src/com/android/settings/wifi/WifiConfigController.java
+++ b/src/com/android/settings/wifi/WifiConfigController.java
@@ -72,6 +72,7 @@
 import com.android.settings.R;
 import com.android.settings.network.SubscriptionUtil;
 import com.android.settings.utils.AndroidKeystoreAliasLoader;
+import com.android.settings.wifi.details2.WifiPrivacyPreferenceController;
 import com.android.settings.wifi.dpp.WifiDppUtils;
 import com.android.settingslib.Utils;
 import com.android.settingslib.utils.ThreadUtils;
@@ -154,6 +155,10 @@
     @VisibleForTesting static final int PRIVACY_SPINNER_INDEX_RANDOMIZED_MAC = 0;
     @VisibleForTesting static final int PRIVACY_SPINNER_INDEX_DEVICE_MAC = 1;
 
+    // Should be the same index value as wifi_dhcp_entries in arrays.xml
+    @VisibleForTesting static final int DHCP_SPINNER_INDEX_SEND_DHCP_HOST_NAME_ENABLE = 0;
+    @VisibleForTesting static final int DHCP_SPINNER_INDEX_SEND_DHCP_HOST_NAME_DISABLE = 1;
+
     /* Phase2 methods supported by PEAP are limited */
     private ArrayAdapter<CharSequence> mPhase2PeapAdapter;
     /* Phase2 methods supported by TTLS are limited */
@@ -194,6 +199,7 @@
     private Spinner mMeteredSettingsSpinner;
     private Spinner mHiddenSettingsSpinner;
     private Spinner mPrivacySettingsSpinner;
+    private Spinner mDhcpSettingsSpinner;
     private TextView mHiddenWarningView;
     private TextView mProxyHostView;
     private TextView mProxyPortView;
@@ -291,6 +297,7 @@
         mMeteredSettingsSpinner = mView.findViewById(R.id.metered_settings);
         mHiddenSettingsSpinner = mView.findViewById(R.id.hidden_settings);
         mPrivacySettingsSpinner = mView.findViewById(R.id.privacy_settings);
+        mDhcpSettingsSpinner = mView.findViewById(R.id.dhcp_settings);
         if (mWifiManager.isConnectedMacRandomizationSupported()) {
             View privacySettingsLayout = mView.findViewById(R.id.privacy_settings_fields);
             privacySettingsLayout.setVisibility(View.VISIBLE);
@@ -323,6 +330,12 @@
                         config.macRandomizationSetting == WifiConfiguration.RANDOMIZATION_PERSISTENT
                         ? PRIVACY_SPINNER_INDEX_RANDOMIZED_MAC : PRIVACY_SPINNER_INDEX_DEVICE_MAC);
 
+                mDhcpSettingsSpinner.setSelection(
+                        config.isSendDhcpHostnameEnabled()
+                                ? DHCP_SPINNER_INDEX_SEND_DHCP_HOST_NAME_ENABLE :
+                                DHCP_SPINNER_INDEX_SEND_DHCP_HOST_NAME_DISABLE
+                );
+
                 if (config.getIpConfiguration().getIpAssignment() == IpAssignment.STATIC) {
                     mIpSettingsSpinner.setSelection(STATIC_IP);
                     showAdvancedFields = true;
@@ -841,6 +854,12 @@
                     : WifiConfiguration.RANDOMIZATION_NONE;
         }
 
+        if (mDhcpSettingsSpinner != null) {
+            config.setSendDhcpHostnameEnabled(WifiPrivacyPreferenceController.Companion
+                    .translatePrefValueToSendDhcpHostnameEnabled(mDhcpSettingsSpinner
+                            .getSelectedItemPosition()));
+        }
+
         return config;
     }
 
diff --git a/src/com/android/settings/wifi/WifiConfigController2.java b/src/com/android/settings/wifi/WifiConfigController2.java
index 7c9b1d1..1e40568 100644
--- a/src/com/android/settings/wifi/WifiConfigController2.java
+++ b/src/com/android/settings/wifi/WifiConfigController2.java
@@ -74,6 +74,7 @@
 import com.android.settings.R;
 import com.android.settings.network.SubscriptionUtil;
 import com.android.settings.utils.AndroidKeystoreAliasLoader;
+import com.android.settings.wifi.details2.WifiPrivacyPreferenceController;
 import com.android.settings.wifi.details2.WifiPrivacyPreferenceController2;
 import com.android.settings.wifi.dpp.WifiDppUtils;
 import com.android.settingslib.Utils;
@@ -208,6 +209,8 @@
     private Spinner mHiddenSettingsSpinner;
     @Nullable
     private Spinner mPrivacySettingsSpinner;
+    @Nullable
+    private Spinner mDhcpSettingsSpinner;
     private TextView mHiddenWarningView;
     private TextView mProxyHostView;
     private TextView mProxyPortView;
@@ -308,6 +311,7 @@
         mHiddenSettingsSpinner = mView.findViewById(R.id.hidden_settings);
         if (!mHideMeteredAndPrivacy && mWifiManager.isConnectedMacRandomizationSupported()) {
             mPrivacySettingsSpinner = mView.findViewById(R.id.privacy_settings);
+            mDhcpSettingsSpinner  = mView.findViewById(R.id.dhcp_settings);
             mView.findViewById(R.id.privacy_settings_fields).setVisibility(View.VISIBLE);
         }
         mHiddenSettingsSpinner.setOnItemSelectedListener(this);
@@ -342,6 +346,13 @@
                     mPrivacySettingsSpinner.setSelection(prefMacValue);
                 }
 
+                if (mDhcpSettingsSpinner != null) {
+                    final int prefDhcpValue = WifiPrivacyPreferenceController.Companion
+                            .translateSendDhcpHostnameEnabledToPrefValue(
+                                    config.isSendDhcpHostnameEnabled());
+                    mDhcpSettingsSpinner.setSelection(prefDhcpValue);
+                }
+
                 if (config.getIpConfiguration().getIpAssignment() == IpAssignment.STATIC) {
                     mIpSettingsSpinner.setSelection(STATIC_IP);
                     showAdvancedFields = true;
@@ -854,6 +865,12 @@
                             .getSelectedItemPosition());
         }
 
+        if (mDhcpSettingsSpinner != null) {
+            config.setSendDhcpHostnameEnabled(WifiPrivacyPreferenceController.Companion
+                    .translatePrefValueToSendDhcpHostnameEnabled(mDhcpSettingsSpinner
+                            .getSelectedItemPosition()));
+        }
+
         return config;
     }
 
diff --git a/src/com/android/settings/wifi/details2/WifiPrivacyPreferenceController.kt b/src/com/android/settings/wifi/details2/WifiPrivacyPreferenceController.kt
index 42741e3..2ed2e5a 100644
--- a/src/com/android/settings/wifi/details2/WifiPrivacyPreferenceController.kt
+++ b/src/com/android/settings/wifi/details2/WifiPrivacyPreferenceController.kt
@@ -63,4 +63,32 @@
                 }
         })
     }
+
+    companion object {
+        private const val PREF_SEND_DHCP_HOST_NAME_ENABLE = 0
+        private const val PREF_SEND_DHCP_HOST_NAME_DISABLE = 1
+
+        /**
+         * Returns preference index value.
+         *
+         * @param isSendDhcpHostnameEnabled determines whether device name can be sent.
+         * @return index value of preference
+         */
+        fun translateSendDhcpHostnameEnabledToPrefValue(
+            isSendDhcpHostnameEnabled: Boolean
+        ): Int {
+            return if (isSendDhcpHostnameEnabled) PREF_SEND_DHCP_HOST_NAME_ENABLE
+            else PREF_SEND_DHCP_HOST_NAME_DISABLE
+        }
+
+        /**
+         * Returns whether device name can be sent.
+         *
+         * @param prefDhcpRandomized is preference index value
+         * @return is send dhcp host name enabled
+         */
+        fun translatePrefValueToSendDhcpHostnameEnabled(prefDhcpRandomized: Int): Boolean {
+            return prefDhcpRandomized == PREF_SEND_DHCP_HOST_NAME_ENABLE
+        }
+    }
 }
\ No newline at end of file
diff --git a/tests/robotests/src/com/android/settings/bluetooth/BluetoothDetailsHearingAidsPresetsControllerTest.java b/tests/robotests/src/com/android/settings/bluetooth/BluetoothDetailsHearingAidsPresetsControllerTest.java
new file mode 100644
index 0000000..c08bb98
--- /dev/null
+++ b/tests/robotests/src/com/android/settings/bluetooth/BluetoothDetailsHearingAidsPresetsControllerTest.java
@@ -0,0 +1,270 @@
+/*
+ * 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.bluetooth;
+
+import static android.bluetooth.BluetoothCsipSetCoordinator.GROUP_ID_INVALID;
+import static android.bluetooth.BluetoothHapClient.PRESET_INDEX_UNAVAILABLE;
+
+import static com.android.settings.bluetooth.BluetoothDetailsHearingDeviceController.KEY_HEARING_DEVICE_GROUP;
+import static com.android.settings.bluetooth.BluetoothDetailsHearingAidsPresetsController.KEY_HEARING_AIDS_PRESETS;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.never;
+import static org.mockito.Mockito.spy;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+import android.bluetooth.BluetoothDevice;
+import android.bluetooth.BluetoothHapClient;
+import android.bluetooth.BluetoothHapPresetInfo;
+
+import androidx.preference.ListPreference;
+import androidx.preference.PreferenceCategory;
+
+import com.android.settingslib.bluetooth.CachedBluetoothDevice;
+import com.android.settingslib.bluetooth.HapClientProfile;
+import com.android.settingslib.bluetooth.LocalBluetoothManager;
+import com.android.settingslib.bluetooth.LocalBluetoothProfileManager;
+
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.junit.MockitoJUnit;
+import org.mockito.junit.MockitoRule;
+import org.robolectric.RobolectricTestRunner;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Set;
+import java.util.concurrent.Executor;
+
+/** Tests for {@link BluetoothDetailsHearingAidsPresetsController}. */
+@RunWith(RobolectricTestRunner.class)
+public class BluetoothDetailsHearingAidsPresetsControllerTest extends
+        BluetoothDetailsControllerTestBase {
+
+    private static final int TEST_PRESET_INDEX = 1;
+    private static final String TEST_PRESET_NAME = "test_preset";
+    private static final int TEST_HAP_GROUP_ID = 1;
+
+    @Rule
+    public final MockitoRule mockito = MockitoJUnit.rule();
+
+    @Mock
+    private LocalBluetoothManager mLocalManager;
+    @Mock
+    private LocalBluetoothProfileManager mProfileManager;
+    @Mock
+    private HapClientProfile mHapClientProfile;
+    @Mock
+    private CachedBluetoothDevice mCachedChildDevice;
+    @Mock
+    private BluetoothDevice mChildDevice;
+
+    private BluetoothDetailsHearingAidsPresetsController mController;
+
+    @Override
+    public void setUp() {
+        super.setUp();
+
+        when(mLocalManager.getProfileManager()).thenReturn(mProfileManager);
+        when(mProfileManager.getHapClientProfile()).thenReturn(mHapClientProfile);
+        when(mCachedDevice.getProfiles()).thenReturn(List.of(mHapClientProfile));
+        when(mCachedDevice.isConnectedHapClientDevice()).thenReturn(true);
+        when(mCachedChildDevice.getDevice()).thenReturn(mChildDevice);
+        PreferenceCategory deviceControls = new PreferenceCategory(mContext);
+        deviceControls.setKey(KEY_HEARING_DEVICE_GROUP);
+        mScreen.addPreference(deviceControls);
+        mController = new BluetoothDetailsHearingAidsPresetsController(mContext, mFragment,
+                mLocalManager, mCachedDevice, mLifecycle);
+        mController.init(mScreen);
+    }
+
+    @Test
+    public void isAvailable_supportHap_returnTrue() {
+        when(mCachedDevice.getProfiles()).thenReturn(List.of(mHapClientProfile));
+
+        assertThat(mController.isAvailable()).isTrue();
+    }
+
+    @Test
+    public void isAvailable_notSupportHap_returnFalse() {
+        when(mCachedDevice.getProfiles()).thenReturn(new ArrayList<>());
+
+        assertThat(mController.isAvailable()).isFalse();
+    }
+
+    @Test
+    public void onResume_registerCallback() {
+        mController.onResume();
+
+        verify(mHapClientProfile).registerCallback(any(Executor.class),
+                any(BluetoothHapClient.Callback.class));
+    }
+
+    @Test
+    public void onPause_unregisterCallback() {
+        mController.onPause();
+
+        verify(mHapClientProfile).unregisterCallback(any(BluetoothHapClient.Callback.class));
+    }
+
+    @Test
+    public void onPreferenceChange_keyMatched_verifyStatusUpdated() {
+        final ListPreference presetPreference = getTestPresetPreference(KEY_HEARING_AIDS_PRESETS);
+
+        boolean handled = mController.onPreferenceChange(presetPreference,
+                String.valueOf(TEST_PRESET_INDEX));
+
+        assertThat(handled).isTrue();
+        verify(presetPreference).setSummary(TEST_PRESET_NAME);
+    }
+
+    @Test
+    public void onPreferenceChange_keyNotMatched_doNothing() {
+        final ListPreference presetPreference = getTestPresetPreference("wrong_key");
+
+        boolean handled = mController.onPreferenceChange(
+                presetPreference, String.valueOf(TEST_PRESET_INDEX));
+
+        assertThat(handled).isFalse();
+        verify(presetPreference, never()).setSummary(any());
+    }
+
+    @Test
+    public void onPreferenceChange_supportGroupOperation_validGroupId_verifySelectPresetForGroup() {
+        final ListPreference presetPreference = getTestPresetPreference(KEY_HEARING_AIDS_PRESETS);
+        when(mHapClientProfile.supportsSynchronizedPresets(mDevice)).thenReturn(true);
+        when(mHapClientProfile.getHapGroup(mDevice)).thenReturn(TEST_HAP_GROUP_ID);
+
+        mController.onPreferenceChange(presetPreference, String.valueOf(TEST_PRESET_INDEX));
+
+        verify(mHapClientProfile).selectPresetForGroup(TEST_HAP_GROUP_ID, TEST_PRESET_INDEX);
+    }
+
+    @Test
+    public void onPreferenceChange_notSupportGroupOperation_verifySelectPreset() {
+        final ListPreference presetPreference = getTestPresetPreference(KEY_HEARING_AIDS_PRESETS);
+        when(mHapClientProfile.supportsSynchronizedPresets(mDevice)).thenReturn(false);
+        when(mHapClientProfile.getHapGroup(mDevice)).thenReturn(TEST_HAP_GROUP_ID);
+
+        mController.onPreferenceChange(presetPreference, String.valueOf(TEST_PRESET_INDEX));
+
+        verify(mHapClientProfile).selectPreset(mDevice, TEST_PRESET_INDEX);
+    }
+
+    @Test
+    public void onPreferenceChange_invalidGroupId_verifySelectPreset() {
+        final ListPreference presetPreference = getTestPresetPreference(KEY_HEARING_AIDS_PRESETS);
+        when(mHapClientProfile.supportsSynchronizedPresets(mDevice)).thenReturn(true);
+        when(mHapClientProfile.getHapGroup(mDevice)).thenReturn(GROUP_ID_INVALID);
+
+        mController.onPreferenceChange(presetPreference, String.valueOf(TEST_PRESET_INDEX));
+
+        verify(mHapClientProfile).selectPreset(mDevice, TEST_PRESET_INDEX);
+    }
+
+    @Test
+    public void onPreferenceChange_notSupportGroupOperation_hasSubDevice_verifyStatusUpdated() {
+        final ListPreference presetPreference = getTestPresetPreference(KEY_HEARING_AIDS_PRESETS);
+        when(mHapClientProfile.supportsSynchronizedPresets(mDevice)).thenReturn(false);
+        when(mCachedDevice.getSubDevice()).thenReturn(mCachedChildDevice);
+
+        mController.onPreferenceChange(presetPreference, String.valueOf(TEST_PRESET_INDEX));
+
+        verify(mHapClientProfile).selectPreset(mDevice, TEST_PRESET_INDEX);
+        verify(mHapClientProfile).selectPreset(mChildDevice, TEST_PRESET_INDEX);
+    }
+
+    @Test
+    public void onPreferenceChange_notSupportGroupOperation_hasMemberDevice_verifyStatusUpdated() {
+        final ListPreference presetPreference = getTestPresetPreference(KEY_HEARING_AIDS_PRESETS);
+        when(mHapClientProfile.supportsSynchronizedPresets(mDevice)).thenReturn(false);
+        when(mCachedDevice.getMemberDevice()).thenReturn(Set.of(mCachedChildDevice));
+
+        mController.onPreferenceChange(presetPreference, String.valueOf(TEST_PRESET_INDEX));
+
+        verify(mHapClientProfile).selectPreset(mDevice, TEST_PRESET_INDEX);
+        verify(mHapClientProfile).selectPreset(mChildDevice, TEST_PRESET_INDEX);
+    }
+
+    @Test
+    public void refresh_emptyPresetInfo_preferenceDisabled() {
+        when(mHapClientProfile.getAllPresetInfo(mDevice)).thenReturn(new ArrayList<>());
+
+        mController.refresh();
+
+        assertThat(mController.getPreference()).isNotNull();
+        assertThat(mController.getPreference().isEnabled()).isFalse();
+    }
+
+    @Test
+    public void refresh_validPresetInfo_preferenceEnabled() {
+        BluetoothHapPresetInfo info = getTestPresetInfo();
+        when(mHapClientProfile.getAllPresetInfo(mDevice)).thenReturn(List.of(info));
+
+        mController.refresh();
+
+        assertThat(mController.getPreference()).isNotNull();
+        assertThat(mController.getPreference().isEnabled()).isTrue();
+    }
+
+    @Test
+    public void refresh_invalidActivePresetIndex_summaryIsNull() {
+        BluetoothHapPresetInfo info = getTestPresetInfo();
+        when(mHapClientProfile.getAllPresetInfo(mDevice)).thenReturn(List.of(info));
+        when(mHapClientProfile.getActivePresetIndex(mDevice)).thenReturn(PRESET_INDEX_UNAVAILABLE);
+
+        mController.refresh();
+
+        assertThat(mController.getPreference()).isNotNull();
+        assertThat(mController.getPreference().getSummary()).isNull();
+    }
+
+    @Test
+    public void refresh_validActivePresetIndex_summaryIsNotNull() {
+        BluetoothHapPresetInfo info = getTestPresetInfo();
+        when(mHapClientProfile.getAllPresetInfo(mDevice)).thenReturn(List.of(info));
+        when(mHapClientProfile.getActivePresetIndex(mDevice)).thenReturn(TEST_PRESET_INDEX);
+
+        mController.refresh();
+
+        assertThat(mController.getPreference()).isNotNull();
+        assertThat(mController.getPreference().getSummary()).isNotNull();
+    }
+
+    private BluetoothHapPresetInfo getTestPresetInfo() {
+        BluetoothHapPresetInfo info = mock(BluetoothHapPresetInfo.class);
+        when(info.getName()).thenReturn(TEST_PRESET_NAME);
+        when(info.getIndex()).thenReturn(TEST_PRESET_INDEX);
+        return info;
+    }
+
+    private ListPreference getTestPresetPreference(String key) {
+        final ListPreference presetPreference = spy(new ListPreference(mContext));
+        when(presetPreference.findIndexOfValue(String.valueOf(TEST_PRESET_INDEX))).thenReturn(0);
+        when(presetPreference.getEntries()).thenReturn(new CharSequence[]{TEST_PRESET_NAME});
+        when(presetPreference.getEntryValues()).thenReturn(
+                new CharSequence[]{String.valueOf(TEST_PRESET_INDEX)});
+        presetPreference.setKey(key);
+        return presetPreference;
+    }
+}
diff --git a/tests/robotests/src/com/android/settings/bluetooth/BluetoothDetailsHearingDeviceControllerTest.java b/tests/robotests/src/com/android/settings/bluetooth/BluetoothDetailsHearingDeviceControllerTest.java
new file mode 100644
index 0000000..2a50f89
--- /dev/null
+++ b/tests/robotests/src/com/android/settings/bluetooth/BluetoothDetailsHearingDeviceControllerTest.java
@@ -0,0 +1,129 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.settings.bluetooth;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import static org.mockito.Mockito.when;
+
+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 com.android.settings.accessibility.Flags;
+import com.android.settingslib.bluetooth.LocalBluetoothManager;
+import com.android.settingslib.bluetooth.LocalBluetoothProfileManager;
+
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.junit.MockitoJUnit;
+import org.mockito.junit.MockitoRule;
+import org.robolectric.RobolectricTestRunner;
+
+/** Tests for {@link BluetoothDetailsHearingDeviceController}. */
+@RunWith(RobolectricTestRunner.class)
+public class BluetoothDetailsHearingDeviceControllerTest extends
+        BluetoothDetailsControllerTestBase {
+
+    @Rule
+    public final CheckFlagsRule mCheckFlagsRule = DeviceFlagsValueProvider.createCheckFlagsRule();
+
+    @Rule
+    public final MockitoRule mockito = MockitoJUnit.rule();
+
+    @Mock
+    private LocalBluetoothManager mLocalManager;
+    @Mock
+    private LocalBluetoothProfileManager mProfileManager;
+    @Mock
+    private BluetoothDetailsHearingDeviceController mHearingDeviceController;
+    @Mock
+    private BluetoothDetailsHearingAidsPresetsController mPresetsController;
+    @Mock
+    private BluetoothDetailsHearingDeviceSettingsController mHearingDeviceSettingsController;
+
+    @Override
+    public void setUp() {
+        super.setUp();
+
+        when(mLocalManager.getProfileManager()).thenReturn(mProfileManager);
+        mHearingDeviceController = new BluetoothDetailsHearingDeviceController(mContext,
+                mFragment, mLocalManager, mCachedDevice, mLifecycle);
+        mHearingDeviceController.setSubControllers(mHearingDeviceSettingsController,
+                mPresetsController);
+    }
+
+    @Test
+    public void isAvailable_hearingDeviceSettingsAvailable_returnTrue() {
+        when(mHearingDeviceSettingsController.isAvailable()).thenReturn(true);
+
+        assertThat(mHearingDeviceController.isAvailable()).isTrue();
+    }
+
+    @Test
+    public void isAvailable_presetsControlsAvailable_returnTrue() {
+        when(mPresetsController.isAvailable()).thenReturn(true);
+
+        assertThat(mHearingDeviceController.isAvailable()).isTrue();
+    }
+
+    @Test
+    public void isAvailable_noControllersAvailable_returnFalse() {
+        when(mHearingDeviceSettingsController.isAvailable()).thenReturn(false);
+        when(mPresetsController.isAvailable()).thenReturn(false);
+
+        assertThat(mHearingDeviceController.isAvailable()).isFalse();
+    }
+
+
+    @Test
+    public void initSubControllers_launchFromHearingDevicePage_hearingDeviceSettingsNotExist() {
+        mHearingDeviceController.initSubControllers(true);
+
+        assertThat(mHearingDeviceController.getSubControllers().stream().anyMatch(
+                c -> c instanceof BluetoothDetailsHearingDeviceSettingsController)).isFalse();
+    }
+
+    @Test
+    public void initSubControllers_notLaunchFromHearingDevicePage_hearingDeviceSettingsExist() {
+        mHearingDeviceController.initSubControllers(false);
+
+        assertThat(mHearingDeviceController.getSubControllers().stream().anyMatch(
+                c -> c instanceof BluetoothDetailsHearingDeviceSettingsController)).isTrue();
+    }
+
+    @Test
+    @RequiresFlagsEnabled(Flags.FLAG_ENABLE_HEARING_AID_PRESET_CONTROL)
+    public void initSubControllers_flagEnabled_presetControllerExist() {
+        mHearingDeviceController.initSubControllers(false);
+
+        assertThat(mHearingDeviceController.getSubControllers().stream().anyMatch(
+                c -> c instanceof BluetoothDetailsHearingAidsPresetsController)).isTrue();
+    }
+
+    @Test
+    @RequiresFlagsDisabled(Flags.FLAG_ENABLE_HEARING_AID_PRESET_CONTROL)
+    public void initSubControllers_flagDisabled_presetControllerNotExist() {
+        mHearingDeviceController.initSubControllers(false);
+
+        assertThat(mHearingDeviceController.getSubControllers().stream().anyMatch(
+                c -> c instanceof BluetoothDetailsHearingAidsPresetsController)).isFalse();
+    }
+}
diff --git a/tests/robotests/src/com/android/settings/bluetooth/BluetoothDetailsHearingDeviceControlsControllerTest.java b/tests/robotests/src/com/android/settings/bluetooth/BluetoothDetailsHearingDeviceSettingsControllerTest.java
similarity index 81%
rename from tests/robotests/src/com/android/settings/bluetooth/BluetoothDetailsHearingDeviceControlsControllerTest.java
rename to tests/robotests/src/com/android/settings/bluetooth/BluetoothDetailsHearingDeviceSettingsControllerTest.java
index 364d299..b420717 100644
--- a/tests/robotests/src/com/android/settings/bluetooth/BluetoothDetailsHearingDeviceControlsControllerTest.java
+++ b/tests/robotests/src/com/android/settings/bluetooth/BluetoothDetailsHearingDeviceSettingsControllerTest.java
@@ -39,23 +39,24 @@
 import org.mockito.junit.MockitoRule;
 import org.robolectric.RobolectricTestRunner;
 
-/** Tests for {@link BluetoothDetailsHearingDeviceControlsController}. */
+/** Tests for {@link BluetoothDetailsHearingDeviceSettingsController}. */
 @RunWith(RobolectricTestRunner.class)
-public class BluetoothDetailsHearingDeviceControlsControllerTest extends
+public class BluetoothDetailsHearingDeviceSettingsControllerTest extends
         BluetoothDetailsControllerTestBase {
+
     @Rule
     public final MockitoRule mockito = MockitoJUnit.rule();
 
     @Captor
     private ArgumentCaptor<Intent> mIntentArgumentCaptor;
-    private BluetoothDetailsHearingDeviceControlsController mController;
+    private BluetoothDetailsHearingDeviceSettingsController mController;
 
     @Override
     public void setUp() {
         super.setUp();
 
         FakeFeatureFactory.setupForTest();
-        mController = new BluetoothDetailsHearingDeviceControlsController(mActivity, mFragment,
+        mController = new BluetoothDetailsHearingDeviceSettingsController(mActivity, mFragment,
                 mCachedDevice, mLifecycle);
         when(mCachedDevice.isHearingAidDevice()).thenReturn(true);
     }
@@ -75,12 +76,12 @@
     }
 
     @Test
-    public void onPreferenceClick_hearingDeviceControlsKey_LaunchExpectedFragment() {
-        final Preference hearingControlsKeyPreference = new Preference(mContext);
-        hearingControlsKeyPreference.setKey(
-                BluetoothDetailsHearingDeviceControlsController.KEY_HEARING_DEVICE_CONTROLS);
+    public void onPreferenceClick_hearingDeviceSettingsKey_launchExpectedFragment() {
+        final Preference hearingDeviceSettingsPreference = new Preference(mContext);
+        hearingDeviceSettingsPreference.setKey(
+                BluetoothDetailsHearingDeviceSettingsController.KEY_HEARING_DEVICE_SETTINGS);
 
-        mController.onPreferenceClick(hearingControlsKeyPreference);
+        mController.onPreferenceClick(hearingDeviceSettingsPreference);
 
         assertStartActivityWithExpectedFragment(mActivity,
                 AccessibilityHearingAidsFragment.class.getName());
diff --git a/tests/robotests/src/com/android/settings/bluetooth/BluetoothDeviceDetailsFragmentTest.java b/tests/robotests/src/com/android/settings/bluetooth/BluetoothDeviceDetailsFragmentTest.java
index fc72c41..50aa771 100644
--- a/tests/robotests/src/com/android/settings/bluetooth/BluetoothDeviceDetailsFragmentTest.java
+++ b/tests/robotests/src/com/android/settings/bluetooth/BluetoothDeviceDetailsFragmentTest.java
@@ -18,7 +18,7 @@
 
 import static android.bluetooth.BluetoothDevice.BOND_NONE;
 
-import static com.android.settings.bluetooth.BluetoothDetailsHearingDeviceControlsController.KEY_DEVICE_CONTROLS_GENERAL_GROUP;
+import static com.android.settings.bluetooth.BluetoothDetailsHearingDeviceSettingsController.KEY_HEARING_DEVICE_SETTINGS;
 
 import static com.google.common.truth.Truth.assertThat;
 
@@ -237,7 +237,7 @@
 
         assertThat(controllerList.stream()
                 .anyMatch(controller -> controller.getPreferenceKey().equals(
-                        KEY_DEVICE_CONTROLS_GENERAL_GROUP))).isFalse();
+                        KEY_HEARING_DEVICE_SETTINGS))).isFalse();
     }
 
     @Test
@@ -253,7 +253,7 @@
 
         assertThat(controllerList.stream()
                 .anyMatch(controller -> controller.getPreferenceKey().equals(
-                        KEY_DEVICE_CONTROLS_GENERAL_GROUP))).isTrue();
+                        KEY_HEARING_DEVICE_SETTINGS))).isTrue();
     }
 
     private InputDevice createInputDeviceWithMatchingBluetoothAddress() {
diff --git a/tests/robotests/src/com/android/settings/fuelgauge/AdvancedPowerUsageDetailTest.java b/tests/robotests/src/com/android/settings/fuelgauge/AdvancedPowerUsageDetailTest.java
index 0648de4..80739e9 100644
--- a/tests/robotests/src/com/android/settings/fuelgauge/AdvancedPowerUsageDetailTest.java
+++ b/tests/robotests/src/com/android/settings/fuelgauge/AdvancedPowerUsageDetailTest.java
@@ -60,12 +60,8 @@
 import com.android.settingslib.applications.ApplicationsState;
 import com.android.settingslib.applications.instantapps.InstantAppDataProvider;
 import com.android.settingslib.core.instrumentation.MetricsFeatureProvider;
-import com.android.settingslib.datastore.ChangeReason;
-import com.android.settingslib.datastore.Observer;
 import com.android.settingslib.widget.LayoutPreference;
 
-import com.google.common.util.concurrent.MoreExecutors;
-
 import org.junit.After;
 import org.junit.Before;
 import org.junit.Rule;
@@ -119,10 +115,8 @@
     @Mock private AppOpsManager mAppOpsManager;
     @Mock private LoaderManager mLoaderManager;
     @Mock private BatteryOptimizeUtils mBatteryOptimizeUtils;
-    @Mock private Observer mObserver;
 
     private Context mContext;
-    private BatterySettingsStorage mBatterySettingsStorage;
     private PrimarySwitchPreference mAllowBackgroundUsagePreference;
     private AdvancedPowerUsageDetail mFragment;
     private SettingsActivity mTestActivity;
@@ -134,7 +128,6 @@
     @Before
     public void setUp() {
         mContext = spy(ApplicationProvider.getApplicationContext());
-        mBatterySettingsStorage = BatterySettingsStorage.get(mContext);
         when(mContext.getPackageName()).thenReturn("foo");
         mFeatureFactory = FakeFeatureFactory.setupForTest();
         mMetricsFeatureProvider = mFeatureFactory.metricsFeatureProvider;
@@ -448,28 +441,4 @@
         TimeUnit.SECONDS.sleep(1);
         verifyNoInteractions(mMetricsFeatureProvider);
     }
-
-    @Test
-    public void notifyBackupManager_optimizationModeIsNotChanged_notInvokeDataChanged() {
-        mBatterySettingsStorage.addObserver(mObserver, MoreExecutors.directExecutor());
-        final int mode = BatteryOptimizeUtils.MODE_RESTRICTED;
-        mFragment.mOptimizationMode = mode;
-        when(mBatteryOptimizeUtils.getAppOptimizationMode()).thenReturn(mode);
-
-        mFragment.notifyBackupManager();
-
-        verifyNoInteractions(mObserver);
-    }
-
-    @Test
-    public void notifyBackupManager_optimizationModeIsChanged_invokeDataChanged() {
-        mBatterySettingsStorage.addObserver(mObserver, MoreExecutors.directExecutor());
-        mFragment.mOptimizationMode = BatteryOptimizeUtils.MODE_RESTRICTED;
-        when(mBatteryOptimizeUtils.getAppOptimizationMode())
-                .thenReturn(BatteryOptimizeUtils.MODE_UNRESTRICTED);
-
-        mFragment.notifyBackupManager();
-
-        verify(mObserver).onChanged(ChangeReason.UPDATE);
-    }
 }
diff --git a/tests/robotests/src/com/android/settings/fuelgauge/BatteryOptimizeUtilsTest.java b/tests/robotests/src/com/android/settings/fuelgauge/BatteryOptimizeUtilsTest.java
index 3551eeb..6085b9a 100644
--- a/tests/robotests/src/com/android/settings/fuelgauge/BatteryOptimizeUtilsTest.java
+++ b/tests/robotests/src/com/android/settings/fuelgauge/BatteryOptimizeUtilsTest.java
@@ -49,8 +49,12 @@
 import android.util.ArraySet;
 
 import com.android.settings.fuelgauge.BatteryOptimizeHistoricalLogEntry.Action;
+import com.android.settingslib.datastore.ChangeReason;
+import com.android.settingslib.datastore.Observer;
 import com.android.settingslib.fuelgauge.PowerAllowlistBackend;
 
+import com.google.common.util.concurrent.MoreExecutors;
+
 import org.junit.Before;
 import org.junit.Test;
 import org.junit.runner.RunWith;
@@ -74,14 +78,18 @@
     @Mock private PowerAllowlistBackend mMockBackend;
     @Mock private IPackageManager mMockIPackageManager;
     @Mock private UserManager mMockUserManager;
+    @Mock private Observer mObserver;
 
     private Context mContext;
     private BatteryOptimizeUtils mBatteryOptimizeUtils;
+    private BatterySettingsStorage mBatterySettingsStorage;
 
     @Before
     public void setUp() {
         MockitoAnnotations.initMocks(this);
         mContext = spy(RuntimeEnvironment.application);
+        mBatterySettingsStorage = BatterySettingsStorage.get(mContext);
+        mBatterySettingsStorage.addObserver(mObserver, MoreExecutors.directExecutor());
         mBatteryOptimizeUtils = spy(new BatteryOptimizeUtils(mContext, UID, PACKAGE_NAME));
         mBatteryOptimizeUtils.mAppOpsManager = mMockAppOpsManager;
         mBatteryOptimizeUtils.mBatteryUtils = mMockBatteryUtils;
@@ -156,6 +164,7 @@
         TimeUnit.SECONDS.sleep(1);
 
         verifySetAppOptimizationMode(AppOpsManager.MODE_IGNORED, /* allowListed */ false);
+        verify(mObserver).onChanged(ChangeReason.UPDATE);
     }
 
     @Test
@@ -169,6 +178,7 @@
         TimeUnit.SECONDS.sleep(1);
 
         verifySetAppOptimizationMode(AppOpsManager.MODE_ALLOWED, /* allowListed */ true);
+        verify(mObserver).onChanged(ChangeReason.UPDATE);
     }
 
     @Test
@@ -182,6 +192,7 @@
         TimeUnit.SECONDS.sleep(1);
 
         verifySetAppOptimizationMode(AppOpsManager.MODE_ALLOWED, /* allowListed */ false);
+        verify(mObserver).onChanged(ChangeReason.UPDATE);
     }
 
     @Test
@@ -197,6 +208,7 @@
         verify(mMockBatteryUtils, never()).setForceAppStandby(anyInt(), anyString(), anyInt());
         verify(mMockBackend, never()).addApp(anyString());
         verify(mMockBackend, never()).removeApp(anyString());
+        verifyNoInteractions(mObserver);
     }
 
     @Test
@@ -288,6 +300,7 @@
         inOrder.verify(mMockBackend).isAllowlisted(PACKAGE_NAME, UID);
         inOrder.verify(mMockBackend).isSysAllowlisted(PACKAGE_NAME);
         verifyNoMoreInteractions(mMockBackend);
+        verify(mObserver).onChanged(ChangeReason.DELETE);
     }
 
     @Test
@@ -298,6 +311,7 @@
                 /* isSystemOrDefaultApp */ false);
 
         verifySetAppOptimizationMode(AppOpsManager.MODE_ALLOWED, /* allowListed */ false);
+        verify(mObserver).onChanged(ChangeReason.DELETE);
     }
 
     @Test
@@ -308,6 +322,7 @@
                 /* isSystemOrDefaultApp */ false);
 
         verifySetAppOptimizationMode(AppOpsManager.MODE_ALLOWED, /* allowListed */ false);
+        verify(mObserver).onChanged(ChangeReason.DELETE);
     }
 
     private void runTestForResetWithMode(
diff --git a/tests/robotests/src/com/android/settings/network/SubscriptionUtilRoboTest.java b/tests/robotests/src/com/android/settings/network/SubscriptionUtilRoboTest.java
index 2595510..ae504be 100644
--- a/tests/robotests/src/com/android/settings/network/SubscriptionUtilRoboTest.java
+++ b/tests/robotests/src/com/android/settings/network/SubscriptionUtilRoboTest.java
@@ -16,11 +16,11 @@
 
 package com.android.settings.network;
 
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+import static org.mockito.ArgumentMatchers.any;
 import static org.mockito.Mockito.spy;
 import static org.mockito.Mockito.when;
-import static org.junit.Assert.assertTrue;
-import static org.junit.Assert.assertFalse;
-import static org.mockito.ArgumentMatchers.any;
 import static org.robolectric.Shadows.shadowOf;
 
 import android.content.Context;
@@ -59,19 +59,19 @@
     }
 
     @Test
-    public void isConnectedToWifiOrDifferentSubId_hasDataOnSubId2_returnTrue() {
+    public void isConnectedToMobileDataWithDifferentSubId_hasDataOnSubId2_returnTrue() {
         addNetworkTransportType(NetworkCapabilities.TRANSPORT_CELLULAR);
         mShadowSubscriptionManager.setActiveDataSubscriptionId(SUBID_2);
 
-        assertTrue(SubscriptionUtil.isConnectedToWifiOrDifferentSubId(mContext, SUBID_1));
+        assertTrue(SubscriptionUtil.isConnectedToMobileDataWithDifferentSubId(mContext, SUBID_1));
     }
 
     @Test
-    public void isConnectedToWifiOrDifferentSubId_hasDataOnSubId1_returnFalse() {
+    public void isConnectedToMobileDataWithDifferentSubId_hasDataOnSubId1_returnFalse() {
         addNetworkTransportType(NetworkCapabilities.TRANSPORT_CELLULAR);
         mShadowSubscriptionManager.setActiveDataSubscriptionId(SUBID_1);
 
-        assertFalse(SubscriptionUtil.isConnectedToWifiOrDifferentSubId(mContext, SUBID_1));
+        assertFalse(SubscriptionUtil.isConnectedToMobileDataWithDifferentSubId(mContext, SUBID_1));
     }
 
     private void addNetworkTransportType(int networkType) {
diff --git a/tests/robotests/src/com/android/settings/privatespace/HidePrivateSpaceControllerTest.java b/tests/robotests/src/com/android/settings/privatespace/HidePrivateSpaceControllerTest.java
new file mode 100644
index 0000000..7ff18a5
--- /dev/null
+++ b/tests/robotests/src/com/android/settings/privatespace/HidePrivateSpaceControllerTest.java
@@ -0,0 +1,146 @@
+/*
+ * 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.privatespace;
+
+import static com.android.settings.core.BasePreferenceController.AVAILABLE;
+import static com.android.settings.core.BasePreferenceController.UNSUPPORTED_ON_DEVICE;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import android.content.Context;
+import android.platform.test.flag.junit.SetFlagsRule;
+
+import androidx.fragment.app.FragmentActivity;
+import androidx.test.core.app.ApplicationProvider;
+
+import com.android.settings.R;
+
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.junit.MockitoJUnit;
+import org.mockito.junit.MockitoRule;
+import org.robolectric.Robolectric;
+import org.robolectric.RobolectricTestRunner;
+import org.robolectric.RuntimeEnvironment;
+import org.robolectric.annotation.Config;
+import org.robolectric.shadow.api.Shadow;
+import org.robolectric.shadows.ShadowAlertDialog;
+import org.robolectric.shadows.ShadowApplication;
+
+@RunWith(RobolectricTestRunner.class)
+@Config(shadows = {ShadowAlertDialog.class})
+public class HidePrivateSpaceControllerTest {
+    @Rule public final MockitoRule mMockitoRule = MockitoJUnit.rule();
+    @Rule public final SetFlagsRule mSetFlagsRule = new SetFlagsRule();
+    private static final String KEY = "private_space_hidden";
+    private static final String DETAIL_PAGE_KEY = "private_space_hidden_details";
+    private HidePrivateSpaceController mHidePrivateSpaceController;
+    private HidePrivateSpaceSummaryController mHidePrivateSpaceSummaryController;
+    private FragmentActivity mActivity;
+
+    @Before
+    public void setUp() {
+        Context context = RuntimeEnvironment.application;
+        mHidePrivateSpaceController = new HidePrivateSpaceController(context, DETAIL_PAGE_KEY);
+        mHidePrivateSpaceSummaryController = new HidePrivateSpaceSummaryController(context, KEY);
+        mActivity = Robolectric.setupActivity(FragmentActivity.class);
+    }
+
+    /** Tests that when flags enabled the controller is available. */
+    @Test
+    public void getAvailabilityStatus_flagEnabled_returnsAvailable() {
+        mSetFlagsRule.enableFlags(android.multiuser.Flags.FLAG_ENABLE_PRIVATE_SPACE_FEATURES);
+
+        assertThat(mHidePrivateSpaceController.getAvailabilityStatus()).isEqualTo(AVAILABLE);
+    }
+
+    /** Tests that when flags disabled the controller is unsupported. */
+    @Test
+    public void getAvailabilityStatus_flagDisabled_returnsUnsupported() {
+        mSetFlagsRule.disableFlags(android.multiuser.Flags.FLAG_ENABLE_PRIVATE_SPACE_FEATURES);
+
+        assertThat(mHidePrivateSpaceController.getAvailabilityStatus())
+                .isEqualTo(UNSUPPORTED_ON_DEVICE);
+    }
+
+    /** Tests that when hide toggle is enabled dialog is displayed. */
+    @Test
+    public void setChecked_enabled_showsDialog() {
+        mSetFlagsRule.enableFlags(android.multiuser.Flags.FLAG_ENABLE_PRIVATE_SPACE_FEATURES);
+        mHidePrivateSpaceController.setChecked(true);
+
+        ShadowAlertDialog shadowAlertDialog = getShadowAlertDialog();
+        assertThat(shadowAlertDialog).isNotNull();
+        assertThat(shadowAlertDialog.getTitle().toString())
+                .isEqualTo(mActivity.getString(R.string.private_space_hide_dialog_title));
+        assertThat(shadowAlertDialog.getMessage().toString())
+                .isEqualTo(mActivity.getString(R.string.private_space_hide_dialog_message));
+    }
+
+    /** Tests that when hide toggle is disabled dialog is not displayed. */
+    @Test
+    public void setChecked_disabled_NoDialogShown() {
+        mSetFlagsRule.enableFlags(android.multiuser.Flags.FLAG_ENABLE_PRIVATE_SPACE_FEATURES);
+        mHidePrivateSpaceController.setChecked(false);
+
+        ShadowAlertDialog shadowAlertDialog = getShadowAlertDialog();
+        assertThat(shadowAlertDialog).isNull();
+    }
+
+    /** Tests that when hide toggle is enabled then isChecked returns true. */
+    @Test
+    public void setChecked_enabled_isCheckedIsTrue() {
+        mSetFlagsRule.enableFlags(android.multiuser.Flags.FLAG_ENABLE_PRIVATE_SPACE_FEATURES);
+        mHidePrivateSpaceController.setChecked(true);
+        assertThat(mHidePrivateSpaceController.isChecked()).isTrue();
+    }
+
+    /** Tests that when hide toggle is disabled then isChecked returns false. */
+    @Test
+    public void setChecked_disabled_isCheckedIsFalse() {
+        mSetFlagsRule.enableFlags(android.multiuser.Flags.FLAG_ENABLE_PRIVATE_SPACE_FEATURES);
+        mHidePrivateSpaceController.setChecked(false);
+        assertThat(mHidePrivateSpaceController.isChecked()).isFalse();
+    }
+
+    /** Tests that hide preference summary displays On when toggle is enabled. */
+    @Test
+    public void setChecked_enable_summaryShouldDisplayOn() {
+        mSetFlagsRule.enableFlags(android.multiuser.Flags.FLAG_ENABLE_PRIVATE_SPACE_FEATURES);
+        mHidePrivateSpaceController.setChecked(true);
+
+        assertThat(mHidePrivateSpaceSummaryController.getSummary().toString()).isEqualTo("On");
+    }
+
+    /** Tests that hide preference summary displays Off when toggle is disabled. */
+    @Test
+    public void setChecked_disable_summaryShouldDisplayOff() {
+        mSetFlagsRule.enableFlags(android.multiuser.Flags.FLAG_ENABLE_PRIVATE_SPACE_FEATURES);
+        mHidePrivateSpaceController.setChecked(false);
+
+        assertThat(mHidePrivateSpaceSummaryController.getSummary().toString()).isEqualTo("Off");
+    }
+
+    private ShadowAlertDialog getShadowAlertDialog() {
+        ShadowApplication shadowApplication =
+                Shadow.extract(ApplicationProvider.getApplicationContext());
+        ShadowAlertDialog shadowAlertDialog = shadowApplication.getLatestAlertDialog();
+        return shadowAlertDialog;
+    }
+}
diff --git a/tests/robotests/src/com/android/settings/security/ContentProtectionPreferenceUtilsTest.java b/tests/robotests/src/com/android/settings/security/ContentProtectionPreferenceUtilsTest.java
index 9b49434..d6f9abd 100644
--- a/tests/robotests/src/com/android/settings/security/ContentProtectionPreferenceUtilsTest.java
+++ b/tests/robotests/src/com/android/settings/security/ContentProtectionPreferenceUtilsTest.java
@@ -16,47 +16,73 @@
 
 package com.android.settings.security;
 
+import static android.view.contentprotection.flags.Flags.FLAG_MANAGE_DEVICE_POLICY_ENABLED;
+
 import static com.android.internal.R.string.config_defaultContentProtectionService;
 
 import static com.google.common.truth.Truth.assertThat;
 
+import static org.junit.Assert.assertThrows;
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.anyInt;
+import static org.mockito.ArgumentMatchers.anyString;
+import static org.mockito.Mockito.never;
+import static org.mockito.Mockito.verify;
 import static org.mockito.Mockito.when;
 
+import android.app.admin.DevicePolicyManager;
 import android.content.ComponentName;
 import android.content.Context;
+import android.content.pm.PackageManager;
+import android.content.pm.UserInfo;
+import android.os.UserHandle;
+import android.os.UserManager;
+import android.platform.test.flag.junit.SetFlagsRule;
 import android.provider.DeviceConfig;
 import android.view.contentcapture.ContentCaptureManager;
 
 import com.android.settings.testutils.shadow.ShadowDeviceConfig;
 
 import org.junit.After;
-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;
+import org.mockito.junit.MockitoJUnit;
+import org.mockito.junit.MockitoRule;
 import org.robolectric.RobolectricTestRunner;
 import org.robolectric.annotation.Config;
 
+import java.util.List;
+
 @RunWith(RobolectricTestRunner.class)
-@Config(
-        shadows = {
-            ShadowDeviceConfig.class,
-        })
+@Config(shadows = {ShadowDeviceConfig.class})
 public class ContentProtectionPreferenceUtilsTest {
+
     private static final String PACKAGE_NAME = "com.test.package";
 
     private static final ComponentName COMPONENT_NAME =
             new ComponentName(PACKAGE_NAME, "TestClass");
 
-    private String mConfigDefaultContentProtectionService = COMPONENT_NAME.flattenToString();
+    private static final UserHandle USER_HANDLE = UserHandle.of(111);
+
+    private static final int PROCESS_USER_ID = 222;
+
+    private final String mConfigDefaultContentProtectionService = COMPONENT_NAME.flattenToString();
+
+    @Rule public final MockitoRule mMockitoRule = MockitoJUnit.rule();
+
+    @Rule public final SetFlagsRule mSetFlagsRule = new SetFlagsRule();
 
     @Mock private Context mMockContext;
 
-    @Before
-    public void setUp() {
-        MockitoAnnotations.initMocks(this);
-    }
+    @Mock private Context mMockUserContext;
+
+    @Mock private UserManager mMockUserManager;
+
+    @Mock private DevicePolicyManager mMockDevicePolicyManager;
+
+    @Mock private UserInfo mMockUserInfo;
 
     @After
     public void tearDown() {
@@ -134,7 +160,6 @@
         assertThat(ContentProtectionPreferenceUtils.isAvailable(mMockContext)).isFalse();
     }
 
-
     @Test
     public void isAvailable_bothDisabled_false() {
         DeviceConfig.setProperty(
@@ -145,4 +170,113 @@
 
         assertThat(ContentProtectionPreferenceUtils.isAvailable(mMockContext)).isFalse();
     }
+
+    @Test
+    public void getManagedProfile_noProfiles() {
+        when(mMockContext.getSystemService(UserManager.class)).thenReturn(mMockUserManager);
+        when(mMockUserManager.getUserProfiles()).thenReturn(List.of());
+
+        UserHandle actual = ContentProtectionPreferenceUtils.getManagedProfile(mMockContext);
+
+        assertThat(actual).isNull();
+    }
+
+    @Test
+    public void getManagedProfile_notManaged() {
+        when(mMockContext.getSystemService(UserManager.class)).thenReturn(mMockUserManager);
+        when(mMockUserManager.getUserProfiles()).thenReturn(List.of(USER_HANDLE));
+        when(mMockUserManager.getProcessUserId()).thenReturn(PROCESS_USER_ID);
+        when(mMockUserManager.getUserInfo(USER_HANDLE.getIdentifier())).thenReturn(mMockUserInfo);
+
+        UserHandle actual = ContentProtectionPreferenceUtils.getManagedProfile(mMockContext);
+
+        assertThat(actual).isNull();
+        verify(mMockUserInfo).isManagedProfile();
+    }
+
+    @Test
+    public void getManagedProfile_managed() {
+        when(mMockContext.getSystemService(UserManager.class)).thenReturn(mMockUserManager);
+        when(mMockUserManager.getUserProfiles()).thenReturn(List.of(USER_HANDLE));
+        when(mMockUserManager.getProcessUserId()).thenReturn(PROCESS_USER_ID);
+        when(mMockUserManager.getUserInfo(USER_HANDLE.getIdentifier())).thenReturn(mMockUserInfo);
+        when(mMockUserInfo.isManagedProfile()).thenReturn(true);
+
+        UserHandle actual = ContentProtectionPreferenceUtils.getManagedProfile(mMockContext);
+
+        assertThat(actual).isEqualTo(USER_HANDLE);
+    }
+
+    @Test
+    public void getContentProtectionPolicy_flagDisabled_managedProfileNull() {
+        mSetFlagsRule.disableFlags(FLAG_MANAGE_DEVICE_POLICY_ENABLED);
+
+        int actual =
+                ContentProtectionPreferenceUtils.getContentProtectionPolicy(
+                        mMockContext, /* managedProfile= */ null);
+
+        assertThat(actual).isEqualTo(DevicePolicyManager.CONTENT_PROTECTION_DISABLED);
+    }
+
+    @Test
+    public void getContentProtectionPolicy_flagDisabled_managedProfileNotNull() {
+        mSetFlagsRule.disableFlags(FLAG_MANAGE_DEVICE_POLICY_ENABLED);
+
+        int actual =
+                ContentProtectionPreferenceUtils.getContentProtectionPolicy(
+                        mMockContext, USER_HANDLE);
+
+        assertThat(actual).isEqualTo(DevicePolicyManager.CONTENT_PROTECTION_DISABLED);
+    }
+
+    @Test
+    public void getContentProtectionPolicy_flagEnabled_managedProfileNull() throws Exception {
+        mSetFlagsRule.enableFlags(FLAG_MANAGE_DEVICE_POLICY_ENABLED);
+        when(mMockContext.getSystemService(DevicePolicyManager.class))
+                .thenReturn(mMockDevicePolicyManager);
+        when(mMockDevicePolicyManager.getContentProtectionPolicy(/* admin= */ null))
+                .thenReturn(DevicePolicyManager.CONTENT_PROTECTION_ENABLED);
+
+        int actual =
+                ContentProtectionPreferenceUtils.getContentProtectionPolicy(
+                        mMockContext, /* managedProfile= */ null);
+
+        assertThat(actual).isEqualTo(DevicePolicyManager.CONTENT_PROTECTION_ENABLED);
+        verify(mMockContext, never()).createPackageContextAsUser(anyString(), anyInt(), any());
+    }
+
+    @Test
+    public void getContentProtectionPolicy_flagEnabled_managedProfileNotNull() throws Exception {
+        mSetFlagsRule.enableFlags(FLAG_MANAGE_DEVICE_POLICY_ENABLED);
+        when(mMockContext.getPackageName()).thenReturn(PACKAGE_NAME);
+        when(mMockContext.createPackageContextAsUser(PACKAGE_NAME, /* flags= */ 0, USER_HANDLE))
+                .thenReturn(mMockUserContext);
+        when(mMockUserContext.getSystemService(DevicePolicyManager.class))
+                .thenReturn(mMockDevicePolicyManager);
+        when(mMockDevicePolicyManager.getContentProtectionPolicy(/* admin= */ null))
+                .thenReturn(DevicePolicyManager.CONTENT_PROTECTION_ENABLED);
+
+        int actual =
+                ContentProtectionPreferenceUtils.getContentProtectionPolicy(
+                        mMockContext, USER_HANDLE);
+
+        assertThat(actual).isEqualTo(DevicePolicyManager.CONTENT_PROTECTION_ENABLED);
+    }
+
+    @Test
+    public void getContentProtectionPolicy_flagEnabled_managedProfileNotNull_nameNotFound()
+            throws Exception {
+        mSetFlagsRule.enableFlags(FLAG_MANAGE_DEVICE_POLICY_ENABLED);
+        when(mMockContext.getPackageName()).thenReturn(PACKAGE_NAME);
+        when(mMockContext.createPackageContextAsUser(PACKAGE_NAME, /* flags= */ 0, USER_HANDLE))
+                .thenThrow(new PackageManager.NameNotFoundException());
+
+        assertThrows(
+                IllegalStateException.class,
+                () ->
+                        ContentProtectionPreferenceUtils.getContentProtectionPolicy(
+                                mMockContext, USER_HANDLE));
+
+        verify(mMockContext, never()).getSystemService(DevicePolicyManager.class);
+    }
 }
diff --git a/tests/robotests/src/com/android/settings/security/ContentProtectionTogglePreferenceControllerTest.java b/tests/robotests/src/com/android/settings/security/ContentProtectionTogglePreferenceControllerTest.java
index 50e9a5c..075ac6c 100644
--- a/tests/robotests/src/com/android/settings/security/ContentProtectionTogglePreferenceControllerTest.java
+++ b/tests/robotests/src/com/android/settings/security/ContentProtectionTogglePreferenceControllerTest.java
@@ -15,20 +15,25 @@
  */
 package com.android.settings.security;
 
+import static android.view.contentprotection.flags.Flags.FLAG_MANAGE_DEVICE_POLICY_ENABLED;
+
+import static com.android.settings.core.BasePreferenceController.AVAILABLE;
 import static com.android.settings.security.ContentProtectionTogglePreferenceController.KEY_CONTENT_PROTECTION_PREFERENCE;
 
 import static com.google.common.truth.Truth.assertThat;
 
 import static org.mockito.ArgumentMatchers.any;
-import static org.mockito.Mockito.mock;
 import static org.mockito.Mockito.never;
 import static org.mockito.Mockito.verify;
 import static org.mockito.Mockito.when;
 
+import android.app.admin.DevicePolicyManager;
 import android.content.Context;
+import android.os.UserHandle;
 import android.platform.test.flag.junit.SetFlagsRule;
 import android.provider.Settings;
 
+import androidx.annotation.Nullable;
 import androidx.preference.PreferenceScreen;
 import androidx.test.core.app.ApplicationProvider;
 
@@ -42,37 +47,40 @@
 import org.junit.Test;
 import org.junit.runner.RunWith;
 import org.mockito.Mock;
-import org.mockito.MockitoAnnotations;
 import org.mockito.junit.MockitoJUnit;
 import org.mockito.junit.MockitoRule;
 import org.robolectric.RobolectricTestRunner;
 import org.robolectric.annotation.Config;
 
 @RunWith(RobolectricTestRunner.class)
-@Config(
-        shadows = {
-            ShadowUtils.class,
-        })
+@Config(shadows = {ShadowUtils.class})
 public class ContentProtectionTogglePreferenceControllerTest {
 
-    @Rule public final SetFlagsRule mSetFlagsRule = new SetFlagsRule();
     @Rule public final MockitoRule mMockitoRule = MockitoJUnit.rule();
 
-    @Mock private PreferenceScreen mMockScreen;
+    @Rule public final SetFlagsRule mSetFlagsRule = new SetFlagsRule();
 
-    private RestrictedLockUtils.EnforcedAdmin mAdmin;
-    private SettingsMainSwitchPreference mSwitchPreference;
     private final Context mContext = ApplicationProvider.getApplicationContext();
-    private ContentProtectionTogglePreferenceController mController;
+
+    @Mock private PreferenceScreen mMockPreferenceScreen;
+
+    @Mock private SettingsMainSwitchPreference mMockSwitchPreference;
+
+    @Nullable private RestrictedLockUtils.EnforcedAdmin mEnforcedAdmin;
+
+    @DevicePolicyManager.ContentProtectionPolicy
+    private int mContentProtectionPolicy = DevicePolicyManager.CONTENT_PROTECTION_DISABLED;
+
+    private TestContentProtectionTogglePreferenceController mController;
+
     private int mSettingBackupValue;
 
     @Before
     public void setUp() {
-        MockitoAnnotations.initMocks(this);
         mController = new TestContentProtectionTogglePreferenceController();
-        mSwitchPreference = new SettingsMainSwitchPreference(mContext);
-        when(mMockScreen.findPreference(mController.getPreferenceKey()))
-                .thenReturn(mSwitchPreference);
+        SettingsMainSwitchPreference switchPreference = new SettingsMainSwitchPreference(mContext);
+        when(mMockPreferenceScreen.findPreference(mController.getPreferenceKey()))
+                .thenReturn(switchPreference);
         mSettingBackupValue = getContentProtectionGlobalSetting();
         Settings.Global.putInt(mContext.getContentResolver(), KEY_CONTENT_PROTECTION_PREFERENCE, 0);
     }
@@ -87,89 +95,223 @@
     }
 
     @Test
-    public void isAvailable_alwaysAvailable() {
+    public void constructor_flagDisabled_doesNotFetchData() {
+        mSetFlagsRule.disableFlags(FLAG_MANAGE_DEVICE_POLICY_ENABLED);
+        mController = new TestContentProtectionTogglePreferenceController();
+
+        assertThat(mController.mCounterGetManagedProfile).isEqualTo(0);
+        assertThat(mController.mCounterGetEnforcedAdmin).isEqualTo(0);
+        assertThat(mController.mCounterGetContentProtectionPolicy).isEqualTo(0);
+    }
+
+    @Test
+    public void constructor_flagEnabled_fetchesData() {
+        mSetFlagsRule.enableFlags(FLAG_MANAGE_DEVICE_POLICY_ENABLED);
+        mController = new TestContentProtectionTogglePreferenceController();
+
+        assertThat(mController.mCounterGetManagedProfile).isEqualTo(1);
+        assertThat(mController.mCounterGetEnforcedAdmin).isEqualTo(1);
+        assertThat(mController.mCounterGetContentProtectionPolicy).isEqualTo(1);
+    }
+
+    @Test
+    public void getAvailabilityStatus_available() {
+        assertThat(mController.getAvailabilityStatus()).isEqualTo(AVAILABLE);
         assertThat(mController.isAvailable()).isTrue();
     }
 
     @Test
-    public void displayPreference() {
-        setUpFullyManagedMode();
-        SettingsMainSwitchPreference mockSwitchPreference =
-                mock(SettingsMainSwitchPreference.class);
-        when(mMockScreen.findPreference(any())).thenReturn(mockSwitchPreference);
-        when(mockSwitchPreference.getKey()).thenReturn(mController.getPreferenceKey());
-
-        mController = new TestContentProtectionTogglePreferenceController();
-        mController.displayPreference(mMockScreen);
-
-        assertThat(mockSwitchPreference).isNotNull();
-    }
-
-    @Test
-    public void updateState_notFullyManagedMode_enabled() {
-        SettingsMainSwitchPreference mockSwitchPreference =
-                mock(SettingsMainSwitchPreference.class);
-        when(mMockScreen.findPreference(any())).thenReturn(mockSwitchPreference);
-        when(mockSwitchPreference.getKey()).thenReturn(mController.getPreferenceKey());
-
-        mController = new TestContentProtectionTogglePreferenceController();
-        mController.displayPreference(mMockScreen);
-        mController.updateState(mockSwitchPreference);
-
-        verify(mockSwitchPreference, never()).setDisabledByAdmin(any());
-    }
-
-    @Test
-    public void updateState_fullyManagedMode_disabled() {
-        setUpFullyManagedMode();
-        SettingsMainSwitchPreference mockSwitchPreference =
-                mock(SettingsMainSwitchPreference.class);
-        when(mMockScreen.findPreference(any())).thenReturn(mockSwitchPreference);
-        when(mockSwitchPreference.getKey()).thenReturn(mController.getPreferenceKey());
-
-        mController = new TestContentProtectionTogglePreferenceController();
-        mController.displayPreference(mMockScreen);
-        mController.updateState(mockSwitchPreference);
-
-        verify(mockSwitchPreference).setDisabledByAdmin(mAdmin);
-    }
-
-    @Test
-    public void isChecked_settingTurnOn() {
+    public void isChecked_noEnforcedAdmin_readsSettingsTrue() {
         Settings.Global.putInt(mContext.getContentResolver(), KEY_CONTENT_PROTECTION_PREFERENCE, 1);
 
         assertThat(mController.isChecked()).isTrue();
     }
 
     @Test
-    public void isChecked_fullyManagedMode_settingTurnOff() {
-        setUpFullyManagedMode();
-        Settings.Global.putInt(mContext.getContentResolver(), KEY_CONTENT_PROTECTION_PREFERENCE, 1);
-        SettingsMainSwitchPreference mockSwitchPreference =
-                mock(SettingsMainSwitchPreference.class);
-        when(mMockScreen.findPreference(any())).thenReturn(mockSwitchPreference);
-        when(mockSwitchPreference.getKey()).thenReturn(mController.getPreferenceKey());
-
-        mController = new TestContentProtectionTogglePreferenceController();
-        mController.displayPreference(mMockScreen);
-        mController.updateState(mockSwitchPreference);
-
-        assertThat(mController.isChecked()).isFalse();
-    }
-
-    @Test
-    public void isChecked_settingTurnOff() {
+    public void isChecked_noEnforcedAdmin_readsSettingsFalse() {
         Settings.Global.putInt(
                 mContext.getContentResolver(), KEY_CONTENT_PROTECTION_PREFERENCE, -1);
 
         assertThat(mController.isChecked()).isFalse();
-        assertThat(getContentProtectionGlobalSetting()).isEqualTo(-1);
     }
 
     @Test
-    public void isChecked_settingDefaultOn() {
+    public void isChecked_noEnforcedAdmin_readsSettingsDefaultTrue() {
         assertThat(mController.isChecked()).isTrue();
-        assertThat(getContentProtectionGlobalSetting()).isEqualTo(0);
+    }
+
+    @Test
+    public void isChecked_enforcedAdmin_flagDisabled_false() {
+        mSetFlagsRule.disableFlags(FLAG_MANAGE_DEVICE_POLICY_ENABLED);
+        mEnforcedAdmin = new RestrictedLockUtils.EnforcedAdmin();
+        Settings.Global.putInt(mContext.getContentResolver(), KEY_CONTENT_PROTECTION_PREFERENCE, 1);
+        setupForUpdateState();
+        mController.updateState(mMockSwitchPreference);
+
+        assertThat(mController.isChecked()).isFalse();
+    }
+
+    @Test
+    public void isChecked_enforcedAdmin_flagEnabled_policyDisabled_false() {
+        mSetFlagsRule.enableFlags(FLAG_MANAGE_DEVICE_POLICY_ENABLED);
+        mEnforcedAdmin = new RestrictedLockUtils.EnforcedAdmin();
+        mContentProtectionPolicy = DevicePolicyManager.CONTENT_PROTECTION_DISABLED;
+        Settings.Global.putInt(mContext.getContentResolver(), KEY_CONTENT_PROTECTION_PREFERENCE, 1);
+        mController = new TestContentProtectionTogglePreferenceController();
+
+        assertThat(mController.isChecked()).isFalse();
+    }
+
+    @Test
+    public void isChecked_enforcedAdmin_flagEnabled_policyEnabled_true() {
+        mSetFlagsRule.enableFlags(FLAG_MANAGE_DEVICE_POLICY_ENABLED);
+        mEnforcedAdmin = new RestrictedLockUtils.EnforcedAdmin();
+        mContentProtectionPolicy = DevicePolicyManager.CONTENT_PROTECTION_ENABLED;
+        Settings.Global.putInt(
+                mContext.getContentResolver(), KEY_CONTENT_PROTECTION_PREFERENCE, -1);
+        mController = new TestContentProtectionTogglePreferenceController();
+
+        assertThat(mController.isChecked()).isTrue();
+    }
+
+    @Test
+    public void isChecked_enforcedAdmin_flagEnabled_policyNotControlled_readsSettingsTrue() {
+        mSetFlagsRule.enableFlags(FLAG_MANAGE_DEVICE_POLICY_ENABLED);
+        mEnforcedAdmin = new RestrictedLockUtils.EnforcedAdmin();
+        mContentProtectionPolicy = DevicePolicyManager.CONTENT_PROTECTION_NOT_CONTROLLED_BY_POLICY;
+        Settings.Global.putInt(mContext.getContentResolver(), KEY_CONTENT_PROTECTION_PREFERENCE, 1);
+        mController = new TestContentProtectionTogglePreferenceController();
+
+        assertThat(mController.isChecked()).isTrue();
+    }
+
+    @Test
+    public void isChecked_enforcedAdmin_flagEnabled_policyNotControlled_readsSettingsFalse() {
+        mSetFlagsRule.enableFlags(FLAG_MANAGE_DEVICE_POLICY_ENABLED);
+        mEnforcedAdmin = new RestrictedLockUtils.EnforcedAdmin();
+        mContentProtectionPolicy = DevicePolicyManager.CONTENT_PROTECTION_NOT_CONTROLLED_BY_POLICY;
+        Settings.Global.putInt(
+                mContext.getContentResolver(), KEY_CONTENT_PROTECTION_PREFERENCE, -1);
+        mController = new TestContentProtectionTogglePreferenceController();
+
+        assertThat(mController.isChecked()).isFalse();
+    }
+
+    @Test
+    public void isChecked_enforcedAdmin_flagEnabled_policyNotControlled_readsSettingsDefaultTrue() {
+        mSetFlagsRule.enableFlags(FLAG_MANAGE_DEVICE_POLICY_ENABLED);
+        mEnforcedAdmin = new RestrictedLockUtils.EnforcedAdmin();
+        mContentProtectionPolicy = DevicePolicyManager.CONTENT_PROTECTION_NOT_CONTROLLED_BY_POLICY;
+        mController = new TestContentProtectionTogglePreferenceController();
+
+        assertThat(mController.isChecked()).isTrue();
+    }
+
+    @Test
+    public void displayPreference() {
+        setupForDisplayPreference();
+
+        mController.displayPreference(mMockPreferenceScreen);
+
+        verify(mMockSwitchPreference).addOnSwitchChangeListener(mController);
+    }
+
+    @Test
+    public void updateState_flagDisabled_noEnforcedAdmin() {
+        mSetFlagsRule.disableFlags(FLAG_MANAGE_DEVICE_POLICY_ENABLED);
+        setupForUpdateState();
+
+        mController.updateState(mMockSwitchPreference);
+
+        assertThat(mController.mCounterGetEnforcedAdmin).isEqualTo(1);
+        verify(mMockSwitchPreference, never()).setDisabledByAdmin(any());
+    }
+
+    @Test
+    public void updateState_flagDisabled_enforcedAdmin() {
+        mSetFlagsRule.disableFlags(FLAG_MANAGE_DEVICE_POLICY_ENABLED);
+        mEnforcedAdmin = new RestrictedLockUtils.EnforcedAdmin();
+        setupForUpdateState();
+
+        mController.updateState(mMockSwitchPreference);
+
+        assertThat(mController.mCounterGetEnforcedAdmin).isEqualTo(1);
+        verify(mMockSwitchPreference).setDisabledByAdmin(mEnforcedAdmin);
+    }
+
+    @Test
+    public void updateState_flagEnabled_noEnforcedAdmin_policyDisabled() {
+        mSetFlagsRule.enableFlags(FLAG_MANAGE_DEVICE_POLICY_ENABLED);
+        mContentProtectionPolicy = DevicePolicyManager.CONTENT_PROTECTION_DISABLED;
+        setupForUpdateState();
+
+        mController.updateState(mMockSwitchPreference);
+
+        assertThat(mController.mCounterGetEnforcedAdmin).isEqualTo(1);
+        verify(mMockSwitchPreference, never()).setDisabledByAdmin(any());
+    }
+
+    @Test
+    public void updateState_flagEnabled_noEnforcedAdmin_policyEnabled() {
+        mSetFlagsRule.enableFlags(FLAG_MANAGE_DEVICE_POLICY_ENABLED);
+        mContentProtectionPolicy = DevicePolicyManager.CONTENT_PROTECTION_ENABLED;
+        setupForUpdateState();
+
+        mController.updateState(mMockSwitchPreference);
+
+        assertThat(mController.mCounterGetEnforcedAdmin).isEqualTo(1);
+        verify(mMockSwitchPreference, never()).setDisabledByAdmin(any());
+    }
+
+    @Test
+    public void updateState_flagEnabled_noEnforcedAdmin_policyNotControlled() {
+        mSetFlagsRule.enableFlags(FLAG_MANAGE_DEVICE_POLICY_ENABLED);
+        mContentProtectionPolicy = DevicePolicyManager.CONTENT_PROTECTION_NOT_CONTROLLED_BY_POLICY;
+        setupForUpdateState();
+
+        mController.updateState(mMockSwitchPreference);
+
+        assertThat(mController.mCounterGetEnforcedAdmin).isEqualTo(1);
+        verify(mMockSwitchPreference, never()).setDisabledByAdmin(any());
+    }
+
+    @Test
+    public void updateState_flagEnabled_enforcedAdmin_policyDisabled() {
+        mSetFlagsRule.enableFlags(FLAG_MANAGE_DEVICE_POLICY_ENABLED);
+        mEnforcedAdmin = new RestrictedLockUtils.EnforcedAdmin();
+        mContentProtectionPolicy = DevicePolicyManager.CONTENT_PROTECTION_DISABLED;
+        setupForUpdateState();
+
+        mController.updateState(mMockSwitchPreference);
+
+        assertThat(mController.mCounterGetEnforcedAdmin).isEqualTo(1);
+        verify(mMockSwitchPreference).setDisabledByAdmin(mEnforcedAdmin);
+    }
+
+    @Test
+    public void updateState_flagEnabled_enforcedAdmin_policyEnabled() {
+        mSetFlagsRule.enableFlags(FLAG_MANAGE_DEVICE_POLICY_ENABLED);
+        mEnforcedAdmin = new RestrictedLockUtils.EnforcedAdmin();
+        mContentProtectionPolicy = DevicePolicyManager.CONTENT_PROTECTION_ENABLED;
+        setupForUpdateState();
+
+        mController.updateState(mMockSwitchPreference);
+
+        assertThat(mController.mCounterGetEnforcedAdmin).isEqualTo(1);
+        verify(mMockSwitchPreference).setDisabledByAdmin(mEnforcedAdmin);
+    }
+
+    @Test
+    public void updateState_flagEnabled_enforcedAdmin_policyNotControlled() {
+        mSetFlagsRule.enableFlags(FLAG_MANAGE_DEVICE_POLICY_ENABLED);
+        mEnforcedAdmin = new RestrictedLockUtils.EnforcedAdmin();
+        mContentProtectionPolicy = DevicePolicyManager.CONTENT_PROTECTION_NOT_CONTROLLED_BY_POLICY;
+        setupForUpdateState();
+
+        mController.updateState(mMockSwitchPreference);
+
+        assertThat(mController.mCounterGetEnforcedAdmin).isEqualTo(1);
+        verify(mMockSwitchPreference, never()).setDisabledByAdmin(any());
     }
 
     @Test
@@ -193,20 +335,49 @@
                 mContext.getContentResolver(), KEY_CONTENT_PROTECTION_PREFERENCE, 0);
     }
 
-    private void setUpFullyManagedMode() {
-        mAdmin = new RestrictedLockUtils.EnforcedAdmin();
+    private void setupForDisplayPreference() {
+        when(mMockPreferenceScreen.findPreference(any())).thenReturn(mMockSwitchPreference);
+        when(mMockSwitchPreference.getKey()).thenReturn(mController.getPreferenceKey());
+        mController = new TestContentProtectionTogglePreferenceController();
+    }
+
+    private void setupForUpdateState() {
+        setupForDisplayPreference();
+        mController.displayPreference(mMockPreferenceScreen);
     }
 
     private class TestContentProtectionTogglePreferenceController
             extends ContentProtectionTogglePreferenceController {
 
+        public int mCounterGetManagedProfile;
+
+        public int mCounterGetEnforcedAdmin;
+
+        public int mCounterGetContentProtectionPolicy;
+
         TestContentProtectionTogglePreferenceController() {
             super(ContentProtectionTogglePreferenceControllerTest.this.mContext, "key");
         }
 
         @Override
+        @Nullable
+        protected UserHandle getManagedProfile() {
+            mCounterGetManagedProfile++;
+            return null;
+        }
+
+        @Override
+        @Nullable
         protected RestrictedLockUtils.EnforcedAdmin getEnforcedAdmin() {
-            return mAdmin;
+            mCounterGetEnforcedAdmin++;
+            return mEnforcedAdmin;
+        }
+
+        @Override
+        @DevicePolicyManager.ContentProtectionPolicy
+        protected int getContentProtectionPolicy(@Nullable UserHandle userHandle) {
+            mCounterGetContentProtectionPolicy++;
+            return mContentProtectionPolicy;
         }
     }
 }
diff --git a/tests/robotests/src/com/android/settings/security/ContentProtectionWorkSwitchControllerTest.java b/tests/robotests/src/com/android/settings/security/ContentProtectionWorkSwitchControllerTest.java
index 8d35e4d..3d367de 100644
--- a/tests/robotests/src/com/android/settings/security/ContentProtectionWorkSwitchControllerTest.java
+++ b/tests/robotests/src/com/android/settings/security/ContentProtectionWorkSwitchControllerTest.java
@@ -16,19 +16,22 @@
 
 package com.android.settings.security;
 
+import static android.view.contentprotection.flags.Flags.FLAG_MANAGE_DEVICE_POLICY_ENABLED;
+
 import static com.android.settings.core.BasePreferenceController.AVAILABLE;
 import static com.android.settings.core.BasePreferenceController.CONDITIONALLY_UNAVAILABLE;
 
 import static com.google.common.truth.Truth.assertThat;
 
 import static org.mockito.ArgumentMatchers.any;
-import static org.mockito.Mockito.mock;
 import static org.mockito.Mockito.never;
 import static org.mockito.Mockito.verify;
 import static org.mockito.Mockito.when;
 
+import android.app.admin.DevicePolicyManager;
 import android.content.Context;
 import android.os.UserHandle;
+import android.platform.test.flag.junit.SetFlagsRule;
 
 import androidx.annotation.NonNull;
 import androidx.annotation.Nullable;
@@ -39,55 +42,169 @@
 import com.android.settingslib.RestrictedSwitchPreference;
 
 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;
+import org.mockito.junit.MockitoJUnit;
+import org.mockito.junit.MockitoRule;
 import org.robolectric.RobolectricTestRunner;
 
 @RunWith(RobolectricTestRunner.class)
 public class ContentProtectionWorkSwitchControllerTest {
+
     private static final UserHandle TEST_USER_HANDLE = UserHandle.of(10);
 
+    @Rule public final MockitoRule mMockitoRule = MockitoJUnit.rule();
+
+    @Rule public final SetFlagsRule mSetFlagsRule = new SetFlagsRule();
+
     private final Context mContext = ApplicationProvider.getApplicationContext();
 
     @Mock private PreferenceScreen mMockPreferenceScreen;
-    private ContentProtectionWorkSwitchController mController;
-    private UserHandle mManagedProfileUserHandle;
-    private RestrictedLockUtils.EnforcedAdmin mEnforcedAdmin;
+
+    @Mock private RestrictedSwitchPreference mMockSwitchPreference;
+
+    @Nullable private UserHandle mManagedProfileUserHandle;
+
+    @Nullable private RestrictedLockUtils.EnforcedAdmin mEnforcedAdmin;
+
+    @DevicePolicyManager.ContentProtectionPolicy
+    private int mContentProtectionPolicy = DevicePolicyManager.CONTENT_PROTECTION_DISABLED;
+
+    private TestContentProtectionWorkSwitchController mController;
 
     @Before
     public void setUp() {
-        MockitoAnnotations.initMocks(this);
         mController = new TestContentProtectionWorkSwitchController();
     }
 
     @Test
-    public void isAvailable_managedProfile_available() {
+    public void constructor_flagDisabled_doesNotFetchData() {
+        mSetFlagsRule.disableFlags(FLAG_MANAGE_DEVICE_POLICY_ENABLED);
+        mController = new TestContentProtectionWorkSwitchController();
+
+        assertThat(mController.mCounterGetManagedProfile).isEqualTo(0);
+        assertThat(mController.mCounterGetEnforcedAdmin).isEqualTo(0);
+        assertThat(mController.mCounterGetContentProtectionPolicy).isEqualTo(0);
+    }
+
+    @Test
+    public void constructor_flagEnabled_fetchesManagedProfile() {
+        mSetFlagsRule.enableFlags(FLAG_MANAGE_DEVICE_POLICY_ENABLED);
+        mController = new TestContentProtectionWorkSwitchController();
+
+        assertThat(mController.mCounterGetManagedProfile).isEqualTo(1);
+        assertThat(mController.mCounterGetEnforcedAdmin).isEqualTo(0);
+        assertThat(mController.mCounterGetContentProtectionPolicy).isEqualTo(0);
+    }
+
+    @Test
+    public void constructor_flagEnabled_withManagedProfile_fetchesPolicy() {
+        mSetFlagsRule.enableFlags(FLAG_MANAGE_DEVICE_POLICY_ENABLED);
         mManagedProfileUserHandle = TEST_USER_HANDLE;
+        mController = new TestContentProtectionWorkSwitchController();
+
+        assertThat(mController.mCounterGetManagedProfile).isEqualTo(1);
+        assertThat(mController.mCounterGetEnforcedAdmin).isEqualTo(0);
+        assertThat(mController.mCounterGetContentProtectionPolicy).isEqualTo(1);
+    }
+
+    @Test
+    public void getAvailabilityStatus_flagDisabled_managedProfile_available() {
+        mSetFlagsRule.disableFlags(FLAG_MANAGE_DEVICE_POLICY_ENABLED);
+        mManagedProfileUserHandle = TEST_USER_HANDLE;
+        mController = new TestContentProtectionWorkSwitchController();
 
         assertThat(mController.getAvailabilityStatus()).isEqualTo(AVAILABLE);
         assertThat(mController.isAvailable()).isTrue();
     }
 
     @Test
-    public void isAvailable_noManagedProfile_notAvailable() {
-        mManagedProfileUserHandle = null;
+    public void getAvailabilityStatus_flagDisabled_noManagedProfile_unavailable() {
+        mSetFlagsRule.disableFlags(FLAG_MANAGE_DEVICE_POLICY_ENABLED);
+        mController = new TestContentProtectionWorkSwitchController();
 
         assertThat(mController.getAvailabilityStatus()).isEqualTo(CONDITIONALLY_UNAVAILABLE);
         assertThat(mController.isAvailable()).isFalse();
     }
 
     @Test
-    public void isChecked_noManagedProfile_alwaysOff() {
-        mManagedProfileUserHandle = null;
+    public void getAvailabilityStatus_flagEnabled_managedProfile_policyDisabled_available() {
+        mSetFlagsRule.enableFlags(FLAG_MANAGE_DEVICE_POLICY_ENABLED);
+        mManagedProfileUserHandle = TEST_USER_HANDLE;
+        mContentProtectionPolicy = DevicePolicyManager.CONTENT_PROTECTION_DISABLED;
+        mController = new TestContentProtectionWorkSwitchController();
+
+        assertThat(mController.getAvailabilityStatus()).isEqualTo(AVAILABLE);
+        assertThat(mController.isAvailable()).isTrue();
+    }
+
+    @Test
+    public void getAvailabilityStatus_flagEnabled_managedProfile_policyEnabled_available() {
+        mSetFlagsRule.enableFlags(FLAG_MANAGE_DEVICE_POLICY_ENABLED);
+        mManagedProfileUserHandle = TEST_USER_HANDLE;
+        mContentProtectionPolicy = DevicePolicyManager.CONTENT_PROTECTION_ENABLED;
+        mController = new TestContentProtectionWorkSwitchController();
+
+        assertThat(mController.getAvailabilityStatus()).isEqualTo(AVAILABLE);
+        assertThat(mController.isAvailable()).isTrue();
+    }
+
+    @Test
+    public void getAvailabilityStatus_flagEnabled_managedProfile_policyNotControlled_unavailable() {
+        mSetFlagsRule.enableFlags(FLAG_MANAGE_DEVICE_POLICY_ENABLED);
+        mManagedProfileUserHandle = TEST_USER_HANDLE;
+        mContentProtectionPolicy = DevicePolicyManager.CONTENT_PROTECTION_NOT_CONTROLLED_BY_POLICY;
+        mController = new TestContentProtectionWorkSwitchController();
+
+        assertThat(mController.getAvailabilityStatus()).isEqualTo(CONDITIONALLY_UNAVAILABLE);
+        assertThat(mController.isAvailable()).isFalse();
+    }
+
+    @Test
+    public void getAvailabilityStatus_flagEnabled_noManagedProfile_unavailable() {
+        mSetFlagsRule.enableFlags(FLAG_MANAGE_DEVICE_POLICY_ENABLED);
+        mController = new TestContentProtectionWorkSwitchController();
+
+        assertThat(mController.getAvailabilityStatus()).isEqualTo(CONDITIONALLY_UNAVAILABLE);
+        assertThat(mController.isAvailable()).isFalse();
+    }
+
+    @Test
+    public void isChecked_flagDisabled_false() {
+        mSetFlagsRule.disableFlags(FLAG_MANAGE_DEVICE_POLICY_ENABLED);
+        mController = new TestContentProtectionWorkSwitchController();
 
         assertThat(mController.isChecked()).isFalse();
     }
 
     @Test
-    public void isChecked_managedProfile_alwaysOff() {
+    public void isChecked_flagEnabled_policyEnabled_true() {
+        mSetFlagsRule.enableFlags(FLAG_MANAGE_DEVICE_POLICY_ENABLED);
         mManagedProfileUserHandle = TEST_USER_HANDLE;
+        mContentProtectionPolicy = DevicePolicyManager.CONTENT_PROTECTION_ENABLED;
+        mController = new TestContentProtectionWorkSwitchController();
+
+        assertThat(mController.isChecked()).isTrue();
+    }
+
+    @Test
+    public void isChecked_flagEnabled_policyDisabled_false() {
+        mSetFlagsRule.enableFlags(FLAG_MANAGE_DEVICE_POLICY_ENABLED);
+        mManagedProfileUserHandle = TEST_USER_HANDLE;
+        mContentProtectionPolicy = DevicePolicyManager.CONTENT_PROTECTION_DISABLED;
+        mController = new TestContentProtectionWorkSwitchController();
+
+        assertThat(mController.isChecked()).isFalse();
+    }
+
+    @Test
+    public void isChecked_flagEnabled_policyNotControlled_false() {
+        mSetFlagsRule.enableFlags(FLAG_MANAGE_DEVICE_POLICY_ENABLED);
+        mManagedProfileUserHandle = TEST_USER_HANDLE;
+        mContentProtectionPolicy = DevicePolicyManager.CONTENT_PROTECTION_NOT_CONTROLLED_BY_POLICY;
+        mController = new TestContentProtectionWorkSwitchController();
 
         assertThat(mController.isChecked()).isFalse();
     }
@@ -99,50 +216,72 @@
     }
 
     @Test
-    public void displayPreference_managedProfile_disabled() {
+    public void displayPreference_flagDisabled_managedProfile_disabledByAdmin() {
+        mSetFlagsRule.disableFlags(FLAG_MANAGE_DEVICE_POLICY_ENABLED);
         mManagedProfileUserHandle = TEST_USER_HANDLE;
         mEnforcedAdmin = new RestrictedLockUtils.EnforcedAdmin();
-        RestrictedSwitchPreference mockSwitchPreference = mock(RestrictedSwitchPreference.class);
-        when(mMockPreferenceScreen.findPreference(any())).thenReturn(mockSwitchPreference);
-        when(mockSwitchPreference.getKey()).thenReturn(mController.getPreferenceKey());
+        setupForDisplayPreference();
 
         mController.displayPreference(mMockPreferenceScreen);
 
-        assertThat(mController.isAvailable()).isTrue();
-        verify(mockSwitchPreference).setDisabledByAdmin(mEnforcedAdmin);
+        verify(mMockSwitchPreference).setDisabledByAdmin(mEnforcedAdmin);
+        assertThat(mController.mCounterGetManagedProfile).isEqualTo(3);
+        assertThat(mController.mCounterGetEnforcedAdmin).isEqualTo(1);
     }
 
     @Test
-    public void displayPreference_noManagedProfile_notDisabled() {
-        mManagedProfileUserHandle = null;
+    public void displayPreference_flagDisabled_noManagedProfile_notDisabledByAdmin() {
+        mSetFlagsRule.disableFlags(FLAG_MANAGE_DEVICE_POLICY_ENABLED);
+        setupForDisplayPreference();
+
+        mController.displayPreference(mMockPreferenceScreen);
+
+        verify(mMockSwitchPreference, never()).setDisabledByAdmin(any());
+        assertThat(mController.mCounterGetManagedProfile).isEqualTo(3);
+        assertThat(mController.mCounterGetEnforcedAdmin).isEqualTo(0);
+    }
+
+    @Test
+    public void displayPreference_flagEnabled_managedProfile_disabledByAdmin() {
+        mSetFlagsRule.enableFlags(FLAG_MANAGE_DEVICE_POLICY_ENABLED);
+        mManagedProfileUserHandle = TEST_USER_HANDLE;
         mEnforcedAdmin = new RestrictedLockUtils.EnforcedAdmin();
-        RestrictedSwitchPreference mockSwitchPreference = mock(RestrictedSwitchPreference.class);
-        when(mMockPreferenceScreen.findPreference(any())).thenReturn(mockSwitchPreference);
-        when(mockSwitchPreference.getKey()).thenReturn(mController.getPreferenceKey());
+        setupForDisplayPreference();
 
         mController.displayPreference(mMockPreferenceScreen);
 
-        assertThat(mController.isAvailable()).isFalse();
-        verify(mockSwitchPreference, never()).setDisabledByAdmin(any());
+        verify(mMockSwitchPreference).setDisabledByAdmin(mEnforcedAdmin);
+        assertThat(mController.mCounterGetManagedProfile).isEqualTo(1);
+        assertThat(mController.mCounterGetEnforcedAdmin).isEqualTo(1);
     }
 
     @Test
-    public void displayPreference_noEnforcedAdmin_notDisabled() {
-        mManagedProfileUserHandle = null;
-        mEnforcedAdmin = null;
-        RestrictedSwitchPreference mockSwitchPreference = mock(RestrictedSwitchPreference.class);
-        when(mMockPreferenceScreen.findPreference(any())).thenReturn(mockSwitchPreference);
-        when(mockSwitchPreference.getKey()).thenReturn(mController.getPreferenceKey());
+    public void displayPreference_flagEnabled_noManagedProfile_notDisabledByAdmin() {
+        mSetFlagsRule.enableFlags(FLAG_MANAGE_DEVICE_POLICY_ENABLED);
+        setupForDisplayPreference();
 
         mController.displayPreference(mMockPreferenceScreen);
 
-        assertThat(mController.isAvailable()).isFalse();
-        verify(mockSwitchPreference, never()).setDisabledByAdmin(any());
+        verify(mMockSwitchPreference, never()).setDisabledByAdmin(any());
+        assertThat(mController.mCounterGetManagedProfile).isEqualTo(1);
+        assertThat(mController.mCounterGetEnforcedAdmin).isEqualTo(0);
+    }
+
+    private void setupForDisplayPreference() {
+        when(mMockPreferenceScreen.findPreference(any())).thenReturn(mMockSwitchPreference);
+        when(mMockSwitchPreference.getKey()).thenReturn(mController.getPreferenceKey());
+        mController = new TestContentProtectionWorkSwitchController();
     }
 
     private class TestContentProtectionWorkSwitchController
             extends ContentProtectionWorkSwitchController {
 
+        public int mCounterGetManagedProfile;
+
+        public int mCounterGetEnforcedAdmin;
+
+        public int mCounterGetContentProtectionPolicy;
+
         TestContentProtectionWorkSwitchController() {
             super(ContentProtectionWorkSwitchControllerTest.this.mContext, "key");
         }
@@ -150,14 +289,23 @@
         @Override
         @Nullable
         protected UserHandle getManagedProfile() {
+            mCounterGetManagedProfile++;
             return mManagedProfileUserHandle;
         }
 
         @Override
         @Nullable
         protected RestrictedLockUtils.EnforcedAdmin getEnforcedAdmin(
-                @NonNull UserHandle managedProfile) {
+                @NonNull UserHandle userHandle) {
+            mCounterGetEnforcedAdmin++;
             return mEnforcedAdmin;
         }
+
+        @Override
+        @DevicePolicyManager.ContentProtectionPolicy
+        protected int getContentProtectionPolicy(@Nullable UserHandle userHandle) {
+            mCounterGetContentProtectionPolicy++;
+            return mContentProtectionPolicy;
+        }
     }
 }
diff --git a/tests/robotests/src/com/android/settings/wifi/WifiConfigController2Test.java b/tests/robotests/src/com/android/settings/wifi/WifiConfigController2Test.java
index 4fcc93d..7d96496 100644
--- a/tests/robotests/src/com/android/settings/wifi/WifiConfigController2Test.java
+++ b/tests/robotests/src/com/android/settings/wifi/WifiConfigController2Test.java
@@ -16,6 +16,7 @@
 
 package com.android.settings.wifi;
 
+import static com.android.settings.wifi.WifiConfigController.DHCP_SPINNER_INDEX_SEND_DHCP_HOST_NAME_DISABLE;
 import static com.android.settings.wifi.WifiConfigController2.DEFAULT_ANONYMOUS_ID;
 import static com.android.settings.wifi.WifiConfigController2.WIFI_EAP_METHOD_SIM;
 
@@ -56,6 +57,7 @@
 import com.android.settings.R;
 import com.android.settings.network.SubscriptionUtil;
 import com.android.settings.utils.AndroidKeystoreAliasLoader;
+import com.android.settings.wifi.details2.WifiPrivacyPreferenceController;
 import com.android.settings.wifi.details2.WifiPrivacyPreferenceController2;
 import com.android.wifitrackerlib.WifiEntry;
 
@@ -513,6 +515,42 @@
     }
 
     @Test
+    public void loadSavedDhcpValue_true() {
+        checkSavedDhcpValue(true);
+    }
+
+    @Test
+    public void loadSavedDhcpValue_false() {
+        checkSavedDhcpValue(false);
+    }
+
+    private void checkSavedDhcpValue(boolean dhcpValue) {
+        when(mWifiEntry.isSaved()).thenReturn(true);
+        final WifiConfiguration mockWifiConfig = mock(WifiConfiguration.class);
+        when(mockWifiConfig.getIpConfiguration()).thenReturn(mock(IpConfiguration.class));
+        when(mockWifiConfig.isSendDhcpHostnameEnabled()).thenReturn(dhcpValue);
+        when(mWifiEntry.getWifiConfiguration()).thenReturn(mockWifiConfig);
+        createController(mWifiEntry, WifiConfigUiBase2.MODE_CONNECT, false);
+        final Spinner dhcpSetting = mView.findViewById(R.id.dhcp_settings);
+        final int expectedPrefValue =
+                WifiPrivacyPreferenceController.Companion
+                        .translateSendDhcpHostnameEnabledToPrefValue(dhcpValue);
+
+        assertThat(dhcpSetting.getVisibility()).isEqualTo(View.VISIBLE);
+        assertThat(dhcpSetting.getSelectedItemPosition()).isEqualTo(expectedPrefValue);
+    }
+
+    @Test
+    public void saveDhcpValue_changedToFalse() {
+        createController(mWifiEntry, WifiConfigUiBase2.MODE_CONNECT, false);
+        final Spinner privacySetting = mView.findViewById(R.id.dhcp_settings);
+        privacySetting.setSelection(DHCP_SPINNER_INDEX_SEND_DHCP_HOST_NAME_DISABLE);
+
+        WifiConfiguration config = mController.getConfig();
+        assertThat(config.isSendDhcpHostnameEnabled()).isEqualTo(false);
+    }
+
+    @Test
     public void replaceTtsString_whenTargetMatched_shouldSuccess() {
         createController(mWifiEntry, WifiConfigUiBase2.MODE_CONNECT, false);
         final CharSequence[] display = {"PEAP", "AKA1", "AKA2'"};
diff --git a/tests/robotests/src/com/android/settings/wifi/WifiConfigControllerTest.java b/tests/robotests/src/com/android/settings/wifi/WifiConfigControllerTest.java
index 2ff4596..d80464d 100644
--- a/tests/robotests/src/com/android/settings/wifi/WifiConfigControllerTest.java
+++ b/tests/robotests/src/com/android/settings/wifi/WifiConfigControllerTest.java
@@ -18,6 +18,8 @@
 
 import static com.android.settings.wifi.WifiConfigController.PRIVACY_SPINNER_INDEX_DEVICE_MAC;
 import static com.android.settings.wifi.WifiConfigController.PRIVACY_SPINNER_INDEX_RANDOMIZED_MAC;
+import static com.android.settings.wifi.WifiConfigController.DHCP_SPINNER_INDEX_SEND_DHCP_HOST_NAME_ENABLE;
+import static com.android.settings.wifi.WifiConfigController.DHCP_SPINNER_INDEX_SEND_DHCP_HOST_NAME_DISABLE;
 
 import static com.google.common.truth.Truth.assertThat;
 
@@ -451,6 +453,41 @@
     }
 
     @Test
+    public void loadSavedDhcpValue_true() {
+        checkSavedDhcpValue(true);
+    }
+
+    @Test
+    public void loadSavedDhcpValue_false() {
+        checkSavedDhcpValue(false);
+    }
+
+    private void checkSavedDhcpValue(boolean dhcpValue) {
+        when(mAccessPoint.isSaved()).thenReturn(true);
+        final WifiConfiguration mockWifiConfig = mock(WifiConfiguration.class);
+        when(mockWifiConfig.getIpConfiguration()).thenReturn(mock(IpConfiguration.class));
+        when(mockWifiConfig.isSendDhcpHostnameEnabled()).thenReturn(dhcpValue);
+        when(mAccessPoint.getConfig()).thenReturn(mockWifiConfig);
+        mController = new TestWifiConfigController(mConfigUiBase, mView, mAccessPoint,
+                WifiConfigUiBase.MODE_CONNECT);
+        final Spinner dhcpSetting = mView.findViewById(R.id.dhcp_settings);
+
+        assertThat(dhcpSetting.getVisibility()).isEqualTo(View.VISIBLE);
+        assertThat(dhcpSetting.getSelectedItemPosition()).isEqualTo(
+                dhcpValue ? DHCP_SPINNER_INDEX_SEND_DHCP_HOST_NAME_ENABLE :
+                        DHCP_SPINNER_INDEX_SEND_DHCP_HOST_NAME_DISABLE);
+    }
+
+    @Test
+    public void saveDhcpValue_changedToFalse() {
+        final Spinner privacySetting = mView.findViewById(R.id.dhcp_settings);
+        privacySetting.setSelection(DHCP_SPINNER_INDEX_SEND_DHCP_HOST_NAME_DISABLE);
+
+        WifiConfiguration config = mController.getConfig();
+        assertThat(config.isSendDhcpHostnameEnabled()).isEqualTo(false);
+    }
+
+    @Test
     public void replaceTtsString_whenTargetMatched_shouldSuccess() {
         final CharSequence[] display = {"PEAP", "AKA1", "AKA2'"};
         final CharSequence[] target = {"AKA1", "AKA2'"};
diff --git a/tests/screenshot/src/com/android/settings/tests/screenshot/biometrics/fingerprint/Injector.kt b/tests/screenshot/src/com/android/settings/tests/screenshot/biometrics/fingerprint/Injector.kt
index 3cd2002..9d97fbf 100644
--- a/tests/screenshot/src/com/android/settings/tests/screenshot/biometrics/fingerprint/Injector.kt
+++ b/tests/screenshot/src/com/android/settings/tests/screenshot/biometrics/fingerprint/Injector.kt
@@ -50,7 +50,7 @@
 import platform.test.screenshot.DeviceEmulationSpec
 import platform.test.screenshot.DisplaySpec
 import platform.test.screenshot.FragmentScreenshotTestRule
-import platform.test.screenshot.GoldenImagePathManager
+import platform.test.screenshot.GoldenPathManager
 import platform.test.screenshot.matchers.PixelPerfectMatcher
 
 class Injector(step: FingerprintNavigationStep.UiStep) {
@@ -154,7 +154,7 @@
     fun BiometricFragmentScreenShotRule() =
       FragmentScreenshotTestRule(
         DeviceEmulationSpec.forDisplays(Phone).first(),
-        GoldenImagePathManager(
+        GoldenPathManager(
           InstrumentationRegistry.getInstrumentation().context,
           InstrumentationRegistry.getInstrumentation().targetContext.filesDir.absolutePath +
             screenshotPath,
diff --git a/tests/spa_unit/AndroidManifest.xml b/tests/spa_unit/AndroidManifest.xml
index 51ac1b7..d234b5d 100644
--- a/tests/spa_unit/AndroidManifest.xml
+++ b/tests/spa_unit/AndroidManifest.xml
@@ -19,11 +19,14 @@
           xmlns:tools="http://schemas.android.com/tools"
           package="com.android.settings.tests.spa_unit">
 
+    <uses-permission android:name="android.permission.ACCESS_KEYGUARD_SECURE_STORAGE" />
+    <uses-permission android:name="android.permission.LOG_COMPAT_CHANGE" />
     <uses-permission android:name="android.permission.MANAGE_APPOPS" />
+    <uses-permission android:name="android.permission.MANAGE_NETWORK_POLICY" />
+    <uses-permission android:name="android.permission.READ_COMPAT_CHANGE_CONFIG" />
+    <uses-permission android:name="android.permission.SCHEDULE_EXACT_ALARM" />
     <uses-permission android:name="android.permission.UPDATE_APP_OPS_STATS" />
     <uses-permission android:name="android.permission.WRITE_DEVICE_CONFIG" />
-    <uses-permission android:name="android.permission.READ_COMPAT_CHANGE_CONFIG" />
-    <uses-permission android:name="android.permission.LOG_COMPAT_CHANGE" />
 
     <application android:debuggable="true">
         <provider android:name="com.android.settings.slices.SettingsSliceProvider"
diff --git a/tests/unit/src/com/android/settings/network/SubscriptionUtilTest.java b/tests/unit/src/com/android/settings/network/SubscriptionUtilTest.java
index 3b9ac9d..6c946e5 100644
--- a/tests/unit/src/com/android/settings/network/SubscriptionUtilTest.java
+++ b/tests/unit/src/com/android/settings/network/SubscriptionUtilTest.java
@@ -25,6 +25,7 @@
 import static org.junit.Assert.assertFalse;
 import static org.junit.Assert.assertTrue;
 import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.anyInt;
 import static org.mockito.ArgumentMatchers.anyString;
 import static org.mockito.ArgumentMatchers.eq;
 import static org.mockito.Mockito.mock;
@@ -65,6 +66,9 @@
     private static final CharSequence CARRIER_1 = "carrier1";
     private static final CharSequence CARRIER_1_SPACE = " carrier1       ";
     private static final CharSequence CARRIER_2 = "carrier2";
+    private static final int RAC_CARRIER_ID = 1;
+    private static final int NO_RAC_CARRIER_ID = 2;
+    private static final int[] CARRIERS_THAT_USE_RAC = {RAC_CARRIER_ID};
 
     private Context mContext;
     private NetworkCapabilities mNetworkCapabilities;
@@ -81,6 +85,7 @@
     public void setUp() {
         MockitoAnnotations.initMocks(this);
         mContext = spy(ApplicationProvider.getApplicationContext());
+        when(mContext.getResources()).thenReturn(mResources);
         when(mContext.getSystemService(SubscriptionManager.class)).thenReturn(mSubMgr);
         when(mContext.getSystemService(TelephonyManager.class)).thenReturn(mTelMgr);
         when(mContext.getSystemService(ConnectivityManager.class)).thenReturn(mConnectivityManager);
@@ -109,6 +114,40 @@
         assertThat(subs).hasSize(1);
     }
 
+    @Test
+    public void hasSubscriptionWithRacCarrier_containsRac_returnTrue() {
+        when(mResources.getIntArray(anyInt())).thenReturn(CARRIERS_THAT_USE_RAC);
+        final SubscriptionInfo info = mock(SubscriptionInfo.class);
+        when(info.getCarrierId()).thenReturn(RAC_CARRIER_ID);
+        when(mSubMgr.getAvailableSubscriptionInfoList()).thenReturn(Arrays.asList(info));
+
+        assertTrue(SubscriptionUtil.hasSubscriptionWithRacCarrier(mContext));
+    }
+
+    @Test
+    public void hasSubscriptionWithRacCarrier_doesNotContainsRac_returnFalse() {
+        when(mResources.getIntArray(anyInt())).thenReturn(CARRIERS_THAT_USE_RAC);
+        final SubscriptionInfo info = mock(SubscriptionInfo.class);
+        when(info.getCarrierId()).thenReturn(NO_RAC_CARRIER_ID);
+        when(mSubMgr.getAvailableSubscriptionInfoList()).thenReturn(Arrays.asList(info));
+
+        assertFalse(SubscriptionUtil.hasSubscriptionWithRacCarrier(mContext));
+    }
+
+    @Test
+    public void isCarrierRac_returnTrue() {
+        when(mResources.getIntArray(anyInt())).thenReturn(CARRIERS_THAT_USE_RAC);
+
+        assertTrue(SubscriptionUtil.isCarrierRac(mContext, RAC_CARRIER_ID));
+    }
+
+    @Test
+    public void isCarrierRac_returnFalse() {
+        when(mResources.getIntArray(anyInt())).thenReturn(CARRIERS_THAT_USE_RAC);
+
+        assertFalse(SubscriptionUtil.isCarrierRac(mContext, NO_RAC_CARRIER_ID));
+    }
+
     @Ignore
     @Test
     public void getAvailableSubscriptions_twoSubscriptions_twoResults() {
@@ -526,7 +565,6 @@
 
     @Test
     public void isSimHardwareVisible_configAsInvisible_returnFalse() {
-        when(mContext.getResources()).thenReturn(mResources);
         when(mResources.getBoolean(R.bool.config_show_sim_info))
                 .thenReturn(false);
 
@@ -535,7 +573,6 @@
 
     @Test
     public void isSimHardwareVisible_configAsVisible_returnTrue() {
-        when(mContext.getResources()).thenReturn(mResources);
         when(mResources.getBoolean(R.bool.config_show_sim_info))
                 .thenReturn(true);
 
@@ -599,17 +636,17 @@
     }
 
     @Test
-    public void isConnectedToWifiOrDifferentSubId_hasWiFi_returnTrue() {
+    public void isConnectedToWifi_hasWiFi_returnTrue() {
         addNetworkTransportType(NetworkCapabilities.TRANSPORT_WIFI);
 
-        assertTrue(SubscriptionUtil.isConnectedToWifiOrDifferentSubId(mContext, SUBID_1));
+        assertTrue(SubscriptionUtil.isConnectedToWifi(mContext));
     }
 
     @Test
-    public void isConnectedToWifiOrDifferentSubId_noData_and_noWiFi_returnFalse() {
+    public void isConnectedToWifi_noWiFi_returnFalse() {
         addNetworkTransportType(NetworkCapabilities.TRANSPORT_BLUETOOTH);
 
-        assertFalse(SubscriptionUtil.isConnectedToWifiOrDifferentSubId(mContext, SUBID_1));
+        assertFalse(SubscriptionUtil.isConnectedToWifi(mContext));
     }
 
     private void addNetworkTransportType(int networkType) {
diff --git a/tests/unit/src/com/android/settings/privatespace/HidePrivateSpaceControllerTest.java b/tests/unit/src/com/android/settings/privatespace/HidePrivateSpaceControllerTest.java
deleted file mode 100644
index b71547b..0000000
--- a/tests/unit/src/com/android/settings/privatespace/HidePrivateSpaceControllerTest.java
+++ /dev/null
@@ -1,110 +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.privatespace;
-
-import static com.android.settings.core.BasePreferenceController.AVAILABLE;
-
-import static com.google.common.truth.Truth.assertThat;
-
-import static org.mockito.Mockito.spy;
-
-import android.content.ContentResolver;
-import android.content.Context;
-import android.os.Flags;
-import android.platform.test.annotations.RequiresFlagsEnabled;
-import android.platform.test.flag.junit.CheckFlagsRule;
-import android.platform.test.flag.junit.DeviceFlagsValueProvider;
-import android.provider.Settings;
-
-import androidx.test.core.app.ApplicationProvider;
-import androidx.test.ext.junit.runners.AndroidJUnit4;
-
-import org.junit.After;
-import org.junit.Before;
-import org.junit.Rule;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-
-@RunWith(AndroidJUnit4.class)
-@RequiresFlagsEnabled({Flags.FLAG_ALLOW_PRIVATE_PROFILE,
-        android.multiuser.Flags.FLAG_ENABLE_PRIVATE_SPACE_FEATURES})
-public class HidePrivateSpaceControllerTest {
-    @Rule
-    public final CheckFlagsRule mCheckFlagsRule =
-            DeviceFlagsValueProvider.createCheckFlagsRule();
-
-    private static final String KEY = "private_space_hidden";
-    private static final String DETAIL_PAGE_KEY = "private_space_hidden_details";
-    private Context mContext;
-    private HidePrivateSpaceSummaryController mHidePrivateSpaceSummaryController;
-    private HidePrivateSpaceController mHidePrivateSpaceController;
-    private ContentResolver mContentResolver;
-    private int mOriginalHiddenValue;
-
-    /** Required setup before a test. */
-    @Before
-    public void setUp() {
-        mContext = spy(ApplicationProvider.getApplicationContext());
-        mContentResolver = mContext.getContentResolver();
-        mHidePrivateSpaceSummaryController = new HidePrivateSpaceSummaryController(mContext, KEY);
-        mHidePrivateSpaceController =
-                new HidePrivateSpaceController(mContext, DETAIL_PAGE_KEY);
-        mOriginalHiddenValue = Settings.Secure.getInt(mContentResolver,
-                Settings.Secure.HIDE_PRIVATESPACE_ENTRY_POINT, 0);
-    }
-
-    @After
-    public void tearDown() {
-        Settings.Secure.putInt(mContentResolver, Settings.Secure.HIDE_PRIVATESPACE_ENTRY_POINT,
-                mOriginalHiddenValue);
-    }
-
-    /** Tests that the controller is always available. */
-    @Test
-    public void getAvailabilityStatus_returnsAvailable() {
-        assertThat(mHidePrivateSpaceController.getAvailabilityStatus()).isEqualTo(AVAILABLE);
-    }
-
-    /** Tests that hide preference summary displays On when hide toggle is enabled.*/
-    @Test
-    public void setChecked_enable_shouldDisplayOn() {
-        Settings.Secure.putInt(mContentResolver, Settings.Secure.HIDE_PRIVATESPACE_ENTRY_POINT,
-                0);
-        assertThat(mHidePrivateSpaceController.isChecked()).isFalse();
-
-        mHidePrivateSpaceController.setChecked(true);
-
-        assertThat(mHidePrivateSpaceSummaryController.getSummary().toString())
-                .isEqualTo("On");
-        assertThat(mHidePrivateSpaceController.isChecked()).isTrue();
-    }
-
-    /** Tests that hide preference summary displays Off when toggle is disabled.*/
-    @Test
-    public void setChecked_disable_shouldDisplayOff() {
-        Settings.Secure.putInt(mContentResolver, Settings.Secure.HIDE_PRIVATESPACE_ENTRY_POINT,
-                1);
-
-        assertThat(mHidePrivateSpaceController.isChecked()).isTrue();
-
-        mHidePrivateSpaceController.setChecked(false);
-
-        assertThat(mHidePrivateSpaceSummaryController.getSummary().toString())
-                .isEqualTo("Off");
-        assertThat(mHidePrivateSpaceController.isChecked()).isFalse();
-    }
-}