Merge "Use the same layout style for contextual cards"
diff --git a/AndroidManifest.xml b/AndroidManifest.xml
index f60d99e..109f2b9 100644
--- a/AndroidManifest.xml
+++ b/AndroidManifest.xml
@@ -1560,7 +1560,7 @@
             android:enabled="false"
             android:exported="true"
             android:taskAffinity="com.android.wizard"
-            android:theme="@style/SuwThemeGlif.Light"
+            android:theme="@style/SuwThemeGlif.DayNight"
             android:label="@string/lock_screen_notifications_interstitial_title"
             android:icon="@drawable/ic_suggested_notifications">
             <intent-filter>
diff --git a/res/layout/condition_tile.xml b/res/layout/condition_tile.xml
index 9fe83dc..dd87be5 100644
--- a/res/layout/condition_tile.xml
+++ b/res/layout/condition_tile.xml
@@ -15,7 +15,8 @@
      limitations under the License.
 -->
 
-<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+<LinearLayout
+    xmlns:android="http://schemas.android.com/apk/res/android"
     android:id="@+id/content"
     android:layout_width="match_parent"
     android:layout_height="wrap_content"
@@ -35,7 +36,7 @@
             android:layout_marginTop="12dp"
             android:layout_marginStart="14dp"
             android:layout_marginEnd="24dp"
-            android:tint="?android:attr/colorAccent" />
+            android:tint="?android:attr/colorAccent"/>
 
         <TextView
             android:id="@android:id/title"
@@ -43,7 +44,7 @@
             android:layout_height="wrap_content"
             android:layout_marginTop="14dp"
             android:textAppearance="?android:attr/textAppearanceSmall"
-            android:textColor="?android:attr/textColorPrimary" />
+            android:textColor="?android:attr/textColorPrimary"/>
 
     </LinearLayout>
 
@@ -56,7 +57,7 @@
         android:paddingBottom="8dp"
         android:textAppearance="?android:attr/textAppearanceListItemSecondary"
         android:alpha=".7"
-        android:textColor="?android:attr/textColorPrimary" />
+        android:textColor="?android:attr/textColorPrimary"/>
 
     <androidx.appcompat.widget.ButtonBarLayout
         android:id="@+id/buttonBar"
@@ -76,20 +77,15 @@
             android:alpha=".8"
             android:textAlignment="viewStart"
             android:textColor="?android:attr/textColorPrimary"
-            style="?android:attr/buttonBarButtonStyle" />
+            style="?android:attr/buttonBarButtonStyle"/>
 
-        <Button
-            android:id="@+id/second_action"
+        <Space
             android:layout_width="0dp"
             android:layout_height="wrap_content"
-            android:layout_weight="1"
-            android:alpha=".8"
-            android:textAlignment="viewStart"
-            android:textColor="?android:attr/textColorPrimary"
-            style="?android:attr/buttonBarButtonStyle" />
+            android:layout_weight="1"/>
 
     </androidx.appcompat.widget.ButtonBarLayout>
 
-    <include layout="@layout/horizontal_divider" />
+    <include layout="@layout/horizontal_divider"/>
 
 </LinearLayout>
diff --git a/res/layout/master_clear.xml b/res/layout/master_clear.xml
index 247eedc..8d4d623 100644
--- a/res/layout/master_clear.xml
+++ b/res/layout/master_clear.xml
@@ -21,7 +21,7 @@
     android:layout_width="match_parent"
     android:layout_height="match_parent"
     android:orientation="vertical"
-    android:theme="@style/SuwThemeGlifV3.Light"
+    android:theme="@style/SuwThemeGlifV3.DayNight"
     android:icon="@drawable/ic_delete_accent"
     app:suwHeaderText="@string/master_clear_title">
 
diff --git a/res/layout/master_clear_confirm.xml b/res/layout/master_clear_confirm.xml
index 146fb77..d513dbb 100644
--- a/res/layout/master_clear_confirm.xml
+++ b/res/layout/master_clear_confirm.xml
@@ -19,7 +19,7 @@
     android:layout_width="match_parent"
     android:layout_height="match_parent"
     android:orientation="vertical"
-    android:theme="@style/SuwThemeGlifV3.Light"
+    android:theme="@style/SuwThemeGlifV3.DayNight"
     android:id="@+id/setup_wizard_layout"
     android:icon="@drawable/ic_delete_accent"
     app:suwHeaderText="@string/master_clear_confirm_title">
diff --git a/res/values/strings.xml b/res/values/strings.xml
index 9ed8417..ac8f305 100644
--- a/res/values/strings.xml
+++ b/res/values/strings.xml
@@ -10259,6 +10259,9 @@
     <!-- Mobile network settings screen, message asking the user to check their pricing with their Carrier, when enabling Data roaming. [CHAR LIMIT=NONE] -->
     <string name="roaming_check_price_warning">Check with your network provider for pricing.</string>
 
+    <!-- Title for mobile data preference, to display the mobile data usage for each app. [CHAR LIMIT=NONE]-->
+    <string name="mobile_data_usage_title">App data usage</string>
+
     <!-- Available networks screen, summary when button disallowed due to permanent automatic mode [CHAR LIMIT=NONE] -->
     <string name="manual_mode_disallowed_summary">Unavailable when connected to <xliff:g id="carrier" example="verizon">%1$s</xliff:g></string>
 </resources>
diff --git a/res/values/themes_suw.xml b/res/values/themes_suw.xml
index f09b2b1..d66f917 100644
--- a/res/values/themes_suw.xml
+++ b/res/values/themes_suw.xml
@@ -17,7 +17,7 @@
 
 <!-- SUW related themes -->
 <resources>
-    <style name="GlifTheme" parent="SuwThemeGlif">
+    <style name="GlifTheme" parent="SuwThemeGlif.DayNight">
         <!-- For all AndroidX Alert Dialogs -->
         <item name="alertDialogTheme">@style/ThemeOverlay.AlertDialog</item>
         <item name="android:windowBackground">?android:attr/colorBackground</item>
@@ -55,7 +55,7 @@
         <item name="*android:colorError">@color/glif_error_color</item>
     </style>
 
-    <style name="GlifV2Theme" parent="SuwThemeGlifV2">
+    <style name="GlifV2Theme" parent="SuwThemeGlifV2.DayNight">
         <!-- For all AndroidX Alert Dialogs -->
         <item name="alertDialogTheme">@style/GlifV2ThemeAlertDialog</item>
         <item name="android:windowBackground">?android:attr/colorBackground</item>
@@ -93,7 +93,7 @@
         <item name="*android:colorError">@color/glif_error_color</item>
     </style>
 
-    <style name="GlifV3Theme" parent="SuwThemeGlifV3">
+    <style name="GlifV3Theme" parent="SuwThemeGlifV3.DayNight">
         <!-- For all AndroidX Alert Dialogs -->
         <item name="alertDialogTheme">@style/GlifV2ThemeAlertDialog</item>
         <item name="android:windowBackground">?android:attr/colorBackground</item>
diff --git a/res/xml/cdma_options.xml b/res/xml/cdma_options.xml
deleted file mode 100644
index 202187c..0000000
--- a/res/xml/cdma_options.xml
+++ /dev/null
@@ -1,53 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-    Copyright (C) 2008 The Android Open Source Project
-
-    Licensed under the Apache License, Version 2.0 (the "License");
-    you may not use this file except in compliance with the License.
-    You may obtain a copy of the License at
-
-         http://www.apache.org/licenses/LICENSE-2.0
-
-    Unless required by applicable law or agreed to in writing, software
-    distributed under the License is distributed on an "AS IS" BASIS,
-    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-    See the License for the specific language governing permissions and
-    limitations under the License.
--->
-
-<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android">
-
-    <com.android.settings.network.telephony.CdmaSystemSelectListPreference
-        android:key="cdma_system_select_key"
-        android:title="@string/cdma_system_select_title"
-        android:summary="@string/cdma_system_select_summary"
-        android:entries="@array/cdma_system_select_choices"
-        android:entryValues="@array/cdma_system_select_values"
-        android:dialogTitle="@string/cdma_system_select_dialogtitle" />
-
-    <com.android.settings.network.telephony.CdmaSubscriptionListPreference
-        android:key="cdma_subscription_key"
-        android:title="@string/cdma_subscription_title"
-        android:summary="@string/cdma_subscription_summary"
-        android:entries="@array/cdma_subscription_choices"
-        android:entryValues="@array/cdma_subscription_values"
-        android:dialogTitle="@string/cdma_subscription_dialogtitle" />
-
-    <!--We want separate APN setting from reset of settings because-->
-    <!--we want user to change it with caution.-->
-    <PreferenceCategory
-        android:key="category_cdma_apn_key">
-        <!-- The launching Intent will be defined thru code as we need to pass some Extra -->
-        <com.android.settingslib.RestrictedPreference
-            android:key="button_cdma_apn_key"
-            android:title="@string/apn_settings"
-            android:persistent="false"/>
-    </PreferenceCategory>
-
-    <Preference
-        android:key="carrier_settings_key"
-        android:title="@string/carrier_settings_title">
-        <!-- b/114749736, create a preference controller to build intent -->
-    </Preference>
-
-</PreferenceScreen>
diff --git a/res/xml/gsm_umts_options.xml b/res/xml/gsm_umts_options.xml
index f5439a4..1d1d4f3 100644
--- a/res/xml/gsm_umts_options.xml
+++ b/res/xml/gsm_umts_options.xml
@@ -27,7 +27,7 @@
             android:title="@string/select_automatically"
             android:persistent="false"/>
 
-        <com.android.settings.mobilenetwork.NetworkSelectListPreference
+        <com.android.settings.network.telephony.NetworkSelectListPreference
             android:key="button_network_select_key"
             android:title="@string/network_select_title"
             android:persistent="false"/>
diff --git a/res/xml/network_setting_fragment.xml b/res/xml/network_setting_fragment.xml
index 413e670..ce1644f 100644
--- a/res/xml/network_setting_fragment.xml
+++ b/res/xml/network_setting_fragment.xml
@@ -38,9 +38,10 @@
         android:summaryOn="@string/roaming_enable"
         android:summaryOff="@string/roaming_disable"/>
 
-    <com.android.settings.network.telephony.DataUsagePreference
+    <Preference
         android:key="data_usage_summary"
-        android:title="@string/data_usage_title" />
+        android:title="@string/mobile_data_usage_title"
+        settings:controller="com.android.settings.network.telephony.DataUsagePreferenceController"/>
 
     <SwitchPreference
         android:key="enhanced_4g_lte"
@@ -91,4 +92,38 @@
 
     </PreferenceCategory>
 
+    <ListPreference
+        android:key="cdma_system_select_key"
+        android:title="@string/cdma_system_select_title"
+        android:summary="@string/cdma_system_select_summary"
+        android:entries="@array/cdma_system_select_choices"
+        android:entryValues="@array/cdma_system_select_values"
+        android:dialogTitle="@string/cdma_system_select_dialogtitle"
+        settings:controller="com.android.settings.network.telephony.cdma.CdmaSystemSelectPreferenceController"/>
+
+    <ListPreference
+        android:key="cdma_subscription_key"
+        android:title="@string/cdma_subscription_title"
+        android:summary="@string/cdma_subscription_summary"
+        android:entries="@array/cdma_subscription_choices"
+        android:entryValues="@array/cdma_subscription_values"
+        android:dialogTitle="@string/cdma_subscription_dialogtitle"
+        settings:controller="com.android.settings.network.telephony.cdma.CdmaSubscriptionPreferenceController"/>
+
+    <!--We want separate APN setting from reset of settings because we want user to change it with caution-->
+    <PreferenceCategory
+        android:key="category_cdma_apn_key">
+        <com.android.settingslib.RestrictedPreference
+            android:key="button_cdma_apn_key"
+            android:title="@string/apn_settings"
+            android:persistent="false"
+            settings:controller="com.android.settings.network.telephony.cdma.CdmaApnPreferenceController"/>
+    </PreferenceCategory>
+
+    <Preference
+        android:key="carrier_settings_key"
+        android:title="@string/carrier_settings_title"
+        settings:controller="com.android.settings.network.telephony.CarrierPreferenceController">
+    </Preference>
+
 </PreferenceScreen>
diff --git a/src/com/android/settings/applications/appinfo/DefaultBrowserShortcutPreferenceController.java b/src/com/android/settings/applications/appinfo/DefaultBrowserShortcutPreferenceController.java
index 64af3c2..4c7dd81 100644
--- a/src/com/android/settings/applications/appinfo/DefaultBrowserShortcutPreferenceController.java
+++ b/src/com/android/settings/applications/appinfo/DefaultBrowserShortcutPreferenceController.java
@@ -30,7 +30,8 @@
 
     @Override
     protected boolean hasAppCapability() {
-        return DefaultBrowserPreferenceController.hasBrowserPreference(mPackageName, mContext);
+        return DefaultBrowserPreferenceController
+                .hasBrowserPreference(mPackageName, mContext, UserHandle.myUserId());
     }
 
     @Override
diff --git a/src/com/android/settings/applications/defaultapps/DefaultBrowserPicker.java b/src/com/android/settings/applications/defaultapps/DefaultBrowserPicker.java
index 626048d..cfaac3a 100644
--- a/src/com/android/settings/applications/defaultapps/DefaultBrowserPicker.java
+++ b/src/com/android/settings/applications/defaultapps/DefaultBrowserPicker.java
@@ -62,7 +62,7 @@
 
         for (ResolveInfo info : list) {
             try {
-                candidates.add(new DefaultAppInfo(context, mPm,
+                candidates.add(new DefaultAppInfo(context, mPm, mUserId,
                         mPm.getApplicationInfoAsUser(info.activityInfo.packageName, 0, mUserId)));
             } catch (PackageManager.NameNotFoundException e) {
                 // Skip unknown packages.
diff --git a/src/com/android/settings/applications/defaultapps/DefaultBrowserPreferenceController.java b/src/com/android/settings/applications/defaultapps/DefaultBrowserPreferenceController.java
index 9e76ff5..24b4dcd 100644
--- a/src/com/android/settings/applications/defaultapps/DefaultBrowserPreferenceController.java
+++ b/src/com/android/settings/applications/defaultapps/DefaultBrowserPreferenceController.java
@@ -29,6 +29,7 @@
 import android.util.IconDrawableFactory;
 import android.util.Log;
 
+import androidx.annotation.VisibleForTesting;
 import androidx.preference.Preference;
 
 import com.android.settingslib.applications.DefaultAppInfo;
@@ -75,8 +76,8 @@
         try {
             final String packageName = mPackageManager.getDefaultBrowserPackageNameAsUser(mUserId);
             Log.d(TAG, "Get default browser package: " + packageName);
-            return new DefaultAppInfo(mContext, mPackageManager,
-                    mPackageManager.getApplicationInfo(packageName, 0));
+            return new DefaultAppInfo(mContext, mPackageManager, mUserId,
+                    mPackageManager.getApplicationInfoAsUser(packageName, 0, mUserId));
         } catch (PackageManager.NameNotFoundException e) {
             return null;
         }
@@ -143,7 +144,8 @@
         return null;
     }
 
-    private Drawable getOnlyAppIcon() {
+    @VisibleForTesting
+    Drawable getOnlyAppIcon() {
         final List<ResolveInfo> list = getCandidates(mPackageManager, mUserId);
         if (list != null && list.size() == 1) {
             final ResolveInfo info = list.get(0);
@@ -154,7 +156,7 @@
             }
             final ApplicationInfo appInfo;
             try {
-                appInfo = mPackageManager.getApplicationInfo(packageName, 0);
+                appInfo = mPackageManager.getApplicationInfoAsUser(packageName, 0, mUserId);
             } catch (PackageManager.NameNotFoundException e) {
                 Log.w(TAG, "Error getting app info for " + packageName);
                 return null;
@@ -169,11 +171,11 @@
     /**
      * Whether or not the pkg contains browser capability
      */
-    public static boolean hasBrowserPreference(String pkg, Context context) {
+    public static boolean hasBrowserPreference(String pkg, Context context, int userId) {
         final Intent intent = new Intent(BROWSE_PROBE);
         intent.setPackage(pkg);
-        final List<ResolveInfo> resolveInfos =
-                context.getPackageManager().queryIntentActivities(intent, 0);
+        final List<ResolveInfo> resolveInfos = context.getPackageManager()
+                .queryIntentActivitiesAsUser(intent, 0 /* flags */, userId);
         return resolveInfos != null && resolveInfos.size() != 0;
     }
 
diff --git a/src/com/android/settings/applications/defaultapps/DefaultEmergencyPicker.java b/src/com/android/settings/applications/defaultapps/DefaultEmergencyPicker.java
index f6f8a56..76e93cc 100644
--- a/src/com/android/settings/applications/defaultapps/DefaultEmergencyPicker.java
+++ b/src/com/android/settings/applications/defaultapps/DefaultEmergencyPicker.java
@@ -58,7 +58,7 @@
                 final PackageInfo packageInfo =
                         mPm.getPackageInfo(info.activityInfo.packageName, 0);
                 final ApplicationInfo appInfo = packageInfo.applicationInfo;
-                candidates.add(new DefaultAppInfo(context, mPm, appInfo));
+                candidates.add(new DefaultAppInfo(context, mPm, mUserId, appInfo));
                 // Get earliest installed system app.
                 if (isSystemApp(appInfo) && (bestMatch == null ||
                         bestMatch.firstInstallTime > packageInfo.firstInstallTime)) {
diff --git a/src/com/android/settings/applications/defaultapps/DefaultPhonePicker.java b/src/com/android/settings/applications/defaultapps/DefaultPhonePicker.java
index 0bda2ec..72f1cc5 100644
--- a/src/com/android/settings/applications/defaultapps/DefaultPhonePicker.java
+++ b/src/com/android/settings/applications/defaultapps/DefaultPhonePicker.java
@@ -58,7 +58,7 @@
         final Context context = getContext();
         for (String packageName : dialerPackages) {
             try {
-                candidates.add(new DefaultAppInfo(context, mPm,
+                candidates.add(new DefaultAppInfo(context, mPm, mUserId,
                         mPm.getApplicationInfoAsUser(packageName, 0, mUserId)));
             } catch (PackageManager.NameNotFoundException e) {
                 // Skip unknown packages.
diff --git a/src/com/android/settings/applications/defaultapps/DefaultPhonePreferenceController.java b/src/com/android/settings/applications/defaultapps/DefaultPhonePreferenceController.java
index 95264b1..7b7755d 100644
--- a/src/com/android/settings/applications/defaultapps/DefaultPhonePreferenceController.java
+++ b/src/com/android/settings/applications/defaultapps/DefaultPhonePreferenceController.java
@@ -59,7 +59,8 @@
     @Override
     protected DefaultAppInfo getDefaultAppInfo() {
         try {
-            return new DefaultAppInfo(mContext, mPackageManager, mPackageManager.getApplicationInfo(
+            return new DefaultAppInfo(mContext, mPackageManager, mUserId,
+                    mPackageManager.getApplicationInfo(
                     DefaultDialerManager.getDefaultDialerApplication(mContext, mUserId), 0));
         } catch (PackageManager.NameNotFoundException e) {
             return null;
diff --git a/src/com/android/settings/applications/defaultapps/DefaultSmsPicker.java b/src/com/android/settings/applications/defaultapps/DefaultSmsPicker.java
index f8b1596..6d1e21d 100644
--- a/src/com/android/settings/applications/defaultapps/DefaultSmsPicker.java
+++ b/src/com/android/settings/applications/defaultapps/DefaultSmsPicker.java
@@ -55,7 +55,7 @@
 
         for (SmsApplication.SmsApplicationData smsApplicationData : smsApplications) {
             try {
-                candidates.add(new DefaultAppInfo(context, mPm,
+                candidates.add(new DefaultAppInfo(context, mPm, mUserId,
                         mPm.getApplicationInfoAsUser(smsApplicationData.mPackageName, 0, mUserId)));
             } catch (PackageManager.NameNotFoundException e) {
                 // Skip unknown packages.
diff --git a/src/com/android/settings/development/WebViewAppPreferenceController.java b/src/com/android/settings/development/WebViewAppPreferenceController.java
index 74d6c10..37653cc 100644
--- a/src/com/android/settings/development/WebViewAppPreferenceController.java
+++ b/src/com/android/settings/development/WebViewAppPreferenceController.java
@@ -19,6 +19,7 @@
 import android.content.Context;
 import android.content.pm.PackageInfo;
 import android.content.pm.PackageManager;
+import android.os.UserHandle;
 import android.text.TextUtils;
 import android.util.Log;
 
@@ -66,7 +67,7 @@
     @VisibleForTesting
     DefaultAppInfo getDefaultAppInfo() {
         final PackageInfo currentPackage = mWebViewUpdateServiceWrapper.getCurrentWebViewPackage();
-        return new DefaultAppInfo(mContext, mPackageManager,
+        return new DefaultAppInfo(mContext, mPackageManager, UserHandle.myUserId(),
                 currentPackage == null ? null : currentPackage.applicationInfo);
     }
 
diff --git a/src/com/android/settings/enterprise/ActionDisabledByAdminDialog.java b/src/com/android/settings/enterprise/ActionDisabledByAdminDialog.java
index 1142766..717c5bc 100644
--- a/src/com/android/settings/enterprise/ActionDisabledByAdminDialog.java
+++ b/src/com/android/settings/enterprise/ActionDisabledByAdminDialog.java
@@ -59,11 +59,15 @@
         }
         admin.component = intent.getParcelableExtra(DevicePolicyManager.EXTRA_DEVICE_ADMIN);
 
-        int userId = intent.getIntExtra(Intent.EXTRA_USER_ID, UserHandle.myUserId());
-        if (userId == UserHandle.USER_NULL) {
-            admin.user = null;
+        if (intent.hasExtra(Intent.EXTRA_USER)) {
+            admin.user = intent.getParcelableExtra(Intent.EXTRA_USER);
         } else {
-            admin.user = UserHandle.of(userId);
+            int userId = intent.getIntExtra(Intent.EXTRA_USER_ID, UserHandle.myUserId());
+            if (userId == UserHandle.USER_NULL) {
+                admin.user = null;
+            } else {
+                admin.user = UserHandle.of(userId);
+            }
         }
         return admin;
     }
diff --git a/src/com/android/settings/enterprise/ActionDisabledByAdminDialogHelper.java b/src/com/android/settings/enterprise/ActionDisabledByAdminDialogHelper.java
index f5010f9..5ca8fea 100644
--- a/src/com/android/settings/enterprise/ActionDisabledByAdminDialogHelper.java
+++ b/src/com/android/settings/enterprise/ActionDisabledByAdminDialogHelper.java
@@ -16,6 +16,7 @@
 
 package com.android.settings.enterprise;
 
+import android.annotation.NonNull;
 import android.annotation.UserIdInt;
 import android.app.Activity;
 import android.app.admin.DevicePolicyManager;
@@ -61,14 +62,18 @@
         mActivity = activity;
     }
 
-    private @UserIdInt int getEnforcementAdminUserId() {
-        if (mEnforcedAdmin.user == null) {
+    private @UserIdInt int getEnforcementAdminUserId(@NonNull EnforcedAdmin admin) {
+        if (admin.user == null) {
             return UserHandle.USER_NULL;
         } else {
-            return mEnforcedAdmin.user.getIdentifier();
+            return admin.user.getIdentifier();
         }
     }
 
+    private @UserIdInt int getEnforcementAdminUserId() {
+        return getEnforcementAdminUserId(mEnforcedAdmin);
+    }
+
     public AlertDialog.Builder prepareDialogBuilder(String restriction,
             EnforcedAdmin enforcedAdmin) {
         mEnforcedAdmin = enforcedAdmin;
@@ -170,18 +175,11 @@
             return;
         }
 
-        final int userId;
-        if (enforcedAdmin.user == null) {
-            userId = UserHandle.USER_NULL;
-        } else {
-            userId = enforcedAdmin.user.getIdentifier();
-        }
-
         final DevicePolicyManager dpm = (DevicePolicyManager) activity.getSystemService(
                 Context.DEVICE_POLICY_SERVICE);
         if (!RestrictedLockUtilsInternal.isAdminInCurrentUserOrProfile(activity,
                 enforcedAdmin.component) || !RestrictedLockUtils.isCurrentUserOrProfile(
-                activity, userId)) {
+                activity, getEnforcementAdminUserId(enforcedAdmin))) {
             enforcedAdmin.component = null;
         } else {
             if (enforcedAdmin.user == null) {
@@ -189,7 +187,8 @@
             }
             CharSequence supportMessage = null;
             if (UserHandle.isSameApp(Process.myUid(), Process.SYSTEM_UID)) {
-                supportMessage = dpm.getShortSupportMessageForUser(enforcedAdmin.component, userId);
+                supportMessage = dpm.getShortSupportMessageForUser(enforcedAdmin.component,
+                        getEnforcementAdminUserId(enforcedAdmin));
             }
             if (supportMessage != null) {
                 final TextView textView = root.findViewById(R.id.admin_support_msg);
diff --git a/src/com/android/settings/network/PrivateDnsPreferenceController.java b/src/com/android/settings/network/PrivateDnsPreferenceController.java
index 5618010..8b3bfa0 100644
--- a/src/com/android/settings/network/PrivateDnsPreferenceController.java
+++ b/src/com/android/settings/network/PrivateDnsPreferenceController.java
@@ -34,6 +34,8 @@
 import android.net.Uri;
 import android.os.Handler;
 import android.os.Looper;
+import android.os.UserHandle;
+import android.os.UserManager;
 import android.provider.Settings;
 
 import androidx.preference.Preference;
@@ -46,6 +48,8 @@
 import com.android.settingslib.core.lifecycle.LifecycleObserver;
 import com.android.settingslib.core.lifecycle.events.OnStart;
 import com.android.settingslib.core.lifecycle.events.OnStop;
+import com.android.settingslib.RestrictedLockUtilsInternal;
+import com.android.settingslib.RestrictedLockUtils.EnforcedAdmin;
 
 import java.net.InetAddress;
 import java.util.List;
@@ -136,6 +140,19 @@
         return "";
     }
 
+    @Override
+    public void updateState(Preference preference) {
+        super.updateState(preference);
+        //TODO(b/112982691): Add policy transparency explaining why this setting is disabled.
+        preference.setEnabled(!isManagedByAdmin());
+    }
+
+    private boolean isManagedByAdmin() {
+        EnforcedAdmin enforcedAdmin = RestrictedLockUtilsInternal.checkIfRestrictionEnforced(
+                mContext, UserManager.DISALLOW_CONFIG_PRIVATE_DNS, UserHandle.myUserId());
+        return enforcedAdmin != null;
+    }
+
     private class PrivateDnsSettingsObserver extends ContentObserver {
         public PrivateDnsSettingsObserver(Handler h) {
             super(h);
diff --git a/src/com/android/settings/network/telephony/CarrierPreferenceController.java b/src/com/android/settings/network/telephony/CarrierPreferenceController.java
new file mode 100644
index 0000000..957eaaa
--- /dev/null
+++ b/src/com/android/settings/network/telephony/CarrierPreferenceController.java
@@ -0,0 +1,68 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.settings.network.telephony;
+
+import android.content.Context;
+import android.os.PersistableBundle;
+import android.telephony.CarrierConfigManager;
+
+import androidx.annotation.VisibleForTesting;
+import androidx.preference.Preference;
+
+import com.android.settings.core.BasePreferenceController;
+
+/**
+ * Preference controller for "Carrier Settings"
+ */
+public class CarrierPreferenceController extends BasePreferenceController {
+
+    @VisibleForTesting
+    CarrierConfigManager mCarrierConfigManager;
+    private int mSubId;
+
+    public CarrierPreferenceController(Context context, String key) {
+        super(context, key);
+        mCarrierConfigManager = new CarrierConfigManager(context);
+    }
+
+    public void init(int subId) {
+        mSubId = subId;
+    }
+
+    @Override
+    public int getAvailabilityStatus() {
+        final PersistableBundle carrierConfig = mCarrierConfigManager.getConfigForSubId(mSubId);
+
+        // Return available if it is in CDMA or GSM mode, and the flag is on
+        return carrierConfig != null
+                && carrierConfig.getBoolean(CarrierConfigManager.KEY_CARRIER_SETTINGS_ENABLE_BOOL)
+                && (MobileNetworkUtils.isCdmaOptions(mContext, mSubId)
+                || MobileNetworkUtils.isGsmOptions(mContext, mSubId))
+                ? AVAILABLE
+                : CONDITIONALLY_UNAVAILABLE;
+    }
+
+    @Override
+    public boolean handlePreferenceTreeClick(Preference preference) {
+        if (getPreferenceKey().equals(preference.getKey())) {
+            //TODO(b/117651939): start carrier settings activity
+            return true;
+        }
+
+        return false;
+    }
+}
diff --git a/src/com/android/settings/network/telephony/CdmaOptions.java b/src/com/android/settings/network/telephony/CdmaOptions.java
index 2a2d8ba..c573128 100644
--- a/src/com/android/settings/network/telephony/CdmaOptions.java
+++ b/src/com/android/settings/network/telephony/CdmaOptions.java
@@ -16,25 +16,11 @@
 
 package com.android.settings.network.telephony;
 
-import android.content.Intent;
-import android.os.PersistableBundle;
-import android.os.SystemProperties;
-import android.provider.Settings;
-import android.telephony.CarrierConfigManager;
-import android.telephony.TelephonyManager;
-import android.text.TextUtils;
-
 import androidx.preference.Preference;
 import androidx.preference.PreferenceFragmentCompat;
 import androidx.preference.PreferenceScreen;
 
-import com.android.internal.annotations.VisibleForTesting;
-import com.android.internal.logging.MetricsLogger;
-import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
-import com.android.internal.telephony.PhoneConstants;
 import com.android.settings.R;
-import com.android.settingslib.RestrictedLockUtilsInternal;
-import com.android.settingslib.RestrictedPreference;
 
 /**
  * List of Phone-specific settings screens.
@@ -42,143 +28,18 @@
 public class CdmaOptions {
     private static final String LOG_TAG = "CdmaOptions";
 
-    private CarrierConfigManager mCarrierConfigManager;
-    private CdmaSystemSelectListPreference mButtonCdmaSystemSelect;
-    private CdmaSubscriptionListPreference mButtonCdmaSubscription;
-    private RestrictedPreference mButtonAPNExpand;
-    private Preference mCategoryAPNExpand;
-    private Preference mButtonCarrierSettings;
-
     private static final String BUTTON_CDMA_SYSTEM_SELECT_KEY = "cdma_system_select_key";
     private static final String BUTTON_CDMA_SUBSCRIPTION_KEY = "cdma_subscription_key";
-    private static final String BUTTON_CARRIER_SETTINGS_KEY = "carrier_settings_key";
-    private static final String BUTTON_APN_EXPAND_KEY = "button_cdma_apn_key";
-    private static final String CATEGORY_APN_EXPAND_KEY = "category_cdma_apn_key";
 
     private PreferenceFragmentCompat mPrefFragment;
-    private PreferenceScreen mPrefScreen;
-    private int mSubId;
 
-    public CdmaOptions(PreferenceFragmentCompat prefFragment, PreferenceScreen prefScreen, int subId) {
+    public CdmaOptions(PreferenceFragmentCompat prefFragment, PreferenceScreen prefScreen,
+            int subId) {
         mPrefFragment = prefFragment;
-        mPrefScreen = prefScreen;
-        mPrefFragment.addPreferencesFromResource(R.xml.cdma_options);
-        mCarrierConfigManager = new CarrierConfigManager(prefFragment.getContext());
-
-        // Initialize preferences.
-        mButtonCdmaSystemSelect = (CdmaSystemSelectListPreference) mPrefScreen
-                .findPreference(BUTTON_CDMA_SYSTEM_SELECT_KEY);
-        mButtonCdmaSubscription = (CdmaSubscriptionListPreference) mPrefScreen
-                .findPreference(BUTTON_CDMA_SUBSCRIPTION_KEY);
-        mButtonCarrierSettings = mPrefScreen.findPreference(BUTTON_CARRIER_SETTINGS_KEY);
-        mButtonAPNExpand = (RestrictedPreference) mPrefScreen.findPreference(BUTTON_APN_EXPAND_KEY);
-        mCategoryAPNExpand = mPrefScreen.findPreference(CATEGORY_APN_EXPAND_KEY);
-
-        updateSubscriptionId(subId);
-    }
-
-    protected void updateSubscriptionId(int subId) {
-        mSubId = subId;
-        int phoneType = TelephonyManager.from(mPrefFragment.getContext())
-                .createForSubscriptionId(mSubId).getPhoneType();
-
-        PersistableBundle carrierConfig = mCarrierConfigManager.getConfigForSubId(mSubId);
-        // Some CDMA carriers want the APN settings.
-        boolean addAPNExpand = shouldAddApnExpandPreference(phoneType, carrierConfig);
-        boolean addCdmaSubscription =
-                deviceSupportsNvAndRuim();
-        // Read platform settings for carrier settings
-        boolean addCarrierSettings =
-                carrierConfig.getBoolean(CarrierConfigManager.KEY_CARRIER_SETTINGS_ENABLE_BOOL);
-
-        mPrefScreen.addPreference(mButtonCdmaSystemSelect);
-        mButtonCdmaSystemSelect.setEnabled(true);
-
-        // Making no assumptions of whether they are added or removed at this point.
-        // Calling add or remove explicitly to make sure they are updated.
-
-        if (addAPNExpand) {
-            log("update: addAPNExpand");
-            mButtonAPNExpand.setDisabledByAdmin(
-                    MobileNetworkUtils.isDpcApnEnforced(mButtonAPNExpand.getContext())
-                            ? RestrictedLockUtilsInternal.getDeviceOwner(
-                                    mButtonAPNExpand.getContext())
-                            : null);
-            mButtonAPNExpand.setOnPreferenceClickListener(
-                    new Preference.OnPreferenceClickListener() {
-                        @Override
-                        public boolean onPreferenceClick(Preference preference) {
-                            MetricsLogger.action(mButtonAPNExpand.getContext(),
-                                    MetricsEvent.ACTION_MOBILE_NETWORK_APN_SETTINGS);
-                            // We need to build the Intent by hand as the Preference Framework
-                            // does not allow to add an Intent with some extras into a Preference
-                            // XML file
-                            final Intent intent = new Intent(Settings.ACTION_APN_SETTINGS);
-                            // This will setup the Home and Search affordance
-                            intent.putExtra(":settings:show_fragment_as_subsetting", true);
-                            intent.putExtra("sub_id", mSubId);
-                            mPrefFragment.startActivity(intent);
-                            return true;
-                        }
-                    });
-            mPrefScreen.addPreference(mCategoryAPNExpand);
-        } else {
-            mPrefScreen.removePreference(mCategoryAPNExpand);
-        }
-
-        if (addCdmaSubscription) {
-            log("Both NV and Ruim supported, ENABLE subscription type selection");
-            mPrefScreen.addPreference(mButtonCdmaSubscription);
-            mButtonCdmaSubscription.setEnabled(true);
-        } else {
-            log("Both NV and Ruim NOT supported, REMOVE subscription type selection");
-            mPrefScreen.removePreference(mButtonCdmaSubscription);
-        }
-
-        if (addCarrierSettings) {
-            mPrefScreen.addPreference(mButtonCarrierSettings);
-        } else {
-            mPrefScreen.removePreference(mButtonCarrierSettings);
-        }
-    }
-
-    /**
-     * Return whether we should add the APN expandable preference based on the phone type and
-     * carrier config
-     */
-    @VisibleForTesting
-    public static boolean shouldAddApnExpandPreference(int phoneType, PersistableBundle config) {
-        return phoneType == PhoneConstants.PHONE_TYPE_CDMA
-                && config.getBoolean(CarrierConfigManager.KEY_SHOW_APN_SETTING_CDMA_BOOL);
-    }
-
-    private boolean deviceSupportsNvAndRuim() {
-        // retrieve the list of subscription types supported by device.
-        String subscriptionsSupported = SystemProperties.get("ril.subscription.types");
-        boolean nvSupported = false;
-        boolean ruimSupported = false;
-
-        log("deviceSupportsnvAnRum: prop=" + subscriptionsSupported);
-        if (!TextUtils.isEmpty(subscriptionsSupported)) {
-            // Searches through the comma-separated list for a match for "NV"
-            // and "RUIM" to update nvSupported and ruimSupported.
-            for (String subscriptionType : subscriptionsSupported.split(",")) {
-                subscriptionType = subscriptionType.trim();
-                if (subscriptionType.equalsIgnoreCase("NV")) {
-                    nvSupported = true;
-                }
-                if (subscriptionType.equalsIgnoreCase("RUIM")) {
-                    ruimSupported = true;
-                }
-            }
-        }
-
-        log("deviceSupportsnvAnRum: nvSupported=" + nvSupported +
-                " ruimSupported=" + ruimSupported);
-        return (nvSupported && ruimSupported);
     }
 
     public boolean preferenceTreeClick(Preference preference) {
+        //TODO(b/114749736): handle it in preferenceController and remove this file
         if (preference.getKey().equals(BUTTON_CDMA_SYSTEM_SELECT_KEY)) {
             log("preferenceTreeClick: return BUTTON_CDMA_ROAMING_KEY true");
             return true;
@@ -190,14 +51,6 @@
         return false;
     }
 
-    public void showDialog(Preference preference) {
-        if (preference.getKey().equals(BUTTON_CDMA_SYSTEM_SELECT_KEY)) {
-            mButtonCdmaSystemSelect.showDialog(null);
-        } else if (preference.getKey().equals(BUTTON_CDMA_SUBSCRIPTION_KEY)) {
-            mButtonCdmaSubscription.showDialog(null);
-        }
-    }
-
     protected void log(String s) {
         android.util.Log.d(LOG_TAG, s);
     }
diff --git a/src/com/android/settings/network/telephony/CdmaSubscriptionListPreference.java b/src/com/android/settings/network/telephony/CdmaSubscriptionListPreference.java
deleted file mode 100644
index 559ba2d..0000000
--- a/src/com/android/settings/network/telephony/CdmaSubscriptionListPreference.java
+++ /dev/null
@@ -1,115 +0,0 @@
-/*
- * Copyright (C) 2018 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.settings.network.telephony;
-
-import android.content.Context;
-import android.os.Bundle;
-import androidx.preference.ListPreference;
-import android.provider.Settings;
-import android.telephony.TelephonyManager;
-import android.util.AttributeSet;
-import android.util.Log;
-
-import com.android.internal.telephony.Phone;
-import com.android.settingslib.utils.ThreadUtils;
-
-public class CdmaSubscriptionListPreference extends ListPreference {
-
-    private static final String LOG_TAG = "CdmaSubListPref";
-
-    // Used for CDMA subscription mode
-    private static final int CDMA_SUBSCRIPTION_RUIM_SIM = 0;
-    private static final int CDMA_SUBSCRIPTION_NV = 1;
-
-    //preferredSubscriptionMode  0 - RUIM/SIM, preferred
-    //                           1 - NV
-    static final int preferredSubscriptionMode = Phone.PREFERRED_CDMA_SUBSCRIPTION;
-
-    private TelephonyManager mTelephonyManager;
-
-    public CdmaSubscriptionListPreference(Context context, AttributeSet attrs) {
-        super(context, attrs);
-
-        mTelephonyManager = TelephonyManager.from(context);
-        setCurrentCdmaSubscriptionModeValue();
-    }
-
-    private void setCurrentCdmaSubscriptionModeValue() {
-        int cdmaSubscriptionMode = Settings.Global.getInt(getContext().getContentResolver(),
-                Settings.Global.CDMA_SUBSCRIPTION_MODE, preferredSubscriptionMode);
-        setValue(Integer.toString(cdmaSubscriptionMode));
-    }
-
-    public CdmaSubscriptionListPreference(Context context) {
-        this(context, null);
-    }
-
-    /**
-     * Sets the subscription id associated with this preference.
-     *
-     * @param subId the subscription id.
-     */
-    public void setSubscriptionId(int subId) {
-        mTelephonyManager = TelephonyManager.from(getContext()).createForSubscriptionId(subId);
-    }
-
-    //TODO(b/114749736): move this logic to preference controller
-    protected void showDialog(Bundle state) {
-        setCurrentCdmaSubscriptionModeValue();
-    }
-
-    //TODO(b/114749736): move this logic to preference controller
-    protected void onDialogClosed(boolean positiveResult) {
-        if (!positiveResult) {
-            //The button was dismissed - no need to set new value
-            return;
-        }
-
-        int buttonCdmaSubscriptionMode = Integer.parseInt(getValue());
-        Log.d(LOG_TAG, "Setting new value " + buttonCdmaSubscriptionMode);
-        int statusCdmaSubscriptionMode;
-        switch(buttonCdmaSubscriptionMode) {
-            case CDMA_SUBSCRIPTION_NV:
-                statusCdmaSubscriptionMode = Phone.CDMA_SUBSCRIPTION_NV;
-                break;
-            case CDMA_SUBSCRIPTION_RUIM_SIM:
-                statusCdmaSubscriptionMode = Phone.CDMA_SUBSCRIPTION_RUIM_SIM;
-                break;
-            default:
-                statusCdmaSubscriptionMode = Phone.PREFERRED_CDMA_SUBSCRIPTION;
-        }
-
-        // Set the CDMA subscription mode, when mode has been successfully changed, update the
-        // mode to the global setting.
-        ThreadUtils.postOnBackgroundThread(() -> {
-            // The subscription mode selected by user.
-            int cdmaSubscriptionMode = Integer.parseInt(getValue());
-
-            boolean isSuccessed = mTelephonyManager.setCdmaSubscriptionMode(
-                    statusCdmaSubscriptionMode);
-
-            // Update the global settings if successed.
-            if (isSuccessed) {
-                Settings.Global.putInt(getContext().getContentResolver(),
-                        Settings.Global.CDMA_SUBSCRIPTION_MODE,
-                        cdmaSubscriptionMode);
-            } else {
-                Log.e(LOG_TAG, "Setting Cdma subscription source failed");
-            }
-        });
-    }
-}
diff --git a/src/com/android/settings/network/telephony/CdmaSystemSelectListPreference.java b/src/com/android/settings/network/telephony/CdmaSystemSelectListPreference.java
deleted file mode 100644
index 5727a9a..0000000
--- a/src/com/android/settings/network/telephony/CdmaSystemSelectListPreference.java
+++ /dev/null
@@ -1,186 +0,0 @@
-/*
- * Copyright (C) 2018 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.settings.network.telephony;
-
-import android.content.Context;
-import android.os.Bundle;
-import android.os.Handler;
-import android.os.Message;
-import android.provider.Settings;
-import android.telephony.TelephonyManager;
-import android.util.AttributeSet;
-import android.util.Log;
-
-import com.android.settingslib.utils.ThreadUtils;
-
-import androidx.preference.ListPreference;
-
-public class CdmaSystemSelectListPreference extends ListPreference {
-
-    private static final String LOG_TAG = "CdmaRoamingListPref";
-    private static final boolean DBG = false;
-
-    private TelephonyManager mTelephonyManager;
-    private MyHandler mHandler = new MyHandler();
-
-    public CdmaSystemSelectListPreference(Context context, AttributeSet attrs) {
-        super(context, attrs);
-
-        mHandler = new MyHandler();
-        mTelephonyManager = TelephonyManager.from(context);
-    }
-
-    public CdmaSystemSelectListPreference(Context context) {
-        this(context, null);
-    }
-
-    /**
-     * Sets the subscription id associated with this preference.
-     *
-     * @param subId the subscription id.
-     */
-    public void setSubscriptionId(int subId) {
-        mTelephonyManager = TelephonyManager.from(getContext()).createForSubscriptionId(subId);
-        queryCdmaRoamingMode();
-    }
-
-    //TODO(b/114749736): Move this to preference controller
-    protected void showDialog(Bundle state) {
-        if (!mTelephonyManager.getEmergencyCallbackMode()) {
-            // show Dialog
-        }
-    }
-
-    //TODO(b/114749736): Move this to preference controller
-    protected void onDialogClosed(boolean positiveResult) {
-        if (positiveResult && (getValue() != null)) {
-            int buttonCdmaRoamingMode = Integer.parseInt(getValue());
-            int settingsCdmaRoamingMode = Settings.Global.getInt(
-                    getContext().getContentResolver(),
-                    Settings.Global.CDMA_ROAMING_MODE,
-                    TelephonyManager.CDMA_ROAMING_MODE_HOME);
-            if (buttonCdmaRoamingMode != settingsCdmaRoamingMode) {
-                int cdmaRoamingMode = TelephonyManager.CDMA_ROAMING_MODE_ANY;
-                if (buttonCdmaRoamingMode != TelephonyManager.CDMA_ROAMING_MODE_ANY) {
-                    cdmaRoamingMode = TelephonyManager.CDMA_ROAMING_MODE_HOME;
-                }
-                //Set the Settings.Secure network mode
-                Settings.Global.putInt(
-                        getContext().getContentResolver(),
-                        Settings.Global.CDMA_ROAMING_MODE,
-                        buttonCdmaRoamingMode);
-                //Set the roaming preference mode
-                setCdmaRoamingMode(cdmaRoamingMode);
-            }
-        } else {
-            Log.d(LOG_TAG, String.format("onDialogClosed: positiveResult=%b value=%s -- do nothing",
-                    positiveResult, getValue()));
-        }
-    }
-
-    private class MyHandler extends Handler {
-
-        static final int MESSAGE_GET_ROAMING_PREFERENCE = 0;
-        static final int MESSAGE_SET_ROAMING_PREFERENCE = 1;
-
-        @Override
-        public void handleMessage(Message msg) {
-            switch (msg.what) {
-                case MESSAGE_GET_ROAMING_PREFERENCE:
-                    handleQueryCdmaRoamingPreference(msg);
-                    break;
-
-                case MESSAGE_SET_ROAMING_PREFERENCE:
-                    handleSetCdmaRoamingPreference(msg);
-                    break;
-            }
-        }
-
-        private void handleQueryCdmaRoamingPreference(Message msg) {
-            int cdmaRoamingMode = msg.arg1;
-
-            if (cdmaRoamingMode != TelephonyManager.CDMA_ROAMING_MODE_RADIO_DEFAULT) {
-                int settingsRoamingMode = Settings.Global.getInt(
-                        getContext().getContentResolver(),
-                        Settings.Global.CDMA_ROAMING_MODE,
-                        TelephonyManager.CDMA_ROAMING_MODE_HOME);
-
-                //check that statusCdmaRoamingMode is from an accepted value
-                if (cdmaRoamingMode == TelephonyManager.CDMA_ROAMING_MODE_HOME
-                        || cdmaRoamingMode == TelephonyManager.CDMA_ROAMING_MODE_ANY) {
-                    //check changes in statusCdmaRoamingMode and updates settingsRoamingMode
-                    if (cdmaRoamingMode != settingsRoamingMode) {
-                        settingsRoamingMode = cdmaRoamingMode;
-                        //changes the Settings.Secure accordingly to statusCdmaRoamingMode
-                        Settings.Global.putInt(
-                                getContext().getContentResolver(),
-                                Settings.Global.CDMA_ROAMING_MODE,
-                                settingsRoamingMode);
-                    }
-                    //changes the mButtonPreferredNetworkMode accordingly to modemNetworkMode
-                    setValue(Integer.toString(cdmaRoamingMode));
-                }
-                else {
-                    if(DBG) Log.i(LOG_TAG, "reset cdma roaming mode to default" );
-                    resetCdmaRoamingModeToDefault();
-                }
-            }
-        }
-
-        private void handleSetCdmaRoamingPreference(Message msg) {
-            boolean isSuccessed = (boolean) msg.obj;
-
-            if (isSuccessed && (getValue() != null)) {
-                int cdmaRoamingMode = Integer.parseInt(getValue());
-                Settings.Global.putInt(
-                        getContext().getContentResolver(),
-                        Settings.Global.CDMA_ROAMING_MODE,
-                        cdmaRoamingMode );
-            } else {
-                queryCdmaRoamingMode();
-            }
-        }
-
-        private void resetCdmaRoamingModeToDefault() {
-            //set the mButtonCdmaRoam
-            setValue(Integer.toString(TelephonyManager.CDMA_ROAMING_MODE_ANY));
-            //set the Settings.System
-            Settings.Global.putInt(
-                    getContext().getContentResolver(),
-                    Settings.Global.CDMA_ROAMING_MODE,
-                    TelephonyManager.CDMA_ROAMING_MODE_ANY);
-            //Set the Status
-            setCdmaRoamingMode(TelephonyManager.CDMA_ROAMING_MODE_ANY);
-        }
-    }
-
-    private void queryCdmaRoamingMode() {
-        ThreadUtils.postOnBackgroundThread(() -> {
-            Message msg = mHandler.obtainMessage(MyHandler.MESSAGE_GET_ROAMING_PREFERENCE);
-            msg.arg1 = mTelephonyManager.getCdmaRoamingMode();
-            msg.sendToTarget();
-        });
-    }
-
-    private void setCdmaRoamingMode(int mode) {
-        ThreadUtils.postOnBackgroundThread(() -> {
-            Message msg = mHandler.obtainMessage(MyHandler.MESSAGE_SET_ROAMING_PREFERENCE);
-            msg.obj = mTelephonyManager.setCdmaRoamingMode(mode);
-            msg.sendToTarget();
-        });
-    }
-}
diff --git a/src/com/android/settings/network/telephony/DataUsagePreference.java b/src/com/android/settings/network/telephony/DataUsagePreference.java
deleted file mode 100644
index 437ba63..0000000
--- a/src/com/android/settings/network/telephony/DataUsagePreference.java
+++ /dev/null
@@ -1,79 +0,0 @@
-/*
- * Copyright (C) 2018 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.settings.network.telephony;
-
-import android.content.Context;
-import android.content.Intent;
-import android.net.NetworkTemplate;
-import androidx.preference.Preference;
-import android.provider.Settings;
-import android.telephony.TelephonyManager;
-import android.text.format.Formatter;
-import android.util.AttributeSet;
-
-import com.android.settings.R;
-import com.android.settingslib.net.DataUsageController;
-
-/**
- * The preference that shows mobile data usage summary and
- * leads to mobile data usage list page.
- */
-public class DataUsagePreference extends Preference {
-
-    private NetworkTemplate mTemplate;
-    private int mSubId;
-
-    public DataUsagePreference(Context context, AttributeSet attrs) {
-        super(context, attrs);
-    }
-
-    /**
-     * After creating this preference, this functions needs to be called to
-     * initialize which subID it connects to.
-     */
-    public void initialize(int subId) {
-        final Context context = getContext();
-        mSubId = subId;
-        mTemplate = getNetworkTemplate(context, subId);
-
-        DataUsageController controller = new DataUsageController(context);
-
-        DataUsageController.DataUsageInfo usageInfo = controller.getDataUsageInfo(mTemplate);
-        setSummary(context.getString(R.string.data_usage_template,
-                Formatter.formatFileSize(context, usageInfo.usageLevel), usageInfo.period));
-        setIntent(getIntent());
-    }
-
-    @Override
-    public Intent getIntent() {
-        Intent intent = new Intent(Settings.ACTION_MOBILE_DATA_USAGE);
-
-        intent.putExtra(Settings.EXTRA_NETWORK_TEMPLATE, mTemplate);
-        intent.putExtra(Settings.EXTRA_SUB_ID, mSubId);
-
-        return intent;
-    }
-
-    private NetworkTemplate getNetworkTemplate(Context context, int subId) {
-        TelephonyManager tm = (TelephonyManager) context
-                .getSystemService(Context.TELEPHONY_SERVICE);
-        NetworkTemplate mobileAll = NetworkTemplate.buildTemplateMobileAll(
-                tm.getSubscriberId(subId));
-        return NetworkTemplate.normalize(mobileAll,
-                tm.getMergedSubscriberIds());
-    }
-}
diff --git a/src/com/android/settings/network/telephony/DataUsagePreferenceController.java b/src/com/android/settings/network/telephony/DataUsagePreferenceController.java
new file mode 100644
index 0000000..07c58c1
--- /dev/null
+++ b/src/com/android/settings/network/telephony/DataUsagePreferenceController.java
@@ -0,0 +1,100 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.settings.network.telephony;
+
+import android.content.Context;
+import android.content.Intent;
+import android.net.NetworkTemplate;
+import android.provider.Settings;
+import android.telephony.SubscriptionManager;
+import android.telephony.TelephonyManager;
+import android.text.TextUtils;
+import android.text.format.Formatter;
+
+import androidx.preference.Preference;
+
+import com.android.settings.R;
+import com.android.settings.core.BasePreferenceController;
+import com.android.settingslib.net.DataUsageController;
+
+/**
+ * Preference controller for "Data usage"
+ */
+public class DataUsagePreferenceController extends BasePreferenceController {
+
+    private NetworkTemplate mTemplate;
+    private DataUsageController.DataUsageInfo mDataUsageInfo;
+    private Intent mIntent;
+    private int mSubId;
+
+    public DataUsagePreferenceController(Context context, String key) {
+        super(context, key);
+    }
+
+    @Override
+    public int getAvailabilityStatus() {
+        return mSubId != SubscriptionManager.INVALID_SUBSCRIPTION_ID
+                ? AVAILABLE
+                : AVAILABLE_UNSEARCHABLE;
+    }
+
+    @Override
+    public boolean handlePreferenceTreeClick(Preference preference) {
+        if (TextUtils.equals(preference.getKey(), getPreferenceKey())) {
+            mContext.startActivity(mIntent);
+            return true;
+        }
+
+        return false;
+    }
+
+    @Override
+    public void updateState(Preference preference) {
+        super.updateState(preference);
+        final boolean enabled = mSubId != SubscriptionManager.INVALID_SUBSCRIPTION_ID;
+        preference.setEnabled(enabled);
+
+        if (enabled) {
+            preference.setSummary(mContext.getString(R.string.data_usage_template,
+                    Formatter.formatFileSize(mContext, mDataUsageInfo.usageLevel),
+                    mDataUsageInfo.period));
+        }
+    }
+
+    public void init(int subId) {
+        mSubId = subId;
+
+        if (mSubId != SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
+            mTemplate = getNetworkTemplate(mContext, subId);
+
+            final DataUsageController controller = new DataUsageController(mContext);
+            mDataUsageInfo = controller.getDataUsageInfo(mTemplate);
+
+            mIntent = new Intent(Settings.ACTION_MOBILE_DATA_USAGE);
+            mIntent.putExtra(Settings.EXTRA_NETWORK_TEMPLATE, mTemplate);
+            mIntent.putExtra(Settings.EXTRA_SUB_ID, mSubId);
+        }
+    }
+
+    private NetworkTemplate getNetworkTemplate(Context context, int subId) {
+        final TelephonyManager tm = TelephonyManager.from(context).createForSubscriptionId(subId);
+        NetworkTemplate mobileAll = NetworkTemplate.buildTemplateMobileAll(tm.getSubscriberId());
+
+        return NetworkTemplate.normalize(mobileAll, tm.getMergedSubscriberIds());
+    }
+
+}
diff --git a/src/com/android/settings/network/telephony/MobileNetworkFragment.java b/src/com/android/settings/network/telephony/MobileNetworkFragment.java
index 106d940..5e6f5d5 100644
--- a/src/com/android/settings/network/telephony/MobileNetworkFragment.java
+++ b/src/com/android/settings/network/telephony/MobileNetworkFragment.java
@@ -49,6 +49,14 @@
 import android.util.Log;
 import android.view.MenuItem;
 
+import androidx.fragment.app.FragmentActivity;
+import androidx.preference.ListPreference;
+import androidx.preference.Preference;
+import androidx.preference.PreferenceCategory;
+import androidx.preference.PreferenceFragmentCompat;
+import androidx.preference.PreferenceScreen;
+import androidx.preference.SwitchPreference;
+
 import com.android.ims.ImsConfig;
 import com.android.ims.ImsManager;
 import com.android.internal.logging.MetricsLogger;
@@ -58,6 +66,9 @@
 import com.android.internal.telephony.TelephonyIntents;
 import com.android.settings.R;
 import com.android.settings.dashboard.DashboardFragment;
+import com.android.settings.network.telephony.cdma.CdmaApnPreferenceController;
+import com.android.settings.network.telephony.cdma.CdmaSubscriptionPreferenceController;
+import com.android.settings.network.telephony.cdma.CdmaSystemSelectPreferenceController;
 import com.android.settings.search.BaseSearchIndexProvider;
 import com.android.settings.search.Indexable;
 import com.android.settingslib.RestrictedLockUtilsInternal;
@@ -68,14 +79,6 @@
 import java.util.Iterator;
 import java.util.List;
 
-import androidx.fragment.app.FragmentActivity;
-import androidx.preference.ListPreference;
-import androidx.preference.Preference;
-import androidx.preference.PreferenceCategory;
-import androidx.preference.PreferenceFragmentCompat;
-import androidx.preference.PreferenceScreen;
-import androidx.preference.SwitchPreference;
-
 @SearchIndexable(forTarget = SearchIndexable.ALL & ~SearchIndexable.ARC)
 public class MobileNetworkFragment extends DashboardFragment implements
         Preference.OnPreferenceChangeListener, RoamingDialogFragment.RoamingDialogListener {
@@ -158,7 +161,9 @@
     private Preference mWiFiCallingPref;
     private SwitchPreference mVideoCallingPref;
     private NetworkSelectListPreference mButtonNetworkSelect;
-    private DataUsagePreference mDataUsagePref;
+
+    private CdmaSystemSelectPreferenceController mCdmaSystemSelectPreferenceController;
+    private CdmaSubscriptionPreferenceController mCdmaSubscriptionPreferenceController;
 
     private static final String iface = "rmnet0"; //TODO: this will go away
     private List<SubscriptionInfo> mActiveSubInfos;
@@ -301,8 +306,7 @@
             Intent intent = new Intent(EuiccManager.ACTION_MANAGE_EMBEDDED_SUBSCRIPTIONS);
             startActivity(intent);
             return true;
-        } else if (preference == mWiFiCallingPref || preference == mVideoCallingPref
-                || preference == mDataUsagePref) {
+        } else if (preference == mWiFiCallingPref || preference == mVideoCallingPref) {
             return false;
         } else {
             // if the button is anything but the simple toggle preference,
@@ -394,6 +398,14 @@
                 SubscriptionManager.INVALID_SUBSCRIPTION_ID);
 
         use(MobileDataPreferenceController.class).init(getFragmentManager(), mSubId);
+        use(CdmaApnPreferenceController.class).init(mSubId);
+        use(CarrierPreferenceController.class).init(mSubId);
+        use(DataUsagePreferenceController.class).init(mSubId);
+
+        mCdmaSystemSelectPreferenceController = use(CdmaSystemSelectPreferenceController.class);
+        mCdmaSystemSelectPreferenceController.init(getPreferenceManager(), mSubId);
+        mCdmaSubscriptionPreferenceController = use(CdmaSubscriptionPreferenceController.class);
+        mCdmaSubscriptionPreferenceController.init(getPreferenceManager(), mSubId);
     }
 
     @Override
@@ -420,7 +432,6 @@
         mCallingCategory = (PreferenceCategory) findPreference(CATEGORY_CALLING_KEY);
         mWiFiCallingPref = findPreference(BUTTON_WIFI_CALLING_KEY);
         mVideoCallingPref = (SwitchPreference) findPreference(BUTTON_VIDEO_CALLING_KEY);
-        mDataUsagePref = (DataUsagePreference) findPreference(BUTTON_DATA_USAGE_KEY);
 
         try {
             Context con = context.createPackageContext("com.android.systemui", 0);
@@ -570,14 +581,10 @@
         }
 
         prefSet.addPreference(mButtonDataRoam);
-        prefSet.addPreference(mDataUsagePref);
 
         mButtonDataRoam.setEnabled(hasActiveSubscriptions);
-        mDataUsagePref.setEnabled(hasActiveSubscriptions);
 
         if (hasActiveSubscriptions) {
-            // Customized preferences needs to be initialized with subId.
-            mDataUsagePref.initialize(phoneSubId);
 
             // Initialize states of mButtonDataRoam.
             mButtonDataRoam.setChecked(mTelephonyManager.isDataRoamingEnabled());
@@ -718,19 +725,6 @@
             }
         }
 
-        /**
-         * Listen to extra preference changes that need as Metrics events logging.
-         */
-        if (prefSet.findPreference(BUTTON_CDMA_SYSTEM_SELECT_KEY) != null) {
-            prefSet.findPreference(BUTTON_CDMA_SYSTEM_SELECT_KEY)
-                    .setOnPreferenceChangeListener(this);
-        }
-
-        if (prefSet.findPreference(BUTTON_CDMA_SUBSCRIPTION_KEY) != null) {
-            prefSet.findPreference(BUTTON_CDMA_SUBSCRIPTION_KEY)
-                    .setOnPreferenceChangeListener(this);
-        }
-
         // Get the networkMode from Settings.System and displays it
         mButtonEnabledNetworks.setValue(Integer.toString(settingsNetworkMode));
         mButtonPreferredNetworkMode.setValue(Integer.toString(settingsNetworkMode));
@@ -784,10 +778,6 @@
         if (ps != null) {
             ps.setEnabled(hasActiveSubscriptions);
         }
-        ps = findPreference(BUTTON_CDMA_SYSTEM_SELECT_KEY);
-        if (ps != null) {
-            ps.setEnabled(hasActiveSubscriptions);
-        }
         ps = findPreference(CATEGORY_CALLING_KEY);
         if (ps != null) {
             ps.setEnabled(hasActiveSubscriptions);
@@ -1095,11 +1085,6 @@
                 mVideoCallingPref.setEnabled(false);
                 return false;
             }
-        } else if (preference == getPreferenceScreen()
-                .findPreference(BUTTON_CDMA_SYSTEM_SELECT_KEY)
-                || preference == getPreferenceScreen()
-                .findPreference(BUTTON_CDMA_SUBSCRIPTION_KEY)) {
-            return true;
         }
 
         updateBody();
@@ -1429,13 +1414,20 @@
 
     @Override
     public void onActivityResult(int requestCode, int resultCode, Intent data) {
-        switch(requestCode) {
+        switch (requestCode) {
             case REQUEST_CODE_EXIT_ECM:
                 Boolean isChoiceYes = data.getBooleanExtra(
                         EXTRA_EXIT_ECM_RESULT, false);
                 if (isChoiceYes) {
                     // If the phone exits from ECM mode, show the CDMA Options
-                    mCdmaOptions.showDialog(mClickedPreference);
+                    final String key = mClickedPreference.getKey();
+                    if (TextUtils.equals(key,
+                            mCdmaSystemSelectPreferenceController.getPreferenceKey())) {
+                        mCdmaSystemSelectPreferenceController.showDialog();
+                    } else if (TextUtils.equals(key,
+                            mCdmaSubscriptionPreferenceController.getPreferenceKey())) {
+                        mCdmaSubscriptionPreferenceController.showDialog();
+                    }
                 } else {
                     // do nothing
                 }
@@ -1665,13 +1657,6 @@
             return;
         }
         updateCdmaOptions(this, prefSet, mSubId);
-        CdmaSystemSelectListPreference systemSelect =
-                (CdmaSystemSelectListPreference)prefSet.findPreference
-                        (BUTTON_CDMA_SYSTEM_SELECT_KEY);
-        systemSelect.setSubscriptionId(mSubId);
-        if (systemSelect != null) {
-            systemSelect.setEnabled(enable);
-        }
     }
 
     private boolean isSupportTdscdma() {
@@ -1710,7 +1695,7 @@
         // For ListPreferences, we log it here without a value, only indicating it's clicked to
         // open the list dialog. When a value is chosen, another MetricsEvent is logged with
         // new value in onPreferenceChange.
-        if (preference == mLteDataServicePref || preference == mDataUsagePref
+        if (preference == mLteDataServicePref
                 || preference == mEuiccSettingsPref
                 || preference == mWiFiCallingPref || preference == mButtonPreferredNetworkMode
                 || preference == mButtonEnabledNetworks
@@ -1751,8 +1736,6 @@
             return MetricsProto.MetricsEvent.VIEW_UNKNOWN;
         } else if (preference == mButtonDataRoam) {
             return MetricsProto.MetricsEvent.ACTION_MOBILE_NETWORK_DATA_ROAMING_TOGGLE;
-        } else if (preference == mDataUsagePref) {
-            return MetricsProto.MetricsEvent.ACTION_MOBILE_NETWORK_DATA_USAGE;
         } else if (preference == mLteDataServicePref) {
             return MetricsProto.MetricsEvent.ACTION_MOBILE_NETWORK_SET_UP_DATA_SERVICE;
         } else if (preference == mButton4glte) {
@@ -1808,8 +1791,6 @@
         // the open dialog gets dismissed or detached after pause / resume.
         if (mCdmaOptions == null) {
             mCdmaOptions = new CdmaOptions(prefFragment, prefScreen, subId);
-        } else {
-            mCdmaOptions.updateSubscriptionId(subId);
         }
     }
 
diff --git a/src/com/android/settings/network/telephony/MobileNetworkUtils.java b/src/com/android/settings/network/telephony/MobileNetworkUtils.java
index 5e78e07..8950178 100644
--- a/src/com/android/settings/network/telephony/MobileNetworkUtils.java
+++ b/src/com/android/settings/network/telephony/MobileNetworkUtils.java
@@ -41,6 +41,9 @@
 
 import com.android.ims.ImsException;
 import com.android.ims.ImsManager;
+import com.android.internal.telephony.Phone;
+import com.android.internal.telephony.PhoneConstants;
+import com.android.settings.R;
 
 import java.util.Arrays;
 import java.util.List;
@@ -238,4 +241,100 @@
             }
         }
     }
+
+    /**
+     * Return {@code true} if show CDMA category
+     */
+    public static boolean isCdmaOptions(Context context, int subId) {
+        if (subId == SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
+            return false;
+        }
+        final TelephonyManager telephonyManager = TelephonyManager.from(context)
+                .createForSubscriptionId(subId);
+
+        if (telephonyManager.getPhoneType() == PhoneConstants.PHONE_TYPE_CDMA) {
+            return true;
+        }
+
+        if (isWorldMode(context, subId)) {
+            final int settingsNetworkMode = android.provider.Settings.Global.getInt(
+                    context.getContentResolver(),
+                    android.provider.Settings.Global.PREFERRED_NETWORK_MODE + subId,
+                    Phone.PREFERRED_NT_MODE);
+            if (settingsNetworkMode == TelephonyManager.NETWORK_MODE_LTE_GSM_WCDMA
+                    || settingsNetworkMode == TelephonyManager.NETWORK_MODE_LTE_CDMA_EVDO) {
+                return true;
+            }
+
+            if (settingsNetworkMode == TelephonyManager.NETWORK_MODE_LTE_CDMA_EVDO_GSM_WCDMA
+                    && !isTdscdmaSupported(context, telephonyManager)) {
+                return true;
+            }
+        }
+
+        return false;
+    }
+
+    public static boolean isGsmOptions(Context context, int subId) {
+        if (subId == SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
+            return false;
+        }
+        final TelephonyManager telephonyManager = TelephonyManager.from(context)
+                .createForSubscriptionId(subId);
+
+        if (telephonyManager.getPhoneType() == PhoneConstants.PHONE_TYPE_GSM) {
+            return true;
+        }
+
+        return false;
+    }
+
+    /**
+     * Return {@code true} if it is world mode, and we may show advanced options in telephony
+     * settings
+     */
+    public static boolean isWorldMode(Context context, int subId) {
+        final TelephonyManager telephonyManager = TelephonyManager.from(context)
+                .createForSubscriptionId(subId);
+        boolean worldModeOn = false;
+        final String configString = context.getString(R.string.config_world_mode);
+
+        if (!TextUtils.isEmpty(configString)) {
+            String[] configArray = configString.split(";");
+            // Check if we have World mode configuration set to True only or config is set to True
+            // and SIM GID value is also set and matches to the current SIM GID.
+            if (configArray != null &&
+                    ((configArray.length == 1 && configArray[0].equalsIgnoreCase("true"))
+                            || (configArray.length == 2 && !TextUtils.isEmpty(configArray[1])
+                            && telephonyManager != null
+                            && configArray[1].equalsIgnoreCase(
+                            telephonyManager.getGroupIdLevel1())))) {
+                worldModeOn = true;
+            }
+        }
+
+        Log.d(TAG, "isWorldMode=" + worldModeOn);
+
+        return worldModeOn;
+    }
+
+    //TODO(b/117651939): move it to telephony
+    private static boolean isTdscdmaSupported(Context context, TelephonyManager telephonyManager) {
+        if (context.getResources().getBoolean(R.bool.config_support_tdscdma)) {
+            return true;
+        }
+
+        String operatorNumeric = telephonyManager.getServiceState().getOperatorNumeric();
+        String[] numericArray = context.getResources().getStringArray(
+                R.array.config_support_tdscdma_roaming_on_networks);
+        if (numericArray.length == 0 || operatorNumeric == null) {
+            return false;
+        }
+        for (String numeric : numericArray) {
+            if (operatorNumeric.equals(numeric)) {
+                return true;
+            }
+        }
+        return false;
+    }
 }
\ No newline at end of file
diff --git a/src/com/android/settings/network/telephony/cdma/CdmaApnPreferenceController.java b/src/com/android/settings/network/telephony/cdma/CdmaApnPreferenceController.java
new file mode 100644
index 0000000..eaacdb2
--- /dev/null
+++ b/src/com/android/settings/network/telephony/cdma/CdmaApnPreferenceController.java
@@ -0,0 +1,87 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.settings.network.telephony.cdma;
+
+import android.content.Context;
+import android.content.Intent;
+import android.os.PersistableBundle;
+import android.provider.Settings;
+import android.telephony.CarrierConfigManager;
+
+import androidx.annotation.VisibleForTesting;
+import androidx.preference.Preference;
+import androidx.preference.PreferenceScreen;
+
+import com.android.settings.SettingsActivity;
+import com.android.settings.network.ApnSettings;
+import com.android.settings.network.telephony.MobileNetworkUtils;
+import com.android.settingslib.RestrictedLockUtilsInternal;
+import com.android.settingslib.RestrictedPreference;
+
+/**
+ * Preference controller for "CDMA Apn"
+ */
+public class CdmaApnPreferenceController extends CdmaBasePreferenceController {
+
+    private static final String CATEGORY_KEY = "category_cdma_apn_key";
+    @VisibleForTesting
+    CarrierConfigManager mCarrierConfigManager;
+
+    public CdmaApnPreferenceController(Context context, String key) {
+        super(context, key);
+        mCarrierConfigManager = new CarrierConfigManager(context);
+    }
+
+    @Override
+    public int getAvailabilityStatus() {
+        final PersistableBundle carrierConfig = mCarrierConfigManager.getConfigForSubId(mSubId);
+
+        return carrierConfig != null
+                && carrierConfig.getBoolean(CarrierConfigManager.KEY_SHOW_APN_SETTING_CDMA_BOOL)
+                && MobileNetworkUtils.isCdmaOptions(mContext, mSubId)
+                ? AVAILABLE
+                : CONDITIONALLY_UNAVAILABLE;
+    }
+
+    @Override
+    public void displayPreference(PreferenceScreen screen) {
+        super.displayPreference(screen);
+        if (isAvailable()) {
+            ((RestrictedPreference) mPreference).setDisabledByAdmin(
+                    MobileNetworkUtils.isDpcApnEnforced(mContext)
+                            ? RestrictedLockUtilsInternal.getDeviceOwner(mContext)
+                            : null);
+        } else {
+            screen.findPreference(CATEGORY_KEY).setVisible(false);
+        }
+    }
+
+    @Override
+    public boolean handlePreferenceTreeClick(Preference preference) {
+        if (getPreferenceKey().equals(preference.getKey())) {
+            // This activity runs in phone process, we must use intent to start
+            final Intent intent = new Intent(Settings.ACTION_APN_SETTINGS);
+            // This will setup the Home and Search affordance
+            intent.putExtra(SettingsActivity.EXTRA_SHOW_FRAGMENT_AS_SUBSETTING, true);
+            intent.putExtra(ApnSettings.SUB_ID, mSubId);
+            mContext.startActivity(intent);
+            return true;
+        }
+
+        return false;
+    }
+}
diff --git a/src/com/android/settings/network/telephony/cdma/CdmaBasePreferenceController.java b/src/com/android/settings/network/telephony/cdma/CdmaBasePreferenceController.java
new file mode 100644
index 0000000..3e9ebc6
--- /dev/null
+++ b/src/com/android/settings/network/telephony/cdma/CdmaBasePreferenceController.java
@@ -0,0 +1,112 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.settings.network.telephony.cdma;
+
+import android.content.Context;
+import android.database.ContentObserver;
+import android.net.Uri;
+import android.os.Handler;
+import android.os.Looper;
+import android.provider.Settings;
+import android.telephony.TelephonyManager;
+
+import androidx.preference.Preference;
+import androidx.preference.PreferenceManager;
+import androidx.preference.PreferenceScreen;
+
+import com.android.settings.core.BasePreferenceController;
+import com.android.settings.network.telephony.MobileNetworkUtils;
+import com.android.settingslib.core.lifecycle.LifecycleObserver;
+import com.android.settingslib.core.lifecycle.events.OnStart;
+import com.android.settingslib.core.lifecycle.events.OnStop;
+
+/**
+ * Preference controller related to CDMA category
+ */
+public abstract class CdmaBasePreferenceController extends BasePreferenceController
+        implements LifecycleObserver, OnStart, OnStop {
+
+    protected Preference mPreference;
+    protected TelephonyManager mTelephonyManager;
+    protected PreferenceManager mPreferenceManager;
+    protected int mSubId;
+    private DataContentObserver mDataContentObserver;
+
+    public CdmaBasePreferenceController(Context context, String key) {
+        super(context, key);
+        mDataContentObserver = new DataContentObserver(new Handler(Looper.getMainLooper()));
+    }
+
+    @Override
+    public void onStart() {
+        mDataContentObserver.register(mContext, mSubId);
+    }
+
+    @Override
+    public void onStop() {
+        mDataContentObserver.unRegister(mContext);
+    }
+
+    @Override
+    public int getAvailabilityStatus() {
+        return MobileNetworkUtils.isCdmaOptions(mContext, mSubId)
+                ? AVAILABLE
+                : CONDITIONALLY_UNAVAILABLE;
+    }
+
+    public void init(PreferenceManager preferenceManager, int subId) {
+        mPreferenceManager = preferenceManager;
+        mSubId = subId;
+        mTelephonyManager = TelephonyManager.from(mContext).createForSubscriptionId(mSubId);
+    }
+
+    public void init(int subId) {
+        init(null, subId);
+    }
+
+    @Override
+    public void displayPreference(PreferenceScreen screen) {
+        super.displayPreference(screen);
+        mPreference = screen.findPreference(getPreferenceKey());
+    }
+
+    /**
+     * Listener that listens to mobile data state change.
+     */
+    public class DataContentObserver extends ContentObserver {
+
+        public DataContentObserver(Handler handler) {
+            super(handler);
+        }
+
+        @Override
+        public void onChange(boolean selfChange) {
+            super.onChange(selfChange);
+            updateState(mPreference);
+        }
+
+        public void register(Context context, int subId) {
+            final Uri uri = Settings.Global.getUriFor(
+                    Settings.Global.PREFERRED_NETWORK_MODE + subId);
+            context.getContentResolver().registerContentObserver(uri, false, this);
+        }
+
+        public void unRegister(Context context) {
+            context.getContentResolver().unregisterContentObserver(this);
+        }
+    }
+}
diff --git a/src/com/android/settings/network/telephony/cdma/CdmaSubscriptionPreferenceController.java b/src/com/android/settings/network/telephony/cdma/CdmaSubscriptionPreferenceController.java
new file mode 100644
index 0000000..eb14664
--- /dev/null
+++ b/src/com/android/settings/network/telephony/cdma/CdmaSubscriptionPreferenceController.java
@@ -0,0 +1,110 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.settings.network.telephony.cdma;
+
+import android.content.Context;
+import android.os.SystemProperties;
+import android.provider.Settings;
+import android.telephony.TelephonyManager;
+import android.text.TextUtils;
+
+import androidx.annotation.VisibleForTesting;
+import androidx.preference.ListPreference;
+import androidx.preference.Preference;
+import androidx.preference.PreferenceManager;
+
+import com.android.internal.telephony.Phone;
+import com.android.settings.network.telephony.MobileNetworkUtils;
+
+/**
+ * Preference controller for "CDMA subscription"
+ */
+public class CdmaSubscriptionPreferenceController extends CdmaBasePreferenceController
+        implements ListPreference.OnPreferenceChangeListener {
+    private static final String TYPE_NV = "NV";
+    private static final String TYPE_RUIM = "RUIM";
+
+    @VisibleForTesting
+    ListPreference mPreference;
+
+    public CdmaSubscriptionPreferenceController(Context context, String key) {
+        super(context, key);
+    }
+
+    @Override
+    public int getAvailabilityStatus() {
+        return MobileNetworkUtils.isCdmaOptions(mContext, mSubId) && deviceSupportsNvAndRuim()
+                ? AVAILABLE
+                : CONDITIONALLY_UNAVAILABLE;
+    }
+
+    @Override
+    public void updateState(Preference preference) {
+        super.updateState(preference);
+        final ListPreference listPreference = (ListPreference) preference;
+        listPreference.setVisible(getAvailabilityStatus() == AVAILABLE);
+        final int mode = Settings.Global.getInt(mContext.getContentResolver(),
+                Settings.Global.CDMA_SUBSCRIPTION_MODE, Phone.PREFERRED_CDMA_SUBSCRIPTION);
+        if (mode != Phone.CDMA_SUBSCRIPTION_UNKNOWN) {
+            listPreference.setValue(Integer.toString(mode));
+        }
+    }
+
+    @Override
+    public boolean onPreferenceChange(Preference preference, Object object) {
+        final int newMode = Integer.parseInt((String) object);
+        //TODO(b/117611981): only set it in one place
+        if (mTelephonyManager.setCdmaSubscriptionMode(newMode)) {
+            Settings.Global.putInt(mContext.getContentResolver(),
+                    Settings.Global.CDMA_SUBSCRIPTION_MODE, newMode);
+            return true;
+        }
+
+        return false;
+    }
+
+    public void showDialog() {
+        final int mode = Settings.Global.getInt(mContext.getContentResolver(),
+                Settings.Global.CDMA_SUBSCRIPTION_MODE, Phone.PREFERRED_CDMA_SUBSCRIPTION);
+
+        mPreference.setValue(Integer.toString(mode));
+        mPreferenceManager.showDialog(mPreference);
+    }
+
+    @VisibleForTesting
+    boolean deviceSupportsNvAndRuim() {
+        // retrieve the list of subscription types supported by device.
+        final String subscriptionsSupported = SystemProperties.get("ril.subscription.types");
+        boolean nvSupported = false;
+        boolean ruimSupported = false;
+
+        if (!TextUtils.isEmpty(subscriptionsSupported)) {
+            // Searches through the comma-separated list for a match for "NV"
+            // and "RUIM" to update nvSupported and ruimSupported.
+            for (String subscriptionType : subscriptionsSupported.split(",")) {
+                subscriptionType = subscriptionType.trim();
+                if (subscriptionType.equalsIgnoreCase(TYPE_NV)) {
+                    nvSupported = true;
+                } else if (subscriptionType.equalsIgnoreCase(TYPE_RUIM)) {
+                    ruimSupported = true;
+                }
+            }
+        }
+
+        return (nvSupported && ruimSupported);
+    }
+}
diff --git a/src/com/android/settings/network/telephony/cdma/CdmaSystemSelectPreferenceController.java b/src/com/android/settings/network/telephony/cdma/CdmaSystemSelectPreferenceController.java
new file mode 100644
index 0000000..95e5dae
--- /dev/null
+++ b/src/com/android/settings/network/telephony/cdma/CdmaSystemSelectPreferenceController.java
@@ -0,0 +1,81 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.settings.network.telephony.cdma;
+
+import android.content.Context;
+import android.provider.Settings;
+import android.telephony.TelephonyManager;
+
+import androidx.preference.ListPreference;
+import androidx.preference.Preference;
+
+/**
+ * Preference controller for "System Select"
+ */
+public class CdmaSystemSelectPreferenceController extends CdmaBasePreferenceController
+        implements ListPreference.OnPreferenceChangeListener {
+
+    public CdmaSystemSelectPreferenceController(Context context, String key) {
+        super(context, key);
+    }
+
+    @Override
+    public void updateState(Preference preference) {
+        super.updateState(preference);
+        final ListPreference listPreference = (ListPreference) preference;
+        listPreference.setVisible(getAvailabilityStatus() == AVAILABLE);
+        final int mode = mTelephonyManager.getCdmaRoamingMode();
+        if (mode != TelephonyManager.CDMA_ROAMING_MODE_RADIO_DEFAULT) {
+            if (mode == TelephonyManager.CDMA_ROAMING_MODE_HOME
+                    || mode == TelephonyManager.CDMA_ROAMING_MODE_ANY) {
+                listPreference.setValue(Integer.toString(mode));
+            } else {
+                resetCdmaRoamingModeToDefault();
+            }
+        }
+    }
+
+    @Override
+    public boolean onPreferenceChange(Preference preference, Object object) {
+        int newMode = Integer.parseInt((String) object);
+        //TODO(b/117611981): only set it in one place
+        if (mTelephonyManager.setCdmaRoamingMode(newMode)) {
+            Settings.Global.putInt(mContext.getContentResolver(),
+                    Settings.Global.CDMA_ROAMING_MODE, newMode);
+            return true;
+        }
+
+        return false;
+    }
+
+    public void showDialog() {
+        if (!mTelephonyManager.getEmergencyCallbackMode()) {
+            mPreferenceManager.showDialog(mPreference);
+        }
+    }
+
+    private void resetCdmaRoamingModeToDefault() {
+        final ListPreference listPreference = (ListPreference) mPreference;
+        //set the mButtonCdmaRoam
+        listPreference.setValue(Integer.toString(TelephonyManager.CDMA_ROAMING_MODE_ANY));
+        //set the Settings.System
+        Settings.Global.putInt(mContext.getContentResolver(), Settings.Global.CDMA_ROAMING_MODE,
+                TelephonyManager.CDMA_ROAMING_MODE_ANY);
+        //Set the Status
+        mTelephonyManager.setCdmaRoamingMode(TelephonyManager.CDMA_ROAMING_MODE_ANY);
+    }
+}
diff --git a/src/com/android/settings/webview/WebViewAppPicker.java b/src/com/android/settings/webview/WebViewAppPicker.java
index b96217e..72d7918 100644
--- a/src/com/android/settings/webview/WebViewAppPicker.java
+++ b/src/com/android/settings/webview/WebViewAppPicker.java
@@ -118,9 +118,9 @@
     }
 
     private static class WebViewAppInfo extends DefaultAppInfo {
-        public WebViewAppInfo(Context context, PackageManager pm,
+        public WebViewAppInfo(Context context, PackageManager pm, int userId,
                 PackageItemInfo packageItemInfo, String summary, boolean enabled) {
-            super(context, pm, packageItemInfo, summary, enabled);
+            super(context, pm, userId, packageItemInfo, summary, enabled);
         }
 
         @Override
@@ -138,7 +138,7 @@
     @VisibleForTesting
     DefaultAppInfo createDefaultAppInfo(Context context, PackageManager pm,
             PackageItemInfo packageItemInfo, String disabledReason) {
-        return new WebViewAppInfo(context, pm, packageItemInfo, disabledReason,
+        return new WebViewAppInfo(context, pm, mUserId, packageItemInfo, disabledReason,
                 TextUtils.isEmpty(disabledReason) /* enabled */);
     }
 
diff --git a/tests/robotests/src/com/android/settings/applications/appinfo/AppDataUsagePreferenceControllerV2Test.java b/tests/robotests/src/com/android/settings/applications/appinfo/AppDataUsagePreferenceControllerV2Test.java
index 5e9179f..708222e 100644
--- a/tests/robotests/src/com/android/settings/applications/appinfo/AppDataUsagePreferenceControllerV2Test.java
+++ b/tests/robotests/src/com/android/settings/applications/appinfo/AppDataUsagePreferenceControllerV2Test.java
@@ -43,12 +43,11 @@
 import org.junit.Before;
 import org.junit.Test;
 import org.junit.runner.RunWith;
-import org.mockito.Mock;import android.net.INetworkStatsSession;
+import org.mockito.Mock;
 import android.util.FeatureFlagUtils;
 
 import org.mockito.MockitoAnnotations;
 import org.robolectric.RuntimeEnvironment;
-import org.robolectric.util.ReflectionHelpers;
 
 import androidx.loader.app.LoaderManager;
 import androidx.preference.Preference;
diff --git a/tests/robotests/src/com/android/settings/applications/appinfo/DefaultBrowserShortcutPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/applications/appinfo/DefaultBrowserShortcutPreferenceControllerTest.java
index f6abb5b..f4571ce 100644
--- a/tests/robotests/src/com/android/settings/applications/appinfo/DefaultBrowserShortcutPreferenceControllerTest.java
+++ b/tests/robotests/src/com/android/settings/applications/appinfo/DefaultBrowserShortcutPreferenceControllerTest.java
@@ -18,8 +18,8 @@
 
 import static com.google.common.truth.Truth.assertThat;
 
-import static org.mockito.ArgumentMatchers.anyInt;
-import static org.mockito.ArgumentMatchers.argThat;
+import static org.mockito.Matchers.anyInt;
+import static org.mockito.Matchers.argThat;
 import static org.mockito.Mockito.spy;
 import static org.mockito.Mockito.when;
 
@@ -66,8 +66,8 @@
     public void hasAppCapability_hasBrowserCapability_shouldReturnTrue() {
         List<ResolveInfo> resolveInfos = new ArrayList<>();
         resolveInfos.add(new ResolveInfo());
-        when(mPackageManager.queryIntentActivities(argThat(intent-> intent != null
-                && intent.getCategories().contains(Intent.CATEGORY_BROWSABLE)), anyInt()))
+        when(mPackageManager.queryIntentActivitiesAsUser(argThat(intent-> intent != null
+                && intent.getCategories().contains(Intent.CATEGORY_BROWSABLE)), anyInt(), anyInt()))
                 .thenReturn(resolveInfos);
 
         assertThat(mController.hasAppCapability()).isTrue();
diff --git a/tests/robotests/src/com/android/settings/applications/defaultapps/DefaultBrowserPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/applications/defaultapps/DefaultBrowserPreferenceControllerTest.java
index 4a482d0..cd3a426 100644
--- a/tests/robotests/src/com/android/settings/applications/defaultapps/DefaultBrowserPreferenceControllerTest.java
+++ b/tests/robotests/src/com/android/settings/applications/defaultapps/DefaultBrowserPreferenceControllerTest.java
@@ -34,6 +34,7 @@
 import android.content.pm.PackageManager;
 import android.content.pm.PackageManager.NameNotFoundException;
 import android.content.pm.ResolveInfo;
+import android.content.res.Resources;
 import android.os.UserManager;
 
 import androidx.preference.Preference;
@@ -131,6 +132,16 @@
     }
 
     @Test
+    public void getDefaultApp_shouldGetApplicationInfoAsUser() throws NameNotFoundException {
+        final String PACKAGE_NAME = "com.test.package";
+        when(mPackageManager.getDefaultBrowserPackageNameAsUser(anyInt())).thenReturn(PACKAGE_NAME);
+
+        mController.getDefaultAppInfo();
+
+        verify(mPackageManager).getApplicationInfoAsUser(eq(PACKAGE_NAME), anyInt(), anyInt());
+    }
+
+    @Test
     public void isBrowserDefault_onlyApp_shouldReturnTrue() {
         when(mPackageManager.getDefaultBrowserPackageNameAsUser(anyInt())).thenReturn(null);
         final List<ResolveInfo> resolveInfos = new ArrayList<>();
@@ -173,6 +184,33 @@
             any(Intent.class), eq(0) /* flags */, eq(0) /* userId */);
     }
 
+    @Test
+    public void getOnlyAppIcon_shouldGetApplicationInfoAsUser() throws NameNotFoundException {
+        final List<ResolveInfo> resolveInfos = new ArrayList<>();
+        final String PACKAGE_NAME = "com.test.package";
+        resolveInfos.add(createResolveInfo(PACKAGE_NAME));
+        when(mPackageManager.queryIntentActivitiesAsUser(any(Intent.class), anyInt(), anyInt()))
+            .thenReturn(resolveInfos);
+        when(mContext.getPackageManager()).thenReturn(mPackageManager);
+        when(mContext.getSystemService(UserManager.class)).thenReturn(mUserManager);
+        when(mContext.getResources()).thenReturn(mock(Resources.class));
+
+        mController.getOnlyAppIcon();
+
+        verify(mPackageManager).getApplicationInfoAsUser(
+            eq(PACKAGE_NAME), eq(0) /* flags */, eq(0) /* userId */);
+    }
+
+    @Test
+    public void hasBrowserPreference_shouldQueryIntentActivitiesAsUser() {
+        when(mContext.getPackageManager()).thenReturn(mPackageManager);
+
+        mController.hasBrowserPreference("com.test.package", mContext, 0 /* userId */);
+
+        verify(mPackageManager).queryIntentActivitiesAsUser(
+            any(Intent.class), eq(0) /* flags */, eq(0) /* userId */);
+    }
+
     private ResolveInfo createResolveInfo(String packageName) {
         final ResolveInfo info = new ResolveInfo();
         info.handleAllWebDataURI = true;
diff --git a/tests/robotests/src/com/android/settings/network/PrivateDnsPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/network/PrivateDnsPreferenceControllerTest.java
index b475c7e..464b290 100644
--- a/tests/robotests/src/com/android/settings/network/PrivateDnsPreferenceControllerTest.java
+++ b/tests/robotests/src/com/android/settings/network/PrivateDnsPreferenceControllerTest.java
@@ -43,6 +43,7 @@
 import static org.mockito.Mockito.when;
 import static org.mockito.Mockito.withSettings;
 
+import android.content.ComponentName;
 import android.content.ContentResolver;
 import android.content.Context;
 import android.net.ConnectivityManager;
@@ -50,6 +51,8 @@
 import android.net.LinkProperties;
 import android.net.Network;
 import android.os.Handler;
+import android.os.UserHandle;
+import android.os.UserManager;
 import android.provider.Settings;
 
 import androidx.lifecycle.LifecycleOwner;
@@ -58,6 +61,8 @@
 
 import com.android.settings.R;
 import com.android.settings.testutils.SettingsRobolectricTestRunner;
+import com.android.settings.testutils.shadow.ShadowUserManager;
+import com.android.settings.testutils.shadow.ShadowDevicePolicyManager;
 import com.android.settingslib.core.lifecycle.Lifecycle;
 
 import org.junit.Before;
@@ -79,6 +84,10 @@
 import java.util.List;
 
 @RunWith(SettingsRobolectricTestRunner.class)
+@Config(shadows = {
+    ShadowUserManager.class,
+    ShadowDevicePolicyManager.class
+})
 public class PrivateDnsPreferenceControllerTest {
 
     private final static String HOSTNAME = "dns.example.com";
@@ -108,6 +117,7 @@
     private ShadowContentResolver mShadowContentResolver;
     private Lifecycle mLifecycle;
     private LifecycleOwner mLifecycleOwner;
+    private ShadowUserManager mShadowUserManager;
 
     @Before
     public void setUp() {
@@ -127,6 +137,8 @@
         mLifecycleOwner = () -> mLifecycle;
         mLifecycle = new Lifecycle(mLifecycleOwner);
         mLifecycle.addObserver(mController);
+
+        mShadowUserManager = ShadowUserManager.getShadow();
     }
 
     private void updateLinkProperties(LinkProperties lp) {
@@ -264,6 +276,31 @@
         verify(mPreference).setSummary(getResourceString(R.string.private_dns_mode_opportunistic));
     }
 
+    @Test
+    public void isEnabled_canBeDisabledByAdmin() {
+        final int userId = UserHandle.myUserId();
+        final List<UserManager.EnforcingUser> enforcingUsers = Collections.singletonList(
+                new UserManager.EnforcingUser(userId,
+                        UserManager.RESTRICTION_SOURCE_DEVICE_OWNER)
+        );
+        mShadowUserManager.setUserRestrictionSources(
+                UserManager.DISALLOW_CONFIG_PRIVATE_DNS,
+                UserHandle.of(userId),
+                enforcingUsers);
+
+        ShadowDevicePolicyManager.getShadow().setDeviceOwnerComponentOnAnyUser(
+                new ComponentName("test", "test"));
+
+        mController.updateState(mPreference);
+        verify(mPreference).setEnabled(false);
+    }
+
+    @Test
+    public void isEnabled_isEnabledByDefault() {
+        mController.updateState(mPreference);
+        verify(mPreference).setEnabled(true);
+    }
+
     private void setPrivateDnsMode(String mode) {
         Settings.Global.putString(mContentResolver, PRIVATE_DNS_MODE, mode);
     }
diff --git a/tests/robotests/src/com/android/settings/network/telephony/CarrierPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/network/telephony/CarrierPreferenceControllerTest.java
new file mode 100644
index 0000000..e119e89
--- /dev/null
+++ b/tests/robotests/src/com/android/settings/network/telephony/CarrierPreferenceControllerTest.java
@@ -0,0 +1,108 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.settings.network.telephony;
+
+import static com.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.Mockito.doReturn;
+import static org.mockito.Mockito.spy;
+
+import android.content.Context;
+import android.os.PersistableBundle;
+import android.telephony.CarrierConfigManager;
+import android.telephony.SubscriptionManager;
+import android.telephony.TelephonyManager;
+
+import com.android.internal.telephony.PhoneConstants;
+import com.android.settings.testutils.SettingsRobolectricTestRunner;
+import com.android.settingslib.RestrictedPreference;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+import org.robolectric.RuntimeEnvironment;
+
+@RunWith(SettingsRobolectricTestRunner.class)
+public class CarrierPreferenceControllerTest {
+    private static final int SUB_ID = 2;
+
+    @Mock
+    private TelephonyManager mTelephonyManager;
+    @Mock
+    private TelephonyManager mInvalidTelephonyManager;
+    @Mock
+    private SubscriptionManager mSubscriptionManager;
+    @Mock
+    private CarrierConfigManager mCarrierConfigManager;
+
+    private CarrierPreferenceController mController;
+    private RestrictedPreference mPreference;
+    private Context mContext;
+
+    @Before
+    public void setUp() {
+        MockitoAnnotations.initMocks(this);
+
+        mContext = spy(RuntimeEnvironment.application);
+        doReturn(mTelephonyManager).when(mContext).getSystemService(Context.TELEPHONY_SERVICE);
+        doReturn(mSubscriptionManager).when(mContext).getSystemService(SubscriptionManager.class);
+        doReturn(mTelephonyManager).when(mTelephonyManager).createForSubscriptionId(SUB_ID);
+        doReturn(mInvalidTelephonyManager).when(mTelephonyManager).createForSubscriptionId(
+                SubscriptionManager.INVALID_SUBSCRIPTION_ID);
+
+        mPreference = new RestrictedPreference(mContext);
+        mController = new CarrierPreferenceController(mContext, "mobile_data");
+        mController.init(SUB_ID);
+        mController.mCarrierConfigManager = mCarrierConfigManager;
+        mPreference.setKey(mController.getPreferenceKey());
+    }
+
+    @Test
+    public void getAvailabilityStatus_cdmaWithFlagOff_returnUnavailable() {
+        doReturn(PhoneConstants.PHONE_TYPE_CDMA).when(mTelephonyManager).getPhoneType();
+        final PersistableBundle bundle = new PersistableBundle();
+        bundle.putBoolean(CarrierConfigManager.KEY_CARRIER_SETTINGS_ENABLE_BOOL, false);
+        doReturn(bundle).when(mCarrierConfigManager).getConfigForSubId(SUB_ID);
+
+        assertThat(mController.getAvailabilityStatus()).isEqualTo(CONDITIONALLY_UNAVAILABLE);
+    }
+
+    @Test
+    public void getAvailabilityStatus_cdmaWithFlagOnreturnAvailable() {
+        doReturn(PhoneConstants.PHONE_TYPE_CDMA).when(mTelephonyManager).getPhoneType();
+        final PersistableBundle bundle = new PersistableBundle();
+        bundle.putBoolean(CarrierConfigManager.KEY_CARRIER_SETTINGS_ENABLE_BOOL, true);
+        doReturn(bundle).when(mCarrierConfigManager).getConfigForSubId(SUB_ID);
+
+        assertThat(mController.getAvailabilityStatus()).isEqualTo(AVAILABLE);
+    }
+
+    @Test
+    public void getAvailabilityStatus_gsmWithFlagOnreturnAvailable() {
+        doReturn(PhoneConstants.PHONE_TYPE_GSM).when(mTelephonyManager).getPhoneType();
+        final PersistableBundle bundle = new PersistableBundle();
+        bundle.putBoolean(CarrierConfigManager.KEY_CARRIER_SETTINGS_ENABLE_BOOL, true);
+        doReturn(bundle).when(mCarrierConfigManager).getConfigForSubId(SUB_ID);
+
+        assertThat(mController.getAvailabilityStatus()).isEqualTo(AVAILABLE);
+    }
+}
diff --git a/tests/robotests/src/com/android/settings/network/telephony/DataUsagePreferenceControllerTest.java b/tests/robotests/src/com/android/settings/network/telephony/DataUsagePreferenceControllerTest.java
new file mode 100644
index 0000000..013fb08
--- /dev/null
+++ b/tests/robotests/src/com/android/settings/network/telephony/DataUsagePreferenceControllerTest.java
@@ -0,0 +1,102 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.settings.network.telephony;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import static org.mockito.Mockito.doReturn;
+import static org.mockito.Mockito.spy;
+import static org.mockito.Mockito.verify;
+
+import android.content.Context;
+import android.content.Intent;
+import android.provider.Settings;
+import android.telephony.SubscriptionManager;
+import android.telephony.TelephonyManager;
+
+import androidx.preference.SwitchPreference;
+
+import com.android.settings.core.BasePreferenceController;
+import com.android.settings.testutils.SettingsRobolectricTestRunner;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.ArgumentCaptor;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+import org.robolectric.RuntimeEnvironment;
+
+@RunWith(SettingsRobolectricTestRunner.class)
+public class DataUsagePreferenceControllerTest {
+    private static final int SUB_ID = 2;
+
+    @Mock
+    private TelephonyManager mTelephonyManager;
+    private DataUsagePreferenceController mController;
+    private SwitchPreference mPreference;
+    private Context mContext;
+
+    @Before
+    public void setUp() {
+        MockitoAnnotations.initMocks(this);
+
+        mContext = spy(RuntimeEnvironment.application);
+        doReturn(mTelephonyManager).when(mContext).getSystemService(Context.TELEPHONY_SERVICE);
+        doReturn(mTelephonyManager).when(mTelephonyManager).createForSubscriptionId(SUB_ID);
+
+        mPreference = new SwitchPreference(mContext);
+        mController = new DataUsagePreferenceController(mContext, "data_usage");
+        mController.init(SUB_ID);
+        mPreference.setKey(mController.getPreferenceKey());
+    }
+
+    @Test
+    public void getAvailabilityStatus_validSubId_returnAvailable() {
+        assertThat(mController.getAvailabilityStatus()).isEqualTo(
+                BasePreferenceController.AVAILABLE);
+    }
+
+    @Test
+    public void getAvailabilityStatus_invalidSubId_returnUnsearchable() {
+        mController.init(SubscriptionManager.INVALID_SUBSCRIPTION_ID);
+
+        assertThat(mController.getAvailabilityStatus()).isEqualTo(
+                BasePreferenceController.AVAILABLE_UNSEARCHABLE);
+    }
+
+    @Test
+    public void handlePreferenceTreeClick_needDialog_showDialog() {
+        final ArgumentCaptor<Intent> captor = ArgumentCaptor.forClass(Intent.class);
+        mController.handlePreferenceTreeClick(mPreference);
+
+        verify(mContext).startActivity(captor.capture());
+        final Intent intent = captor.getValue();
+
+        assertThat(intent.getAction()).isEqualTo(Settings.ACTION_MOBILE_DATA_USAGE);
+        assertThat(intent.getIntExtra(Settings.EXTRA_SUB_ID, 0)).isEqualTo(SUB_ID);
+    }
+
+    @Test
+    public void updateState_invalidSubId_disabled() {
+        mController.init(SubscriptionManager.INVALID_SUBSCRIPTION_ID);
+
+        mController.updateState(mPreference);
+
+        assertThat(mPreference.isEnabled()).isFalse();
+    }
+}
diff --git a/tests/robotests/src/com/android/settings/network/telephony/MobileNetworkUtilsTest.java b/tests/robotests/src/com/android/settings/network/telephony/MobileNetworkUtilsTest.java
index d5c8648..c03fb71 100644
--- a/tests/robotests/src/com/android/settings/network/telephony/MobileNetworkUtilsTest.java
+++ b/tests/robotests/src/com/android/settings/network/telephony/MobileNetworkUtilsTest.java
@@ -18,7 +18,6 @@
 
 import static com.google.common.truth.Truth.assertThat;
 
-import static org.mockito.ArgumentMatchers.any;
 import static org.mockito.ArgumentMatchers.anyBoolean;
 import static org.mockito.ArgumentMatchers.anyInt;
 import static org.mockito.ArgumentMatchers.nullable;
@@ -32,11 +31,14 @@
 import android.content.Intent;
 import android.content.pm.PackageManager;
 import android.content.pm.ResolveInfo;
+import android.provider.Settings;
 import android.telecom.PhoneAccountHandle;
 import android.telephony.SubscriptionInfo;
 import android.telephony.SubscriptionManager;
 import android.telephony.TelephonyManager;
 
+import com.android.internal.telephony.PhoneConstants;
+import com.android.settings.R;
 import com.android.settings.testutils.SettingsRobolectricTestRunner;
 
 import org.junit.Before;
@@ -142,4 +144,22 @@
         assertThat(MobileNetworkUtils.buildPhoneAccountConfigureIntent(mContext,
                 mPhoneAccountHandle)).isNotNull();
     }
+
+    @Test
+    public void isCdmaOptions_phoneTypeCdma_returnTrue() {
+        doReturn(PhoneConstants.PHONE_TYPE_CDMA).when(mTelephonyManager).getPhoneType();
+
+        assertThat(MobileNetworkUtils.isCdmaOptions(mContext, SUB_ID_1)).isTrue();
+    }
+
+    @Test
+    public void isCdmaOptions_worldModeWithGsmWcdma_returnTrue() {
+        doReturn(PhoneConstants.PHONE_TYPE_GSM).when(mTelephonyManager).getPhoneType();
+        doReturn("true").when(mContext).getString(R.string.config_world_mode);
+        Settings.Global.putInt(mContext.getContentResolver(),
+                android.provider.Settings.Global.PREFERRED_NETWORK_MODE + SUB_ID_1,
+                TelephonyManager.NETWORK_MODE_LTE_GSM_WCDMA);
+
+        assertThat(MobileNetworkUtils.isCdmaOptions(mContext, SUB_ID_1)).isTrue();
+    }
 }
diff --git a/tests/robotests/src/com/android/settings/network/telephony/cdma/CdmaApnPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/network/telephony/cdma/CdmaApnPreferenceControllerTest.java
new file mode 100644
index 0000000..2aceda7
--- /dev/null
+++ b/tests/robotests/src/com/android/settings/network/telephony/cdma/CdmaApnPreferenceControllerTest.java
@@ -0,0 +1,116 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.settings.network.telephony.cdma;
+
+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.Mockito.doReturn;
+import static org.mockito.Mockito.spy;
+import static org.mockito.Mockito.verify;
+
+import android.content.Context;
+import android.content.Intent;
+import android.os.PersistableBundle;
+import android.provider.Settings;
+import android.telephony.CarrierConfigManager;
+import android.telephony.SubscriptionManager;
+import android.telephony.TelephonyManager;
+
+import com.android.internal.telephony.PhoneConstants;
+import com.android.settings.network.ApnSettings;
+import com.android.settings.testutils.SettingsRobolectricTestRunner;
+import com.android.settingslib.RestrictedPreference;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.ArgumentCaptor;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+import org.robolectric.RuntimeEnvironment;
+
+@RunWith(SettingsRobolectricTestRunner.class)
+public class CdmaApnPreferenceControllerTest {
+    private static final int SUB_ID = 2;
+
+    @Mock
+    private TelephonyManager mTelephonyManager;
+    @Mock
+    private TelephonyManager mInvalidTelephonyManager;
+    @Mock
+    private SubscriptionManager mSubscriptionManager;
+    @Mock
+    private CarrierConfigManager mCarrierConfigManager;
+
+    private CdmaApnPreferenceController mController;
+    private RestrictedPreference mPreference;
+    private Context mContext;
+
+    @Before
+    public void setUp() {
+        MockitoAnnotations.initMocks(this);
+
+        mContext = spy(RuntimeEnvironment.application);
+        doReturn(mTelephonyManager).when(mContext).getSystemService(Context.TELEPHONY_SERVICE);
+        doReturn(mSubscriptionManager).when(mContext).getSystemService(SubscriptionManager.class);
+        doReturn(mTelephonyManager).when(mTelephonyManager).createForSubscriptionId(SUB_ID);
+        doReturn(mInvalidTelephonyManager).when(mTelephonyManager).createForSubscriptionId(
+                SubscriptionManager.INVALID_SUBSCRIPTION_ID);
+
+        mPreference = new RestrictedPreference(mContext);
+        mController = new CdmaApnPreferenceController(mContext, "mobile_data");
+        mController.init(SUB_ID);
+        mController.mPreference = mPreference;
+        mController.mCarrierConfigManager = mCarrierConfigManager;
+        mPreference.setKey(mController.getPreferenceKey());
+    }
+
+    @Test
+    public void getAvailabilityStatus_apnSettingsNotSupported_returnUnavailable() {
+        doReturn(PhoneConstants.PHONE_TYPE_CDMA).when(mTelephonyManager).getPhoneType();
+        final PersistableBundle bundle = new PersistableBundle();
+        bundle.putBoolean(CarrierConfigManager.KEY_SHOW_APN_SETTING_CDMA_BOOL, false);
+        doReturn(bundle).when(mCarrierConfigManager).getConfigForSubId(SUB_ID);
+
+        assertThat(mController.getAvailabilityStatus()).isEqualTo(CONDITIONALLY_UNAVAILABLE);
+    }
+
+    @Test
+    public void getAvailabilityStatus_apnSettingsSupportedWithCDMA_returnAvailable() {
+        doReturn(PhoneConstants.PHONE_TYPE_CDMA).when(mTelephonyManager).getPhoneType();
+        final PersistableBundle bundle = new PersistableBundle();
+        bundle.putBoolean(CarrierConfigManager.KEY_SHOW_APN_SETTING_CDMA_BOOL, true);
+        doReturn(bundle).when(mCarrierConfigManager).getConfigForSubId(SUB_ID);
+
+        assertThat(mController.getAvailabilityStatus()).isEqualTo(AVAILABLE);
+    }
+
+    @Test
+    public void handPreferenceTreeClick_fireIntent() {
+        ArgumentCaptor<Intent> captor = ArgumentCaptor.forClass(Intent.class);
+
+        mController.handlePreferenceTreeClick(mPreference);
+
+        verify(mContext).startActivity(captor.capture());
+        final Intent intent = captor.getValue();
+        assertThat(intent.getAction()).isEqualTo(Settings.ACTION_APN_SETTINGS);
+        assertThat(intent.getIntExtra(ApnSettings.SUB_ID, 0)).isEqualTo(SUB_ID);
+    }
+}
diff --git a/tests/robotests/src/com/android/settings/network/telephony/cdma/CdmaSubscriptionPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/network/telephony/cdma/CdmaSubscriptionPreferenceControllerTest.java
new file mode 100644
index 0000000..c938948
--- /dev/null
+++ b/tests/robotests/src/com/android/settings/network/telephony/cdma/CdmaSubscriptionPreferenceControllerTest.java
@@ -0,0 +1,121 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.settings.network.telephony.cdma;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import static org.mockito.ArgumentMatchers.anyInt;
+import static org.mockito.Mockito.doReturn;
+import static org.mockito.Mockito.spy;
+
+import android.content.Context;
+import android.os.SystemProperties;
+import android.provider.Settings;
+import android.telephony.SubscriptionManager;
+import android.telephony.TelephonyManager;
+
+import androidx.preference.ListPreference;
+import androidx.preference.PreferenceManager;
+
+import com.android.internal.telephony.Phone;
+import com.android.settings.testutils.SettingsRobolectricTestRunner;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+import org.robolectric.RuntimeEnvironment;
+
+@RunWith(SettingsRobolectricTestRunner.class)
+public class CdmaSubscriptionPreferenceControllerTest {
+    private static final int SUB_ID = 2;
+
+    @Mock
+    private PreferenceManager mPreferenceManager;
+    @Mock
+    private TelephonyManager mTelephonyManager;
+    @Mock
+    private TelephonyManager mInvalidTelephonyManager;
+    @Mock
+    private SubscriptionManager mSubscriptionManager;
+
+    private CdmaSubscriptionPreferenceController mController;
+    private ListPreference mPreference;
+    private Context mContext;
+
+    @Before
+    public void setUp() {
+        MockitoAnnotations.initMocks(this);
+
+        mContext = spy(RuntimeEnvironment.application);
+        doReturn(mTelephonyManager).when(mContext).getSystemService(Context.TELEPHONY_SERVICE);
+        doReturn(mSubscriptionManager).when(mContext).getSystemService(SubscriptionManager.class);
+        doReturn(mTelephonyManager).when(mTelephonyManager).createForSubscriptionId(SUB_ID);
+        doReturn(mInvalidTelephonyManager).when(mTelephonyManager).createForSubscriptionId(
+                SubscriptionManager.INVALID_SUBSCRIPTION_ID);
+
+        mPreference = new ListPreference(mContext);
+        mController = new CdmaSubscriptionPreferenceController(mContext, "mobile_data");
+        mController.init(mPreferenceManager, SUB_ID);
+        mController.mPreference = mPreference;
+        mPreference.setKey(mController.getPreferenceKey());
+    }
+
+    @Test
+    public void onPreferenceChange_selectNV_returnNVMode() {
+        doReturn(true).when(mTelephonyManager).setCdmaSubscriptionMode(anyInt());
+
+        mController.onPreferenceChange(mPreference, Integer.toString(Phone.CDMA_SUBSCRIPTION_NV));
+
+        assertThat(Settings.Global.getInt(mContext.getContentResolver(),
+                Settings.Global.CDMA_SUBSCRIPTION_MODE,
+                Phone.CDMA_SUBSCRIPTION_RUIM_SIM)).isEqualTo(Phone.CDMA_SUBSCRIPTION_NV);
+    }
+
+    @Test
+    public void updateState_stateRUIM_displayRUIM() {
+        Settings.Global.putInt(mContext.getContentResolver(),
+                Settings.Global.CDMA_SUBSCRIPTION_MODE, Phone.CDMA_SUBSCRIPTION_NV);
+
+        mController.updateState(mPreference);
+
+        assertThat(mPreference.getValue()).isEqualTo(Integer.toString(Phone.CDMA_SUBSCRIPTION_NV));
+    }
+
+    @Test
+    public void updateState_stateUnknown_doNothing() {
+        mPreference.setValue(Integer.toString(Phone.CDMA_SUBSCRIPTION_NV));
+        Settings.Global.putInt(mContext.getContentResolver(),
+                Settings.Global.CDMA_SUBSCRIPTION_MODE, Phone.CDMA_SUBSCRIPTION_UNKNOWN);
+
+        mController.updateState(mPreference);
+
+        // Still NV mode
+        assertThat(mPreference.getValue()).isEqualTo(Integer.toString(Phone.CDMA_SUBSCRIPTION_NV));
+    }
+
+    @Test
+    public void deviceSupportsNvAndRuim() {
+        SystemProperties.set("ril.subscription.types", "NV,RUIM");
+        assertThat(mController.deviceSupportsNvAndRuim()).isTrue();
+
+        SystemProperties.set("ril.subscription.types", "");
+
+        assertThat(mController.deviceSupportsNvAndRuim()).isFalse();
+    }
+}
diff --git a/tests/robotests/src/com/android/settings/network/telephony/cdma/CdmaSystemSelectPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/network/telephony/cdma/CdmaSystemSelectPreferenceControllerTest.java
new file mode 100644
index 0000000..2046237
--- /dev/null
+++ b/tests/robotests/src/com/android/settings/network/telephony/cdma/CdmaSystemSelectPreferenceControllerTest.java
@@ -0,0 +1,122 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.settings.network.telephony.cdma;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import static org.mockito.ArgumentMatchers.anyInt;
+import static org.mockito.Mockito.doReturn;
+import static org.mockito.Mockito.spy;
+
+import android.content.Context;
+import android.provider.Settings;
+import android.telephony.SubscriptionManager;
+import android.telephony.TelephonyManager;
+
+import androidx.preference.ListPreference;
+import androidx.preference.PreferenceManager;
+
+import com.android.settings.testutils.SettingsRobolectricTestRunner;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+import org.robolectric.RuntimeEnvironment;
+
+@RunWith(SettingsRobolectricTestRunner.class)
+public class CdmaSystemSelectPreferenceControllerTest {
+    private static final int SUB_ID = 2;
+
+    @Mock
+    private PreferenceManager mPreferenceManager;
+    @Mock
+    private TelephonyManager mTelephonyManager;
+    @Mock
+    private TelephonyManager mInvalidTelephonyManager;
+    @Mock
+    private SubscriptionManager mSubscriptionManager;
+
+    private CdmaSystemSelectPreferenceController mController;
+    private ListPreference mPreference;
+    private Context mContext;
+
+    @Before
+    public void setUp() {
+        MockitoAnnotations.initMocks(this);
+
+        mContext = spy(RuntimeEnvironment.application);
+        doReturn(mTelephonyManager).when(mContext).getSystemService(Context.TELEPHONY_SERVICE);
+        doReturn(mSubscriptionManager).when(mContext).getSystemService(SubscriptionManager.class);
+        doReturn(mTelephonyManager).when(mTelephonyManager).createForSubscriptionId(SUB_ID);
+        doReturn(mInvalidTelephonyManager).when(mTelephonyManager).createForSubscriptionId(
+                SubscriptionManager.INVALID_SUBSCRIPTION_ID);
+
+        mPreference = new ListPreference(mContext);
+        mController = new CdmaSystemSelectPreferenceController(mContext, "mobile_data");
+        mController.init(mPreferenceManager, SUB_ID);
+        mController.mPreference = mPreference;
+        mPreference.setKey(mController.getPreferenceKey());
+    }
+
+    @Test
+    public void onPreferenceChange_selectHome_returnHomeMode() {
+        Settings.Global.putInt(mContext.getContentResolver(),
+                Settings.Global.CDMA_ROAMING_MODE,
+                TelephonyManager.CDMA_ROAMING_MODE_ANY);
+        doReturn(true).when(mTelephonyManager).setCdmaRoamingMode(anyInt());
+
+        mController.onPreferenceChange(mPreference,
+                Integer.toString(TelephonyManager.CDMA_ROAMING_MODE_HOME));
+
+        assertThat(Settings.Global.getInt(mContext.getContentResolver(),
+                Settings.Global.CDMA_ROAMING_MODE,
+                TelephonyManager.CDMA_ROAMING_MODE_ANY)).isEqualTo(
+                TelephonyManager.CDMA_ROAMING_MODE_HOME);
+    }
+
+    @Test
+    public void updateState_stateHome_displayHome() {
+        doReturn(TelephonyManager.CDMA_ROAMING_MODE_HOME).when(
+                mTelephonyManager).getCdmaRoamingMode();
+
+        mController.updateState(mPreference);
+
+        assertThat(mPreference.getValue()).isEqualTo(
+                Integer.toString(TelephonyManager.CDMA_ROAMING_MODE_HOME));
+    }
+
+    @Test
+    public void updateState_stateOther_resetToDefault() {
+        Settings.Global.putInt(mContext.getContentResolver(),
+                Settings.Global.CDMA_ROAMING_MODE,
+                TelephonyManager.CDMA_ROAMING_MODE_HOME);
+        doReturn(TelephonyManager.CDMA_ROAMING_MODE_AFFILIATED).when(
+                mTelephonyManager).getCdmaRoamingMode();
+
+        mController.updateState(mPreference);
+
+        assertThat(mPreference.getValue()).isEqualTo(
+                Integer.toString(TelephonyManager.CDMA_ROAMING_MODE_ANY));
+        assertThat(Settings.Global.getInt(mContext.getContentResolver(),
+                Settings.Global.CDMA_ROAMING_MODE,
+                TelephonyManager.CDMA_ROAMING_MODE_HOME)).isEqualTo(
+                TelephonyManager.CDMA_ROAMING_MODE_ANY);
+    }
+
+}
diff --git a/tests/robotests/src/com/android/settings/testutils/shadow/ShadowUserManager.java b/tests/robotests/src/com/android/settings/testutils/shadow/ShadowUserManager.java
index 3266a7f..bb691cb 100644
--- a/tests/robotests/src/com/android/settings/testutils/shadow/ShadowUserManager.java
+++ b/tests/robotests/src/com/android/settings/testutils/shadow/ShadowUserManager.java
@@ -89,6 +89,16 @@
     }
 
     @Implementation
+    public List<UserHandle> getUserProfiles(){
+        int[] userIds = getProfileIds(UserHandle.myUserId(), true /* enabledOnly */);
+        List<UserHandle> result = new ArrayList<>(userIds.length);
+        for (int userId : userIds) {
+            result.add(UserHandle.of(userId));
+        }
+        return result;
+    }
+
+    @Implementation
     public int getCredentialOwnerProfile(@UserIdInt int userHandle) {
         return userHandle;
     }