Merge "Fix script to compile emergency number database"
diff --git a/AndroidManifest.xml b/AndroidManifest.xml
index 0da698e..ad1ed76 100644
--- a/AndroidManifest.xml
+++ b/AndroidManifest.xml
@@ -604,5 +604,25 @@
                 <action android:name="android.telephony.data.DataService" />
             </intent-filter>
         </service>
+
+        <activity
+            android:name=".settings.RadioInfo"
+            android:label="@string/phone_info_label"
+            android:theme="@style/Theme.AppCompat.DayNight">
+            <intent-filter>
+                <action android:name="android.intent.action.MAIN" />
+                <category android:name="android.intent.category.DEVELOPMENT_PREFERENCE" />
+            </intent-filter>
+        </activity>
+
+        <activity android:name=".settings.BandMode"
+                  android:label="@string/band_mode_title"
+                  android:theme="@style/Theme.AppCompat.DayNight">
+            <intent-filter>
+                <action android:name="android.intent.action.MAIN" />
+                <category android:name="android.intent.category.DEFAULT" />
+                <category android:name="android.intent.category.VOICE_LAUNCH" />
+            </intent-filter>
+        </activity>
     </application>
 </manifest>
diff --git a/res/layout/band_mode.xml b/res/layout/band_mode.xml
new file mode 100644
index 0000000..b43dd1d
--- /dev/null
+++ b/res/layout/band_mode.xml
@@ -0,0 +1,30 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2007 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"
+              android:orientation="vertical"
+              android:padding="4dip"
+              android:gravity="center_horizontal"
+              android:layout_width="match_parent"
+              android:layout_height="wrap_content">
+
+    <ListView android:id="@+id/band"
+              android:layout_width="match_parent"
+              android:layout_height="match_parent"
+              android:textSize="7sp">
+    </ListView>
+
+</LinearLayout>
diff --git a/res/layout/radio_info.xml b/res/layout/radio_info.xml
new file mode 100644
index 0000000..40c2e53
--- /dev/null
+++ b/res/layout/radio_info.xml
@@ -0,0 +1,414 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/* //device/apps/Settings/assets/res/any/layout/radio_info.xml
+**
+** Copyright 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.
+*/
+-->
+<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent">
+
+    <LinearLayout style="@style/info_layout"
+        android:descendantFocusability="beforeDescendants"
+        android:focusableInTouchMode="true">
+
+        <!-- Phone index -->
+        <TextView
+                android:layout_width="match_parent"
+                android:layout_height="wrap_content"
+                android:text="@string/phone_index_label"
+                style="@style/info_label"
+                />
+
+        <Spinner android:id="@+id/phoneIndex"
+                 android:layout_width="match_parent"
+                 android:layout_height="wrap_content"
+                />
+
+        <!-- IMEI -->
+        <LinearLayout style="@style/RadioInfo_entry_layout">
+            <TextView android:text="@string/radio_info_imei_label" style="@style/info_label" />
+            <TextView android:id="@+id/imei" style="@style/info_value" />
+        </LinearLayout>
+
+        <!-- Phone Number -->
+        <LinearLayout style="@style/RadioInfo_entry_layout">
+            <TextView android:text="@string/radio_info_phone_number_label" style="@style/info_label" />
+            <TextView android:id="@+id/number" style="@style/info_value" />
+        </LinearLayout>
+
+        <!-- Subscription ID -->
+        <LinearLayout style="@style/RadioInfo_entry_layout">
+            <TextView android:text="@string/radio_info_subid" style="@style/info_label" />
+            <TextView android:id="@+id/subid" style="@style/info_value" />
+        </LinearLayout>
+
+        <!-- Default data subscription -->
+        <LinearLayout style="@style/RadioInfo_entry_layout">
+            <TextView android:text="@string/radio_info_dds" style="@style/info_label" />
+            <TextView android:id="@+id/dds" style="@style/info_value" />
+        </LinearLayout>
+
+        <!-- IMSI -->
+        <LinearLayout style="@style/RadioInfo_entry_layout">
+            <TextView android:text="@string/radio_info_imsi_label" style="@style/info_label" />
+            <TextView android:id="@+id/imsi" style="@style/info_value" />
+        </LinearLayout>
+
+        <!-- Network Identifier -->
+        <LinearLayout style="@style/RadioInfo_entry_layout">
+            <TextView android:text="@string/radio_info_current_network_label" style="@style/info_label" />
+            <TextView android:id="@+id/operator" style="@style/info_value" />
+        </LinearLayout>
+
+        <!-- Roaming -->
+        <LinearLayout style="@style/RadioInfo_entry_layout">
+            <TextView android:text="@string/radio_info_roaming_label" style="@style/info_label" />
+            <TextView android:id="@+id/roaming" style="@style/info_value" />
+        </LinearLayout>
+
+        <!-- Data Service Status -->
+        <LinearLayout style="@style/RadioInfo_entry_layout">
+            <TextView android:text="@string/radio_info_gprs_service_label" style="@style/info_label" />
+            <TextView android:id="@+id/gprs" style="@style/info_value" />
+        </LinearLayout>
+
+        <!-- Data Network Type -->
+        <LinearLayout style="@style/RadioInfo_entry_layout">
+            <TextView android:text="@string/radio_info_data_network_type_label" style="@style/info_label" />
+            <TextView android:id="@+id/data_network" style="@style/info_value" />
+        </LinearLayout>
+
+        <!-- Voice Service Status -->
+        <LinearLayout style="@style/RadioInfo_entry_layout">
+            <TextView android:text="@string/radio_info_gsm_service_label" style="@style/info_label" />
+            <TextView android:id="@+id/gsm" style="@style/info_value" />
+        </LinearLayout>
+
+        <!-- Voice Network Type -->
+        <LinearLayout style="@style/RadioInfo_entry_layout">
+            <TextView android:text="@string/radio_info_voice_network_type_label" style="@style/info_label" />
+            <TextView android:id="@+id/voice_network" style="@style/info_value" />
+        </LinearLayout>
+
+        <!-- Signal Strength -->
+        <LinearLayout style="@style/RadioInfo_entry_layout">
+            <TextView android:text="@string/radio_info_signal_strength_label" style="@style/info_label" />
+            <TextView android:id="@+id/dbm" style="@style/info_value" />
+        </LinearLayout>
+
+        <!-- Link Bandwidth -->
+        <LinearLayout style="@style/RadioInfo_entry_layout" android:orientation="horizontal">
+            <TextView android:text="@string/radio_info_dl_kbps" style="@style/info_label" />
+            <TextView android:id="@+id/dl_kbps" style="@style/info_value" />
+        </LinearLayout>
+
+        <!-- Link Bandwidth -->
+        <LinearLayout style="@style/RadioInfo_entry_layout" android:orientation="horizontal">
+            <TextView android:text="@string/radio_info_ul_kbps" style="@style/info_label" />
+            <TextView android:id="@+id/ul_kbps" style="@style/info_value" />
+        </LinearLayout>
+
+        <!-- Physical Channel Config -->
+        <LinearLayout style="@style/RadioInfo_entry_layout">
+            <TextView android:text="@string/radio_info_phy_chan_config" style="@style/info_label" />
+            <TextView android:id="@+id/phy_chan_config" style="@style/info_value" />
+        </LinearLayout>
+
+        <!-- Horizontal Rule -->
+        <View
+            android:layout_width="fill_parent"
+            android:layout_height="1dip"
+            android:background="?android:attr/listDivider" />
+
+        <!-- Preferred Network Type -->
+        <TextView
+                android:layout_width="match_parent"
+                android:layout_height="wrap_content"
+                android:text="@string/radio_info_set_perferred_label"
+                style="@style/info_label"
+                />
+
+        <Spinner android:id="@+id/preferredNetworkType"
+                 android:layout_width="match_parent"
+                 android:layout_height="wrap_content"
+                />
+
+        <!-- Horizontal Rule -->
+        <View
+            android:layout_width="fill_parent"
+            android:layout_height="1dip"
+            android:background="?android:attr/listDivider" />
+
+        <!-- Radio Power -->
+        <Switch android:id="@+id/radio_power"
+                android:textSize="14sp"
+                android:layout_marginTop="8dip"
+                android:layout_width="match_parent"
+                android:layout_height="wrap_content"
+                android:text="@string/radio_info_radio_power"/>
+
+        <!-- VoLTE provisioned -->
+        <Switch android:id="@+id/volte_provisioned_switch"
+                android:textSize="14sp"
+                android:layout_marginTop="8dip"
+                android:layout_width="match_parent"
+                android:layout_height="wrap_content"
+                android:text="@string/volte_provisioned_switch_string"/>
+
+        <!-- VT provisioned -->
+        <Switch android:id="@+id/vt_provisioned_switch"
+                android:textSize="14sp"
+                android:layout_marginTop="8dip"
+                android:layout_width="match_parent"
+                android:layout_height="wrap_content"
+                android:text="@string/vt_provisioned_switch_string"/>
+
+        <!-- Wifi Calling provisioned -->
+        <Switch android:id="@+id/wfc_provisioned_switch"
+                android:textSize="14sp"
+                android:layout_marginTop="8dip"
+                android:layout_width="match_parent"
+                android:layout_height="wrap_content"
+                android:text="@string/wfc_provisioned_switch_string"/>
+
+        <!-- EAB/Presence provisioned -->
+        <Switch android:id="@+id/eab_provisioned_switch"
+                android:textSize="14sp"
+                android:layout_marginTop="8dip"
+                android:layout_width="match_parent"
+                android:layout_height="wrap_content"
+                android:text="@string/eab_provisioned_switch_string"/>
+
+        <!-- Horizontal Rule -->
+        <View
+            android:layout_width="fill_parent"
+            android:layout_height="1dip"
+            android:background="?android:attr/listDivider" />
+
+        <!-- Enable/Disable CBRS data -->
+        <Switch android:id="@+id/cbrs_data_switch"
+                android:textSize="14sp"
+                android:layout_marginTop="8dip"
+                android:layout_width="match_parent"
+                android:layout_height="wrap_content"
+                android:text="@string/cbrs_data_switch_string" />
+
+        <!-- Switch between SSSS(single sim single standby) and DSDS(dual sim dual standby). -->
+        <Switch android:id="@+id/dsds_switch"
+                android:textSize="14sp"
+                android:layout_marginTop="8dip"
+                android:layout_width="match_parent"
+                android:layout_height="wrap_content"
+                android:text="@string/dsds_switch_string" />
+
+        <!-- Horizontal Rule -->
+        <View
+            android:layout_width="fill_parent"
+            android:layout_height="1dip"
+            android:background="?android:attr/listDivider" />
+
+        <!-- Ping stats -->
+        <Button android:id="@+id/ping_test"
+                android:textSize="14sp"
+                android:layout_marginTop="8dip"
+                android:layout_width="wrap_content"
+                android:layout_height="wrap_content"
+                android:text="@string/ping_test_label"
+                />
+ 
+        <LinearLayout style="@style/RadioInfo_entry_layout">
+            <TextView android:text="@string/radio_info_ping_hostname_v4" style="@style/info_label" />
+            <TextView android:id="@+id/pingHostnameV4" style="@style/info_value" />
+        </LinearLayout>
+
+        <LinearLayout style="@style/RadioInfo_entry_layout">
+            <TextView android:text="@string/radio_info_ping_hostname_v6" style="@style/info_label" />
+            <TextView android:id="@+id/pingHostnameV6" style="@style/info_value" />
+        </LinearLayout>
+
+        <LinearLayout style="@style/RadioInfo_entry_layout">
+            <TextView android:text="@string/radio_info_http_client_test" style="@style/info_label" />
+            <TextView android:id="@+id/httpClientTest" style="@style/info_value" />
+        </LinearLayout>
+
+        <!-- Horizontal Rule -->
+        <View
+            android:layout_width="fill_parent"
+            android:layout_height="1dip"
+            android:background="?android:attr/listDivider" />
+
+        <!-- PPP Sent -->
+        <LinearLayout style="@style/RadioInfo_entry_layout">
+            <TextView android:text="@string/radio_info_ppp_sent_label"
+                style="@style/info_label" />
+            <TextView android:id="@+id/sent" style="@style/info_value" />
+        </LinearLayout>
+
+        <!-- PPP Received -->
+        <LinearLayout style="@style/RadioInfo_entry_layout">
+            <TextView android:text="@string/radio_info_ppp_received_label"
+                style="@style/info_label" />
+            <TextView android:id="@+id/received" style="@style/info_value" />
+        </LinearLayout>
+
+        <!-- PPP Sent since last received -->
+        <LinearLayout style="@style/RadioInfo_entry_layout">
+            <TextView android:text="@string/radio_info_ppp_resets_label"
+                style="@style/info_label" />
+            <TextView android:id="@+id/sentSinceReceived" style="@style/info_value" />
+        </LinearLayout>
+
+        <!-- Horizontal Rule -->
+        <View
+            android:layout_width="fill_parent"
+            android:layout_height="1dip"
+            android:background="?android:attr/listDivider" />
+
+        <!-- Call Status -->
+        <LinearLayout style="@style/RadioInfo_entry_layout">
+            <TextView android:text="@string/radio_info_call_status_label" style="@style/info_label" />
+            <TextView android:id="@+id/call" style="@style/info_value" />
+        </LinearLayout>
+
+        <!-- Message Waiting Indicator -->
+        <LinearLayout style="@style/RadioInfo_entry_layout">
+            <TextView android:text="@string/radio_info_message_waiting_label" style="@style/info_label" />
+            <TextView android:id="@+id/mwi" style="@style/info_value" />
+        </LinearLayout>
+
+        <!-- Call Forwarding Indicator -->
+        <LinearLayout style="@style/RadioInfo_entry_layout">
+            <TextView android:text="@string/radio_info_call_redirect_label" style="@style/info_label" />
+            <TextView android:id="@+id/cfi" style="@style/info_value" />
+        </LinearLayout>
+
+        <!-- Horizontal Rule -->
+        <View
+            android:layout_width="fill_parent"
+            android:layout_height="1dip"
+            android:background="?android:attr/listDivider" />
+
+        <!-- CellInfoListRate Selection -->
+        <!-- Location -->
+        <LinearLayout style="@style/RadioInfo_entry_layout">
+            <TextView android:text="@string/radio_info_signal_location_label" style="@style/info_label" />
+            <TextView android:id="@+id/location" style="@style/info_value" />
+        </LinearLayout>
+
+        <TextView
+                android:layout_width="match_parent"
+                android:layout_height="wrap_content"
+                android:text="@string/radio_info_cell_info_refresh_rate"
+                style="@style/info_label"
+                />
+
+        <Spinner android:id="@+id/cell_info_rate_select"
+                 android:layout_width="match_parent"
+                 android:layout_height="wrap_content"
+                />
+
+        <!-- CellInfo -->
+        <LinearLayout style="@style/RadioInfo_entry_layout">
+            <TextView android:text="@string/radio_info_cellinfo_label"
+                      style="@style/info_label" />
+        </LinearLayout>
+        <LinearLayout style="@style/RadioInfo_entry_layout">
+            <TextView android:id="@+id/cellinfo"
+                      style="@style/info_value"
+                      android:minHeight="300dip"
+                      android:textSize="12sp" />
+        </LinearLayout>
+
+        <!-- Horizontal Rule -->
+        <View
+            android:layout_width="fill_parent"
+            android:layout_height="1dip"
+            android:background="?android:attr/listDivider" />
+
+        <!-- Launch OEM-specific Info/Settings Activity (if any) -->
+        <!-- Carrier Provisioning -->
+        <LinearLayout style="@style/RadioInfo_entry_layout"
+                      android:orientation="horizontal" >
+            <Button android:id="@+id/carrier_provisioning"
+                    android:layout_marginTop="8dip"
+                    android:layout_weight="1"
+                    android:layout_width="0dp"
+                    android:layout_height="wrap_content"
+                    android:text="@string/carrier_provisioning"
+                    android:textSize="14sp"/>
+            <Button android:id="@+id/trigger_carrier_provisioning"
+                    android:layout_marginTop="8dip"
+                    android:layout_weight="1"
+                    android:layout_width="0dp"
+                    android:layout_height="wrap_content"
+                    android:text="@string/trigger_carrier_provisioning"
+                    android:textSize="14sp"/>
+            <Button android:id="@+id/oem_info"
+                    android:layout_marginTop="8dip"
+                    android:layout_weight="1"
+                    android:layout_width="0dp"
+                    android:layout_height="wrap_content"
+                    android:text="@string/oem_radio_info_label"
+                    android:textSize="14sp"/>
+        </LinearLayout>
+
+        <!-- SMSC -->
+        <RelativeLayout android:layout_width="match_parent"
+                        android:layout_height="wrap_content">
+            <TextView android:id="@+id/smsc_label"
+                      android:text="@string/radio_info_smsc_label"
+                      android:layout_alignBaseline="@+id/update_smsc"
+                      style="@style/info_label" />
+            <Button android:id="@+id/refresh_smsc"
+                    android:textSize="14sp"
+                    android:layout_marginTop="8dip"
+                    android:layout_width="wrap_content"
+                    android:layout_height="wrap_content"
+                    android:text="@string/radio_info_smsc_refresh_label"
+                    android:layout_alignParentEnd="true"
+                    />
+            <Button android:id="@+id/update_smsc"
+                    android:textSize="14sp"
+                    android:layout_marginTop="8dip"
+                    android:layout_width="wrap_content"
+                    android:layout_height="wrap_content"
+                    android:text="@string/radio_info_smsc_update_label"
+                    android:layout_toStartOf="@+id/refresh_smsc"
+                    android:layout_alignBaseline="@+id/refresh_smsc"
+                    />
+            <EditText android:id="@+id/smsc"
+                      style="@style/form_value"
+                      android:layout_alignBaseline="@+id/refresh_smsc"
+                      android:layout_toStartOf="@id/update_smsc"
+                      android:layout_toEndOf="@id/smsc_label" />
+        </RelativeLayout>
+
+        <!-- Test setting to ignore bad DNS, useful in lab environments -->
+        <LinearLayout style="@style/RadioInfo_entry_layout">
+            <Button android:id="@+id/dns_check_toggle"
+                    android:textSize="14sp"
+                    android:layout_marginTop="8dip"
+                    android:layout_width="wrap_content"
+                    android:layout_height="wrap_content"
+                    android:text="@string/radio_info_toggle_dns_check_label"
+                    />
+            <TextView android:id="@+id/dnsCheckState" style="@style/info_value" />
+        </LinearLayout>
+
+
+    </LinearLayout>
+</ScrollView>
diff --git a/res/values-ca/strings.xml b/res/values-ca/strings.xml
index 1b5b95d..800977d 100644
--- a/res/values-ca/strings.xml
+++ b/res/values-ca/strings.xml
@@ -534,7 +534,7 @@
     <string name="dial_emergency_calling_not_available" msgid="5675557523782491826">"Les trucades d\'emergència no estan disponibles"</string>
     <string name="police_type_description" msgid="5324410799919829693">"Policia"</string>
     <string name="ambulance_type_description" msgid="4114815025408089866">"Ambulància"</string>
-    <string name="fire_type_description" msgid="7145996705197064710">"Foc"</string>
+    <string name="fire_type_description" msgid="7145996705197064710">"Bombers"</string>
     <string name="description_concat_format" msgid="7141070875487870177">"%1$s, %2$s"</string>
     <string name="dialerKeyboardHintText" msgid="9192914825413747792">"Utilitzeu el teclat per marcar"</string>
     <string name="onscreenHoldText" msgid="2285258239691145872">"Posa en espera"</string>
diff --git a/res/values-et/strings.xml b/res/values-et/strings.xml
index aca0c21..42d72d5 100644
--- a/res/values-et/strings.xml
+++ b/res/values-et/strings.xml
@@ -533,7 +533,7 @@
     <string name="dial_emergency_empty_error" msgid="9130194953830414638">"Ei saa helistada. Valige hädaabinumber."</string>
     <string name="dial_emergency_calling_not_available" msgid="5675557523782491826">"Hädaabikõned pole saadaval"</string>
     <string name="police_type_description" msgid="5324410799919829693">"Politsei"</string>
-    <string name="ambulance_type_description" msgid="4114815025408089866">"Kiirabiauto"</string>
+    <string name="ambulance_type_description" msgid="4114815025408089866">"Kiirabi"</string>
     <string name="fire_type_description" msgid="7145996705197064710">"Tuletõrje"</string>
     <string name="description_concat_format" msgid="7141070875487870177">"%1$s, %2$s"</string>
     <string name="dialerKeyboardHintText" msgid="9192914825413747792">"Kasutage valimiseks klaviatuuri"</string>
diff --git a/res/values-eu/strings.xml b/res/values-eu/strings.xml
index 33c38b8..7405259 100644
--- a/res/values-eu/strings.xml
+++ b/res/values-eu/strings.xml
@@ -313,9 +313,9 @@
     <string name="enable_disable_local" msgid="7890281063123416120">"Tokikoa"</string>
     <string name="local_enable" msgid="6370463247609136359">"Tokiko albisteak gaituta"</string>
     <string name="local_disable" msgid="4405691986943795798">"Tokiko albisteak desgaituta"</string>
-    <string name="enable_disable_regional" msgid="4905652414535565872">"Eskualdekoak"</string>
-    <string name="regional_enable" msgid="4434680415437834759">"Eskualdeko albisteak gaituta"</string>
-    <string name="regional_disable" msgid="5359325527213850077">"Eskualdeko albisteak desgaituta"</string>
+    <string name="enable_disable_regional" msgid="4905652414535565872">"Tokikoak"</string>
+    <string name="regional_enable" msgid="4434680415437834759">"Tokiko albisteak gaituta"</string>
+    <string name="regional_disable" msgid="5359325527213850077">"Tokiko albisteak desgaituta"</string>
     <string name="enable_disable_national" msgid="236278090206880734">"Nazionalak"</string>
     <string name="national_enable" msgid="1172443648912246952">"Albiste nazionalak gaituta"</string>
     <string name="national_disable" msgid="326018148178601166">"Albiste nazionalak desgaituta"</string>
diff --git a/res/values-fi/strings.xml b/res/values-fi/strings.xml
index e18698d..1868240 100644
--- a/res/values-fi/strings.xml
+++ b/res/values-fi/strings.xml
@@ -760,7 +760,7 @@
     <string name="call_barring_old_pwd" msgid="6080515987320238522">"Vanha salasana"</string>
     <string name="call_barring_new_pwd" msgid="7048532299150269547">"Uusi salasana"</string>
     <string name="call_barring_confirm_pwd" msgid="1947167278466285411">"Vahvista salasana"</string>
-    <string name="messageCallBarring" msgid="2412123220272136055">"Anna salasana"</string>
+    <string name="messageCallBarring" msgid="2412123220272136055">"Lisää salasana"</string>
     <string name="call_barring_settings" msgid="80766145008623645">"Puhelunestoasetukset"</string>
     <string name="call_barring_deactivate_all_no_password" msgid="920902774366557311">"Poistetaanko kaikki puhelunestoasetukset käytöstä?"</string>
     <string name="callFailed_NetworkBusy" msgid="1068322087736565421">"Verkko on varattu. Yritä soittaa myöhemmin uudelleen."</string>
diff --git a/res/values-gu/strings.xml b/res/values-gu/strings.xml
index b915cab..3d3ee36 100644
--- a/res/values-gu/strings.xml
+++ b/res/values-gu/strings.xml
@@ -519,7 +519,7 @@
     <string name="incall_error_supp_service_hold" msgid="7967020511232222078">"કૉલ્સને હોલ્ડ કરી શકતાં નથી."</string>
     <string name="incall_error_wfc_only_no_wireless_network" msgid="1782466780452640089">"કૉલ કરવા માટે વાયરલેસ નેટવર્કથી કનેક્ટ કરો."</string>
     <string name="incall_error_promote_wfc" msgid="106510757624022064">"કૉલ કરવા માટે Wi-Fi કૉલિંગ સક્ષમ કરો."</string>
-    <string name="emergency_information_hint" msgid="399011533038204351">"કટોકટીની માહિતી"</string>
+    <string name="emergency_information_hint" msgid="399011533038204351">"ઇમર્જન્સીની માહિતી"</string>
     <string name="emergency_information_owner_hint" msgid="688331472291637149">"માલિક"</string>
     <string name="emergency_information_confirm_hint" msgid="4039012670779853030">"માહિતી જોવા માટે ફરીથી ટૅપ કરો"</string>
     <string name="emergency_enable_radio_dialog_title" msgid="4627849966634578257">"કટોકટીનો કૉલ"</string>
diff --git a/res/values-hy/strings.xml b/res/values-hy/strings.xml
index 4d68c8b..6cc47dd 100644
--- a/res/values-hy/strings.xml
+++ b/res/values-hy/strings.xml
@@ -635,7 +635,7 @@
     <string name="enable_video_calling_dialog_msg" msgid="8948186136957417948">"Տեսազանգերը միացնելու համար ձեզ անհրաժեշտ է ցանցի կարգավորումներում թույլատրել Ընդլայնված 4G LTE ռեժիմը:"</string>
     <string name="enable_video_calling_dialog_settings" msgid="576528473599603249">"Ցանցային կարգավորումներ"</string>
     <string name="enable_video_calling_dialog_close" msgid="7411471282167927991">"Փակել"</string>
-    <string name="sim_label_emergency_calls" msgid="4847699229529306397">"Արտակարգ իրավիճակների զանգեր"</string>
+    <string name="sim_label_emergency_calls" msgid="4847699229529306397">"Շտապ զանգեր"</string>
     <string name="sim_description_emergency_calls" msgid="7535215397212301562">"Միայն արտակարգ իրավիճակների զանգեր"</string>
     <string name="sim_description_default" msgid="4778679519938775515">"SIM քարտ, բնիկը՝ <xliff:g id="SLOT_ID">%s</xliff:g>"</string>
     <string name="accessibility_settings_activity_title" msgid="8562004288733103868">"Հատուկ գործառույթներ"</string>
diff --git a/res/values-kk/strings.xml b/res/values-kk/strings.xml
index 6ac793e..34b3579 100644
--- a/res/values-kk/strings.xml
+++ b/res/values-kk/strings.xml
@@ -519,7 +519,7 @@
     <string name="incall_error_supp_service_hold" msgid="7967020511232222078">"Қоңырауларды ұстау мүмкін емес."</string>
     <string name="incall_error_wfc_only_no_wireless_network" msgid="1782466780452640089">"Қоңырау шалу үшін сымсыз желіге қосылыңыз."</string>
     <string name="incall_error_promote_wfc" msgid="106510757624022064">"Қоңырау шалу үшін, Wi-Fi желісін қосыңыз."</string>
-    <string name="emergency_information_hint" msgid="399011533038204351">"Төтенше жағдайда қолданылатын деректер"</string>
+    <string name="emergency_information_hint" msgid="399011533038204351">"Төтенше жағдайға арналған ақпарат"</string>
     <string name="emergency_information_owner_hint" msgid="688331472291637149">"Иесі"</string>
     <string name="emergency_information_confirm_hint" msgid="4039012670779853030">"Ақпаратты көру үшін қайта түртіңіз"</string>
     <string name="emergency_enable_radio_dialog_title" msgid="4627849966634578257">"Төтенше қоңырау"</string>
@@ -534,7 +534,7 @@
     <string name="dial_emergency_calling_not_available" msgid="5675557523782491826">"Төтенше жағдай қызметіне қоңырау шалу мүмкіндігі жоқ"</string>
     <string name="police_type_description" msgid="5324410799919829693">"Полиция"</string>
     <string name="ambulance_type_description" msgid="4114815025408089866">"Жедел жәрдем"</string>
-    <string name="fire_type_description" msgid="7145996705197064710">"Өрт"</string>
+    <string name="fire_type_description" msgid="7145996705197064710">"Өрт қызметі"</string>
     <string name="description_concat_format" msgid="7141070875487870177">"%1$s, %2$s"</string>
     <string name="dialerKeyboardHintText" msgid="9192914825413747792">"Теру үшін пернетақтаны қолдану"</string>
     <string name="onscreenHoldText" msgid="2285258239691145872">"Күту"</string>
diff --git a/res/values-mk/strings.xml b/res/values-mk/strings.xml
index 734ee76..2ae98f2 100644
--- a/res/values-mk/strings.xml
+++ b/res/values-mk/strings.xml
@@ -536,7 +536,7 @@
     <string name="dial_emergency_calling_not_available" msgid="5675557523782491826">"Итните повици не се достапни"</string>
     <string name="police_type_description" msgid="5324410799919829693">"Полиција"</string>
     <string name="ambulance_type_description" msgid="4114815025408089866">"Брза помош"</string>
-    <string name="fire_type_description" msgid="7145996705197064710">"Оган"</string>
+    <string name="fire_type_description" msgid="7145996705197064710">"Пожарна"</string>
     <string name="description_concat_format" msgid="7141070875487870177">"%1$s, %2$s"</string>
     <string name="dialerKeyboardHintText" msgid="9192914825413747792">"Користи тастатурата за бирање"</string>
     <string name="onscreenHoldText" msgid="2285258239691145872">"Почекај"</string>
diff --git a/res/values-nl/strings.xml b/res/values-nl/strings.xml
index f1fd9df..80246b6 100644
--- a/res/values-nl/strings.xml
+++ b/res/values-nl/strings.xml
@@ -534,7 +534,7 @@
     <string name="dial_emergency_calling_not_available" msgid="5675557523782491826">"Noodoproepen niet beschikbaar"</string>
     <string name="police_type_description" msgid="5324410799919829693">"Politie"</string>
     <string name="ambulance_type_description" msgid="4114815025408089866">"Ambulance"</string>
-    <string name="fire_type_description" msgid="7145996705197064710">"Vuur"</string>
+    <string name="fire_type_description" msgid="7145996705197064710">"Brand"</string>
     <string name="description_concat_format" msgid="7141070875487870177">"%1$s, %2$s"</string>
     <string name="dialerKeyboardHintText" msgid="9192914825413747792">"Toetsen gebruiken om te bellen"</string>
     <string name="onscreenHoldText" msgid="2285258239691145872">"In de wacht"</string>
diff --git a/res/values-or/strings.xml b/res/values-or/strings.xml
index 5122424..668ec06 100644
--- a/res/values-or/strings.xml
+++ b/res/values-or/strings.xml
@@ -226,18 +226,18 @@
     <string name="preferred_network_mode_lte_cdma_evdo_summary" msgid="228702246343742853">"ନିଜ ପସନ୍ଦର ନେଟ୍‌ୱର୍କ ମୋଡ୍: CDMA+LTE/EVDO"</string>
     <string name="preferred_network_mode_global_summary" msgid="1633134285545730364">"ନିଜ ପସନ୍ଦର ନେଟ୍‌ୱର୍କ ମୋଡ୍: ଗ୍ଲୋବାଲ୍"</string>
     <string name="preferred_network_mode_lte_wcdma_summary" msgid="9180775701594742750">"ନିଜ ପସନ୍ଦର ନେଟ୍‌ୱର୍କ ମୋଡ୍: LTE / WCDMA"</string>
-    <string name="preferred_network_mode_lte_gsm_umts_summary" msgid="633315028976225026">"ପସନ୍ଦଦାର୍ ନେଟ୍‌ୱର୍କ ମୋଡ୍: LTE / GSM / UMTS"</string>
+    <string name="preferred_network_mode_lte_gsm_umts_summary" msgid="633315028976225026">"ପସନ୍ଦର ନେଟ୍‌ୱର୍କ ମୋଡ୍: LTE / GSM / UMTS"</string>
     <string name="preferred_network_mode_lte_cdma_summary" msgid="3722647806454528426">"ନିଜ ପସନ୍ଦର ନେଟ୍‌ୱର୍କ ମୋଡ୍: LTE / CDMA"</string>
-    <string name="preferred_network_mode_tdscdma_summary" msgid="8021016193718678775">"ପସନ୍ଦଦାର୍ ନେଟ୍‌ୱର୍କ ମୋଡ୍: TDSCDMA"</string>
-    <string name="preferred_network_mode_tdscdma_wcdma_summary" msgid="2405154895437348623">"ପସନ୍ଦଦାର୍ ନେଟ୍‌ୱର୍କ ମୋଡ୍: TDSCDMA / WCDMA"</string>
-    <string name="preferred_network_mode_lte_tdscdma_summary" msgid="2104702896644235637">"ପସନ୍ଦଦାର୍ ନେଟ୍‌ୱର୍କ ମୋଡ୍: LTE / TDSCDMA"</string>
-    <string name="preferred_network_mode_tdscdma_gsm_summary" msgid="4893784445338396204">"ପସନ୍ଦଦାର୍ ନେଟ୍‌ୱର୍କ ମୋଡ୍: TDSCDMA / GSM"</string>
-    <string name="preferred_network_mode_lte_tdscdma_gsm_summary" msgid="1815169717046729757">"ପସନ୍ଦଦାର୍ ନେଟ୍‌ୱର୍କ ମୋଡ୍: LTE/GSM/TDSCDMA"</string>
-    <string name="preferred_network_mode_tdscdma_gsm_wcdma_summary" msgid="2195358773359424099">"ପସନ୍ଦଦାର୍ ନେଟ୍‌ୱର୍କ ମୋଡ୍: TDSCDMA/GSM/WCDMA"</string>
-    <string name="preferred_network_mode_lte_tdscdma_wcdma_summary" msgid="1181424059695667803">"ପସନ୍ଦଦାର୍ ନେଟ୍‌ୱର୍କ ମୋଡ୍: LTE/TDSCDMA/WCDMA"</string>
-    <string name="preferred_network_mode_lte_tdscdma_gsm_wcdma_summary" msgid="2526539326505354382">"ପସନ୍ଦଦାର୍ ନେଟ୍‌ୱର୍କ ମୋଡ୍: LTE/TDSCDMA/GSM/WCDMA"</string>
-    <string name="preferred_network_mode_tdscdma_cdma_evdo_gsm_wcdma_summary" msgid="8195248059196614939">"ପସନ୍ଦଦାର୍ ନେଟ୍‌ୱର୍କ ମୋଡ୍: TDSCDMA/CDMA/EvDo/GSM/WCDMA"</string>
-    <string name="preferred_network_mode_lte_tdscdma_cdma_evdo_gsm_wcdma_summary" msgid="5596733053095592791">"ପସନ୍ଦଦାର୍ ନେଟ୍‌ୱର୍କ ମୋଡ୍: LTE/TDSCDMA/CDMA/EvDo/GSM/WCDMA"</string>
+    <string name="preferred_network_mode_tdscdma_summary" msgid="8021016193718678775">"ପସନ୍ଦର ନେଟ୍‌ୱର୍କ ମୋଡ୍: TDSCDMA"</string>
+    <string name="preferred_network_mode_tdscdma_wcdma_summary" msgid="2405154895437348623">"ପସନ୍ଦର ନେଟ୍‌ୱର୍କ ମୋଡ୍: TDSCDMA / WCDMA"</string>
+    <string name="preferred_network_mode_lte_tdscdma_summary" msgid="2104702896644235637">"ପସନ୍ଦର ନେଟ୍‌ୱର୍କ ମୋଡ୍: LTE / TDSCDMA"</string>
+    <string name="preferred_network_mode_tdscdma_gsm_summary" msgid="4893784445338396204">"ପସନ୍ଦର ନେଟ୍‌ୱର୍କ ମୋଡ୍: TDSCDMA / GSM"</string>
+    <string name="preferred_network_mode_lte_tdscdma_gsm_summary" msgid="1815169717046729757">"ପସନ୍ଦର ନେଟ୍‌ୱର୍କ ମୋଡ୍: LTE/GSM/TDSCDMA"</string>
+    <string name="preferred_network_mode_tdscdma_gsm_wcdma_summary" msgid="2195358773359424099">"ପସନ୍ଦର ନେଟ୍‌ୱର୍କ ମୋଡ୍: TDSCDMA/GSM/WCDMA"</string>
+    <string name="preferred_network_mode_lte_tdscdma_wcdma_summary" msgid="1181424059695667803">"ପସନ୍ଦର ନେଟ୍‌ୱର୍କ ମୋଡ୍: LTE/TDSCDMA/WCDMA"</string>
+    <string name="preferred_network_mode_lte_tdscdma_gsm_wcdma_summary" msgid="2526539326505354382">"ପସନ୍ଦର ନେଟ୍‌ୱର୍କ ମୋଡ୍: LTE/TDSCDMA/GSM/WCDMA"</string>
+    <string name="preferred_network_mode_tdscdma_cdma_evdo_gsm_wcdma_summary" msgid="8195248059196614939">"ପସନ୍ଦର ନେଟ୍‌ୱର୍କ ମୋଡ୍: TDSCDMA/CDMA/EvDo/GSM/WCDMA"</string>
+    <string name="preferred_network_mode_lte_tdscdma_cdma_evdo_gsm_wcdma_summary" msgid="5596733053095592791">"ପସନ୍ଦର ନେଟ୍‌ୱର୍କ ମୋଡ୍: LTE/TDSCDMA/CDMA/EvDo/GSM/WCDMA"</string>
     <string name="call_category" msgid="5863978196309462052">"କଲ୍ କରାଯାଉଛି"</string>
     <string name="network_operator_category" msgid="4830701959205735636">"ନେଟ୍‌ୱର୍କ"</string>
     <string name="enhanced_4g_lte_mode_title" msgid="522191650223239171">"ଉନ୍ନତ 4G LTE ମୋଡ୍‍"</string>
diff --git a/res/values-pt-rPT/strings.xml b/res/values-pt-rPT/strings.xml
index 9deb14a..6a96234 100644
--- a/res/values-pt-rPT/strings.xml
+++ b/res/values-pt-rPT/strings.xml
@@ -112,17 +112,17 @@
     <string name="messageCFB" msgid="3711089705936187129">"Número no caso de estar ocupado"</string>
     <string name="sum_cfb_enabled" msgid="5984198104833116690">"A encaminhar para <xliff:g id="PHONENUMBER">{0}</xliff:g>"</string>
     <string name="sum_cfb_disabled" msgid="4913145177320506827">"Desativado"</string>
-    <string name="disable_cfb_forbidden" msgid="3506984333877998061">"O seu operador não suporta a desativação do reencaminhamento de chamadas quando o telemóvel está ocupado."</string>
+    <string name="disable_cfb_forbidden" msgid="3506984333877998061">"O seu operador não suporta a desativação do encaminhamento de chamadas quando o telemóvel está ocupado."</string>
     <string name="labelCFNRy" msgid="1736067178393744351">"Quando não tiver atendido"</string>
     <string name="messageCFNRy" msgid="672317899884380374">"Número no caso de não atender"</string>
     <string name="sum_cfnry_enabled" msgid="6955775691317662910">"A encaminhar para <xliff:g id="PHONENUMBER">{0}</xliff:g>"</string>
     <string name="sum_cfnry_disabled" msgid="3884684060443538097">"Desativado"</string>
-    <string name="disable_cfnry_forbidden" msgid="4308233959150658058">"O operador não suporta a desativação do reencaminhamento de chamadas quando o telemóvel não atende."</string>
+    <string name="disable_cfnry_forbidden" msgid="4308233959150658058">"O operador não suporta a desativação do encaminhamento de chamadas quando o telemóvel não atende."</string>
     <string name="labelCFNRc" msgid="2614827454402079766">"Quando estiver inacessível"</string>
     <string name="messageCFNRc" msgid="6380695421020295119">"Número no caso de estar inacessível"</string>
     <string name="sum_cfnrc_enabled" msgid="7010898346095497421">"A encaminhar para <xliff:g id="PHONENUMBER">{0}</xliff:g>"</string>
     <string name="sum_cfnrc_disabled" msgid="2684474391807469832">"Desativado"</string>
-    <string name="disable_cfnrc_forbidden" msgid="5646361343094064333">"O seu operador não suporta a desativação do reencaminhamento de chamadas quando o telemóvel não está acessível."</string>
+    <string name="disable_cfnrc_forbidden" msgid="5646361343094064333">"O seu operador não suporta a desativação do encaminhamento de chamadas quando o telemóvel não está acessível."</string>
     <string name="updating_title" msgid="6146755386174019046">"Definições de chamadas"</string>
     <string name="call_settings_admin_user_only" msgid="4526094783818216374">"As definições de chamadas só podem ser alteradas pelo utilizador gestor."</string>
     <string name="call_settings_with_label" msgid="3401177261468593519">"Definições (<xliff:g id="SUBSCRIPTIONLABEL">%s</xliff:g>)"</string>
@@ -770,7 +770,7 @@
     <string name="supp_service_closed_user_group_call" msgid="5761735840904590950">"A chamada pertence a um grupo de utilizadores fechado."</string>
     <string name="supp_service_incoming_calls_barred" msgid="3248813207307882723">"As chamadas recebidas foram barradas."</string>
     <string name="supp_service_outgoing_calls_barred" msgid="1962644621292054081">"As chamadas efetuadas foram barradas."</string>
-    <string name="supp_service_call_forwarding_active" msgid="1253134771682248735">"O reencaminhamento de chamadas está ativado."</string>
+    <string name="supp_service_call_forwarding_active" msgid="1253134771682248735">"O encaminhamento de chamadas está ativado."</string>
     <string name="supp_service_additional_call_forwarded" msgid="5228624725214727315">"A chamada adicional foi reencaminhada."</string>
     <string name="supp_service_additional_ect_connected" msgid="6396964292513707102">"A transferência da chamada explícita foi concluída."</string>
     <string name="supp_service_additional_ect_connecting" msgid="5443373059716058480">"A transferência da chamada explícita está em curso."</string>
diff --git a/res/values-te/strings.xml b/res/values-te/strings.xml
index 12b2931..dd6cc45 100644
--- a/res/values-te/strings.xml
+++ b/res/values-te/strings.xml
@@ -534,7 +534,7 @@
     <string name="dial_emergency_calling_not_available" msgid="5675557523782491826">"అత్యవసర కాలింగ్ అందుబాటులో లేదు"</string>
     <string name="police_type_description" msgid="5324410799919829693">"పోలీస్"</string>
     <string name="ambulance_type_description" msgid="4114815025408089866">"అంబులెన్స్‌"</string>
-    <string name="fire_type_description" msgid="7145996705197064710">"అగ్ని"</string>
+    <string name="fire_type_description" msgid="7145996705197064710">"అగ్నిమాపక శాఖ"</string>
     <string name="description_concat_format" msgid="7141070875487870177">"%1$s, %2$s"</string>
     <string name="dialerKeyboardHintText" msgid="9192914825413747792">"డయల్ చేయడానికి కీబోర్డ్‌ను ఉపయోగించండి"</string>
     <string name="onscreenHoldText" msgid="2285258239691145872">"హోల్డ్ చేయి"</string>
diff --git a/res/values/strings.xml b/res/values/strings.xml
index 7b3af07..27130ac 100644
--- a/res/values/strings.xml
+++ b/res/values/strings.xml
@@ -1887,4 +1887,209 @@
     <string name="supp_service_over_ut_precautions_roaming_dual_sim">To use <xliff:g id="supp service">%1$s</xliff:g>, make sure mobile data and data roaming are turned on for SIM <xliff:g id="sim number">%2$d</xliff:g>. You can change these in mobile network settings.</string>
     <!-- supplementary services over ut precaution exit dialog choice -->
     <string name="supp_service_over_ut_precautions_dialog_dismiss">Dismiss</string>
+
+    <!-- Data Connection Enable. Only shown in diagnostic screen, so precise translation is not needed. -->
+    <string name="radio_info_data_connection_enable">Enable Data Connection</string>
+    <!-- Data Connection Disable. Only shown in diagnostic screen, so precise translation is not needed. -->
+    <string name="radio_info_data_connection_disable">Disable Data Connection</string>
+
+    <!-- VoLTE provisioning flag on. Only shown in diagnostic screen, so precise translation is not needed. -->
+    <string name="volte_provisioned_switch_string">VoLTE Provisioned</string>
+
+    <!-- Video calling provisioning flag on. Only shown in diagnostic screen, so precise translation is not needed. -->
+    <string name="vt_provisioned_switch_string">Video Calling Provisioned</string>
+
+    <!-- Wifi Calling provisioning flag on. Only shown in diagnostic screen, so precise translation is not needed. -->
+    <string name="wfc_provisioned_switch_string">Wifi Calling Provisioned</string>
+
+    <!-- EAB provisioning flag on. Only shown in diagnostic screen, so precise translation is not needed. -->
+    <string name="eab_provisioned_switch_string">EAB/Presence Provisioned</string>
+
+    <!-- Cbrs enable disable flag. Only shown in diagnostic screen, so precise translation is not needed -->
+    <string name="cbrs_data_switch_string">Cbrs Data</string>
+
+    <!-- Dsds enable/disable flag. Only shown in diagnostic screen, so precise translation is not needed, [CHAR LIMIT=none] -->
+    <string name="dsds_switch_string">Enable DSDS</string>
+
+    <!-- UI debug setting: Enable/Disable DSDS [CHAR LIMIT=none] -->
+    <string name="dsds_dialog_title">Restart Device?</string>
+
+    <!-- UI debug setting: Enable/Disable DSDS [CHAR LIMIT=none] -->
+    <string name="dsds_dialog_message">You need to restart your device to change this setting.</string>
+
+    <!-- UI debug setting: Enable/Disable DSDS [CHAR LIMIT=none] -->
+    <string name="dsds_dialog_confirm">Restart</string>
+
+    <!-- UI debug setting: Enable/Disable DSDS [CHAR LIMIT=none] -->
+    <string name="dsds_dialog_cancel">Cancel</string>
+
+    <!-- Title for controlling on/off for Mobile phone's radio power. Only shown in diagnostic screen, so precise translation is not needed. -->
+    <string name="radio_info_radio_power">Mobile Radio Power</string>
+
+    <!-- Phone Info screen. Menu item label.  Used for diagnostic info screens, precise translation isn't needed -->
+    <string name="radioInfo_menu_viewADN">View SIM Address Book</string>
+    <!-- Phone Info screen. Menu item label.  Used for diagnostic info screens, precise translation isn't needed -->
+    <string name="radioInfo_menu_viewFDN">View Fixed Dialing Numbers</string>
+    <!-- Phone Info screen. Menu item label.  Used for diagnostic info screens, precise translation isn't needed -->
+    <string name="radioInfo_menu_viewSDN">View Service Dialing Numbers</string>
+    <!-- Phone Info screen. Menu item label.  Used for diagnostic info screens, precise translation isn't needed -->
+    <string name="radioInfo_menu_getIMS">IMS Service Status</string>
+
+    <!-- Phone Info screen. IMS Registration Title.  Used for diagnostic info screens, precise translation isn't needed -->
+    <string name="radio_info_ims_reg_status_title">IMS Status</string>
+
+    <!-- Phone Info screen. IMS Status - Registered.  Used for diagnostic info screens, precise translation isn't needed -->
+    <string name="radio_info_ims_reg_status_registered">Registered</string>
+    <!-- Phone Info screen. Ims Status - Unregistered.  Used for diagnostic info screens, precise translation isn't needed -->
+    <string name="radio_info_ims_reg_status_not_registered">Not Registered</string>
+
+    <!-- Phone Info screen. Ims Feature Status label.  Used for diagnostic info screens, precise translation isn't needed -->
+    <string name="radio_info_ims_feature_status_available">Available</string>
+    <!-- Phone Info screen. Ims Feature status label.  Used for diagnostic info screens, precise translation isn't needed -->
+    <string name="radio_info_ims_feature_status_unavailable">Unavailable</string>
+
+    <!-- Phone Info screen. IMS Registration.  Used for diagnostic info screens, precise translation isn't needed -->
+    <string name="radio_info_ims_reg_status">IMS Registration: <xliff:g id="status" example="registered">%1$s</xliff:g>\u000AVoice over LTE: <xliff:g id="availability" example="available">%2$s</xliff:g>\u000AVoice over WiFi: <xliff:g id="availability" example="available">%3$s</xliff:g>\u000AVideo Calling: <xliff:g id="availability" example="available">%4$s</xliff:g>\u000AUT Interface: <xliff:g id="availability" example="available">%5$s</xliff:g></string>
+
+    <!-- Phone Info screen. Status label.  Used for diagnostic info screens, precise translation isn't needed -->
+    <string name="radioInfo_service_in">In Service</string>
+    <!-- Phone Info screen. Status label.  Used for diagnostic info screens, precise translation isn't needed -->
+    <string name="radioInfo_service_out">Out of Service</string>
+    <!-- Phone Info screen. Status label.  Used for diagnostic info screens, precise translation isn't needed -->
+    <string name="radioInfo_service_emergency">Emergency Calls Only</string>
+    <!-- Phone Info screen. Status label.  Used for diagnostic info screens, precise translation isn't needed -->
+    <string name="radioInfo_service_off">Radio Off</string>
+
+    <!-- Phone Info screen. Status label.  Used for diagnostic info screens, precise translation isn't needed -->
+    <string name="radioInfo_roaming_in">Roaming</string>
+    <!-- Phone Info screen. Status label.  Used for diagnostic info screens, precise translation isn't needed -->
+    <string name="radioInfo_roaming_not">Not Roaming</string>
+
+    <!-- Phone Info screen. Status label.  Used for diagnostic info screens, precise translation isn't needed -->
+    <string name="radioInfo_phone_idle">Idle</string>
+    <!-- Phone Info screen. Status label.  Used for diagnostic info screens, precise translation isn't needed -->
+    <string name="radioInfo_phone_ringing">Ringing</string>
+    <!-- Phone Info screen. Status label.  Used for diagnostic info screens, precise translation isn't needed -->
+    <string name="radioInfo_phone_offhook">Call in Progress</string>
+
+    <!-- Phone Info screen. Status label.  Used for diagnostic info screens, precise translation isn't needed -->
+    <string name="radioInfo_data_disconnected">Disconnected</string>
+    <!-- Phone Info screen. Status label.  Used for diagnostic info screens, precise translation isn't needed -->
+    <string name="radioInfo_data_connecting">Connecting</string>
+    <!-- Phone Info screen. Status label.  Used for diagnostic info screens, precise translation isn't needed -->
+    <string name="radioInfo_data_connected">Connected</string>
+    <!-- Phone Info screen. Status label.  Used for diagnostic info screens, precise translation isn't needed -->
+    <string name="radioInfo_data_suspended">Suspended</string>
+
+    <!-- Used for diagnostic info screens, precise translation isn't needed -->
+    <string name="radioInfo_unknown">Unknown</string>
+    <!-- Phone Info screen. Units shown after a value.  Used for diagnostic info screens, precise translation isn't needed -->
+    <string name="radioInfo_display_packets">pkts</string>
+    <!-- Phone Info screen. Units shown after a value.  Used for diagnostic info screens, precise translation isn't needed -->
+    <string name="radioInfo_display_bytes">bytes</string>
+    <!-- Phone Info screen. Units shown after a value.  Used for diagnostic info screens, precise translation isn't needed -->
+    <string name="radioInfo_display_dbm">dBm</string>
+    <!-- Phone Info screen. Units shown after a value.  Used for diagnostic info screens, precise translation isn't needed -->
+    <string name="radioInfo_display_asu">asu</string>
+    <!-- Used for diagnostic info screens, precise translation isn't needed -->
+    <string name="radioInfo_lac">LAC</string>
+    <!-- Used for diagnostic info screens, precise translation isn't needed -->
+    <string name="radioInfo_cid">CID</string>
+
+
+    <!-- Radio Info screen. Label for a status item.  Used for diagnostic info screens, precise translation isn't needed -->
+    <string name="radio_info_subid">Current subId:</string>
+    <!-- Radio Info screen. Label for a status item.  Used for diagnostic info screens, precise translation isn't needed -->
+    <string name="radio_info_dds">SubId of default data SIM:</string>
+    <!-- Radio Info screen. Label for a status item.  Used for diagnostic info screens, precise translation isn't needed -->
+    <string name="radio_info_dl_kbps">DL Bandwidth (kbps):</string>
+    <!-- Radio Info screen. Label for a status item.  Used for diagnostic info screens, precise translation isn't needed -->
+    <string name="radio_info_ul_kbps">UL Bandwidth (kbps):</string>
+    <!-- Radio Info screen. Label for a status item.  Used for diagnostic info screens, precise translation isn't needed -->
+    <string name="radio_info_signal_location_label">Cell Location Info (deprecated):</string>
+    <!-- Radio Info screen. Label for a status item.  Used for diagnostic info screens, precise translation isn't needed -->
+    <string name="radio_info_phy_chan_config">LTE Physical Channel Configuration:</string>
+    <!-- Radio Info screen. Label for a status item.  Used for diagnostic info screens, precise translation isn't needed -->
+    <string name="radio_info_cell_info_refresh_rate">Cell Info Refresh Rate:</string>
+    <!-- Radio Info screen. Label for a status item.  Used for diagnostic info screens, precise translation isn't needed -->
+    <string name="radio_info_cellinfo_label">All Cell Measurement Info:</string>
+    <!-- Radio Info screen. Label for a status item.  Used for diagnostic info screens, precise translation isn't needed -->
+    <string name="radio_info_gprs_service_label">Data Service:</string>
+    <!-- Radio Info screen. Label for a status item.  Used for diagnostic info screens, precise translation isn't needed -->
+    <string name="radio_info_roaming_label">Roaming:</string>
+    <!-- Radio Info screen. Label for a status item.  Used for diagnostic info screens, precise translation isn't needed -->
+    <string name="radio_info_imei_label">IMEI:</string>
+    <!-- Radio Info screen. Label for a status item.  Used for diagnostic info screens, DO NOT TRANSLATE. -->
+    <string name="radio_info_imsi_label">IMSI:</string>
+    <!-- Radio Info screen. Label for a status item.  Used for diagnostic info screens, precise translation isn't needed -->
+    <string name="radio_info_call_redirect_label">Call Redirect:</string>
+    <!-- Radio Info screen. Label for a status item.  Used for diagnostic info screens, precise translation isn't needed -->
+    <string name="radio_info_ppp_resets_label">Number of PPP Reset Since Boot:</string>
+    <!-- Radio Info screen. Label for a status item.  Used for diagnostic info screens, precise translation isn't needed -->
+    <string name="radio_info_current_network_label">Current Network:</string>
+    <!-- Radio Info screen. Label for a status item.  Used for diagnostic info screens, precise translation isn't needed -->
+    <string name="radio_info_ppp_received_label">Data Received:</string>
+    <!-- Radio Info screen. Label for a status item.  Used for diagnostic info screens, precise translation isn't needed -->
+    <string name="radio_info_gsm_service_label">Voice Service:</string>
+    <!-- Radio Info screen. Label for a status item.  Used for diagnostic info screens, precise translation isn't needed -->
+    <string name="radio_info_signal_strength_label">Signal Strength:</string>
+    <!-- Radio Info screen. Label for a status item.  Used for diagnostic info screens, precise translation isn't needed -->
+    <string name="radio_info_call_status_label">Voice Call Status:</string>
+    <!-- Radio Info screen. Label for a status item.  Used for diagnostic info screens, precise translation isn't needed -->
+    <string name="radio_info_ppp_sent_label">Data Sent:</string>
+    <!-- Radio Info screen. Label for a status item.  Used for diagnostic info screens, precise translation isn't needed -->
+    <string name="radio_info_message_waiting_label">Message Waiting:</string>
+    <!-- Radio Info screen. Label for a status item.  Used for diagnostic info screens, precise translation isn't needed -->
+    <string name="radio_info_phone_number_label">Phone Number:</string>
+    <!-- Radio Info screen. Label for a status item.  Used for diagnostic info screens, precise translation isn't needed -->
+    <string name="radio_info_band_mode_label">Select Radio Band</string>
+    <!-- Radio Info screen. Label for a status item.  Used for diagnostic info screens, precise translation isn't needed -->
+    <string name="radio_info_voice_network_type_label">Voice Network Type:</string>
+    <!-- Radio Info screen. Label for a status item.  Used for diagnostic info screens, precise translation isn't needed -->
+    <string name="radio_info_data_network_type_label">Data Network Type:</string>
+    <!-- Radio Info screen. Label for a status item.  Used for diagnostic info screens, precise translation isn't needed -->
+    <string name="phone_index_label">Select phone index</string>
+    <!-- Radio Info screen. Label for a status item.  Used for diagnostic info screens, precise translation isn't needed -->
+    <string name="radio_info_set_perferred_label">Set Preferred Network Type:</string>
+    <!-- Radio Info screen. Label for a status item.  Used for diagnostic info screens, precise translation isn't needed -->
+    <string name="radio_info_ping_hostname_v4">Ping Hostname(www.google.com) IPv4:</string>
+    <!-- Radio Info screen. Label for a status item.  Used for diagnostic info screens, precise translation isn't needed -->
+    <string name="radio_info_ping_hostname_v6">Ping Hostname(www.google.com) IPv6:</string>
+    <!-- Radio Info screen. Label for a status item.  Used for diagnostic info screens, precise translation isn't needed -->
+    <string name="radio_info_http_client_test">HTTP Client Test:</string>
+    <!-- Radio Info screen. Label for a status item.  Used for diagnostic info screens, precise translation isn't needed -->
+    <string name="ping_test_label">Run Ping Test</string>
+    <!-- Radio Info screen. Label for a status item.  Used for diagnostic info screens, precise translation isn't needed -->
+    <string name="radio_info_smsc_label">SMSC:</string>
+    <!-- Radio Info screen. Label for a status item.  Used for diagnostic info screens, precise translation isn't needed -->
+    <string name="radio_info_smsc_update_label">Update</string>
+    <!-- Radio Info screen. Label for a status item.  Used for diagnostic info screens, precise translation isn't needed -->
+    <string name="radio_info_smsc_refresh_label">Refresh</string>
+    <!-- Radio Info screen. Label for a status item.  Used for diagnostic info screens, precise translation isn't needed -->
+    <string name="radio_info_toggle_dns_check_label">Toggle DNS Check</string>
+    <!-- Radio Info screen. Label for a status item.  Used for diagnostic info screens, precise translation isn't needed -->
+    <string name="oem_radio_info_label">OEM-specific Info/Settings</string>
+
+    <!-- Band Mode Selection -->
+    <!-- Band mode screen.  Title of activity. -->
+    <string name="band_mode_title">Set Radio Band Mode</string>
+    <!-- Band mode screen.  Loading message. -->
+    <string name="band_mode_loading">Loading Band List\u2026</string>
+    <!-- Band mode screen. Button caption to set the bandmode. -->
+    <string name="band_mode_set">Set</string>
+    <!-- Band mode screen. Status message when unsuccessful. -->
+    <string name="band_mode_failed">Unsuccessful</string>
+    <!-- Band mode screen. Statusm essage when successful. -->
+    <string name="band_mode_succeeded">Successful</string>
+
+    <!-- The title of the activity to see phone info -->
+    <string name="phone_info_label" product="tablet">Tablet info</string>
+    <!-- The title of the activity to see phone info -->
+    <string name="phone_info_label" product="default">Phone info</string>
+
+    <!-- Carrier Provisioning Info [CHAR LIMIT=NONE] -->
+    <string name="carrier_provisioning">Carrier Provisioning Info</string>
+    <!-- Trigger Carrier Provisioning [CHAR LIMIT=NONE] -->
+    <string name="trigger_carrier_provisioning">Trigger Carrier Provisioning</string>
+
 </resources>
diff --git a/res/values/styles.xml b/res/values/styles.xml
index 1d5e7dc..df409c7 100644
--- a/res/values/styles.xml
+++ b/res/values/styles.xml
@@ -45,6 +45,23 @@
         <item name="android:layout_height">wrap_content</item>
     </style>
 
+    <style name="RadioInfo_entry_layout">
+        <item name="android:orientation">horizontal</item>
+        <item name="android:layout_width">wrap_content</item>
+        <item name="android:layout_height">wrap_content</item>
+    </style>
+
+    <style name="info_value">
+        <item name="android:layout_height">wrap_content</item>
+        <item name="android:layout_width">wrap_content</item>
+        <item name="android:textAppearance">@style/TextAppearance.info_value</item>
+    </style>
+
+    <style name="form_value">
+        <item name="android:layout_height">wrap_content</item>
+        <item name="android:layout_width">match_parent</item>
+    </style>
+
     <style name="TextAppearance" parent="android:TextAppearance">
     </style>
 
@@ -53,6 +70,11 @@
         <item name="android:textStyle">bold</item>
     </style>
 
+    <style name="TextAppearance.info_value">
+        <item name="android:textSize">14sp</item>
+        <item name="android:textStyle">normal</item>
+    </style>
+
     <!-- Preference Style for the phone number preferences -->
     <style name="EditPhoneNumberPreference">
         <item name="enableButtonText">@string/enable</item>
diff --git a/src/com/android/phone/CallFeaturesSetting.java b/src/com/android/phone/CallFeaturesSetting.java
index 320fc24..29df8b8 100644
--- a/src/com/android/phone/CallFeaturesSetting.java
+++ b/src/com/android/phone/CallFeaturesSetting.java
@@ -202,7 +202,8 @@
         if (DBG) log("onCreate: Intent is " + getIntent());
 
         // Make sure we are running as an admin user.
-        if (!UserManager.get(this).isAdminUser()) {
+        UserManager userManager = (UserManager) getSystemService(Context.USER_SERVICE);
+        if (!userManager.isAdminUser()) {
             Toast.makeText(this, R.string.call_settings_admin_user_only,
                     Toast.LENGTH_SHORT).show();
             finish();
diff --git a/src/com/android/phone/CarrierConfigLoader.java b/src/com/android/phone/CarrierConfigLoader.java
index 18ff034..ad7a2b2 100644
--- a/src/com/android/phone/CarrierConfigLoader.java
+++ b/src/com/android/phone/CarrierConfigLoader.java
@@ -194,7 +194,8 @@
 
                 case EVENT_SYSTEM_UNLOCKED:
                 {
-                    for (int i = 0; i < TelephonyManager.from(mContext).getMaxPhoneCount(); ++i) {
+                    for (int i = 0; i < TelephonyManager.from(mContext)
+                            .getSupportedModemCount(); ++i) {
                         // When user unlock device, we should only try to send broadcast again if we
                         // have sent it before unlock. This will avoid we try to load carrier config
                         // when SIM is still loading when unlock happens.
@@ -211,7 +212,8 @@
                     // Only update if there are cached config removed to avoid updating config for
                     // unrelated packages.
                     if (clearCachedConfigForPackage(carrierPackageName)) {
-                        int numPhones = TelephonyManager.from(mContext).getMaxPhoneCount();
+                        int numPhones = TelephonyManager.from(mContext)
+                                .getSupportedModemCount();
                         for (int i = 0; i < numPhones; ++i) {
                             updateConfigForPhoneId(i);
                         }
@@ -523,7 +525,7 @@
         pkgFilter.addDataScheme("package");
         context.registerReceiver(mPackageReceiver, pkgFilter);
 
-        int numPhones = TelephonyManager.from(context).getMaxPhoneCount();
+        int numPhones = TelephonyManager.from(context).getSupportedModemCount();
         mConfigFromDefaultApp = new PersistableBundle[numPhones];
         mConfigFromCarrierApp = new PersistableBundle[numPhones];
         mOverrideConfigs = new PersistableBundle[numPhones];
diff --git a/src/com/android/phone/EmergencyInfoGroup.java b/src/com/android/phone/EmergencyInfoGroup.java
index 9e7121d..186de03 100644
--- a/src/com/android/phone/EmergencyInfoGroup.java
+++ b/src/com/android/phone/EmergencyInfoGroup.java
@@ -153,7 +153,7 @@
     private Drawable getCircularUserIcon() {
         final UserManager userManager = (UserManager) getContext().getSystemService(
                 Context.USER_SERVICE);
-        Bitmap bitmapUserIcon = userManager.getUserIcon(UserHandle.getCallingUserId());
+        Bitmap bitmapUserIcon = userManager.getUserIcon();
 
         if (bitmapUserIcon == null) {
             // get default user icon.
diff --git a/src/com/android/phone/NotificationMgr.java b/src/com/android/phone/NotificationMgr.java
index 8c6d23c..6486ae2 100644
--- a/src/com/android/phone/NotificationMgr.java
+++ b/src/com/android/phone/NotificationMgr.java
@@ -64,6 +64,7 @@
 import com.android.internal.telephony.util.NotificationChannelController;
 import com.android.phone.settings.VoicemailSettingsActivity;
 
+import java.util.ArrayList;
 import java.util.HashSet;
 import java.util.Iterator;
 import java.util.List;
@@ -375,10 +376,9 @@
                     .setOnlyAlertOnce(isRefresh);
 
             final Notification notification = builder.build();
-            List<UserInfo> users = mUserManager.getUsers(true);
-            for (UserInfo user : users) {
-                final UserHandle userHandle = user.getUserHandle();
-                if (!mUserManager.hasUserRestriction(
+            List<UserHandle> users = getUsersExcludeDying();
+            for (UserHandle userHandle : users) {
+                if (!hasUserRestriction(
                         UserManager.DISALLOW_OUTGOING_CALLS, userHandle)
                         && !mUserManager.isManagedProfile(userHandle.getIdentifier())) {
                     if (!maybeSendVoicemailNotificationUsingDefaultDialer(phone, vmCount, vmNumber,
@@ -392,10 +392,9 @@
                 }
             }
         } else {
-            List<UserInfo> users = mUserManager.getUsers(true /* excludeDying */);
-            for (UserInfo user : users) {
-                final UserHandle userHandle = user.getUserHandle();
-                if (!mUserManager.hasUserRestriction(
+            List<UserHandle> users = getUsersExcludeDying();
+            for (UserHandle userHandle : users) {
+                if (!hasUserRestriction(
                         UserManager.DISALLOW_OUTGOING_CALLS, userHandle)
                         && !mUserManager.isManagedProfile(userHandle.getIdentifier())) {
                     if (!maybeSendVoicemailNotificationUsingDefaultDialer(phone, 0, null, null,
@@ -410,6 +409,22 @@
         }
     }
 
+    private List<UserHandle> getUsersExcludeDying() {
+        long[] serialNumbersOfUsers =
+                mUserManager.getSerialNumbersOfUsers(/* excludeDying= */ true);
+        List<UserHandle> users = new ArrayList<>(serialNumbersOfUsers.length);
+        for (long serialNumber : serialNumbersOfUsers) {
+            users.add(mUserManager.getUserForSerialNumber(serialNumber));
+        }
+        return users;
+    }
+
+    private boolean hasUserRestriction(String restrictionKey, UserHandle userHandle) {
+        final List<UserManager.EnforcingUser> sources = mUserManager
+                .getUserRestrictionSources(restrictionKey, userHandle);
+        return (sources != null && !sources.isEmpty());
+    }
+
     /**
      * Sends a broadcast with the voicemail notification information to the default dialer. This
      * method is also used to indicate to the default dialer when to clear the
diff --git a/src/com/android/phone/PhoneDisplayMessage.java b/src/com/android/phone/PhoneDisplayMessage.java
index 2b86a61..199fbb8 100644
--- a/src/com/android/phone/PhoneDisplayMessage.java
+++ b/src/com/android/phone/PhoneDisplayMessage.java
@@ -78,10 +78,11 @@
         sDisplayMessageDialog.getWindow().setType(
                 WindowManager.LayoutParams.TYPE_SYSTEM_DIALOG);
         sDisplayMessageDialog.getWindow().addFlags(
-                WindowManager.LayoutParams.FLAG_DIM_BEHIND);
+                WindowManager.LayoutParams.FLAG_DIM_BEHIND
+                | WindowManager.LayoutParams.FLAG_TURN_SCREEN_ON
+                | WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
 
         sDisplayMessageDialog.show();
-        PhoneGlobals.getInstance().wakeUpScreen();
     }
 
     /**
@@ -91,6 +92,9 @@
         if (DBG) log("Dissmissing Display Info Record...");
 
         if (sDisplayMessageDialog != null) {
+            sDisplayMessageDialog.getWindow().clearFlags(
+                    WindowManager.LayoutParams.FLAG_TURN_SCREEN_ON
+                    | WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
             sDisplayMessageDialog.dismiss();
             sDisplayMessageDialog = null;
         }
diff --git a/src/com/android/phone/PhoneGlobals.java b/src/com/android/phone/PhoneGlobals.java
index 8094812..d7ba19c 100644
--- a/src/com/android/phone/PhoneGlobals.java
+++ b/src/com/android/phone/PhoneGlobals.java
@@ -37,7 +37,6 @@
 import android.os.Message;
 import android.os.PersistableBundle;
 import android.os.PowerManager;
-import android.os.SystemClock;
 import android.os.SystemProperties;
 import android.os.UserManager;
 import android.preference.PreferenceManager;
@@ -271,7 +270,8 @@
                     // not want this running if the device is still in the FBE encrypted state.
                     // This is the same procedure that is triggered in the SipIncomingCallReceiver
                     // upon BOOT_COMPLETED.
-                    UserManager userManager = UserManager.get(sMe);
+                    UserManager userManager =
+                            (UserManager) sMe.getSystemService(Context.USER_SERVICE);
                     if (userManager != null && userManager.isUserUnlocked()) {
                         SipUtil.startSipService();
                     }
@@ -496,19 +496,6 @@
         mPUKEntryProgressDialog = dialog;
     }
 
-    /**
-     * If we are not currently keeping the screen on, then poke the power
-     * manager to wake up the screen for the user activity timeout duration.
-     */
-    /* package */ void wakeUpScreen() {
-        synchronized (this) {
-            if (mWakeState == WakeState.SLEEP) {
-                if (DBG) Log.d(LOG_TAG, "pulse screen lock");
-                mPowerManager.wakeUp(SystemClock.uptimeMillis(), "android.phone:WAKE");
-            }
-        }
-    }
-
     KeyguardManager getKeyguardManager() {
         return mKeyguardManager;
     }
diff --git a/src/com/android/phone/PhoneInterfaceManager.java b/src/com/android/phone/PhoneInterfaceManager.java
index a847d66..28646b9 100755
--- a/src/com/android/phone/PhoneInterfaceManager.java
+++ b/src/com/android/phone/PhoneInterfaceManager.java
@@ -18,6 +18,7 @@
 
 import static android.content.pm.PackageManager.PERMISSION_GRANTED;
 
+import static com.android.internal.telephony.PhoneConstants.PHONE_TYPE_IMS;
 import static com.android.internal.telephony.PhoneConstants.SUBSCRIPTION_KEY;
 
 import android.Manifest.permission;
@@ -64,6 +65,7 @@
 import android.telephony.Annotation.ApnType;
 import android.telephony.CarrierConfigManager;
 import android.telephony.CarrierRestrictionRules;
+import android.telephony.CellIdentity;
 import android.telephony.CellInfo;
 import android.telephony.CellInfoGsm;
 import android.telephony.CellInfoWcdma;
@@ -150,6 +152,8 @@
 import com.android.internal.telephony.emergency.EmergencyNumberTracker;
 import com.android.internal.telephony.euicc.EuiccConnector;
 import com.android.internal.telephony.ims.ImsResolver;
+import com.android.internal.telephony.imsphone.ImsPhone;
+import com.android.internal.telephony.imsphone.ImsPhoneCallTracker;
 import com.android.internal.telephony.metrics.TelephonyMetrics;
 import com.android.internal.telephony.uicc.IccCardApplicationStatus.AppType;
 import com.android.internal.telephony.uicc.IccIoResult;
@@ -257,6 +261,8 @@
     private static final int EVENT_ENABLE_MODEM_DONE = 69;
     private static final int CMD_GET_MODEM_STATUS = 70;
     private static final int EVENT_GET_MODEM_STATUS_DONE = 71;
+    private static final int CMD_SET_FORBIDDEN_PLMNS = 72;
+    private static final int EVENT_SET_FORBIDDEN_PLMNS_DONE = 73;
 
     // Parameters of select command.
     private static final int SELECT_COMMAND = 0xA4;
@@ -1072,11 +1078,13 @@
                     try {
                         if (ar.exception != null) {
                             Log.e(LOG_TAG, "Exception retrieving CellInfo=" + ar.exception);
-                            cb.onError(TelephonyManager.CellInfoCallback.ERROR_MODEM_ERROR,
-                                    new android.os.ParcelableException(ar.exception));
+                            cb.onError(
+                                    TelephonyManager.CellInfoCallback.ERROR_MODEM_ERROR,
+                                    ar.exception.getClass().getName(),
+                                    ar.exception.toString());
                         } else if (ar.result == null) {
                             Log.w(LOG_TAG, "Timeout Waiting for CellInfo!");
-                            cb.onError(TelephonyManager.CellInfoCallback.ERROR_TIMEOUT, null);
+                            cb.onError(TelephonyManager.CellInfoCallback.ERROR_TIMEOUT, null, null);
                         } else {
                             // use the result as returned
                             cb.onCellInfo((List<CellInfo>) ar.result);
@@ -1164,6 +1172,50 @@
                     }
                     notifyRequester(request);
                     break;
+                case EVENT_SET_FORBIDDEN_PLMNS_DONE:
+                    ar = (AsyncResult) msg.obj;
+                    request = (MainThreadRequest) ar.userObj;
+                    if (ar.exception == null && ar.result != null) {
+                        request.result = ar.result;
+                    } else {
+                        request.result = -1;
+                        loge("Failed to set Forbidden Plmns");
+                        if (ar.result == null) {
+                            loge("setForbidenPlmns: Empty response");
+                        } else if (ar.exception != null) {
+                            loge("setForbiddenPlmns: Exception: " + ar.exception);
+                            request.result = -1;
+                        } else {
+                            loge("setForbiddenPlmns: Unknown exception");
+                        }
+                    }
+                    notifyRequester(request);
+                    break;
+                case CMD_SET_FORBIDDEN_PLMNS:
+                    request = (MainThreadRequest) msg.obj;
+                    uiccCard = getUiccCardFromRequest(request);
+                    if (uiccCard == null) {
+                        loge("setForbiddenPlmns: UiccCard is null");
+                        request.result = -1;
+                        notifyRequester(request);
+                        break;
+                    }
+                    Pair<Integer, List<String>> setFplmnsArgs =
+                            (Pair<Integer, List<String>>) request.argument;
+                    appType = setFplmnsArgs.first;
+                    List<String> fplmns = setFplmnsArgs.second;
+                    uiccApp = uiccCard.getApplicationByType(appType);
+                    if (uiccApp == null) {
+                        loge("setForbiddenPlmns: no app with specified type -- " + appType);
+                        request.result = -1;
+                        loge("Failed to get UICC App");
+                        notifyRequester(request);
+                    } else {
+                        onCompleted = obtainMessage(EVENT_SET_FORBIDDEN_PLMNS_DONE, request);
+                        ((SIMRecords) uiccApp.getIccRecords())
+                                .setForbiddenPlmns(onCompleted, fplmns);
+                    }
+                    break;
                 default:
                     Log.w(LOG_TAG, "MainThreadHandler: unexpected message code: " + msg.what);
                     break;
@@ -2727,7 +2779,7 @@
             if (phone != null) {
                 phone.setDataActivationState(activationState);
             } else {
-                loge("setVoiceActivationState fails with invalid subId: " + subId);
+                loge("setDataActivationState fails with invalid subId: " + subId);
             }
         } finally {
             Binder.restoreCallingIdentity(identity);
@@ -4039,7 +4091,7 @@
             if (response instanceof String[]) {
                 return (String[]) response;
             }
-            // Response is an Exception of some kind,
+            // Response is an Exception of some kind
             // which is signalled to the user as a NULL retval
             return null;
         } finally {
@@ -4047,6 +4099,47 @@
         }
     }
 
+    /**
+     * Set the forbidden PLMN list from the given app type (ex APPTYPE_USIM) on a particular
+     * subscription.
+     *
+     * @param subId the id of the subscription.
+     * @param appType the uicc app type, must be USIM or SIM.
+     * @param fplmns the Forbiden plmns list that needed to be written to the SIM.
+     * @param callingPackage the op Package name.
+     * @return number of fplmns that is successfully written to the SIM.
+     */
+    public int setForbiddenPlmns(
+            int subId, int appType, List<String> fplmns, String callingPackage) {
+        if (!TelephonyPermissions.checkCallingOrSelfReadPhoneState(
+                mApp, subId, callingPackage, "setForbiddenPlmns")) {
+            if (DBG) logv("no permissions for setForbiddenplmns");
+            throw new IllegalStateException("No Permissions for setForbiddenPlmns");
+        }
+        if (appType != TelephonyManager.APPTYPE_USIM && appType != TelephonyManager.APPTYPE_SIM) {
+            loge("setForbiddenPlmnList(): App Type must be USIM or SIM");
+            throw new IllegalArgumentException("Invalid appType: App Type must be USIM or SIM");
+        }
+        if (fplmns == null) {
+            throw new IllegalArgumentException("Fplmn List provided is null");
+        }
+        for (String fplmn : fplmns) {
+            if (!CellIdentity.isValidPlmn(fplmn)) {
+                throw new IllegalArgumentException("Invalid fplmn provided: " + fplmn);
+            }
+        }
+        final long identity = Binder.clearCallingIdentity();
+        try {
+            Object response = sendRequest(
+                    CMD_SET_FORBIDDEN_PLMNS,
+                    new Pair<Integer, List<String>>(new Integer(appType), fplmns),
+                    subId);
+            return (int) response;
+        } finally {
+            Binder.restoreCallingIdentity(identity);
+        }
+    }
+
     @Override
     public String sendEnvelopeWithStatus(int subId, String content) {
         TelephonyPermissions.enforceCallingOrSelfModifyPermissionOrCarrierPrivilege(
@@ -4868,13 +4961,13 @@
     public int getCarrierPrivilegeStatusForUid(int subId, int uid) {
         final Phone phone = getPhone(subId);
         if (phone == null) {
-            loge("getCarrierPrivilegeStatus: Invalid subId");
+            loge("getCarrierPrivilegeStatusForUid: Invalid subId");
             return TelephonyManager.CARRIER_PRIVILEGE_STATUS_NO_ACCESS;
         }
         UiccProfile profile =
                 UiccController.getInstance().getUiccProfileForPhone(phone.getPhoneId());
         if (profile == null) {
-            loge("getCarrierPrivilegeStatus: No UICC");
+            loge("getCarrierPrivilegeStatusForUid: No UICC");
             return TelephonyManager.CARRIER_PRIVILEGE_STATUS_RULES_NOT_LOADED;
         }
         return getCarrierPrivilegeStatusFromCarrierConfigRules(
@@ -4930,7 +5023,7 @@
         }
         UiccCard card = UiccController.getInstance().getUiccCard(phoneId);
         if (card == null) {
-            loge("getCarrierPackageNamesForIntent: No UICC");
+            loge("getCarrierPackageNamesForIntentAndPhone: No UICC");
             return null ;
         }
         return card.getCarrierPackageNamesForIntent(mApp.getPackageManager(), intent);
@@ -6807,7 +6900,7 @@
     }
 
     private void ensureUserRunning(int userId) {
-        if (!mUserManager.isUserRunning(userId)) {
+        if (!mUserManager.isUserRunning(UserHandle.of(userId))) {
             throw new IllegalStateException("User " + userId + " does not exist or not running");
         }
     }
@@ -7222,10 +7315,8 @@
      */
     @Override
     public boolean isDataEnabledForApn(int apnType, int subId, String callingPackage) {
-        if (!TelephonyPermissions.checkCallingOrSelfReadPhoneState(
-                mApp, subId, callingPackage, "isDataEnabledForApn")) {
-            throw new SecurityException("Needs READ_PHONE_STATE for isDataEnabledForApn");
-        }
+        enforceReadPrivilegedPermission("Needs READ_PRIVILEGED_PHONE_STATE for "
+                + "isDataEnabledForApn");
 
         // Now that all security checks passes, perform the operation as ourselves.
         final long identity = Binder.clearCallingIdentity();
@@ -7328,4 +7419,32 @@
             Binder.restoreCallingIdentity(identity);
         }
     }
+
+    /**
+     * Updates whether conference event pacakge handling is enabled.
+     * @param isCepEnabled {@code true} if CEP handling is enabled (default), or {@code false}
+     *                                 otherwise.
+     */
+    @Override
+    public void setCepEnabled(boolean isCepEnabled) {
+        TelephonyPermissions.enforceShellOnly(Binder.getCallingUid(), "setCepEnabled");
+
+        final long identity = Binder.clearCallingIdentity();
+        try {
+            Rlog.i(LOG_TAG, "setCepEnabled isCepEnabled=" + isCepEnabled);
+            for (Phone phone : PhoneFactory.getPhones()) {
+                Phone defaultPhone = phone.getImsPhone();
+                if (defaultPhone != null && defaultPhone.getPhoneType() == PHONE_TYPE_IMS) {
+                    ImsPhone imsPhone = (ImsPhone) defaultPhone;
+                    ImsPhoneCallTracker imsPhoneCallTracker =
+                            (ImsPhoneCallTracker) imsPhone.getCallTracker();
+                    imsPhoneCallTracker.setConferenceEventPackageEnabled(isCepEnabled);
+                    Rlog.i(LOG_TAG, "setCepEnabled isCepEnabled=" + isCepEnabled + ", for imsPhone "
+                            + imsPhone.getMsisdn());
+                }
+            }
+        } finally {
+            Binder.restoreCallingIdentity(identity);
+        }
+    }
 }
diff --git a/src/com/android/phone/TelephonyShellCommand.java b/src/com/android/phone/TelephonyShellCommand.java
index a59c9c4..a34abc0 100644
--- a/src/com/android/phone/TelephonyShellCommand.java
+++ b/src/com/android/phone/TelephonyShellCommand.java
@@ -53,6 +53,10 @@
     private static final String IMS_GET_CARRIER_SERVICE = "get-ims-service";
     private static final String IMS_ENABLE = "enable";
     private static final String IMS_DISABLE = "disable";
+    // Used to disable or enable processing of conference event package data from the network.
+    // This is handy for testing scenarios where CEP data does not exist on a network which does
+    // support CEP data.
+    private static final String IMS_CEP = "conference-event-package";
 
     private static final String SMS_GET_APPS = "get-apps";
     private static final String SMS_GET_DEFAULT_APP = "get-default-app";
@@ -131,6 +135,8 @@
         pw.println("  ims disable [-s SLOT_ID]");
         pw.println("    disables IMS for the SIM slot specified, or for the default voice SIM");
         pw.println("    slot if none is specified.");
+        pw.println("  ims conference-event-package [enable/disable]");
+        pw.println("    enables or disables handling or network conference event package data.");
     }
 
     private void onHelpSms() {
@@ -190,6 +196,9 @@
             case IMS_DISABLE: {
                 return handleDisableIms();
             }
+            case IMS_CEP: {
+                return handleCepChange();
+            }
         }
 
         return -1;
@@ -466,6 +475,22 @@
         return 0;
     }
 
+    private int handleCepChange() {
+        Log.i(LOG_TAG, "handleCepChange");
+        String opt = getNextArg();
+        if (opt == null) {
+            return -1;
+        }
+        boolean isCepEnabled = opt.equals("enable");
+
+        try {
+            mInterface.setCepEnabled(isCepEnabled);
+        } catch (RemoteException e) {
+            return -1;
+        }
+        return 0;
+    }
+
     private int getDefaultSlot() {
         int slotId = SubscriptionManager.getDefaultVoicePhoneId();
         if (slotId <= SubscriptionManager.INVALID_SIM_SLOT_INDEX
diff --git a/src/com/android/phone/settings/BandMode.java b/src/com/android/phone/settings/BandMode.java
new file mode 100644
index 0000000..853075a
--- /dev/null
+++ b/src/com/android/phone/settings/BandMode.java
@@ -0,0 +1,255 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.phone.settings;
+
+import android.app.Activity;
+import android.content.DialogInterface;
+import android.os.AsyncResult;
+import android.os.Bundle;
+import android.os.Handler;
+import android.os.Message;
+import android.util.Log;
+import android.view.View;
+import android.view.Window;
+import android.widget.AdapterView;
+import android.widget.ArrayAdapter;
+import android.widget.ListView;
+
+import androidx.appcompat.app.AlertDialog;
+
+import com.android.internal.telephony.Phone;
+import com.android.internal.telephony.PhoneFactory;
+import com.android.phone.R;
+
+/**
+ * Radio Band Mode Selection Class
+ *
+ * It will query baseband about all available band modes and display them
+ * in screen. It will display all six band modes if the query failed.
+ *
+ * After user select one band, it will send the selection to baseband.
+ *
+ * It will alter user the result of select operation and exit, no matter success
+ * or not.
+ *
+ */
+public class BandMode extends Activity {
+    private static final String LOG_TAG = "phone";
+    private static final boolean DBG = false;
+
+    private static final int EVENT_BAND_SCAN_COMPLETED = 100;
+    private static final int EVENT_BAND_SELECTION_DONE = 200;
+
+    //Directly maps to RIL_RadioBandMode from ril.h
+    private static final String[] BAND_NAMES = new String[] {
+            "Automatic",
+            "Europe",
+            "United States",
+            "Japan",
+            "Australia",
+            "Australia 2",
+            "Cellular 800",
+            "PCS",
+            "Class 3 (JTACS)",
+            "Class 4 (Korea-PCS)",
+            "Class 5",
+            "Class 6 (IMT2000)",
+            "Class 7 (700Mhz-Upper)",
+            "Class 8 (1800Mhz-Upper)",
+            "Class 9 (900Mhz)",
+            "Class 10 (800Mhz-Secondary)",
+            "Class 11 (Europe PAMR 400Mhz)",
+            "Class 15 (US-AWS)",
+            "Class 16 (US-2500Mhz)"
+    };
+
+    private ListView mBandList;
+    private ArrayAdapter mBandListAdapter;
+    private BandListItem mTargetBand = null;
+    private DialogInterface mProgressPanel;
+
+    private Phone mPhone = null;
+
+    @Override
+    protected void onCreate(Bundle icicle) {
+        super.onCreate(icicle);
+
+        requestWindowFeature(Window.FEATURE_INDETERMINATE_PROGRESS);
+        setContentView(R.layout.band_mode);
+
+        mPhone = PhoneFactory.getDefaultPhone();
+
+        mBandList = (ListView) findViewById(R.id.band);
+        mBandListAdapter = new ArrayAdapter<BandListItem>(this,
+                android.R.layout.simple_list_item_1);
+        mBandList.setAdapter(mBandListAdapter);
+        mBandList.setOnItemClickListener(mBandSelectionHandler);
+
+        loadBandList();
+    }
+
+    private AdapterView.OnItemClickListener mBandSelectionHandler =
+            new AdapterView.OnItemClickListener() {
+                public void onItemClick(AdapterView parent, View v,
+                        int position, long id) {
+
+                    getWindow().setFeatureInt(
+                            Window.FEATURE_INDETERMINATE_PROGRESS,
+                            Window.PROGRESS_VISIBILITY_ON);
+
+                    mTargetBand = (BandListItem) parent.getAdapter().getItem(position);
+
+                    if (DBG) log("Select band : " + mTargetBand.toString());
+
+                    Message msg =
+                            mHandler.obtainMessage(EVENT_BAND_SELECTION_DONE);
+                    mPhone.setBandMode(mTargetBand.getBand(), msg);
+                }
+            };
+
+    private static class BandListItem {
+        private int mBandMode = Phone.BM_UNSPECIFIED;
+
+        BandListItem(int bm) {
+            mBandMode = bm;
+        }
+
+        public int getBand() {
+            return mBandMode;
+        }
+
+        public String toString() {
+            if (mBandMode >= BAND_NAMES.length) return "Band mode " + mBandMode;
+            return BAND_NAMES[mBandMode];
+        }
+    }
+
+    private void loadBandList() {
+        String str = getString(R.string.band_mode_loading);
+
+        if (DBG) log(str);
+
+
+        //ProgressDialog.show(this, null, str, true, true, null);
+        mProgressPanel = new AlertDialog.Builder(this)
+            .setMessage(str)
+            .show();
+
+        Message msg = mHandler.obtainMessage(EVENT_BAND_SCAN_COMPLETED);
+        mPhone.queryAvailableBandMode(msg);
+
+    }
+
+    private void bandListLoaded(AsyncResult result) {
+        if (DBG) log("network list loaded");
+
+        if (mProgressPanel != null) mProgressPanel.dismiss();
+
+        clearList();
+
+        boolean addBandSuccess = false;
+        BandListItem item;
+
+        if (result.result != null) {
+            int [] bands = (int []) result.result;
+
+            if (bands.length == 0) {
+                Log.wtf(LOG_TAG, "No Supported Band Modes");
+                return;
+            }
+
+            int size = bands[0];
+
+            if (size > 0) {
+                mBandListAdapter.add(
+                        new BandListItem(Phone.BM_UNSPECIFIED)); //Always include AUTOMATIC
+                for (int i = 1; i <= size; i++) {
+                    if (bands[i] == Phone.BM_UNSPECIFIED) {
+                        continue;
+                    }
+                    item = new BandListItem(bands[i]);
+                    mBandListAdapter.add(item);
+                    if (DBG) log("Add " + item.toString());
+                }
+                addBandSuccess = true;
+            }
+        }
+
+        if (!addBandSuccess) {
+            if (DBG) log("Error in query, add default list");
+            for (int i = 0; i < Phone.BM_NUM_BAND_MODES; i++) {
+                item = new BandListItem(i);
+                mBandListAdapter.add(item);
+                if (DBG) log("Add default " + item.toString());
+            }
+        }
+        mBandList.requestFocus();
+    }
+
+    private void displayBandSelectionResult(Throwable ex) {
+        String status = getString(R.string.band_mode_set)
+                + " [" + mTargetBand.toString() + "] ";
+
+        if (ex != null) {
+            status = status + getString(R.string.band_mode_failed);
+        } else {
+            status = status + getString(R.string.band_mode_succeeded);
+        }
+
+        mProgressPanel = new AlertDialog.Builder(this)
+            .setMessage(status)
+            .setPositiveButton(android.R.string.ok, null).show();
+    }
+
+    private void clearList() {
+        while (mBandListAdapter.getCount() > 0) {
+            mBandListAdapter.remove(
+                    mBandListAdapter.getItem(0));
+        }
+    }
+
+    private void log(String msg) {
+        Log.d(LOG_TAG, "[BandsList] " + msg);
+    }
+
+    private Handler mHandler = new Handler() {
+        public void handleMessage(Message msg) {
+            AsyncResult ar;
+            switch (msg.what) {
+                case EVENT_BAND_SCAN_COMPLETED:
+                    ar = (AsyncResult) msg.obj;
+
+                    bandListLoaded(ar);
+                    break;
+
+                case EVENT_BAND_SELECTION_DONE:
+                    ar = (AsyncResult) msg.obj;
+
+                    getWindow().setFeatureInt(
+                            Window.FEATURE_INDETERMINATE_PROGRESS,
+                            Window.PROGRESS_VISIBILITY_OFF);
+
+                    if (!isFinishing()) {
+                        displayBandSelectionResult(ar.exception);
+                    }
+                    break;
+            }
+        }
+    };
+
+
+}
diff --git a/src/com/android/phone/settings/RadioInfo.java b/src/com/android/phone/settings/RadioInfo.java
new file mode 100644
index 0000000..04045f1
--- /dev/null
+++ b/src/com/android/phone/settings/RadioInfo.java
@@ -0,0 +1,1768 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.phone.settings;
+
+import static android.net.ConnectivityManager.NetworkCallback;
+import static android.provider.Settings.Global.PREFERRED_NETWORK_MODE;
+
+import android.content.ComponentName;
+import android.content.Context;
+import android.content.DialogInterface;
+import android.content.Intent;
+import android.content.pm.PackageManager;
+import android.content.pm.ResolveInfo;
+import android.content.res.Resources;
+import android.graphics.Typeface;
+import android.net.ConnectivityManager;
+import android.net.Network;
+import android.net.NetworkCapabilities;
+import android.net.NetworkRequest;
+import android.net.TrafficStats;
+import android.net.Uri;
+import android.os.AsyncResult;
+import android.os.Build;
+import android.os.Bundle;
+import android.os.Handler;
+import android.os.Message;
+import android.os.SystemProperties;
+import android.provider.Settings;
+import android.telephony.CarrierConfigManager;
+import android.telephony.CellIdentityCdma;
+import android.telephony.CellIdentityGsm;
+import android.telephony.CellIdentityLte;
+import android.telephony.CellIdentityWcdma;
+import android.telephony.CellInfo;
+import android.telephony.CellInfoCdma;
+import android.telephony.CellInfoGsm;
+import android.telephony.CellInfoLte;
+import android.telephony.CellInfoWcdma;
+import android.telephony.CellLocation;
+import android.telephony.CellSignalStrengthCdma;
+import android.telephony.CellSignalStrengthGsm;
+import android.telephony.CellSignalStrengthLte;
+import android.telephony.CellSignalStrengthWcdma;
+import android.telephony.PhoneStateListener;
+import android.telephony.PhysicalChannelConfig;
+import android.telephony.PreciseCallState;
+import android.telephony.ServiceState;
+import android.telephony.SignalStrength;
+import android.telephony.SubscriptionManager;
+import android.telephony.TelephonyManager;
+import android.telephony.cdma.CdmaCellLocation;
+import android.telephony.gsm.GsmCellLocation;
+import android.text.TextUtils;
+import android.util.Log;
+import android.view.Menu;
+import android.view.MenuItem;
+import android.view.View;
+import android.view.View.OnClickListener;
+import android.widget.AdapterView;
+import android.widget.ArrayAdapter;
+import android.widget.Button;
+import android.widget.CompoundButton;
+import android.widget.CompoundButton.OnCheckedChangeListener;
+import android.widget.EditText;
+import android.widget.Spinner;
+import android.widget.Switch;
+import android.widget.TextView;
+
+import androidx.appcompat.app.AlertDialog;
+import androidx.appcompat.app.AlertDialog.Builder;
+import androidx.appcompat.app.AppCompatActivity;
+
+import com.android.ims.ImsConfig;
+import com.android.ims.ImsException;
+import com.android.ims.ImsManager;
+import com.android.internal.telephony.Phone;
+import com.android.internal.telephony.PhoneFactory;
+import com.android.phone.R;
+
+import java.io.IOException;
+import java.net.HttpURLConnection;
+import java.net.URL;
+import java.util.List;
+import java.util.concurrent.LinkedBlockingDeque;
+import java.util.concurrent.ThreadPoolExecutor;
+import java.util.concurrent.TimeUnit;
+
+/**
+ * Radio Information Class
+ *
+ * Allows user to read and alter some of the radio related information.
+ *
+ */
+public class RadioInfo extends AppCompatActivity {
+    private static final String TAG = "RadioInfo";
+
+    private static final boolean IS_USER_BUILD = "user".equals(Build.TYPE);
+
+    private static final String[] PREFERRED_NETWORK_LABELS = {
+            "WCDMA preferred",
+            "GSM only",
+            "WCDMA only",
+            "GSM auto (PRL)",
+            "CDMA auto (PRL)",
+            "CDMA only",
+            "EvDo only",
+            "Global auto (PRL)",
+            "LTE/CDMA auto (PRL)",
+            "LTE/UMTS auto (PRL)",
+            "LTE/CDMA/UMTS auto (PRL)",
+            "LTE only",
+            "LTE/WCDMA",
+            "TD-SCDMA only",
+            "TD-SCDMA/WCDMA",
+            "LTE/TD-SCDMA",
+            "TD-SCDMA/GSM",
+            "TD-SCDMA/UMTS",
+            "LTE/TD-SCDMA/WCDMA",
+            "LTE/TD-SCDMA/UMTS",
+            "TD-SCDMA/CDMA/UMTS",
+            "Global/TD-SCDMA",
+            "Unknown"
+    };
+
+    private static String[] sPhoneIndexLabels;
+
+    private static final int sCellInfoListRateDisabled = Integer.MAX_VALUE;
+    private static final int sCellInfoListRateMax = 0;
+
+    private static final String OEM_RADIO_INFO_INTENT =
+            "com.android.phone.settings.OEM_RADIO_INFO";
+
+    private static final String DSDS_MODE_PROPERTY = "ro.boot.hardware.dsds";
+
+    /**
+     * A value indicates the device is always on dsds mode.
+     * @see {@link #DSDS_MODE_PROPERTY}
+     */
+    private static final int ALWAYS_ON_DSDS_MODE = 1;
+
+    private static final int IMS_VOLTE_PROVISIONED_CONFIG_ID =
+            ImsConfig.ConfigConstants.VLT_SETTING_ENABLED;
+
+    private static final int IMS_VT_PROVISIONED_CONFIG_ID =
+            ImsConfig.ConfigConstants.LVC_SETTING_ENABLED;
+
+    private static final int IMS_WFC_PROVISIONED_CONFIG_ID =
+            ImsConfig.ConfigConstants.VOICE_OVER_WIFI_SETTING_ENABLED;
+
+    private static final int EAB_PROVISIONED_CONFIG_ID =
+            ImsConfig.ConfigConstants.EAB_SETTING_ENABLED;
+
+    //Values in must match CELL_INFO_REFRESH_RATES
+    private static final String[] CELL_INFO_REFRESH_RATE_LABELS = {
+            "Disabled",
+            "Immediate",
+            "Min 5s",
+            "Min 10s",
+            "Min 60s"
+    };
+
+    //Values in seconds, must match CELL_INFO_REFRESH_RATE_LABELS
+    private static final int [] CELL_INFO_REFRESH_RATES = {
+        sCellInfoListRateDisabled,
+        sCellInfoListRateMax,
+        5000,
+        10000,
+        60000
+    };
+
+    private static void log(String s) {
+        Log.d(TAG, s);
+    }
+
+    private static final int EVENT_CFI_CHANGED = 302;
+
+    private static final int EVENT_QUERY_PREFERRED_TYPE_DONE = 1000;
+    private static final int EVENT_SET_PREFERRED_TYPE_DONE = 1001;
+    private static final int EVENT_QUERY_SMSC_DONE = 1005;
+    private static final int EVENT_UPDATE_SMSC_DONE = 1006;
+
+    private static final int MENU_ITEM_SELECT_BAND         = 0;
+    private static final int MENU_ITEM_VIEW_ADN            = 1;
+    private static final int MENU_ITEM_VIEW_FDN            = 2;
+    private static final int MENU_ITEM_VIEW_SDN            = 3;
+    private static final int MENU_ITEM_GET_IMS_STATUS      = 4;
+    private static final int MENU_ITEM_TOGGLE_DATA         = 5;
+
+    private TextView mDeviceId; //DeviceId is the IMEI in GSM and the MEID in CDMA
+    private TextView mLine1Number;
+    private TextView mSubscriptionId;
+    private TextView mDds;
+    private TextView mSubscriberId;
+    private TextView mCallState;
+    private TextView mOperatorName;
+    private TextView mRoamingState;
+    private TextView mGsmState;
+    private TextView mGprsState;
+    private TextView mVoiceNetwork;
+    private TextView mDataNetwork;
+    private TextView mDBm;
+    private TextView mMwi;
+    private TextView mCfi;
+    private TextView mLocation;
+    private TextView mCellInfo;
+    private TextView mSent;
+    private TextView mReceived;
+    private TextView mPingHostnameV4;
+    private TextView mPingHostnameV6;
+    private TextView mHttpClientTest;
+    private TextView mPhyChanConfig;
+    private TextView mDnsCheckState;
+    private TextView mDownlinkKbps;
+    private TextView mUplinkKbps;
+    private EditText mSmsc;
+    private Switch mRadioPowerOnSwitch;
+    private Button mCellInfoRefreshRateButton;
+    private Button mDnsCheckToggleButton;
+    private Button mPingTestButton;
+    private Button mUpdateSmscButton;
+    private Button mRefreshSmscButton;
+    private Button mOemInfoButton;
+    private Button mCarrierProvisioningButton;
+    private Button mTriggerCarrierProvisioningButton;
+    private Switch mImsVolteProvisionedSwitch;
+    private Switch mImsVtProvisionedSwitch;
+    private Switch mImsWfcProvisionedSwitch;
+    private Switch mEabProvisionedSwitch;
+    private Switch mCbrsDataSwitch;
+    private Switch mDsdsSwitch;
+    private Spinner mPreferredNetworkType;
+    private Spinner mSelectPhoneIndex;
+    private Spinner mCellInfoRefreshRateSpinner;
+
+    private static final long RUNNABLE_TIMEOUT_MS = 5 * 60 * 1000L;
+
+    private ThreadPoolExecutor mQueuedWork;
+
+    private ConnectivityManager mConnectivityManager;
+    private TelephonyManager mTelephonyManager;
+    private ImsManager mImsManager = null;
+    private Phone mPhone = null;
+
+    private String mPingHostnameResultV4;
+    private String mPingHostnameResultV6;
+    private String mHttpClientTestResult;
+    private boolean mMwiValue = false;
+    private boolean mCfiValue = false;
+
+    private List<CellInfo> mCellInfoResult = null;
+    private CellLocation mCellLocationResult = null;
+
+    private int mPreferredNetworkTypeResult;
+    private int mCellInfoRefreshRateIndex;
+    private int mSelectedPhoneIndex;
+
+    private final NetworkRequest mDefaultNetworkRequest = new NetworkRequest.Builder()
+            .addTransportType(NetworkCapabilities.TRANSPORT_CELLULAR)
+            .addCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET)
+            .build();
+
+    private final NetworkCallback mNetworkCallback = new NetworkCallback() {
+        public void onCapabilitiesChanged(Network n, NetworkCapabilities nc) {
+            int dlbw = nc.getLinkDownstreamBandwidthKbps();
+            int ulbw = nc.getLinkUpstreamBandwidthKbps();
+            updateBandwidths(dlbw, ulbw);
+        }
+    };
+
+    // not final because we need to recreate this object to register on a new subId (b/117555407)
+    private PhoneStateListener mPhoneStateListener = new RadioInfoPhoneStateListener();
+    private class RadioInfoPhoneStateListener extends PhoneStateListener {
+        @Override
+        public void onDataConnectionStateChanged(int state) {
+            updateDataState();
+            updateNetworkType();
+        }
+
+        @Override
+        public void onDataActivity(int direction) {
+            updateDataStats2();
+        }
+
+        @Override
+        public void onCallStateChanged(int state, String incomingNumber) {
+            updateNetworkType();
+            updatePhoneState(state);
+        }
+
+        @Override
+        public void onPreciseCallStateChanged(PreciseCallState preciseState) {
+            updateNetworkType();
+        }
+
+        @Override
+        public void onCellLocationChanged(CellLocation location) {
+            updateLocation(location);
+        }
+
+        @Override
+        public void onMessageWaitingIndicatorChanged(boolean mwi) {
+            mMwiValue = mwi;
+            updateMessageWaiting();
+        }
+
+        @Override
+        public void onCallForwardingIndicatorChanged(boolean cfi) {
+            mCfiValue = cfi;
+            updateCallRedirect();
+        }
+
+        @Override
+        public void onCellInfoChanged(List<CellInfo> arrayCi) {
+            log("onCellInfoChanged: arrayCi=" + arrayCi);
+            mCellInfoResult = arrayCi;
+            updateCellInfo(mCellInfoResult);
+        }
+
+        @Override
+        public void onSignalStrengthsChanged(SignalStrength signalStrength) {
+            log("onSignalStrengthChanged: SignalStrength=" + signalStrength);
+            updateSignalStrength(signalStrength);
+        }
+
+        @Override
+        public void onServiceStateChanged(ServiceState serviceState) {
+            log("onServiceStateChanged: ServiceState=" + serviceState);
+            updateServiceState(serviceState);
+            updateRadioPowerState();
+            updateNetworkType();
+            updateImsProvisionedState();
+        }
+
+        @Override
+        public void onPhysicalChannelConfigurationChanged(
+                List<PhysicalChannelConfig> configs) {
+            updatePhysicalChannelConfiguration(configs);
+        }
+
+    }
+
+    private void updatePhysicalChannelConfiguration(List<PhysicalChannelConfig> configs) {
+        StringBuilder sb = new StringBuilder();
+        String div = "";
+        sb.append("{");
+        if (configs != null) {
+            for (PhysicalChannelConfig c : configs) {
+                sb.append(div).append(c);
+                div = ",";
+            }
+        }
+        sb.append("}");
+        mPhyChanConfig.setText(sb.toString());
+    }
+
+    private void updatePreferredNetworkType(int type) {
+        if (type >= PREFERRED_NETWORK_LABELS.length || type < 0) {
+            log("EVENT_QUERY_PREFERRED_TYPE_DONE: unknown "
+                    + "type=" + type);
+            type = PREFERRED_NETWORK_LABELS.length - 1; //set to Unknown
+        }
+        mPreferredNetworkTypeResult = type;
+
+        mPreferredNetworkType.setSelection(mPreferredNetworkTypeResult, true);
+    }
+
+    private void updatePhoneIndex(int phoneIndex, int subId) {
+        // unregister listeners on the old subId
+        unregisterPhoneStateListener();
+        mTelephonyManager.setCellInfoListRate(sCellInfoListRateDisabled);
+
+        // update the subId
+        mTelephonyManager = mTelephonyManager.createForSubscriptionId(subId);
+
+        // update the phoneId
+        mImsManager = ImsManager.getInstance(getApplicationContext(), phoneIndex);
+        mPhone = PhoneFactory.getPhone(phoneIndex);
+
+        updateAllFields();
+    }
+
+    private Handler mHandler = new Handler() {
+        @Override
+        public void handleMessage(Message msg) {
+            AsyncResult ar;
+            switch (msg.what) {
+                case EVENT_QUERY_PREFERRED_TYPE_DONE:
+                    ar = (AsyncResult) msg.obj;
+                    if (ar.exception == null && ar.result != null) {
+                        updatePreferredNetworkType(((int []) ar.result)[0]);
+                    } else {
+                        //In case of an exception, we will set this to unknown
+                        updatePreferredNetworkType(PREFERRED_NETWORK_LABELS.length - 1);
+                    }
+                    break;
+                case EVENT_SET_PREFERRED_TYPE_DONE:
+                    ar = (AsyncResult) msg.obj;
+                    if (ar.exception != null) {
+                        log("Set preferred network type failed.");
+                    }
+                    break;
+                case EVENT_QUERY_SMSC_DONE:
+                    ar = (AsyncResult) msg.obj;
+                    if (ar.exception != null) {
+                        mSmsc.setText("refresh error");
+                    } else {
+                        mSmsc.setText((String) ar.result);
+                    }
+                    break;
+                case EVENT_UPDATE_SMSC_DONE:
+                    mUpdateSmscButton.setEnabled(true);
+                    ar = (AsyncResult) msg.obj;
+                    if (ar.exception != null) {
+                        mSmsc.setText("update error");
+                    }
+                    break;
+                default:
+                    super.handleMessage(msg);
+                    break;
+
+            }
+        }
+    };
+
+    @Override
+    public void onCreate(Bundle icicle) {
+        super.onCreate(icicle);
+        if (!android.os.Process.myUserHandle().isSystem()) {
+            Log.e(TAG, "Not run from system user, don't do anything.");
+            finish();
+            return;
+        }
+
+        setContentView(R.layout.radio_info);
+
+        log("Started onCreate");
+
+        mQueuedWork = new ThreadPoolExecutor(1, 1, RUNNABLE_TIMEOUT_MS, TimeUnit.MICROSECONDS,
+                new LinkedBlockingDeque<Runnable>());
+        mTelephonyManager = (TelephonyManager) getSystemService(TELEPHONY_SERVICE);
+        mConnectivityManager = (ConnectivityManager) getSystemService(CONNECTIVITY_SERVICE);
+        mPhone = PhoneFactory.getDefaultPhone();
+
+        mImsManager = ImsManager.getInstance(getApplicationContext(),
+                SubscriptionManager.getDefaultVoicePhoneId());
+
+        sPhoneIndexLabels = getPhoneIndexLabels(mTelephonyManager);
+
+        mDeviceId = (TextView) findViewById(R.id.imei);
+        mLine1Number = (TextView) findViewById(R.id.number);
+        mSubscriptionId = (TextView) findViewById(R.id.subid);
+        mDds = (TextView) findViewById(R.id.dds);
+        mSubscriberId = (TextView) findViewById(R.id.imsi);
+        mCallState = (TextView) findViewById(R.id.call);
+        mOperatorName = (TextView) findViewById(R.id.operator);
+        mRoamingState = (TextView) findViewById(R.id.roaming);
+        mGsmState = (TextView) findViewById(R.id.gsm);
+        mGprsState = (TextView) findViewById(R.id.gprs);
+        mVoiceNetwork = (TextView) findViewById(R.id.voice_network);
+        mDataNetwork = (TextView) findViewById(R.id.data_network);
+        mDBm = (TextView) findViewById(R.id.dbm);
+        mMwi = (TextView) findViewById(R.id.mwi);
+        mCfi = (TextView) findViewById(R.id.cfi);
+        mLocation = (TextView) findViewById(R.id.location);
+        mCellInfo = (TextView) findViewById(R.id.cellinfo);
+        mCellInfo.setTypeface(Typeface.MONOSPACE);
+
+        mSent = (TextView) findViewById(R.id.sent);
+        mReceived = (TextView) findViewById(R.id.received);
+        mSmsc = (EditText) findViewById(R.id.smsc);
+        mDnsCheckState = (TextView) findViewById(R.id.dnsCheckState);
+        mPingHostnameV4 = (TextView) findViewById(R.id.pingHostnameV4);
+        mPingHostnameV6 = (TextView) findViewById(R.id.pingHostnameV6);
+        mHttpClientTest = (TextView) findViewById(R.id.httpClientTest);
+
+        mPhyChanConfig = (TextView) findViewById(R.id.phy_chan_config);
+
+        mPreferredNetworkType = (Spinner) findViewById(R.id.preferredNetworkType);
+        ArrayAdapter<String> mPreferredNetworkTypeAdapter = new ArrayAdapter<String>(this,
+                android.R.layout.simple_spinner_item, PREFERRED_NETWORK_LABELS);
+        mPreferredNetworkTypeAdapter
+                .setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
+        mPreferredNetworkType.setAdapter(mPreferredNetworkTypeAdapter);
+
+        mSelectPhoneIndex = (Spinner) findViewById(R.id.phoneIndex);
+        ArrayAdapter<String> phoneIndexAdapter = new ArrayAdapter<String>(this,
+                android.R.layout.simple_spinner_item, sPhoneIndexLabels);
+        phoneIndexAdapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
+        mSelectPhoneIndex.setAdapter(phoneIndexAdapter);
+
+        mCellInfoRefreshRateSpinner = (Spinner) findViewById(R.id.cell_info_rate_select);
+        ArrayAdapter<String> cellInfoAdapter = new ArrayAdapter<String>(this,
+                android.R.layout.simple_spinner_item, CELL_INFO_REFRESH_RATE_LABELS);
+        cellInfoAdapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
+        mCellInfoRefreshRateSpinner.setAdapter(cellInfoAdapter);
+
+        mImsVolteProvisionedSwitch = (Switch) findViewById(R.id.volte_provisioned_switch);
+        mImsVtProvisionedSwitch = (Switch) findViewById(R.id.vt_provisioned_switch);
+        mImsWfcProvisionedSwitch = (Switch) findViewById(R.id.wfc_provisioned_switch);
+        mEabProvisionedSwitch = (Switch) findViewById(R.id.eab_provisioned_switch);
+
+        if (!ImsManager.isImsSupportedOnDevice(mPhone.getContext())) {
+            mImsVolteProvisionedSwitch.setVisibility(View.GONE);
+            mImsVtProvisionedSwitch.setVisibility(View.GONE);
+            mImsWfcProvisionedSwitch.setVisibility(View.GONE);
+            mEabProvisionedSwitch.setVisibility(View.GONE);
+        }
+
+        mCbrsDataSwitch = (Switch) findViewById(R.id.cbrs_data_switch);
+        mCbrsDataSwitch.setVisibility(isCbrsSupported() ? View.VISIBLE : View.GONE);
+
+        mDsdsSwitch = findViewById(R.id.dsds_switch);
+        if (isDsdsSupported() && !dsdsModeOnly()) {
+            mDsdsSwitch.setVisibility(View.VISIBLE);
+            mDsdsSwitch.setOnClickListener(v -> {
+                if (mTelephonyManager.doesSwitchMultiSimConfigTriggerReboot()) {
+                    // Undo the click action until user clicks the confirm dialog.
+                    mDsdsSwitch.toggle();
+                    showDsdsChangeDialog();
+                } else {
+                    performDsdsSwitch();
+                }
+            });
+            mDsdsSwitch.setChecked(isDsdsEnabled());
+        } else {
+            mDsdsSwitch.setVisibility(View.GONE);
+        }
+
+        mRadioPowerOnSwitch = (Switch) findViewById(R.id.radio_power);
+
+        mDownlinkKbps = (TextView) findViewById(R.id.dl_kbps);
+        mUplinkKbps = (TextView) findViewById(R.id.ul_kbps);
+        updateBandwidths(0, 0);
+
+        mPingTestButton = (Button) findViewById(R.id.ping_test);
+        mPingTestButton.setOnClickListener(mPingButtonHandler);
+        mUpdateSmscButton = (Button) findViewById(R.id.update_smsc);
+        mUpdateSmscButton.setOnClickListener(mUpdateSmscButtonHandler);
+        mRefreshSmscButton = (Button) findViewById(R.id.refresh_smsc);
+        mRefreshSmscButton.setOnClickListener(mRefreshSmscButtonHandler);
+        mDnsCheckToggleButton = (Button) findViewById(R.id.dns_check_toggle);
+        mDnsCheckToggleButton.setOnClickListener(mDnsCheckButtonHandler);
+        mCarrierProvisioningButton = (Button) findViewById(R.id.carrier_provisioning);
+        mCarrierProvisioningButton.setOnClickListener(mCarrierProvisioningButtonHandler);
+        mTriggerCarrierProvisioningButton = (Button) findViewById(
+                R.id.trigger_carrier_provisioning);
+        mTriggerCarrierProvisioningButton.setOnClickListener(
+                mTriggerCarrierProvisioningButtonHandler);
+
+        mOemInfoButton = (Button) findViewById(R.id.oem_info);
+        mOemInfoButton.setOnClickListener(mOemInfoButtonHandler);
+        PackageManager pm = getPackageManager();
+        Intent oemInfoIntent = new Intent(OEM_RADIO_INFO_INTENT);
+        List<ResolveInfo> oemInfoIntentList = pm.queryIntentActivities(oemInfoIntent, 0);
+        if (oemInfoIntentList.size() == 0) {
+            mOemInfoButton.setEnabled(false);
+        }
+
+        mCellInfoRefreshRateIndex = 0; //disabled
+        mPreferredNetworkTypeResult = PREFERRED_NETWORK_LABELS.length - 1; //Unknown
+        mSelectedPhoneIndex = 0; //phone 0
+
+        //FIXME: Replace with TelephonyManager call
+        mPhone.getPreferredNetworkType(
+                mHandler.obtainMessage(EVENT_QUERY_PREFERRED_TYPE_DONE));
+
+        restoreFromBundle(icicle);
+    }
+
+    @Override
+    public Intent getParentActivityIntent() {
+        Intent parentActivity = super.getParentActivityIntent();
+        if (parentActivity == null) {
+            parentActivity = (new Intent()).setClassName("com.android.settings",
+                    "com.android.settings.Settings$TestingSettingsActivity");
+        }
+        return parentActivity;
+    }
+
+    @Override
+    protected void onResume() {
+        super.onResume();
+
+        log("Started onResume");
+
+        updateAllFields();
+    }
+
+    private void updateAllFields() {
+        updateMessageWaiting();
+        updateCallRedirect();
+        updateDataState();
+        updateDataStats2();
+        updateRadioPowerState();
+        updateImsProvisionedState();
+        updateProperties();
+        updateDnsCheckState();
+        updateNetworkType();
+
+        updateLocation(mCellLocationResult);
+        updateCellInfo(mCellInfoResult);
+        updateSubscriptionIds();
+
+        mPingHostnameV4.setText(mPingHostnameResultV4);
+        mPingHostnameV6.setText(mPingHostnameResultV6);
+        mHttpClientTest.setText(mHttpClientTestResult);
+
+        mCellInfoRefreshRateSpinner.setOnItemSelectedListener(mCellInfoRefreshRateHandler);
+        //set selection after registering listener to force update
+        mCellInfoRefreshRateSpinner.setSelection(mCellInfoRefreshRateIndex);
+
+        //set selection before registering to prevent update
+        mPreferredNetworkType.setSelection(mPreferredNetworkTypeResult, true);
+        mPreferredNetworkType.setOnItemSelectedListener(mPreferredNetworkHandler);
+
+        // set phone index
+        mSelectPhoneIndex.setSelection(mSelectedPhoneIndex, true);
+        mSelectPhoneIndex.setOnItemSelectedListener(mSelectPhoneIndexHandler);
+
+        mRadioPowerOnSwitch.setOnCheckedChangeListener(mRadioPowerOnChangeListener);
+        mImsVolteProvisionedSwitch.setOnCheckedChangeListener(mImsVolteCheckedChangeListener);
+        mImsVtProvisionedSwitch.setOnCheckedChangeListener(mImsVtCheckedChangeListener);
+        mImsWfcProvisionedSwitch.setOnCheckedChangeListener(mImsWfcCheckedChangeListener);
+        mEabProvisionedSwitch.setOnCheckedChangeListener(mEabCheckedChangeListener);
+
+        if (isCbrsSupported()) {
+            mCbrsDataSwitch.setChecked(getCbrsDataState());
+            mCbrsDataSwitch.setOnCheckedChangeListener(mCbrsDataSwitchChangeListener);
+        }
+
+        unregisterPhoneStateListener();
+        registerPhoneStateListener();
+
+        mConnectivityManager.registerNetworkCallback(
+                mDefaultNetworkRequest, mNetworkCallback, mHandler);
+
+        mSmsc.clearFocus();
+    }
+
+    @Override
+    protected void onPause() {
+        super.onPause();
+
+        log("onPause: unregister phone & data intents");
+
+        mTelephonyManager.listen(mPhoneStateListener, PhoneStateListener.LISTEN_NONE);
+        mTelephonyManager.setCellInfoListRate(sCellInfoListRateDisabled);
+        mConnectivityManager.unregisterNetworkCallback(mNetworkCallback);
+
+    }
+
+    private void restoreFromBundle(Bundle b) {
+        if (b == null) {
+            return;
+        }
+
+        mPingHostnameResultV4 = b.getString("mPingHostnameResultV4", "");
+        mPingHostnameResultV6 = b.getString("mPingHostnameResultV6", "");
+        mHttpClientTestResult = b.getString("mHttpClientTestResult", "");
+
+        mPingHostnameV4.setText(mPingHostnameResultV4);
+        mPingHostnameV6.setText(mPingHostnameResultV6);
+        mHttpClientTest.setText(mHttpClientTestResult);
+
+        mPreferredNetworkTypeResult = b.getInt("mPreferredNetworkTypeResult",
+                PREFERRED_NETWORK_LABELS.length - 1);
+
+        mSelectedPhoneIndex = b.getInt("mSelectedPhoneIndex", 0);
+
+        mCellInfoRefreshRateIndex = b.getInt("mCellInfoRefreshRateIndex", 0);
+    }
+
+    @Override
+    protected void onSaveInstanceState(Bundle outState) {
+        outState.putString("mPingHostnameResultV4", mPingHostnameResultV4);
+        outState.putString("mPingHostnameResultV6", mPingHostnameResultV6);
+        outState.putString("mHttpClientTestResult", mHttpClientTestResult);
+
+        outState.putInt("mPreferredNetworkTypeResult", mPreferredNetworkTypeResult);
+        outState.putInt("mSelectedPhoneIndex", mSelectedPhoneIndex);
+        outState.putInt("mCellInfoRefreshRateIndex", mCellInfoRefreshRateIndex);
+
+    }
+
+    @Override
+    public boolean onCreateOptionsMenu(Menu menu) {
+        menu.add(0, MENU_ITEM_SELECT_BAND, 0, R.string.radio_info_band_mode_label)
+                .setOnMenuItemClickListener(mSelectBandCallback)
+                .setAlphabeticShortcut('b');
+        menu.add(1, MENU_ITEM_VIEW_ADN, 0,
+                R.string.radioInfo_menu_viewADN).setOnMenuItemClickListener(mViewADNCallback);
+        menu.add(1, MENU_ITEM_VIEW_FDN, 0,
+                R.string.radioInfo_menu_viewFDN).setOnMenuItemClickListener(mViewFDNCallback);
+        menu.add(1, MENU_ITEM_VIEW_SDN, 0,
+                R.string.radioInfo_menu_viewSDN).setOnMenuItemClickListener(mViewSDNCallback);
+        if (ImsManager.isImsSupportedOnDevice(mPhone.getContext())) {
+            menu.add(1, MENU_ITEM_GET_IMS_STATUS,
+                    0, R.string.radioInfo_menu_getIMS).setOnMenuItemClickListener(mGetImsStatus);
+        }
+        menu.add(1, MENU_ITEM_TOGGLE_DATA,
+                0, R.string.radio_info_data_connection_disable)
+                .setOnMenuItemClickListener(mToggleData);
+        return true;
+    }
+
+    @Override
+    public boolean onPrepareOptionsMenu(Menu menu) {
+        // Get the TOGGLE DATA menu item in the right state.
+        MenuItem item = menu.findItem(MENU_ITEM_TOGGLE_DATA);
+        int state = mTelephonyManager.getDataState();
+        boolean visible = true;
+
+        switch (state) {
+            case TelephonyManager.DATA_CONNECTED:
+            case TelephonyManager.DATA_SUSPENDED:
+                item.setTitle(R.string.radio_info_data_connection_disable);
+                break;
+            case TelephonyManager.DATA_DISCONNECTED:
+                item.setTitle(R.string.radio_info_data_connection_enable);
+                break;
+            default:
+                visible = false;
+                break;
+        }
+        item.setVisible(visible);
+        return true;
+    }
+
+    @Override
+    protected void onDestroy() {
+        super.onDestroy();
+        mQueuedWork.shutdown();
+    }
+
+    // returns array of string labels for each phone index. The array index is equal to the phone
+    // index.
+    private static String[] getPhoneIndexLabels(TelephonyManager tm) {
+        int phones = tm.getPhoneCount();
+        String[] labels = new String[phones];
+        for (int i = 0; i < phones; i++) {
+            labels[i] = "Phone " + i;
+        }
+        return labels;
+    }
+
+    private void unregisterPhoneStateListener() {
+        mTelephonyManager.listen(mPhoneStateListener, PhoneStateListener.LISTEN_NONE);
+
+        // clear all fields so they are blank until the next listener event occurs
+        mOperatorName.setText("");
+        mGprsState.setText("");
+        mDataNetwork.setText("");
+        mVoiceNetwork.setText("");
+        mSent.setText("");
+        mReceived.setText("");
+        mCallState.setText("");
+        mLocation.setText("");
+        mMwiValue = false;
+        mMwi.setText("");
+        mCfiValue = false;
+        mCfi.setText("");
+        mCellInfo.setText("");
+        mDBm.setText("");
+        mGsmState.setText("");
+        mRoamingState.setText("");
+        mPhyChanConfig.setText("");
+    }
+
+    // register mPhoneStateListener for relevant fields using the current TelephonyManager
+    private void registerPhoneStateListener() {
+        mPhoneStateListener = new RadioInfoPhoneStateListener();
+        mTelephonyManager.listen(mPhoneStateListener,
+                  PhoneStateListener.LISTEN_CALL_STATE
+        //b/27803938 - RadioInfo currently cannot read PRECISE_CALL_STATE
+        //      | PhoneStateListener.LISTEN_PRECISE_CALL_STATE
+                | PhoneStateListener.LISTEN_DATA_CONNECTION_STATE
+                | PhoneStateListener.LISTEN_DATA_ACTIVITY
+                | PhoneStateListener.LISTEN_CELL_LOCATION
+                | PhoneStateListener.LISTEN_MESSAGE_WAITING_INDICATOR
+                | PhoneStateListener.LISTEN_CALL_FORWARDING_INDICATOR
+                | PhoneStateListener.LISTEN_CELL_INFO
+                | PhoneStateListener.LISTEN_SERVICE_STATE
+                | PhoneStateListener.LISTEN_SIGNAL_STRENGTHS
+                | PhoneStateListener.LISTEN_PHYSICAL_CHANNEL_CONFIGURATION);
+    }
+
+    private void updateDnsCheckState() {
+        //FIXME: Replace with a TelephonyManager call
+        mDnsCheckState.setText(mPhone.isDnsCheckDisabled()
+                ? "0.0.0.0 allowed" : "0.0.0.0 not allowed");
+    }
+
+    private void updateBandwidths(int dlbw, int ulbw) {
+        dlbw = (dlbw < 0 || dlbw == Integer.MAX_VALUE) ? -1 : dlbw;
+        ulbw = (ulbw < 0 || ulbw == Integer.MAX_VALUE) ? -1 : ulbw;
+        mDownlinkKbps.setText(String.format("%-5d", dlbw));
+        mUplinkKbps.setText(String.format("%-5d", ulbw));
+    }
+
+
+    private void updateSignalStrength(SignalStrength signalStrength) {
+        Resources r = getResources();
+
+        int signalDbm = signalStrength.getDbm();
+
+        int signalAsu = signalStrength.getAsuLevel();
+
+        if (-1 == signalAsu) signalAsu = 0;
+
+        mDBm.setText(String.valueOf(signalDbm) + " "
+                + r.getString(R.string.radioInfo_display_dbm) + "   "
+                + String.valueOf(signalAsu) + " "
+                + r.getString(R.string.radioInfo_display_asu));
+    }
+
+    private void updateLocation(CellLocation location) {
+        Resources r = getResources();
+        if (location instanceof GsmCellLocation) {
+            GsmCellLocation loc = (GsmCellLocation) location;
+            int lac = loc.getLac();
+            int cid = loc.getCid();
+            mLocation.setText(r.getString(R.string.radioInfo_lac) + " = "
+                    + ((lac == -1) ? "unknown" : Integer.toHexString(lac))
+                    + "   "
+                    + r.getString(R.string.radioInfo_cid) + " = "
+                    + ((cid == -1) ? "unknown" : Integer.toHexString(cid)));
+        } else if (location instanceof CdmaCellLocation) {
+            CdmaCellLocation loc = (CdmaCellLocation) location;
+            int bid = loc.getBaseStationId();
+            int sid = loc.getSystemId();
+            int nid = loc.getNetworkId();
+            int lat = loc.getBaseStationLatitude();
+            int lon = loc.getBaseStationLongitude();
+            mLocation.setText("BID = "
+                    + ((bid == -1) ? "unknown" : Integer.toHexString(bid))
+                    + "   "
+                    + "SID = "
+                    + ((sid == -1) ? "unknown" : Integer.toHexString(sid))
+                    + "   "
+                    + "NID = "
+                    + ((nid == -1) ? "unknown" : Integer.toHexString(nid))
+                    + "\n"
+                    + "LAT = "
+                    + ((lat == -1) ? "unknown" : Integer.toHexString(lat))
+                    + "   "
+                    + "LONG = "
+                    + ((lon == -1) ? "unknown" : Integer.toHexString(lon)));
+        } else {
+            mLocation.setText("unknown");
+        }
+
+
+    }
+
+    private String getCellInfoDisplayString(int i) {
+        return (i != Integer.MAX_VALUE) ? Integer.toString(i) : "";
+    }
+
+    private String getCellInfoDisplayString(long i) {
+        return (i != Long.MAX_VALUE) ? Long.toString(i) : "";
+    }
+
+    private String getConnectionStatusString(CellInfo ci) {
+        String regStr = "";
+        String connStatStr = "";
+        String connector = "";
+
+        if (ci.isRegistered()) {
+            regStr = "R";
+        }
+        switch (ci.getCellConnectionStatus()) {
+            case CellInfo.CONNECTION_PRIMARY_SERVING: connStatStr = "P"; break;
+            case CellInfo.CONNECTION_SECONDARY_SERVING: connStatStr = "S"; break;
+            case CellInfo.CONNECTION_NONE: connStatStr = "N"; break;
+            case CellInfo.CONNECTION_UNKNOWN: /* Field is unsupported */ break;
+            default: break;
+        }
+        if (!TextUtils.isEmpty(regStr) && !TextUtils.isEmpty(connStatStr)) {
+            connector = "+";
+        }
+
+        return regStr + connector + connStatStr;
+    }
+
+    private String buildCdmaInfoString(CellInfoCdma ci) {
+        CellIdentityCdma cidCdma = ci.getCellIdentity();
+        CellSignalStrengthCdma ssCdma = ci.getCellSignalStrength();
+
+        return String.format("%-3.3s %-5.5s %-5.5s %-5.5s %-6.6s %-6.6s %-6.6s %-6.6s %-5.5s",
+                getConnectionStatusString(ci),
+                getCellInfoDisplayString(cidCdma.getSystemId()),
+                getCellInfoDisplayString(cidCdma.getNetworkId()),
+                getCellInfoDisplayString(cidCdma.getBasestationId()),
+                getCellInfoDisplayString(ssCdma.getCdmaDbm()),
+                getCellInfoDisplayString(ssCdma.getCdmaEcio()),
+                getCellInfoDisplayString(ssCdma.getEvdoDbm()),
+                getCellInfoDisplayString(ssCdma.getEvdoEcio()),
+                getCellInfoDisplayString(ssCdma.getEvdoSnr()));
+    }
+
+    private String buildGsmInfoString(CellInfoGsm ci) {
+        CellIdentityGsm cidGsm = ci.getCellIdentity();
+        CellSignalStrengthGsm ssGsm = ci.getCellSignalStrength();
+
+        return String.format("%-3.3s %-3.3s %-3.3s %-5.5s %-5.5s %-6.6s %-4.4s %-4.4s\n",
+                getConnectionStatusString(ci),
+                getCellInfoDisplayString(cidGsm.getMcc()),
+                getCellInfoDisplayString(cidGsm.getMnc()),
+                getCellInfoDisplayString(cidGsm.getLac()),
+                getCellInfoDisplayString(cidGsm.getCid()),
+                getCellInfoDisplayString(cidGsm.getArfcn()),
+                getCellInfoDisplayString(cidGsm.getBsic()),
+                getCellInfoDisplayString(ssGsm.getDbm()));
+    }
+
+    private String buildLteInfoString(CellInfoLte ci) {
+        CellIdentityLte cidLte = ci.getCellIdentity();
+        CellSignalStrengthLte ssLte = ci.getCellSignalStrength();
+
+        return String.format(
+                "%-3.3s %-3.3s %-3.3s %-5.5s %-5.5s %-3.3s %-6.6s %-2.2s %-4.4s %-4.4s %-2.2s\n",
+                getConnectionStatusString(ci),
+                getCellInfoDisplayString(cidLte.getMcc()),
+                getCellInfoDisplayString(cidLte.getMnc()),
+                getCellInfoDisplayString(cidLte.getTac()),
+                getCellInfoDisplayString(cidLte.getCi()),
+                getCellInfoDisplayString(cidLte.getPci()),
+                getCellInfoDisplayString(cidLte.getEarfcn()),
+                getCellInfoDisplayString(cidLte.getBandwidth()),
+                getCellInfoDisplayString(ssLte.getDbm()),
+                getCellInfoDisplayString(ssLte.getRsrq()),
+                getCellInfoDisplayString(ssLte.getTimingAdvance()));
+    }
+
+    private String buildWcdmaInfoString(CellInfoWcdma ci) {
+        CellIdentityWcdma cidWcdma = ci.getCellIdentity();
+        CellSignalStrengthWcdma ssWcdma = ci.getCellSignalStrength();
+
+        return String.format("%-3.3s %-3.3s %-3.3s %-5.5s %-5.5s %-6.6s %-3.3s %-4.4s\n",
+                getConnectionStatusString(ci),
+                getCellInfoDisplayString(cidWcdma.getMcc()),
+                getCellInfoDisplayString(cidWcdma.getMnc()),
+                getCellInfoDisplayString(cidWcdma.getLac()),
+                getCellInfoDisplayString(cidWcdma.getCid()),
+                getCellInfoDisplayString(cidWcdma.getUarfcn()),
+                getCellInfoDisplayString(cidWcdma.getPsc()),
+                getCellInfoDisplayString(ssWcdma.getDbm()));
+    }
+
+    private String buildCellInfoString(List<CellInfo> arrayCi) {
+        String value = new String();
+        StringBuilder cdmaCells = new StringBuilder(),
+                gsmCells = new StringBuilder(),
+                lteCells = new StringBuilder(),
+                wcdmaCells = new StringBuilder();
+
+        if (arrayCi != null) {
+            for (CellInfo ci : arrayCi) {
+
+                if (ci instanceof CellInfoLte) {
+                    lteCells.append(buildLteInfoString((CellInfoLte) ci));
+                } else if (ci instanceof CellInfoWcdma) {
+                    wcdmaCells.append(buildWcdmaInfoString((CellInfoWcdma) ci));
+                } else if (ci instanceof CellInfoGsm) {
+                    gsmCells.append(buildGsmInfoString((CellInfoGsm) ci));
+                } else if (ci instanceof CellInfoCdma) {
+                    cdmaCells.append(buildCdmaInfoString((CellInfoCdma) ci));
+                }
+            }
+            if (lteCells.length() != 0) {
+                value += String.format(
+                        "LTE\n%-3.3s %-3.3s %-3.3s %-5.5s %-5.5s %-3.3s"
+                                + " %-6.6s %-2.2s %-4.4s %-4.4s %-2.2s\n",
+                        "SRV", "MCC", "MNC", "TAC", "CID", "PCI",
+                        "EARFCN", "BW", "RSRP", "RSRQ", "TA");
+                value += lteCells.toString();
+            }
+            if (wcdmaCells.length() != 0) {
+                value += String.format(
+                        "WCDMA\n%-3.3s %-3.3s %-3.3s %-5.5s %-5.5s %-6.6s %-3.3s %-4.4s\n",
+                        "SRV", "MCC", "MNC", "LAC", "CID", "UARFCN", "PSC", "RSCP");
+                value += wcdmaCells.toString();
+            }
+            if (gsmCells.length() != 0) {
+                value += String.format(
+                        "GSM\n%-3.3s %-3.3s %-3.3s %-5.5s %-5.5s %-6.6s %-4.4s %-4.4s\n",
+                        "SRV", "MCC", "MNC", "LAC", "CID", "ARFCN", "BSIC", "RSSI");
+                value += gsmCells.toString();
+            }
+            if (cdmaCells.length() != 0) {
+                value += String.format(
+                        "CDMA/EVDO\n%-3.3s %-5.5s %-5.5s %-5.5s"
+                                + " %-6.6s %-6.6s %-6.6s %-6.6s %-5.5s\n",
+                        "SRV", "SID", "NID", "BSID",
+                        "C-RSSI", "C-ECIO", "E-RSSI", "E-ECIO", "E-SNR");
+                value += cdmaCells.toString();
+            }
+        } else {
+            value = "unknown";
+        }
+
+        return value.toString();
+    }
+
+    private void updateCellInfo(List<CellInfo> arrayCi) {
+        mCellInfo.setText(buildCellInfoString(arrayCi));
+    }
+
+    private void updateSubscriptionIds() {
+        mSubscriptionId.setText(Integer.toString(mPhone.getSubId()));
+        mDds.setText(Integer.toString(SubscriptionManager.getDefaultDataSubscriptionId()));
+    }
+
+    private void updateMessageWaiting() {
+        mMwi.setText(String.valueOf(mMwiValue));
+    }
+
+    private void updateCallRedirect() {
+        mCfi.setText(String.valueOf(mCfiValue));
+    }
+
+
+    private void updateServiceState(ServiceState serviceState) {
+        int state = serviceState.getState();
+        Resources r = getResources();
+        String display = r.getString(R.string.radioInfo_unknown);
+
+        switch (state) {
+            case ServiceState.STATE_IN_SERVICE:
+                display = r.getString(R.string.radioInfo_service_in);
+                break;
+            case ServiceState.STATE_OUT_OF_SERVICE:
+            case ServiceState.STATE_EMERGENCY_ONLY:
+                display = r.getString(R.string.radioInfo_service_emergency);
+                break;
+            case ServiceState.STATE_POWER_OFF:
+                display = r.getString(R.string.radioInfo_service_off);
+                break;
+        }
+
+        mGsmState.setText(display);
+
+        if (serviceState.getRoaming()) {
+            mRoamingState.setText(R.string.radioInfo_roaming_in);
+        } else {
+            mRoamingState.setText(R.string.radioInfo_roaming_not);
+        }
+
+        mOperatorName.setText(serviceState.getOperatorAlphaLong());
+    }
+
+    private void updatePhoneState(int state) {
+        Resources r = getResources();
+        String display = r.getString(R.string.radioInfo_unknown);
+
+        switch (state) {
+            case TelephonyManager.CALL_STATE_IDLE:
+                display = r.getString(R.string.radioInfo_phone_idle);
+                break;
+            case TelephonyManager.CALL_STATE_RINGING:
+                display = r.getString(R.string.radioInfo_phone_ringing);
+                break;
+            case TelephonyManager.CALL_STATE_OFFHOOK:
+                display = r.getString(R.string.radioInfo_phone_offhook);
+                break;
+        }
+
+        mCallState.setText(display);
+    }
+
+    private void updateDataState() {
+        int state = mTelephonyManager.getDataState();
+        Resources r = getResources();
+        String display = r.getString(R.string.radioInfo_unknown);
+
+        switch (state) {
+            case TelephonyManager.DATA_CONNECTED:
+                display = r.getString(R.string.radioInfo_data_connected);
+                break;
+            case TelephonyManager.DATA_CONNECTING:
+                display = r.getString(R.string.radioInfo_data_connecting);
+                break;
+            case TelephonyManager.DATA_DISCONNECTED:
+                display = r.getString(R.string.radioInfo_data_disconnected);
+                break;
+            case TelephonyManager.DATA_SUSPENDED:
+                display = r.getString(R.string.radioInfo_data_suspended);
+                break;
+        }
+
+        mGprsState.setText(display);
+    }
+
+    private void updateNetworkType() {
+        if (mPhone != null) {
+            ServiceState ss = mPhone.getServiceState();
+            mDataNetwork.setText(ServiceState.rilRadioTechnologyToString(
+                    mPhone.getServiceState().getRilDataRadioTechnology()));
+            mVoiceNetwork.setText(ServiceState.rilRadioTechnologyToString(
+                    mPhone.getServiceState().getRilVoiceRadioTechnology()));
+        }
+    }
+
+    private void updateProperties() {
+        String s;
+        Resources r = getResources();
+
+        s = mPhone.getDeviceId();
+        if (s == null) s = r.getString(R.string.radioInfo_unknown);
+        mDeviceId.setText(s);
+
+        s = mPhone.getSubscriberId();
+        if (s == null) s = r.getString(R.string.radioInfo_unknown);
+        mSubscriberId.setText(s);
+
+        //FIXME: Replace with a TelephonyManager call
+        s = mPhone.getLine1Number();
+        if (s == null) s = r.getString(R.string.radioInfo_unknown);
+        mLine1Number.setText(s);
+    }
+
+    private void updateDataStats2() {
+        Resources r = getResources();
+
+        long txPackets = TrafficStats.getMobileTxPackets();
+        long rxPackets = TrafficStats.getMobileRxPackets();
+        long txBytes   = TrafficStats.getMobileTxBytes();
+        long rxBytes   = TrafficStats.getMobileRxBytes();
+
+        String packets = r.getString(R.string.radioInfo_display_packets);
+        String bytes   = r.getString(R.string.radioInfo_display_bytes);
+
+        mSent.setText(txPackets + " " + packets + ", " + txBytes + " " + bytes);
+        mReceived.setText(rxPackets + " " + packets + ", " + rxBytes + " " + bytes);
+    }
+
+    /**
+     *  Ping a host name
+     */
+    private void pingHostname() {
+        try {
+            try {
+                Process p4 = Runtime.getRuntime().exec("ping -c 1 www.google.com");
+                int status4 = p4.waitFor();
+                if (status4 == 0) {
+                    mPingHostnameResultV4 = "Pass";
+                } else {
+                    mPingHostnameResultV4 = String.format("Fail(%d)", status4);
+                }
+            } catch (IOException e) {
+                mPingHostnameResultV4 = "Fail: IOException";
+            }
+            try {
+                Process p6 = Runtime.getRuntime().exec("ping6 -c 1 www.google.com");
+                int status6 = p6.waitFor();
+                if (status6 == 0) {
+                    mPingHostnameResultV6 = "Pass";
+                } else {
+                    mPingHostnameResultV6 = String.format("Fail(%d)", status6);
+                }
+            } catch (IOException e) {
+                mPingHostnameResultV6 = "Fail: IOException";
+            }
+        } catch (InterruptedException e) {
+            mPingHostnameResultV4 = mPingHostnameResultV6 = "Fail: InterruptedException";
+        }
+    }
+
+    /**
+     * This function checks for basic functionality of HTTP Client.
+     */
+    private void httpClientTest() {
+        HttpURLConnection urlConnection = null;
+        try {
+            // TODO: Hardcoded for now, make it UI configurable
+            URL url = new URL("https://www.google.com");
+            urlConnection = (HttpURLConnection) url.openConnection();
+            if (urlConnection.getResponseCode() == 200) {
+                mHttpClientTestResult = "Pass";
+            } else {
+                mHttpClientTestResult = "Fail: Code: " + urlConnection.getResponseMessage();
+            }
+        } catch (IOException e) {
+            mHttpClientTestResult = "Fail: IOException";
+        } finally {
+            if (urlConnection != null) {
+                urlConnection.disconnect();
+            }
+        }
+    }
+
+    private void refreshSmsc() {
+        mQueuedWork.execute(new Runnable() {
+            public void run() {
+                //FIXME: Replace with a TelephonyManager call
+                mPhone.getSmscAddress(mHandler.obtainMessage(EVENT_QUERY_SMSC_DONE));
+            }
+        });
+    }
+
+    private void updateAllCellInfo() {
+
+        mCellInfo.setText("");
+        mLocation.setText("");
+
+        final Runnable updateAllCellInfoResults = new Runnable() {
+            public void run() {
+                updateLocation(mCellLocationResult);
+                updateCellInfo(mCellInfoResult);
+            }
+        };
+
+        mQueuedWork.execute(new Runnable() {
+            @Override
+            public void run() {
+                mCellInfoResult = mTelephonyManager.getAllCellInfo();
+                mCellLocationResult = mTelephonyManager.getCellLocation();
+
+                mHandler.post(updateAllCellInfoResults);
+            }
+        });
+    }
+
+    private void updatePingState() {
+        // Set all to unknown since the threads will take a few secs to update.
+        mPingHostnameResultV4 = getResources().getString(R.string.radioInfo_unknown);
+        mPingHostnameResultV6 = getResources().getString(R.string.radioInfo_unknown);
+        mHttpClientTestResult = getResources().getString(R.string.radioInfo_unknown);
+
+        mPingHostnameV4.setText(mPingHostnameResultV4);
+        mPingHostnameV6.setText(mPingHostnameResultV6);
+        mHttpClientTest.setText(mHttpClientTestResult);
+
+        final Runnable updatePingResults = new Runnable() {
+            public void run() {
+                mPingHostnameV4.setText(mPingHostnameResultV4);
+                mPingHostnameV6.setText(mPingHostnameResultV6);
+                mHttpClientTest.setText(mHttpClientTestResult);
+            }
+        };
+
+        Thread hostname = new Thread() {
+            @Override
+            public void run() {
+                pingHostname();
+                mHandler.post(updatePingResults);
+            }
+        };
+        hostname.start();
+
+        Thread httpClient = new Thread() {
+            @Override
+            public void run() {
+                httpClientTest();
+                mHandler.post(updatePingResults);
+            }
+        };
+        httpClient.start();
+    }
+
+    private MenuItem.OnMenuItemClickListener mViewADNCallback =
+            new MenuItem.OnMenuItemClickListener() {
+        public boolean onMenuItemClick(MenuItem item) {
+            Intent intent = new Intent(Intent.ACTION_VIEW);
+            // XXX We need to specify the component here because if we don't
+            // the activity manager will try to resolve the type by calling
+            // the content provider, which causes it to be loaded in a process
+            // other than the Dialer process, which causes a lot of stuff to
+            // break.
+            intent.setClassName("com.android.phone", "com.android.phone.SimContacts");
+            startActivity(intent);
+            return true;
+        }
+    };
+
+    private MenuItem.OnMenuItemClickListener mViewFDNCallback =
+            new MenuItem.OnMenuItemClickListener() {
+        public boolean onMenuItemClick(MenuItem item) {
+            Intent intent = new Intent(Intent.ACTION_VIEW);
+            // XXX We need to specify the component here because if we don't
+            // the activity manager will try to resolve the type by calling
+            // the content provider, which causes it to be loaded in a process
+            // other than the Dialer process, which causes a lot of stuff to
+            // break.
+            intent.setClassName("com.android.phone", "com.android.phone.settings.fdn.FdnList");
+            startActivity(intent);
+            return true;
+        }
+    };
+
+    private MenuItem.OnMenuItemClickListener mViewSDNCallback =
+            new MenuItem.OnMenuItemClickListener() {
+        public boolean onMenuItemClick(MenuItem item) {
+            Intent intent = new Intent(
+                    Intent.ACTION_VIEW, Uri.parse("content://icc/sdn"));
+            // XXX We need to specify the component here because if we don't
+            // the activity manager will try to resolve the type by calling
+            // the content provider, which causes it to be loaded in a process
+            // other than the Dialer process, which causes a lot of stuff to
+            // break.
+            intent.setClassName("com.android.phone", "com.android.phone.ADNList");
+            startActivity(intent);
+            return true;
+        }
+    };
+
+    private MenuItem.OnMenuItemClickListener mGetImsStatus =
+            new MenuItem.OnMenuItemClickListener() {
+        public boolean onMenuItemClick(MenuItem item) {
+            boolean isImsRegistered = mPhone.isImsRegistered();
+            boolean availableVolte = mPhone.isVolteEnabled();
+            boolean availableWfc = mPhone.isWifiCallingEnabled();
+            boolean availableVt = mPhone.isVideoEnabled();
+            boolean availableUt = mPhone.isUtEnabled();
+
+            final String imsRegString = isImsRegistered
+                    ? getString(R.string.radio_info_ims_reg_status_registered)
+                    : getString(R.string.radio_info_ims_reg_status_not_registered);
+
+            final String available = getString(R.string.radio_info_ims_feature_status_available);
+            final String unavailable = getString(
+                    R.string.radio_info_ims_feature_status_unavailable);
+
+            String imsStatus = getString(R.string.radio_info_ims_reg_status,
+                    imsRegString,
+                    availableVolte ? available : unavailable,
+                    availableWfc ? available : unavailable,
+                    availableVt ? available : unavailable,
+                    availableUt ? available : unavailable);
+
+            AlertDialog imsDialog = new AlertDialog.Builder(RadioInfo.this)
+                    .setMessage(imsStatus)
+                    .setTitle(getString(R.string.radio_info_ims_reg_status_title))
+                    .create();
+
+            imsDialog.show();
+
+            return true;
+        }
+    };
+
+    private MenuItem.OnMenuItemClickListener mSelectBandCallback =
+            new MenuItem.OnMenuItemClickListener() {
+        public boolean onMenuItemClick(MenuItem item) {
+            Intent intent = new Intent();
+            intent.setClass(RadioInfo.this, BandMode.class);
+            startActivity(intent);
+            return true;
+        }
+    };
+
+    private MenuItem.OnMenuItemClickListener mToggleData =
+            new MenuItem.OnMenuItemClickListener() {
+        public boolean onMenuItemClick(MenuItem item) {
+            int state = mTelephonyManager.getDataState();
+            switch (state) {
+                case TelephonyManager.DATA_CONNECTED:
+                    mTelephonyManager.setDataEnabled(false);
+                    break;
+                case TelephonyManager.DATA_DISCONNECTED:
+                    mTelephonyManager.setDataEnabled(true);
+                    break;
+                default:
+                    // do nothing
+                    break;
+            }
+            return true;
+        }
+    };
+
+    private boolean isRadioOn() {
+        //FIXME: Replace with a TelephonyManager call
+        return mPhone.getServiceState().getState() != ServiceState.STATE_POWER_OFF;
+    }
+
+    private void updateRadioPowerState() {
+        //delightful hack to prevent on-checked-changed calls from
+        //actually forcing the radio preference to its transient/current value.
+        mRadioPowerOnSwitch.setOnCheckedChangeListener(null);
+        mRadioPowerOnSwitch.setChecked(isRadioOn());
+        mRadioPowerOnSwitch.setOnCheckedChangeListener(mRadioPowerOnChangeListener);
+    }
+
+    void setImsVolteProvisionedState(boolean state) {
+        Log.d(TAG, "setImsVolteProvisioned state: " + ((state) ? "on" : "off"));
+        setImsConfigProvisionedState(IMS_VOLTE_PROVISIONED_CONFIG_ID, state);
+    }
+
+    void setImsVtProvisionedState(boolean state) {
+        Log.d(TAG, "setImsVtProvisioned() state: " + ((state) ? "on" : "off"));
+        setImsConfigProvisionedState(IMS_VT_PROVISIONED_CONFIG_ID, state);
+    }
+
+    void setImsWfcProvisionedState(boolean state) {
+        Log.d(TAG, "setImsWfcProvisioned() state: " + ((state) ? "on" : "off"));
+        setImsConfigProvisionedState(IMS_WFC_PROVISIONED_CONFIG_ID, state);
+    }
+
+    void setEabProvisionedState(boolean state) {
+        Log.d(TAG, "setEabProvisioned() state: " + ((state) ? "on" : "off"));
+        setImsConfigProvisionedState(EAB_PROVISIONED_CONFIG_ID, state);
+    }
+
+    void setImsConfigProvisionedState(int configItem, boolean state) {
+        if (mPhone != null && mImsManager != null) {
+            mQueuedWork.execute(new Runnable() {
+                public void run() {
+                    try {
+                        mImsManager.getConfigInterface().setProvisionedValue(
+                                configItem, state ? 1 : 0);
+                    } catch (ImsException e) {
+                        Log.e(TAG, "setImsConfigProvisioned() exception:", e);
+                    }
+                }
+            });
+        }
+    }
+
+    OnCheckedChangeListener mRadioPowerOnChangeListener = new OnCheckedChangeListener() {
+        @Override
+        public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
+            log("toggle radio power: currently " + (isRadioOn() ? "on" : "off"));
+            mPhone.setRadioPower(isChecked);
+        }
+    };
+
+    private boolean isImsVolteProvisioned() {
+        if (mPhone != null && mImsManager != null) {
+            return mImsManager.isVolteEnabledByPlatform(mPhone.getContext())
+                && mImsManager.isVolteProvisionedOnDevice(mPhone.getContext());
+        }
+        return false;
+    }
+
+    OnCheckedChangeListener mImsVolteCheckedChangeListener = new OnCheckedChangeListener() {
+        @Override
+        public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
+            setImsVolteProvisionedState(isChecked);
+        }
+    };
+
+    private boolean isImsVtProvisioned() {
+        if (mPhone != null && mImsManager != null) {
+            return mImsManager.isVtEnabledByPlatform(mPhone.getContext())
+                && mImsManager.isVtProvisionedOnDevice(mPhone.getContext());
+        }
+        return false;
+    }
+
+    OnCheckedChangeListener mImsVtCheckedChangeListener = new OnCheckedChangeListener() {
+        @Override
+        public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
+            setImsVtProvisionedState(isChecked);
+        }
+    };
+
+    private boolean isImsWfcProvisioned() {
+        if (mPhone != null && mImsManager != null) {
+            return mImsManager.isWfcEnabledByPlatform(mPhone.getContext())
+                && mImsManager.isWfcProvisionedOnDevice(mPhone.getContext());
+        }
+        return false;
+    }
+
+    OnCheckedChangeListener mImsWfcCheckedChangeListener = new OnCheckedChangeListener() {
+        @Override
+        public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
+            setImsWfcProvisionedState(isChecked);
+        }
+    };
+
+    private boolean isEabProvisioned() {
+        return isFeatureProvisioned(EAB_PROVISIONED_CONFIG_ID, false);
+    }
+
+    OnCheckedChangeListener mEabCheckedChangeListener = new OnCheckedChangeListener() {
+        @Override
+        public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
+            setEabProvisionedState(isChecked);
+        }
+    };
+
+    private boolean isFeatureProvisioned(int featureId, boolean defaultValue) {
+        boolean provisioned = defaultValue;
+        if (mImsManager != null) {
+            try {
+                ImsConfig imsConfig = mImsManager.getConfigInterface();
+                if (imsConfig != null) {
+                    provisioned =
+                            (imsConfig.getProvisionedValue(featureId)
+                                    == ImsConfig.FeatureValueConstants.ON);
+                }
+            } catch (ImsException ex) {
+                Log.e(TAG, "isFeatureProvisioned() exception:", ex);
+            }
+        }
+
+        log("isFeatureProvisioned() featureId=" + featureId + " provisioned=" + provisioned);
+        return provisioned;
+    }
+
+    private static boolean isEabEnabledByPlatform(Context context) {
+        if (context != null) {
+            CarrierConfigManager configManager = (CarrierConfigManager)
+                    context.getSystemService(Context.CARRIER_CONFIG_SERVICE);
+            if (configManager != null && configManager.getConfig().getBoolean(
+                        CarrierConfigManager.KEY_USE_RCS_PRESENCE_BOOL)) {
+                return true;
+            }
+        }
+        return false;
+    }
+
+    private void updateImsProvisionedState() {
+        if (!ImsManager.isImsSupportedOnDevice(mPhone.getContext())) {
+            return;
+        }
+        log("updateImsProvisionedState isImsVolteProvisioned()=" + isImsVolteProvisioned());
+        //delightful hack to prevent on-checked-changed calls from
+        //actually forcing the ims provisioning to its transient/current value.
+        mImsVolteProvisionedSwitch.setOnCheckedChangeListener(null);
+        mImsVolteProvisionedSwitch.setChecked(isImsVolteProvisioned());
+        mImsVolteProvisionedSwitch.setOnCheckedChangeListener(mImsVolteCheckedChangeListener);
+        mImsVolteProvisionedSwitch.setEnabled(!IS_USER_BUILD
+                && mImsManager.isVolteEnabledByPlatform(mPhone.getContext()));
+
+        mImsVtProvisionedSwitch.setOnCheckedChangeListener(null);
+        mImsVtProvisionedSwitch.setChecked(isImsVtProvisioned());
+        mImsVtProvisionedSwitch.setOnCheckedChangeListener(mImsVtCheckedChangeListener);
+        mImsVtProvisionedSwitch.setEnabled(!IS_USER_BUILD
+                && mImsManager.isVtEnabledByPlatform(mPhone.getContext()));
+
+        mImsWfcProvisionedSwitch.setOnCheckedChangeListener(null);
+        mImsWfcProvisionedSwitch.setChecked(isImsWfcProvisioned());
+        mImsWfcProvisionedSwitch.setOnCheckedChangeListener(mImsWfcCheckedChangeListener);
+        mImsWfcProvisionedSwitch.setEnabled(!IS_USER_BUILD
+                && mImsManager.isWfcEnabledByPlatform(mPhone.getContext()));
+
+        mEabProvisionedSwitch.setOnCheckedChangeListener(null);
+        mEabProvisionedSwitch.setChecked(isEabProvisioned());
+        mEabProvisionedSwitch.setOnCheckedChangeListener(mEabCheckedChangeListener);
+        mEabProvisionedSwitch.setEnabled(!IS_USER_BUILD
+                && isEabEnabledByPlatform(mPhone.getContext()));
+    }
+
+    OnClickListener mDnsCheckButtonHandler = new OnClickListener() {
+        public void onClick(View v) {
+            //FIXME: Replace with a TelephonyManager call
+            mPhone.disableDnsCheck(!mPhone.isDnsCheckDisabled());
+            updateDnsCheckState();
+        }
+    };
+
+    OnClickListener mOemInfoButtonHandler = new OnClickListener() {
+        public void onClick(View v) {
+            Intent intent = new Intent(OEM_RADIO_INFO_INTENT);
+            try {
+                startActivity(intent);
+            } catch (android.content.ActivityNotFoundException ex) {
+                log("OEM-specific Info/Settings Activity Not Found : " + ex);
+                // If the activity does not exist, there are no OEM
+                // settings, and so we can just do nothing...
+            }
+        }
+    };
+
+    OnClickListener mPingButtonHandler = new OnClickListener() {
+        public void onClick(View v) {
+            updatePingState();
+        }
+    };
+
+    OnClickListener mUpdateSmscButtonHandler = new OnClickListener() {
+        public void onClick(View v) {
+            mUpdateSmscButton.setEnabled(false);
+            mQueuedWork.execute(new Runnable() {
+                public void run() {
+                    mPhone.setSmscAddress(mSmsc.getText().toString(),
+                            mHandler.obtainMessage(EVENT_UPDATE_SMSC_DONE));
+                }
+            });
+        }
+    };
+
+    OnClickListener mRefreshSmscButtonHandler = new OnClickListener() {
+        public void onClick(View v) {
+            refreshSmsc();
+        }
+    };
+
+    OnClickListener mCarrierProvisioningButtonHandler = new OnClickListener() {
+        public void onClick(View v) {
+            final Intent intent = new Intent("com.android.settings.CARRIER_PROVISIONING");
+            final ComponentName serviceComponent = ComponentName.unflattenFromString(
+                    "com.android.omadm.service/.DMIntentReceiver");
+            intent.setComponent(serviceComponent);
+            sendBroadcast(intent);
+        }
+    };
+
+    OnClickListener mTriggerCarrierProvisioningButtonHandler = new OnClickListener() {
+        public void onClick(View v) {
+            final Intent intent = new Intent("com.android.settings.TRIGGER_CARRIER_PROVISIONING");
+            final ComponentName serviceComponent = ComponentName.unflattenFromString(
+                    "com.android.omadm.service/.DMIntentReceiver");
+            intent.setComponent(serviceComponent);
+            sendBroadcast(intent);
+        }
+    };
+
+    AdapterView.OnItemSelectedListener mPreferredNetworkHandler =
+            new AdapterView.OnItemSelectedListener() {
+
+        public void onItemSelected(AdapterView parent, View v, int pos, long id) {
+            if (mPreferredNetworkTypeResult != pos && pos >= 0
+                    && pos <= PREFERRED_NETWORK_LABELS.length - 2) {
+                mPreferredNetworkTypeResult = pos;
+
+                // TODO: Possibly migrate this to TelephonyManager.setPreferredNetworkType()
+                // which today still has some issues (mostly that the "set" is conditional
+                // on a successful modem call, which is not what we want). Instead we always
+                // want this setting to be set, so that if the radio hiccups and this setting
+                // is for some reason unsuccessful, future calls to the radio will reflect
+                // the users's preference which is set here.
+                final int subId = mPhone.getSubId();
+                if (SubscriptionManager.isUsableSubIdValue(subId)) {
+                    Settings.Global.putInt(mPhone.getContext().getContentResolver(),
+                            PREFERRED_NETWORK_MODE + subId, mPreferredNetworkTypeResult);
+                }
+                log("Calling setPreferredNetworkType(" + mPreferredNetworkTypeResult + ")");
+                Message msg = mHandler.obtainMessage(EVENT_SET_PREFERRED_TYPE_DONE);
+                mPhone.setPreferredNetworkType(mPreferredNetworkTypeResult, msg);
+            }
+        }
+
+        public void onNothingSelected(AdapterView parent) {
+        }
+    };
+
+    AdapterView.OnItemSelectedListener mSelectPhoneIndexHandler =
+            new AdapterView.OnItemSelectedListener() {
+
+        public void onItemSelected(AdapterView parent, View v, int pos, long id) {
+            if (pos >= 0 && pos <= sPhoneIndexLabels.length - 1) {
+                // the array position is equal to the phone index
+                int phoneIndex = pos;
+                Phone[] phones = PhoneFactory.getPhones();
+                if (phones == null || phones.length <= phoneIndex) {
+                    return;
+                }
+                // getSubId says it takes a slotIndex, but it actually takes a phone index
+                int subId = SubscriptionManager.INVALID_SUBSCRIPTION_ID;
+                int[] subIds = SubscriptionManager.getSubId(phoneIndex);
+                if (subIds != null && subIds.length > 0) {
+                    subId = subIds[0];
+                }
+                mSelectedPhoneIndex = phoneIndex;
+
+                updatePhoneIndex(phoneIndex, subId);
+            }
+        }
+
+        public void onNothingSelected(AdapterView parent) {
+        }
+    };
+
+    AdapterView.OnItemSelectedListener mCellInfoRefreshRateHandler  =
+            new AdapterView.OnItemSelectedListener() {
+
+        public void onItemSelected(AdapterView parent, View v, int pos, long id) {
+            mCellInfoRefreshRateIndex = pos;
+            mTelephonyManager.setCellInfoListRate(CELL_INFO_REFRESH_RATES[pos]);
+            updateAllCellInfo();
+        }
+
+        public void onNothingSelected(AdapterView parent) {
+        }
+    };
+
+    boolean isCbrsSupported() {
+        return getResources().getBoolean(
+              com.android.internal.R.bool.config_cbrs_supported);
+    }
+
+    void updateCbrsDataState(boolean state) {
+        Log.d(TAG, "setCbrsDataSwitchState() state:" + ((state) ? "on" : "off"));
+        if (mTelephonyManager != null) {
+            mQueuedWork.execute(new Runnable() {
+                public void run() {
+                    mTelephonyManager.setOpportunisticNetworkState(state);
+                    mCbrsDataSwitch.setChecked(getCbrsDataState());
+                }
+            });
+        }
+    }
+
+    boolean getCbrsDataState() {
+        boolean state = false;
+        if (mTelephonyManager != null) {
+            state = mTelephonyManager.isOpportunisticNetworkEnabled();
+        }
+        Log.d(TAG, "getCbrsDataState() state:" + ((state) ? "on" : "off"));
+        return state;
+    }
+
+    OnCheckedChangeListener mCbrsDataSwitchChangeListener = new OnCheckedChangeListener() {
+        @Override
+        public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
+            updateCbrsDataState(isChecked);
+        }
+    };
+
+    private void showDsdsChangeDialog() {
+        final AlertDialog confirmDialog = new Builder(RadioInfo.this)
+                .setTitle(R.string.dsds_dialog_title)
+                .setMessage(R.string.dsds_dialog_message)
+                .setPositiveButton(R.string.dsds_dialog_confirm, mOnDsdsDialogConfirmedListener)
+                .setNegativeButton(R.string.dsds_dialog_cancel, mOnDsdsDialogConfirmedListener)
+                .create();
+        confirmDialog.show();
+    }
+
+    private static boolean isDsdsSupported() {
+        return (TelephonyManager.getDefault().isMultiSimSupported()
+            == TelephonyManager.MULTISIM_ALLOWED);
+    }
+
+    private static boolean isDsdsEnabled() {
+        return TelephonyManager.getDefault().getPhoneCount() > 1;
+    }
+
+    private void performDsdsSwitch() {
+        mTelephonyManager.switchMultiSimConfig(mDsdsSwitch.isChecked() ? 2 : 1);
+    }
+
+    /**
+     * @return {@code True} if the device is only supported dsds mode.
+     */
+    private boolean dsdsModeOnly() {
+        String dsdsMode = SystemProperties.get(DSDS_MODE_PROPERTY);
+        return !TextUtils.isEmpty(dsdsMode) && Integer.parseInt(dsdsMode) == ALWAYS_ON_DSDS_MODE;
+    }
+
+    DialogInterface.OnClickListener mOnDsdsDialogConfirmedListener =
+            new DialogInterface.OnClickListener() {
+        @Override
+        public void onClick(DialogInterface dialog, int which) {
+            if (which == DialogInterface.BUTTON_POSITIVE) {
+                mDsdsSwitch.toggle();
+                performDsdsSwitch();
+            }
+        }
+    };
+}
diff --git a/src/com/android/services/telephony/DisconnectCauseUtil.java b/src/com/android/services/telephony/DisconnectCauseUtil.java
index 5227e8b..4a5fb4a 100644
--- a/src/com/android/services/telephony/DisconnectCauseUtil.java
+++ b/src/com/android/services/telephony/DisconnectCauseUtil.java
@@ -18,10 +18,14 @@
 
 import android.content.Context;
 import android.media.ToneGenerator;
+import android.os.PersistableBundle;
 import android.telecom.DisconnectCause;
+import android.telephony.CarrierConfigManager;
 import android.telephony.SubscriptionManager;
 
 import com.android.internal.telephony.CallFailCause;
+import com.android.internal.telephony.Phone;
+import com.android.internal.telephony.PhoneFactory;
 import com.android.phone.ImsUtil;
 import com.android.phone.PhoneGlobals;
 import com.android.phone.common.R;
@@ -102,7 +106,7 @@
                         telephonyPerciseDisconnectCause),
                 toTelecomDisconnectCauseDescription(context, telephonyDisconnectCause, phoneId),
                 toTelecomDisconnectReason(context,telephonyDisconnectCause, reason, phoneId),
-                toTelecomDisconnectCauseTone(telephonyDisconnectCause));
+                toTelecomDisconnectCauseTone(telephonyDisconnectCause, phoneId));
     }
 
     /**
@@ -807,11 +811,22 @@
     /**
      * Returns the tone to play for the disconnect cause, or UNKNOWN if none should be played.
      */
-    private static int toTelecomDisconnectCauseTone(int telephonyDisconnectCause) {
-        switch (telephonyDisconnectCause) {
-            case android.telephony.DisconnectCause.BUSY:
+    private static int toTelecomDisconnectCauseTone(int telephonyDisconnectCause, int phoneId) {
+        Phone phone = PhoneFactory.getPhone(phoneId);
+        PersistableBundle config;
+        if (phone != null) {
+            config = PhoneGlobals.getInstance().getCarrierConfigForSubId(phone.getSubId());
+        } else {
+            config = PhoneGlobals.getInstance().getCarrierConfig();
+        }
+        int[] busyToneArray = config.getIntArray(
+                CarrierConfigManager.KEY_DISCONNECT_CAUSE_PLAY_BUSYTONE_INT_ARRAY);
+        for (int busyTone : busyToneArray) {
+            if (busyTone == telephonyDisconnectCause) {
                 return ToneGenerator.TONE_SUP_BUSY;
-
+            }
+        }
+        switch (telephonyDisconnectCause) {
             case android.telephony.DisconnectCause.CONGESTION:
                 return ToneGenerator.TONE_SUP_CONGESTION;
 
diff --git a/src/com/android/services/telephony/RadioOnHelper.java b/src/com/android/services/telephony/RadioOnHelper.java
index 85f94ab..741a6c5 100644
--- a/src/com/android/services/telephony/RadioOnHelper.java
+++ b/src/com/android/services/telephony/RadioOnHelper.java
@@ -53,7 +53,7 @@
             return;
         }
         mListeners = new ArrayList<>(2);
-        for (int i = 0; i < TelephonyManager.getDefault().getMaxPhoneCount(); i++) {
+        for (int i = 0; i < TelephonyManager.getDefault().getSupportedModemCount(); i++) {
             mListeners.add(new RadioOnStateListener());
         }
     }
@@ -76,7 +76,7 @@
         mCallback = callback;
         mInProgressListeners.clear();
         mIsRadioOnCallingEnabled = false;
-        for (int i = 0; i < TelephonyManager.getDefault().getMaxPhoneCount(); i++) {
+        for (int i = 0; i < TelephonyManager.getDefault().getSupportedModemCount(); i++) {
             Phone phone = PhoneFactory.getPhone(i);
             if (phone == null) {
                 continue;
diff --git a/src/com/android/services/telephony/TelecomAccountRegistry.java b/src/com/android/services/telephony/TelecomAccountRegistry.java
index 6bbcdc4..0cb687f 100644
--- a/src/com/android/services/telephony/TelecomAccountRegistry.java
+++ b/src/com/android/services/telephony/TelecomAccountRegistry.java
@@ -803,8 +803,10 @@
                 Log.i(this, "User changed, re-registering phone accounts.");
 
                 int userHandleId = intent.getIntExtra(Intent.EXTRA_USER_HANDLE, 0);
-                UserHandle currentUserHandle = new UserHandle(userHandleId);
-                mIsPrimaryUser = UserManager.get(mContext).getPrimaryUser().getUserHandle()
+                UserHandle currentUserHandle = UserHandle.of(userHandleId);
+                UserManager userManager =
+                        (UserManager) context.getSystemService(Context.USER_SERVICE);
+                mIsPrimaryUser = userManager.getPrimaryUser().getUserHandle()
                         .equals(currentUserHandle);
 
                 // Any time the user changes, re-register the accounts.