Merge "Remove volume plus flag in Settings" into main
diff --git a/aconfig/settings_threadnetwork_flag_declarations.aconfig b/aconfig/settings_threadnetwork_flag_declarations.aconfig
new file mode 100644
index 0000000..70945d3
--- /dev/null
+++ b/aconfig/settings_threadnetwork_flag_declarations.aconfig
@@ -0,0 +1,8 @@
+package: "com.android.settings.flags"
+
+flag {
+    name: "thread_settings_enabled"
+    namespace: "thread_network"
+    description: "Controls whether the Thread Settings UX is displayed"
+    bug: "329384658"
+}
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 2f0e1d9..5c98fac 100644
--- a/res/values/strings.xml
+++ b/res/values/strings.xml
@@ -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] -->
@@ -10478,6 +10479,9 @@
     <!-- Summary text for 3-button navigation  [CHAR LIMIT=NONE] -->
     <string name="legacy_navigation_summary">Go back, Home, and switch apps with buttons at the bottom of your screen.</string>
 
+    <!-- Accessibility string for gesture nav tutorial button [CHAR_LIMIT=NONE] -->
+    <string name="nav_tutorial_button_description">Start gesture navigation tutorial</string>
+
     <!-- Search keywords for System Navigation settings. [CHAR_LIMIT=NONE]-->
     <string name="keywords_system_navigation">system navigation, 2 button navigation, 3 button navigation, gesture navigation, swipe</string>
 
@@ -11996,6 +12000,9 @@
     <string name="confirm_format_ext4_text">16K developer option is supported with ext4 filesystem. Device will be wiped and filesystem will be changed to ext4 after confirmation.</string>
     <!-- Toast on failure to reformat data to ext4 -->
     <string name="format_ext4_failure_toast">Failed to reformat and wipe the data partiton to ext4.</string>
+    <!-- Dialog to OEM unlock the device before using 16K developer option -->
+    <string name="confirm_oem_unlock_for_16k_title">OEM unlock required</string>
+    <string name="confirm_oem_unlock_for_16k_text">Device needs to be OEM unlocked before using 16K developer option. OEM unlock will also require formatting userdata. Please OEM unlock the device and try again.</string>
 
     <!-- DSU Loader. Do not translate. -->
 
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/values/themes_suw.xml b/res/values/themes_suw.xml
index 71d9fcb..9efac28 100644
--- a/res/values/themes_suw.xml
+++ b/res/values/themes_suw.xml
@@ -231,7 +231,7 @@
     <style name="SuwAlertDialogThemeCompat" parent="@style/Theme.AppCompat.Dialog.Alert">
         <!-- Referenced SudThemeGlifV3 style -->
         <item name="android:textAllCaps">false</item>
-
+        <item name="android:colorBackground">@android:color/system_neutral1_900</item>
         <item name="android:windowSoftInputMode">adjustResize</item>
         <!-- copied from Theme.DeviceDefault.Dialog.Alert -->
         <item name="colorAccent">@*android:color/accent_device_default_dark</item>
@@ -243,7 +243,7 @@
     <style name="SuwAlertDialogThemeCompat.Light" parent="@style/Theme.AppCompat.Light.Dialog.Alert">
         <!-- Referenced SudThemeGlifV3.Light style -->
         <item name="android:textAllCaps">false</item>
-
+        <item name="android:colorBackground">@android:color/system_neutral1_50</item>
         <item name="android:windowSoftInputMode">adjustResize</item>
         <!-- copied from Theme.DeviceDefault.Light.Dialog.Alert -->
         <item name="colorAccent">@*android:color/accent_device_default_light</item>
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/res/xml/security_lockscreen_settings.xml b/res/xml/security_lockscreen_settings.xml
index cb1ce44..15d5303 100644
--- a/res/xml/security_lockscreen_settings.xml
+++ b/res/xml/security_lockscreen_settings.xml
@@ -69,9 +69,11 @@
             android:summary="@string/lockscreen_trivial_controls_summary"
             settings:controller="com.android.settings.display.ControlsTrivialPrivacyPreferenceController"/>
 
+        <!-- Shortcuts -->
         <Preference
             android:key="customizable_lock_screen_quick_affordances"
             android:title="@string/lockscreen_quick_affordances_title"
+            android:summary="@string/summary_placeholder"
             settings:controller="com.android.settings.display.CustomizableLockScreenQuickAffordancesPreferenceController" />
 
         <SwitchPreferenceCompat
diff --git a/res/xml/wifi_network_details_fragment2.xml b/res/xml/wifi_network_details_fragment2.xml
index 598f9d8..eacff88 100644
--- a/res/xml/wifi_network_details_fragment2.xml
+++ b/res/xml/wifi_network_details_fragment2.xml
@@ -112,6 +112,10 @@
         android:title="@string/wifi_auto_connect_title"
         android:summary="@string/wifi_auto_connect_summary"/>
 
+    <com.android.settings.spa.preference.ComposePreference
+        android:key="certificate_details"
+        settings:controller="com.android.settings.wifi.details2.CertificateDetailsPreferenceController"/>
+
     <!-- Add device Preference -->
     <Preference
         android:key="add_device_to_network"
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/accessibility/AccessibilitySettings.java b/src/com/android/settings/accessibility/AccessibilitySettings.java
index fe89bf2..35fe6e4 100644
--- a/src/com/android/settings/accessibility/AccessibilitySettings.java
+++ b/src/com/android/settings/accessibility/AccessibilitySettings.java
@@ -175,6 +175,9 @@
         // Observe changes from accessibility selection menu
         shortcutFeatureKeys.add(Settings.Secure.ACCESSIBILITY_BUTTON_TARGETS);
         shortcutFeatureKeys.add(Settings.Secure.ACCESSIBILITY_SHORTCUT_TARGET_SERVICE);
+        if (android.view.accessibility.Flags.a11yQsShortcut()) {
+            shortcutFeatureKeys.add(Settings.Secure.ACCESSIBILITY_QS_TARGETS);
+        }
         shortcutFeatureKeys.add(Settings.Secure.ACCESSIBILITY_STICKY_KEYS);
         shortcutFeatureKeys.add(Settings.Secure.ACCESSIBILITY_SLOW_KEYS);
         shortcutFeatureKeys.add(Settings.Secure.ACCESSIBILITY_BOUNCE_KEYS);
diff --git a/src/com/android/settings/accessibility/AccessibilityShortcutPreferenceFragment.java b/src/com/android/settings/accessibility/AccessibilityShortcutPreferenceFragment.java
index 8af284d..41c5d75 100644
--- a/src/com/android/settings/accessibility/AccessibilityShortcutPreferenceFragment.java
+++ b/src/com/android/settings/accessibility/AccessibilityShortcutPreferenceFragment.java
@@ -125,6 +125,9 @@
         final List<String> shortcutFeatureKeys = new ArrayList<>();
         shortcutFeatureKeys.add(Settings.Secure.ACCESSIBILITY_BUTTON_TARGETS);
         shortcutFeatureKeys.add(Settings.Secure.ACCESSIBILITY_SHORTCUT_TARGET_SERVICE);
+        if (android.view.accessibility.Flags.a11yQsShortcut()) {
+            shortcutFeatureKeys.add(Settings.Secure.ACCESSIBILITY_QS_TARGETS);
+        }
         mSettingsContentObserver = new AccessibilitySettingsContentObserver(new Handler());
         mSettingsContentObserver.registerKeysToObserverCallback(shortcutFeatureKeys, key -> {
             updateShortcutPreferenceData();
diff --git a/src/com/android/settings/accessibility/ColorAndMotionFragment.java b/src/com/android/settings/accessibility/ColorAndMotionFragment.java
index 28c5335..4ea2226 100644
--- a/src/com/android/settings/accessibility/ColorAndMotionFragment.java
+++ b/src/com/android/settings/accessibility/ColorAndMotionFragment.java
@@ -74,6 +74,9 @@
         mShortcutFeatureKeys.add(Settings.Secure.ACCESSIBILITY_DISPLAY_DALTONIZER_ENABLED);
         mShortcutFeatureKeys.add(Settings.Secure.ACCESSIBILITY_SHORTCUT_TARGET_SERVICE);
         mShortcutFeatureKeys.add(Settings.Secure.ACCESSIBILITY_BUTTON_TARGETS);
+        if (android.view.accessibility.Flags.a11yQsShortcut()) {
+            mShortcutFeatureKeys.add(Settings.Secure.ACCESSIBILITY_QS_TARGETS);
+        }
         if (Flags.forceInvertColor()) {
             mShortcutFeatureKeys.add(ToggleForceInvertPreferenceController.SETTINGS_KEY);
         }
diff --git a/src/com/android/settings/accessibility/HearingDevicePairingFragment.java b/src/com/android/settings/accessibility/HearingDevicePairingFragment.java
index 0b762f3..c797559 100644
--- a/src/com/android/settings/accessibility/HearingDevicePairingFragment.java
+++ b/src/com/android/settings/accessibility/HearingDevicePairingFragment.java
@@ -192,7 +192,7 @@
     public void onDeviceBondStateChanged(@NonNull CachedBluetoothDevice cachedDevice,
             int bondState) {
         if (DEBUG) {
-            Log.d(TAG, "onDeviceBondStateChanged: " + cachedDevice.getDevice() + ", state = "
+            Log.d(TAG, "onDeviceBondStateChanged: " + cachedDevice + ", state = "
                     + bondState);
         }
         if (bondState == BluetoothDevice.BOND_BONDED) {
@@ -276,13 +276,13 @@
         }
         mDevicePreferenceMap.put(cachedDevice, preference);
         if (DEBUG) {
-            Log.d(TAG, "Add device. device: " + cachedDevice.getDevice());
+            Log.d(TAG, "Add device. device: " + cachedDevice);
         }
     }
 
     void removeDevice(CachedBluetoothDevice cachedDevice) {
         if (DEBUG) {
-            Log.d(TAG, "removeDevice: " + cachedDevice.getDevice());
+            Log.d(TAG, "removeDevice: " + cachedDevice);
         }
         BluetoothDevicePreference preference = mDevicePreferenceMap.remove(cachedDevice);
         if (mAvailableHearingDeviceGroup != null && preference != null) {
@@ -331,13 +331,13 @@
             cachedDevice = mCachedDeviceManager.addDevice(device);
         } else if (cachedDevice.getBondState() == BluetoothDevice.BOND_BONDED) {
             if (DEBUG) {
-                Log.d(TAG, "Skip this device, already bonded: " + cachedDevice.getDevice());
+                Log.d(TAG, "Skip this device, already bonded: " + cachedDevice);
             }
             return;
         }
         if (cachedDevice.getHearingAidInfo() == null) {
             if (DEBUG) {
-                Log.d(TAG, "Set hearing aid info on device: " + cachedDevice.getDevice());
+                Log.d(TAG, "Set hearing aid info on device: " + cachedDevice);
             }
             cachedDevice.setHearingAidInfo(new HearingAidInfo.Builder().build());
         }
@@ -455,7 +455,7 @@
 
     void discoverServices(CachedBluetoothDevice cachedDevice) {
         if (DEBUG) {
-            Log.d(TAG, "connectGattToCheckCompatibility, device: " + cachedDevice.getDevice());
+            Log.d(TAG, "connectGattToCheckCompatibility, device: " + cachedDevice);
         }
         BluetoothGatt gatt = cachedDevice.getDevice().connectGatt(getContext(), false,
                 new BluetoothGattCallback() {
@@ -465,7 +465,7 @@
                         super.onConnectionStateChange(gatt, status, newState);
                         if (DEBUG) {
                             Log.d(TAG, "onConnectionStateChange, status: " + status + ", newState: "
-                                    + newState + ", device: " + cachedDevice.getDevice());
+                                    + newState + ", device: " + cachedDevice);
                         }
                         if (status == GATT_SUCCESS
                                 && newState == BluetoothProfile.STATE_CONNECTED) {
@@ -481,14 +481,14 @@
                         super.onServicesDiscovered(gatt, status);
                         if (DEBUG) {
                             Log.d(TAG, "onServicesDiscovered, status: " + status + ", device: "
-                                    + cachedDevice.getDevice());
+                                    + cachedDevice);
                         }
                         if (status == GATT_SUCCESS) {
                             if (gatt.getService(BluetoothUuid.HEARING_AID.getUuid()) != null
                                     || gatt.getService(BluetoothUuid.HAS.getUuid()) != null) {
                                 if (DEBUG) {
                                     Log.d(TAG, "compatible with Android, device: "
-                                            + cachedDevice.getDevice());
+                                            + cachedDevice);
                                 }
                                 addDevice(cachedDevice);
                             }
diff --git a/src/com/android/settings/accessibility/KeyboardVibrationTogglePreferenceController.java b/src/com/android/settings/accessibility/KeyboardVibrationTogglePreferenceController.java
index 58aa0cc..21800b9 100644
--- a/src/com/android/settings/accessibility/KeyboardVibrationTogglePreferenceController.java
+++ b/src/com/android/settings/accessibility/KeyboardVibrationTogglePreferenceController.java
@@ -22,6 +22,7 @@
 import static com.android.settings.accessibility.AccessibilityUtil.State.ON;
 
 import android.app.settings.SettingsEnums;
+import android.content.ContentResolver;
 import android.content.Context;
 import android.database.ContentObserver;
 import android.net.Uri;
@@ -159,8 +160,11 @@
     }
 
     private boolean updateKeyboardVibrationSetting(boolean enable) {
-        final boolean success = Settings.System.putInt(mContext.getContentResolver(),
-                    KEYBOARD_VIBRATION_ENABLED, enable ? ON : OFF);
+        final ContentResolver contentResolver = mContext.getContentResolver();
+        final boolean success = Settings.System.putInt(contentResolver,
+                KEYBOARD_VIBRATION_ENABLED, enable ? ON : OFF);
+        contentResolver.notifyChange(Settings.System.getUriFor(KEYBOARD_VIBRATION_ENABLED),
+                null /* observer */, ContentResolver.NOTIFY_NO_DELAY);
         if (!success) {
             Log.w(TAG, "Update settings database error!");
         }
diff --git a/src/com/android/settings/accessibility/ToggleFeaturePreferenceFragment.java b/src/com/android/settings/accessibility/ToggleFeaturePreferenceFragment.java
index 6d5f536..ed47007 100644
--- a/src/com/android/settings/accessibility/ToggleFeaturePreferenceFragment.java
+++ b/src/com/android/settings/accessibility/ToggleFeaturePreferenceFragment.java
@@ -179,6 +179,9 @@
         final List<String> shortcutFeatureKeys = new ArrayList<>();
         shortcutFeatureKeys.add(Settings.Secure.ACCESSIBILITY_BUTTON_TARGETS);
         shortcutFeatureKeys.add(Settings.Secure.ACCESSIBILITY_SHORTCUT_TARGET_SERVICE);
+        if (android.view.accessibility.Flags.a11yQsShortcut()) {
+            shortcutFeatureKeys.add(Settings.Secure.ACCESSIBILITY_QS_TARGETS);
+        }
         return shortcutFeatureKeys;
     }
 
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/connecteddevice/threadnetwork/ThreadNetworkPreferenceController.kt b/src/com/android/settings/connecteddevice/threadnetwork/ThreadNetworkPreferenceController.kt
index f5c0a87..1c01750 100644
--- a/src/com/android/settings/connecteddevice/threadnetwork/ThreadNetworkPreferenceController.kt
+++ b/src/com/android/settings/connecteddevice/threadnetwork/ThreadNetworkPreferenceController.kt
@@ -34,9 +34,9 @@
 import androidx.lifecycle.LifecycleOwner
 import androidx.preference.Preference
 import androidx.preference.PreferenceScreen
-import com.android.net.thread.platform.flags.Flags
 import com.android.settings.R
 import com.android.settings.core.TogglePreferenceController
+import com.android.settings.flags.Flags
 import java.util.concurrent.Executor
 
 /** Controller for the "Thread" toggle in "Connected devices > Connection preferences".  */
@@ -110,7 +110,7 @@
     }
 
     override fun getAvailabilityStatus(): Int {
-        return if (!Flags.threadEnabledPlatform()) {
+        return if (!Flags.threadSettingsEnabled()) {
             CONDITIONALLY_UNAVAILABLE
         } else if (!isThreadSupportedOnDevice) {
             UNSUPPORTED_ON_DEVICE
diff --git a/src/com/android/settings/development/Enable16KOemUnlockDialog.java b/src/com/android/settings/development/Enable16KOemUnlockDialog.java
new file mode 100644
index 0000000..65690df
--- /dev/null
+++ b/src/com/android/settings/development/Enable16KOemUnlockDialog.java
@@ -0,0 +1,77 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.settings.development;
+
+import android.app.Dialog;
+import android.app.settings.SettingsEnums;
+import android.content.DialogInterface;
+import android.os.Bundle;
+
+import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
+import androidx.appcompat.app.AlertDialog;
+import androidx.fragment.app.Fragment;
+import androidx.fragment.app.FragmentManager;
+
+import com.android.settings.R;
+import com.android.settings.core.instrumentation.InstrumentedDialogFragment;
+
+/** Dialog when user interacts 16K pages developer option and device is not OEM unlocked */
+public class Enable16KOemUnlockDialog extends InstrumentedDialogFragment
+        implements DialogInterface.OnClickListener, DialogInterface.OnDismissListener {
+
+    public static final String TAG = "Enable16KOemUnlockDialog";
+
+    /** This method is used to prompt user to do OEM unlock before using 16k */
+    public static void show(@NonNull Fragment hostFragment) {
+        final FragmentManager manager = hostFragment.getActivity().getSupportFragmentManager();
+        Fragment existingFragment = manager.findFragmentByTag(TAG);
+        if (existingFragment == null) {
+            existingFragment = new Enable16KOemUnlockDialog();
+        }
+
+        if (existingFragment instanceof Enable16KOemUnlockDialog) {
+            existingFragment.setTargetFragment(hostFragment, 0 /* requestCode */);
+            ((Enable16KOemUnlockDialog) existingFragment).show(manager, TAG);
+        }
+    }
+
+    @Override
+    public int getMetricsCategory() {
+        return SettingsEnums.DIALOG_ENABLE_16K_PAGES;
+    }
+
+    @NonNull
+    @Override
+    public Dialog onCreateDialog(@Nullable Bundle savedInstanceState) {
+        return new AlertDialog.Builder(getActivity())
+                .setTitle(R.string.confirm_oem_unlock_for_16k_title)
+                .setMessage(R.string.confirm_oem_unlock_for_16k_text)
+                .setPositiveButton(android.R.string.ok, this /* onClickListener */)
+                .create();
+    }
+
+    @Override
+    public void onClick(@NonNull DialogInterface dialog, int buttonId) {
+        // Do nothing. OEM unlock has to be done by user
+    }
+
+    @Override
+    public void onDismiss(@NonNull DialogInterface dialog) {
+        super.onDismiss(dialog);
+    }
+}
diff --git a/src/com/android/settings/development/Enable16kPagesPreferenceController.java b/src/com/android/settings/development/Enable16kPagesPreferenceController.java
index 7049e79..bed5c04 100644
--- a/src/com/android/settings/development/Enable16kPagesPreferenceController.java
+++ b/src/com/android/settings/development/Enable16kPagesPreferenceController.java
@@ -28,7 +28,10 @@
 import android.os.UpdateEngine;
 import android.os.UpdateEngineStable;
 import android.os.UpdateEngineStableCallback;
+import android.os.UserHandle;
+import android.os.UserManager;
 import android.provider.Settings;
+import android.service.oemlock.OemLockManager;
 import android.util.Log;
 import android.widget.LinearLayout;
 import android.widget.ProgressBar;
@@ -116,6 +119,12 @@
     @Override
     public boolean onPreferenceChange(Preference preference, Object newValue) {
         mEnable16k = (Boolean) newValue;
+        // Prompt user to do oem unlock first
+        if (!isDeviceOEMUnlocked()) {
+            Enable16KOemUnlockDialog.show(mFragment);
+            return false;
+        }
+
         if (isDataf2fs()) {
             EnableExt4WarningDialog.show(mFragment, this);
             return false;
@@ -418,4 +427,30 @@
 
         return false;
     }
+
+    private boolean isDeviceOEMUnlocked() {
+        // OEM unlock is checked for bootloader, carrier and user. Check all three to ensure
+        // that device is unlocked and it is also allowed by user as well as carrier
+        final OemLockManager oemLockManager = mContext.getSystemService(OemLockManager.class);
+        final UserManager userManager = mContext.getSystemService(UserManager.class);
+        if (oemLockManager == null || userManager == null) {
+            Log.e(TAG, "Required services not found on device to check for OEM unlock state.");
+            return false;
+        }
+
+        // If either of device or carrier is not allowed to unlock, return false
+        if (!oemLockManager.isDeviceOemUnlocked()
+                || !oemLockManager.isOemUnlockAllowedByCarrier()) {
+            Log.e(TAG, "Device is not OEM unlocked or it is not allowed by carrier");
+            return false;
+        }
+
+        final UserHandle userHandle = UserHandle.of(UserHandle.myUserId());
+        if (userManager.hasBaseUserRestriction(UserManager.DISALLOW_FACTORY_RESET, userHandle)) {
+            Log.e(TAG, "Factory reset is not allowed for user.");
+            return false;
+        }
+
+        return true;
+    }
 }
diff --git a/src/com/android/settings/gestures/OneHandedSettingsUtils.java b/src/com/android/settings/gestures/OneHandedSettingsUtils.java
index 04898dc..fe7db4f 100644
--- a/src/com/android/settings/gestures/OneHandedSettingsUtils.java
+++ b/src/com/android/settings/gestures/OneHandedSettingsUtils.java
@@ -50,6 +50,8 @@
             Settings.Secure.getUriFor(Settings.Secure.ACCESSIBILITY_BUTTON_TARGETS);
     static final Uri HARDWARE_SHORTCUT_ENABLED_URI =
             Settings.Secure.getUriFor(Settings.Secure.ACCESSIBILITY_SHORTCUT_TARGET_SERVICE);
+    static final Uri QS_SHORTCUT_ENABLED_URI =
+            Settings.Secure.getUriFor(Settings.Secure.ACCESSIBILITY_QS_TARGETS);
 
     public enum OneHandedTimeout {
         NEVER(0), SHORT(4), MEDIUM(8), LONG(12);
@@ -254,6 +256,16 @@
         if (!TextUtils.isEmpty(targetsHW) && targetsHW.contains(ONE_HANDED_MODE_TARGET_NAME)) {
             return true;
         }
+
+        if (android.view.accessibility.Flags.a11yQsShortcut()) {
+            // Checks QS_SHORTCUT_KEY
+            final String targetsQs = Settings.Secure.getStringForUser(context.getContentResolver(),
+                    Settings.Secure.ACCESSIBILITY_QS_TARGETS, sCurrentUserId);
+            if (!TextUtils.isEmpty(targetsQs) && targetsQs.contains(ONE_HANDED_MODE_TARGET_NAME)) {
+                return true;
+            }
+        }
+
         return false;
     }
 
@@ -301,6 +313,9 @@
             resolver.registerContentObserver(SHOW_NOTIFICATION_ENABLED_URI, true, this);
             resolver.registerContentObserver(SOFTWARE_SHORTCUT_ENABLED_URI, true, this);
             resolver.registerContentObserver(HARDWARE_SHORTCUT_ENABLED_URI, true, this);
+            if (android.view.accessibility.Flags.a11yQsShortcut()) {
+                resolver.registerContentObserver(QS_SHORTCUT_ENABLED_URI, true, this);
+            }
         }
 
         @Override
diff --git a/src/com/android/settings/gestures/SystemNavigationGestureSettings.java b/src/com/android/settings/gestures/SystemNavigationGestureSettings.java
index c40212b..c38be94 100644
--- a/src/com/android/settings/gestures/SystemNavigationGestureSettings.java
+++ b/src/com/android/settings/gestures/SystemNavigationGestureSettings.java
@@ -247,6 +247,7 @@
         switch (systemNavKey) {
             case KEY_SYSTEM_NAV_GESTURAL:
                 if (isGestureTutorialAvailable()){
+                    videoPref.setContentDescription(R.string.nav_tutorial_button_description);
                     videoPref.setOnPreferenceClickListener(preference -> {
                         startActivity(mLaunchSandboxIntent);
                         return true;
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/network/telephony/MobileNetworkEidPreferenceController.kt b/src/com/android/settings/network/telephony/MobileNetworkEidPreferenceController.kt
index 907bab1..1e635a5 100644
--- a/src/com/android/settings/network/telephony/MobileNetworkEidPreferenceController.kt
+++ b/src/com/android/settings/network/telephony/MobileNetworkEidPreferenceController.kt
@@ -84,6 +84,13 @@
     }
 
     override fun onViewCreated(viewLifecycleOwner: LifecycleOwner) {
+        if (!this::lazyViewModel.isInitialized) {
+            Log.e(
+                this.javaClass.simpleName,
+                "lateinit property lazyViewModel has not been initialized"
+            )
+            return
+        }
         preference.isVisible = false
 
         val viewModel by lazyViewModel
diff --git a/src/com/android/settings/network/telephony/MobileNetworkImeiPreferenceController.kt b/src/com/android/settings/network/telephony/MobileNetworkImeiPreferenceController.kt
index 8ec313b..e134681 100644
--- a/src/com/android/settings/network/telephony/MobileNetworkImeiPreferenceController.kt
+++ b/src/com/android/settings/network/telephony/MobileNetworkImeiPreferenceController.kt
@@ -78,6 +78,13 @@
     }
 
     override fun onViewCreated(viewLifecycleOwner: LifecycleOwner) {
+        if (!this::lazyViewModel.isInitialized) {
+            Log.e(
+                this.javaClass.simpleName,
+                "lateinit property lazyViewModel has not been initialized"
+            )
+            return
+        }
         val viewModel by lazyViewModel
         val coroutineScope = viewLifecycleOwner.lifecycleScope
 
diff --git a/src/com/android/settings/network/telephony/MobileNetworkPhoneNumberPreferenceController.kt b/src/com/android/settings/network/telephony/MobileNetworkPhoneNumberPreferenceController.kt
index 65a4b7e..10a8b53 100644
--- a/src/com/android/settings/network/telephony/MobileNetworkPhoneNumberPreferenceController.kt
+++ b/src/com/android/settings/network/telephony/MobileNetworkPhoneNumberPreferenceController.kt
@@ -19,6 +19,7 @@
 import android.content.Context
 import android.telephony.SubscriptionInfo
 import android.telephony.SubscriptionManager
+import android.util.Log
 import androidx.annotation.VisibleForTesting
 import androidx.fragment.app.Fragment
 import androidx.fragment.app.viewModels
@@ -66,6 +67,13 @@
     }
 
     override fun onViewCreated(viewLifecycleOwner: LifecycleOwner) {
+        if (!this::lazyViewModel.isInitialized) {
+            Log.e(
+                this.javaClass.simpleName,
+                "lateinit property lazyViewModel has not been initialized"
+            )
+            return
+        }
         val viewModel by lazyViewModel
         val coroutineScope = viewLifecycleOwner.lifecycleScope
 
diff --git a/src/com/android/settings/network/telephony/MobileNetworkSpnPreferenceController.kt b/src/com/android/settings/network/telephony/MobileNetworkSpnPreferenceController.kt
index ac055b0..4736eb7 100644
--- a/src/com/android/settings/network/telephony/MobileNetworkSpnPreferenceController.kt
+++ b/src/com/android/settings/network/telephony/MobileNetworkSpnPreferenceController.kt
@@ -19,6 +19,7 @@
 import android.content.Context
 import android.telephony.SubscriptionInfo
 import android.telephony.SubscriptionManager
+import android.util.Log
 import androidx.annotation.VisibleForTesting
 import androidx.fragment.app.Fragment
 import androidx.fragment.app.viewModels
@@ -26,6 +27,7 @@
 import androidx.preference.Preference
 import androidx.preference.PreferenceScreen
 import com.android.settings.flags.Flags
+import com.android.settings.network.SimOnboardingActivity
 import com.android.settings.network.SubscriptionInfoListViewModel
 import com.android.settingslib.spa.framework.util.collectLatestWithLifecycle
 
@@ -57,6 +59,14 @@
     }
 
     override fun onViewCreated(viewLifecycleOwner: LifecycleOwner) {
+        if (!this::lazyViewModel.isInitialized) {
+            Log.e(
+                this.javaClass.simpleName,
+                "lateinit property lazyViewModel has not been initialized"
+            )
+            return
+        }
+
         val viewModel by lazyViewModel
 
         viewModel.subscriptionInfoListFlow
diff --git a/src/com/android/settings/network/telephony/NetworkSelectRepository.kt b/src/com/android/settings/network/telephony/NetworkSelectRepository.kt
new file mode 100644
index 0000000..1f5fbc2
--- /dev/null
+++ b/src/com/android/settings/network/telephony/NetworkSelectRepository.kt
@@ -0,0 +1,75 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.settings.network.telephony
+
+import android.content.Context
+import android.telephony.AccessNetworkConstants
+import android.telephony.NetworkRegistrationInfo
+import android.telephony.TelephonyManager
+import androidx.lifecycle.Lifecycle
+import androidx.lifecycle.LifecycleOwner
+import androidx.lifecycle.lifecycleScope
+import androidx.lifecycle.repeatOnLifecycle
+import kotlinx.coroutines.Dispatchers
+import kotlinx.coroutines.launch
+import kotlinx.coroutines.withContext
+
+class NetworkSelectRepository(context: Context, subId: Int) {
+    private val telephonyManager =
+        context.getSystemService(TelephonyManager::class.java)!!.createForSubscriptionId(subId)
+
+    data class NetworkRegistrationAndForbiddenInfo(
+        val networkList: List<NetworkRegistrationInfo>,
+        val forbiddenPlmns: List<String>,
+    )
+
+    /** TODO: Move this to UI layer, when UI layer migrated to Kotlin. */
+    fun launchUpdateNetworkRegistrationInfo(
+        lifecycleOwner: LifecycleOwner,
+        action: (NetworkRegistrationAndForbiddenInfo) -> Unit,
+    ) {
+        lifecycleOwner.lifecycleScope.launch {
+            lifecycleOwner.repeatOnLifecycle(Lifecycle.State.STARTED) {
+                withContext(Dispatchers.Default) {
+                    getNetworkRegistrationInfo()
+                }?.let(action)
+            }
+        }
+    }
+
+    fun getNetworkRegistrationInfo(): NetworkRegistrationAndForbiddenInfo? {
+        if (telephonyManager.dataState != TelephonyManager.DATA_CONNECTED) return null
+        // Try to get the network registration states
+        val serviceState = telephonyManager.serviceState ?: return null
+        val networkList = serviceState.getNetworkRegistrationInfoListForTransportType(
+            AccessNetworkConstants.TRANSPORT_TYPE_WWAN
+        )
+        if (networkList.isEmpty()) return null
+        // Due to the aggregation of cell between carriers, it's possible to get CellIdentity
+        // containing forbidden PLMN.
+        // Getting current network from ServiceState is no longer a good idea.
+        // Add an additional rule to avoid from showing forbidden PLMN to the user.
+        return NetworkRegistrationAndForbiddenInfo(networkList, getForbiddenPlmns())
+    }
+
+    /**
+     * Update forbidden PLMNs from the USIM App
+     */
+    private fun getForbiddenPlmns(): List<String> {
+        return telephonyManager.forbiddenPlmns?.toList() ?: emptyList()
+    }
+}
diff --git a/src/com/android/settings/network/telephony/NetworkSelectSettings.java b/src/com/android/settings/network/telephony/NetworkSelectSettings.java
index eb89d9e..19bc390 100644
--- a/src/com/android/settings/network/telephony/NetworkSelectSettings.java
+++ b/src/com/android/settings/network/telephony/NetworkSelectSettings.java
@@ -24,12 +24,10 @@
 import android.os.Message;
 import android.os.PersistableBundle;
 import android.provider.Settings;
-import android.telephony.AccessNetworkConstants;
 import android.telephony.CarrierConfigManager;
 import android.telephony.CellIdentity;
 import android.telephony.CellInfo;
 import android.telephony.NetworkRegistrationInfo;
-import android.telephony.ServiceState;
 import android.telephony.SignalStrength;
 import android.telephony.SubscriptionManager;
 import android.telephony.TelephonyManager;
@@ -52,13 +50,11 @@
 import com.android.settings.network.telephony.scan.NetworkScanRepository.NetworkScanCellInfos;
 import com.android.settings.network.telephony.scan.NetworkScanRepository.NetworkScanComplete;
 import com.android.settings.network.telephony.scan.NetworkScanRepository.NetworkScanError;
-import com.android.settings.network.telephony.scan.NetworkScanRepository.NetworkScanResult;
 import com.android.settings.overlay.FeatureFactory;
 import com.android.settingslib.core.instrumentation.MetricsFeatureProvider;
 import com.android.settingslib.utils.ThreadUtils;
 
 import kotlin.Unit;
-import kotlin.jvm.functions.Function1;
 
 import java.util.ArrayList;
 import java.util.Arrays;
@@ -101,6 +97,8 @@
     private NetworkScanRepository mNetworkScanRepository;
     private boolean mUpdateScanResult = false;
 
+    private NetworkSelectRepository mNetworkSelectRepository;
+
     @Override
     public void onCreate(Bundle icicle) {
         super.onCreate(icicle);
@@ -138,6 +136,7 @@
         mCarrierConfigManager.registerCarrierConfigChangeListener(mNetworkScanExecutor,
                 mCarrierConfigChangeListener);
         mNetworkScanRepository = new NetworkScanRepository(context, mSubId);
+        mNetworkSelectRepository = new NetworkSelectRepository(context, mSubId);
     }
 
     @Keep
@@ -202,35 +201,37 @@
         mProgressHeader = setPinnedHeaderView(
                 com.android.settingslib.widget.progressbar.R.layout.progress_header
         ).findViewById(com.android.settingslib.widget.progressbar.R.id.progress_bar_animation);
-        forceUpdateConnectedPreferenceCategory();
+        mNetworkSelectRepository.launchUpdateNetworkRegistrationInfo(
+                getViewLifecycleOwner(),
+                (info) -> {
+                    forceUpdateConnectedPreferenceCategory(info);
+                    return Unit.INSTANCE;
+                });
         launchNetworkScan();
     }
 
     private void launchNetworkScan() {
-        mNetworkScanRepository.launchNetworkScan(getViewLifecycleOwner(), new Function1<>() {
-            @Override
-            public Unit invoke(@NonNull NetworkScanResult networkScanResult) {
-                if (!mUpdateScanResult) {
-                    // Not update UI if not in scan mode.
-                    return Unit.INSTANCE;
-                }
-                if (networkScanResult instanceof NetworkScanCellInfos networkScanCellInfos) {
-                    scanResultHandler(networkScanCellInfos.getCellInfos());
-                    return Unit.INSTANCE;
-                }
-                if (!isPreferenceScreenEnabled()) {
-                    clearPreferenceSummary();
-                    enablePreferenceScreen(true);
-                } else if (networkScanResult instanceof NetworkScanComplete
-                        && mCellInfoList == null) {
-                    // In case the scan timeout before getting any results
-                    addMessagePreference(R.string.empty_networks_list);
-                } else if (networkScanResult instanceof NetworkScanError) {
-                    addMessagePreference(R.string.network_query_error);
-                }
-
+        mNetworkScanRepository.launchNetworkScan(getViewLifecycleOwner(), (networkScanResult) -> {
+            if (!mUpdateScanResult) {
+                // Not update UI if not in scan mode.
                 return Unit.INSTANCE;
             }
+            if (networkScanResult instanceof NetworkScanCellInfos networkScanCellInfos) {
+                scanResultHandler(networkScanCellInfos.getCellInfos());
+                return Unit.INSTANCE;
+            }
+            if (!isPreferenceScreenEnabled()) {
+                clearPreferenceSummary();
+                enablePreferenceScreen(true);
+            } else if (networkScanResult instanceof NetworkScanComplete
+                    && mCellInfoList == null) {
+                // In case the scan timeout before getting any results
+                addMessagePreference(R.string.empty_networks_list);
+            } else if (networkScanResult instanceof NetworkScanError) {
+                addMessagePreference(R.string.network_query_error);
+            }
+
+            return Unit.INSTANCE;
         });
     }
 
@@ -238,7 +239,6 @@
     public void onStart() {
         super.onStart();
 
-        updateForbiddenPlmns();
         setProgressBarVisible(true);
         mUpdateScanResult = true;
     }
@@ -477,45 +477,26 @@
      * - If the device has no data, we will remove the connected network operators list from the
      * screen.
      */
-    private void forceUpdateConnectedPreferenceCategory() {
-        if (mTelephonyManager.getDataState() == mTelephonyManager.DATA_CONNECTED) {
-            // Try to get the network registration states
-            final ServiceState ss = mTelephonyManager.getServiceState();
-            if (ss == null) {
-                return;
+    private void forceUpdateConnectedPreferenceCategory(
+            NetworkSelectRepository.NetworkRegistrationAndForbiddenInfo info) {
+        for (NetworkRegistrationInfo regInfo : info.getNetworkList()) {
+            final CellIdentity cellIdentity = regInfo.getCellIdentity();
+            if (cellIdentity == null) {
+                continue;
             }
-            final List<NetworkRegistrationInfo> networkList =
-                    ss.getNetworkRegistrationInfoListForTransportType(
-                            AccessNetworkConstants.TRANSPORT_TYPE_WWAN);
-            if (networkList == null || networkList.size() == 0) {
-                return;
+            final NetworkOperatorPreference pref = new NetworkOperatorPreference(
+                    getPrefContext(), info.getForbiddenPlmns(), mShow4GForLTE);
+            pref.updateCell(null, cellIdentity);
+            if (pref.isForbiddenNetwork()) {
+                continue;
             }
-            // Due to the aggregation of cell between carriers, it's possible to get CellIdentity
-            // containing forbidden PLMN.
-            // Getting current network from ServiceState is no longer a good idea.
-            // Add an additional rule to avoid from showing forbidden PLMN to the user.
-            if (mForbiddenPlmns == null) {
-                updateForbiddenPlmns();
-            }
-            for (NetworkRegistrationInfo regInfo : networkList) {
-                final CellIdentity cellIdentity = regInfo.getCellIdentity();
-                if (cellIdentity == null) {
-                    continue;
-                }
-                final NetworkOperatorPreference pref = new NetworkOperatorPreference(
-                        getPrefContext(), mForbiddenPlmns, mShow4GForLTE);
-                pref.updateCell(null, cellIdentity);
-                if (pref.isForbiddenNetwork()) {
-                    continue;
-                }
-                pref.setSummary(R.string.network_connected);
-                // Update the signal strength icon, since the default signalStrength value
-                // would be zero
-                // (it would be quite confusing why the connected network has no signal)
-                pref.setIcon(SignalStrength.NUM_SIGNAL_STRENGTH_BINS - 1);
-                mPreferenceCategory.addPreference(pref);
-                break;
-            }
+            pref.setSummary(R.string.network_connected);
+            // Update the signal strength icon, since the default signalStrength value
+            // would be zero
+            // (it would be quite confusing why the connected network has no signal)
+            pref.setIcon(SignalStrength.NUM_SIGNAL_STRENGTH_BINS - 1);
+            mPreferenceCategory.addPreference(pref);
+            break;
         }
     }
 
diff --git a/src/com/android/settings/network/telephony/WifiCallingPreferenceController.kt b/src/com/android/settings/network/telephony/WifiCallingPreferenceController.kt
index 0ee1d87..f184092 100644
--- a/src/com/android/settings/network/telephony/WifiCallingPreferenceController.kt
+++ b/src/com/android/settings/network/telephony/WifiCallingPreferenceController.kt
@@ -22,6 +22,7 @@
 import android.telephony.SubscriptionManager
 import android.telephony.TelephonyManager
 import android.telephony.ims.ImsMmTelManager
+import android.util.Log
 import androidx.lifecycle.LifecycleOwner
 import androidx.preference.Preference
 import androidx.preference.PreferenceScreen
@@ -76,6 +77,13 @@
     }
 
     override fun onViewCreated(viewLifecycleOwner: LifecycleOwner) {
+        if(mSubId == SubscriptionManager.INVALID_SUBSCRIPTION_ID){
+            Log.e(
+                this.javaClass.simpleName,
+                "mSubId is INVALID_SUBSCRIPTION_ID"
+            )
+            return
+        }
         wifiCallingRepositoryFactory(mSubId).wifiCallingReadyFlow()
             .collectLatestWithLifecycle(viewLifecycleOwner) { isReady ->
                 preference.isVisible = isReady
diff --git a/src/com/android/settings/network/telephony/gsm/AutoSelectPreferenceController.kt b/src/com/android/settings/network/telephony/gsm/AutoSelectPreferenceController.kt
index d709574..67a2356 100644
--- a/src/com/android/settings/network/telephony/gsm/AutoSelectPreferenceController.kt
+++ b/src/com/android/settings/network/telephony/gsm/AutoSelectPreferenceController.kt
@@ -23,6 +23,7 @@
 import android.provider.Settings
 import android.telephony.CarrierConfigManager
 import android.telephony.ServiceState
+import android.telephony.SubscriptionManager
 import android.telephony.TelephonyManager
 import androidx.annotation.VisibleForTesting
 import androidx.compose.runtime.Composable
@@ -80,7 +81,7 @@
     @VisibleForTesting
     var progressDialog: ProgressDialog? = null
 
-    private var subId by notNull<Int>()
+    private var subId = SubscriptionManager.INVALID_SUBSCRIPTION_ID
 
     /**
      * Initialization based on given subscription id.
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/SettingsSpaEnvironment.kt b/src/com/android/settings/spa/SettingsSpaEnvironment.kt
index 568188f..f701323 100644
--- a/src/com/android/settings/spa/SettingsSpaEnvironment.kt
+++ b/src/com/android/settings/spa/SettingsSpaEnvironment.kt
@@ -22,11 +22,11 @@
 import com.android.settings.spa.about.AboutPhonePageProvider
 import com.android.settings.spa.app.AllAppListPageProvider
 import com.android.settings.spa.app.AppsMainPageProvider
-import com.android.settings.spa.app.battery.BatteryOptimizationModeAppListPageProvider
 import com.android.settings.spa.app.appcompat.UserAspectRatioAppsPageProvider
 import com.android.settings.spa.app.appinfo.AppInfoSettingsProvider
 import com.android.settings.spa.app.appinfo.CloneAppInfoSettingsProvider
 import com.android.settings.spa.app.backgroundinstall.BackgroundInstalledAppsPageProvider
+import com.android.settings.spa.app.battery.BatteryOptimizationModeAppListPageProvider
 import com.android.settings.spa.app.specialaccess.AlarmsAndRemindersAppListProvider
 import com.android.settings.spa.app.specialaccess.AllFilesAccessAppListProvider
 import com.android.settings.spa.app.specialaccess.BackupTasksAppsListProvider
diff --git a/src/com/android/settings/spa/network/SimOnboardingLabelSim.kt b/src/com/android/settings/spa/network/SimOnboardingLabelSim.kt
index 3b2d5ec..94e4a88 100644
--- a/src/com/android/settings/spa/network/SimOnboardingLabelSim.kt
+++ b/src/com/android/settings/spa/network/SimOnboardingLabelSim.kt
@@ -16,6 +16,7 @@
 
 package com.android.settings.spa.network
 
+import android.telephony.SubscriptionInfo
 import androidx.compose.foundation.layout.Column
 import androidx.compose.foundation.layout.padding
 import androidx.compose.material.icons.Icons
@@ -63,52 +64,55 @@
             cancelAction
         ),
     ) {
-        labelSimBody(onboardingService)
+        LabelSimBody(onboardingService)
     }
 }
 
 @Composable
-private fun labelSimBody(onboardingService: SimOnboardingService) {
+private fun LabelSimBody(onboardingService: SimOnboardingService) {
     Column(Modifier.padding(SettingsDimension.itemPadding)) {
         SettingsBody(stringResource(R.string.sim_onboarding_label_sim_msg))
     }
 
     for (subInfo in onboardingService.getSelectableSubscriptionInfoList()) {
-        var titleSimName by remember {
-            mutableStateOf(
-                onboardingService.getSubscriptionInfoDisplayName(subInfo)
-            )
-        }
-        var summaryNumber = subInfo.number
-            // TODO using the SubscriptionUtil.getFormattedPhoneNumber
-        val alertDialogPresenter = rememberAlertDialogPresenter(
-            confirmButton = AlertDialogButton(
-                stringResource(R.string.mobile_network_sim_name_rename)
-            ) {
-                onboardingService.addItemForRenaming(subInfo, titleSimName)
-            },
-            dismissButton = AlertDialogButton(stringResource(R.string.cancel)) {
-                titleSimName = onboardingService.getSubscriptionInfoDisplayName(subInfo)
-            },
-            title = stringResource(R.string.sim_onboarding_label_sim_dialog_title),
-            text = {
-                Text(summaryNumber,
-                    modifier = Modifier.padding(bottom = SettingsDimension.itemPaddingVertical))
-                SettingsOutlinedTextField(
-                    value = titleSimName,
-                    label = stringResource(R.string.sim_onboarding_label_sim_dialog_label),
-                    enabled = true,
-                    shape = MaterialTheme.shapes.extraLarge
-                ) {
-                    titleSimName = it
-                }
-            },
-        )
-        Preference(object : PreferenceModel {
-            override val title = titleSimName
-            override val summary: () -> String
-                get() = { summaryNumber }
-            override val onClick = alertDialogPresenter::open
-        })
+        LabelSimPreference(onboardingService, subInfo)
     }
-}
\ No newline at end of file
+}
+
+@Composable
+private fun LabelSimPreference(
+    onboardingService: SimOnboardingService,
+    subInfo: SubscriptionInfo,
+) {
+    var titleSimName by remember {
+        mutableStateOf(onboardingService.getSubscriptionInfoDisplayName(subInfo))
+    }
+    val phoneNumber = phoneNumber(subInfo)
+    val alertDialogPresenter = rememberAlertDialogPresenter(
+        confirmButton = AlertDialogButton(stringResource(R.string.mobile_network_sim_name_rename)) {
+            onboardingService.addItemForRenaming(subInfo, titleSimName)
+        },
+        dismissButton = AlertDialogButton(stringResource(R.string.cancel)) {
+            titleSimName = onboardingService.getSubscriptionInfoDisplayName(subInfo)
+        },
+        title = stringResource(R.string.sim_onboarding_label_sim_dialog_title),
+        text = {
+            Text(
+                phoneNumber.value ?: "",
+                modifier = Modifier.padding(bottom = SettingsDimension.itemPaddingVertical)
+            )
+            SettingsOutlinedTextField(
+                value = titleSimName,
+                label = stringResource(R.string.sim_onboarding_label_sim_dialog_label),
+                shape = MaterialTheme.shapes.extraLarge
+            ) {
+                titleSimName = it
+            }
+        },
+    )
+    Preference(object : PreferenceModel {
+        override val title = titleSimName
+        override val summary = { phoneNumber.value ?: "" }
+        override val onClick = alertDialogPresenter::open
+    })
+}
diff --git a/src/com/android/settings/spa/network/SimsSection.kt b/src/com/android/settings/spa/network/SimsSection.kt
index 9e4cf9f..0b638c4 100644
--- a/src/com/android/settings/spa/network/SimsSection.kt
+++ b/src/com/android/settings/spa/network/SimsSection.kt
@@ -25,6 +25,7 @@
 import androidx.compose.material.icons.Icons
 import androidx.compose.material.icons.outlined.Add
 import androidx.compose.runtime.Composable
+import androidx.compose.runtime.State
 import androidx.compose.runtime.remember
 import androidx.compose.ui.platform.LocalContext
 import androidx.compose.ui.res.stringResource
@@ -58,9 +59,7 @@
     val checked = remember(subInfo.subscriptionId) {
         context.isSubscriptionEnabledFlow(subInfo.subscriptionId)
     }.collectAsStateWithLifecycle(initialValue = false)
-    val phoneNumber = remember(subInfo) {
-        context.phoneNumberFlow(subInfo)
-    }.collectAsStateWithLifecycle(initialValue = null)
+    val phoneNumber = phoneNumber(subInfo)
     RestrictedTwoTargetSwitchPreference(
         model = object : SwitchPreferenceModel {
             override val title = subInfo.displayName.toString()
@@ -81,6 +80,14 @@
 }
 
 @Composable
+fun phoneNumber(subInfo: SubscriptionInfo): State<String?> {
+    val context = LocalContext.current
+    return remember(subInfo) {
+        context.phoneNumberFlow(subInfo)
+    }.collectAsStateWithLifecycle(initialValue = null)
+}
+
+@Composable
 private fun AddSim() {
     val context = LocalContext.current
     if (remember { MobileNetworkUtils.showEuiccSettings(context) }) {
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/details/WifiNetworkDetailsFragment.java b/src/com/android/settings/wifi/details/WifiNetworkDetailsFragment.java
index e1774e3..06b3e5d 100644
--- a/src/com/android/settings/wifi/details/WifiNetworkDetailsFragment.java
+++ b/src/com/android/settings/wifi/details/WifiNetworkDetailsFragment.java
@@ -55,6 +55,7 @@
 import com.android.settings.wifi.WifiDialog2;
 import com.android.settings.wifi.WifiUtils;
 import com.android.settings.wifi.details2.AddDevicePreferenceController2;
+import com.android.settings.wifi.details2.CertificateDetailsPreferenceController;
 import com.android.settings.wifi.details2.WifiAutoConnectPreferenceController2;
 import com.android.settings.wifi.details2.WifiDetailPreferenceController2;
 import com.android.settings.wifi.details2.WifiMeteredPreferenceController2;
@@ -122,8 +123,12 @@
     @Override
     public void onAttach(@NonNull Context context) {
         super.onAttach(context);
+        String wifiEntryKey = getArguments().getString(KEY_CHOSEN_WIFIENTRY_KEY);
+        setupNetworksDetailTracker();
         use(WifiPrivacyPreferenceController.class)
-                .setWifiEntryKey(getArguments().getString(KEY_CHOSEN_WIFIENTRY_KEY));
+                .setWifiEntryKey(wifiEntryKey);
+        use(CertificateDetailsPreferenceController.class)
+                .setWifiEntry(mNetworkDetailsTracker.getWifiEntry());
     }
 
     @Override
diff --git a/src/com/android/settings/wifi/details2/CertificateDetailsPreferenceController.kt b/src/com/android/settings/wifi/details2/CertificateDetailsPreferenceController.kt
new file mode 100644
index 0000000..8e1fa23
--- /dev/null
+++ b/src/com/android/settings/wifi/details2/CertificateDetailsPreferenceController.kt
@@ -0,0 +1,130 @@
+/*
+ * 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.wifi.details2
+
+import android.content.Context
+import android.content.DialogInterface
+import android.net.http.SslCertificate
+import android.security.KeyChain
+import android.security.keystore.KeyProperties
+import android.security.keystore2.AndroidKeyStoreLoadStoreParameter
+import android.util.Log
+import android.view.View
+import android.widget.ArrayAdapter
+import android.widget.LinearLayout
+import android.widget.Spinner
+import androidx.appcompat.app.AlertDialog
+import androidx.compose.runtime.Composable
+import androidx.compose.ui.platform.LocalContext
+import androidx.compose.ui.res.stringResource
+import com.android.settings.R
+import com.android.settings.spa.preference.ComposePreferenceController
+import com.android.settingslib.spa.widget.preference.Preference
+import com.android.settingslib.spa.widget.preference.PreferenceModel
+import com.android.wifi.flags.Flags
+import com.android.wifitrackerlib.WifiEntry
+import java.security.KeyStore
+import java.security.cert.X509Certificate
+
+class CertificateDetailsPreferenceController(context: Context, preferenceKey: String) :
+    ComposePreferenceController(context, preferenceKey) {
+
+    private lateinit var wifiEntry: WifiEntry
+    lateinit var certificateAliases: String
+    lateinit var certX509: X509Certificate
+
+    fun setWifiEntry(entry: WifiEntry) {
+        wifiEntry = entry
+    }
+
+    override fun getAvailabilityStatus(): Int {
+        return if (Flags.androidVWifiApi() && getCertX509(wifiEntry)) AVAILABLE
+        else CONDITIONALLY_UNAVAILABLE
+    }
+
+    @Composable
+    override fun Content() {
+        CertificateDetails()
+    }
+
+    @Composable
+    fun CertificateDetails() {
+        val context = LocalContext.current
+        Preference(object : PreferenceModel {
+            override val title = stringResource(com.android.internal.R.string.ssl_certificate)
+            override val summary = { certificateAliases }
+            override val onClick: () -> Unit = { createCertificateDetailsDialog(context, certX509) }
+        })
+    }
+
+    private fun getCertX509(wifiEntry: WifiEntry): Boolean {
+        certificateAliases =
+            wifiEntry.wifiConfiguration?.enterpriseConfig?.caCertificateAliases?.get(0)
+                ?: return false
+        return try {
+            val keyStore = KeyStore.getInstance("AndroidKeyStore")
+            keyStore.load(AndroidKeyStoreLoadStoreParameter(KeyProperties.NAMESPACE_WIFI))
+            val cert = keyStore.getCertificate(certificateAliases)
+            certX509 = KeyChain.toCertificate(cert.encoded)
+            true
+        } catch (e: Exception) {
+            Log.e(TAG, "Failed to open Android Keystore.", e)
+            false
+        }
+    }
+
+    private fun createCertificateDetailsDialog(context: Context, certX509: X509Certificate) {
+        val listener =
+            DialogInterface.OnClickListener { dialog, id ->
+                dialog.dismiss()
+            }
+        val titles = ArrayList<String>()
+        val sslCert = SslCertificate(certX509)
+        titles.add(sslCert.issuedTo.cName)
+        val arrayAdapter = ArrayAdapter(
+            context,
+            android.R.layout.simple_spinner_item,
+            titles
+        )
+        arrayAdapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item)
+        val spinner = Spinner(context)
+        spinner.setAdapter(arrayAdapter)
+
+        val certLayout = LinearLayout(context)
+        certLayout.orientation = LinearLayout.VERTICAL
+        // Prevent content overlapping with spinner
+        certLayout.setClipChildren(true)
+        certLayout.addView(spinner)
+
+        val view = sslCert.inflateCertificateView(context)
+        view.visibility = View.VISIBLE
+        certLayout.addView(view)
+        certLayout.visibility = View.VISIBLE
+
+        val dialog = AlertDialog.Builder(context)
+            .setView(certLayout)
+            .setTitle(com.android.internal.R.string.ssl_certificate)
+            .setPositiveButton(R.string.wifi_settings_ssid_block_button_close, null)
+            .setNegativeButton(R.string.trusted_credentials_remove_label, listener).create()
+        dialog.show()
+        dialog.getButton(AlertDialog.BUTTON_NEGATIVE).setEnabled(false)
+    }
+
+    companion object {
+        const val TAG = "CertificateDetailsPreferenceController"
+    }
+}
\ No newline at end of file
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/accessibility/AccessibilitySettingsTest.java b/tests/robotests/src/com/android/settings/accessibility/AccessibilitySettingsTest.java
index 05e56ca..624a39a 100644
--- a/tests/robotests/src/com/android/settings/accessibility/AccessibilitySettingsTest.java
+++ b/tests/robotests/src/com/android/settings/accessibility/AccessibilitySettingsTest.java
@@ -38,8 +38,12 @@
 import android.content.pm.ServiceInfo;
 import android.database.ContentObserver;
 import android.os.Build;
+import android.platform.test.annotations.DisableFlags;
+import android.platform.test.annotations.EnableFlags;
+import android.platform.test.flag.junit.SetFlagsRule;
 import android.provider.Settings;
 import android.view.accessibility.AccessibilityManager;
+import android.view.accessibility.Flags;
 
 import androidx.fragment.app.Fragment;
 import androidx.test.core.app.ApplicationProvider;
@@ -59,6 +63,8 @@
 import com.android.settingslib.search.SearchIndexableRaw;
 import com.android.settingslib.testutils.shadow.ShadowColorDisplayManager;
 
+import com.google.common.truth.BooleanSubject;
+
 import org.junit.Before;
 import org.junit.Rule;
 import org.junit.Test;
@@ -103,6 +109,7 @@
 
     @Rule
     public final MockitoRule mocks = MockitoJUnit.rule();
+    @Rule public final SetFlagsRule mSetFlagsRule = new SetFlagsRule();
     private final Context mContext = ApplicationProvider.getApplicationContext();
     @Spy
     private final AccessibilityServiceInfo mServiceInfo = getMockAccessibilityServiceInfo(
@@ -316,30 +323,39 @@
     }
 
     @Test
-    public void onCreate_haveRegisterToSpecificUrisAndActions() {
+    @DisableFlags(Flags.FLAG_A11Y_QS_SHORTCUT)
+    public void onCreate_flagDisabled_haveRegisterToSpecificUrisAndActions() {
         setupFragment();
 
-        ShadowContentResolver shadowContentResolver = shadowOf(mContext.getContentResolver());
-        Collection<ContentObserver> a11yButtonTargetsObservers =
-                shadowContentResolver.getContentObservers(
-                        Settings.Secure.getUriFor(Settings.Secure.ACCESSIBILITY_BUTTON_TARGETS));
-        Collection<ContentObserver> a11yShortcutTargetServiceObservers =
-                shadowContentResolver.getContentObservers(Settings.Secure.getUriFor(
-                        Settings.Secure.ACCESSIBILITY_SHORTCUT_TARGET_SERVICE));
+        assertUriObserversContainsClazz(Settings.Secure.ACCESSIBILITY_BUTTON_TARGETS,
+                AccessibilitySettingsContentObserver.class).isTrue();
+        assertUriObserversContainsClazz(Settings.Secure.ACCESSIBILITY_SHORTCUT_TARGET_SERVICE,
+                AccessibilitySettingsContentObserver.class).isTrue();
+        assertUriObserversContainsClazz(Settings.Secure.ACCESSIBILITY_QS_TARGETS,
+                AccessibilitySettingsContentObserver.class).isFalse();
         List<BroadcastReceiver> broadcastReceivers =
                 shadowOf((Application) ApplicationProvider.getApplicationContext())
                         .getRegisteredReceivers()
                         .stream().map(wrapper -> wrapper.broadcastReceiver).toList();
-        assertThat(
-                a11yButtonTargetsObservers.stream()
-                        .anyMatch(contentObserver ->
-                                contentObserver instanceof AccessibilitySettingsContentObserver))
-                .isTrue();
-        assertThat(
-                a11yShortcutTargetServiceObservers.stream()
-                        .anyMatch(contentObserver ->
-                                contentObserver instanceof AccessibilitySettingsContentObserver))
-                .isTrue();
+        assertThat(broadcastReceivers.stream().anyMatch(
+                broadcastReceiver -> broadcastReceiver instanceof PackageMonitor)).isTrue();
+    }
+
+    @Test
+    @EnableFlags(Flags.FLAG_A11Y_QS_SHORTCUT)
+    public void onCreate_flagEnabled_haveRegisterToSpecificUrisAndActions() {
+        setupFragment();
+
+        assertUriObserversContainsClazz(Settings.Secure.ACCESSIBILITY_BUTTON_TARGETS,
+                AccessibilitySettingsContentObserver.class).isTrue();
+        assertUriObserversContainsClazz(Settings.Secure.ACCESSIBILITY_SHORTCUT_TARGET_SERVICE,
+                AccessibilitySettingsContentObserver.class).isTrue();
+        assertUriObserversContainsClazz(Settings.Secure.ACCESSIBILITY_QS_TARGETS,
+                AccessibilitySettingsContentObserver.class).isTrue();
+        List<BroadcastReceiver> broadcastReceivers =
+                shadowOf((Application) ApplicationProvider.getApplicationContext())
+                        .getRegisteredReceivers()
+                        .stream().map(wrapper -> wrapper.broadcastReceiver).toList();
         assertThat(broadcastReceivers.stream().anyMatch(
                 broadcastReceiver -> broadcastReceiver instanceof PackageMonitor)).isTrue();
     }
@@ -350,27 +366,16 @@
 
         mActivityController.pause().stop().destroy();
 
-        ShadowContentResolver shadowContentResolver = shadowOf(mContext.getContentResolver());
-        Collection<ContentObserver> a11yButtonTargetsObservers =
-                shadowContentResolver.getContentObservers(
-                        Settings.Secure.getUriFor(Settings.Secure.ACCESSIBILITY_BUTTON_TARGETS));
-        Collection<ContentObserver> a11yShortcutTargetServiceObservers =
-                shadowContentResolver.getContentObservers(Settings.Secure.getUriFor(
-                        Settings.Secure.ACCESSIBILITY_SHORTCUT_TARGET_SERVICE));
+        assertUriObserversContainsClazz(Settings.Secure.ACCESSIBILITY_BUTTON_TARGETS,
+                AccessibilitySettingsContentObserver.class).isFalse();
+        assertUriObserversContainsClazz(Settings.Secure.ACCESSIBILITY_SHORTCUT_TARGET_SERVICE,
+                AccessibilitySettingsContentObserver.class).isFalse();
+        assertUriObserversContainsClazz(Settings.Secure.ACCESSIBILITY_QS_TARGETS,
+                AccessibilitySettingsContentObserver.class).isFalse();
         List<BroadcastReceiver> broadcastReceivers =
                 shadowOf((Application) ApplicationProvider.getApplicationContext())
                         .getRegisteredReceivers()
                         .stream().map(wrapper -> wrapper.broadcastReceiver).toList();
-        assertThat(
-                a11yButtonTargetsObservers.stream()
-                        .anyMatch(contentObserver ->
-                                contentObserver instanceof AccessibilitySettingsContentObserver))
-                .isFalse();
-        assertThat(
-                a11yShortcutTargetServiceObservers.stream()
-                        .anyMatch(contentObserver ->
-                                contentObserver instanceof AccessibilitySettingsContentObserver))
-                .isFalse();
         assertThat(broadcastReceivers.stream().anyMatch(
                 broadcastReceiver -> broadcastReceiver instanceof PackageMonitor)).isFalse();
     }
@@ -491,4 +496,14 @@
                 Settings.Secure.ACCESSIBILITY_BUTTON_TARGETS,
                 enabled ? componentName.flattenToString() : "");
     }
+
+    private BooleanSubject assertUriObserversContainsClazz(
+            String settingUri, Class<?> clazz) {
+        ShadowContentResolver shadowContentResolver = shadowOf(mContext.getContentResolver());
+        Collection<ContentObserver> observers =
+                shadowContentResolver.getContentObservers(
+                        Settings.Secure.getUriFor(settingUri));
+
+        return assertThat(observers.stream().anyMatch(clazz::isInstance));
+    }
 }
diff --git a/tests/robotests/src/com/android/settings/accessibility/HearingDevicePairingFragmentTest.java b/tests/robotests/src/com/android/settings/accessibility/HearingDevicePairingFragmentTest.java
index e14686e..db82be6 100644
--- a/tests/robotests/src/com/android/settings/accessibility/HearingDevicePairingFragmentTest.java
+++ b/tests/robotests/src/com/android/settings/accessibility/HearingDevicePairingFragmentTest.java
@@ -178,7 +178,7 @@
     }
 
     @Test
-    public void handleLeScanResult_isNotAndroidCompatible_() {
+    public void handleLeScanResult_isNotAndroidCompatible_discoverServices() {
         ScanResult scanResult = mock(ScanResult.class);
         doReturn(mDevice).when(scanResult).getDevice();
         doReturn(mCachedDevice).when(mCachedDeviceManager).findDevice(mDevice);
@@ -190,6 +190,19 @@
     }
 
     @Test
+    public void handleLeScanResult_alreadyBonded_doNothing() {
+        ScanResult scanResult = mock(ScanResult.class);
+        doReturn(mDevice).when(scanResult).getDevice();
+        doReturn(mCachedDevice).when(mCachedDeviceManager).findDevice(mDevice);
+        doReturn(BluetoothDevice.BOND_BONDED).when(mCachedDevice).getBondState();
+
+        mFragment.handleLeScanResult(scanResult);
+
+        verify(mFragment, never()).addDevice(mCachedDevice);
+        verify(mFragment, never()).discoverServices(mCachedDevice);
+    }
+
+    @Test
     public void onProfileConnectionStateChanged_deviceConnected_inSelectedList_finish() {
         doReturn(true).when(mCachedDevice).isConnected();
         mFragment.mSelectedDeviceList.add(mDevice);
diff --git a/tests/robotests/src/com/android/settings/accessibility/KeyboardVibrationTogglePreferenceControllerTest.java b/tests/robotests/src/com/android/settings/accessibility/KeyboardVibrationTogglePreferenceControllerTest.java
index 2d5905e..832a313 100644
--- a/tests/robotests/src/com/android/settings/accessibility/KeyboardVibrationTogglePreferenceControllerTest.java
+++ b/tests/robotests/src/com/android/settings/accessibility/KeyboardVibrationTogglePreferenceControllerTest.java
@@ -30,6 +30,7 @@
 import static org.mockito.Mockito.verify;
 
 import android.app.settings.SettingsEnums;
+import android.content.ContentResolver;
 import android.content.Context;
 import android.content.res.Resources;
 import android.os.vibrator.Flags;
@@ -60,6 +61,9 @@
     @Mock
     private PreferenceScreen mPreferenceScreen;
 
+    @Mock
+    private ContentResolver mContentResolver;
+
     private Context mContext;
     private Resources mResources;
     private KeyboardVibrationTogglePreferenceController mController;
@@ -72,6 +76,7 @@
         mContext = spy(ApplicationProvider.getApplicationContext());
         mResources = spy(mContext.getResources());
         when(mContext.getResources()).thenReturn(mResources);
+        when(mContext.getContentResolver()).thenReturn(mContentResolver);
         mFeatureFactory = FakeFeatureFactory.setupForTest();
         mController = new KeyboardVibrationTogglePreferenceController(mContext, "preferenceKey");
         mPreference = new SwitchPreference(mContext);
diff --git a/tests/robotests/src/com/android/settings/accessibility/MagnificationOneFingerPanningPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/accessibility/MagnificationOneFingerPanningPreferenceControllerTest.java
index 326a7a0..4501d27 100644
--- a/tests/robotests/src/com/android/settings/accessibility/MagnificationOneFingerPanningPreferenceControllerTest.java
+++ b/tests/robotests/src/com/android/settings/accessibility/MagnificationOneFingerPanningPreferenceControllerTest.java
@@ -16,7 +16,6 @@
 
 package com.android.settings.accessibility;
 
-import static com.android.server.accessibility.Flags.enableMagnificationOneFingerPanningGesture;
 import static com.android.settings.accessibility.AccessibilityUtil.State.OFF;
 import static com.android.settings.accessibility.AccessibilityUtil.State.ON;
 import static com.android.settings.core.BasePreferenceController.AVAILABLE;
@@ -28,7 +27,10 @@
 import static org.mockito.Mockito.verify;
 
 import android.content.Context;
-import android.platform.test.flag.junit.SetFlagsRule;
+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 android.provider.Settings;
 
 import androidx.preference.PreferenceManager;
@@ -51,8 +53,9 @@
     private static final String ONE_FINGER_PANNING_KEY =
             Settings.Secure.ACCESSIBILITY_SINGLE_FINGER_PANNING_ENABLED;
 
-    @Rule public final SetFlagsRule mSetFlagsRule =
-            new SetFlagsRule(SetFlagsRule.DefaultInitValueType.DEVICE_DEFAULT);
+    @Rule
+    public final CheckFlagsRule mCheckFlagsRule =
+            DeviceFlagsValueProvider.createCheckFlagsRule();
 
     private final Context mContext = ApplicationProvider.getApplicationContext();
     private final SwitchPreference mSwitchPreference = spy(new SwitchPreference(mContext));
@@ -88,16 +91,16 @@
     }
 
     @Test
-    public void getAvailabilityStatus_defaultState_disabled() {
+    @RequiresFlagsDisabled(Flags.FLAG_ENABLE_MAGNIFICATION_ONE_FINGER_PANNING_GESTURE)
+    public void getAvailabilityStatus_flagDisabled_disabled() {
         int status = mController.getAvailabilityStatus();
 
         assertThat(status).isEqualTo(DISABLED_FOR_USER);
     }
 
     @Test
+    @RequiresFlagsEnabled(Flags.FLAG_ENABLE_MAGNIFICATION_ONE_FINGER_PANNING_GESTURE)
     public void getAvailabilityStatus_featureFlagEnabled_enabled() {
-        enableFlag();
-
         int status = mController.getAvailabilityStatus();
 
         assertThat(status).isEqualTo(AVAILABLE);
@@ -158,9 +161,8 @@
     }
 
     @Test
+    @RequiresFlagsEnabled(Flags.FLAG_ENABLE_MAGNIFICATION_ONE_FINGER_PANNING_GESTURE)
     public void performClick_switchDefaultState_shouldReturnTrue() {
-        enableFlag();
-
         mSwitchPreference.performClick();
 
         verify(mSwitchPreference).setChecked(true);
@@ -168,13 +170,6 @@
         assertThat(mSwitchPreference.isChecked()).isTrue();
     }
 
-    private void enableFlag() {
-        mSetFlagsRule.enableFlags(Flags.FLAG_ENABLE_MAGNIFICATION_ONE_FINGER_PANNING_GESTURE);
-        assertThat(enableMagnificationOneFingerPanningGesture()).isTrue();
-        // This ensures that preference change listeners are added correctly.
-        mController.displayPreference(mScreen);
-    }
-
     private String enabledSummary() {
         return mContext.getString(
                 R.string.accessibility_magnification_one_finger_panning_summary_on);
diff --git a/tests/robotests/src/com/android/settings/accessibility/ToggleFeaturePreferenceFragmentTest.java b/tests/robotests/src/com/android/settings/accessibility/ToggleFeaturePreferenceFragmentTest.java
index e963bd0..6fb1c3f 100644
--- a/tests/robotests/src/com/android/settings/accessibility/ToggleFeaturePreferenceFragmentTest.java
+++ b/tests/robotests/src/com/android/settings/accessibility/ToggleFeaturePreferenceFragmentTest.java
@@ -24,6 +24,7 @@
 import static org.mockito.ArgumentMatchers.eq;
 import static org.mockito.Mockito.doReturn;
 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;
@@ -146,8 +147,9 @@
     }
 
     @Test
+    @EnableFlags(android.view.accessibility.Flags.FLAG_A11Y_QS_SHORTCUT)
     @Config(shadows = {ShadowFragment.class})
-    public void onResume_haveRegisterToSpecificUris() {
+    public void onResume_flagEnabled_haveRegisterToSpecificUris() {
         mFragment.onAttach(mContext);
         mFragment.onCreate(Bundle.EMPTY);
 
@@ -162,6 +164,36 @@
                         Settings.Secure.ACCESSIBILITY_SHORTCUT_TARGET_SERVICE)),
                 eq(false),
                 any(AccessibilitySettingsContentObserver.class));
+        verify(mContentResolver).registerContentObserver(
+                eq(Settings.Secure.getUriFor(
+                        Settings.Secure.ACCESSIBILITY_QS_TARGETS)),
+                eq(false),
+                any(AccessibilitySettingsContentObserver.class));
+    }
+
+    @Test
+    @DisableFlags(android.view.accessibility.Flags.FLAG_A11Y_QS_SHORTCUT)
+    @Config(shadows = {ShadowFragment.class})
+    public void onResume_flagDisabled_haveRegisterToSpecificUris() {
+        mFragment.onAttach(mContext);
+        mFragment.onCreate(Bundle.EMPTY);
+
+        mFragment.onResume();
+
+        verify(mContentResolver).registerContentObserver(
+                eq(Settings.Secure.getUriFor(Settings.Secure.ACCESSIBILITY_BUTTON_TARGETS)),
+                eq(false),
+                any(AccessibilitySettingsContentObserver.class));
+        verify(mContentResolver).registerContentObserver(
+                eq(Settings.Secure.getUriFor(
+                        Settings.Secure.ACCESSIBILITY_SHORTCUT_TARGET_SERVICE)),
+                eq(false),
+                any(AccessibilitySettingsContentObserver.class));
+        verify(mContentResolver, never()).registerContentObserver(
+                eq(Settings.Secure.getUriFor(
+                        Settings.Secure.ACCESSIBILITY_QS_TARGETS)),
+                eq(false),
+                any(AccessibilitySettingsContentObserver.class));
     }
 
     @Test
diff --git a/tests/robotests/src/com/android/settings/accessibility/ToggleScreenMagnificationPreferenceFragmentTest.java b/tests/robotests/src/com/android/settings/accessibility/ToggleScreenMagnificationPreferenceFragmentTest.java
index 3d24fbb..1d85705 100644
--- a/tests/robotests/src/com/android/settings/accessibility/ToggleScreenMagnificationPreferenceFragmentTest.java
+++ b/tests/robotests/src/com/android/settings/accessibility/ToggleScreenMagnificationPreferenceFragmentTest.java
@@ -292,7 +292,39 @@
     }
 
     @Test
-    public void onResume_haveRegisterToSpecificUris() {
+    @EnableFlags(android.view.accessibility.Flags.FLAG_A11Y_QS_SHORTCUT)
+    public void onResume_flagEnabled_haveRegisterToSpecificUris() {
+        ShadowContentResolver shadowContentResolver = Shadows.shadowOf(
+                mContext.getContentResolver());
+        Uri[] observedUri = new Uri[]{
+                Settings.Secure.getUriFor(Settings.Secure.ACCESSIBILITY_BUTTON_TARGETS),
+                Settings.Secure.getUriFor(
+                        Settings.Secure.ACCESSIBILITY_SHORTCUT_TARGET_SERVICE),
+                Settings.Secure.getUriFor(
+                        Settings.Secure.ACCESSIBILITY_QS_TARGETS),
+                Settings.Secure.getUriFor(
+                        Settings.Secure.ACCESSIBILITY_MAGNIFICATION_FOLLOW_TYPING_ENABLED),
+                Settings.Secure.getUriFor(
+                        Settings.Secure.ACCESSIBILITY_MAGNIFICATION_ALWAYS_ON_ENABLED)
+        };
+        for (Uri uri : observedUri) {
+            // verify no observer registered before launching the fragment
+            assertThat(shadowContentResolver.getContentObservers(uri)).isEmpty();
+        }
+
+        mFragController.create(R.id.main_content, /* bundle= */ null).start().resume();
+
+        for (Uri uri : observedUri) {
+            Collection<ContentObserver> observers = shadowContentResolver.getContentObservers(uri);
+            assertThat(observers.size()).isEqualTo(1);
+            assertThat(observers.stream().findFirst().get()).isInstanceOf(
+                    AccessibilitySettingsContentObserver.class);
+        }
+    }
+
+    @Test
+    @DisableFlags(android.view.accessibility.Flags.FLAG_A11Y_QS_SHORTCUT)
+    public void onResume_flagDisabled_haveRegisterToSpecificUris() {
         ShadowContentResolver shadowContentResolver = Shadows.shadowOf(
                 mContext.getContentResolver());
         Uri[] observedUri = new Uri[]{
@@ -317,6 +349,9 @@
             assertThat(observers.stream().findFirst().get()).isInstanceOf(
                     AccessibilitySettingsContentObserver.class);
         }
+        assertThat(shadowContentResolver.getContentObservers(
+                Settings.Secure.getUriFor(
+                        Settings.Secure.ACCESSIBILITY_QS_TARGETS))).hasSize(0);
     }
 
     @Test
diff --git a/tests/robotests/src/com/android/settings/gestures/OneHandedSettingsUtilsTest.java b/tests/robotests/src/com/android/settings/gestures/OneHandedSettingsUtilsTest.java
index 9559043..ee5f72e 100644
--- a/tests/robotests/src/com/android/settings/gestures/OneHandedSettingsUtilsTest.java
+++ b/tests/robotests/src/com/android/settings/gestures/OneHandedSettingsUtilsTest.java
@@ -16,13 +16,20 @@
 
 package com.android.settings.gestures;
 
+import static com.android.settings.gestures.OneHandedSettingsUtils.ONE_HANDED_MODE_TARGET_NAME;
+
 import static com.google.common.truth.Truth.assertThat;
 
 import android.content.Context;
 import android.os.UserHandle;
+import android.platform.test.annotations.DisableFlags;
+import android.platform.test.annotations.EnableFlags;
+import android.platform.test.flag.junit.SetFlagsRule;
 import android.provider.Settings;
+import android.view.accessibility.Flags;
 
 import org.junit.Before;
+import org.junit.Rule;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 import org.robolectric.RobolectricTestRunner;
@@ -30,7 +37,8 @@
 
 @RunWith(RobolectricTestRunner.class)
 public class OneHandedSettingsUtilsTest {
-
+    @Rule
+    public final SetFlagsRule mSetFlagsRule = new SetFlagsRule();
     private static final int OFF = 0;
     private static final int ON = 1;
 
@@ -120,4 +128,66 @@
                 OneHandedSettingsUtils.OneHandedTimeout.LONG.getValue(), mCurrentUserId))
                 .isEqualTo(12);
     }
+
+    @Test
+    public void getShortcutEnabled_a11yButtonVolumeKeysShortcutEnabled_returnTrue() {
+        setupShortcuts(
+                /* enableFab= */ true, /* enableVolumeKeys= */ true, /* enableQs=*/ false);
+
+        assertThat(OneHandedSettingsUtils.getShortcutEnabled(mContext)).isTrue();
+    }
+
+    @Test
+    public void getShortcutEnabled_a11yButtonShortcutEnabled_returnTrue() {
+        setupShortcuts(
+                /* enableFab= */ true, /* enableVolumeKeys= */ false, /* enableQs=*/ false);
+
+        assertThat(OneHandedSettingsUtils.getShortcutEnabled(mContext)).isTrue();
+    }
+
+    @Test
+    public void getShortcutEnabled_volumeKeysShortcutEnabled_returnTrue() {
+        setupShortcuts(
+                /* enableFab= */ false, /* enableVolumeKeys= */ true, /* enableQs=*/ false);
+
+        assertThat(OneHandedSettingsUtils.getShortcutEnabled(mContext)).isTrue();
+    }
+
+    @Test
+    public void getShortcutEnabled_noShortcutsEnabled_returnFalse() {
+        setupShortcuts(
+                /* enableFab= */ false, /* enableVolumeKeys= */ false, /* enableQs=*/ false);
+
+        assertThat(OneHandedSettingsUtils.getShortcutEnabled(mContext)).isFalse();
+    }
+
+    @Test
+    @EnableFlags(Flags.FLAG_A11Y_QS_SHORTCUT)
+    public void getShortcutEnabled_qsShortcutEnabled_returnTrue() {
+        setupShortcuts(
+                /* enableFab= */ false, /* enableVolumeKeys= */ false, /* enableQs=*/ true);
+
+        assertThat(OneHandedSettingsUtils.getShortcutEnabled(mContext)).isTrue();
+    }
+
+    @Test
+    @DisableFlags(Flags.FLAG_A11Y_QS_SHORTCUT)
+    public void getShortcutEnabled_flagDisabled_qsShortcutEnabled_returnFalse() {
+        setupShortcuts(
+                /* enableFab= */ false, /* enableVolumeKeys= */ false, /* enableQs=*/ true);
+
+        assertThat(OneHandedSettingsUtils.getShortcutEnabled(mContext)).isFalse();
+    }
+
+    private void setupShortcuts(boolean enableFab, boolean enableVolumeKeys, boolean enableQs) {
+        setupShortcut(Settings.Secure.ACCESSIBILITY_BUTTON_TARGETS, enableFab);
+        setupShortcut(Settings.Secure.ACCESSIBILITY_SHORTCUT_TARGET_SERVICE, enableVolumeKeys);
+        setupShortcut(Settings.Secure.ACCESSIBILITY_QS_TARGETS, enableQs);
+    }
+
+    private void setupShortcut(String shortcutSettingKey, boolean enabled) {
+        final String targetName = enabled ? ONE_HANDED_MODE_TARGET_NAME : "";
+        Settings.Secure.putStringForUser(
+                mContext.getContentResolver(), shortcutSettingKey, targetName, mCurrentUserId);
+    }
 }
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/spa_unit/src/com/android/settings/network/telephony/NetworkSelectRepositoryTest.kt b/tests/spa_unit/src/com/android/settings/network/telephony/NetworkSelectRepositoryTest.kt
new file mode 100644
index 0000000..4137de4
--- /dev/null
+++ b/tests/spa_unit/src/com/android/settings/network/telephony/NetworkSelectRepositoryTest.kt
@@ -0,0 +1,123 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.settings.network.telephony
+
+import android.content.Context
+import android.telephony.AccessNetworkConstants
+import android.telephony.NetworkRegistrationInfo
+import android.telephony.ServiceState
+import android.telephony.TelephonyManager
+import androidx.test.core.app.ApplicationProvider
+import androidx.test.ext.junit.runners.AndroidJUnit4
+import com.android.settings.network.telephony.scan.NetworkScanRepositoryTest
+import com.google.common.truth.Truth.assertThat
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.mockito.kotlin.doReturn
+import org.mockito.kotlin.mock
+import org.mockito.kotlin.spy
+import org.mockito.kotlin.stub
+
+@RunWith(AndroidJUnit4::class)
+class NetworkSelectRepositoryTest {
+
+    private val mockServiceState = mock<ServiceState> {
+        on {
+            getNetworkRegistrationInfoListForTransportType(
+                AccessNetworkConstants.TRANSPORT_TYPE_WWAN
+            )
+        } doReturn NetworkRegistrationInfos
+    }
+
+    private val mockTelephonyManager = mock<TelephonyManager> {
+        on { createForSubscriptionId(SUB_ID) } doReturn mock
+        on { dataState } doReturn TelephonyManager.DATA_CONNECTED
+        on { serviceState } doReturn mockServiceState
+    }
+
+    private val context: Context = spy(ApplicationProvider.getApplicationContext()) {
+        on { getSystemService(TelephonyManager::class.java) } doReturn mockTelephonyManager
+    }
+
+    private val repository = NetworkSelectRepository(context, SUB_ID)
+
+    @Test
+    fun getNetworkRegistrationInfo_notConnected_returnNull() {
+        mockTelephonyManager.stub {
+            on { dataState } doReturn TelephonyManager.DATA_DISCONNECTED
+        }
+
+        val info = repository.getNetworkRegistrationInfo()
+
+        assertThat(info).isNull()
+    }
+
+    @Test
+    fun getNetworkRegistrationInfo_nullServiceState_returnNull() {
+        mockTelephonyManager.stub {
+            on { serviceState } doReturn null
+        }
+
+        val info = repository.getNetworkRegistrationInfo()
+
+        assertThat(info).isNull()
+    }
+
+    @Test
+    fun getNetworkRegistrationInfo_emptyNetworkList_returnNull() {
+        mockServiceState.stub {
+            on {
+                getNetworkRegistrationInfoListForTransportType(
+                    AccessNetworkConstants.TRANSPORT_TYPE_WWAN
+                )
+            } doReturn emptyList()
+        }
+
+        val info = repository.getNetworkRegistrationInfo()
+
+        assertThat(info).isNull()
+    }
+
+    @Test
+    fun getNetworkRegistrationInfo_hasNetworkList_returnInfo() {
+        mockServiceState.stub {
+            on {
+                getNetworkRegistrationInfoListForTransportType(
+                    AccessNetworkConstants.TRANSPORT_TYPE_WWAN
+                )
+            } doReturn NetworkRegistrationInfos
+        }
+        mockTelephonyManager.stub {
+            on { forbiddenPlmns } doReturn arrayOf(FORBIDDEN_PLMN)
+        }
+
+        val info = repository.getNetworkRegistrationInfo()
+
+        assertThat(info).isEqualTo(
+            NetworkSelectRepository.NetworkRegistrationAndForbiddenInfo(
+                networkList = NetworkRegistrationInfos,
+                forbiddenPlmns = listOf(FORBIDDEN_PLMN),
+            )
+        )
+    }
+
+    private companion object {
+        const val SUB_ID = 1
+        val NetworkRegistrationInfos = listOf(NetworkRegistrationInfo.Builder().build())
+        const val FORBIDDEN_PLMN = "Forbidden PLMN"
+    }
+}
diff --git a/tests/spa_unit/src/com/android/settings/wifi/details2/CertificateDetailsPreferenceControllerTest.kt b/tests/spa_unit/src/com/android/settings/wifi/details2/CertificateDetailsPreferenceControllerTest.kt
new file mode 100644
index 0000000..1499374
--- /dev/null
+++ b/tests/spa_unit/src/com/android/settings/wifi/details2/CertificateDetailsPreferenceControllerTest.kt
@@ -0,0 +1,73 @@
+/*
+ * 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.wifi.details2
+
+import android.content.Context
+import androidx.compose.runtime.CompositionLocalProvider
+import androidx.compose.ui.platform.LocalContext
+import androidx.compose.ui.test.assertIsDisplayed
+import androidx.compose.ui.test.junit4.createComposeRule
+import androidx.compose.ui.test.onNodeWithText
+import androidx.test.core.app.ApplicationProvider
+import androidx.test.ext.junit.runners.AndroidJUnit4
+import java.security.cert.X509Certificate
+import org.junit.Before
+import org.junit.Rule
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.mockito.kotlin.any
+import org.mockito.kotlin.doNothing
+import org.mockito.kotlin.mock
+import org.mockito.kotlin.spy
+import org.mockito.kotlin.whenever
+
+@RunWith(AndroidJUnit4::class)
+class CertificateDetailsPreferenceControllerTest {
+    @get:Rule
+    val composeTestRule = createComposeRule()
+
+    private val mockCertX509 = mock<X509Certificate> {}
+
+    private val context: Context = spy(ApplicationProvider.getApplicationContext()) {
+        doNothing().whenever(mock).startActivity(any())
+    }
+
+    private val controller = CertificateDetailsPreferenceController(context, TEST_KEY)
+
+    @Before
+    fun setUp() {
+        controller.certificateAliases = MOCK_CA
+        controller.certX509 = mockCertX509
+    }
+
+    @Test
+    fun title_isDisplayed() {
+        composeTestRule.setContent {
+            CompositionLocalProvider(LocalContext provides context) {
+                controller.Content()
+            }
+        }
+
+        composeTestRule.onNodeWithText(context.getString(com.android.internal.R.string.ssl_certificate))
+            .assertIsDisplayed()
+    }
+
+    private companion object {
+        const val TEST_KEY = "test_key"
+        const val MOCK_CA = "mock_ca"
+    }
+}
\ No newline at end of file
diff --git a/tests/unit/src/com/android/settings/conecteddevice/threadnetwork/ThreadNetworkPreferenceControllerTest.kt b/tests/unit/src/com/android/settings/conecteddevice/threadnetwork/ThreadNetworkPreferenceControllerTest.kt
index 644095d..976096c 100644
--- a/tests/unit/src/com/android/settings/conecteddevice/threadnetwork/ThreadNetworkPreferenceControllerTest.kt
+++ b/tests/unit/src/com/android/settings/conecteddevice/threadnetwork/ThreadNetworkPreferenceControllerTest.kt
@@ -33,13 +33,13 @@
 import androidx.preference.SwitchPreference
 import androidx.test.core.app.ApplicationProvider
 import androidx.test.ext.junit.runners.AndroidJUnit4
-import com.android.net.thread.platform.flags.Flags
 import com.android.settings.R
 import com.android.settings.core.BasePreferenceController.AVAILABLE
 import com.android.settings.core.BasePreferenceController.CONDITIONALLY_UNAVAILABLE
 import com.android.settings.core.BasePreferenceController.DISABLED_DEPENDENT_SETTING
 import com.android.settings.core.BasePreferenceController.UNSUPPORTED_ON_DEVICE
 import com.android.settings.connecteddevice.threadnetwork.ThreadNetworkPreferenceController.BaseThreadNetworkController
+import com.android.settings.flags.Flags
 import com.google.common.truth.Truth.assertThat
 import org.junit.Before
 import org.junit.Rule
@@ -68,7 +68,7 @@
 
     @Before
     fun setUp() {
-        mSetFlagsRule.enableFlags(Flags.FLAG_THREAD_ENABLED_PLATFORM)
+        mSetFlagsRule.enableFlags(Flags.FLAG_THREAD_SETTINGS_ENABLED)
         context = spy(ApplicationProvider.getApplicationContext<Context>())
         executor = ContextCompat.getMainExecutor(context)
         fakeThreadNetworkController = FakeThreadNetworkController(executor)
@@ -96,7 +96,7 @@
 
     @Test
     fun availabilityStatus_flagDisabled_returnsConditionallyUnavailable() {
-        mSetFlagsRule.disableFlags(Flags.FLAG_THREAD_ENABLED_PLATFORM)
+        mSetFlagsRule.disableFlags(Flags.FLAG_THREAD_SETTINGS_ENABLED)
         assertThat(controller.getAvailabilityStatus()).isEqualTo(CONDITIONALLY_UNAVAILABLE)
     }
 
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();
-    }
-}