Merge "Remove obsolete chart view widgets."
diff --git a/AndroidManifest.xml b/AndroidManifest.xml
index 94be61c..ec34514 100644
--- a/AndroidManifest.xml
+++ b/AndroidManifest.xml
@@ -131,6 +131,13 @@
                   android:launchMode="singleTask">
         </activity>
 
+        <activity android:name=".mobilenetwork.MobileSettingsActivity"
+                  android:label="@string/network_settings_title"
+                  android:theme="@style/Theme.Settings.Home"
+                  android:launchMode="singleTask">
+            <!-- TODO(b/114749736): add intent filter here and disable the one in telephony -->
+        </activity>
+
         <!-- Alias for launcher activity only, as this belongs to each profile. -->
         <activity-alias android:name="Settings"
                 android:taskAffinity="com.android.settings.root"
@@ -3029,9 +3036,6 @@
             android:exported="true"
             android:permission="android.permission.DUMP" />
 
-         <service android:name=".search.DeviceIndexUpdateJobService"
-            android:permission="android.permission.BIND_JOB_SERVICE" />
-
         <!-- Quick Settings tiles for Developer Options -->
         <service
             android:name=".development.qstile.DevelopmentTiles$ShowLayout"
diff --git a/res/layout/mobile_settings_container.xml b/res/layout/mobile_settings_container.xml
new file mode 100644
index 0000000..d81a72e
--- /dev/null
+++ b/res/layout/mobile_settings_container.xml
@@ -0,0 +1,50 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  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.
+  -->
+
+<LinearLayout
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:app="http://schemas.android.com/apk/res-auto"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent"
+    android:orientation="vertical">
+
+    <Toolbar
+        android:id="@+id/action_bar"
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:navigationContentDescription="@*android:string/action_bar_up_description"
+        android:theme="?android:attr/actionBarTheme"
+        style="?android:attr/actionBarStyle"/>
+
+    <FrameLayout
+        android:id="@+id/main_content"
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:layout_weight="1"/>
+
+    <com.google.android.material.bottomnavigation.BottomNavigationView
+        android:id="@+id/bottom_nav"
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:layout_alignParentBottom="true"
+        android:layout_marginEnd="0dp"
+        android:layout_marginStart="0dp"
+        android:background="?android:attr/windowBackground"
+        app:itemIconTint="@color/bottom_navigation_colors"
+        app:itemTextColor="@color/bottom_navigation_colors"
+        app:menu="@menu/home_bottom_navigation"/>
+</LinearLayout>
diff --git a/res/values/arrays.xml b/res/values/arrays.xml
index e57cbfa..6cc10fe 100644
--- a/res/values/arrays.xml
+++ b/res/values/arrays.xml
@@ -1133,4 +1133,186 @@
         <item>4</item> <!-- AutofillManager.FLAG_ADD_CLIENT_VERBOSE -->
     </string-array>
 
+    <string-array name="enabled_networks_choices" translatable="false">
+        <item>@string/network_lte</item>
+        <item>@string/network_3G</item>
+        <item>@string/network_2G</item>
+    </string-array>
+    <string-array name="enabled_networks_4g_choices" translatable="false">
+        <item>@string/network_4G</item>
+        <item>@string/network_3G</item>
+        <item>@string/network_2G</item>
+    </string-array>
+    <string-array name="enabled_networks_values" translatable="false">
+        <item>"9"</item>
+        <item>"0"</item>
+        <item>"1"</item>
+    </string-array>
+
+    <string-array name="cdma_system_select_choices">
+        <!-- System select dialog screen, setting option name -->
+        <item>Home only</item>
+        <!-- Remove the following option "Affiliated Networks" from the option list -->
+        <!-- <item>Affiliated Networks</item> -->
+        <!-- System select dialog screen, setting option name -->
+        <item>Automatic</item>
+    </string-array>
+    <string-array name="cdma_system_select_values" translatable="false">
+        <!-- Do not translate. -->
+        <item>"0"</item>
+        <!-- Remove the following value "1" which corresponds to "Affiliated Networks" above -->
+        <!-- <item>"1"</item>  -->
+        <!-- Do not translate. -->
+        <item>"2"</item>
+    </string-array>
+
+    <!-- The preferred network modes in Mobile network settings -->
+    <string-array name="preferred_network_mode_choices">
+        <item>GSM/WCDMA preferred</item>
+        <item>GSM only</item>
+        <item>WCDMA only</item>
+        <item>GSM/WCDMA auto</item>
+        <item>CDMA/EvDo auto</item>
+        <item>CDMA w/o EvDo</item>
+        <item>EvDo only</item>
+        <item>CDMA/EvDo/GSM/WCDMA</item>
+        <item>CDMA + LTE/EvDo</item>
+        <item>GSM/WCDMA/LTE</item>
+        <item>Global</item>
+        <item>LTE</item>
+        <item>LTE / WCDMA</item>
+        <item>TDSCDMA only</item>
+        <item>TDSCDMA/WCDMA</item>
+        <item>LTE/TDSCDMA</item>
+        <item>TDSCDMA/GSM</item>
+        <item>LTE/TDSCDMA/GSM</item>
+        <item>TDSCDMA/GSM/WCDMA</item>
+        <item>LTE/TDSCDMA/WCDMA</item>
+        <item>LTE/TDSCDMA/GSM/WCDMA</item>
+        <item>TDSCDMA/CDMA/EVDO/GSM/WCDMA </item>
+        <item>LTE/TDSCDMA/CDMA/EVDO/GSM/WCDMA</item>
+    </string-array>
+    <!-- The preferred network modes RIL constants, in order of the modes above,
+         e.g. the choice "GSM/WCDMA preferred" has the corresponding value "0" -->
+    <string-array name="preferred_network_mode_values"  translatable="false">
+        <item>"0"</item>
+        <item>"1"</item>
+        <item>"2"</item>
+        <item>"3"</item>
+        <item>"4"</item>
+        <item>"5"</item>
+        <item>"6"</item>
+        <item>"7"</item>
+        <item>"8"</item>
+        <item>"9"</item>
+        <item>"10"</item>
+        <item>"11"</item>
+        <item>"12"</item>
+        <item>"13"</item>
+        <item>"14"</item>
+        <item>"15"</item>
+        <item>"16"</item>
+        <item>"17"</item>
+        <item>"18"</item>
+        <item>"19"</item>
+        <item>"20"</item>
+        <item>"21"</item>
+        <item>"22"</item>
+    </string-array>
+
+    <!-- Choices for CDMA subscription-->
+    <string-array name="cdma_subscription_choices">
+        <item>RUIM/SIM</item>
+        <item>NV</item>
+    </string-array>
+    <!-- Values for CDMA subscription-->
+    <string-array name="cdma_subscription_values">
+        <item>"0"</item>
+        <item>"1"</item>
+    </string-array>
+
+    <string-array name="enabled_networks_except_gsm_choices" translatable="false">
+        <item>@string/network_lte</item>
+        <item>@string/network_3G</item>
+    </string-array>
+    <string-array name="enabled_networks_except_gsm_4g_choices" translatable="false">
+        <item>@string/network_4G</item>
+        <item>@string/network_3G</item>
+    </string-array>
+    <string-array name="enabled_networks_except_gsm_values" translatable="false">
+        <item>"9"</item>
+        <item>"0"</item>
+    </string-array>
+
+    <string-array name="enabled_networks_except_lte_choices" translatable="false">
+        <item>@string/network_3G</item>
+        <item>@string/network_2G</item>
+    </string-array>
+    <string-array name="enabled_networks_except_lte_values" translatable="false">
+        <item>"0"</item>
+        <item>"1"</item>
+    </string-array>
+
+    <string-array name="enabled_networks_except_gsm_lte_choices" translatable="false">
+        <item>@string/network_3G</item>
+    </string-array>
+    <string-array name="enabled_networks_except_gsm_lte_values" translatable="false">
+        <item>"0"</item>
+    </string-array>
+
+    <string-array name="enabled_networks_cdma_choices" translatable="false">
+        <item>@string/network_lte</item>
+        <item>@string/network_3G</item>
+        <item>@string/network_1x</item>
+        <item>@string/network_global</item>
+    </string-array>
+    <string-array name="enabled_networks_cdma_values" translatable="false">
+        <item>"8"</item>
+        <item>"4"</item>
+        <item>"5"</item>
+        <item>"10"</item>
+    </string-array>
+
+    <string-array name="enabled_networks_cdma_no_lte_choices" translatable="false">
+        <item>@string/network_3G</item>
+        <item>@string/network_1x</item>
+    </string-array>
+    <string-array name="enabled_networks_cdma_no_lte_values" translatable="false">
+        <item>"4"</item>
+        <item>"5"</item>
+    </string-array>
+
+    <string-array name="enabled_networks_cdma_only_lte_choices" translatable="false">
+        <item>@string/network_lte</item>
+        <item>@string/network_global</item>
+    </string-array>
+    <string-array name="enabled_networks_cdma_only_lte_values" translatable="false">
+        <item>"8"</item>
+        <item>"10"</item>
+    </string-array>
+
+    <string-array name="enabled_networks_tdscdma_choices" translatable="false">
+        <item>@string/network_lte</item>
+        <item>@string/network_3G</item>
+        <item>@string/network_2G</item>
+    </string-array>
+    <string-array name="enabled_networks_tdscdma_values" translatable="false">
+        <item>"22"</item>
+        <item>"18"</item>
+        <item>"1"</item>
+    </string-array>
+
+    <!--String arrays for World preferred netwrok modes -->
+    <string-array name="preferred_network_mode_choices_world_mode">
+        <item>Global</item>
+        <item>LTE / CDMA</item>
+        <item>LTE / GSM / UMTS</item>
+    </string-array>
+
+    <string-array name="preferred_network_mode_values_world_mode">
+        <item>"10"</item>
+        <item>"8"</item>
+        <item>"9"</item>
+    </string-array>
+
 </resources>
diff --git a/res/values/config.xml b/res/values/config.xml
index b9a69f1..8e60505 100755
--- a/res/values/config.xml
+++ b/res/values/config.xml
@@ -136,4 +136,13 @@
 
     <!-- Whether or not TopLevelSettings should force rounded icon for injected tiles -->
     <bool name="config_force_rounded_icon_TopLevelSettings">true</bool>
+
+    <!-- TODO(b/115429501): move those 3 configs to framework-->
+    <!-- Show enabled lte option for lte device -->
+    <bool name="config_enabled_lte" translatable="false">false</bool>
+    <!-- Show enabled tdscdma option for device -->
+    <bool name="config_support_tdscdma" translatable="false">false</bool>
+    <!-- Show enabled tdscdma option for device when connect roaming network -->
+    <string-array name="config_support_tdscdma_roaming_on_networks"
+                  translatable="false"></string-array>
 </resources>
diff --git a/res/values/strings.xml b/res/values/strings.xml
index d78b7b0..9843b80 100644
--- a/res/values/strings.xml
+++ b/res/values/strings.xml
@@ -6971,6 +6971,9 @@
     <!-- Search keyword for Ambient display settings screen. -->
     <string name="keywords_ambient_display_screen">Ambient display, Lock screen display</string>
 
+    <!-- Search keyword for lock screen notification setting [CHAR_LIMIT=NONE] -->
+    <string name="keywords_lock_screen_notif">lock screen notification</string>
+
     <!-- Search keyword for face settings. -->
     <string name="keywords_face_settings">face</string>
 
@@ -10112,4 +10115,146 @@
 
     <!-- Message informs the user that has no SIM card in personalized Settings [CHAR LIMIT=30] -->
     <string name="no_sim_card">No SIM card</string>
+
+    <!-- Carrier variant of Enhaced 4G LTE Mode title.  [CHAR LIMIT=50] -->
+    <string name="enhanced_4g_lte_mode_title_variant">Advanced Calling</string>
+    <!-- The following strings are summaries for preferred network modes in Mobile network settings,
+     and have a character limit of 100 -->
+    <!-- WCDMA preferred [CHAR LIMIT=NONE] -->
+    <string name="preferred_network_mode_wcdma_perf_summary">Preferred network mode: WCDMA preferred</string>
+    <!-- GSM only [CHAR LIMIT=NONE] -->
+    <string name="preferred_network_mode_gsm_only_summary">Preferred network mode: GSM only</string>
+    <!-- WCDMA only [CHAR LIMIT=NONE] -->
+    <string name="preferred_network_mode_wcdma_only_summary">Preferred network mode: WCDMA only</string>
+    <!-- GSM / WCDMA [CHAR LIMIT=NONE] -->
+    <string name="preferred_network_mode_gsm_wcdma_summary">Preferred network mode: GSM / WCDMA</string>
+    <!-- CDMA [CHAR LIMIT=NONE] -->
+    <string name="preferred_network_mode_cdma_summary">Preferred network mode: CDMA</string>
+    <!-- CDMA / EvDo [CHAR LIMIT=NONE] -->
+    <string name="preferred_network_mode_cdma_evdo_summary">Preferred network mode: CDMA / EvDo</string>
+    <!-- CDMA only [CHAR LIMIT=NONE] -->
+    <string name="preferred_network_mode_cdma_only_summary">Preferred network mode: CDMA only</string>
+    <!-- EvDo only [CHAR LIMIT=NONE] -->
+    <string name="preferred_network_mode_evdo_only_summary">Preferred network mode: EvDo only</string>
+    <!-- CDMA/EvDo/GSM/WCDMA [CHAR LIMIT=NONE] -->
+    <string name="preferred_network_mode_cdma_evdo_gsm_wcdma_summary">Preferred network mode: CDMA/EvDo/GSM/WCDMA</string>
+    <!-- LTE [CHAR LIMIT=NONE] -->
+    <string name="preferred_network_mode_lte_summary">Preferred network mode: LTE </string>
+    <!-- GSM/WCDMA/LTE [CHAR LIMIT=NONE] -->
+    <string name="preferred_network_mode_lte_gsm_wcdma_summary">Preferred network mode: GSM/WCDMA/LTE</string>
+    <!-- CDMA+LTE/EVDO [CHAR LIMIT=NONE] -->
+    <string name="preferred_network_mode_lte_cdma_evdo_summary">Preferred network mode: CDMA+LTE/EVDO</string>
+    <!-- Global [CHAR LIMIT=NONE] -->
+    <string name="preferred_network_mode_global_summary">Preferred network mode: Global</string>
+    <!-- LTE / WCDMA [CHAR LIMIT=NONE] -->
+    <string name="preferred_network_mode_lte_wcdma_summary">Preferred network mode: LTE / WCDMA</string>
+    <!-- LTE / GSM / UMTS [CHAR LIMIT=NONE] -->
+    <string name="preferred_network_mode_lte_gsm_umts_summary">Preferred network mode: LTE / GSM / UMTS</string>
+    <!-- LTE / CDMA [CHAR LIMIT=NONE] -->
+    <string name="preferred_network_mode_lte_cdma_summary">Preferred network mode: LTE / CDMA</string>
+    <!-- TDSCDMA [CHAR LIMIT=NONE] -->
+    <string name="preferred_network_mode_tdscdma_summary">Preferred network mode: TDSCDMA</string>
+    <!-- TDSCDMA / WCDMA [CHAR LIMIT=NONE] -->
+    <string name="preferred_network_mode_tdscdma_wcdma_summary">Preferred network mode: TDSCDMA / WCDMA</string>
+    <!-- LTE / TDSCDMA [CHAR LIMIT=NONE] -->
+    <string name="preferred_network_mode_lte_tdscdma_summary">Preferred network mode: LTE / TDSCDMA</string>
+    <!-- TDSCDMA / GSM [CHAR LIMIT=NONE] -->
+    <string name="preferred_network_mode_tdscdma_gsm_summary">Preferred network mode: TDSCDMA / GSM</string>
+    <!-- LTE/GSM/TDSCDMA [CHAR LIMIT=NONE] -->
+    <string name="preferred_network_mode_lte_tdscdma_gsm_summary">Preferred network mode: LTE/GSM/TDSCDMA</string>
+    <!-- TDSCDMA/GSM/WCDMA [CHAR LIMIT=NONE] -->
+    <string name="preferred_network_mode_tdscdma_gsm_wcdma_summary">Preferred network mode: TDSCDMA/GSM/WCDMA</string>
+    <!-- LTE/TDSCDMA/WCDMA [CHAR LIMIT=NONE] -->
+    <string name="preferred_network_mode_lte_tdscdma_wcdma_summary">Preferred network mode: LTE/TDSCDMA/WCDMA</string>
+    <!-- LTE/TDSCDMA/GSM/WCDMA [CHAR LIMIT=NONE] -->
+    <string name="preferred_network_mode_lte_tdscdma_gsm_wcdma_summary">Preferred network mode: LTE/TDSCDMA/GSM/WCDMA</string>
+    <!-- TDSCDMA/CDMA/EvDo/GSM/WCDMA [CHAR LIMIT=NONE] -->
+    <string name="preferred_network_mode_tdscdma_cdma_evdo_gsm_wcdma_summary">Preferred network mode: TDSCDMA/CDMA/EvDo/GSM/WCDMA</string>
+    <!-- LTE/TDSCDMA/CDMA/EvDo/GSM/WCDMA [CHAR LIMIT=NONE] -->
+    <string name="preferred_network_mode_lte_tdscdma_cdma_evdo_gsm_wcdma_summary">Preferred network mode: LTE/TDSCDMA/CDMA/EvDo/GSM/WCDMA</string>
+
+    <!-- Text for Network lte [CHAR LIMIT=NONE] -->
+    <string name="network_lte">LTE (recommended)</string>
+    <!-- Text for Network 4g [CHAR LIMIT=NONE] -->
+    <string name="network_4G">4G (recommended)</string>
+    <!-- Text for Network 3g [CHAR LIMIT=NONE] -->
+    <string name="network_3G" translatable="false">3G</string>
+    <!-- Text for Network 2g [CHAR LIMIT=NONE] -->
+    <string name="network_2G" translatable="false">2G</string>
+    <!-- Text for Network 1x [CHAR LIMIT=NONE] -->
+    <string name="network_1x" translatable="false">1x</string>
+    <!-- Text for Network global [CHAR LIMIT=NONE] -->
+    <string name="network_global">Global</string>
+
+    <!-- Configuration setting for world mode Format is <true;GID if any to be checked> [CHAR LIMIT=NONE] -->
+    <string translatable="false" name="config_world_mode"/>
+
+    <!-- Available networks screen title/heading [CHAR LIMIT=NONE] -->
+    <string name="label_available">Available networks</string>
+    <!-- Mobile network settings screen, toast when searching for available networks [CHAR LIMIT=NONE] -->
+    <string name="load_networks_progress">Searching\u2026</string>
+    <!-- Available networks screen, toast when registering on a specific network [CHAR LIMIT=NONE] -->
+    <string name="register_on_network">Registering on <xliff:g id="network" example="Verizon">%s</xliff:g>\u2026</string>
+    <!-- Available networks screen, toast when SIM card isn't allowed on a network [CHAR LIMIT=NONE] -->
+    <string name="not_allowed">Your SIM card doesn\u2019t allow a connection to this network.</string>
+    <!-- Available networks screen, toast when unable to connect to a network temporarily [CHAR LIMIT=NONE] -->
+    <string name="connect_later">Can\u2019t connect to this network right now. Try again later.</string>
+    <!-- Available networks screen, toast when registered on a specific network [CHAR LIMIT=NONE] -->
+    <string name="registration_done">Registered on network.</string>
+
+    <!-- Available networks screen, name of switch button for whether to select network automatically [CHAR LIMIT=NONE] -->
+    <string name="select_automatically">Automatically select network</string>
+
+    <!-- A menu item in "Mobile network settings" that allows the user to update the phone
+     with mobile operator specific settings. [CHAR LIMIT=25] -->
+    <string name="carrier_settings_title">Carrier settings</string>
+    <!-- Preference title for launching an account manager page for prepaid LTE [CHAR LIMIT=30] -->
+    <string name="cdma_lte_data_service">Set up data service</string>
+    <!-- Mobile network settings screen, title of Mobile Data switch preference [CHAR LIMIT=NONE] -->
+    <string name="mobile_data_settings_title">Mobile data</string>
+    <!-- Mobile network settings screen, title of Mobile data switch preference [CHAR LIMIT=NONE] -->
+    <string name="mobile_data_settings_summary">Access data using mobile network</string>
+
+    <!-- Title for preferred network type [CHAR LIMIT=NONE] -->
+    <string name="preferred_network_mode_title">Preferred network type</string>
+    <!-- Summary for preferred network type [CHAR LIMIT=NONE] -->
+    <string name="preferred_network_mode_summary">Change the network operating mode</string>
+    <!-- Dialog title for preferred network type [CHAR LIMIT=NONE] -->
+    <string name="preferred_network_mode_dialogtitle">Preferred network type</string>
+    <!-- Mobile network settings screen, name of the option to manage carrier profiles on devices which support embedded carrier profiles [CHAR LIMIT=NONE] -->
+    <string name="carrier_settings_euicc">Carrier</string>
+
+    <!-- Mobile network settings screen, name for call settings category [CHAR LIMIT=NONE] -->
+    <string name="call_category">Calling</string>
+    <!-- Mobile network settings screen, title of Video calling setting [CHAR LIMIT=NONE] -->
+    <string name="video_calling_settings_title">Carrier video calling</string>
+
+    <!-- Mobile network settings screen, setting option name [CHAR LIMIT=NONE] -->
+    <string name="cdma_system_select_title">System select</string>
+    <!-- Mobile network settings screen, setting summary text [CHAR LIMIT=NONE] -->
+    <string name="cdma_system_select_summary">Change the CDMA roaming mode</string>
+    <!-- System select settings screen title [CHAR LIMIT=NONE] -->
+    <string name="cdma_system_select_dialogtitle">System select</string>
+
+    <!-- Mobile network settings screen, name for network operator category [CHAR LIMIT=NONE] -->
+    <string name="network_operator_category">Network</string>
+    <!-- Available networks screen, name of button when user wants to select network manually [CHAR LIMIT=NONE] -->
+    <string name="network_select_title">Network</string>
+
+    <!-- Title for CDMA subscription [CHAR LIMIT=50] -->
+    <string name="cdma_subscription_title">CDMA subscription</string>
+    <!-- Summary for CDMA subscription [CHAR LIMIT=NONE] -->
+    <string name="cdma_subscription_summary">Change between RUIM/SIM and NV</string>
+    <!-- Dialog title for CDMA subscription [CHAR LIMIT=30] -->
+    <string name="cdma_subscription_dialogtitle">subscription</string>
+
+    <!-- Title to register automatically [CHAR LIMIT=NONE] -->
+    <string name="register_automatically">Automatic registration\u2026</string>
+    <!-- Mobile network settings screen, dialog message title when user selects the Data roaming check box [CHAR LIMIT=120] -->
+    <string name="roaming_alert_title">Allow data roaming?</string>
+    <!-- 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>
+
+    <!-- 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/xml/cdma_options.xml b/res/xml/cdma_options.xml
new file mode 100644
index 0000000..046d16f
--- /dev/null
+++ b/res/xml/cdma_options.xml
@@ -0,0 +1,53 @@
+<?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.mobilenetwork.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.mobilenetwork.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
new file mode 100644
index 0000000..6ca9ad6
--- /dev/null
+++ b/res/xml/gsm_umts_options.xml
@@ -0,0 +1,59 @@
+<?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.mobilenetwork.NetworkOperators
+        android:key="network_operators_category_key"
+        android:title="@string/network_operator_category"
+        android:persistent="false">
+
+        <SwitchPreference
+            android:key="button_auto_select_key"
+            android:title="@string/select_automatically"
+            android:persistent="false"/>
+
+        <com.android.settings.mobilenetwork.NetworkSelectListPreference
+            android:key="button_network_select_key"
+            android:title="@string/network_select_title"
+            android:persistent="false"/>
+
+        <Preference
+            android:key="button_choose_network_key"
+            android:title="@string/choose_network_title"
+            android:fragment="com.android.phone.NetworkSelectSetting" />
+    </com.android.settings.mobilenetwork.NetworkOperators>
+
+    <!--We want separate APN setting from reset of settings because-->
+    <!--we want user to change it with caution.-->
+    <PreferenceCategory
+        android:key="category_gsm_apn_key"
+        android:layout="@layout/preference_category_no_label">
+
+        <com.android.settingslib.RestrictedPreference
+            android:key="button_gsm_apn_key"
+            android:title="@string/apn_settings"
+            android:persistent="false" />
+    </PreferenceCategory>
+
+    <PreferenceScreen
+        android:key="carrier_settings_key"
+        android:title="@string/carrier_settings_title">
+        <!-- b/114749736, create a preference controller to build intent -->
+    </PreferenceScreen>
+
+</PreferenceScreen>
diff --git a/res/xml/network_setting_fragment.xml b/res/xml/network_setting_fragment.xml
new file mode 100644
index 0000000..c383ab6
--- /dev/null
+++ b/res/xml/network_setting_fragment.xml
@@ -0,0 +1,91 @@
+<?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"
+    xmlns:settings="http://schemas.android.com/apk/res-auto"
+    settings:initialExpandedChildrenCount="4">
+
+    <PreferenceScreen
+        android:key="cdma_lte_data_service_key"
+        android:title="@string/cdma_lte_data_service">
+    </PreferenceScreen>
+
+    <com.android.settings.mobilenetwork.MobileDataPreference
+        android:key="mobile_data_enable"
+        android:title="@string/mobile_data_settings_title"
+        android:summary="@string/mobile_data_settings_summary"/>
+
+    <com.android.settingslib.RestrictedSwitchPreference
+        android:key="button_roaming_key"
+        android:title="@string/roaming"
+        android:persistent="false"
+        android:summaryOn="@string/roaming_enable"
+        android:summaryOff="@string/roaming_disable"/>
+
+    <com.android.settings.mobilenetwork.DataUsagePreference
+        android:key="data_usage_summary"
+        android:title="@string/data_usage_title" />
+
+    <SwitchPreference
+        android:key="enhanced_4g_lte"
+        android:title="@string/enhanced_4g_lte_mode_title"
+        android:persistent="false"
+        android:summary="@string/enhanced_4g_lte_mode_summary"/>
+
+    <ListPreference
+        android:key="preferred_network_mode_key"
+        android:title="@string/preferred_network_mode_title"
+        android:summary="@string/preferred_network_mode_summary"
+        android:entries="@array/preferred_network_mode_choices"
+        android:entryValues="@array/preferred_network_mode_values"
+        android:dialogTitle="@string/preferred_network_mode_dialogtitle" />
+
+    <ListPreference
+        android:key="enabled_networks_key"
+        android:title="@string/preferred_network_mode_title"
+        android:summary="@string/preferred_network_mode_summary"
+        android:entries="@array/enabled_networks_choices"
+        android:entryValues="@array/enabled_networks_values"
+        android:dialogTitle="@string/preferred_network_mode_dialogtitle" />
+
+    <Preference
+        android:key="carrier_settings_euicc_key"
+        android:title="@string/carrier_settings_euicc" />
+
+    <PreferenceCategory
+        android:key="calling"
+        android:title="@string/call_category">
+
+        <PreferenceScreen
+            android:key="wifi_calling_key"
+            android:title="@string/wifi_calling_settings_title">
+
+            <intent android:action="android.intent.action.MAIN"
+                    android:targetPackage="com.android.settings"
+                    android:targetClass="com.android.settings.Settings$WifiCallingSettingsActivity">
+                        <extra android:name="show_drawer_menu" android:value="true" />
+            </intent>
+
+        </PreferenceScreen>
+
+        <SwitchPreference
+            android:key="video_calling_key"
+            android:title="@string/video_calling_settings_title"
+            android:persistent="true"/>
+
+    </PreferenceCategory>
+
+</PreferenceScreen>
diff --git a/res/xml/security_lockscreen_settings.xml b/res/xml/security_lockscreen_settings.xml
index 51b1f5d..f829c8a 100644
--- a/res/xml/security_lockscreen_settings.xml
+++ b/res/xml/security_lockscreen_settings.xml
@@ -27,7 +27,8 @@
         <com.android.settings.RestrictedListPreference
             android:key="security_setting_lock_screen_notif"
             android:title="@string/lock_screen_notifications_title"
-            android:summary="@string/summary_placeholder" />
+            android:summary="@string/summary_placeholder"
+            settings:keywords="@string/keywords_lock_screen_notif"/>
 
         <com.android.settingslib.RestrictedSwitchPreference
             android:key="security_lockscreen_add_users_when_locked"
diff --git a/src/com/android/settings/SettingsActivity.java b/src/com/android/settings/SettingsActivity.java
index ea2370c..a51d45f 100644
--- a/src/com/android/settings/SettingsActivity.java
+++ b/src/com/android/settings/SettingsActivity.java
@@ -65,14 +65,12 @@
 import com.android.settings.homepage.SettingsHomepageActivity;
 import com.android.settings.homepage.TopLevelSettings;
 import com.android.settings.overlay.FeatureFactory;
-import com.android.settings.search.DeviceIndexFeatureProvider;
 import com.android.settings.wfd.WifiDisplaySettings;
 import com.android.settings.widget.SwitchBar;
 import com.android.settingslib.core.instrumentation.Instrumentable;
 import com.android.settingslib.core.instrumentation.SharedPreferencesLogger;
 import com.android.settingslib.development.DevelopmentSettingsEnabler;
 import com.android.settingslib.drawer.DashboardCategory;
-import com.android.settingslib.utils.ThreadUtils;
 
 import java.util.ArrayList;
 import java.util.List;
@@ -514,7 +512,6 @@
         registerReceiver(mBatteryInfoReceiver, new IntentFilter(Intent.ACTION_BATTERY_CHANGED));
 
         updateTilesList();
-        updateDeviceIndex();
     }
 
     @Override
@@ -636,14 +633,6 @@
         });
     }
 
-    private void updateDeviceIndex() {
-        DeviceIndexFeatureProvider indexProvider = FeatureFactory.getFactory(
-                this).getDeviceIndexFeatureProvider();
-
-        ThreadUtils.postOnBackgroundThread(
-                () -> indexProvider.updateIndex(SettingsActivity.this, false /* force */));
-    }
-
     private void doUpdateTilesList() {
         PackageManager pm = getPackageManager();
         final UserManager um = UserManager.get(this);
diff --git a/src/com/android/settings/mobilenetwork/CdmaOptions.java b/src/com/android/settings/mobilenetwork/CdmaOptions.java
new file mode 100644
index 0000000..fe50914
--- /dev/null
+++ b/src/com/android/settings/mobilenetwork/CdmaOptions.java
@@ -0,0 +1,204 @@
+/*
+ * 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.mobilenetwork;
+
+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.
+ */
+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) {
+        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) {
+        if (preference.getKey().equals(BUTTON_CDMA_SYSTEM_SELECT_KEY)) {
+            log("preferenceTreeClick: return BUTTON_CDMA_ROAMING_KEY true");
+            return true;
+        }
+        if (preference.getKey().equals(BUTTON_CDMA_SUBSCRIPTION_KEY)) {
+            log("preferenceTreeClick: return CDMA_SUBSCRIPTION_KEY true");
+            return true;
+        }
+        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/mobilenetwork/CdmaSubscriptionListPreference.java b/src/com/android/settings/mobilenetwork/CdmaSubscriptionListPreference.java
new file mode 100644
index 0000000..4e3767a
--- /dev/null
+++ b/src/com/android/settings/mobilenetwork/CdmaSubscriptionListPreference.java
@@ -0,0 +1,115 @@
+/*
+ * 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.mobilenetwork;
+
+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/mobilenetwork/CdmaSystemSelectListPreference.java b/src/com/android/settings/mobilenetwork/CdmaSystemSelectListPreference.java
new file mode 100644
index 0000000..3d3419f
--- /dev/null
+++ b/src/com/android/settings/mobilenetwork/CdmaSystemSelectListPreference.java
@@ -0,0 +1,186 @@
+/*
+ * 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.mobilenetwork;
+
+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/mobilenetwork/CellInfoUtil.java b/src/com/android/settings/mobilenetwork/CellInfoUtil.java
index 3d6cb28..bb5a8b4 100644
--- a/src/com/android/settings/mobilenetwork/CellInfoUtil.java
+++ b/src/com/android/settings/mobilenetwork/CellInfoUtil.java
@@ -127,6 +127,35 @@
         return oi;
     }
 
+    /**
+     * Creates a CellInfo object from OperatorInfo. GsmCellInfo is used here only because
+     * operatorInfo does not contain technology type while CellInfo is an abstract object that
+     * requires to specify technology type. It doesn't matter which CellInfo type to use here, since
+     * we only want to wrap the operator info and PLMN to a CellInfo object.
+     */
+    public static CellInfo convertOperatorInfoToCellInfo(OperatorInfo operatorInfo) {
+        String operatorNumeric = operatorInfo.getOperatorNumeric();
+        String mcc = null;
+        String mnc = null;
+        if (operatorNumeric != null && operatorNumeric.matches("^[0-9]{5,6}$")) {
+            mcc = operatorNumeric.substring(0, 3);
+            mnc = operatorNumeric.substring(3);
+        }
+        CellIdentityGsm cig = new CellIdentityGsm(
+                Integer.MAX_VALUE /* lac */,
+                Integer.MAX_VALUE /* cid */,
+                Integer.MAX_VALUE /* arfcn */,
+                Integer.MAX_VALUE /* bsic */,
+                mcc,
+                mnc,
+                operatorInfo.getOperatorAlphaLong(),
+                operatorInfo.getOperatorAlphaShort());
+
+        CellInfoGsm ci = new CellInfoGsm();
+        ci.setCellIdentity(cig);
+        return ci;
+    }
+
     /** Checks whether the network operator is forbidden. */
     public static boolean isForbidden(CellInfo cellInfo, List<String> forbiddenPlmns) {
         String plmn = CellInfoUtil.getOperatorInfoFromCellInfo(cellInfo).getOperatorNumeric();
diff --git a/src/com/android/settings/mobilenetwork/DataUsagePreference.java b/src/com/android/settings/mobilenetwork/DataUsagePreference.java
new file mode 100644
index 0000000..05d26ed
--- /dev/null
+++ b/src/com/android/settings/mobilenetwork/DataUsagePreference.java
@@ -0,0 +1,80 @@
+/*
+ * 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.mobilenetwork;
+
+import android.app.Activity;
+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/mobilenetwork/GsmUmtsOptions.java b/src/com/android/settings/mobilenetwork/GsmUmtsOptions.java
new file mode 100644
index 0000000..95f24fb
--- /dev/null
+++ b/src/com/android/settings/mobilenetwork/GsmUmtsOptions.java
@@ -0,0 +1,180 @@
+/*
+ * 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.
+ */
+
+package com.android.settings.mobilenetwork;
+
+import android.content.Context;
+import android.content.Intent;
+import android.os.PersistableBundle;
+import android.provider.Settings;
+import android.telephony.CarrierConfigManager;
+import android.telephony.TelephonyManager;
+
+import androidx.preference.Preference;
+import androidx.preference.PreferenceFragmentCompat;
+import androidx.preference.PreferenceScreen;
+
+import com.android.internal.logging.MetricsLogger;
+import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
+import com.android.internal.telephony.Phone;
+import com.android.internal.telephony.PhoneConstants;
+import com.android.settings.R;
+import com.android.settingslib.RestrictedLockUtilsInternal;
+import com.android.settingslib.RestrictedPreference;
+
+/**
+ * List of Network-specific settings screens.
+ */
+public class GsmUmtsOptions {
+    private static final String LOG_TAG = "GsmUmtsOptions";
+
+    private CarrierConfigManager mCarrierConfigManager;
+    private RestrictedPreference mButtonAPNExpand;
+    private Preference mCategoryAPNExpand;
+    Preference mCarrierSettingPref;
+
+    private NetworkOperators mNetworkOperator;
+
+    private static final String BUTTON_APN_EXPAND_KEY = "button_gsm_apn_key";
+    private static final String CATEGORY_APN_EXPAND_KEY = "category_gsm_apn_key";
+    private static final String BUTTON_CARRIER_SETTINGS_KEY = "carrier_settings_key";
+
+    public static final String EXTRA_SUB_ID = "sub_id";
+    private PreferenceFragmentCompat mPrefFragment;
+    private PreferenceScreen mPrefScreen;
+
+    public GsmUmtsOptions(PreferenceFragmentCompat prefFragment, PreferenceScreen prefScreen,
+            final int subId) {
+        final Context context = prefFragment.getContext();
+        mPrefFragment = prefFragment;
+        mPrefScreen = prefScreen;
+        mCarrierConfigManager = new CarrierConfigManager(context);
+        mPrefFragment.addPreferencesFromResource(R.xml.gsm_umts_options);
+        mButtonAPNExpand = (RestrictedPreference) mPrefScreen.findPreference(BUTTON_APN_EXPAND_KEY);
+        mCategoryAPNExpand = mPrefScreen.findPreference(CATEGORY_APN_EXPAND_KEY);
+        mNetworkOperator = (NetworkOperators) mPrefScreen
+                .findPreference(NetworkOperators.CATEGORY_NETWORK_OPERATORS_KEY);
+        mCarrierSettingPref = mPrefScreen.findPreference(BUTTON_CARRIER_SETTINGS_KEY);
+
+        mNetworkOperator.initialize();
+
+        update(subId);
+    }
+
+    // Unlike mPrefFragment or mPrefScreen, subId  may change during lifecycle of GsmUmtsOptions.
+    // When that happens, we update GsmUmtsOptions with new parameters.
+    protected void update(final int subId) {
+        boolean addAPNExpand = true;
+        boolean addNetworkOperatorsCategory = true;
+        boolean addCarrierSettings = true;
+        final TelephonyManager telephonyManager = TelephonyManager.from(mPrefFragment.getContext())
+                .createForSubscriptionId(subId);
+        //TODO(b/115429509): Get phone from subId
+        Phone phone = null;
+        if (phone == null) return;
+        if (telephonyManager.getPhoneType() != PhoneConstants.PHONE_TYPE_GSM) {
+            log("Not a GSM phone");
+            addAPNExpand = false;
+            mNetworkOperator.setEnabled(false);
+        } else {
+            log("Not a CDMA phone");
+            PersistableBundle carrierConfig = mCarrierConfigManager.getConfigForSubId(subId);
+
+            // Determine which options to display. For GSM these are defaulted to true in
+            // CarrierConfigManager, but they maybe overriden by DefaultCarrierConfigService or a
+            // carrier app.
+            // Note: these settings used to be controlled with overlays in
+            // Telephony/res/values/config.xml
+            if (!carrierConfig.getBoolean(CarrierConfigManager.KEY_APN_EXPAND_BOOL)
+                    && mCategoryAPNExpand != null) {
+                addAPNExpand = false;
+            }
+            if (!carrierConfig.getBoolean(
+                    CarrierConfigManager.KEY_OPERATOR_SELECTION_EXPAND_BOOL)) {
+                addNetworkOperatorsCategory = false;
+            }
+
+            if (carrierConfig.getBoolean(CarrierConfigManager.KEY_CSP_ENABLED_BOOL)) {
+                if (phone.isCspPlmnEnabled()) {
+                    log("[CSP] Enabling Operator Selection menu.");
+                    mNetworkOperator.setEnabled(true);
+                } else {
+                    log("[CSP] Disabling Operator Selection menu.");
+                    addNetworkOperatorsCategory = false;
+                }
+            }
+
+            // Read platform settings for carrier settings
+            addCarrierSettings = carrierConfig.getBoolean(
+                    CarrierConfigManager.KEY_CARRIER_SETTINGS_ENABLE_BOOL);
+        }
+
+        // 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(EXTRA_SUB_ID, subId);
+                            mPrefFragment.startActivity(intent);
+                            return true;
+                        }
+                    });
+            mPrefScreen.addPreference(mCategoryAPNExpand);
+        } else {
+            mPrefScreen.removePreference(mCategoryAPNExpand);
+        }
+
+        if (addNetworkOperatorsCategory) {
+            mPrefScreen.addPreference(mNetworkOperator);
+            mNetworkOperator.update(subId);
+        } else {
+            mPrefScreen.removePreference(mNetworkOperator);
+        }
+
+        if (addCarrierSettings) {
+            mPrefScreen.addPreference(mCarrierSettingPref);
+        } else {
+            mPrefScreen.removePreference(mCarrierSettingPref);
+        }
+
+    }
+
+    protected boolean preferenceTreeClick(Preference preference) {
+        return mNetworkOperator.preferenceTreeClick(preference);
+    }
+
+    protected void log(String s) {
+        android.util.Log.d(LOG_TAG, s);
+    }
+}
+
diff --git a/src/com/android/settings/mobilenetwork/MobileDataPreference.java b/src/com/android/settings/mobilenetwork/MobileDataPreference.java
new file mode 100644
index 0000000..37ce5a6
--- /dev/null
+++ b/src/com/android/settings/mobilenetwork/MobileDataPreference.java
@@ -0,0 +1,324 @@
+/*
+ * 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.mobilenetwork;
+
+import android.app.AlertDialog;
+import android.content.Context;
+import android.content.DialogInterface;
+import android.database.ContentObserver;
+import android.net.Uri;
+import android.os.Handler;
+import android.os.Looper;
+import android.os.Parcel;
+import android.os.Parcelable;
+import android.provider.Settings.Global;
+import android.telephony.SubscriptionInfo;
+import android.telephony.SubscriptionManager;
+import android.telephony.TelephonyManager;
+import android.util.AttributeSet;
+import android.util.Log;
+import android.view.View;
+import android.widget.Checkable;
+
+import androidx.preference.DialogPreference;
+import androidx.preference.PreferenceScreen;
+import androidx.preference.PreferenceViewHolder;
+
+import com.android.internal.logging.MetricsLogger;
+import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
+import com.android.settings.R;
+
+import java.util.List;
+
+/**
+ * Customized Preference to enable / disable mobile data.
+ * Basically copy of with com.android.settings.CellDataPreference.
+ */
+public class MobileDataPreference extends DialogPreference implements
+        DialogInterface.OnClickListener {
+
+    private static final boolean DBG = false;
+    private static final String TAG = "MobileDataPreference";
+
+    public int mSubId = SubscriptionManager.INVALID_SUBSCRIPTION_ID;
+    public boolean mChecked;
+    // Whether to show the dialog to ask switching default data subscription.
+    // Should be true only when a multi-sim phone only supports data connection on a single phone,
+    // and user is enabling data on the non-default phone.
+    public boolean mMultiSimDialog;
+    private TelephonyManager mTelephonyManager;
+    private SubscriptionManager mSubscriptionManager;
+
+    public MobileDataPreference(Context context, AttributeSet attrs) {
+        super(context, attrs, com.android.internal.R.attr.switchPreferenceStyle);
+    }
+
+    // Must be called to avoid binder leakage.
+    void dispose() {
+        mListener.setListener(false, mSubId, getContext());
+    }
+
+    @Override
+    protected void onRestoreInstanceState(Parcelable s) {
+        CellDataState state = (CellDataState) s;
+        super.onRestoreInstanceState(state.getSuperState());
+        mTelephonyManager = TelephonyManager.from(getContext());
+        mChecked = state.mChecked;
+        mMultiSimDialog = state.mMultiSimDialog;
+        if (mSubId == SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
+            mSubId = state.mSubId;
+            setKey(getKey() + mSubId);
+        }
+        notifyChanged();
+    }
+
+    @Override
+    protected Parcelable onSaveInstanceState() {
+        CellDataState state = new CellDataState(super.onSaveInstanceState());
+        state.mChecked = mChecked;
+        state.mMultiSimDialog = mMultiSimDialog;
+        state.mSubId = mSubId;
+        return state;
+    }
+
+    @Override
+    public void onAttached() {
+        super.onAttached();
+        mListener.setListener(true, mSubId, getContext());
+    }
+
+    @Override
+    protected void onPrepareForRemoval() {
+        mListener.setListener(false, mSubId, getContext());
+        super.onPrepareForRemoval();
+    }
+
+    /**
+     * Initialize this preference with subId.
+     */
+    public void initialize(int subId) {
+        if (subId == SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
+            throw new IllegalArgumentException("MobileDataPreference needs a SubscriptionInfo");
+        }
+        mSubscriptionManager = SubscriptionManager.from(getContext());
+        mTelephonyManager = TelephonyManager.from(getContext());
+        if (mSubId != subId) {
+            mSubId = subId;
+            setKey(getKey() + subId);
+        }
+        updateChecked();
+    }
+
+    private void updateChecked() {
+        setChecked(mTelephonyManager.getDataEnabled(mSubId));
+    }
+
+    @Override
+    public void performClick() {
+        if (!isEnabled() || !SubscriptionManager.isValidSubscriptionId(mSubId)) {
+            return;
+        }
+        final SubscriptionInfo currentSir = mSubscriptionManager.getActiveSubscriptionInfo(
+                mSubId);
+        final SubscriptionInfo nextSir = mSubscriptionManager.getDefaultDataSubscriptionInfo();
+        final boolean isMultiSim = (mTelephonyManager.getSimCount() > 1);
+        final boolean isMultipleDataOnCapable =
+                (mTelephonyManager.getNumberOfModemsWithSimultaneousDataConnections() > 1);
+        final boolean isDefaultDataSubscription = (nextSir != null && currentSir != null
+                && currentSir.getSubscriptionId() == nextSir.getSubscriptionId());
+        if (mChecked) {
+            if (!isMultiSim) {
+                // disabling data; show confirmation dialog which eventually
+                // calls setMobileDataEnabled() once user confirms.
+                mMultiSimDialog = false;
+                super.performClick();
+            } else {
+                // Don't show any dialog.
+                setMobileDataEnabled(false /* enabled */, false /* disableOtherSubscriptions */);
+            }
+        } else {
+            if (isMultiSim && !isMultipleDataOnCapable && !isDefaultDataSubscription) {
+                // enabling data and setting to default; show confirmation dialog which eventually
+                // calls setMobileDataEnabled() once user confirms.
+                mMultiSimDialog = true;
+                super.performClick();
+            } else {
+                // Don't show any dialog.
+                setMobileDataEnabled(true /* enabled */, false /* disableOtherSubscriptions */);
+            }
+        }
+    }
+
+    private void setMobileDataEnabled(boolean enabled, boolean disableOtherSubscriptions) {
+        if (DBG) Log.d(TAG, "setMobileDataEnabled(" + enabled + "," + mSubId + ")");
+
+        MetricsLogger.action(getContext(), MetricsEvent.ACTION_MOBILE_NETWORK_MOBILE_DATA_TOGGLE,
+                enabled);
+
+        mTelephonyManager.setDataEnabled(mSubId, enabled);
+
+        if (disableOtherSubscriptions) {
+            disableDataForOtherSubscriptions(mSubId);
+        }
+
+        setChecked(enabled);
+    }
+
+    private void setChecked(boolean checked) {
+        if (mChecked == checked) return;
+        mChecked = checked;
+        notifyChanged();
+    }
+
+    @Override
+    public void onBindViewHolder(PreferenceViewHolder holder) {
+        super.onBindViewHolder(holder);
+        View checkableView = holder.findViewById(com.android.internal.R.id.switch_widget);
+        checkableView.setClickable(false);
+        ((Checkable) checkableView).setChecked(mChecked);
+    }
+
+    //TODO(b/114749736): move it to preference controller
+    protected void onPrepareDialogBuilder(AlertDialog.Builder builder) {
+        if (mMultiSimDialog) {
+            showMultiSimDialog(builder);
+        } else {
+            showDisableDialog(builder);
+        }
+    }
+
+    private void showDisableDialog(AlertDialog.Builder builder) {
+        builder.setTitle(null)
+                .setMessage(R.string.data_usage_disable_mobile)
+                .setPositiveButton(android.R.string.ok, this)
+                .setNegativeButton(android.R.string.cancel, null);
+    }
+
+    private void showMultiSimDialog(AlertDialog.Builder builder) {
+        final SubscriptionInfo currentSir = mSubscriptionManager.getActiveSubscriptionInfo(mSubId);
+        final SubscriptionInfo nextSir = mSubscriptionManager.getDefaultDataSubscriptionInfo();
+
+        final String previousName = (nextSir == null)
+                ? getContext().getResources().getString(R.string.sim_selection_required_pref)
+                : nextSir.getDisplayName().toString();
+
+        builder.setTitle(R.string.sim_change_data_title);
+        builder.setMessage(getContext().getString(R.string.sim_change_data_message,
+                String.valueOf(currentSir != null ? currentSir.getDisplayName() : null),
+                previousName));
+
+        builder.setPositiveButton(android.R.string.ok, this);
+        builder.setNegativeButton(R.string.cancel, null);
+    }
+
+    private void disableDataForOtherSubscriptions(int subId) {
+        List<SubscriptionInfo> subInfoList = mSubscriptionManager.getActiveSubscriptionInfoList();
+        if (subInfoList != null) {
+            for (SubscriptionInfo subInfo : subInfoList) {
+                if (subInfo.getSubscriptionId() != subId) {
+                    mTelephonyManager.setDataEnabled(subInfo.getSubscriptionId(), false);
+                }
+            }
+        }
+    }
+
+    @Override
+    public void onClick(DialogInterface dialog, int which) {
+        if (which != DialogInterface.BUTTON_POSITIVE) {
+            return;
+        }
+        if (mMultiSimDialog) {
+            mSubscriptionManager.setDefaultDataSubId(mSubId);
+            setMobileDataEnabled(true /* enabled */, true /* disableOtherSubscriptions */);
+        } else {
+            // TODO: extend to modify policy enabled flag.
+            setMobileDataEnabled(false /* enabled */, false /* disableOtherSubscriptions */);
+        }
+    }
+
+    private final DataStateListener mListener = new DataStateListener() {
+        @Override
+        public void onChange(boolean selfChange) {
+            updateChecked();
+        }
+    };
+
+    /**
+     * Listener that listens mobile data state change.
+     */
+    public abstract static class DataStateListener extends ContentObserver {
+        public DataStateListener() {
+            super(new Handler(Looper.getMainLooper()));
+        }
+
+        /**
+         * Set / Unset data state listening, specifying subId.
+         */
+        public void setListener(boolean listening, int subId, Context context) {
+            if (listening) {
+                Uri uri = Global.getUriFor(Global.MOBILE_DATA);
+                if (TelephonyManager.getDefault().getSimCount() != 1) {
+                    uri = Global.getUriFor(Global.MOBILE_DATA + subId);
+                }
+                context.getContentResolver().registerContentObserver(uri, false, this);
+            } else {
+                context.getContentResolver().unregisterContentObserver(this);
+            }
+        }
+    }
+
+    /**
+     * Class that represents state of mobile data state.
+     * Used by onSaveInstanceState and onRestoreInstanceState.
+     */
+    public static class CellDataState extends BaseSavedState {
+        public int mSubId;
+        public boolean mChecked;
+        public boolean mMultiSimDialog;
+
+        public CellDataState(Parcelable base) {
+            super(base);
+        }
+
+        public CellDataState(Parcel source) {
+            super(source);
+            mChecked = source.readByte() != 0;
+            mMultiSimDialog = source.readByte() != 0;
+            mSubId = source.readInt();
+        }
+
+        @Override
+        public void writeToParcel(Parcel dest, int flags) {
+            super.writeToParcel(dest, flags);
+            dest.writeByte((byte) (mChecked ? 1 : 0));
+            dest.writeByte((byte) (mMultiSimDialog ? 1 : 0));
+            dest.writeInt(mSubId);
+        }
+
+        public static final Creator<CellDataState> CREATOR = new Creator<CellDataState>() {
+            @Override
+            public CellDataState createFromParcel(Parcel source) {
+                return new CellDataState(source);
+            }
+
+            @Override
+            public CellDataState[] newArray(int size) {
+                return new CellDataState[size];
+            }
+        };
+    }
+}
diff --git a/src/com/android/settings/mobilenetwork/MobileNetworkFragment.java b/src/com/android/settings/mobilenetwork/MobileNetworkFragment.java
new file mode 100644
index 0000000..d8df8fa
--- /dev/null
+++ b/src/com/android/settings/mobilenetwork/MobileNetworkFragment.java
@@ -0,0 +1,1895 @@
+/*
+ * 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.mobilenetwork;
+
+import static android.provider.Telephony.Carriers.ENFORCE_MANAGED_URI;
+
+import android.app.ActionBar;
+import android.content.BroadcastReceiver;
+import android.content.Context;
+import android.content.Intent;
+import android.content.IntentFilter;
+import android.content.pm.PackageManager;
+import android.content.pm.ResolveInfo;
+import android.database.ContentObserver;
+import android.net.Uri;
+import android.os.AsyncTask;
+import android.os.Bundle;
+import android.os.Handler;
+import android.os.Message;
+import android.os.PersistableBundle;
+import android.os.UserHandle;
+import android.os.UserManager;
+import android.provider.Settings;
+import android.telecom.PhoneAccountHandle;
+import android.telecom.TelecomManager;
+import android.telephony.CarrierConfigManager;
+import android.telephony.PhoneStateListener;
+import android.telephony.ServiceState;
+import android.telephony.SubscriptionInfo;
+import android.telephony.SubscriptionManager;
+import android.telephony.TelephonyManager;
+import android.telephony.euicc.EuiccManager;
+import android.text.TextUtils;
+import android.util.Log;
+import android.view.MenuItem;
+
+import com.android.ims.ImsConfig;
+import com.android.ims.ImsManager;
+import com.android.internal.logging.MetricsLogger;
+import com.android.internal.logging.nano.MetricsProto;
+import com.android.internal.telephony.Phone;
+import com.android.internal.telephony.PhoneConstants;
+import com.android.internal.telephony.TelephonyIntents;
+import com.android.settings.R;
+import com.android.settings.dashboard.DashboardFragment;
+import com.android.settings.search.BaseSearchIndexProvider;
+import com.android.settings.search.Indexable;
+import com.android.settingslib.RestrictedLockUtilsInternal;
+import com.android.settingslib.RestrictedSwitchPreference;
+import com.android.settingslib.search.SearchIndexable;
+
+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 {
+
+    // debug data
+    private static final String LOG_TAG = "NetworkSettings";
+    private static final boolean DBG = true;
+    public static final int REQUEST_CODE_EXIT_ECM = 17;
+
+    // Number of active Subscriptions to show tabs
+    private static final int TAB_THRESHOLD = 2;
+
+    // Number of last phone number digits shown in Euicc Setting tab
+    private static final int NUM_LAST_PHONE_DIGITS = 4;
+
+    // fragment tag for roaming data dialog
+    private static final String ROAMING_TAG = "RoamingDialogFragment";
+
+    //String keys for preference lookup
+    private static final String BUTTON_PREFERED_NETWORK_MODE = "preferred_network_mode_key";
+    private static final String BUTTON_ROAMING_KEY = "button_roaming_key";
+    private static final String BUTTON_CDMA_LTE_DATA_SERVICE_KEY = "cdma_lte_data_service_key";
+    private static final String BUTTON_ENABLED_NETWORKS_KEY = "enabled_networks_key";
+    private static final String BUTTON_4G_LTE_KEY = "enhanced_4g_lte";
+    private static final String BUTTON_CELL_BROADCAST_SETTINGS = "cell_broadcast_settings";
+    private static final String BUTTON_CARRIER_SETTINGS_KEY = "carrier_settings_key";
+    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_EUICC_KEY =
+            "carrier_settings_euicc_key";
+    private static final String BUTTON_WIFI_CALLING_KEY = "wifi_calling_key";
+    private static final String BUTTON_VIDEO_CALLING_KEY = "video_calling_key";
+    private static final String BUTTON_MOBILE_DATA_ENABLE_KEY = "mobile_data_enable";
+    private static final String BUTTON_DATA_USAGE_KEY = "data_usage_summary";
+    private static final String BUTTON_ADVANCED_OPTIONS_KEY = "advanced_options";
+    private static final String CATEGORY_CALLING_KEY = "calling";
+    private static final String CATEGORY_GSM_APN_EXPAND_KEY = "category_gsm_apn_key";
+    private static final String CATEGORY_CDMA_APN_EXPAND_KEY = "category_cdma_apn_key";
+    private static final String BUTTON_GSM_APN_EXPAND_KEY = "button_gsm_apn_key";
+    private static final String BUTTON_CDMA_APN_EXPAND_KEY = "button_cdma_apn_key";
+
+    private static final String EXTRA_EXIT_ECM_RESULT = "exit_ecm_result";
+    private static final String LEGACY_ACTION_CONFIGURE_PHONE_ACCOUNT =
+            "android.telecom.action.CONNECTION_SERVICE_CONFIGURE";
+
+    private final BroadcastReceiver
+            mPhoneChangeReceiver = new PhoneChangeReceiver();
+    private final ContentObserver
+            mDpcEnforcedContentObserver = new DpcApnEnforcedObserver();
+
+    static final int preferredNetworkMode = Phone.PREFERRED_NT_MODE;
+
+    //Information about logical "up" Activity
+    private static final String UP_ACTIVITY_PACKAGE = "com.android.settings";
+    private static final String UP_ACTIVITY_CLASS =
+            "com.android.settings.Settings$WirelessSettingsActivity";
+
+    //Information that needs to save into Bundle.
+    private static final String EXPAND_ADVANCED_FIELDS = "expand_advanced_fields";
+    //Intent extra to indicate expand all fields.
+    private static final String EXPAND_EXTRA = "expandable";
+
+    private enum TabState {
+        NO_TABS, UPDATE, DO_NOTHING
+    }
+
+    private SubscriptionManager mSubscriptionManager;
+    private TelephonyManager mTelephonyManager;
+    private CarrierConfigManager mCarrierConfigManager;
+    private int mSubId;
+
+    //UI objects
+    private ListPreference mButtonPreferredNetworkMode;
+    private ListPreference mButtonEnabledNetworks;
+    private RestrictedSwitchPreference mButtonDataRoam;
+    private SwitchPreference mButton4glte;
+    private Preference mLteDataServicePref;
+    private Preference mEuiccSettingsPref;
+    private PreferenceCategory mCallingCategory;
+    private Preference mWiFiCallingPref;
+    private SwitchPreference mVideoCallingPref;
+    private NetworkSelectListPreference mButtonNetworkSelect;
+    private MobileDataPreference mMobileDataPref;
+    private DataUsagePreference mDataUsagePref;
+
+    private static final String iface = "rmnet0"; //TODO: this will go away
+    private List<SubscriptionInfo> mActiveSubInfos;
+
+    private UserManager mUm;
+    private ImsManager mImsMgr;
+    private MyHandler mHandler;
+    private boolean mOkClicked;
+
+    //GsmUmts options and Cdma options
+    GsmUmtsOptions mGsmUmtsOptions;
+    CdmaOptions mCdmaOptions;
+
+    private Preference mClickedPreference;
+    private boolean mShow4GForLTE;
+    private boolean mIsGlobalCdma;
+    private boolean mOnlyAutoSelectInHomeNW;
+    private boolean mUnavailable;
+
+    private class PhoneCallStateListener extends PhoneStateListener {
+        /*
+         * Enable/disable the 'Enhanced 4G LTE Mode' when in/out of a call
+         * and depending on TTY mode and TTY support over VoLTE.
+         * @see android.telephony.PhoneStateListener#onCallStateChanged(int,
+         * java.lang.String)
+         */
+        @Override
+        public void onCallStateChanged(int state, String incomingNumber) {
+            if (DBG) log("PhoneStateListener.onCallStateChanged: state=" + state);
+
+            updateEnhanced4gLteState();
+            updateWiFiCallState();
+            updateVideoCallState();
+            updatePreferredNetworkType();
+        }
+
+        /**
+         * Listen to different subId if it's changed.
+         */
+        protected void updateSubscriptionId(Integer subId) {
+            if (subId.equals(PhoneCallStateListener.this.mSubId)) {
+                return;
+            }
+
+            PhoneCallStateListener.this.mSubId = subId;
+
+            mTelephonyManager.listen(this, PhoneStateListener.LISTEN_NONE);
+
+            // Now, listen to new subId if it's valid.
+            if (SubscriptionManager.isValidSubscriptionId(subId)) {
+                mTelephonyManager.listen(this, PhoneStateListener.LISTEN_CALL_STATE);
+            }
+        }
+    }
+
+    private final PhoneCallStateListener
+            mPhoneStateListener = new PhoneCallStateListener();
+
+    @Override
+    public int getMetricsCategory() {
+        //TODO(b/114749736): add metrics id for it
+        return 0;
+    }
+
+    @Override
+    public void onPositiveButtonClick(androidx.fragment.app.DialogFragment dialog) {
+        mTelephonyManager.setDataRoamingEnabled(true);
+        mButtonDataRoam.setChecked(true);
+        MetricsLogger.action(getContext(),
+                getMetricsEventCategory(getPreferenceScreen(), mButtonDataRoam),
+                true);
+    }
+
+    /**
+     * Invoked on each preference click in this hierarchy, overrides
+     * PreferenceActivity's implementation.  Used to make sure we track the
+     * preference click events.
+     */
+    @Override
+    public boolean onPreferenceTreeClick(Preference preference) {
+        sendMetricsEventPreferenceClicked(getPreferenceScreen(), preference);
+
+        /** TODO: Refactor and get rid of the if's using subclasses */
+        if (preference.getKey().equals(BUTTON_4G_LTE_KEY)) {
+            return true;
+        } else if (mGsmUmtsOptions != null &&
+                mGsmUmtsOptions.preferenceTreeClick(preference) == true) {
+            return true;
+        } else if (mCdmaOptions != null &&
+                mCdmaOptions.preferenceTreeClick(preference) == true) {
+            if (mTelephonyManager.getEmergencyCallbackMode()) {
+
+                mClickedPreference = preference;
+
+                // In ECM mode launch ECM app dialog
+                startActivityForResult(
+                        new Intent(TelephonyIntents.ACTION_SHOW_NOTICE_ECM_BLOCK_OTHERS, null),
+                        REQUEST_CODE_EXIT_ECM);
+            }
+            return true;
+        } else if (preference == mButtonPreferredNetworkMode) {
+            //displays the value taken from the Settings.System
+            int settingsNetworkMode = android.provider.Settings.Global.getInt(
+                    getContext().getContentResolver(),
+                    android.provider.Settings.Global.PREFERRED_NETWORK_MODE + mSubId,
+                    preferredNetworkMode);
+            mButtonPreferredNetworkMode.setValue(Integer.toString(settingsNetworkMode));
+            return true;
+        } else if (preference == mLteDataServicePref) {
+            String tmpl = android.provider.Settings.Global.getString(
+                    getContext().getContentResolver(),
+                    android.provider.Settings.Global.SETUP_PREPAID_DATA_SERVICE_URL);
+            if (!TextUtils.isEmpty(tmpl)) {
+                String imsi = mTelephonyManager.getSubscriberId();
+                if (imsi == null) {
+                    imsi = "";
+                }
+                final String url = TextUtils.isEmpty(tmpl) ? null
+                        : TextUtils.expandTemplate(tmpl, imsi).toString();
+                Intent intent = new Intent(Intent.ACTION_VIEW, Uri.parse(url));
+                startActivity(intent);
+            } else {
+                android.util.Log.e(LOG_TAG, "Missing SETUP_PREPAID_DATA_SERVICE_URL");
+            }
+            return true;
+        }  else if (preference == mButtonEnabledNetworks) {
+            int settingsNetworkMode = android.provider.Settings.Global.getInt(
+                    getContext().getContentResolver(),
+                    android.provider.Settings.Global.PREFERRED_NETWORK_MODE + mSubId,
+                    preferredNetworkMode);
+            mButtonEnabledNetworks.setValue(Integer.toString(settingsNetworkMode));
+            return true;
+        } else if (preference == mButtonDataRoam) {
+            // Do not disable the preference screen if the user clicks Data roaming.
+            return true;
+        } else if (preference == mEuiccSettingsPref) {
+            Intent intent = new Intent(EuiccManager.ACTION_MANAGE_EMBEDDED_SUBSCRIPTIONS);
+            startActivity(intent);
+            return true;
+        } else if (preference == mWiFiCallingPref || preference == mVideoCallingPref
+                || preference == mMobileDataPref || preference == mDataUsagePref) {
+            return false;
+        } else {
+            // if the button is anything but the simple toggle preference,
+            // we'll need to disable all preferences to reject all click
+            // events until the sub-activity's UI comes up.
+            getPreferenceScreen().setEnabled(false);
+            // Let the intents be launched by the Preference manager
+            return false;
+        }
+    }
+
+    private final SubscriptionManager.OnSubscriptionsChangedListener
+            mOnSubscriptionsChangeListener
+            = new SubscriptionManager.OnSubscriptionsChangedListener() {
+        @Override
+        public void onSubscriptionsChanged() {
+            if (DBG) log("onSubscriptionsChanged:");
+            initializeSubscriptions();
+        }
+    };
+
+    private int getSlotIdFromIntent(Intent intent) {
+        Bundle data = intent.getExtras();
+        int subId = -1;
+        if (data != null) {
+            subId = data.getInt(Settings.EXTRA_SUB_ID, -1);
+        }
+        return SubscriptionManager.getSlotIndex(subId);
+    }
+
+    private void initializeSubscriptions() {
+        final FragmentActivity activity = getActivity();
+        if (activity == null) {
+            // Process preferences in activity only if its not destroyed
+            return;
+        }
+        updatePhone();
+        updateBody();
+        if (DBG) log("initializeSubscriptions:-");
+    }
+
+    private TabState isUpdateTabsNeeded(List<SubscriptionInfo> newSil) {
+        TabState state = TabState.DO_NOTHING;
+        if (newSil == null) {
+            if (mActiveSubInfos.size() >= TAB_THRESHOLD) {
+                if (DBG) log("isUpdateTabsNeeded: NO_TABS, size unknown and was tabbed");
+                state = TabState.NO_TABS;
+            }
+        } else if (newSil.size() < TAB_THRESHOLD && mActiveSubInfos.size() >= TAB_THRESHOLD) {
+            if (DBG) log("isUpdateTabsNeeded: NO_TABS, size went to small");
+            state = TabState.NO_TABS;
+        } else if (newSil.size() >= TAB_THRESHOLD && mActiveSubInfos.size() < TAB_THRESHOLD) {
+            if (DBG) log("isUpdateTabsNeeded: UPDATE, size changed");
+            state = TabState.UPDATE;
+        } else if (newSil.size() >= TAB_THRESHOLD) {
+            Iterator<SubscriptionInfo> siIterator = mActiveSubInfos.iterator();
+            for(SubscriptionInfo newSi : newSil) {
+                SubscriptionInfo curSi = siIterator.next();
+                if (!newSi.getDisplayName().equals(curSi.getDisplayName())) {
+                    if (DBG) log("isUpdateTabsNeeded: UPDATE, new name="
+                            + newSi.getDisplayName());
+                    state = TabState.UPDATE;
+                    break;
+                }
+            }
+        }
+        if (DBG) {
+            Log.i(LOG_TAG, "isUpdateTabsNeeded:- " + state
+                    + " newSil.size()=" + ((newSil != null) ? newSil.size() : 0)
+                    + " mActiveSubInfos.size()=" + mActiveSubInfos.size());
+        }
+        return state;
+    }
+
+    private void updatePhone() {
+        if (mSubId != SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
+            mImsMgr = ImsManager.getInstance(getContext(),
+                    SubscriptionManager.getPhoneId(mSubId));
+            mTelephonyManager = new TelephonyManager(getContext(), mSubId);
+        }
+
+        mPhoneStateListener.updateSubscriptionId(mSubId);
+    }
+
+    @Override
+    public void onCreate(Bundle icicle) {
+        Log.i(LOG_TAG, "onCreate:+");
+        super.onCreate(icicle);
+        final Context context = getContext();
+
+        if (context == null) {
+            Log.e(LOG_TAG, "onCreate:- with no valid activity.");
+            return;
+        }
+
+        mHandler = new MyHandler();
+        mUm = (UserManager) context.getSystemService(Context.USER_SERVICE);
+        mSubscriptionManager = SubscriptionManager.from(context);
+        mTelephonyManager = (TelephonyManager) context.getSystemService(
+                Context.TELEPHONY_SERVICE);
+        mCarrierConfigManager = new CarrierConfigManager(getContext());
+
+        mButton4glte = (SwitchPreference)findPreference(BUTTON_4G_LTE_KEY);
+        mButton4glte.setOnPreferenceChangeListener(this);
+
+        mCallingCategory = (PreferenceCategory) findPreference(CATEGORY_CALLING_KEY);
+        mWiFiCallingPref = findPreference(BUTTON_WIFI_CALLING_KEY);
+        mVideoCallingPref = (SwitchPreference) findPreference(BUTTON_VIDEO_CALLING_KEY);
+        mMobileDataPref = (MobileDataPreference) findPreference(BUTTON_MOBILE_DATA_ENABLE_KEY);
+        mDataUsagePref = (DataUsagePreference) findPreference(BUTTON_DATA_USAGE_KEY);
+
+        try {
+            Context con = context.createPackageContext("com.android.systemui", 0);
+            int id = con.getResources().getIdentifier("config_show4GForLTE",
+                    "bool", "com.android.systemui");
+            mShow4GForLTE = con.getResources().getBoolean(id);
+        } catch (PackageManager.NameNotFoundException e) {
+            Log.e(LOG_TAG, "NameNotFoundException for show4GFotLTE");
+            mShow4GForLTE = false;
+        }
+
+        //get UI object references
+        PreferenceScreen prefSet = getPreferenceScreen();
+
+        mButtonDataRoam = (RestrictedSwitchPreference) prefSet.findPreference(
+                BUTTON_ROAMING_KEY);
+        mButtonPreferredNetworkMode = (ListPreference) prefSet.findPreference(
+                BUTTON_PREFERED_NETWORK_MODE);
+        mButtonEnabledNetworks = (ListPreference) prefSet.findPreference(
+                BUTTON_ENABLED_NETWORKS_KEY);
+        mButtonDataRoam.setOnPreferenceChangeListener(this);
+
+        mLteDataServicePref = prefSet.findPreference(BUTTON_CDMA_LTE_DATA_SERVICE_KEY);
+
+        mEuiccSettingsPref = prefSet.findPreference(BUTTON_CARRIER_SETTINGS_EUICC_KEY);
+        mEuiccSettingsPref.setOnPreferenceChangeListener(this);
+
+        // Initialize mActiveSubInfo
+        int max = mSubscriptionManager.getActiveSubscriptionInfoCountMax();
+        mActiveSubInfos = mSubscriptionManager.getActiveSubscriptionInfoList();
+        mSubId = getArguments().getInt(MobileSettingsActivity.KEY_SUBSCRIPTION_ID,
+                SubscriptionManager.INVALID_SUBSCRIPTION_ID);
+
+        updatePhone();
+        if (hasActiveSubscriptions()) {
+            updateEnabledNetworksEntries();
+        }
+        Log.i(LOG_TAG, "onCreate:-");
+    }
+
+    @Override
+    public void onActivityCreated(Bundle savedInstanceState) {
+        super.onActivityCreated(savedInstanceState);
+        if (mUm.hasUserRestriction(UserManager.DISALLOW_CONFIG_MOBILE_NETWORKS)
+                || !mUm.isSystemUser()) {
+            mUnavailable = true;
+            //TODO(b/114749736): migrate telephony_disallowed_preference_screen.xml
+        } else {
+            initializeSubscriptions();
+        }
+    }
+
+    private class PhoneChangeReceiver extends BroadcastReceiver {
+        @Override
+        public void onReceive(Context context, Intent intent) {
+            Log.i(LOG_TAG, "onReceive:");
+            if (getActivity() == null || getContext() == null) {
+                // Received broadcast and activity is in the process of being torn down.
+                return;
+            }
+            // When the radio changes (ex: CDMA->GSM), refresh all options.
+            updateBody();
+        }
+    }
+
+    private class DpcApnEnforcedObserver extends ContentObserver {
+        DpcApnEnforcedObserver() {
+            super(null);
+        }
+
+        @Override
+        public void onChange(boolean selfChange) {
+            Log.i(LOG_TAG, "DPC enforced onChange:");
+            if (getActivity() == null || getContext() == null) {
+                // Received content change and activity is in the process of being torn down.
+                return;
+            }
+            updateBody();
+        }
+    }
+
+    @Override
+    public void onDestroy() {
+        super.onDestroy();
+        if (mMobileDataPref != null) {
+            mMobileDataPref.dispose();
+        }
+    }
+
+    @Override
+    public void onResume() {
+        super.onResume();
+        Log.i(LOG_TAG, "onResume:+");
+
+        if (mUnavailable) {
+            Log.i(LOG_TAG, "onResume:- ignore mUnavailable == false");
+            return;
+        }
+
+        // upon resumption from the sub-activity, make sure we re-enable the
+        // preferences.
+        getPreferenceScreen().setEnabled(true);
+
+        // Set UI state in onResume because a user could go home, launch some
+        // app to change this setting's backend, and re-launch this settings app
+        // and the UI state would be inconsistent with actual state
+        mButtonDataRoam.setChecked(mTelephonyManager.isDataRoamingEnabled());
+
+        if (getPreferenceScreen().findPreference(BUTTON_PREFERED_NETWORK_MODE) != null
+                || getPreferenceScreen().findPreference(BUTTON_ENABLED_NETWORKS_KEY) != null)  {
+            updatePreferredNetworkUIFromDb();
+        }
+
+        mTelephonyManager.listen(mPhoneStateListener, PhoneStateListener.LISTEN_CALL_STATE);
+
+        // NOTE: Buttons will be enabled/disabled in mPhoneStateListener
+        updateEnhanced4gLteState();
+
+        // Video calling and WiFi calling state might have changed.
+        updateCallingCategory();
+
+        mSubscriptionManager.addOnSubscriptionsChangedListener(mOnSubscriptionsChangeListener);
+
+        final Context context = getContext();
+        IntentFilter intentFilter = new IntentFilter(
+                TelephonyIntents.ACTION_RADIO_TECHNOLOGY_CHANGED);
+        context.registerReceiver(mPhoneChangeReceiver, intentFilter);
+        context.getContentResolver().registerContentObserver(ENFORCE_MANAGED_URI, false,
+                mDpcEnforcedContentObserver);
+
+        Log.i(LOG_TAG, "onResume:-");
+
+    }
+
+    @Override
+    protected int getPreferenceScreenResId() {
+        return R.xml.network_setting_fragment;
+    }
+
+    @Override
+    protected String getLogTag() {
+        return null;
+    }
+
+    private boolean hasActiveSubscriptions() {
+        return mSubId != SubscriptionManager.INVALID_SUBSCRIPTION_ID;
+    }
+
+    private void updateBodyBasicFields(FragmentActivity activity, PreferenceScreen prefSet,
+            int phoneSubId, boolean hasActiveSubscriptions) {
+        Context context = getContext();
+
+        ActionBar actionBar = activity.getActionBar();
+        if (actionBar != null) {
+            // android.R.id.home will be triggered in onOptionsItemSelected()
+            actionBar.setDisplayHomeAsUpEnabled(true);
+        }
+
+        prefSet.addPreference(mMobileDataPref);
+        prefSet.addPreference(mButtonDataRoam);
+        prefSet.addPreference(mDataUsagePref);
+
+        mMobileDataPref.setEnabled(hasActiveSubscriptions);
+        mButtonDataRoam.setEnabled(hasActiveSubscriptions);
+        mDataUsagePref.setEnabled(hasActiveSubscriptions);
+
+        if (hasActiveSubscriptions) {
+            // Customized preferences needs to be initialized with subId.
+            mMobileDataPref.initialize(phoneSubId);
+            mDataUsagePref.initialize(phoneSubId);
+
+            // Initialize states of mButtonDataRoam.
+            mButtonDataRoam.setChecked(mTelephonyManager.isDataRoamingEnabled());
+            if (mButtonDataRoam.isEnabled()) {
+                if (RestrictedLockUtilsInternal.hasBaseUserRestriction(context,
+                        UserManager.DISALLOW_DATA_ROAMING, UserHandle.myUserId())) {
+                    mButtonDataRoam.setEnabled(false);
+                } else {
+                    mButtonDataRoam.checkRestrictionAndSetDisabled(
+                            UserManager.DISALLOW_DATA_ROAMING);
+                }
+            }
+        }
+    }
+
+    private void updateBody() {
+        final FragmentActivity activity = getActivity();
+        final PreferenceScreen prefSet = getPreferenceScreen();
+        final boolean hasActiveSubscriptions = hasActiveSubscriptions();
+
+        if (activity == null) {
+            Log.e(LOG_TAG, "updateBody with no valid activity.");
+            return;
+        }
+
+        if (prefSet == null) {
+            Log.e(LOG_TAG, "updateBody with no null prefSet.");
+            return;
+        }
+
+        prefSet.removeAll();
+
+        updateBodyBasicFields(activity, prefSet, mSubId, hasActiveSubscriptions);
+
+        if (hasActiveSubscriptions) {
+            updateBodyAdvancedFields(activity, prefSet, mSubId, hasActiveSubscriptions);
+        } else {
+            // Shows the "Carrier" preference that allows user to add a e-sim profile.
+            if (MobileNetworkUtils.showEuiccSettings(getContext())) {
+                mEuiccSettingsPref.setSummary(null /* summary */);
+                prefSet.addPreference(mEuiccSettingsPref);
+            }
+        }
+    }
+
+    private void updateBodyAdvancedFields(FragmentActivity activity, PreferenceScreen prefSet,
+            int phoneSubId, boolean hasActiveSubscriptions) {
+        boolean isLteOnCdma = mTelephonyManager.getLteOnCdmaMode()
+                == PhoneConstants.LTE_ON_CDMA_TRUE;
+
+        if (DBG) {
+            log("updateBody: isLteOnCdma=" + isLteOnCdma + " phoneSubId=" + phoneSubId);
+        }
+
+        prefSet.addPreference(mButtonPreferredNetworkMode);
+        prefSet.addPreference(mButtonEnabledNetworks);
+        prefSet.addPreference(mButton4glte);
+
+        if (MobileNetworkUtils.showEuiccSettings(getContext())) {
+            prefSet.addPreference(mEuiccSettingsPref);
+            String spn = mTelephonyManager.getSimOperatorName();
+            if (TextUtils.isEmpty(spn)) {
+                mEuiccSettingsPref.setSummary(null);
+            } else {
+                mEuiccSettingsPref.setSummary(spn);
+            }
+        }
+
+        int settingsNetworkMode = android.provider.Settings.Global.getInt(
+                getContext().getContentResolver(),
+                android.provider.Settings.Global.PREFERRED_NETWORK_MODE + phoneSubId,
+                preferredNetworkMode);
+
+        PersistableBundle carrierConfig = mCarrierConfigManager.getConfigForSubId(mSubId);
+        mIsGlobalCdma = isLteOnCdma
+                && carrierConfig.getBoolean(CarrierConfigManager.KEY_SHOW_CDMA_CHOICES_BOOL);
+        if (carrierConfig.getBoolean(
+                CarrierConfigManager.KEY_HIDE_CARRIER_NETWORK_SETTINGS_BOOL)) {
+            prefSet.removePreference(mButtonPreferredNetworkMode);
+            prefSet.removePreference(mButtonEnabledNetworks);
+            prefSet.removePreference(mLteDataServicePref);
+        } else if (carrierConfig.getBoolean(CarrierConfigManager
+                .KEY_HIDE_PREFERRED_NETWORK_TYPE_BOOL)
+                && !mTelephonyManager.getServiceState().getRoaming()
+                && mTelephonyManager.getServiceState().getDataRegState()
+                == ServiceState.STATE_IN_SERVICE) {
+            prefSet.removePreference(mButtonPreferredNetworkMode);
+            prefSet.removePreference(mButtonEnabledNetworks);
+
+            final int phoneType = mTelephonyManager.getPhoneType();
+            if (phoneType == PhoneConstants.PHONE_TYPE_CDMA) {
+                updateCdmaOptions(this, prefSet, mSubId);
+            } else if (phoneType == PhoneConstants.PHONE_TYPE_GSM) {
+                updateGsmUmtsOptions(this, prefSet, phoneSubId);
+            } else {
+                throw new IllegalStateException("Unexpected phone type: " + phoneType);
+            }
+            // Since pref is being hidden from user, set network mode to default
+            // in case it is currently something else. That is possible if user
+            // changed the setting while roaming and is now back to home network.
+            settingsNetworkMode = preferredNetworkMode;
+        } else if (carrierConfig.getBoolean(
+                CarrierConfigManager.KEY_WORLD_PHONE_BOOL) == true) {
+            prefSet.removePreference(mButtonEnabledNetworks);
+            // set the listener for the mButtonPreferredNetworkMode list preference so we can issue
+            // change Preferred Network Mode.
+            mButtonPreferredNetworkMode.setOnPreferenceChangeListener(this);
+
+            updateCdmaOptions(this, prefSet, mSubId);
+            updateGsmUmtsOptions(this, prefSet, phoneSubId);
+        } else {
+            prefSet.removePreference(mButtonPreferredNetworkMode);
+            updateEnabledNetworksEntries();
+            mButtonEnabledNetworks.setOnPreferenceChangeListener(this);
+            if (DBG) log("settingsNetworkMode: " + settingsNetworkMode);
+        }
+
+        final boolean missingDataServiceUrl = TextUtils.isEmpty(
+                android.provider.Settings.Global.getString(activity.getContentResolver(),
+                        android.provider.Settings.Global.SETUP_PREPAID_DATA_SERVICE_URL));
+        if (!isLteOnCdma || missingDataServiceUrl) {
+            prefSet.removePreference(mLteDataServicePref);
+        } else {
+            android.util.Log.d(LOG_TAG, "keep ltePref");
+        }
+
+        updateEnhanced4gLteState();
+        updatePreferredNetworkType();
+        updateCallingCategory();
+
+        // Enable link to CMAS app settings depending on the value in config.xml.
+        final boolean isCellBroadcastAppLinkEnabled = activity.getResources().getBoolean(
+                com.android.internal.R.bool.config_cellBroadcastAppLinks);
+        if (!mUm.isAdminUser() || !isCellBroadcastAppLinkEnabled
+                || mUm.hasUserRestriction(UserManager.DISALLOW_CONFIG_CELL_BROADCASTS)) {
+            PreferenceScreen root = getPreferenceScreen();
+            Preference ps = findPreference(BUTTON_CELL_BROADCAST_SETTINGS);
+            if (ps != null) {
+                root.removePreference(ps);
+            }
+        }
+
+        /**
+         * 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));
+        UpdatePreferredNetworkModeSummary(settingsNetworkMode);
+        UpdateEnabledNetworksValueAndSummary(settingsNetworkMode);
+        // Display preferred network type based on what modem returns b/18676277
+        new SetPreferredNetworkAsyncTask(
+                mTelephonyManager,
+                mSubId,
+                settingsNetworkMode,
+                mHandler.obtainMessage(MyHandler.MESSAGE_SET_PREFERRED_NETWORK_TYPE))
+                .executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
+
+        /**
+         * Enable/disable depending upon if there are any active subscriptions.
+         *
+         * I've decided to put this enable/disable code at the bottom as the
+         * code above works even when there are no active subscriptions, thus
+         * putting it afterwards is a smaller change. This can be refined later,
+         * but you do need to remember that this all needs to work when subscriptions
+         * change dynamically such as when hot swapping sims.
+         */
+        boolean useVariant4glteTitle = carrierConfig.getBoolean(
+                CarrierConfigManager.KEY_ENHANCED_4G_LTE_TITLE_VARIANT_BOOL);
+        int enhanced4glteModeTitleId = useVariant4glteTitle ?
+                R.string.enhanced_4g_lte_mode_title_variant :
+                R.string.enhanced_4g_lte_mode_title;
+
+        mOnlyAutoSelectInHomeNW = carrierConfig.getBoolean(
+                CarrierConfigManager.KEY_ONLY_AUTO_SELECT_IN_HOME_NETWORK_BOOL);
+        mButton4glte.setTitle(enhanced4glteModeTitleId);
+        mLteDataServicePref.setEnabled(hasActiveSubscriptions);
+        Preference ps;
+        ps = findPreference(BUTTON_CELL_BROADCAST_SETTINGS);
+        if (ps != null) {
+            ps.setEnabled(hasActiveSubscriptions);
+        }
+        ps = findPreference(CATEGORY_GSM_APN_EXPAND_KEY);
+        if (ps != null) {
+            ps.setEnabled(hasActiveSubscriptions);
+        }
+        ps = findPreference(CATEGORY_CDMA_APN_EXPAND_KEY);
+        if (ps != null) {
+            ps.setEnabled(hasActiveSubscriptions);
+        }
+        ps = findPreference(NetworkOperators.CATEGORY_NETWORK_OPERATORS_KEY);
+        if (ps != null) {
+            ps.setEnabled(hasActiveSubscriptions);
+        }
+        ps = findPreference(BUTTON_CARRIER_SETTINGS_KEY);
+        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);
+        }
+        ps = findPreference(NetworkOperators.BUTTON_AUTO_SELECT_KEY);
+        if (ps != null) {
+            ps.setSummary(null);
+            if (mTelephonyManager.getServiceState().getRoaming()) {
+                ps.setEnabled(true);
+            } else {
+                ps.setEnabled(!mOnlyAutoSelectInHomeNW);
+                if (mOnlyAutoSelectInHomeNW) {
+                    ps.setSummary(getResources().getString(
+                            R.string.manual_mode_disallowed_summary,
+                            mTelephonyManager.getSimOperatorName()));
+                }
+            }
+        }
+    }
+
+    // Requires that mSubId is up to date
+    void updateEnabledNetworksEntries() {
+        final int phoneType = mTelephonyManager.getPhoneType();
+        final PersistableBundle carrierConfig = mCarrierConfigManager.getConfigForSubId(mSubId);
+        if (phoneType == PhoneConstants.PHONE_TYPE_CDMA) {
+            final int lteForced = android.provider.Settings.Global.getInt(
+                    getContext().getContentResolver(),
+                    android.provider.Settings.Global.LTE_SERVICE_FORCED + mSubId,
+                    0);
+            final boolean isLteOnCdma = mTelephonyManager.getLteOnCdmaMode()
+                    == PhoneConstants.LTE_ON_CDMA_TRUE;
+            final int settingsNetworkMode = android.provider.Settings.Global.getInt(
+                    getContext().getContentResolver(),
+                    android.provider.Settings.Global.PREFERRED_NETWORK_MODE + mSubId,
+                    preferredNetworkMode);
+            if (isLteOnCdma) {
+                if (lteForced == 0) {
+                    mButtonEnabledNetworks.setEntries(
+                            R.array.enabled_networks_cdma_choices);
+                    mButtonEnabledNetworks.setEntryValues(
+                            R.array.enabled_networks_cdma_values);
+                } else {
+                    switch (settingsNetworkMode) {
+                        case TelephonyManager.NETWORK_MODE_CDMA_EVDO:
+                        case TelephonyManager.NETWORK_MODE_CDMA_NO_EVDO:
+                        case TelephonyManager.NETWORK_MODE_EVDO_NO_CDMA:
+                            mButtonEnabledNetworks.setEntries(
+                                    R.array.enabled_networks_cdma_no_lte_choices);
+                            mButtonEnabledNetworks.setEntryValues(
+                                    R.array.enabled_networks_cdma_no_lte_values);
+                            break;
+                        case TelephonyManager.NETWORK_MODE_GLOBAL:
+                        case TelephonyManager.NETWORK_MODE_LTE_CDMA_EVDO:
+                        case TelephonyManager.NETWORK_MODE_LTE_CDMA_EVDO_GSM_WCDMA:
+                        case TelephonyManager.NETWORK_MODE_LTE_ONLY:
+                            mButtonEnabledNetworks.setEntries(
+                                    R.array.enabled_networks_cdma_only_lte_choices);
+                            mButtonEnabledNetworks.setEntryValues(
+                                    R.array.enabled_networks_cdma_only_lte_values);
+                            break;
+                        default:
+                            mButtonEnabledNetworks.setEntries(
+                                    R.array.enabled_networks_cdma_choices);
+                            mButtonEnabledNetworks.setEntryValues(
+                                    R.array.enabled_networks_cdma_values);
+                            break;
+                    }
+                }
+            }
+            updateCdmaOptions(this, getPreferenceScreen(), mSubId);
+
+        } else if (phoneType == PhoneConstants.PHONE_TYPE_GSM) {
+            if (isSupportTdscdma()) {
+                mButtonEnabledNetworks.setEntries(
+                        R.array.enabled_networks_tdscdma_choices);
+                mButtonEnabledNetworks.setEntryValues(
+                        R.array.enabled_networks_tdscdma_values);
+            } else if (!carrierConfig.getBoolean(CarrierConfigManager.KEY_PREFER_2G_BOOL)
+                    && !getResources().getBoolean(R.bool.config_enabled_lte)) {
+                mButtonEnabledNetworks.setEntries(
+                        R.array.enabled_networks_except_gsm_lte_choices);
+                mButtonEnabledNetworks.setEntryValues(
+                        R.array.enabled_networks_except_gsm_lte_values);
+            } else if (!carrierConfig.getBoolean(CarrierConfigManager.KEY_PREFER_2G_BOOL)) {
+                int select = mShow4GForLTE
+                        ? R.array.enabled_networks_except_gsm_4g_choices
+                        : R.array.enabled_networks_except_gsm_choices;
+                mButtonEnabledNetworks.setEntries(select);
+                mButtonEnabledNetworks.setEntryValues(
+                        R.array.enabled_networks_except_gsm_values);
+            } else if (!getResources().getBoolean(R.bool.config_enabled_lte)) {
+                mButtonEnabledNetworks.setEntries(
+                        R.array.enabled_networks_except_lte_choices);
+                mButtonEnabledNetworks.setEntryValues(
+                        R.array.enabled_networks_except_lte_values);
+            } else if (mIsGlobalCdma) {
+                mButtonEnabledNetworks.setEntries(
+                        R.array.enabled_networks_cdma_choices);
+                mButtonEnabledNetworks.setEntryValues(
+                        R.array.enabled_networks_cdma_values);
+            } else {
+                int select = mShow4GForLTE ? R.array.enabled_networks_4g_choices
+                        : R.array.enabled_networks_choices;
+                mButtonEnabledNetworks.setEntries(select);
+                mButtonEnabledNetworks.setEntryValues(
+                        R.array.enabled_networks_values);
+            }
+            updateGsmUmtsOptions(this, getPreferenceScreen(), mSubId);
+        } else {
+            throw new IllegalStateException("Unexpected phone type: " + phoneType);
+        }
+        if (isWorldMode()) {
+            mButtonEnabledNetworks.setEntries(
+                    R.array.preferred_network_mode_choices_world_mode);
+            mButtonEnabledNetworks.setEntryValues(
+                    R.array.preferred_network_mode_values_world_mode);
+        }
+    }
+
+    @Override
+    public void onPause() {
+        super.onPause();
+        if (DBG) log("onPause:+");
+
+        mTelephonyManager.listen(mPhoneStateListener, PhoneStateListener.LISTEN_NONE);
+
+        mSubscriptionManager
+                .removeOnSubscriptionsChangedListener(mOnSubscriptionsChangeListener);
+
+        final Context context = getActivity();
+        context.unregisterReceiver(mPhoneChangeReceiver);
+        context.getContentResolver().unregisterContentObserver(mDpcEnforcedContentObserver);
+        if (DBG) log("onPause:-");
+    }
+
+    /**
+     * Implemented to support onPreferenceChangeListener to look for preference
+     * changes specifically on CLIR.
+     *
+     * @param preference is the preference to be changed, should be mButtonCLIR.
+     * @param objValue should be the value of the selection, NOT its localized
+     * display value.
+     */
+    public boolean onPreferenceChange(Preference preference, Object objValue) {
+        sendMetricsEventPreferenceChanged(getPreferenceScreen(), preference, objValue);
+
+        final int phoneSubId = mSubId;
+        if (preference == mButtonPreferredNetworkMode) {
+            //NOTE onPreferenceChange seems to be called even if there is no change
+            //Check if the button value is changed from the System.Setting
+            mButtonPreferredNetworkMode.setValue((String) objValue);
+            int buttonNetworkMode;
+            buttonNetworkMode = Integer.parseInt((String) objValue);
+            int settingsNetworkMode = android.provider.Settings.Global.getInt(
+                    getContext().getContentResolver(),
+                    android.provider.Settings.Global.PREFERRED_NETWORK_MODE + phoneSubId,
+                    preferredNetworkMode);
+            if (buttonNetworkMode != settingsNetworkMode) {
+                int modemNetworkMode;
+                // if new mode is invalid ignore it
+                switch (buttonNetworkMode) {
+                    case TelephonyManager.NETWORK_MODE_WCDMA_PREF:
+                    case TelephonyManager.NETWORK_MODE_GSM_ONLY:
+                    case TelephonyManager.NETWORK_MODE_WCDMA_ONLY:
+                    case TelephonyManager.NETWORK_MODE_GSM_UMTS:
+                    case TelephonyManager.NETWORK_MODE_CDMA_EVDO:
+                    case TelephonyManager.NETWORK_MODE_CDMA_NO_EVDO:
+                    case TelephonyManager.NETWORK_MODE_EVDO_NO_CDMA:
+                    case TelephonyManager.NETWORK_MODE_GLOBAL:
+                    case TelephonyManager.NETWORK_MODE_LTE_CDMA_EVDO:
+                    case TelephonyManager.NETWORK_MODE_LTE_GSM_WCDMA:
+                    case TelephonyManager.NETWORK_MODE_LTE_CDMA_EVDO_GSM_WCDMA:
+                    case TelephonyManager.NETWORK_MODE_LTE_ONLY:
+                    case TelephonyManager.NETWORK_MODE_LTE_WCDMA:
+                    case TelephonyManager.NETWORK_MODE_TDSCDMA_ONLY:
+                    case TelephonyManager.NETWORK_MODE_TDSCDMA_WCDMA:
+                    case TelephonyManager.NETWORK_MODE_LTE_TDSCDMA:
+                    case TelephonyManager.NETWORK_MODE_TDSCDMA_GSM:
+                    case TelephonyManager.NETWORK_MODE_LTE_TDSCDMA_GSM:
+                    case TelephonyManager.NETWORK_MODE_TDSCDMA_GSM_WCDMA:
+                    case TelephonyManager.NETWORK_MODE_LTE_TDSCDMA_WCDMA:
+                    case TelephonyManager.NETWORK_MODE_LTE_TDSCDMA_GSM_WCDMA:
+                    case TelephonyManager.NETWORK_MODE_TDSCDMA_CDMA_EVDO_GSM_WCDMA:
+                    case TelephonyManager.NETWORK_MODE_LTE_TDSCDMA_CDMA_EVDO_GSM_WCDMA:
+                        // This is one of the modes we recognize
+                        modemNetworkMode = buttonNetworkMode;
+                        break;
+                    default:
+                        loge("Invalid Network Mode (" +buttonNetworkMode+ ") chosen. Ignore.");
+                        return true;
+                }
+
+                android.provider.Settings.Global.putInt(
+                        getContext().getContentResolver(),
+                        android.provider.Settings.Global.PREFERRED_NETWORK_MODE + phoneSubId,
+                        buttonNetworkMode );
+                //Set the modem network mode
+                new SetPreferredNetworkAsyncTask(
+                        mTelephonyManager,
+                        mSubId,
+                        modemNetworkMode,
+                        mHandler.obtainMessage(MyHandler.MESSAGE_SET_PREFERRED_NETWORK_TYPE))
+                        .executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
+            }
+        } else if (preference == mButtonEnabledNetworks) {
+            mButtonEnabledNetworks.setValue((String) objValue);
+            int buttonNetworkMode;
+            buttonNetworkMode = Integer.parseInt((String) objValue);
+            if (DBG) log("buttonNetworkMode: " + buttonNetworkMode);
+            int settingsNetworkMode = android.provider.Settings.Global.getInt(
+                    getContext().getContentResolver(),
+                    android.provider.Settings.Global.PREFERRED_NETWORK_MODE + phoneSubId,
+                    preferredNetworkMode);
+            if (buttonNetworkMode != settingsNetworkMode) {
+                int modemNetworkMode;
+                // if new mode is invalid ignore it
+                switch (buttonNetworkMode) {
+                    case TelephonyManager.NETWORK_MODE_WCDMA_PREF:
+                    case TelephonyManager.NETWORK_MODE_GSM_ONLY:
+                    case TelephonyManager.NETWORK_MODE_LTE_GSM_WCDMA:
+                    case TelephonyManager.NETWORK_MODE_LTE_CDMA_EVDO_GSM_WCDMA:
+                    case TelephonyManager.NETWORK_MODE_CDMA_EVDO:
+                    case TelephonyManager.NETWORK_MODE_CDMA_NO_EVDO:
+                    case TelephonyManager.NETWORK_MODE_LTE_CDMA_EVDO:
+                    case TelephonyManager.NETWORK_MODE_TDSCDMA_ONLY:
+                    case TelephonyManager.NETWORK_MODE_TDSCDMA_WCDMA:
+                    case TelephonyManager.NETWORK_MODE_LTE_TDSCDMA:
+                    case TelephonyManager.NETWORK_MODE_TDSCDMA_GSM:
+                    case TelephonyManager.NETWORK_MODE_LTE_TDSCDMA_GSM:
+                    case TelephonyManager.NETWORK_MODE_TDSCDMA_GSM_WCDMA:
+                    case TelephonyManager.NETWORK_MODE_LTE_TDSCDMA_WCDMA:
+                    case TelephonyManager.NETWORK_MODE_LTE_TDSCDMA_GSM_WCDMA:
+                    case TelephonyManager.NETWORK_MODE_TDSCDMA_CDMA_EVDO_GSM_WCDMA:
+                    case TelephonyManager.NETWORK_MODE_LTE_TDSCDMA_CDMA_EVDO_GSM_WCDMA:
+                        // This is one of the modes we recognize
+                        modemNetworkMode = buttonNetworkMode;
+                        break;
+                    default:
+                        loge("Invalid Network Mode (" +buttonNetworkMode+ ") chosen. Ignore.");
+                        return true;
+                }
+
+                UpdateEnabledNetworksValueAndSummary(buttonNetworkMode);
+
+                android.provider.Settings.Global.putInt(
+                        getContext().getContentResolver(),
+                        android.provider.Settings.Global.PREFERRED_NETWORK_MODE + phoneSubId,
+                        buttonNetworkMode );
+                //Set the modem network mode
+                new SetPreferredNetworkAsyncTask(
+                        mTelephonyManager,
+                        mSubId,
+                        modemNetworkMode,
+                        mHandler.obtainMessage(MyHandler.MESSAGE_SET_PREFERRED_NETWORK_TYPE))
+                        .executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
+            }
+        } else if (preference == mButton4glte) {
+            boolean enhanced4gMode = !mButton4glte.isChecked();
+            mButton4glte.setChecked(enhanced4gMode);
+            mImsMgr.setEnhanced4gLteModeSetting(mButton4glte.isChecked());
+        } else if (preference == mButtonDataRoam) {
+            if (DBG) log("onPreferenceTreeClick: preference == mButtonDataRoam.");
+
+            //normally called on the toggle click
+            if (!mButtonDataRoam.isChecked()) {
+                PersistableBundle carrierConfig = mCarrierConfigManager.getConfigForSubId(
+                        mSubId);
+                if (carrierConfig != null && carrierConfig.getBoolean(
+                        CarrierConfigManager.KEY_DISABLE_CHARGE_INDICATION_BOOL)) {
+                    mTelephonyManager.setDataRoamingEnabled(true);
+                    MetricsLogger.action(getContext(),
+                            getMetricsEventCategory(getPreferenceScreen(), mButtonDataRoam),
+                            true);
+                } else {
+                    // MetricsEvent with no value update.
+                    MetricsLogger.action(getContext(),
+                            getMetricsEventCategory(getPreferenceScreen(), mButtonDataRoam));
+                    // First confirm with a warning dialog about charges
+                    mOkClicked = false;
+                    RoamingDialogFragment
+                            fragment = new RoamingDialogFragment();
+                    Bundle b = new Bundle();
+                    b.putInt(RoamingDialogFragment.SUB_ID_KEY, mSubId);
+                    fragment.setArguments(b);
+                    fragment.show(getFragmentManager(), ROAMING_TAG);
+                    // Don't update the toggle unless the confirm button is actually pressed.
+                    return false;
+                }
+            } else {
+                mTelephonyManager.setDataRoamingEnabled(false);
+                MetricsLogger.action(getContext(),
+                        getMetricsEventCategory(getPreferenceScreen(), mButtonDataRoam),
+                        false);
+                return true;
+            }
+        } else if (preference == mVideoCallingPref) {
+            // If mButton4glte is not checked, mVideoCallingPref should be disabled.
+            // So it only makes sense to call phoneMgr.enableVideoCalling if it's checked.
+            if (mButton4glte.isChecked()) {
+                mImsMgr.setVtSetting((boolean) objValue);
+                return true;
+            } else {
+                loge("mVideoCallingPref should be disabled if mButton4glte is not checked.");
+                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();
+        // always let the preference setting proceed.
+        return true;
+    }
+
+    private boolean is4gLtePrefEnabled(PersistableBundle carrierConfig) {
+        return (mTelephonyManager.getCallState(mSubId)
+                == TelephonyManager.CALL_STATE_IDLE)
+                && mImsMgr != null
+                && mImsMgr.isNonTtyOrTtyOnVolteEnabled()
+                && carrierConfig.getBoolean(
+                CarrierConfigManager.KEY_EDITABLE_ENHANCED_4G_LTE_BOOL);
+    }
+
+    private class MyHandler extends Handler {
+
+        static final int MESSAGE_SET_PREFERRED_NETWORK_TYPE = 0;
+
+        @Override
+        public void handleMessage(Message msg) {
+            switch (msg.what) {
+                case MESSAGE_SET_PREFERRED_NETWORK_TYPE:
+                    handleSetPreferredNetworkTypeResponse(msg);
+                    break;
+            }
+        }
+
+        private void handleSetPreferredNetworkTypeResponse(Message msg) {
+            final FragmentActivity activity = getActivity();
+            if (activity == null || activity.isDestroyed()) {
+                // Access preferences of activity only if it is not destroyed
+                // or if fragment is not attached to an activity.
+                return;
+            }
+
+            boolean success = (boolean) msg.obj;
+
+            if (success) {
+                int networkMode;
+                if (getPreferenceScreen().findPreference(
+                        BUTTON_PREFERED_NETWORK_MODE) != null)  {
+                    networkMode =  Integer.parseInt(mButtonPreferredNetworkMode.getValue());
+                    android.provider.Settings.Global.putInt(
+                            getContext().getContentResolver(),
+                            android.provider.Settings.Global.PREFERRED_NETWORK_MODE
+                                    + mSubId,
+                            networkMode );
+                }
+                if (getPreferenceScreen().findPreference(BUTTON_ENABLED_NETWORKS_KEY) != null) {
+                    networkMode = Integer.parseInt(mButtonEnabledNetworks.getValue());
+                    android.provider.Settings.Global.putInt(
+                            getContext().getContentResolver(),
+                            android.provider.Settings.Global.PREFERRED_NETWORK_MODE
+                                    + mSubId,
+                            networkMode );
+                }
+            } else {
+                Log.i(LOG_TAG, "handleSetPreferredNetworkTypeResponse:" +
+                        "exception in setting network mode.");
+                updatePreferredNetworkUIFromDb();
+            }
+        }
+    }
+
+    private void updatePreferredNetworkUIFromDb() {
+        int settingsNetworkMode = android.provider.Settings.Global.getInt(
+                getContext().getContentResolver(),
+                android.provider.Settings.Global.PREFERRED_NETWORK_MODE + mSubId,
+                preferredNetworkMode);
+
+        if (DBG) {
+            log("updatePreferredNetworkUIFromDb: settingsNetworkMode = " +
+                    settingsNetworkMode);
+        }
+
+        UpdatePreferredNetworkModeSummary(settingsNetworkMode);
+        UpdateEnabledNetworksValueAndSummary(settingsNetworkMode);
+        // changes the mButtonPreferredNetworkMode accordingly to settingsNetworkMode
+        mButtonPreferredNetworkMode.setValue(Integer.toString(settingsNetworkMode));
+    }
+
+    private void UpdatePreferredNetworkModeSummary(int NetworkMode) {
+        switch(NetworkMode) {
+            case TelephonyManager.NETWORK_MODE_TDSCDMA_GSM_WCDMA:
+                mButtonPreferredNetworkMode.setSummary(
+                        R.string.preferred_network_mode_tdscdma_gsm_wcdma_summary);
+                break;
+            case TelephonyManager.NETWORK_MODE_TDSCDMA_GSM:
+                mButtonPreferredNetworkMode.setSummary(
+                        R.string.preferred_network_mode_tdscdma_gsm_summary);
+                break;
+            case TelephonyManager.NETWORK_MODE_WCDMA_PREF:
+                mButtonPreferredNetworkMode.setSummary(
+                        R.string.preferred_network_mode_wcdma_perf_summary);
+                break;
+            case TelephonyManager.NETWORK_MODE_GSM_ONLY:
+                mButtonPreferredNetworkMode.setSummary(
+                        R.string.preferred_network_mode_gsm_only_summary);
+                break;
+            case TelephonyManager.NETWORK_MODE_TDSCDMA_WCDMA:
+                mButtonPreferredNetworkMode.setSummary(
+                        R.string.preferred_network_mode_tdscdma_wcdma_summary);
+                break;
+            case TelephonyManager.NETWORK_MODE_WCDMA_ONLY:
+                mButtonPreferredNetworkMode.setSummary(
+                        R.string.preferred_network_mode_wcdma_only_summary);
+                break;
+            case TelephonyManager.NETWORK_MODE_GSM_UMTS:
+                mButtonPreferredNetworkMode.setSummary(
+                        R.string.preferred_network_mode_gsm_wcdma_summary);
+                break;
+            case TelephonyManager.NETWORK_MODE_CDMA_EVDO:
+                switch (mTelephonyManager.getLteOnCdmaMode()) {
+                    case PhoneConstants.LTE_ON_CDMA_TRUE:
+                        mButtonPreferredNetworkMode.setSummary(
+                                R.string.preferred_network_mode_cdma_summary);
+                        break;
+                    case PhoneConstants.LTE_ON_CDMA_FALSE:
+                    default:
+                        mButtonPreferredNetworkMode.setSummary(
+                                R.string.preferred_network_mode_cdma_evdo_summary);
+                        break;
+                }
+                break;
+            case TelephonyManager.NETWORK_MODE_CDMA_NO_EVDO:
+                mButtonPreferredNetworkMode.setSummary(
+                        R.string.preferred_network_mode_cdma_only_summary);
+                break;
+            case TelephonyManager.NETWORK_MODE_EVDO_NO_CDMA:
+                mButtonPreferredNetworkMode.setSummary(
+                        R.string.preferred_network_mode_evdo_only_summary);
+                break;
+            case TelephonyManager.NETWORK_MODE_LTE_TDSCDMA:
+                mButtonPreferredNetworkMode.setSummary(
+                        R.string.preferred_network_mode_lte_tdscdma_summary);
+                break;
+            case TelephonyManager.NETWORK_MODE_LTE_ONLY:
+                mButtonPreferredNetworkMode.setSummary(
+                        R.string.preferred_network_mode_lte_summary);
+                break;
+            case TelephonyManager.NETWORK_MODE_LTE_TDSCDMA_GSM:
+                mButtonPreferredNetworkMode.setSummary(
+                        R.string.preferred_network_mode_lte_tdscdma_gsm_summary);
+                break;
+            case TelephonyManager.NETWORK_MODE_LTE_TDSCDMA_GSM_WCDMA:
+                mButtonPreferredNetworkMode.setSummary(
+                        R.string.preferred_network_mode_lte_tdscdma_gsm_wcdma_summary);
+                break;
+            case TelephonyManager.NETWORK_MODE_LTE_GSM_WCDMA:
+                mButtonPreferredNetworkMode.setSummary(
+                        R.string.preferred_network_mode_lte_gsm_wcdma_summary);
+                break;
+            case TelephonyManager.NETWORK_MODE_LTE_CDMA_EVDO:
+                mButtonPreferredNetworkMode.setSummary(
+                        R.string.preferred_network_mode_lte_cdma_evdo_summary);
+                break;
+            case TelephonyManager.NETWORK_MODE_TDSCDMA_ONLY:
+                mButtonPreferredNetworkMode.setSummary(
+                        R.string.preferred_network_mode_tdscdma_summary);
+                break;
+            case TelephonyManager.NETWORK_MODE_LTE_TDSCDMA_CDMA_EVDO_GSM_WCDMA:
+                mButtonPreferredNetworkMode.setSummary(
+                        R.string.preferred_network_mode_lte_tdscdma_cdma_evdo_gsm_wcdma_summary);
+                break;
+            case TelephonyManager.NETWORK_MODE_LTE_CDMA_EVDO_GSM_WCDMA:
+                if (mTelephonyManager.getPhoneType() == PhoneConstants.PHONE_TYPE_CDMA
+                        || mIsGlobalCdma
+                        || isWorldMode()) {
+                    mButtonPreferredNetworkMode.setSummary(
+                            R.string.preferred_network_mode_global_summary);
+                } else {
+                    mButtonPreferredNetworkMode.setSummary(
+                            R.string.preferred_network_mode_lte_summary);
+                }
+                break;
+            case TelephonyManager.NETWORK_MODE_TDSCDMA_CDMA_EVDO_GSM_WCDMA:
+                mButtonPreferredNetworkMode.setSummary(
+                        R.string.preferred_network_mode_tdscdma_cdma_evdo_gsm_wcdma_summary);
+                break;
+            case TelephonyManager.NETWORK_MODE_GLOBAL:
+                mButtonPreferredNetworkMode.setSummary(
+                        R.string.preferred_network_mode_cdma_evdo_gsm_wcdma_summary);
+                break;
+            case TelephonyManager.NETWORK_MODE_LTE_TDSCDMA_WCDMA:
+                mButtonPreferredNetworkMode.setSummary(
+                        R.string.preferred_network_mode_lte_tdscdma_wcdma_summary);
+                break;
+            case TelephonyManager.NETWORK_MODE_LTE_WCDMA:
+                mButtonPreferredNetworkMode.setSummary(
+                        R.string.preferred_network_mode_lte_wcdma_summary);
+                break;
+            default:
+                mButtonPreferredNetworkMode.setSummary(
+                        R.string.preferred_network_mode_global_summary);
+        }
+    }
+
+    private void UpdateEnabledNetworksValueAndSummary(int NetworkMode) {
+        switch (NetworkMode) {
+            case TelephonyManager.NETWORK_MODE_TDSCDMA_WCDMA:
+            case TelephonyManager.NETWORK_MODE_TDSCDMA_GSM_WCDMA:
+            case TelephonyManager.NETWORK_MODE_TDSCDMA_GSM:
+                mButtonEnabledNetworks.setValue(
+                        Integer.toString(TelephonyManager.NETWORK_MODE_TDSCDMA_GSM_WCDMA));
+                mButtonEnabledNetworks.setSummary(R.string.network_3G);
+                break;
+            case TelephonyManager.NETWORK_MODE_WCDMA_ONLY:
+            case TelephonyManager.NETWORK_MODE_GSM_UMTS:
+            case TelephonyManager.NETWORK_MODE_WCDMA_PREF:
+                if (!mIsGlobalCdma) {
+                    mButtonEnabledNetworks.setValue(
+                            Integer.toString(TelephonyManager.NETWORK_MODE_WCDMA_PREF));
+                    mButtonEnabledNetworks.setSummary(R.string.network_3G);
+                } else {
+                    mButtonEnabledNetworks.setValue(
+                            Integer.toString(TelephonyManager
+                                    .NETWORK_MODE_LTE_CDMA_EVDO_GSM_WCDMA));
+                    mButtonEnabledNetworks.setSummary(R.string.network_global);
+                }
+                break;
+            case TelephonyManager.NETWORK_MODE_GSM_ONLY:
+                if (!mIsGlobalCdma) {
+                    mButtonEnabledNetworks.setValue(
+                            Integer.toString(TelephonyManager.NETWORK_MODE_GSM_ONLY));
+                    mButtonEnabledNetworks.setSummary(R.string.network_2G);
+                } else {
+                    mButtonEnabledNetworks.setValue(
+                            Integer.toString(TelephonyManager
+                                    .NETWORK_MODE_LTE_CDMA_EVDO_GSM_WCDMA));
+                    mButtonEnabledNetworks.setSummary(R.string.network_global);
+                }
+                break;
+            case TelephonyManager.NETWORK_MODE_LTE_GSM_WCDMA:
+                if (isWorldMode()) {
+                    mButtonEnabledNetworks.setSummary(
+                            R.string.preferred_network_mode_lte_gsm_umts_summary);
+                    controlCdmaOptions(false);
+                    controlGsmOptions(true);
+                    break;
+                }
+            case TelephonyManager.NETWORK_MODE_LTE_ONLY:
+            case TelephonyManager.NETWORK_MODE_LTE_WCDMA:
+                if (!mIsGlobalCdma) {
+                    mButtonEnabledNetworks.setValue(
+                            Integer.toString(TelephonyManager.NETWORK_MODE_LTE_GSM_WCDMA));
+                    mButtonEnabledNetworks.setSummary((mShow4GForLTE == true)
+                            ? R.string.network_4G : R.string.network_lte);
+                } else {
+                    mButtonEnabledNetworks.setValue(
+                            Integer.toString(TelephonyManager
+                                    .NETWORK_MODE_LTE_CDMA_EVDO_GSM_WCDMA));
+                    mButtonEnabledNetworks.setSummary(R.string.network_global);
+                }
+                break;
+            case TelephonyManager.NETWORK_MODE_LTE_CDMA_EVDO:
+                if (isWorldMode()) {
+                    mButtonEnabledNetworks.setSummary(
+                            R.string.preferred_network_mode_lte_cdma_summary);
+                    controlCdmaOptions(true);
+                    controlGsmOptions(false);
+                } else {
+                    mButtonEnabledNetworks.setValue(
+                            Integer.toString(TelephonyManager.NETWORK_MODE_LTE_CDMA_EVDO));
+                    mButtonEnabledNetworks.setSummary(R.string.network_lte);
+                }
+                break;
+            case TelephonyManager.NETWORK_MODE_TDSCDMA_CDMA_EVDO_GSM_WCDMA:
+                mButtonEnabledNetworks.setValue(
+                        Integer.toString(TelephonyManager
+                                .NETWORK_MODE_TDSCDMA_CDMA_EVDO_GSM_WCDMA));
+                mButtonEnabledNetworks.setSummary(R.string.network_3G);
+                break;
+            case TelephonyManager.NETWORK_MODE_CDMA_EVDO:
+            case TelephonyManager.NETWORK_MODE_EVDO_NO_CDMA:
+            case TelephonyManager.NETWORK_MODE_GLOBAL:
+                mButtonEnabledNetworks.setValue(
+                        Integer.toString(TelephonyManager.NETWORK_MODE_CDMA_EVDO));
+                mButtonEnabledNetworks.setSummary(R.string.network_3G);
+                break;
+            case TelephonyManager.NETWORK_MODE_CDMA_NO_EVDO:
+                mButtonEnabledNetworks.setValue(
+                        Integer.toString(TelephonyManager.NETWORK_MODE_CDMA_NO_EVDO));
+                mButtonEnabledNetworks.setSummary(R.string.network_1x);
+                break;
+            case TelephonyManager.NETWORK_MODE_TDSCDMA_ONLY:
+                mButtonEnabledNetworks.setValue(
+                        Integer.toString(TelephonyManager.NETWORK_MODE_TDSCDMA_ONLY));
+                mButtonEnabledNetworks.setSummary(R.string.network_3G);
+                break;
+            case TelephonyManager.NETWORK_MODE_LTE_TDSCDMA_GSM:
+            case TelephonyManager.NETWORK_MODE_LTE_TDSCDMA_GSM_WCDMA:
+            case TelephonyManager.NETWORK_MODE_LTE_TDSCDMA:
+            case TelephonyManager.NETWORK_MODE_LTE_TDSCDMA_WCDMA:
+            case TelephonyManager.NETWORK_MODE_LTE_TDSCDMA_CDMA_EVDO_GSM_WCDMA:
+            case TelephonyManager.NETWORK_MODE_LTE_CDMA_EVDO_GSM_WCDMA:
+                if (isSupportTdscdma()) {
+                    mButtonEnabledNetworks.setValue(
+                            Integer.toString(TelephonyManager
+                                    .NETWORK_MODE_LTE_TDSCDMA_CDMA_EVDO_GSM_WCDMA));
+                    mButtonEnabledNetworks.setSummary(R.string.network_lte);
+                } else {
+                    if (isWorldMode()) {
+                        controlCdmaOptions(true);
+                        controlGsmOptions(false);
+                    }
+                    mButtonEnabledNetworks.setValue(
+                            Integer.toString(TelephonyManager
+                                    .NETWORK_MODE_LTE_CDMA_EVDO_GSM_WCDMA));
+                    if (mTelephonyManager.getPhoneType() == PhoneConstants.PHONE_TYPE_CDMA
+                            || mIsGlobalCdma
+                            || isWorldMode()) {
+                        mButtonEnabledNetworks.setSummary(R.string.network_global);
+                    } else {
+                        mButtonEnabledNetworks.setSummary((mShow4GForLTE == true)
+                                ? R.string.network_4G : R.string.network_lte);
+                    }
+                }
+                break;
+            default:
+                String errMsg = "Invalid Network Mode (" + NetworkMode + "). Ignore.";
+                loge(errMsg);
+                mButtonEnabledNetworks.setSummary(errMsg);
+        }
+    }
+
+    @Override
+    public void onActivityResult(int requestCode, int resultCode, Intent data) {
+        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);
+                } else {
+                    // do nothing
+                }
+                break;
+
+            default:
+                break;
+        }
+    }
+
+    private void updateWiFiCallState() {
+        if (mWiFiCallingPref == null || mCallingCategory == null) {
+            return;
+        }
+
+        // Removes the preference if the wifi calling is disabled.
+        if (!MobileNetworkUtils.isWifiCallingEnabled(getContext(),
+                SubscriptionManager.getPhoneId(mSubId))) {
+            mCallingCategory.removePreference(mWiFiCallingPref);
+            return;
+        }
+
+        final PhoneAccountHandle simCallManager =
+                TelecomManager.from(getContext()).getSimCallManager();
+
+        if (simCallManager != null) {
+            Intent intent = buildPhoneAccountConfigureIntent(getContext(), simCallManager);
+            PackageManager pm = getContext().getPackageManager();
+            List<ResolveInfo> resolutions = pm.queryIntentActivities(intent, 0);
+            mWiFiCallingPref.setTitle(resolutions.get(0).loadLabel(pm));
+            mWiFiCallingPref.setSummary(null);
+            mWiFiCallingPref.setIntent(intent);
+        } else {
+            int resId = com.android.internal.R.string.wifi_calling_off_summary;
+            if (mImsMgr.isWfcEnabledByUser()) {
+                boolean isRoaming = mTelephonyManager.isNetworkRoaming();
+                int wfcMode = mImsMgr.getWfcMode(isRoaming);
+
+                switch (wfcMode) {
+                    case ImsConfig.WfcModeFeatureValueConstants.WIFI_ONLY:
+                        resId = com.android.internal.R.string.wfc_mode_wifi_only_summary;
+                        break;
+                    case ImsConfig.WfcModeFeatureValueConstants.CELLULAR_PREFERRED:
+                        resId = com.android.internal.R.string
+                                .wfc_mode_cellular_preferred_summary;
+                        break;
+                    case ImsConfig.WfcModeFeatureValueConstants.WIFI_PREFERRED:
+                        resId = com.android.internal.R.string.wfc_mode_wifi_preferred_summary;
+                        break;
+                    default:
+                        if (DBG) log("Unexpected WFC mode value: " + wfcMode);
+                }
+            }
+            mWiFiCallingPref.setSummary(resId);
+        }
+
+        mCallingCategory.addPreference(mWiFiCallingPref);
+        mWiFiCallingPref.setEnabled(mTelephonyManager.getCallState(mSubId)
+                == TelephonyManager.CALL_STATE_IDLE && hasActiveSubscriptions());
+    }
+
+    private void updateEnhanced4gLteState() {
+        if (mButton4glte == null) {
+            return;
+        }
+
+        PersistableBundle carrierConfig = mCarrierConfigManager.getConfigForSubId(mSubId);
+
+        if ((mImsMgr == null
+                || !mImsMgr.isVolteEnabledByPlatform()
+                || !mImsMgr.isVolteProvisionedOnDevice()
+                || !MobileNetworkUtils.isImsServiceStateReady(mImsMgr)
+                || carrierConfig.getBoolean(
+                CarrierConfigManager.KEY_HIDE_ENHANCED_4G_LTE_BOOL))) {
+            getPreferenceScreen().removePreference(mButton4glte);
+        } else {
+            mButton4glte.setEnabled(is4gLtePrefEnabled(carrierConfig)
+                    && hasActiveSubscriptions());
+            boolean enh4glteMode = mImsMgr.isEnhanced4gLteModeSettingEnabledByUser()
+                    && mImsMgr.isNonTtyOrTtyOnVolteEnabled();
+            mButton4glte.setChecked(enh4glteMode);
+        }
+    }
+
+    private void updateVideoCallState() {
+        if (mVideoCallingPref == null || mCallingCategory == null) {
+            return;
+        }
+
+        PersistableBundle carrierConfig = mCarrierConfigManager.getConfigForSubId(mSubId);
+
+        if (mImsMgr != null
+                && mImsMgr.isVtEnabledByPlatform()
+                && mImsMgr.isVtProvisionedOnDevice()
+                && MobileNetworkUtils.isImsServiceStateReady(mImsMgr)
+                && (carrierConfig.getBoolean(
+                CarrierConfigManager.KEY_IGNORE_DATA_ENABLED_CHANGED_FOR_VIDEO_CALLS)
+                || mTelephonyManager.isDataEnabled())) {
+            mCallingCategory.addPreference(mVideoCallingPref);
+            if (!mButton4glte.isChecked()) {
+                mVideoCallingPref.setEnabled(false);
+                mVideoCallingPref.setChecked(false);
+            } else {
+                mVideoCallingPref.setEnabled(mTelephonyManager.getCallState(mSubId)
+                        == TelephonyManager.CALL_STATE_IDLE && hasActiveSubscriptions());
+                mVideoCallingPref.setChecked(mImsMgr.isVtEnabledByUser());
+                mVideoCallingPref.setOnPreferenceChangeListener(this);
+            }
+        } else {
+            mCallingCategory.removePreference(mVideoCallingPref);
+        }
+    }
+
+    private void updatePreferredNetworkType() {
+        boolean enabled = mTelephonyManager.getCallState(
+                mSubId) == TelephonyManager.CALL_STATE_IDLE
+                && hasActiveSubscriptions();
+        Log.i(LOG_TAG, "updatePreferredNetworkType: " + enabled);
+        // TODO: Disentangle enabled networks vs preferred network mode, it looks like
+        // both buttons are shown to the user as "Preferred network type" and the options change
+        // based on what looks like World mode.
+        if (mButtonEnabledNetworks != null) {
+            mButtonEnabledNetworks.setEnabled(enabled);
+        }
+        if (mButtonPreferredNetworkMode != null) {
+            mButtonPreferredNetworkMode.setEnabled(enabled);
+        }
+    }
+
+    private void updateCallingCategory() {
+        if (mCallingCategory == null) {
+            return;
+        }
+
+        updateWiFiCallState();
+        updateVideoCallState();
+
+        // If all items in calling category is removed, we remove it from
+        // the screen. Otherwise we'll see title of the category but nothing
+        // is in there.
+        if (mCallingCategory.getPreferenceCount() == 0) {
+            getPreferenceScreen().removePreference(mCallingCategory);
+        } else {
+            getPreferenceScreen().addPreference(mCallingCategory);
+        }
+    }
+
+    private static void log(String msg) {
+        Log.d(LOG_TAG, msg);
+    }
+
+    private static void loge(String msg) {
+        Log.e(LOG_TAG, msg);
+    }
+
+    @Override
+    public boolean onOptionsItemSelected(MenuItem item) {
+        final int itemId = item.getItemId();
+        if (itemId == android.R.id.home) {  // See ActionBar#setDisplayHomeAsUpEnabled()
+            // Commenting out "logical up" capability. This is a workaround for issue 5278083.
+            //
+            // Settings app may not launch this activity via UP_ACTIVITY_CLASS but the other
+            // Activity that looks exactly same as UP_ACTIVITY_CLASS ("SubSettings" Activity).
+            // At that moment, this Activity launches UP_ACTIVITY_CLASS on top of the Activity.
+            // which confuses users.
+            // TODO: introduce better mechanism for "up" capability here.
+            /*Intent intent = new Intent(Intent.ACTION_MAIN);
+            intent.setClassName(UP_ACTIVITY_PACKAGE, UP_ACTIVITY_CLASS);
+            intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
+            startActivity(intent);*/
+            getActivity().finish();
+            return true;
+        }
+        return super.onOptionsItemSelected(item);
+    }
+
+    private boolean isWorldMode() {
+        boolean worldModeOn = false;
+        final String configString = getResources().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])
+                            && mTelephonyManager != null
+                            && configArray[1].equalsIgnoreCase(
+                            mTelephonyManager.getGroupIdLevel1())))) {
+                worldModeOn = true;
+            }
+        }
+
+        Log.d(LOG_TAG, "isWorldMode=" + worldModeOn);
+
+        return worldModeOn;
+    }
+
+    private void controlGsmOptions(boolean enable) {
+        PreferenceScreen prefSet = getPreferenceScreen();
+        if (prefSet == null) {
+            return;
+        }
+
+        updateGsmUmtsOptions(this, prefSet, mSubId);
+
+        PreferenceCategory networkOperatorCategory =
+                (PreferenceCategory) prefSet.findPreference(
+                        NetworkOperators.CATEGORY_NETWORK_OPERATORS_KEY);
+        Preference carrierSettings = prefSet.findPreference(BUTTON_CARRIER_SETTINGS_KEY);
+        if (networkOperatorCategory != null) {
+            if (enable) {
+                networkOperatorCategory.setEnabled(true);
+            } else {
+                prefSet.removePreference(networkOperatorCategory);
+            }
+        }
+        if (carrierSettings != null) {
+            prefSet.removePreference(carrierSettings);
+        }
+    }
+
+    private void controlCdmaOptions(boolean enable) {
+        PreferenceScreen prefSet = getPreferenceScreen();
+        if (prefSet == null) {
+            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() {
+        if (getResources().getBoolean(R.bool.config_support_tdscdma)) {
+            return true;
+        }
+
+        String operatorNumeric = mTelephonyManager.getServiceState().getOperatorNumeric();
+        String[] numericArray = 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;
+    }
+
+    /**
+     * Metrics events related methods. it takes care of all preferences possible in this
+     * fragment(except a few that log on their own). It doesn't only include preferences in
+     * network_setting_fragment.xml, but also those defined in GsmUmtsOptions and CdmaOptions.
+     */
+    private void sendMetricsEventPreferenceClicked(
+            PreferenceScreen preferenceScreen, Preference preference) {
+        final int category = getMetricsEventCategory(preferenceScreen, preference);
+        if (category == MetricsProto.MetricsEvent.VIEW_UNKNOWN) {
+            return;
+        }
+
+        // Send MetricsEvent on click. It includes preferences other than SwitchPreferences,
+        // which send MetricsEvent in onPreferenceChange.
+        // 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
+                || preference == mEuiccSettingsPref
+                || preference == mWiFiCallingPref || preference == mButtonPreferredNetworkMode
+                || preference == mButtonEnabledNetworks
+                || preference == preferenceScreen.findPreference(BUTTON_CDMA_SYSTEM_SELECT_KEY)
+                || preference == preferenceScreen.findPreference(BUTTON_CDMA_SUBSCRIPTION_KEY)
+                || preference == preferenceScreen.findPreference(BUTTON_GSM_APN_EXPAND_KEY)
+                || preference == preferenceScreen.findPreference(BUTTON_CDMA_APN_EXPAND_KEY)
+                || preference == preferenceScreen.findPreference(BUTTON_CARRIER_SETTINGS_KEY)) {
+            MetricsLogger.action(getContext(), category);
+        }
+    }
+
+    private void sendMetricsEventPreferenceChanged(
+            PreferenceScreen preferenceScreen, Preference preference, Object newValue) {
+        final int category = getMetricsEventCategory(preferenceScreen, preference);
+        if (category == MetricsProto.MetricsEvent.VIEW_UNKNOWN) {
+            return;
+        }
+
+        // MetricsEvent logging with new value, for SwitchPreferences and ListPreferences.
+        if (preference == mButton4glte || preference == mVideoCallingPref) {
+            MetricsLogger.action(getContext(), category, (Boolean) newValue);
+        } else if (preference == mButtonPreferredNetworkMode
+                || preference == mButtonEnabledNetworks
+                || preference == preferenceScreen
+                .findPreference(BUTTON_CDMA_SYSTEM_SELECT_KEY)
+                || preference == preferenceScreen
+                .findPreference(BUTTON_CDMA_SUBSCRIPTION_KEY)) {
+            // Network select preference sends metrics event in its own listener.
+            MetricsLogger.action(getContext(), category, Integer.valueOf((String) newValue));
+        }
+    }
+
+    private int getMetricsEventCategory(
+            PreferenceScreen preferenceScreen, Preference preference) {
+
+        if (preference == null) {
+            return MetricsProto.MetricsEvent.VIEW_UNKNOWN;
+        } else if (preference == mMobileDataPref) {
+            return MetricsProto.MetricsEvent.ACTION_MOBILE_NETWORK_MOBILE_DATA_TOGGLE;
+        } 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) {
+            return MetricsProto.MetricsEvent.ACTION_MOBILE_ENHANCED_4G_LTE_MODE_TOGGLE;
+        } else if (preference == mButtonPreferredNetworkMode) {
+            return MetricsProto.MetricsEvent.ACTION_MOBILE_NETWORK_SELECT_PREFERRED_NETWORK;
+        } else if (preference == mButtonEnabledNetworks) {
+            return MetricsProto.MetricsEvent.ACTION_MOBILE_NETWORK_SELECT_ENABLED_NETWORK;
+        } else if (preference == mEuiccSettingsPref) {
+            return MetricsProto.MetricsEvent.ACTION_MOBILE_NETWORK_EUICC_SETTING;
+        } else if (preference == mWiFiCallingPref) {
+            return MetricsProto.MetricsEvent.ACTION_MOBILE_NETWORK_WIFI_CALLING;
+        } else if (preference == mVideoCallingPref) {
+            return MetricsProto.MetricsEvent.ACTION_MOBILE_NETWORK_VIDEO_CALLING_TOGGLE;
+        } else if (preference == preferenceScreen
+                .findPreference(NetworkOperators.BUTTON_AUTO_SELECT_KEY)) {
+            return MetricsProto.MetricsEvent.ACTION_MOBILE_NETWORK_AUTO_SELECT_NETWORK_TOGGLE;
+        } else if (preference == preferenceScreen
+                .findPreference(NetworkOperators.BUTTON_NETWORK_SELECT_KEY)) {
+            return MetricsProto.MetricsEvent.ACTION_MOBILE_NETWORK_MANUAL_SELECT_NETWORK;
+        } else if (preference == preferenceScreen
+                .findPreference(BUTTON_CDMA_SYSTEM_SELECT_KEY)) {
+            return MetricsProto.MetricsEvent.ACTION_MOBILE_NETWORK_CDMA_SYSTEM_SELECT;
+        } else if (preference == preferenceScreen
+                .findPreference(BUTTON_CDMA_SUBSCRIPTION_KEY)) {
+            return MetricsProto.MetricsEvent.ACTION_MOBILE_NETWORK_CDMA_SUBSCRIPTION_SELECT;
+        } else if (preference == preferenceScreen.findPreference(BUTTON_GSM_APN_EXPAND_KEY)
+                || preference == preferenceScreen.findPreference(BUTTON_CDMA_APN_EXPAND_KEY)) {
+            return MetricsProto.MetricsEvent.ACTION_MOBILE_NETWORK_APN_SETTINGS;
+        } else if (preference == preferenceScreen.findPreference(BUTTON_CARRIER_SETTINGS_KEY)) {
+            return MetricsProto.MetricsEvent.ACTION_MOBILE_NETWORK_CARRIER_SETTINGS;
+        } else {
+            return MetricsProto.MetricsEvent.VIEW_UNKNOWN;
+        }
+    }
+
+    private void updateGsmUmtsOptions(PreferenceFragmentCompat prefFragment,
+            PreferenceScreen prefScreen, final int subId) {
+        // We don't want to re-create GsmUmtsOptions if already exists. Otherwise, the
+        // preferences inside it will also be re-created which causes unexpected behavior.
+        // For example, the open dialog gets dismissed or detached after pause / resume.
+        if (mGsmUmtsOptions == null) {
+            mGsmUmtsOptions = new GsmUmtsOptions(prefFragment, prefScreen, subId);
+        } else {
+            mGsmUmtsOptions.update(subId);
+        }
+    }
+
+    private void updateCdmaOptions(PreferenceFragmentCompat prefFragment, PreferenceScreen prefScreen,
+            int subId) {
+        // We don't want to re-create CdmaOptions if already exists. Otherwise, the preferences
+        // inside it will also be re-created which causes unexpected behavior. For example,
+        // the open dialog gets dismissed or detached after pause / resume.
+        if (mCdmaOptions == null) {
+            mCdmaOptions = new CdmaOptions(prefFragment, prefScreen, subId);
+        } else {
+            mCdmaOptions.updateSubscriptionId(subId);
+        }
+    }
+
+    private static Intent buildPhoneAccountConfigureIntent(
+            Context context, PhoneAccountHandle accountHandle) {
+        Intent intent = buildConfigureIntent(
+                context, accountHandle, TelecomManager.ACTION_CONFIGURE_PHONE_ACCOUNT);
+
+        if (intent == null) {
+            // If the new configuration didn't work, try the old configuration intent.
+            intent = buildConfigureIntent(
+                    context, accountHandle, LEGACY_ACTION_CONFIGURE_PHONE_ACCOUNT);
+            if (intent != null) {
+                Log.w(MobileNetworkFragment.LOG_TAG,
+                        "Phone account using old configuration intent: " + accountHandle);
+            }
+        }
+        return intent;
+    }
+
+    private static Intent buildConfigureIntent(
+            Context context, PhoneAccountHandle accountHandle, String actionStr) {
+        if (accountHandle == null || accountHandle.getComponentName() == null
+                || TextUtils.isEmpty(accountHandle.getComponentName().getPackageName())) {
+            return null;
+        }
+
+        // Build the settings intent.
+        Intent intent = new Intent(actionStr);
+        intent.setPackage(accountHandle.getComponentName().getPackageName());
+        intent.addCategory(Intent.CATEGORY_DEFAULT);
+        intent.putExtra(TelecomManager.EXTRA_PHONE_ACCOUNT_HANDLE, accountHandle);
+
+        // Check to see that the phone account package can handle the setting intent.
+        PackageManager pm = context.getPackageManager();
+        List<ResolveInfo> resolutions = pm.queryIntentActivities(intent, 0);
+        if (resolutions.size() == 0) {
+            intent = null;  // set no intent if the package cannot handle it.
+        }
+
+        return intent;
+    }
+
+    //TODO(b/114749736): update search provider
+    public static final Indexable.SearchIndexProvider SEARCH_INDEX_DATA_PROVIDER =
+            new BaseSearchIndexProvider() {
+                @Override
+                protected boolean isPageSearchEnabled(Context context) {
+                    return false;
+                }
+            };
+
+    private static final class SetPreferredNetworkAsyncTask extends AsyncTask<Void, Void, Boolean> {
+
+        private final TelephonyManager mTelephonyManager;
+        private final int mSubId;
+        private final int mNetworkType;
+        private final Message mCallback;
+
+        SetPreferredNetworkAsyncTask(
+                TelephonyManager tm, int subId, int networkType, Message callback) {
+            mTelephonyManager = tm;
+            mSubId = subId;
+            mNetworkType = networkType;
+            mCallback = callback;
+        }
+
+        @Override
+        protected Boolean doInBackground(Void... voids) {
+            return mTelephonyManager.setPreferredNetworkType(mSubId, mNetworkType);
+        }
+
+        @Override
+        protected void onPostExecute(Boolean isSuccessed) {
+            mCallback.obj = isSuccessed;
+            mCallback.sendToTarget();
+        }
+    }
+}
diff --git a/src/com/android/settings/mobilenetwork/MobileNetworkUtils.java b/src/com/android/settings/mobilenetwork/MobileNetworkUtils.java
new file mode 100644
index 0000000..2109375
--- /dev/null
+++ b/src/com/android/settings/mobilenetwork/MobileNetworkUtils.java
@@ -0,0 +1,173 @@
+/*
+ * 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.mobilenetwork;
+
+import static android.provider.Telephony.Carriers.ENFORCE_MANAGED_URI;
+
+import android.content.ContentResolver;
+import android.content.Context;
+import android.content.Intent;
+import android.content.pm.PackageManager;
+import android.content.pm.ResolveInfo;
+import android.database.Cursor;
+import android.os.PersistableBundle;
+import android.os.SystemProperties;
+import android.provider.Settings;
+import android.telecom.PhoneAccountHandle;
+import android.telecom.TelecomManager;
+import android.telephony.TelephonyManager;
+import android.telephony.euicc.EuiccManager;
+import android.telephony.ims.feature.ImsFeature;
+import android.text.TextUtils;
+import android.util.Log;
+
+import com.android.ims.ImsException;
+import com.android.ims.ImsManager;
+
+import java.util.Arrays;
+import java.util.List;
+
+public class MobileNetworkUtils {
+
+    private static final String TAG = "MobileNetworkUtils";
+
+    // CID of the device.
+    private static final String KEY_CID = "ro.boot.cid";
+    // CIDs of devices which should not show anything related to eSIM.
+    private static final String KEY_ESIM_CID_IGNORE = "ro.setupwizard.esim_cid_ignore";
+    // System Property which is used to decide whether the default eSIM UI will be shown,
+    // the default value is false.
+    private static final String KEY_ENABLE_ESIM_UI_BY_DEFAULT =
+            "esim.enable_esim_system_ui_by_default";
+
+    /**
+     * Returns if DPC APNs are enforced.
+     */
+    public static boolean isDpcApnEnforced(Context context) {
+        try (Cursor enforceCursor = context.getContentResolver().query(ENFORCE_MANAGED_URI,
+                null, null, null, null)) {
+            if (enforceCursor == null || enforceCursor.getCount() != 1) {
+                return false;
+            }
+            enforceCursor.moveToFirst();
+            return enforceCursor.getInt(0) > 0;
+        }
+    }
+
+    /**
+     * Returns true if Wifi calling is enabled for at least one phone.
+     */
+    public static boolean isWifiCallingEnabled(Context context) {
+        int phoneCount = TelephonyManager.from(context).getPhoneCount();
+        for (int i = 0; i < phoneCount; i++) {
+            if (isWifiCallingEnabled(context, i)) {
+                return true;
+            }
+        }
+        return false;
+    }
+
+    /**
+     * Returns true if Wifi calling is enabled for the specific phone with id {@code phoneId}.
+     */
+    public static boolean isWifiCallingEnabled(Context context, int phoneId) {
+        final PhoneAccountHandle simCallManager =
+                TelecomManager.from(context).getSimCallManager();
+
+        boolean isWifiCallingEnabled;
+        if (simCallManager != null) {
+            //TODO(b/114749736): build intent to query wifi calling feature
+            final Intent intent = null;
+            PackageManager pm = context.getPackageManager();
+            isWifiCallingEnabled = intent != null
+                    && !pm.queryIntentActivities(intent, 0 /* flags */).isEmpty();
+        } else {
+            ImsManager imsMgr = ImsManager.getInstance(context, phoneId);
+            isWifiCallingEnabled = imsMgr != null
+                    && imsMgr.isWfcEnabledByPlatform()
+                    && imsMgr.isWfcProvisionedOnDevice()
+                    && isImsServiceStateReady(imsMgr);
+        }
+
+        return isWifiCallingEnabled;
+    }
+
+    public static boolean isImsServiceStateReady(ImsManager imsMgr) {
+        boolean isImsServiceStateReady = false;
+
+        try {
+            if (imsMgr != null && imsMgr.getImsServiceState() == ImsFeature.STATE_READY) {
+                isImsServiceStateReady = true;
+            }
+        } catch (ImsException ex) {
+            Log.e(TAG, "Exception when trying to get ImsServiceStatus: " + ex);
+        }
+
+        Log.d(TAG, "isImsServiceStateReady=" + isImsServiceStateReady);
+        return isImsServiceStateReady;
+    }
+
+    /**
+     * Whether to show the entry point to eUICC settings.
+     *
+     * <p>We show the entry point on any device which supports eUICC as long as either the eUICC
+     * was ever provisioned (that is, at least one profile was ever downloaded onto it), or if
+     * the user has enabled development mode.
+     */
+    public static boolean showEuiccSettings(Context context) {
+        EuiccManager euiccManager =
+                (EuiccManager) context.getSystemService(Context.EUICC_SERVICE);
+        if (!euiccManager.isEnabled()) {
+            return false;
+        }
+
+        final ContentResolver cr = context.getContentResolver();
+
+        TelephonyManager tm =
+                (TelephonyManager) context.getSystemService(Context.TELEPHONY_SERVICE);
+        String currentCountry = tm.getNetworkCountryIso().toLowerCase();
+        String supportedCountries =
+                Settings.Global.getString(cr, Settings.Global.EUICC_SUPPORTED_COUNTRIES);
+        boolean inEsimSupportedCountries = false;
+        if (TextUtils.isEmpty(currentCountry)) {
+            inEsimSupportedCountries = true;
+        } else if (!TextUtils.isEmpty(supportedCountries)) {
+            List<String> supportedCountryList =
+                    Arrays.asList(TextUtils.split(supportedCountries.toLowerCase(), ","));
+            if (supportedCountryList.contains(currentCountry)) {
+                inEsimSupportedCountries = true;
+            }
+        }
+        final boolean esimIgnoredDevice =
+                Arrays.asList(TextUtils.split(SystemProperties.get(KEY_ESIM_CID_IGNORE, ""), ","))
+                        .contains(SystemProperties.get(KEY_CID, null));
+        final boolean enabledEsimUiByDefault =
+                SystemProperties.getBoolean(KEY_ENABLE_ESIM_UI_BY_DEFAULT, true);
+        final boolean euiccProvisioned =
+                Settings.Global.getInt(cr, Settings.Global.EUICC_PROVISIONED, 0) != 0;
+        final boolean inDeveloperMode =
+                Settings.Global.getInt(cr, Settings.Global.DEVELOPMENT_SETTINGS_ENABLED, 0) != 0;
+
+        return (inDeveloperMode || euiccProvisioned
+                || (!esimIgnoredDevice && enabledEsimUiByDefault && inEsimSupportedCountries));
+    }
+
+    public static PersistableBundle getCarrierConfigBySubId(int mSubId) {
+        //TODO(b/114749736): get carrier config from subId
+        return new PersistableBundle();
+    }
+}
\ No newline at end of file
diff --git a/src/com/android/settings/mobilenetwork/MobileSettingsActivity.java b/src/com/android/settings/mobilenetwork/MobileSettingsActivity.java
new file mode 100644
index 0000000..37a180c
--- /dev/null
+++ b/src/com/android/settings/mobilenetwork/MobileSettingsActivity.java
@@ -0,0 +1,126 @@
+/*
+ * 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.mobilenetwork;
+
+import android.content.Intent;
+import android.os.Bundle;
+import android.telephony.SubscriptionInfo;
+import android.telephony.SubscriptionManager;
+import android.view.Menu;
+import android.view.View;
+
+import com.android.internal.util.CollectionUtils;
+import com.android.settings.R;
+import com.android.settings.core.SettingsBaseActivity;
+
+import com.google.android.material.bottomnavigation.BottomNavigationView;
+
+import java.util.List;
+
+import androidx.annotation.VisibleForTesting;
+import androidx.fragment.app.Fragment;
+import androidx.fragment.app.FragmentManager;
+import androidx.fragment.app.FragmentTransaction;
+
+public class MobileSettingsActivity extends SettingsBaseActivity {
+
+    @VisibleForTesting
+    static final String MOBILE_SETTINGS_TAG = "mobile_settings:";
+    public static final String KEY_SUBSCRIPTION_ID = "key_subscription_id";
+
+    private SubscriptionManager mSubscriptionManager;
+    @VisibleForTesting
+    int mPrevSubscriptionId;
+    @VisibleForTesting
+    List<SubscriptionInfo> mSubscriptionInfos;
+
+    @Override
+    protected void onNewIntent(Intent intent) {
+        super.onNewIntent(intent);
+        //TODO(b/114749736): update fragment by new intent, or at least make sure this page shows
+        // current tab for sim card
+    }
+
+    @Override
+    protected void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+        mSubscriptionManager = getSystemService(SubscriptionManager.class);
+        mSubscriptionInfos = mSubscriptionManager.getActiveSubscriptionInfoList();
+        mPrevSubscriptionId = CollectionUtils.isEmpty(mSubscriptionInfos)
+                ? SubscriptionManager.INVALID_SUBSCRIPTION_ID
+                : mSubscriptionInfos.get(0).getSubscriptionId();
+
+        setContentView(R.layout.mobile_settings_container);
+
+        updateBottomNavigationView();
+
+        if (savedInstanceState == null) {
+            switchFragment(new MobileNetworkFragment(), mPrevSubscriptionId);
+        }
+    }
+
+    @VisibleForTesting
+    void updateBottomNavigationView() {
+        final BottomNavigationView navigation = findViewById(R.id.bottom_nav);
+
+        if (CollectionUtils.size(mSubscriptionInfos) <= 1) {
+            navigation.setVisibility(View.GONE);
+        } else {
+            final Menu menu = navigation.getMenu();
+            menu.clear();
+            for (int i = 0, size = mSubscriptionInfos.size(); i < size; i++) {
+                final SubscriptionInfo subscriptionInfo = mSubscriptionInfos.get(i);
+                menu.add(0, subscriptionInfo.getSubscriptionId(), i,
+                        subscriptionInfo.getDisplayName());
+            }
+            navigation.setOnNavigationItemSelectedListener(item -> {
+                switchFragment(new MobileNetworkFragment(), item.getItemId());
+                mPrevSubscriptionId = item.getItemId();
+                return true;
+            });
+
+        }
+    }
+
+    @VisibleForTesting
+    void switchFragment(Fragment fragment, int subscriptionId) {
+        final FragmentManager fragmentManager = getSupportFragmentManager();
+        final FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
+        final Bundle bundle = new Bundle();
+        bundle.putInt(KEY_SUBSCRIPTION_ID, subscriptionId);
+
+        final Fragment hideFragment = fragmentManager.findFragmentByTag(
+                buildFragmentTag(mPrevSubscriptionId));
+        if (hideFragment != null) {
+            fragmentTransaction.hide(hideFragment);
+        }
+
+        Fragment showFragment = fragmentManager.findFragmentByTag(buildFragmentTag(subscriptionId));
+        if (showFragment == null) {
+            fragment.setArguments(bundle);
+            fragmentTransaction.add(R.id.main_content, fragment, buildFragmentTag(subscriptionId));
+        } else {
+            showFragment.setArguments(bundle);
+            fragmentTransaction.show(showFragment);
+        }
+        fragmentTransaction.commit();
+    }
+
+    private String buildFragmentTag(int subscriptionId) {
+        return MOBILE_SETTINGS_TAG + subscriptionId;
+    }
+}
\ No newline at end of file
diff --git a/src/com/android/settings/mobilenetwork/NetworkOperators.java b/src/com/android/settings/mobilenetwork/NetworkOperators.java
new file mode 100644
index 0000000..9f0de8a
--- /dev/null
+++ b/src/com/android/settings/mobilenetwork/NetworkOperators.java
@@ -0,0 +1,301 @@
+/*
+ * 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.mobilenetwork;
+
+import android.app.ProgressDialog;
+import android.content.Context;
+import android.content.Intent;
+import android.os.Handler;
+import android.os.Message;
+import android.telephony.ServiceState;
+import android.telephony.SubscriptionManager;
+import android.telephony.TelephonyManager;
+import android.util.AttributeSet;
+import android.util.Log;
+import android.widget.Toast;
+
+import androidx.preference.Preference;
+import androidx.preference.PreferenceCategory;
+import androidx.preference.TwoStatePreference;
+
+import com.android.internal.logging.MetricsLogger;
+import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
+import com.android.settings.R;
+import com.android.settingslib.utils.ThreadUtils;
+
+/**
+ * "Networks" settings UI for the Phone app.
+ */
+public class NetworkOperators extends PreferenceCategory
+        implements Preference.OnPreferenceChangeListener {
+
+    private static final String LOG_TAG = "NetworkOperators";
+    private static final boolean DBG = true;
+
+    private static final int EVENT_AUTO_SELECT_DONE = 100;
+    private static final int EVENT_GET_NETWORK_SELECTION_MODE_DONE = 200;
+
+    //String keys for preference lookup
+    public static final String BUTTON_NETWORK_SELECT_KEY = "button_network_select_key";
+    public static final String BUTTON_AUTO_SELECT_KEY = "button_auto_select_key";
+    public static final String BUTTON_CHOOSE_NETWORK_KEY = "button_choose_network_key";
+    public static final String CATEGORY_NETWORK_OPERATORS_KEY = "network_operators_category_key";
+
+    //preference objects
+    private NetworkSelectListPreference mNetworkSelect;
+    private TwoStatePreference mAutoSelect;
+    private Preference mChooseNetwork;
+    private ProgressDialog mProgressDialog;
+
+    private int mSubId;
+    private TelephonyManager mTelephonyManager;
+
+    // There's two sets of Auto-Select UI in this class.
+    // If {@code com.android.internal.R.bool.config_enableNewAutoSelectNetworkUI} set as true
+    // {@link mChooseNetwork} will be used, otherwise {@link mNetworkSelect} will be used.
+    boolean mEnableNewManualSelectNetworkUI;
+
+    public NetworkOperators(Context context, AttributeSet attrs) {
+        super(context, attrs);
+    }
+
+    public NetworkOperators(Context context) {
+        super(context);
+    }
+
+    /**
+     * Initialize NetworkOperators instance.
+     */
+    public void initialize() {
+        mEnableNewManualSelectNetworkUI = getContext().getResources().getBoolean(
+                com.android.internal.R.bool.config_enableNewAutoSelectNetworkUI);
+        mAutoSelect = (TwoStatePreference) findPreference(BUTTON_AUTO_SELECT_KEY);
+        mChooseNetwork = findPreference(BUTTON_CHOOSE_NETWORK_KEY);
+        mNetworkSelect = (NetworkSelectListPreference) findPreference(BUTTON_NETWORK_SELECT_KEY);
+        if (mEnableNewManualSelectNetworkUI) {
+            removePreference(mNetworkSelect);
+        } else {
+            removePreference(mChooseNetwork);
+        }
+        mProgressDialog = new ProgressDialog(getContext());
+        mTelephonyManager = TelephonyManager.from(getContext());
+    }
+
+    /**
+     * Update NetworkOperators instance if like subId is updated.
+     *
+     * @param subId Corresponding subscription ID of this network.
+     */
+    protected void update(final int subId) {
+        mSubId = subId;
+        mTelephonyManager = TelephonyManager.from(getContext()).createForSubscriptionId(mSubId);
+
+        if (mAutoSelect != null) {
+            mAutoSelect.setOnPreferenceChangeListener(this);
+        }
+
+        if (mEnableNewManualSelectNetworkUI) {
+            if (mChooseNetwork != null) {
+                ServiceState ss = mTelephonyManager.getServiceState();
+                if (ss != null && ss.getState() == ServiceState.STATE_IN_SERVICE) {
+                    mChooseNetwork.setSummary(mTelephonyManager.getNetworkOperatorName());
+                } else {
+                    mChooseNetwork.setSummary(R.string.network_disconnected);
+                }
+            }
+        } else {
+            if (mNetworkSelect != null) {
+                mNetworkSelect.initialize(mSubId, this, mProgressDialog);
+            }
+        }
+        getNetworkSelectionMode();
+    }
+
+    /**
+     * Implemented to support onPreferenceChangeListener to look for preference
+     * changes specifically on auto select button.
+     *
+     * @param preference is the preference to be changed, should be auto select button.
+     * @param newValue   should be the value of whether autoSelect is checked.
+     */
+    @Override
+    public boolean onPreferenceChange(Preference preference, Object newValue) {
+        if (preference == mAutoSelect) {
+            boolean autoSelect = (Boolean) newValue;
+            if (DBG) logd("onPreferenceChange autoSelect: " + String.valueOf(autoSelect));
+            selectNetworkAutomatic(autoSelect);
+            MetricsLogger.action(getContext(),
+                    MetricsEvent.ACTION_MOBILE_NETWORK_AUTO_SELECT_NETWORK_TOGGLE, autoSelect);
+            return true;
+        }
+        return false;
+    }
+
+    private final Handler mHandler = new Handler() {
+        @Override
+        public void handleMessage(Message msg) {
+            switch (msg.what) {
+                case EVENT_AUTO_SELECT_DONE:
+                    mAutoSelect.setEnabled(true);
+                    dismissProgressBar();
+
+                    boolean isSuccessed = (boolean) msg.obj;
+
+                    if (isSuccessed) {
+                        if (DBG) logd("automatic network selection: succeeded!");
+                        displayNetworkSelectionSucceeded();
+                    } else {
+                        if (DBG) logd("automatic network selection: failed!");
+                        displayNetworkSelectionFailed();
+                    }
+
+                    break;
+                case EVENT_GET_NETWORK_SELECTION_MODE_DONE:
+                    int networkSelectionMode = msg.arg1;
+                    if (networkSelectionMode == TelephonyManager.NETWORK_SELECTION_MODE_UNKNOWN) {
+                        if (DBG) logd("get network selection mode: failed!");
+                    } else {
+                        boolean autoSelect = networkSelectionMode
+                                == TelephonyManager.NETWORK_SELECTION_MODE_AUTO;
+                        if (DBG) {
+                            logd("get network selection mode: "
+                                    + (autoSelect ? "auto" : "manual") + " selection");
+                        }
+                        if (mAutoSelect != null) {
+                            mAutoSelect.setChecked(autoSelect);
+                        }
+                        if (mEnableNewManualSelectNetworkUI) {
+                            if (mChooseNetwork != null) {
+                                mChooseNetwork.setEnabled(!autoSelect);
+                            }
+                        } else {
+                            if (mNetworkSelect != null) {
+                                mNetworkSelect.setEnabled(!autoSelect);
+                            }
+                        }
+                    }
+            }
+            return;
+        }
+    };
+
+    // Used by both mAutoSelect and mNetworkSelect buttons.
+    protected void displayNetworkSelectionFailed() {
+        Toast.makeText(getContext(), R.string.connect_later, Toast.LENGTH_LONG).show();
+    }
+
+    // Used by both mAutoSelect and mNetworkSelect buttons.
+    protected void displayNetworkSelectionSucceeded() {
+        Toast.makeText(getContext(), R.string.registration_done, Toast.LENGTH_LONG).show();
+    }
+
+    private void selectNetworkAutomatic(boolean autoSelect) {
+        if (DBG) logd("selectNetworkAutomatic: " + String.valueOf(autoSelect));
+
+        if (autoSelect) {
+            if (mEnableNewManualSelectNetworkUI) {
+                if (mChooseNetwork != null) {
+                    mChooseNetwork.setEnabled(!autoSelect);
+                }
+            } else {
+                if (mNetworkSelect != null) {
+                    mNetworkSelect.setEnabled(!autoSelect);
+                }
+            }
+            if (DBG) logd("select network automatically...");
+            showAutoSelectProgressBar();
+            mAutoSelect.setEnabled(false);
+            if (SubscriptionManager.isValidSubscriptionId(mSubId)) {
+                ThreadUtils.postOnBackgroundThread(() -> {
+                    mTelephonyManager.setNetworkSelectionModeAutomatic();
+                    // Because TelephonyManager#setNetworkSelectionModeAutomatic doesn't have a
+                    // return value, we query the current network selection mode to tell if the
+                    // TelephonyManager#setNetworkSelectionModeAutomatic is successed.
+                    int networkSelectionMode = mTelephonyManager.getNetworkSelectionMode();
+                    Message msg = mHandler.obtainMessage(EVENT_AUTO_SELECT_DONE);
+                    msg.obj = networkSelectionMode == TelephonyManager.NETWORK_SELECTION_MODE_AUTO;
+                    msg.sendToTarget();
+                });
+            }
+        } else {
+            if (mEnableNewManualSelectNetworkUI) {
+                if (mChooseNetwork != null) {
+                    // Open the choose Network page automatically when user turn off the auto-select
+                    openChooseNetworkPage();
+                }
+            } else {
+                if (mNetworkSelect != null) {
+                    mNetworkSelect.onClick();
+                }
+            }
+        }
+    }
+
+    protected void getNetworkSelectionMode() {
+        if (DBG) logd("getting network selection mode...");
+        ThreadUtils.postOnBackgroundThread(() -> {
+            int networkSelectionMode = mTelephonyManager.getNetworkSelectionMode();
+            Message msg = mHandler.obtainMessage(EVENT_GET_NETWORK_SELECTION_MODE_DONE);
+            msg.arg1 = networkSelectionMode;
+            msg.sendToTarget();
+        });
+    }
+
+    private void dismissProgressBar() {
+        if (mProgressDialog != null && mProgressDialog.isShowing()) {
+            mProgressDialog.dismiss();
+        }
+    }
+
+    private void showAutoSelectProgressBar() {
+        mProgressDialog.setMessage(
+                getContext().getResources().getString(R.string.register_automatically));
+        mProgressDialog.setCanceledOnTouchOutside(false);
+        mProgressDialog.setCancelable(false);
+        mProgressDialog.setIndeterminate(true);
+        mProgressDialog.show();
+    }
+
+    /**
+     * Open the Choose network page via {@alink NetworkSelectSettingActivity}
+     */
+    public void openChooseNetworkPage() {
+        //TODO(b/114749736): Build intent without calling static method
+        Intent intent = new Intent();
+        getContext().startActivity(intent);
+    }
+
+    protected boolean preferenceTreeClick(Preference preference) {
+        if (mEnableNewManualSelectNetworkUI) {
+            if (DBG) logd("enable New AutoSelectNetwork UI");
+            if (preference == mChooseNetwork) {
+                openChooseNetworkPage();
+            }
+            return (preference == mAutoSelect || preference == mChooseNetwork);
+        } else {
+            return (preference == mAutoSelect || preference == mNetworkSelect);
+        }
+    }
+
+    private void logd(String msg) {
+        Log.d(LOG_TAG, "[NetworksList] " + msg);
+    }
+
+    private void loge(String msg) {
+        Log.e(LOG_TAG, "[NetworksList] " + msg);
+    }
+}
diff --git a/src/com/android/settings/mobilenetwork/NetworkScanHelper.java b/src/com/android/settings/mobilenetwork/NetworkScanHelper.java
new file mode 100644
index 0000000..234d3b3
--- /dev/null
+++ b/src/com/android/settings/mobilenetwork/NetworkScanHelper.java
@@ -0,0 +1,286 @@
+/*
+ * 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.mobilenetwork;
+
+import android.annotation.IntDef;
+import android.telephony.AccessNetworkConstants.AccessNetworkType;
+import android.telephony.CellInfo;
+import android.telephony.NetworkScan;
+import android.telephony.NetworkScanRequest;
+import android.telephony.RadioAccessSpecifier;
+import android.telephony.TelephonyManager;
+import android.telephony.TelephonyScanManager;
+import android.util.Log;
+
+import com.android.internal.telephony.CellNetworkScanResult;
+
+import com.google.common.util.concurrent.FutureCallback;
+import com.google.common.util.concurrent.Futures;
+import com.google.common.util.concurrent.ListenableFuture;
+import com.google.common.util.concurrent.SettableFuture;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.util.List;
+import java.util.concurrent.Executor;
+import java.util.stream.Collectors;
+
+/**
+ * A helper class that builds the common interface and performs the network scan for two different
+ * network scan APIs.
+ */
+public class NetworkScanHelper {
+    public static final String TAG = "NetworkScanHelper";
+    private static final boolean DBG = true;
+
+    /**
+     * Callbacks interface to inform the network scan results.
+     */
+    public interface NetworkScanCallback {
+        /**
+         * Called when the results is returned from {@link TelephonyManager}. This method will be
+         * called at least one time if there is no error occurred during the network scan.
+         *
+         * <p> This method can be called multiple times in one network scan, until
+         * {@link #onComplete()} or {@link #onError(int)} is called.
+         *
+         * @param results
+         */
+        void onResults(List<CellInfo> results);
+
+        /**
+         * Called when the current network scan process is finished. No more
+         * {@link #onResults(List)} will be called for the current network scan after this method is
+         * called.
+         */
+        void onComplete();
+
+        /**
+         * Called when an error occurred during the network scan process.
+         *
+         * <p> There is no more result returned from {@link TelephonyManager} if an error occurred.
+         *
+         * <p> {@link #onComplete()} will not be called if an error occurred.
+         *
+         * @see {@link NetworkScan.ScanErrorCode}
+         */
+        void onError(int errorCode);
+    }
+
+    @Retention(RetentionPolicy.SOURCE)
+    @IntDef({NETWORK_SCAN_TYPE_WAIT_FOR_ALL_RESULTS, NETWORK_SCAN_TYPE_INCREMENTAL_RESULTS})
+    public @interface NetworkQueryType {}
+
+    /**
+     * Performs the network scan using {@link TelephonyManager#getAvailableNetworks()}. The network
+     * scan results won't be returned to the caller until the network scan is completed.
+     *
+     * <p> This is typically used when the modem doesn't support the new network scan api
+     * {@link TelephonyManager#requestNetworkScan(
+     * NetworkScanRequest, Executor, TelephonyScanManager.NetworkScanCallback)}.
+     */
+    public static final int NETWORK_SCAN_TYPE_WAIT_FOR_ALL_RESULTS = 1;
+
+    /**
+     * Performs the network scan using {@link TelephonyManager#requestNetworkScan(
+     * NetworkScanRequest, Executor, TelephonyScanManager.NetworkScanCallback)} The network scan
+     * results will be returned to the caller periodically in a small time window until the network
+     * scan is completed. The complete results should be returned in the last called of
+     * {@link NetworkScanCallback#onResults(List)}.
+     *
+     * <p> This is recommended to be used if modem supports the new network scan api
+     * {@link TelephonyManager#requestNetworkScan(
+     * NetworkScanRequest, Executor, TelephonyScanManager.NetworkScanCallback)}
+     */
+    public static final int NETWORK_SCAN_TYPE_INCREMENTAL_RESULTS = 2;
+
+    /** The constants below are used in the async network scan. */
+    private static final boolean INCREMENTAL_RESULTS = true;
+    private static final int SEARCH_PERIODICITY_SEC = 5;
+    private static final int MAX_SEARCH_TIME_SEC = 300;
+    private static final int INCREMENTAL_RESULTS_PERIODICITY_SEC = 3;
+
+    private static final NetworkScanRequest NETWORK_SCAN_REQUEST =
+            new NetworkScanRequest(
+                    NetworkScanRequest.SCAN_TYPE_ONE_SHOT,
+                    new RadioAccessSpecifier[]{
+                            // GSM
+                            new RadioAccessSpecifier(
+                                    AccessNetworkType.GERAN,
+                                    null /* bands */,
+                                    null /* channels */),
+                            // LTE
+                            new RadioAccessSpecifier(
+                                    AccessNetworkType.EUTRAN,
+                                    null /* bands */,
+                                    null /* channels */),
+                            // WCDMA
+                            new RadioAccessSpecifier(
+                                    AccessNetworkType.UTRAN,
+                                    null /* bands */,
+                                    null /* channels */)
+                    },
+                    SEARCH_PERIODICITY_SEC,
+                    MAX_SEARCH_TIME_SEC,
+                    INCREMENTAL_RESULTS,
+                    INCREMENTAL_RESULTS_PERIODICITY_SEC,
+                    null /* List of PLMN ids (MCC-MNC) */);
+
+    private final NetworkScanCallback mNetworkScanCallback;
+    private final TelephonyManager mTelephonyManager;
+    private final TelephonyScanManager.NetworkScanCallback mInternalNetworkScanCallback;
+    private final Executor mExecutor;
+
+    private NetworkScan mNetworkScanRequester;
+
+    /** Callbacks for sync network scan */
+    private ListenableFuture<List<CellInfo>> mNetworkScanFuture;
+
+    public NetworkScanHelper(TelephonyManager tm, NetworkScanCallback callback, Executor executor) {
+        mTelephonyManager = tm;
+        mNetworkScanCallback = callback;
+        mInternalNetworkScanCallback = new NetworkScanCallbackImpl();
+        mExecutor = executor;
+    }
+
+    /**
+     * Performs a network scan for the given type {@code type}.
+     * {@link #NETWORK_SCAN_TYPE_INCREMENTAL_RESULTS} is recommended if modem supports
+     * {@link TelephonyManager#requestNetworkScan(
+     * NetworkScanRequest, Executor, TelephonyScanManager.NetworkScanCallback)}.
+     *
+     * @param type used to tell which network scan API should be used.
+     */
+    public void startNetworkScan(@NetworkQueryType int type) {
+        if (type == NETWORK_SCAN_TYPE_WAIT_FOR_ALL_RESULTS) {
+            mNetworkScanFuture = SettableFuture.create();
+            Futures.addCallback(mNetworkScanFuture, new FutureCallback<List<CellInfo>>() {
+                @Override
+                public void onSuccess(List<CellInfo> result) {
+                    onResults(result);
+                    onComplete();
+                }
+
+                @Override
+                public void onFailure(Throwable t) {
+                    int errCode = Integer.parseInt(t.getMessage());
+                    onError(errCode);
+                }
+            });
+            mExecutor.execute(new NetworkScanSyncTask(
+                    mTelephonyManager, (SettableFuture) mNetworkScanFuture));
+        } else if (type == NETWORK_SCAN_TYPE_INCREMENTAL_RESULTS) {
+            if (DBG) Log.d(TAG, "start network scan async");
+            mNetworkScanRequester = mTelephonyManager.requestNetworkScan(
+                    NETWORK_SCAN_REQUEST,
+                    mExecutor,
+                    mInternalNetworkScanCallback);
+        }
+    }
+
+    /**
+     * The network scan of type {@link #NETWORK_SCAN_TYPE_WAIT_FOR_ALL_RESULTS} can't be stopped,
+     * however, the result of the current network scan won't be returned to the callback after
+     * calling this method.
+     */
+    public void stopNetworkQuery() {
+        if (mNetworkScanRequester != null) {
+            mNetworkScanRequester.stopScan();
+            mNetworkScanFuture = null;
+        }
+
+        if (mNetworkScanFuture != null) {
+            mNetworkScanFuture.cancel(true /* mayInterruptIfRunning */);
+            mNetworkScanFuture = null;
+        }
+    }
+
+    private void onResults(List<CellInfo> cellInfos) {
+        mNetworkScanCallback.onResults(cellInfos);
+    }
+
+    private void onComplete() {
+        mNetworkScanCallback.onComplete();
+    }
+
+    private void onError(int errCode) {
+        mNetworkScanCallback.onError(errCode);
+    }
+
+    /**
+     * Converts the status code of {@link CellNetworkScanResult} to one of the
+     * {@link NetworkScan.ScanErrorCode}.
+     * @param errCode status code from {@link CellNetworkScanResult}.
+     *
+     * @return one of the scan error code from {@link NetworkScan.ScanErrorCode}.
+     */
+    private static int convertToScanErrorCode(int errCode) {
+        switch (errCode) {
+            case CellNetworkScanResult.STATUS_RADIO_NOT_AVAILABLE:
+                return NetworkScan.ERROR_RADIO_INTERFACE_ERROR;
+            case CellNetworkScanResult.STATUS_RADIO_GENERIC_FAILURE:
+            default:
+                return NetworkScan.ERROR_MODEM_ERROR;
+        }
+    }
+
+    private final class NetworkScanCallbackImpl extends TelephonyScanManager.NetworkScanCallback {
+        public void onResults(List<CellInfo> results) {
+            if (DBG) Log.d(TAG, "async scan onResults() results = " + results);
+            NetworkScanHelper.this.onResults(results);
+        }
+
+        public void onComplete() {
+            if (DBG) Log.d(TAG, "async scan onComplete()");
+            NetworkScanHelper.this.onComplete();
+        }
+
+        public void onError(@NetworkScan.ScanErrorCode int errCode) {
+            if (DBG) Log.d(TAG, "async scan onError() errorCode = " + errCode);
+            NetworkScanHelper.this.onError(errCode);
+        }
+    }
+
+    private static final class NetworkScanSyncTask implements Runnable {
+        private final SettableFuture<List<CellInfo>> mCallback;
+        private final TelephonyManager mTelephonyManager;
+
+        NetworkScanSyncTask(
+                TelephonyManager telephonyManager, SettableFuture<List<CellInfo>> callback) {
+            mTelephonyManager = telephonyManager;
+            mCallback = callback;
+        }
+
+        @Override
+        public void run() {
+            if (DBG) Log.d(TAG, "sync scan start");
+            CellNetworkScanResult result = mTelephonyManager.getAvailableNetworks();
+            if (result.getStatus() == CellNetworkScanResult.STATUS_SUCCESS) {
+                List<CellInfo> cellInfos = result.getOperators()
+                        .stream()
+                        .map(operatorInfo
+                                -> CellInfoUtil.convertOperatorInfoToCellInfo(operatorInfo))
+                        .collect(Collectors.toList());
+                if (DBG) Log.d(TAG, "sync scan complete");
+                mCallback.set(cellInfos);
+            } else {
+                mCallback.setException(new Throwable(
+                        Integer.toString(convertToScanErrorCode(result.getStatus()))));
+            }
+        }
+    }
+}
diff --git a/src/com/android/settings/mobilenetwork/NetworkSelectListPreference.java b/src/com/android/settings/mobilenetwork/NetworkSelectListPreference.java
new file mode 100644
index 0000000..c4d0d77
--- /dev/null
+++ b/src/com/android/settings/mobilenetwork/NetworkSelectListPreference.java
@@ -0,0 +1,506 @@
+/*
+ * Copyright (C) 2006 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.mobilenetwork;
+
+import android.app.ProgressDialog;
+import android.content.Context;
+import android.content.DialogInterface;
+import android.os.AsyncTask;
+import android.os.Handler;
+import android.os.Message;
+import android.os.Parcel;
+import android.os.Parcelable;
+import android.telephony.CellInfo;
+import android.telephony.CellInfoCdma;
+import android.telephony.CellInfoGsm;
+import android.telephony.CellInfoLte;
+import android.telephony.CellInfoWcdma;
+import android.telephony.SubscriptionManager;
+import android.telephony.TelephonyManager;
+import android.text.BidiFormatter;
+import android.text.TextDirectionHeuristics;
+import android.text.TextUtils;
+import android.util.AttributeSet;
+import android.util.Log;
+import android.widget.Toast;
+
+import com.android.internal.logging.MetricsLogger;
+import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
+import com.android.internal.telephony.OperatorInfo;
+import com.android.settings.R;
+import com.android.settingslib.utils.ThreadUtils;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
+
+import androidx.preference.ListPreference;
+import androidx.preference.Preference;
+
+
+/**
+ * "Networks" preference in "Mobile network" settings UI for the Phone app.
+ * It's used to manually search and choose mobile network. Enabled only when
+ * autoSelect preference is turned off.
+ */
+public class NetworkSelectListPreference extends ListPreference
+        implements DialogInterface.OnCancelListener,
+        Preference.OnPreferenceChangeListener{
+
+    private static final String LOG_TAG = "networkSelect";
+    private static final boolean DBG = true;
+
+    private static final int EVENT_MANUALLY_NETWORK_SELECTION_DONE = 1;
+    private static final int EVENT_NETWORK_SCAN_RESULTS = 2;
+    private static final int EVENT_NETWORK_SCAN_COMPLETED = 3;
+    private static final int EVENT_NETWORK_SCAN_ERROR = 4;
+
+    //dialog ids
+    private static final int DIALOG_NETWORK_SELECTION = 100;
+    private static final int DIALOG_NETWORK_LIST_LOAD = 200;
+
+    private final ExecutorService mNetworkScanExecutor = Executors.newFixedThreadPool(1);
+
+    private List<CellInfo> mCellInfoList;
+    private CellInfo mCellInfo;
+
+    private int mSubId;
+    private TelephonyManager mTelephonyManager;
+    private NetworkScanHelper mNetworkScanHelper;
+    private NetworkOperators mNetworkOperators;
+    private List<String> mForbiddenPlmns;
+
+    private ProgressDialog mProgressDialog;
+    public NetworkSelectListPreference(Context context, AttributeSet attrs) {
+        super(context, attrs);
+    }
+
+    public NetworkSelectListPreference(Context context, AttributeSet attrs, int defStyleAttr,
+            int defStyleRes) {
+        super(context, attrs, defStyleAttr, defStyleRes);
+    }
+
+    @Override
+    protected void onClick() {
+        showProgressDialog(DIALOG_NETWORK_LIST_LOAD);
+        TelephonyManager telephonyManager = (TelephonyManager)
+                getContext().getSystemService(Context.TELEPHONY_SERVICE);
+        new AsyncTask<Void, Void, List<String>>() {
+            @Override
+            protected List<String> doInBackground(Void... voids) {
+                String[] forbiddenPlmns = telephonyManager.getForbiddenPlmns();
+                return forbiddenPlmns != null ? Arrays.asList(forbiddenPlmns) : null;
+            }
+
+            @Override
+            protected void onPostExecute(List<String> result) {
+                mForbiddenPlmns = result;
+                loadNetworksList();
+            }
+        }.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
+    }
+
+    private final Handler mHandler = new Handler() {
+        @Override
+        public void handleMessage(Message msg) {
+            switch (msg.what) {
+                case EVENT_MANUALLY_NETWORK_SELECTION_DONE:
+                    if (DBG) logd("hideProgressPanel");
+                    dismissProgressDialog();
+
+                    boolean isSuccessed = (boolean) msg.obj;
+                    if (isSuccessed) {
+                        if (DBG) {
+                            logd("manual network selection: succeeded! "
+                                    + getNetworkTitle(mCellInfo));
+                        }
+                        mNetworkOperators.displayNetworkSelectionSucceeded();
+                    } else {
+                        if (DBG) logd("manual network selection: failed!");
+                        mNetworkOperators.displayNetworkSelectionFailed();
+                    }
+                    mNetworkOperators.getNetworkSelectionMode();
+                    break;
+
+                case EVENT_NETWORK_SCAN_RESULTS:
+                    List<CellInfo> results = (List<CellInfo>) msg.obj;
+                    results.removeIf(cellInfo -> cellInfo == null);
+                    mCellInfoList = new ArrayList<>(results);
+                    if (DBG) logd("CALLBACK_SCAN_RESULTS" + mCellInfoList.toString());
+                    break;
+
+                case EVENT_NETWORK_SCAN_COMPLETED:
+                    if (DBG) logd("scan complete, load the cellInfosList");
+                    dismissProgressDialog();
+                    networksListLoaded();
+                    break;
+                case EVENT_NETWORK_SCAN_ERROR:
+                    dismissProgressDialog();
+                    displayNetworkQueryFailed();
+                    mNetworkOperators.getNetworkSelectionMode();
+                    break;
+            }
+            return;
+        }
+    };
+
+    private final NetworkScanHelper.NetworkScanCallback mCallback =
+            new NetworkScanHelper.NetworkScanCallback() {
+                public void onResults(List<CellInfo> results) {
+                    if (DBG) logd("get scan results: " + results.toString());
+                    Message msg = mHandler.obtainMessage(EVENT_NETWORK_SCAN_RESULTS, results);
+                    msg.sendToTarget();
+                }
+
+                public void onComplete() {
+                    if (DBG) logd("network scan completed.");
+                    Message msg = mHandler.obtainMessage(EVENT_NETWORK_SCAN_COMPLETED);
+                    msg.sendToTarget();
+                }
+
+                public void onError(int error) {
+                    if (DBG) logd("network scan error.");
+                    Message msg = mHandler.obtainMessage(EVENT_NETWORK_SCAN_ERROR);
+                    msg.sendToTarget();
+                }
+            };
+
+    @Override
+    //implemented for DialogInterface.OnCancelListener
+    public void onCancel(DialogInterface dialog) {
+        if (DBG) logd("user manually close the dialog");
+        mNetworkScanHelper.stopNetworkQuery();
+
+        // If cancelled, we query NetworkSelectMode and update states of AutoSelect button.
+        mNetworkOperators.getNetworkSelectionMode();
+    }
+
+    //TODO(b/114749736): move this logic to preference controller
+    protected void onDialogClosed(boolean positiveResult) {
+        // If dismissed, we query NetworkSelectMode and update states of AutoSelect button.
+        if (!positiveResult) {
+            mNetworkOperators.getNetworkSelectionMode();
+        }
+    }
+
+    // This initialize method needs to be called for this preference to work properly.
+    protected void initialize(int subId, NetworkOperators networkOperators,
+            ProgressDialog progressDialog) {
+        mSubId = subId;
+        mNetworkOperators = networkOperators;
+        // This preference should share the same progressDialog with networkOperators category.
+        mProgressDialog = progressDialog;
+
+        mTelephonyManager = TelephonyManager.from(getContext()).createForSubscriptionId(mSubId);
+        mNetworkScanHelper = new NetworkScanHelper(
+                mTelephonyManager, mCallback, mNetworkScanExecutor);
+
+        setSummary(mTelephonyManager.getNetworkOperatorName());
+
+        setOnPreferenceChangeListener(this);
+    }
+
+    @Override
+    protected void onPrepareForRemoval() {
+        destroy();
+        super.onPrepareForRemoval();
+    }
+
+    private void destroy() {
+        dismissProgressDialog();
+
+        if (mNetworkScanHelper != null) {
+            mNetworkScanHelper.stopNetworkQuery();
+        }
+
+        mNetworkScanExecutor.shutdown();
+    }
+
+    private void displayEmptyNetworkList() {
+        Toast.makeText(getContext(), R.string.empty_networks_list, Toast.LENGTH_LONG).show();
+    }
+
+    private void displayNetworkQueryFailed() {
+        Toast.makeText(getContext(), R.string.network_query_error, Toast.LENGTH_LONG).show();
+    }
+
+    private void loadNetworksList() {
+        if (DBG) logd("load networks list...");
+        mNetworkScanHelper.startNetworkScan(
+                NetworkScanHelper.NETWORK_SCAN_TYPE_WAIT_FOR_ALL_RESULTS);
+    }
+
+    private void networksListLoaded() {
+        if (DBG) logd("networks list loaded");
+
+        mNetworkOperators.getNetworkSelectionMode();
+        if (mCellInfoList != null) {
+            // create a preference for each item in the list.
+            // just use the operator name instead of the mildly
+            // confusing mcc/mnc.
+            List<CharSequence> networkEntriesList = new ArrayList<>();
+            List<CharSequence> networkEntryValuesList = new ArrayList<>();
+            for (CellInfo cellInfo: mCellInfoList) {
+                // Display each operator name only once.
+                String networkTitle = getNetworkTitle(cellInfo);
+                if (CellInfoUtil.isForbidden(cellInfo, mForbiddenPlmns)) {
+                    networkTitle += " "
+                            + getContext().getResources().getString(R.string.forbidden_network);
+                }
+                networkEntriesList.add(networkTitle);
+                networkEntryValuesList.add(getOperatorNumeric(cellInfo));
+            }
+            setEntries(networkEntriesList.toArray(new CharSequence[networkEntriesList.size()]));
+            setEntryValues(networkEntryValuesList.toArray(
+                    new CharSequence[networkEntryValuesList.size()]));
+
+            super.onClick();
+        } else {
+            displayEmptyNetworkList();
+        }
+    }
+
+    private void dismissProgressDialog() {
+        if (mProgressDialog != null && mProgressDialog.isShowing()) {
+            try {
+                mProgressDialog.dismiss();
+            } catch (IllegalArgumentException ex) {
+                loge("Can't close the progress dialog " + ex);
+            }
+        }
+    }
+
+    private void showProgressDialog(int id) {
+        if (mProgressDialog == null) {
+            mProgressDialog = new ProgressDialog(getContext());
+        } else {
+            // Dismiss progress bar if it's showing now.
+            dismissProgressDialog();
+        }
+
+        switch (id) {
+            case DIALOG_NETWORK_SELECTION:
+                final String networkSelectMsg = getContext().getResources()
+                        .getString(R.string.register_on_network,
+                                getNetworkTitle(mCellInfo));
+                mProgressDialog.setMessage(networkSelectMsg);
+                mProgressDialog.setCanceledOnTouchOutside(false);
+                mProgressDialog.setCancelable(false);
+                mProgressDialog.setIndeterminate(true);
+                break;
+            case DIALOG_NETWORK_LIST_LOAD:
+                mProgressDialog.setMessage(
+                        getContext().getResources().getString(R.string.load_networks_progress));
+                mProgressDialog.setCanceledOnTouchOutside(false);
+                mProgressDialog.setCancelable(true);
+                mProgressDialog.setIndeterminate(false);
+                mProgressDialog.setOnCancelListener(this);
+                break;
+            default:
+        }
+        mProgressDialog.show();
+    }
+
+    /**
+     * Implemented to support onPreferenceChangeListener to look for preference
+     * changes specifically on this button.
+     *
+     * @param preference is the preference to be changed, should be network select button.
+     * @param newValue should be the value of the selection as index of operators.
+     */
+    @Override
+    public boolean onPreferenceChange(Preference preference, Object newValue) {
+        int operatorIndex = findIndexOfValue((String) newValue);
+        mCellInfo = mCellInfoList.get(operatorIndex);
+        if (DBG) logd("selected network: " + mCellInfo.toString());
+
+        MetricsLogger.action(getContext(),
+                MetricsEvent.ACTION_MOBILE_NETWORK_MANUAL_SELECT_NETWORK);
+
+        if (SubscriptionManager.isValidSubscriptionId(mSubId)) {
+            ThreadUtils.postOnBackgroundThread(() -> {
+                final OperatorInfo operatorInfo = getOperatorInfoFromCellInfo(mCellInfo);
+                if (DBG) logd("manually selected network: " + operatorInfo.toString());
+                boolean isSuccessed = mTelephonyManager.setNetworkSelectionModeManual(
+                        operatorInfo, true /* persistSelection */);
+                Message msg = mHandler.obtainMessage(EVENT_MANUALLY_NETWORK_SELECTION_DONE);
+                msg.obj = isSuccessed;
+                msg.sendToTarget();
+            });
+        } else {
+            loge("Error selecting network, subscription Id is invalid " + mSubId);
+        }
+
+        return true;
+    }
+
+    /**
+     * Returns the title of the network obtained in the manual search.
+     *
+     * @param cellInfo contains the information of the network.
+     * @return Long Name if not null/empty, otherwise Short Name if not null/empty,
+     * else MCCMNC string.
+     */
+    private String getNetworkTitle(CellInfo cellInfo) {
+        OperatorInfo ni = getOperatorInfoFromCellInfo(cellInfo);
+
+        if (!TextUtils.isEmpty(ni.getOperatorAlphaLong())) {
+            return ni.getOperatorAlphaLong();
+        } else if (!TextUtils.isEmpty(ni.getOperatorAlphaShort())) {
+            return ni.getOperatorAlphaShort();
+        } else {
+            BidiFormatter bidiFormatter = BidiFormatter.getInstance();
+            return bidiFormatter.unicodeWrap(ni.getOperatorNumeric(), TextDirectionHeuristics.LTR);
+        }
+    }
+
+    /**
+     * Returns the operator numeric (MCCMNC) obtained in the manual search.
+     *
+     * @param cellInfo contains the information of the network.
+     * @return MCCMNC string.
+     */
+    private String getOperatorNumeric(CellInfo cellInfo) {
+        return getOperatorInfoFromCellInfo(cellInfo).getOperatorNumeric();
+    }
+
+    /**
+     * Wrap a cell info into an operator info.
+     */
+    private OperatorInfo getOperatorInfoFromCellInfo(CellInfo cellInfo) {
+        OperatorInfo oi;
+        if (cellInfo instanceof CellInfoLte) {
+            CellInfoLte lte = (CellInfoLte) cellInfo;
+            oi = new OperatorInfo(
+                    (String) lte.getCellIdentity().getOperatorAlphaLong(),
+                    (String) lte.getCellIdentity().getOperatorAlphaShort(),
+                    lte.getCellIdentity().getMobileNetworkOperator());
+        } else if (cellInfo instanceof CellInfoWcdma) {
+            CellInfoWcdma wcdma = (CellInfoWcdma) cellInfo;
+            oi = new OperatorInfo(
+                    (String) wcdma.getCellIdentity().getOperatorAlphaLong(),
+                    (String) wcdma.getCellIdentity().getOperatorAlphaShort(),
+                    wcdma.getCellIdentity().getMobileNetworkOperator());
+        } else if (cellInfo instanceof CellInfoGsm) {
+            CellInfoGsm gsm = (CellInfoGsm) cellInfo;
+            oi = new OperatorInfo(
+                    (String) gsm.getCellIdentity().getOperatorAlphaLong(),
+                    (String) gsm.getCellIdentity().getOperatorAlphaShort(),
+                    gsm.getCellIdentity().getMobileNetworkOperator());
+        } else if (cellInfo instanceof CellInfoCdma) {
+            CellInfoCdma cdma = (CellInfoCdma) cellInfo;
+            oi = new OperatorInfo(
+                    (String) cdma.getCellIdentity().getOperatorAlphaLong(),
+                    (String) cdma.getCellIdentity().getOperatorAlphaShort(),
+                    "" /* operator numeric */);
+        } else {
+            oi = new OperatorInfo("", "", "");
+        }
+        return oi;
+    }
+
+    @Override
+    protected Parcelable onSaveInstanceState() {
+        final Parcelable superState = super.onSaveInstanceState();
+        if (isPersistent()) {
+            // No need to save instance state since it's persistent
+            return superState;
+        }
+
+        final SavedState myState = new SavedState(superState);
+        myState.mDialogListEntries = getEntries();
+        myState.mDialogListEntryValues = getEntryValues();
+        myState.mCellInfoList = mCellInfoList;
+        return myState;
+    }
+
+    @Override
+    protected void onRestoreInstanceState(Parcelable state) {
+        if (state == null || !state.getClass().equals(SavedState.class)) {
+            // Didn't save state for us in onSaveInstanceState
+            super.onRestoreInstanceState(state);
+            return;
+        }
+
+        SavedState myState = (SavedState) state;
+
+        if (getEntries() == null && myState.mDialogListEntries != null) {
+            setEntries(myState.mDialogListEntries);
+        }
+        if (getEntryValues() == null && myState.mDialogListEntryValues != null) {
+            setEntryValues(myState.mDialogListEntryValues);
+        }
+        if (mCellInfoList == null && myState.mCellInfoList != null) {
+            mCellInfoList = myState.mCellInfoList;
+        }
+
+        super.onRestoreInstanceState(myState.getSuperState());
+    }
+
+    /**
+     *  We save entries, entryValues and operatorInfoList into bundle.
+     *  At onCreate of fragment, dialog will be restored if it was open. In this case,
+     *  we need to restore entries, entryValues and operatorInfoList. Without those information,
+     *  onPreferenceChange will fail if user select network from the dialog.
+     */
+    private static class SavedState extends BaseSavedState {
+        CharSequence[] mDialogListEntries;
+        CharSequence[] mDialogListEntryValues;
+        List<CellInfo> mCellInfoList;
+
+        SavedState(Parcel source) {
+            super(source);
+            final ClassLoader boot = Object.class.getClassLoader();
+            mDialogListEntries = source.readCharSequenceArray();
+            mDialogListEntryValues = source.readCharSequenceArray();
+            mCellInfoList = source.readParcelableList(mCellInfoList, boot);
+        }
+
+        @Override
+        public void writeToParcel(Parcel dest, int flags) {
+            super.writeToParcel(dest, flags);
+            dest.writeCharSequenceArray(mDialogListEntries);
+            dest.writeCharSequenceArray(mDialogListEntryValues);
+            dest.writeParcelableList(mCellInfoList, flags);
+        }
+
+        SavedState(Parcelable superState) {
+            super(superState);
+        }
+
+        public static final Parcelable.Creator<SavedState> CREATOR =
+                new Parcelable.Creator<SavedState>() {
+                    public SavedState createFromParcel(Parcel in) {
+                        return new SavedState(in);
+                    }
+
+                    public SavedState[] newArray(int size) {
+                        return new SavedState[size];
+                    }
+                };
+    }
+
+    private void logd(String msg) {
+        Log.d(LOG_TAG, "[NetworksList] " + msg);
+    }
+
+    private void loge(String msg) {
+        Log.e(LOG_TAG, "[NetworksList] " + msg);
+    }
+}
\ No newline at end of file
diff --git a/src/com/android/settings/mobilenetwork/NetworkSelectSettings.java b/src/com/android/settings/mobilenetwork/NetworkSelectSettings.java
index f04eae7..20cc628 100644
--- a/src/com/android/settings/mobilenetwork/NetworkSelectSettings.java
+++ b/src/com/android/settings/mobilenetwork/NetworkSelectSettings.java
@@ -31,6 +31,10 @@
 import android.util.Log;
 import android.view.View;
 
+import androidx.preference.Preference;
+import androidx.preference.PreferenceCategory;
+import androidx.preference.PreferenceScreen;
+
 import com.android.internal.logging.MetricsLogger;
 import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
 import com.android.internal.telephony.OperatorInfo;
@@ -47,10 +51,6 @@
 import java.util.List;
 import java.util.Map;
 
-import androidx.preference.Preference;
-import androidx.preference.PreferenceCategory;
-import androidx.preference.PreferenceScreen;
-
 /**
  * "Choose network" settings UI for the Phone app.
  */
diff --git a/src/com/android/settings/mobilenetwork/RoamingDialogFragment.java b/src/com/android/settings/mobilenetwork/RoamingDialogFragment.java
new file mode 100644
index 0000000..6f71d9c
--- /dev/null
+++ b/src/com/android/settings/mobilenetwork/RoamingDialogFragment.java
@@ -0,0 +1,103 @@
+/*
+ * 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.mobilenetwork;
+
+import android.app.AlertDialog;
+import android.app.Dialog;
+import android.content.Context;
+import android.content.DialogInterface;
+import android.content.DialogInterface.OnClickListener;
+import android.os.Bundle;
+import android.os.PersistableBundle;
+import android.telephony.CarrierConfigManager;
+
+import androidx.fragment.app.DialogFragment;
+import androidx.fragment.app.Fragment;
+import androidx.fragment.app.FragmentManager;
+
+
+import com.android.settings.R;
+import com.android.settings.core.instrumentation.InstrumentedDialogFragment;
+
+/**
+ * A dialog fragment that asks the user if they are sure they want to turn on data roaming
+ * to avoid accidental charges.
+ */
+public class RoamingDialogFragment extends InstrumentedDialogFragment implements OnClickListener {
+
+    public static final String SUB_ID_KEY = "sub_id_key";
+
+    private CarrierConfigManager mCarrierConfigManager;
+    private int mSubId;
+
+    /**
+     * The interface we expect a host activity to implement.
+     */
+    public interface RoamingDialogListener {
+        void onPositiveButtonClick(DialogFragment dialog);
+    }
+
+    // the host activity which implements the listening interface
+    private RoamingDialogListener mListener;
+
+    @Override
+    public void onAttach(Context context) {
+        super.onAttach(context);
+        Bundle args = getArguments();
+        mSubId = args.getInt(SUB_ID_KEY);
+        mCarrierConfigManager = new CarrierConfigManager(context);
+
+        //TODO(b/114749736): set target fragment in host fragment
+        Fragment fragment = getTargetFragment();
+        try {
+            mListener = (RoamingDialogListener) fragment;
+        } catch (ClassCastException e) {
+            throw new ClassCastException(fragment.toString() +
+                    "must implement RoamingDialogListener");
+        }
+    }
+
+    @Override
+    public Dialog onCreateDialog(Bundle savedInstanceState) {
+        AlertDialog.Builder builder = new AlertDialog.Builder(getContext());
+        int title = R.string.roaming_alert_title;
+        PersistableBundle carrierConfig = mCarrierConfigManager.getConfigForSubId(mSubId);
+        if (carrierConfig != null && carrierConfig.getBoolean(
+                CarrierConfigManager.KEY_CHECK_PRICING_WITH_CARRIER_FOR_DATA_ROAMING_BOOL)) {
+            title = R.string.roaming_check_price_warning;
+        }
+        builder.setMessage(getResources().getString(R.string.roaming_warning))
+                .setTitle(title)
+                .setIconAttribute(android.R.attr.alertDialogIcon)
+                .setPositiveButton(android.R.string.yes, this)
+                .setNegativeButton(android.R.string.no, this);
+        return builder.create();
+    }
+
+    @Override
+    public int getMetricsCategory() {
+        //TODO(b/114749736): add category for roaming dialog
+        return 0;
+    }
+
+    @Override
+    public void onClick(DialogInterface dialog, int which) {
+        // let the host know that the positive button has been clicked
+        if (which == dialog.BUTTON_POSITIVE) {
+            mListener.onPositiveButtonClick(this);
+        }
+    }
+}
diff --git a/src/com/android/settings/network/MobileNetworkPreferenceController.java b/src/com/android/settings/network/MobileNetworkPreferenceController.java
index 4230c67..c0e6e1c 100644
--- a/src/com/android/settings/network/MobileNetworkPreferenceController.java
+++ b/src/com/android/settings/network/MobileNetworkPreferenceController.java
@@ -36,6 +36,7 @@
 
 import com.android.settings.core.FeatureFlags;
 import com.android.settings.core.PreferenceControllerMixin;
+import com.android.settings.mobilenetwork.MobileSettingsActivity;
 import com.android.settingslib.RestrictedLockUtilsInternal;
 import com.android.settingslib.RestrictedPreference;
 import com.android.settingslib.Utils;
@@ -146,7 +147,8 @@
     public boolean handlePreferenceTreeClick(Preference preference) {
         if (KEY_MOBILE_NETWORK_SETTINGS.equals(preference.getKey())) {
             if (FeatureFlagUtils.isEnabled(mContext, FeatureFlags.MOBILE_NETWORK_V2)) {
-                //TODO(b/110260193): go to the mobile network page existed in settings
+                final Intent intent = new Intent(mContext, MobileSettingsActivity.class);
+                mContext.startActivity(intent);
             } else {
                 final Intent intent = new Intent(Intent.ACTION_MAIN);
                 intent.setComponent(
diff --git a/src/com/android/settings/overlay/FeatureFactory.java b/src/com/android/settings/overlay/FeatureFactory.java
index ef8d1ee..38d48c8 100644
--- a/src/com/android/settings/overlay/FeatureFactory.java
+++ b/src/com/android/settings/overlay/FeatureFactory.java
@@ -29,7 +29,6 @@
 import com.android.settings.fuelgauge.PowerUsageFeatureProvider;
 import com.android.settings.gestures.AssistGestureFeatureProvider;
 import com.android.settings.localepicker.LocaleFeatureProvider;
-import com.android.settings.search.DeviceIndexFeatureProvider;
 import com.android.settings.search.SearchFeatureProvider;
 import com.android.settings.security.SecurityFeatureProvider;
 import com.android.settings.slices.SlicesFeatureProvider;
@@ -106,8 +105,6 @@
 
     public abstract AccountFeatureProvider getAccountFeatureProvider();
 
-    public abstract DeviceIndexFeatureProvider getDeviceIndexFeatureProvider();
-
     public static final class FactoryNotFoundException extends RuntimeException {
         public FactoryNotFoundException(Throwable throwable) {
             super("Unable to create factory. Did you misconfigure Proguard?", throwable);
diff --git a/src/com/android/settings/overlay/FeatureFactoryImpl.java b/src/com/android/settings/overlay/FeatureFactoryImpl.java
index 61be109..1f57529 100644
--- a/src/com/android/settings/overlay/FeatureFactoryImpl.java
+++ b/src/com/android/settings/overlay/FeatureFactoryImpl.java
@@ -41,8 +41,6 @@
 import com.android.settings.gestures.AssistGestureFeatureProviderImpl;
 import com.android.settings.localepicker.LocaleFeatureProvider;
 import com.android.settings.localepicker.LocaleFeatureProviderImpl;
-import com.android.settings.search.DeviceIndexFeatureProvider;
-import com.android.settings.search.DeviceIndexFeatureProviderImpl;
 import com.android.settings.search.SearchFeatureProvider;
 import com.android.settings.search.SearchFeatureProviderImpl;
 import com.android.settings.security.SecurityFeatureProvider;
@@ -73,7 +71,6 @@
     private UserFeatureProvider mUserFeatureProvider;
     private SlicesFeatureProvider mSlicesFeatureProvider;
     private AccountFeatureProvider mAccountFeatureProvider;
-    private DeviceIndexFeatureProviderImpl mDeviceIndexFeatureProvider;
 
     @Override
     public SupportFeatureProvider getSupportFeatureProvider(Context context) {
@@ -211,12 +208,4 @@
         }
         return mAccountFeatureProvider;
     }
-
-    @Override
-    public DeviceIndexFeatureProvider getDeviceIndexFeatureProvider() {
-        if (mDeviceIndexFeatureProvider == null) {
-            mDeviceIndexFeatureProvider = new DeviceIndexFeatureProviderImpl();
-        }
-        return mDeviceIndexFeatureProvider;
-    }
 }
diff --git a/src/com/android/settings/search/DeviceIndexFeatureProvider.java b/src/com/android/settings/search/DeviceIndexFeatureProvider.java
deleted file mode 100644
index f777f71..0000000
--- a/src/com/android/settings/search/DeviceIndexFeatureProvider.java
+++ /dev/null
@@ -1,136 +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.search;
-
-import static com.android.settings.slices.SliceDeepLinkSpringBoard.INTENT;
-import static com.android.settings.slices.SliceDeepLinkSpringBoard.SETTINGS;
-
-import android.app.job.JobInfo;
-import android.app.job.JobScheduler;
-import android.content.ComponentName;
-import android.content.Context;
-import android.content.pm.PackageManager;
-import android.content.pm.ServiceInfo;
-import android.net.Uri;
-import android.os.Binder;
-import android.os.Build;
-import android.provider.Settings;
-import android.text.TextUtils;
-import android.util.Log;
-
-import com.android.settings.R;
-import com.android.settings.Utils;
-import com.android.settings.slices.SettingsSliceProvider;
-
-import java.util.List;
-import java.util.Locale;
-
-public interface DeviceIndexFeatureProvider {
-
-    String TAG = "DeviceIndex";
-
-    String INDEX_VERSION = "settings:index_version";
-    String INDEX_LANGUAGE = "settings:language";
-
-    // Increment when new items are added to ensure they get pushed to the device index.
-    String VERSION = Build.FINGERPRINT;
-
-    // When the device language changes, re-index so Slices trigger in device language.
-    Locale LANGUAGE = Locale.getDefault();
-
-    default boolean isIndexingEnabled() {
-        return false;
-    }
-
-    void index(Context context, CharSequence title, Uri sliceUri, Uri launchUri,
-            List<String> keywords);
-
-    void clearIndex(Context context);
-
-    default void updateIndex(Context context, boolean force) {
-        if (!isIndexingEnabled()) {
-            Log.i(TAG, "Skipping: device index is not enabled");
-            return;
-        }
-
-        if (!Utils.isDeviceProvisioned(context)) {
-            Log.w(TAG, "Skipping: device is not provisioned");
-            return;
-        }
-
-        final ComponentName jobComponent = new ComponentName(context.getPackageName(),
-                DeviceIndexUpdateJobService.class.getName());
-
-        try {
-            final int callerUid = Binder.getCallingUid();
-            final ServiceInfo si = context.getPackageManager().getServiceInfo(jobComponent,
-                    PackageManager.MATCH_DIRECT_BOOT_AWARE
-                            | PackageManager.MATCH_DIRECT_BOOT_UNAWARE);
-            if (si == null) {
-                Log.w(TAG, "Skipping: No such service " + jobComponent);
-                return;
-            }
-            if (si.applicationInfo.uid != callerUid) {
-                Log.w(TAG, "Skipping: Uid cannot schedule DeviceIndexUpdate: " + callerUid);
-                return;
-            }
-        } catch (PackageManager.NameNotFoundException e) {
-            Log.w(TAG, "Skipping: error finding DeviceIndexUpdateJobService from packageManager");
-            return;
-        }
-
-        if (!force && skipIndex(context)) {
-            Log.i(TAG, "Skipping: already indexed.");
-            // No need to update.
-            return;
-        }
-
-        // Prevent scheduling multiple jobs
-        setIndexState(context);
-
-        final int jobId = context.getResources().getInteger(R.integer.device_index_update);
-        // Schedule a job so that we know it'll be able to complete, but try to run as
-        // soon as possible.
-        context.getSystemService(JobScheduler.class).schedule(
-                new JobInfo.Builder(jobId, jobComponent)
-                        .setPersisted(false)
-                        .setMinimumLatency(1000)
-                        .setOverrideDeadline(1)
-                        .build());
-
-    }
-
-    static Uri createDeepLink(String s) {
-        return new Uri.Builder().scheme(SETTINGS)
-                .authority(SettingsSliceProvider.SLICE_AUTHORITY)
-                .appendQueryParameter(INTENT, s)
-                .build();
-    }
-
-    static boolean skipIndex(Context context) {
-        final boolean isSameVersion = TextUtils.equals(
-                Settings.Secure.getString(context.getContentResolver(), INDEX_VERSION), VERSION);
-        final boolean isSameLanguage = TextUtils.equals(
-                Settings.Secure.getString(context.getContentResolver(), INDEX_LANGUAGE),
-                LANGUAGE.toString());
-        return isSameLanguage && isSameVersion;
-    }
-
-    static void setIndexState(Context context) {
-        Settings.Secure.putString(context.getContentResolver(), INDEX_VERSION, VERSION);
-        Settings.Secure.putString(context.getContentResolver(), INDEX_LANGUAGE,
-                LANGUAGE.toString());
-    }
-}
diff --git a/src/com/android/settings/search/DeviceIndexFeatureProviderImpl.java b/src/com/android/settings/search/DeviceIndexFeatureProviderImpl.java
deleted file mode 100644
index 8fd1606..0000000
--- a/src/com/android/settings/search/DeviceIndexFeatureProviderImpl.java
+++ /dev/null
@@ -1,34 +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.search;
-
-import android.content.Context;
-import android.net.Uri;
-
-import java.util.List;
-
-public class DeviceIndexFeatureProviderImpl implements DeviceIndexFeatureProvider {
-
-    @Override
-    public void index(Context context, CharSequence title, Uri sliceUri, Uri launchUri,
-            List<String> keywords) {
-        // Not enabled by default.
-    }
-
-    @Override
-    public void clearIndex(Context context) {
-        // Not enabled by default.
-    }
-}
diff --git a/src/com/android/settings/search/DeviceIndexUpdateJobService.java b/src/com/android/settings/search/DeviceIndexUpdateJobService.java
deleted file mode 100644
index 1f7ee31..0000000
--- a/src/com/android/settings/search/DeviceIndexUpdateJobService.java
+++ /dev/null
@@ -1,192 +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.search;
-
-import static android.app.slice.Slice.HINT_LARGE;
-import static android.app.slice.Slice.HINT_TITLE;
-import static android.app.slice.SliceItem.FORMAT_TEXT;
-
-import static com.android.settings.search.DeviceIndexFeatureProvider.createDeepLink;
-
-import android.app.job.JobParameters;
-import android.app.job.JobService;
-import android.content.ContentResolver;
-import android.content.Intent;
-import android.net.Uri;
-import android.net.Uri.Builder;
-import android.provider.SettingsSlicesContract;
-import android.util.Log;
-
-import androidx.annotation.VisibleForTesting;
-import androidx.slice.Slice;
-import androidx.slice.SliceItem;
-import androidx.slice.SliceMetadata;
-import androidx.slice.SliceViewManager;
-import androidx.slice.SliceViewManager.SliceCallback;
-import androidx.slice.core.SliceQuery;
-import androidx.slice.widget.ListContent;
-import androidx.slice.widget.SliceContent;
-
-import com.android.settings.overlay.FeatureFactory;
-import com.android.settings.slices.SettingsSliceProvider;
-import com.android.settings.slices.SliceDeepLinkSpringBoard;
-
-import java.util.Collection;
-import java.util.concurrent.CountDownLatch;
-
-public class DeviceIndexUpdateJobService extends JobService {
-
-    private static final String TAG = "DeviceIndexUpdate";
-    private static final boolean DEBUG = false;
-    @VisibleForTesting
-    protected boolean mRunningJob;
-
-    @Override
-    public boolean onStartJob(JobParameters params) {
-        if (DEBUG) Log.d(TAG, "onStartJob");
-        if (!mRunningJob) {
-            mRunningJob = true;
-            Thread thread = new Thread(() -> updateIndex(params));
-            thread.setPriority(Thread.MIN_PRIORITY);
-            thread.start();
-        }
-        return true;
-    }
-
-    @Override
-    public boolean onStopJob(JobParameters params) {
-        if (DEBUG) Log.d(TAG, "onStopJob " + mRunningJob);
-        if (mRunningJob) {
-            mRunningJob = false;
-            return true;
-        }
-        return false;
-    }
-
-    @VisibleForTesting
-    protected void updateIndex(JobParameters params) {
-        if (DEBUG) {
-            Log.d(TAG, "Starting index");
-        }
-        final DeviceIndexFeatureProvider indexProvider = FeatureFactory.getFactory(this)
-                .getDeviceIndexFeatureProvider();
-        final SliceViewManager manager = getSliceViewManager();
-        final Uri baseUri = new Builder()
-                .scheme(ContentResolver.SCHEME_CONTENT)
-                .authority(SettingsSliceProvider.SLICE_AUTHORITY)
-                .build();
-        final Uri platformBaseUri = new Builder()
-                .scheme(ContentResolver.SCHEME_CONTENT)
-                .authority(SettingsSlicesContract.AUTHORITY)
-                .build();
-        final Collection<Uri> slices = manager.getSliceDescendants(baseUri);
-        slices.addAll(manager.getSliceDescendants(platformBaseUri));
-
-        if (DEBUG) {
-            Log.d(TAG, "Indexing " + slices.size() + " slices");
-        }
-
-        indexProvider.clearIndex(this /* context */);
-
-        for (Uri slice : slices) {
-            if (!mRunningJob) {
-                return;
-            }
-            Slice loadedSlice = bindSliceSynchronous(manager, slice);
-            // TODO: Get Title APIs on SliceMetadata and use that.
-            SliceMetadata metaData = getMetadata(loadedSlice);
-            CharSequence title = findTitle(loadedSlice, metaData);
-            if (title != null) {
-                if (DEBUG) {
-                    Log.d(TAG, "Indexing: " + slice + " " + title + " " + loadedSlice);
-                }
-                indexProvider.index(this, title, slice, createDeepLink(
-                        new Intent(SliceDeepLinkSpringBoard.ACTION_VIEW_SLICE)
-                                .setPackage(getPackageName())
-                                .putExtra(SliceDeepLinkSpringBoard.EXTRA_SLICE, slice.toString())
-                                .toUri(Intent.URI_ANDROID_APP_SCHEME)),
-                        metaData.getSliceKeywords());
-            }
-        }
-        if (DEBUG) {
-            Log.d(TAG, "Done indexing");
-        }
-        jobFinished(params, false);
-    }
-
-    protected SliceViewManager getSliceViewManager() {
-        return SliceViewManager.getInstance(this);
-    }
-
-    protected SliceMetadata getMetadata(Slice loadedSlice) {
-        return SliceMetadata.from(this, loadedSlice);
-    }
-
-    protected CharSequence findTitle(Slice loadedSlice, SliceMetadata metaData) {
-        ListContent content = new ListContent(null, loadedSlice);
-        SliceContent headerItem = content.getHeader();
-        if (headerItem == null) {
-            if (content.getRowItems().size() != 0) {
-                headerItem = content.getRowItems().get(0);
-            } else {
-                return null;
-            }
-        }
-        // Look for a title, then large text, then any text at all.
-        SliceItem title = SliceQuery.find(headerItem.getSliceItem(), FORMAT_TEXT, HINT_TITLE, null);
-        if (title != null) {
-            return title.getText();
-        }
-        title = SliceQuery.find(headerItem.getSliceItem(), FORMAT_TEXT, HINT_LARGE, null);
-        if (title != null) {
-            return title.getText();
-        }
-        title = SliceQuery.find(headerItem.getSliceItem(), FORMAT_TEXT);
-        if (title != null) {
-            return title.getText();
-        }
-        return null;
-    }
-
-    protected Slice bindSliceSynchronous(SliceViewManager manager, Uri slice) {
-        final Slice[] returnSlice = new Slice[1];
-        CountDownLatch latch = new CountDownLatch(1);
-        SliceCallback callback = new SliceCallback() {
-            @Override
-            public void onSliceUpdated(Slice s) {
-                try {
-                    SliceMetadata m = SliceMetadata.from(DeviceIndexUpdateJobService.this, s);
-                    if (m.getLoadingState() == SliceMetadata.LOADED_ALL) {
-                        returnSlice[0] = s;
-                        latch.countDown();
-                        manager.unregisterSliceCallback(slice, this);
-                    }
-                } catch (Exception e) {
-                    Log.w(TAG, slice + " cannot be indexed", e);
-                    returnSlice[0] = s;
-                }
-            }
-        };
-        // Register a callback until we get a loaded slice.
-        manager.registerSliceCallback(slice, callback);
-        // Trigger the first bind in case no loading is needed.
-        callback.onSliceUpdated(manager.bindSlice(slice));
-        try {
-            latch.await();
-        } catch (InterruptedException e) {
-        }
-        return returnSlice[0];
-    }
-}
diff --git a/src/com/android/settings/search/SearchFeatureProvider.java b/src/com/android/settings/search/SearchFeatureProvider.java
index ed26931..caddb1f 100644
--- a/src/com/android/settings/search/SearchFeatureProvider.java
+++ b/src/com/android/settings/search/SearchFeatureProvider.java
@@ -23,6 +23,7 @@
 import android.content.Intent;
 import android.view.View;
 
+import com.android.internal.logging.nano.MetricsProto;
 import com.android.settings.overlay.FeatureFactory;
 import com.android.settingslib.search.SearchIndexableResources;
 
@@ -63,10 +64,12 @@
         view.setOnClickListener(tb -> {
             final Intent intent = SEARCH_UI_INTENT;
             intent.setPackage(getSettingsIntelligencePkgName());
+            final Context context = activity.getApplicationContext();
 
-            FeatureFactory.getFactory(
-                    activity.getApplicationContext()).getSlicesFeatureProvider()
+            FeatureFactory.getFactory(context).getSlicesFeatureProvider()
                     .indexSliceDataAsync(activity.getApplicationContext());
+            FeatureFactory.getFactory(context).getMetricsFeatureProvider()
+                    .action(context, MetricsProto.MetricsEvent.ACTION_SEARCH_RESULTS);
             activity.startActivityForResult(intent, REQUEST_CODE);
         });
     }
diff --git a/src/com/android/settings/search/actionbar/SearchMenuController.java b/src/com/android/settings/search/actionbar/SearchMenuController.java
index 6855717..81e9e60 100644
--- a/src/com/android/settings/search/actionbar/SearchMenuController.java
+++ b/src/com/android/settings/search/actionbar/SearchMenuController.java
@@ -17,6 +17,7 @@
 package com.android.settings.search.actionbar;
 
 import android.annotation.NonNull;
+import android.content.Context;
 import android.content.Intent;
 import android.os.Bundle;
 import android.view.Menu;
@@ -25,6 +26,7 @@
 
 import androidx.fragment.app.Fragment;
 
+import com.android.internal.logging.nano.MetricsProto;
 import com.android.settings.R;
 import com.android.settings.Utils;
 import com.android.settings.overlay.FeatureFactory;
@@ -70,10 +72,12 @@
         searchItem.setShowAsAction(MenuItem.SHOW_AS_ACTION_ALWAYS);
 
         searchItem.setOnMenuItemClickListener(target -> {
+            final Context context = mHost.getContext();
             final Intent intent = SearchFeatureProvider.SEARCH_UI_INTENT;
             intent.setPackage(FeatureFactory.getFactory(mHost.getContext())
                     .getSearchFeatureProvider().getSettingsIntelligencePkgName());
-
+            FeatureFactory.getFactory(context).getMetricsFeatureProvider()
+                    .action(context, MetricsProto.MetricsEvent.ACTION_SEARCH_RESULTS);
             mHost.startActivityForResult(intent, 0 /* requestCode */);
             return true;
         });
diff --git a/src/com/android/settings/slices/SliceDeepLinkSpringBoard.java b/src/com/android/settings/slices/SliceDeepLinkSpringBoard.java
index 5d36d73..7531778 100644
--- a/src/com/android/settings/slices/SliceDeepLinkSpringBoard.java
+++ b/src/com/android/settings/slices/SliceDeepLinkSpringBoard.java
@@ -21,6 +21,8 @@
 import android.provider.Settings;
 import android.util.Log;
 
+import androidx.annotation.Keep;
+
 import com.android.settings.bluetooth.BluetoothSliceBuilder;
 import com.android.settings.location.LocationSliceBuilder;
 import com.android.settings.notification.ZenModeSliceBuilder;
@@ -90,6 +92,14 @@
         }
     }
 
+    @Keep
+    public static Uri createDeepLink(String s) {
+        return new Uri.Builder().scheme(SETTINGS)
+                .authority(SettingsSliceProvider.SLICE_AUTHORITY)
+                .appendQueryParameter(INTENT, s)
+                .build();
+    }
+
     public static Intent parse(Uri uri, String pkg) throws URISyntaxException {
         Intent intent = Intent.parseUri(uri.getQueryParameter(INTENT),
                 Intent.URI_ANDROID_APP_SCHEME);
diff --git a/tests/robotests/src/com/android/settings/mobilenetwork/MobileSettingsActivityTest.java b/tests/robotests/src/com/android/settings/mobilenetwork/MobileSettingsActivityTest.java
new file mode 100644
index 0000000..cb86d6f
--- /dev/null
+++ b/tests/robotests/src/com/android/settings/mobilenetwork/MobileSettingsActivityTest.java
@@ -0,0 +1,140 @@
+/*
+ * 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.mobilenetwork;
+
+import static com.android.settings.mobilenetwork.MobileSettingsActivity.MOBILE_SETTINGS_TAG;
+
+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.telephony.SubscriptionInfo;
+import android.telephony.SubscriptionManager;
+import android.view.Menu;
+import android.view.View;
+
+import com.android.internal.view.menu.ContextMenuBuilder;
+import com.android.settings.R;
+import com.android.settings.testutils.SettingsRobolectricTestRunner;
+
+import com.google.android.material.bottomnavigation.BottomNavigationView;
+
+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;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import androidx.fragment.app.Fragment;
+import androidx.fragment.app.FragmentManager;
+import androidx.fragment.app.FragmentTransaction;
+
+@RunWith(SettingsRobolectricTestRunner.class)
+public class MobileSettingsActivityTest {
+
+    private static final int CURRENT_SUB_ID = 3;
+    private static final int PREV_SUB_ID = 1;
+
+    private Context mContext;
+    private MobileSettingsActivity mMobileSettingsActivity;
+    private List<SubscriptionInfo> mSubscriptionInfos;
+    private Fragment mShowFragment;
+    private Fragment mHideFragment;
+
+    @Mock
+    private SubscriptionManager mSubscriptionManager;
+    @Mock
+    private SubscriptionInfo mSubscriptionInfo;
+    @Mock
+    private FragmentManager mFragmentManager;
+    @Mock
+    private FragmentTransaction mFragmentTransaction;
+    @Mock
+    private BottomNavigationView mBottomNavigationView;
+
+    @Before
+    public void setUp() {
+        MockitoAnnotations.initMocks(this);
+        mContext = spy(RuntimeEnvironment.application);
+
+        mMobileSettingsActivity = spy(new MobileSettingsActivity());
+        mSubscriptionInfos = new ArrayList<>();
+        mShowFragment = new Fragment();
+        mHideFragment = new Fragment();
+        mMobileSettingsActivity.mSubscriptionInfos = mSubscriptionInfos;
+
+        doReturn(mSubscriptionManager).when(mMobileSettingsActivity).getSystemService(
+                SubscriptionManager.class);
+        doReturn(mBottomNavigationView).when(mMobileSettingsActivity).findViewById(R.id.bottom_nav);
+        doReturn(mFragmentManager).when(mMobileSettingsActivity).getSupportFragmentManager();
+        doReturn(mFragmentTransaction).when(mFragmentManager).beginTransaction();
+        doReturn(mHideFragment).when(mFragmentManager).findFragmentByTag(
+                MOBILE_SETTINGS_TAG + PREV_SUB_ID);
+        doReturn(mShowFragment).when(mFragmentManager).findFragmentByTag(
+                MOBILE_SETTINGS_TAG + CURRENT_SUB_ID);
+    }
+
+    @Test
+    public void updateBottomNavigationView_oneSubscription_shouldBeGone() {
+        mSubscriptionInfos.add(mSubscriptionInfo);
+        doReturn(mSubscriptionInfos).when(mSubscriptionManager).getActiveSubscriptionInfoList();
+
+        mMobileSettingsActivity.updateBottomNavigationView();
+
+        verify(mBottomNavigationView).setVisibility(View.GONE);
+    }
+
+    @Test
+    public void updateBottomNavigationView_twoSubscription_updateMenu() {
+        final Menu menu = new ContextMenuBuilder(mContext);
+        mSubscriptionInfos.add(mSubscriptionInfo);
+        mSubscriptionInfos.add(mSubscriptionInfo);
+        doReturn(mSubscriptionInfos).when(mSubscriptionManager).getActiveSubscriptionInfoList();
+        doReturn(menu).when(mBottomNavigationView).getMenu();
+
+        mMobileSettingsActivity.updateBottomNavigationView();
+
+        assertThat(menu.size()).isEqualTo(2);
+    }
+
+    @Test
+    public void switchFragment_hidePreviousFragment() {
+        mMobileSettingsActivity.mPrevSubscriptionId = PREV_SUB_ID;
+
+        mMobileSettingsActivity.switchFragment(mShowFragment, CURRENT_SUB_ID);
+
+        verify(mFragmentTransaction).hide(mHideFragment);
+    }
+
+    @Test
+    public void switchFragment_fragmentExist_showItWithArguments() {
+        mMobileSettingsActivity.mPrevSubscriptionId = PREV_SUB_ID;
+
+        mMobileSettingsActivity.switchFragment(mShowFragment, CURRENT_SUB_ID);
+
+        assertThat(mShowFragment.getArguments().getInt(
+                MobileSettingsActivity.KEY_SUBSCRIPTION_ID)).isEqualTo(CURRENT_SUB_ID);
+        verify(mFragmentTransaction).show(mShowFragment);
+    }
+}
diff --git a/tests/robotests/src/com/android/settings/search/DeviceIndexFeatureProviderTest.java b/tests/robotests/src/com/android/settings/search/DeviceIndexFeatureProviderTest.java
deleted file mode 100644
index b49ef1d..0000000
--- a/tests/robotests/src/com/android/settings/search/DeviceIndexFeatureProviderTest.java
+++ /dev/null
@@ -1,148 +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.search;
-
-import static org.mockito.ArgumentMatchers.any;
-import static org.mockito.Mockito.never;
-import static org.mockito.Mockito.spy;
-import static org.mockito.Mockito.verify;
-import static org.mockito.Mockito.when;
-
-import android.app.Activity;
-import android.app.job.JobScheduler;
-import android.os.Binder;
-import android.provider.Settings;
-
-import com.android.settings.testutils.FakeFeatureFactory;
-import com.android.settings.testutils.SettingsRobolectricTestRunner;
-
-import org.junit.After;
-import org.junit.Before;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.mockito.Mock;
-import org.mockito.MockitoAnnotations;
-import org.robolectric.Robolectric;
-import org.robolectric.shadows.ShadowBinder;
-
-@RunWith(SettingsRobolectricTestRunner.class)
-public class DeviceIndexFeatureProviderTest {
-
-    @Mock
-    private JobScheduler mJobScheduler;
-    private DeviceIndexFeatureProvider mProvider;
-    private Activity mActivity;
-
-    @Before
-    public void setUp() {
-        MockitoAnnotations.initMocks(this);
-        ShadowBinder.reset();
-        FakeFeatureFactory.setupForTest();
-        mActivity = spy(Robolectric.buildActivity(Activity.class).create().visible().get());
-        mProvider = spy(new DeviceIndexFeatureProviderImpl());
-        when(mActivity.getSystemService(JobScheduler.class)).thenReturn(mJobScheduler);
-    }
-
-    @After
-    public void tearDown() {
-        ShadowBinder.reset();
-    }
-
-    @Test
-    public void updateIndex_disabled_shouldDoNothing() {
-        when(mProvider.isIndexingEnabled()).thenReturn(false);
-
-        mProvider.updateIndex(mActivity, false);
-        verify(mJobScheduler, never()).schedule(any());
-    }
-
-    @Test
-    public void updateIndex_enabled_unprovisioned_shouldDoNothing() {
-        when(mProvider.isIndexingEnabled()).thenReturn(true);
-        Settings.Global.putInt(mActivity.getContentResolver(),
-                Settings.Global.DEVICE_PROVISIONED, 0);
-
-        mProvider.updateIndex(mActivity, false);
-
-        verify(mJobScheduler, never()).schedule(any());
-    }
-
-    @Test
-    public void updateIndex_enabled_provisioned_shouldIndex() {
-        Settings.Global.putInt(mActivity.getContentResolver(),
-                Settings.Global.DEVICE_PROVISIONED, 1);
-        when(mProvider.isIndexingEnabled()).thenReturn(true);
-
-        mProvider.updateIndex(mActivity, false);
-        verify(mJobScheduler).schedule(any());
-    }
-
-    @Test
-    public void updateIndex_enabled_provisioned_newBuild_shouldIndex() {
-        Settings.Global.putInt(mActivity.getContentResolver(),
-                Settings.Global.DEVICE_PROVISIONED, 1);
-        DeviceIndexFeatureProvider.setIndexState(mActivity);
-        Settings.Global.putString(mActivity.getContentResolver(),
-                DeviceIndexFeatureProvider.INDEX_VERSION, "new version");
-        Settings.Global.putString(mActivity.getContentResolver(),
-                DeviceIndexFeatureProvider.LANGUAGE.toString(),
-                DeviceIndexFeatureProvider.INDEX_LANGUAGE);
-        when(mProvider.isIndexingEnabled()).thenReturn(true);
-
-        mProvider.updateIndex(mActivity, false);
-        verify(mJobScheduler).schedule(any());
-    }
-
-    @Test
-    public void updateIndex_enabled_provisioned_differentUid_shouldNotIndex() {
-        Settings.Global.putInt(mActivity.getContentResolver(),
-                Settings.Global.DEVICE_PROVISIONED, 1);
-        when(mProvider.isIndexingEnabled()).thenReturn(true);
-
-        ShadowBinder.setCallingUid(Binder.getCallingUid() + 2000);
-
-        mProvider.updateIndex(mActivity, false);
-        verify(mJobScheduler, never()).schedule(any());
-    }
-
-    @Test
-    public void updateIndex_enabled_provisioned_newIndex_shouldIndex() {
-        Settings.Global.putInt(mActivity.getContentResolver(),
-                Settings.Global.DEVICE_PROVISIONED, 1);
-        DeviceIndexFeatureProvider.setIndexState(mActivity);
-        Settings.Global.putString(mActivity.getContentResolver(),
-                DeviceIndexFeatureProvider.INDEX_LANGUAGE, "new language");
-
-        when(mProvider.isIndexingEnabled()).thenReturn(true);
-
-        mProvider.updateIndex(mActivity, false);
-        verify(mJobScheduler).schedule(any());
-    }
-
-    @Test
-    public void updateIndex_enabled_provisioned_sameBuild_sameLang_shouldNotIndex() {
-        // Enabled
-        when(mProvider.isIndexingEnabled()).thenReturn(true);
-        // Provisioned
-        Settings.Global.putInt(mActivity.getContentResolver(),
-                Settings.Global.DEVICE_PROVISIONED, 1);
-        // Same build and same language
-        DeviceIndexFeatureProvider.setIndexState(mActivity);
-
-        mProvider.updateIndex(mActivity, false);
-
-        verify(mJobScheduler, never()).schedule(any());
-    }
-}
diff --git a/tests/robotests/src/com/android/settings/search/DeviceIndexUpdateJobServiceTest.java b/tests/robotests/src/com/android/settings/search/DeviceIndexUpdateJobServiceTest.java
deleted file mode 100644
index 43ce966..0000000
--- a/tests/robotests/src/com/android/settings/search/DeviceIndexUpdateJobServiceTest.java
+++ /dev/null
@@ -1,144 +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.search;
-
-import static org.mockito.ArgumentMatchers.any;
-import static org.mockito.ArgumentMatchers.eq;
-import static org.mockito.Mockito.doAnswer;
-import static org.mockito.Mockito.doNothing;
-import static org.mockito.Mockito.doReturn;
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.spy;
-import static org.mockito.Mockito.times;
-import static org.mockito.Mockito.verify;
-import static org.mockito.Mockito.when;
-
-import android.app.Activity;
-import android.content.ContentResolver;
-import android.net.Uri;
-
-import androidx.slice.Slice;
-import androidx.slice.SliceMetadata;
-import androidx.slice.SliceViewManager;
-
-import com.android.settings.slices.SettingsSliceProvider;
-import com.android.settings.testutils.FakeFeatureFactory;
-import com.android.settings.testutils.SettingsRobolectricTestRunner;
-
-import org.junit.Before;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.robolectric.Robolectric;
-
-import java.util.ArrayList;
-import java.util.List;
-
-@RunWith(SettingsRobolectricTestRunner.class)
-public class DeviceIndexUpdateJobServiceTest {
-        private static final Uri BASE_URI = new Uri.Builder()
-                .scheme(ContentResolver.SCHEME_CONTENT)
-                .authority(SettingsSliceProvider.SLICE_AUTHORITY)
-                .build();
-
-    private Activity mActivity;
-    private DeviceIndexUpdateJobService mJob;
-    private SliceViewManager mSliceManager;
-
-    @Before
-    public void setup() {
-        FakeFeatureFactory.setupForTest();
-        mActivity = spy(Robolectric.buildActivity(Activity.class).create().visible().get());
-        mJob = spy(new DeviceIndexUpdateJobService());
-        mSliceManager = mock(SliceViewManager.class);
-
-        doReturn(mActivity.getPackageName()).when(mJob).getPackageName();
-        doReturn(mSliceManager).when(mJob).getSliceViewManager();
-        doNothing().when(mJob).jobFinished(null, false);
-    }
-
-    @Test
-    public void testGetsSlices() {
-        setSlices();
-
-        mJob.updateIndex(null);
-        verify(mSliceManager).getSliceDescendants(eq(BASE_URI));
-    }
-
-    @Test
-    public void testIndexesSlices() {
-        setSlices(genSlice("path1"), genSlice("path2"));
-
-        mJob.mRunningJob = true;
-        mJob.updateIndex(null);
-        verify(mSliceManager).getSliceDescendants(eq(BASE_URI));
-
-        DeviceIndexFeatureProvider indexFeatureProvider = FakeFeatureFactory.getFactory(mActivity)
-                .getDeviceIndexFeatureProvider();
-        verify(indexFeatureProvider, times(2)).index(any(), any(), any(), any(), any());
-    }
-
-    @Test
-    public void testDoNotIndexWithoutTitle() {
-        Slice testSlice = genSlice("path2");
-        setSlices(genSlice("path1"), testSlice);
-        doReturn(null).when(mJob).findTitle(testSlice, mJob.getMetadata(testSlice));
-
-        mJob.mRunningJob = true;
-        mJob.updateIndex(null);
-        verify(mSliceManager).getSliceDescendants(eq(BASE_URI));
-
-        DeviceIndexFeatureProvider indexFeatureProvider = FakeFeatureFactory.getFactory(mActivity)
-                .getDeviceIndexFeatureProvider();
-        verify(indexFeatureProvider, times(1)).index(any(), any(), any(), any(), any());
-    }
-
-    @Test
-    public void testStopIndexing() {
-        Slice testSlice = genSlice("path1");
-        setSlices(testSlice, genSlice("path2"));
-        mJob.mRunningJob = true;
-
-        doAnswer(invocation -> {
-            // Stop running after the first iteration
-            mJob.mRunningJob = false;
-            return testSlice;
-        }).when(mJob).bindSliceSynchronous(mSliceManager, testSlice.getUri());
-
-        mJob.updateIndex(null);
-        verify(mSliceManager).getSliceDescendants(eq(BASE_URI));
-
-        DeviceIndexFeatureProvider indexFeatureProvider = FakeFeatureFactory.getFactory(mActivity)
-                .getDeviceIndexFeatureProvider();
-        verify(indexFeatureProvider).clearIndex(any());
-        verify(indexFeatureProvider, times(1)).index(any(), any(), any(), any(), any());
-    }
-
-    private Slice genSlice(String path) {
-        return new Slice.Builder(BASE_URI.buildUpon().path(path).build()).build();
-    }
-
-    private void setSlices(Slice... slice) {
-        List<Uri> mUris = new ArrayList<>();
-        for (Slice slouse : slice) {
-            SliceMetadata m = mock(SliceMetadata.class);
-            mUris.add(slouse.getUri());
-            doReturn(slouse).when(mJob).bindSliceSynchronous(mSliceManager, slouse.getUri());
-            doReturn(m).when(mJob).getMetadata(slouse);
-            doReturn(slouse.getUri().getPath()).when(mJob).findTitle(slouse, m);
-        }
-        when(mSliceManager.getSliceDescendants(BASE_URI)).thenReturn(mUris);
-    }
-
-}
diff --git a/tests/robotests/src/com/android/settings/testutils/FakeFeatureFactory.java b/tests/robotests/src/com/android/settings/testutils/FakeFeatureFactory.java
index 39d4417..24db829 100644
--- a/tests/robotests/src/com/android/settings/testutils/FakeFeatureFactory.java
+++ b/tests/robotests/src/com/android/settings/testutils/FakeFeatureFactory.java
@@ -33,7 +33,6 @@
 import com.android.settings.overlay.FeatureFactory;
 import com.android.settings.overlay.SupportFeatureProvider;
 import com.android.settings.overlay.SurveyFeatureProvider;
-import com.android.settings.search.DeviceIndexFeatureProvider;
 import com.android.settings.search.SearchFeatureProvider;
 import com.android.settings.security.SecurityFeatureProvider;
 import com.android.settings.slices.SlicesFeatureProvider;
@@ -62,7 +61,6 @@
     public final UserFeatureProvider userFeatureProvider;
     public final AssistGestureFeatureProvider assistGestureFeatureProvider;
     public final AccountFeatureProvider mAccountFeatureProvider;
-    public final DeviceIndexFeatureProvider deviceIndexFeatureProvider;
 
     public SlicesFeatureProvider slicesFeatureProvider;
     public SearchFeatureProvider searchFeatureProvider;
@@ -104,7 +102,6 @@
         assistGestureFeatureProvider = mock(AssistGestureFeatureProvider.class);
         slicesFeatureProvider = mock(SlicesFeatureProvider.class);
         mAccountFeatureProvider = mock(AccountFeatureProvider.class);
-        deviceIndexFeatureProvider = mock(DeviceIndexFeatureProvider.class);
     }
 
     @Override
@@ -186,9 +183,4 @@
     public AccountFeatureProvider getAccountFeatureProvider() {
         return mAccountFeatureProvider;
     }
-
-    @Override
-    public DeviceIndexFeatureProvider getDeviceIndexFeatureProvider() {
-        return deviceIndexFeatureProvider;
-    }
 }
diff --git a/tests/unit/src/com/android/settings/slices/SliceDeepLinkSpringBoardTest.java b/tests/unit/src/com/android/settings/slices/SliceDeepLinkSpringBoardTest.java
index dfeca5f..81f1fac 100644
--- a/tests/unit/src/com/android/settings/slices/SliceDeepLinkSpringBoardTest.java
+++ b/tests/unit/src/com/android/settings/slices/SliceDeepLinkSpringBoardTest.java
@@ -16,7 +16,7 @@
 
 package com.android.settings.slices;
 
-import static com.android.settings.search.DeviceIndexFeatureProvider.createDeepLink;
+import static com.android.settings.slices.SliceDeepLinkSpringBoard.createDeepLink;
 
 import android.content.Context;
 import android.content.Intent;