Copy MobileNetworkSettings to settings app
This is a CL to copy most components from telephony to settings app with
following changes to pass the preupload check:
1. Add [CHAR LIMIT]/comments for strings that miss them
This CL cannot build and future CL will fix the broken part.
Bug: 114749736
Test: Build
Change-Id: I744d537610eeeb7f2fb801defdd0ce47ef6088b6
diff --git a/res/values/arrays.xml b/res/values/arrays.xml
index e57cbfa..6cc10fe 100644
--- a/res/values/arrays.xml
+++ b/res/values/arrays.xml
@@ -1133,4 +1133,186 @@
<item>4</item> <!-- AutofillManager.FLAG_ADD_CLIENT_VERBOSE -->
</string-array>
+ <string-array name="enabled_networks_choices" translatable="false">
+ <item>@string/network_lte</item>
+ <item>@string/network_3G</item>
+ <item>@string/network_2G</item>
+ </string-array>
+ <string-array name="enabled_networks_4g_choices" translatable="false">
+ <item>@string/network_4G</item>
+ <item>@string/network_3G</item>
+ <item>@string/network_2G</item>
+ </string-array>
+ <string-array name="enabled_networks_values" translatable="false">
+ <item>"9"</item>
+ <item>"0"</item>
+ <item>"1"</item>
+ </string-array>
+
+ <string-array name="cdma_system_select_choices">
+ <!-- System select dialog screen, setting option name -->
+ <item>Home only</item>
+ <!-- Remove the following option "Affiliated Networks" from the option list -->
+ <!-- <item>Affiliated Networks</item> -->
+ <!-- System select dialog screen, setting option name -->
+ <item>Automatic</item>
+ </string-array>
+ <string-array name="cdma_system_select_values" translatable="false">
+ <!-- Do not translate. -->
+ <item>"0"</item>
+ <!-- Remove the following value "1" which corresponds to "Affiliated Networks" above -->
+ <!-- <item>"1"</item> -->
+ <!-- Do not translate. -->
+ <item>"2"</item>
+ </string-array>
+
+ <!-- The preferred network modes in Mobile network settings -->
+ <string-array name="preferred_network_mode_choices">
+ <item>GSM/WCDMA preferred</item>
+ <item>GSM only</item>
+ <item>WCDMA only</item>
+ <item>GSM/WCDMA auto</item>
+ <item>CDMA/EvDo auto</item>
+ <item>CDMA w/o EvDo</item>
+ <item>EvDo only</item>
+ <item>CDMA/EvDo/GSM/WCDMA</item>
+ <item>CDMA + LTE/EvDo</item>
+ <item>GSM/WCDMA/LTE</item>
+ <item>Global</item>
+ <item>LTE</item>
+ <item>LTE / WCDMA</item>
+ <item>TDSCDMA only</item>
+ <item>TDSCDMA/WCDMA</item>
+ <item>LTE/TDSCDMA</item>
+ <item>TDSCDMA/GSM</item>
+ <item>LTE/TDSCDMA/GSM</item>
+ <item>TDSCDMA/GSM/WCDMA</item>
+ <item>LTE/TDSCDMA/WCDMA</item>
+ <item>LTE/TDSCDMA/GSM/WCDMA</item>
+ <item>TDSCDMA/CDMA/EVDO/GSM/WCDMA </item>
+ <item>LTE/TDSCDMA/CDMA/EVDO/GSM/WCDMA</item>
+ </string-array>
+ <!-- The preferred network modes RIL constants, in order of the modes above,
+ e.g. the choice "GSM/WCDMA preferred" has the corresponding value "0" -->
+ <string-array name="preferred_network_mode_values" translatable="false">
+ <item>"0"</item>
+ <item>"1"</item>
+ <item>"2"</item>
+ <item>"3"</item>
+ <item>"4"</item>
+ <item>"5"</item>
+ <item>"6"</item>
+ <item>"7"</item>
+ <item>"8"</item>
+ <item>"9"</item>
+ <item>"10"</item>
+ <item>"11"</item>
+ <item>"12"</item>
+ <item>"13"</item>
+ <item>"14"</item>
+ <item>"15"</item>
+ <item>"16"</item>
+ <item>"17"</item>
+ <item>"18"</item>
+ <item>"19"</item>
+ <item>"20"</item>
+ <item>"21"</item>
+ <item>"22"</item>
+ </string-array>
+
+ <!-- Choices for CDMA subscription-->
+ <string-array name="cdma_subscription_choices">
+ <item>RUIM/SIM</item>
+ <item>NV</item>
+ </string-array>
+ <!-- Values for CDMA subscription-->
+ <string-array name="cdma_subscription_values">
+ <item>"0"</item>
+ <item>"1"</item>
+ </string-array>
+
+ <string-array name="enabled_networks_except_gsm_choices" translatable="false">
+ <item>@string/network_lte</item>
+ <item>@string/network_3G</item>
+ </string-array>
+ <string-array name="enabled_networks_except_gsm_4g_choices" translatable="false">
+ <item>@string/network_4G</item>
+ <item>@string/network_3G</item>
+ </string-array>
+ <string-array name="enabled_networks_except_gsm_values" translatable="false">
+ <item>"9"</item>
+ <item>"0"</item>
+ </string-array>
+
+ <string-array name="enabled_networks_except_lte_choices" translatable="false">
+ <item>@string/network_3G</item>
+ <item>@string/network_2G</item>
+ </string-array>
+ <string-array name="enabled_networks_except_lte_values" translatable="false">
+ <item>"0"</item>
+ <item>"1"</item>
+ </string-array>
+
+ <string-array name="enabled_networks_except_gsm_lte_choices" translatable="false">
+ <item>@string/network_3G</item>
+ </string-array>
+ <string-array name="enabled_networks_except_gsm_lte_values" translatable="false">
+ <item>"0"</item>
+ </string-array>
+
+ <string-array name="enabled_networks_cdma_choices" translatable="false">
+ <item>@string/network_lte</item>
+ <item>@string/network_3G</item>
+ <item>@string/network_1x</item>
+ <item>@string/network_global</item>
+ </string-array>
+ <string-array name="enabled_networks_cdma_values" translatable="false">
+ <item>"8"</item>
+ <item>"4"</item>
+ <item>"5"</item>
+ <item>"10"</item>
+ </string-array>
+
+ <string-array name="enabled_networks_cdma_no_lte_choices" translatable="false">
+ <item>@string/network_3G</item>
+ <item>@string/network_1x</item>
+ </string-array>
+ <string-array name="enabled_networks_cdma_no_lte_values" translatable="false">
+ <item>"4"</item>
+ <item>"5"</item>
+ </string-array>
+
+ <string-array name="enabled_networks_cdma_only_lte_choices" translatable="false">
+ <item>@string/network_lte</item>
+ <item>@string/network_global</item>
+ </string-array>
+ <string-array name="enabled_networks_cdma_only_lte_values" translatable="false">
+ <item>"8"</item>
+ <item>"10"</item>
+ </string-array>
+
+ <string-array name="enabled_networks_tdscdma_choices" translatable="false">
+ <item>@string/network_lte</item>
+ <item>@string/network_3G</item>
+ <item>@string/network_2G</item>
+ </string-array>
+ <string-array name="enabled_networks_tdscdma_values" translatable="false">
+ <item>"22"</item>
+ <item>"18"</item>
+ <item>"1"</item>
+ </string-array>
+
+ <!--String arrays for World preferred netwrok modes -->
+ <string-array name="preferred_network_mode_choices_world_mode">
+ <item>Global</item>
+ <item>LTE / CDMA</item>
+ <item>LTE / GSM / UMTS</item>
+ </string-array>
+
+ <string-array name="preferred_network_mode_values_world_mode">
+ <item>"10"</item>
+ <item>"8"</item>
+ <item>"9"</item>
+ </string-array>
+
</resources>
diff --git a/res/values/config.xml b/res/values/config.xml
index b9a69f1..0129768 100755
--- a/res/values/config.xml
+++ b/res/values/config.xml
@@ -136,4 +136,8 @@
<!-- Whether or not TopLevelSettings should force rounded icon for injected tiles -->
<bool name="config_force_rounded_icon_TopLevelSettings">true</bool>
+
+ <!-- TODO(b/114749736): migrate override for config value -->
+ <!-- Show enabled lte option for lte device -->
+ <bool name="config_enabled_lte" translatable="false">false</bool>
</resources>
diff --git a/res/values/strings.xml b/res/values/strings.xml
index d78b7b0..0060202 100644
--- a/res/values/strings.xml
+++ b/res/values/strings.xml
@@ -10112,4 +10112,151 @@
<!-- Message informs the user that has no SIM card in personalized Settings [CHAR LIMIT=30] -->
<string name="no_sim_card">No SIM card</string>
+
+ <!-- Carrier variant of Enhaced 4G LTE Mode title. [CHAR LIMIT=50] -->
+ <string name="enhanced_4g_lte_mode_title_variant">Advanced Calling</string>
+ <!-- The following strings are summaries for preferred network modes in Mobile network settings,
+ and have a character limit of 100 -->
+ <!-- WCDMA preferred [CHAR LIMIT=NONE] -->
+ <string name="preferred_network_mode_wcdma_perf_summary">Preferred network mode: WCDMA preferred</string>
+ <!-- GSM only [CHAR LIMIT=NONE] -->
+ <string name="preferred_network_mode_gsm_only_summary">Preferred network mode: GSM only</string>
+ <!-- WCDMA only [CHAR LIMIT=NONE] -->
+ <string name="preferred_network_mode_wcdma_only_summary">Preferred network mode: WCDMA only</string>
+ <!-- GSM / WCDMA [CHAR LIMIT=NONE] -->
+ <string name="preferred_network_mode_gsm_wcdma_summary">Preferred network mode: GSM / WCDMA</string>
+ <!-- CDMA [CHAR LIMIT=NONE] -->
+ <string name="preferred_network_mode_cdma_summary">Preferred network mode: CDMA</string>
+ <!-- CDMA / EvDo [CHAR LIMIT=NONE] -->
+ <string name="preferred_network_mode_cdma_evdo_summary">Preferred network mode: CDMA / EvDo</string>
+ <!-- CDMA only [CHAR LIMIT=NONE] -->
+ <string name="preferred_network_mode_cdma_only_summary">Preferred network mode: CDMA only</string>
+ <!-- EvDo only [CHAR LIMIT=NONE] -->
+ <string name="preferred_network_mode_evdo_only_summary">Preferred network mode: EvDo only</string>
+ <!-- CDMA/EvDo/GSM/WCDMA [CHAR LIMIT=NONE] -->
+ <string name="preferred_network_mode_cdma_evdo_gsm_wcdma_summary">Preferred network mode: CDMA/EvDo/GSM/WCDMA</string>
+ <!-- LTE [CHAR LIMIT=NONE] -->
+ <string name="preferred_network_mode_lte_summary">Preferred network mode: LTE </string>
+ <!-- GSM/WCDMA/LTE [CHAR LIMIT=NONE] -->
+ <string name="preferred_network_mode_lte_gsm_wcdma_summary">Preferred network mode: GSM/WCDMA/LTE</string>
+ <!-- CDMA+LTE/EVDO [CHAR LIMIT=NONE] -->
+ <string name="preferred_network_mode_lte_cdma_evdo_summary">Preferred network mode: CDMA+LTE/EVDO</string>
+ <!-- Global [CHAR LIMIT=NONE] -->
+ <string name="preferred_network_mode_global_summary">Preferred network mode: Global</string>
+ <!-- LTE / WCDMA [CHAR LIMIT=NONE] -->
+ <string name="preferred_network_mode_lte_wcdma_summary">Preferred network mode: LTE / WCDMA</string>
+ <!-- LTE / GSM / UMTS [CHAR LIMIT=NONE] -->
+ <string name="preferred_network_mode_lte_gsm_umts_summary">Preferred network mode: LTE / GSM / UMTS</string>
+ <!-- LTE / CDMA [CHAR LIMIT=NONE] -->
+ <string name="preferred_network_mode_lte_cdma_summary">Preferred network mode: LTE / CDMA</string>
+ <!-- TDSCDMA [CHAR LIMIT=NONE] -->
+ <string name="preferred_network_mode_tdscdma_summary">Preferred network mode: TDSCDMA</string>
+ <!-- TDSCDMA / WCDMA [CHAR LIMIT=NONE] -->
+ <string name="preferred_network_mode_tdscdma_wcdma_summary">Preferred network mode: TDSCDMA / WCDMA</string>
+ <!-- LTE / TDSCDMA [CHAR LIMIT=NONE] -->
+ <string name="preferred_network_mode_lte_tdscdma_summary">Preferred network mode: LTE / TDSCDMA</string>
+ <!-- TDSCDMA / GSM [CHAR LIMIT=NONE] -->
+ <string name="preferred_network_mode_tdscdma_gsm_summary">Preferred network mode: TDSCDMA / GSM</string>
+ <!-- LTE/GSM/TDSCDMA [CHAR LIMIT=NONE] -->
+ <string name="preferred_network_mode_lte_tdscdma_gsm_summary">Preferred network mode: LTE/GSM/TDSCDMA</string>
+ <!-- TDSCDMA/GSM/WCDMA [CHAR LIMIT=NONE] -->
+ <string name="preferred_network_mode_tdscdma_gsm_wcdma_summary">Preferred network mode: TDSCDMA/GSM/WCDMA</string>
+ <!-- LTE/TDSCDMA/WCDMA [CHAR LIMIT=NONE] -->
+ <string name="preferred_network_mode_lte_tdscdma_wcdma_summary">Preferred network mode: LTE/TDSCDMA/WCDMA</string>
+ <!-- LTE/TDSCDMA/GSM/WCDMA [CHAR LIMIT=NONE] -->
+ <string name="preferred_network_mode_lte_tdscdma_gsm_wcdma_summary">Preferred network mode: LTE/TDSCDMA/GSM/WCDMA</string>
+ <!-- TDSCDMA/CDMA/EvDo/GSM/WCDMA [CHAR LIMIT=NONE] -->
+ <string name="preferred_network_mode_tdscdma_cdma_evdo_gsm_wcdma_summary">Preferred network mode: TDSCDMA/CDMA/EvDo/GSM/WCDMA</string>
+ <!-- LTE/TDSCDMA/CDMA/EvDo/GSM/WCDMA [CHAR LIMIT=NONE] -->
+ <string name="preferred_network_mode_lte_tdscdma_cdma_evdo_gsm_wcdma_summary">Preferred network mode: LTE/TDSCDMA/CDMA/EvDo/GSM/WCDMA</string>
+
+ <!-- Text for Network lte [CHAR LIMIT=NONE] -->
+ <string name="network_lte">LTE (recommended)</string>
+ <!-- Text for Network 4g [CHAR LIMIT=NONE] -->
+ <string name="network_4G">4G (recommended)</string>
+ <!-- Text for Network 3g [CHAR LIMIT=NONE] -->
+ <string name="network_3G" translatable="false">3G</string>
+ <!-- Text for Network 2g [CHAR LIMIT=NONE] -->
+ <string name="network_2G" translatable="false">2G</string>
+ <!-- Text for Network 1x [CHAR LIMIT=NONE] -->
+ <string name="network_1x" translatable="false">1x</string>
+ <!-- Text for Network global [CHAR LIMIT=NONE] -->
+ <string name="network_global">Global</string>
+
+ <!-- Configuration setting for world mode Format is <true;GID if any to be checked> [CHAR LIMIT=NONE] -->
+ <string translatable="false" name="config_world_mode"/>
+
+ <!-- Available networks screen, text when no networks connected [CHAR LIMIT=NONE] -->
+ <string name="network_disconnected">Disconnected</string>
+ <!-- Available networks screen, text when network connected [CHAR LIMIT=NONE] -->
+ <string name="network_connected">Connected</string>
+ <!-- Available networks screen, text when a network is connecting [CHAR LIMIT=NONE] -->
+ <string name="network_connecting">Connecting\u2026</string>
+ <!-- Available networks screen, text when a network cannot be connected [CHAR LIMIT=NONE] -->
+ <string name="network_could_not_connect">Couldn’t connect</string>
+
+ <!-- Available networks screen title/heading [CHAR LIMIT=NONE] -->
+ <string name="label_available">Available networks</string>
+ <!-- Mobile network settings screen, toast when searching for available networks [CHAR LIMIT=NONE] -->
+ <string name="load_networks_progress">Searching\u2026</string>
+ <!-- Available networks screen, text when no networks are found [CHAR LIMIT=NONE] -->
+ <string name="empty_networks_list">No networks found.</string>
+ <!-- Available networks screen, toast when an error is encountered when searching for networks [CHAR LIMIT=NONE] -->
+ <string name="network_query_error">Couldn\u2019t find networks. Try again.</string>
+ <!-- Available networks screen, toast when registering on a specific network [CHAR LIMIT=NONE] -->
+ <string name="register_on_network">Registering on <xliff:g id="network" example="Verizon">%s</xliff:g>\u2026</string>
+ <!-- Available networks screen, toast when SIM card isn't allowed on a network [CHAR LIMIT=NONE] -->
+ <string name="not_allowed">Your SIM card doesn\u2019t allow a connection to this network.</string>
+ <!-- Available networks screen, toast when unable to connect to a network temporarily [CHAR LIMIT=NONE] -->
+ <string name="connect_later">Can\u2019t connect to this network right now. Try again later.</string>
+ <!-- Available networks screen, toast when registered on a specific network [CHAR LIMIT=NONE] -->
+ <string name="registration_done">Registered on network.</string>
+
+ <!-- Available networks screen, name of switch button for whether to select network automatically [CHAR LIMIT=NONE] -->
+ <string name="select_automatically">Automatically select network</string>
+
+ <!-- Available networks screen, name of button when user wants to select network manually [CHAR LIMIT=NONE] -->
+ <string name="choose_network_title">Choose network</string>
+ <!-- A menu item in "Mobile network settings" that allows the user to update the phone
+ with mobile operator specific settings. [CHAR LIMIT=25] -->
+ <string name="carrier_settings_title">Carrier settings</string>
+ <!-- Preference title for launching an account manager page for prepaid LTE [CHAR LIMIT=30] -->
+ <string name="cdma_lte_data_service">Set up data service</string>
+ <!-- Mobile network settings screen, title of Mobile Data switch preference [CHAR LIMIT=NONE] -->
+ <string name="mobile_data_settings_title">Mobile data</string>
+ <!-- Mobile network settings screen, title of Mobile data switch preference [CHAR LIMIT=NONE] -->
+ <string name="mobile_data_settings_summary">Access data using mobile network</string>
+
+ <!-- Title for preferred network type [CHAR LIMIT=NONE] -->
+ <string name="preferred_network_mode_title">Preferred network type</string>
+ <!-- Summary for preferred network type [CHAR LIMIT=NONE] -->
+ <string name="preferred_network_mode_summary">Change the network operating mode</string>
+ <!-- Dialog title for preferred network type [CHAR LIMIT=NONE] -->
+ <string name="preferred_network_mode_dialogtitle">Preferred network type</string>
+ <!-- Mobile network settings screen, name of the option to manage carrier profiles on devices which support embedded carrier profiles [CHAR LIMIT=NONE] -->
+ <string name="carrier_settings_euicc">Carrier</string>
+
+ <!-- Mobile network settings screen, name for call settings category [CHAR LIMIT=NONE] -->
+ <string name="call_category">Calling</string>
+ <!-- Mobile network settings screen, title of Video calling setting [CHAR LIMIT=NONE] -->
+ <string name="video_calling_settings_title">Carrier video calling</string>
+
+ <!-- Mobile network settings screen, setting option name [CHAR LIMIT=NONE] -->
+ <string name="cdma_system_select_title">System select</string>
+ <!-- Mobile network settings screen, setting summary text [CHAR LIMIT=NONE] -->
+ <string name="cdma_system_select_summary">Change the CDMA roaming mode</string>
+ <!-- System select settings screen title [CHAR LIMIT=NONE] -->
+ <string name="cdma_system_select_dialogtitle">System select</string>
+
+ <!-- Mobile network settings screen, name for network operator category [CHAR LIMIT=NONE] -->
+ <string name="network_operator_category">Network</string>
+ <!-- Available networks screen, name of button when user wants to select network manually [CHAR LIMIT=NONE] -->
+ <string name="network_select_title">Network</string>
+
+ <!-- Title for CDMA subscription [CHAR LIMIT=50] -->
+ <string name="cdma_subscription_title">CDMA subscription</string>
+ <!-- Summary for CDMA subscription [CHAR LIMIT=NONE] -->
+ <string name="cdma_subscription_summary">Change between RUIM/SIM and NV</string>
+ <!-- Dialog title for CDMA subscription [CHAR LIMIT=30] -->
+ <string name="cdma_subscription_dialogtitle">subscription</string>
</resources>
diff --git a/res/xml/cdma_options.xml b/res/xml/cdma_options.xml
new file mode 100644
index 0000000..f6ef97a
--- /dev/null
+++ b/res/xml/cdma_options.xml
@@ -0,0 +1,54 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2008 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+
+<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android">
+
+ <com.android.phone.CdmaSystemSelectListPreference
+ android:key="cdma_system_select_key"
+ android:title="@string/cdma_system_select_title"
+ android:summary="@string/cdma_system_select_summary"
+ android:entries="@array/cdma_system_select_choices"
+ android:entryValues="@array/cdma_system_select_values"
+ android:dialogTitle="@string/cdma_system_select_dialogtitle" />
+
+ <com.android.phone.CdmaSubscriptionListPreference
+ android:key="cdma_subscription_key"
+ android:title="@string/cdma_subscription_title"
+ android:summary="@string/cdma_subscription_summary"
+ android:entries="@array/cdma_subscription_choices"
+ android:entryValues="@array/cdma_subscription_values"
+ android:dialogTitle="@string/cdma_subscription_dialogtitle" />
+
+ <!--We want separate APN setting from reset of settings because-->
+ <!--we want user to change it with caution.-->
+ <PreferenceCategory
+ android:key="category_cdma_apn_key">
+ <!-- The launching Intent will be defined thru code as we need to pass some Extra -->
+ <com.android.phone.RestrictedPreference
+ android:key="button_cdma_apn_key"
+ android:title="@string/apn_settings"
+ android:persistent="false"/>
+ </PreferenceCategory>
+
+ <Preference
+ android:key="carrier_settings_key"
+ android:title="@string/carrier_settings_title">
+ <intent android:action="android.intent.action.MAIN"
+ android:targetPackage="@string/carrier_settings"
+ android:targetClass="@string/carrier_settings_menu" />
+ </Preference>
+
+</PreferenceScreen>
diff --git a/res/xml/gsm_umts_options.xml b/res/xml/gsm_umts_options.xml
new file mode 100644
index 0000000..81b2deb
--- /dev/null
+++ b/res/xml/gsm_umts_options.xml
@@ -0,0 +1,60 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2008 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+
+<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android">
+
+ <com.android.phone.NetworkOperators
+ android:key="network_operators_category_key"
+ android:title="@string/network_operator_category"
+ android:persistent="false">
+
+ <SwitchPreference
+ android:key="button_auto_select_key"
+ android:title="@string/select_automatically"
+ android:persistent="false"/>
+
+ <com.android.phone.NetworkSelectListPreference
+ android:key="button_network_select_key"
+ android:title="@string/network_select_title"
+ android:persistent="false"/>
+
+ <Preference
+ android:key="button_choose_network_key"
+ android:title="@string/choose_network_title"
+ android:fragment="com.android.phone.NetworkSelectSetting" />
+ </com.android.phone.NetworkOperators>
+
+ <!--We want separate APN setting from reset of settings because-->
+ <!--we want user to change it with caution.-->
+ <PreferenceCategory
+ android:key="category_gsm_apn_key"
+ android:layout="@layout/preference_category_no_label">
+
+ <com.android.phone.RestrictedPreference
+ android:key="button_gsm_apn_key"
+ android:title="@string/apn_settings"
+ android:persistent="false" />
+ </PreferenceCategory>
+
+ <PreferenceScreen
+ android:key="carrier_settings_key"
+ android:title="@string/carrier_settings_title">
+ <intent android:action="android.intent.action.MAIN"
+ android:targetPackage="@string/carrier_settings"
+ android:targetClass="@string/carrier_settings_menu" />
+ </PreferenceScreen>
+
+</PreferenceScreen>
diff --git a/res/xml/network_setting_fragment.xml b/res/xml/network_setting_fragment.xml
new file mode 100644
index 0000000..d334861
--- /dev/null
+++ b/res/xml/network_setting_fragment.xml
@@ -0,0 +1,91 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2008 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android">
+
+ <PreferenceScreen
+ android:key="cdma_lte_data_service_key"
+ android:title="@string/cdma_lte_data_service">
+ </PreferenceScreen>
+
+ <com.android.phone.MobileDataPreference
+ android:key="mobile_data_enable"
+ android:title="@string/mobile_data_settings_title"
+ android:summary="@string/mobile_data_settings_summary"/>
+
+ <com.android.phone.RestrictedSwitchPreference
+ android:key="button_roaming_key"
+ android:title="@string/roaming"
+ android:persistent="false"
+ android:summaryOn="@string/roaming_enable"
+ android:summaryOff="@string/roaming_disable"/>
+
+ <com.android.phone.DataUsagePreference
+ android:key="data_usage_summary"
+ android:title="@string/data_usage_title" />
+
+ <com.android.phone.AdvancedOptionsPreference
+ android:key="advanced_options"/>
+
+ <SwitchPreference
+ android:key="enhanced_4g_lte"
+ android:title="@string/enhanced_4g_lte_mode_title"
+ android:persistent="false"
+ android:summary="@string/enhanced_4g_lte_mode_summary"/>
+
+ <ListPreference
+ android:key="preferred_network_mode_key"
+ android:title="@string/preferred_network_mode_title"
+ android:summary="@string/preferred_network_mode_summary"
+ android:entries="@array/preferred_network_mode_choices"
+ android:entryValues="@array/preferred_network_mode_values"
+ android:dialogTitle="@string/preferred_network_mode_dialogtitle" />
+
+ <ListPreference
+ android:key="enabled_networks_key"
+ android:title="@string/preferred_network_mode_title"
+ android:summary="@string/preferred_network_mode_summary"
+ android:entries="@array/enabled_networks_choices"
+ android:entryValues="@array/enabled_networks_values"
+ android:dialogTitle="@string/preferred_network_mode_dialogtitle" />
+
+ <Preference
+ android:key="carrier_settings_euicc_key"
+ android:title="@string/carrier_settings_euicc" />
+
+ <PreferenceCategory
+ android:key="calling"
+ android:title="@string/call_category">
+
+ <PreferenceScreen
+ android:key="wifi_calling_key"
+ android:title="@string/wifi_calling_settings_title">
+
+ <intent android:action="android.intent.action.MAIN"
+ android:targetPackage="com.android.settings"
+ android:targetClass="com.android.settings.Settings$WifiCallingSettingsActivity">
+ <extra android:name="show_drawer_menu" android:value="true" />
+ </intent>
+
+ </PreferenceScreen>
+
+ <SwitchPreference
+ android:key="video_calling_key"
+ android:title="@string/video_calling_settings_title"
+ android:persistent="true"/>
+
+ </PreferenceCategory>
+
+</PreferenceScreen>
diff --git a/src/com/android/settings/mobilenetwork/AdvancedOptionsPreference.java b/src/com/android/settings/mobilenetwork/AdvancedOptionsPreference.java
new file mode 100644
index 0000000..23e3cd4
--- /dev/null
+++ b/src/com/android/settings/mobilenetwork/AdvancedOptionsPreference.java
@@ -0,0 +1,42 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.settings.mobilenetwork;
+
+import android.content.Context;
+import android.preference.Preference;
+import android.util.AttributeSet;
+import android.view.View;
+import android.widget.TextView;
+
+/**
+ * Customized preference class representing the "Advanced" button that expands to fields that
+ * are hidden by default.
+ */
+public class AdvancedOptionsPreference extends Preference {
+ public AdvancedOptionsPreference(Context context, AttributeSet attrs) {
+ super(context, attrs);
+ }
+
+ @Override
+ protected void onBindView(View view) {
+ super.onBindView(view);
+
+ setIcon(R.drawable.ic_expand_more);
+ setTitle(R.string.advanced_options_title);
+ TextView summary = view.findViewById(android.R.id.summary);
+ summary.setMaxLines(1);
+ }
+}
diff --git a/src/com/android/settings/mobilenetwork/CdmaOptions.java b/src/com/android/settings/mobilenetwork/CdmaOptions.java
new file mode 100644
index 0000000..38c6ca3
--- /dev/null
+++ b/src/com/android/settings/mobilenetwork/CdmaOptions.java
@@ -0,0 +1,203 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.settings.mobilenetwork;
+
+import android.content.Intent;
+import android.os.PersistableBundle;
+import android.os.SystemProperties;
+import android.preference.Preference;
+import android.preference.PreferenceFragment;
+import android.preference.PreferenceScreen;
+import android.provider.Settings;
+import android.telephony.CarrierConfigManager;
+import android.telephony.TelephonyManager;
+import android.text.TextUtils;
+
+import com.android.internal.annotations.VisibleForTesting;
+import com.android.internal.logging.MetricsLogger;
+import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
+import com.android.internal.telephony.PhoneConstants;
+import com.android.phone.MobileNetworkSettings;
+import com.android.phone.RestrictedPreference;
+import com.android.settingslib.RestrictedLockUtilsInternal;
+
+/**
+ * List of Phone-specific settings screens.
+ */
+public class CdmaOptions {
+ private static final String LOG_TAG = "CdmaOptions";
+
+ private CarrierConfigManager mCarrierConfigManager;
+ private CdmaSystemSelectListPreference mButtonCdmaSystemSelect;
+ private CdmaSubscriptionListPreference mButtonCdmaSubscription;
+ private RestrictedPreference mButtonAPNExpand;
+ private Preference mCategoryAPNExpand;
+ private Preference mButtonCarrierSettings;
+
+ private static final String BUTTON_CDMA_SYSTEM_SELECT_KEY = "cdma_system_select_key";
+ private static final String BUTTON_CDMA_SUBSCRIPTION_KEY = "cdma_subscription_key";
+ private static final String BUTTON_CARRIER_SETTINGS_KEY = "carrier_settings_key";
+ private static final String BUTTON_APN_EXPAND_KEY = "button_cdma_apn_key";
+ private static final String CATEGORY_APN_EXPAND_KEY = "category_cdma_apn_key";
+
+ private PreferenceFragment mPrefFragment;
+ private PreferenceScreen mPrefScreen;
+ private int mSubId;
+
+ public CdmaOptions(PreferenceFragment prefFragment, PreferenceScreen prefScreen, int subId) {
+ mPrefFragment = prefFragment;
+ mPrefScreen = prefScreen;
+ mPrefFragment.addPreferencesFromResource(R.xml.cdma_options);
+ mCarrierConfigManager = new CarrierConfigManager(prefFragment.getContext());
+
+ // Initialize preferences.
+ mButtonCdmaSystemSelect = (CdmaSystemSelectListPreference) mPrefScreen
+ .findPreference(BUTTON_CDMA_SYSTEM_SELECT_KEY);
+ mButtonCdmaSubscription = (CdmaSubscriptionListPreference) mPrefScreen
+ .findPreference(BUTTON_CDMA_SUBSCRIPTION_KEY);
+ mButtonCarrierSettings = mPrefScreen.findPreference(BUTTON_CARRIER_SETTINGS_KEY);
+ mButtonAPNExpand = (RestrictedPreference) mPrefScreen.findPreference(BUTTON_APN_EXPAND_KEY);
+ mCategoryAPNExpand = mPrefScreen.findPreference(CATEGORY_APN_EXPAND_KEY);
+
+ updateSubscriptionId(subId);
+ }
+
+ protected void updateSubscriptionId(int subId) {
+ mSubId = subId;
+ int phoneType = TelephonyManager.from(mPrefFragment.getContext())
+ .createForSubscriptionId(mSubId).getPhoneType();
+
+ PersistableBundle carrierConfig = mCarrierConfigManager.getConfigForSubId(mSubId);
+ // Some CDMA carriers want the APN settings.
+ boolean addAPNExpand = shouldAddApnExpandPreference(phoneType, carrierConfig);
+ boolean addCdmaSubscription =
+ deviceSupportsNvAndRuim();
+ // Read platform settings for carrier settings
+ boolean addCarrierSettings =
+ carrierConfig.getBoolean(CarrierConfigManager.KEY_CARRIER_SETTINGS_ENABLE_BOOL);
+
+ mPrefScreen.addPreference(mButtonCdmaSystemSelect);
+ mButtonCdmaSystemSelect.setEnabled(true);
+
+ // Making no assumptions of whether they are added or removed at this point.
+ // Calling add or remove explicitly to make sure they are updated.
+
+ if (addAPNExpand) {
+ log("update: addAPNExpand");
+ mButtonAPNExpand.setDisabledByAdmin(
+ MobileNetworkSettings.isDpcApnEnforced(mButtonAPNExpand.getContext())
+ ? RestrictedLockUtilsInternal.getDeviceOwner(
+ mButtonAPNExpand.getContext())
+ : null);
+ mButtonAPNExpand.setOnPreferenceClickListener(
+ new Preference.OnPreferenceClickListener() {
+ @Override
+ public boolean onPreferenceClick(Preference preference) {
+ MetricsLogger.action(mButtonAPNExpand.getContext(),
+ MetricsEvent.ACTION_MOBILE_NETWORK_APN_SETTINGS);
+ // We need to build the Intent by hand as the Preference Framework
+ // does not allow to add an Intent with some extras into a Preference
+ // XML file
+ final Intent intent = new Intent(Settings.ACTION_APN_SETTINGS);
+ // This will setup the Home and Search affordance
+ intent.putExtra(":settings:show_fragment_as_subsetting", true);
+ intent.putExtra("sub_id", mSubId);
+ mPrefFragment.startActivity(intent);
+ return true;
+ }
+ });
+ mPrefScreen.addPreference(mCategoryAPNExpand);
+ } else {
+ mPrefScreen.removePreference(mCategoryAPNExpand);
+ }
+
+ if (addCdmaSubscription) {
+ log("Both NV and Ruim supported, ENABLE subscription type selection");
+ mPrefScreen.addPreference(mButtonCdmaSubscription);
+ mButtonCdmaSubscription.setEnabled(true);
+ } else {
+ log("Both NV and Ruim NOT supported, REMOVE subscription type selection");
+ mPrefScreen.removePreference(mButtonCdmaSubscription);
+ }
+
+ if (addCarrierSettings) {
+ mPrefScreen.addPreference(mButtonCarrierSettings);
+ } else {
+ mPrefScreen.removePreference(mButtonCarrierSettings);
+ }
+ }
+
+ /**
+ * Return whether we should add the APN expandable preference based on the phone type and
+ * carrier config
+ */
+ @VisibleForTesting
+ public static boolean shouldAddApnExpandPreference(int phoneType, PersistableBundle config) {
+ return phoneType == PhoneConstants.PHONE_TYPE_CDMA
+ && config.getBoolean(CarrierConfigManager.KEY_SHOW_APN_SETTING_CDMA_BOOL);
+ }
+
+ private boolean deviceSupportsNvAndRuim() {
+ // retrieve the list of subscription types supported by device.
+ String subscriptionsSupported = SystemProperties.get("ril.subscription.types");
+ boolean nvSupported = false;
+ boolean ruimSupported = false;
+
+ log("deviceSupportsnvAnRum: prop=" + subscriptionsSupported);
+ if (!TextUtils.isEmpty(subscriptionsSupported)) {
+ // Searches through the comma-separated list for a match for "NV"
+ // and "RUIM" to update nvSupported and ruimSupported.
+ for (String subscriptionType : subscriptionsSupported.split(",")) {
+ subscriptionType = subscriptionType.trim();
+ if (subscriptionType.equalsIgnoreCase("NV")) {
+ nvSupported = true;
+ }
+ if (subscriptionType.equalsIgnoreCase("RUIM")) {
+ ruimSupported = true;
+ }
+ }
+ }
+
+ log("deviceSupportsnvAnRum: nvSupported=" + nvSupported +
+ " ruimSupported=" + ruimSupported);
+ return (nvSupported && ruimSupported);
+ }
+
+ public boolean preferenceTreeClick(Preference preference) {
+ if (preference.getKey().equals(BUTTON_CDMA_SYSTEM_SELECT_KEY)) {
+ log("preferenceTreeClick: return BUTTON_CDMA_ROAMING_KEY true");
+ return true;
+ }
+ if (preference.getKey().equals(BUTTON_CDMA_SUBSCRIPTION_KEY)) {
+ log("preferenceTreeClick: return CDMA_SUBSCRIPTION_KEY true");
+ return true;
+ }
+ return false;
+ }
+
+ public void showDialog(Preference preference) {
+ if (preference.getKey().equals(BUTTON_CDMA_SYSTEM_SELECT_KEY)) {
+ mButtonCdmaSystemSelect.showDialog(null);
+ } else if (preference.getKey().equals(BUTTON_CDMA_SUBSCRIPTION_KEY)) {
+ mButtonCdmaSubscription.showDialog(null);
+ }
+ }
+
+ protected void log(String s) {
+ android.util.Log.d(LOG_TAG, s);
+ }
+}
diff --git a/src/com/android/settings/mobilenetwork/CdmaSubscriptionListPreference.java b/src/com/android/settings/mobilenetwork/CdmaSubscriptionListPreference.java
new file mode 100644
index 0000000..9752e99
--- /dev/null
+++ b/src/com/android/settings/mobilenetwork/CdmaSubscriptionListPreference.java
@@ -0,0 +1,119 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.settings.mobilenetwork;
+
+import android.content.Context;
+import android.os.Bundle;
+import android.preference.ListPreference;
+import android.provider.Settings;
+import android.telephony.TelephonyManager;
+import android.util.AttributeSet;
+import android.util.Log;
+
+import com.android.internal.telephony.Phone;
+import com.android.settingslib.utils.ThreadUtils;
+
+public class CdmaSubscriptionListPreference extends ListPreference {
+
+ private static final String LOG_TAG = "CdmaSubscriptionListPreference";
+
+ // Used for CDMA subscription mode
+ private static final int CDMA_SUBSCRIPTION_RUIM_SIM = 0;
+ private static final int CDMA_SUBSCRIPTION_NV = 1;
+
+ //preferredSubscriptionMode 0 - RUIM/SIM, preferred
+ // 1 - NV
+ static final int preferredSubscriptionMode = Phone.PREFERRED_CDMA_SUBSCRIPTION;
+
+ private TelephonyManager mTelephonyManager;
+
+ public CdmaSubscriptionListPreference(Context context, AttributeSet attrs) {
+ super(context, attrs);
+
+ mTelephonyManager = TelephonyManager.from(context);
+ setCurrentCdmaSubscriptionModeValue();
+ }
+
+ private void setCurrentCdmaSubscriptionModeValue() {
+ int cdmaSubscriptionMode = Settings.Global.getInt(getContext().getContentResolver(),
+ Settings.Global.CDMA_SUBSCRIPTION_MODE, preferredSubscriptionMode);
+ setValue(Integer.toString(cdmaSubscriptionMode));
+ }
+
+ public CdmaSubscriptionListPreference(Context context) {
+ this(context, null);
+ }
+
+ /**
+ * Sets the subscription id associated with this preference.
+ *
+ * @param subId the subscription id.
+ */
+ public void setSubscriptionId(int subId) {
+ mTelephonyManager = TelephonyManager.from(getContext()).createForSubscriptionId(subId);
+ }
+
+ @Override
+ protected void showDialog(Bundle state) {
+ setCurrentCdmaSubscriptionModeValue();
+
+ super.showDialog(state);
+ }
+
+ @Override
+ protected void onDialogClosed(boolean positiveResult) {
+ super.onDialogClosed(positiveResult);
+
+ if (!positiveResult) {
+ //The button was dismissed - no need to set new value
+ return;
+ }
+
+ int buttonCdmaSubscriptionMode = Integer.parseInt(getValue());
+ Log.d(LOG_TAG, "Setting new value " + buttonCdmaSubscriptionMode);
+ int statusCdmaSubscriptionMode;
+ switch(buttonCdmaSubscriptionMode) {
+ case CDMA_SUBSCRIPTION_NV:
+ statusCdmaSubscriptionMode = Phone.CDMA_SUBSCRIPTION_NV;
+ break;
+ case CDMA_SUBSCRIPTION_RUIM_SIM:
+ statusCdmaSubscriptionMode = Phone.CDMA_SUBSCRIPTION_RUIM_SIM;
+ break;
+ default:
+ statusCdmaSubscriptionMode = Phone.PREFERRED_CDMA_SUBSCRIPTION;
+ }
+
+ // Set the CDMA subscription mode, when mode has been successfully changed, update the
+ // mode to the global setting.
+ ThreadUtils.postOnBackgroundThread(() -> {
+ // The subscription mode selected by user.
+ int cdmaSubscriptionMode = Integer.parseInt(getValue());
+
+ boolean isSuccessed = mTelephonyManager.setCdmaSubscriptionMode(
+ statusCdmaSubscriptionMode);
+
+ // Update the global settings if successed.
+ if (isSuccessed) {
+ Settings.Global.putInt(getContext().getContentResolver(),
+ Settings.Global.CDMA_SUBSCRIPTION_MODE,
+ cdmaSubscriptionMode);
+ } else {
+ Log.e(LOG_TAG, "Setting Cdma subscription source failed");
+ }
+ });
+ }
+}
diff --git a/src/com/android/settings/mobilenetwork/CdmaSystemSelectListPreference.java b/src/com/android/settings/mobilenetwork/CdmaSystemSelectListPreference.java
new file mode 100644
index 0000000..ab62f88
--- /dev/null
+++ b/src/com/android/settings/mobilenetwork/CdmaSystemSelectListPreference.java
@@ -0,0 +1,187 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.settings.mobilenetwork;
+
+import android.content.Context;
+import android.os.Bundle;
+import android.os.Handler;
+import android.os.Message;
+import android.preference.ListPreference;
+import android.provider.Settings;
+import android.telephony.TelephonyManager;
+import android.util.AttributeSet;
+import android.util.Log;
+
+import com.android.settingslib.utils.ThreadUtils;
+
+public class CdmaSystemSelectListPreference extends ListPreference {
+
+ private static final String LOG_TAG = "CdmaRoamingListPreference";
+ private static final boolean DBG = false;
+
+ private TelephonyManager mTelephonyManager;
+ private MyHandler mHandler = new MyHandler();
+
+ public CdmaSystemSelectListPreference(Context context, AttributeSet attrs) {
+ super(context, attrs);
+
+ mHandler = new MyHandler();
+ mTelephonyManager = TelephonyManager.from(context);
+ }
+
+ public CdmaSystemSelectListPreference(Context context) {
+ this(context, null);
+ }
+
+ /**
+ * Sets the subscription id associated with this preference.
+ *
+ * @param subId the subscription id.
+ */
+ public void setSubscriptionId(int subId) {
+ mTelephonyManager = TelephonyManager.from(getContext()).createForSubscriptionId(subId);
+ queryCdmaRoamingMode();
+ }
+
+ @Override
+ protected void showDialog(Bundle state) {
+ if (!mTelephonyManager.getEmergencyCallbackMode()) {
+ super.showDialog(state);
+ }
+ }
+
+ @Override
+ protected void onDialogClosed(boolean positiveResult) {
+ super.onDialogClosed(positiveResult);
+
+ if (positiveResult && (getValue() != null)) {
+ int buttonCdmaRoamingMode = Integer.parseInt(getValue());
+ int settingsCdmaRoamingMode = Settings.Global.getInt(
+ getContext().getContentResolver(),
+ Settings.Global.CDMA_ROAMING_MODE,
+ TelephonyManager.CDMA_ROAMING_MODE_HOME);
+ if (buttonCdmaRoamingMode != settingsCdmaRoamingMode) {
+ int cdmaRoamingMode = TelephonyManager.CDMA_ROAMING_MODE_ANY;
+ if (buttonCdmaRoamingMode != TelephonyManager.CDMA_ROAMING_MODE_ANY) {
+ cdmaRoamingMode = TelephonyManager.CDMA_ROAMING_MODE_HOME;
+ }
+ //Set the Settings.Secure network mode
+ Settings.Global.putInt(
+ getContext().getContentResolver(),
+ Settings.Global.CDMA_ROAMING_MODE,
+ buttonCdmaRoamingMode);
+ //Set the roaming preference mode
+ setCdmaRoamingMode(cdmaRoamingMode);
+ }
+ } else {
+ Log.d(LOG_TAG, String.format("onDialogClosed: positiveResult=%b value=%s -- do nothing",
+ positiveResult, getValue()));
+ }
+ }
+
+ private class MyHandler extends Handler {
+
+ static final int MESSAGE_GET_ROAMING_PREFERENCE = 0;
+ static final int MESSAGE_SET_ROAMING_PREFERENCE = 1;
+
+ @Override
+ public void handleMessage(Message msg) {
+ switch (msg.what) {
+ case MESSAGE_GET_ROAMING_PREFERENCE:
+ handleQueryCdmaRoamingPreference(msg);
+ break;
+
+ case MESSAGE_SET_ROAMING_PREFERENCE:
+ handleSetCdmaRoamingPreference(msg);
+ break;
+ }
+ }
+
+ private void handleQueryCdmaRoamingPreference(Message msg) {
+ int cdmaRoamingMode = msg.arg1;
+
+ if (cdmaRoamingMode != TelephonyManager.CDMA_ROAMING_MODE_RADIO_DEFAULT) {
+ int settingsRoamingMode = Settings.Global.getInt(
+ getContext().getContentResolver(),
+ Settings.Global.CDMA_ROAMING_MODE,
+ TelephonyManager.CDMA_ROAMING_MODE_HOME);
+
+ //check that statusCdmaRoamingMode is from an accepted value
+ if (cdmaRoamingMode == TelephonyManager.CDMA_ROAMING_MODE_HOME
+ || cdmaRoamingMode == TelephonyManager.CDMA_ROAMING_MODE_ANY) {
+ //check changes in statusCdmaRoamingMode and updates settingsRoamingMode
+ if (cdmaRoamingMode != settingsRoamingMode) {
+ settingsRoamingMode = cdmaRoamingMode;
+ //changes the Settings.Secure accordingly to statusCdmaRoamingMode
+ Settings.Global.putInt(
+ getContext().getContentResolver(),
+ Settings.Global.CDMA_ROAMING_MODE,
+ settingsRoamingMode);
+ }
+ //changes the mButtonPreferredNetworkMode accordingly to modemNetworkMode
+ setValue(Integer.toString(cdmaRoamingMode));
+ }
+ else {
+ if(DBG) Log.i(LOG_TAG, "reset cdma roaming mode to default" );
+ resetCdmaRoamingModeToDefault();
+ }
+ }
+ }
+
+ private void handleSetCdmaRoamingPreference(Message msg) {
+ boolean isSuccessed = (boolean) msg.obj;
+
+ if (isSuccessed && (getValue() != null)) {
+ int cdmaRoamingMode = Integer.parseInt(getValue());
+ Settings.Global.putInt(
+ getContext().getContentResolver(),
+ Settings.Global.CDMA_ROAMING_MODE,
+ cdmaRoamingMode );
+ } else {
+ queryCdmaRoamingMode();
+ }
+ }
+
+ private void resetCdmaRoamingModeToDefault() {
+ //set the mButtonCdmaRoam
+ setValue(Integer.toString(TelephonyManager.CDMA_ROAMING_MODE_ANY));
+ //set the Settings.System
+ Settings.Global.putInt(
+ getContext().getContentResolver(),
+ Settings.Global.CDMA_ROAMING_MODE,
+ TelephonyManager.CDMA_ROAMING_MODE_ANY);
+ //Set the Status
+ setCdmaRoamingMode(TelephonyManager.CDMA_ROAMING_MODE_ANY);
+ }
+ }
+
+ private void queryCdmaRoamingMode() {
+ ThreadUtils.postOnBackgroundThread(() -> {
+ Message msg = mHandler.obtainMessage(MyHandler.MESSAGE_GET_ROAMING_PREFERENCE);
+ msg.arg1 = mTelephonyManager.getCdmaRoamingMode();
+ msg.sendToTarget();
+ });
+ }
+
+ private void setCdmaRoamingMode(int mode) {
+ ThreadUtils.postOnBackgroundThread(() -> {
+ Message msg = mHandler.obtainMessage(MyHandler.MESSAGE_SET_ROAMING_PREFERENCE);
+ msg.obj = mTelephonyManager.setCdmaRoamingMode(mode);
+ msg.sendToTarget();
+ });
+ }
+}
diff --git a/src/com/android/settings/mobilenetwork/DataUsagePreference.java b/src/com/android/settings/mobilenetwork/DataUsagePreference.java
new file mode 100644
index 0000000..594f83b
--- /dev/null
+++ b/src/com/android/settings/mobilenetwork/DataUsagePreference.java
@@ -0,0 +1,80 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.settings.mobilenetwork;
+
+import android.app.Activity;
+import android.content.Context;
+import android.content.Intent;
+import android.net.NetworkTemplate;
+import android.preference.Preference;
+import android.provider.Settings;
+import android.telephony.TelephonyManager;
+import android.text.format.Formatter;
+import android.util.AttributeSet;
+
+import com.android.settingslib.net.DataUsageController;
+
+/**
+ * The preference that shows mobile data usage summary and
+ * leads to mobile data usage list page.
+ */
+public class DataUsagePreference extends Preference {
+
+ private NetworkTemplate mTemplate;
+ private int mSubId;
+
+ public DataUsagePreference(Context context, AttributeSet attrs) {
+ super(context, attrs);
+ }
+
+ /**
+ * After creating this preference, this functions needs to be called to
+ * initialize which subID it connects to.
+ */
+ public void initialize(int subId) {
+ Activity activity = (Activity) getContext();
+
+ mSubId = subId;
+ mTemplate = getNetworkTemplate(activity, subId);
+
+ DataUsageController controller = new DataUsageController(activity);
+
+ DataUsageController.DataUsageInfo usageInfo = controller.getDataUsageInfo(mTemplate);
+ setSummary(activity.getString(R.string.data_usage_template,
+ Formatter.formatFileSize(activity, usageInfo.usageLevel), usageInfo.period));
+ setIntent(getIntent());
+ }
+
+ @Override
+ public Intent getIntent() {
+ Intent intent = new Intent(Settings.ACTION_MOBILE_DATA_USAGE);
+
+ intent.putExtra(Settings.EXTRA_NETWORK_TEMPLATE, mTemplate);
+ intent.putExtra(Settings.EXTRA_SUB_ID, mSubId);
+
+ return intent;
+ }
+
+ private NetworkTemplate getNetworkTemplate(Activity activity, int subId) {
+ TelephonyManager tm = (TelephonyManager) activity
+ .getSystemService(Context.TELEPHONY_SERVICE);
+ NetworkTemplate mobileAll = NetworkTemplate.buildTemplateMobileAll(
+ tm.getSubscriberId(subId));
+ return NetworkTemplate.normalize(mobileAll,
+ tm.getMergedSubscriberIds());
+ }
+}
diff --git a/src/com/android/settings/mobilenetwork/GsmUmtsOptions.java b/src/com/android/settings/mobilenetwork/GsmUmtsOptions.java
new file mode 100644
index 0000000..8400ec3
--- /dev/null
+++ b/src/com/android/settings/mobilenetwork/GsmUmtsOptions.java
@@ -0,0 +1,179 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.settings.mobilenetwork;
+
+import android.content.Context;
+import android.content.Intent;
+import android.os.PersistableBundle;
+import android.preference.Preference;
+import android.preference.PreferenceFragment;
+import android.preference.PreferenceScreen;
+import android.provider.Settings;
+import android.telephony.CarrierConfigManager;
+import android.telephony.TelephonyManager;
+
+import com.android.internal.logging.MetricsLogger;
+import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
+import com.android.internal.telephony.Phone;
+import com.android.internal.telephony.PhoneConstants;
+import com.android.phone.INetworkQueryService;
+import com.android.phone.MobileNetworkSettings;
+import com.android.phone.PhoneGlobals;
+import com.android.phone.RestrictedPreference;
+import com.android.settingslib.RestrictedLockUtilsInternal;
+
+/**
+ * List of Network-specific settings screens.
+ */
+public class GsmUmtsOptions {
+ private static final String LOG_TAG = "GsmUmtsOptions";
+
+ private CarrierConfigManager mCarrierConfigManager;
+ private RestrictedPreference mButtonAPNExpand;
+ private Preference mCategoryAPNExpand;
+ Preference mCarrierSettingPref;
+
+ private NetworkOperators mNetworkOperator;
+
+ private static final String BUTTON_APN_EXPAND_KEY = "button_gsm_apn_key";
+ private static final String CATEGORY_APN_EXPAND_KEY = "category_gsm_apn_key";
+ private static final String BUTTON_CARRIER_SETTINGS_KEY = "carrier_settings_key";
+
+ public static final String EXTRA_SUB_ID = "sub_id";
+ private PreferenceFragment mPrefFragment;
+ private PreferenceScreen mPrefScreen;
+
+ public GsmUmtsOptions(PreferenceFragment prefFragment, PreferenceScreen prefScreen,
+ final int subId, INetworkQueryService queryService) {
+ final Context context = prefFragment.getContext();
+ mPrefFragment = prefFragment;
+ mPrefScreen = prefScreen;
+ mCarrierConfigManager = new CarrierConfigManager(context);
+ mPrefFragment.addPreferencesFromResource(R.xml.gsm_umts_options);
+ mButtonAPNExpand = (RestrictedPreference) mPrefScreen.findPreference(BUTTON_APN_EXPAND_KEY);
+ mCategoryAPNExpand = mPrefScreen.findPreference(CATEGORY_APN_EXPAND_KEY);
+ mNetworkOperator = (NetworkOperators) mPrefScreen
+ .findPreference(NetworkOperators.CATEGORY_NETWORK_OPERATORS_KEY);
+ mCarrierSettingPref = mPrefScreen.findPreference(BUTTON_CARRIER_SETTINGS_KEY);
+
+ mNetworkOperator.initialize();
+
+ update(subId, queryService);
+ }
+
+ // Unlike mPrefFragment or mPrefScreen, subId or queryService may change during lifecycle of
+ // GsmUmtsOptions. When that happens, we update GsmUmtsOptions with new parameters.
+ protected void update(final int subId, INetworkQueryService queryService) {
+ boolean addAPNExpand = true;
+ boolean addNetworkOperatorsCategory = true;
+ boolean addCarrierSettings = true;
+ final TelephonyManager telephonyManager = TelephonyManager.from(mPrefFragment.getContext())
+ .createForSubscriptionId(subId);
+ Phone phone = PhoneGlobals.getPhone(subId);
+ if (phone == null) return;
+ if (telephonyManager.getPhoneType() != PhoneConstants.PHONE_TYPE_GSM) {
+ log("Not a GSM phone");
+ addAPNExpand = false;
+ mNetworkOperator.setEnabled(false);
+ } else {
+ log("Not a CDMA phone");
+ PersistableBundle carrierConfig = mCarrierConfigManager.getConfigForSubId(subId);
+
+ // Determine which options to display. For GSM these are defaulted to true in
+ // CarrierConfigManager, but they maybe overriden by DefaultCarrierConfigService or a
+ // carrier app.
+ // Note: these settings used to be controlled with overlays in
+ // Telephony/res/values/config.xml
+ if (!carrierConfig.getBoolean(CarrierConfigManager.KEY_APN_EXPAND_BOOL)
+ && mCategoryAPNExpand != null) {
+ addAPNExpand = false;
+ }
+ if (!carrierConfig.getBoolean(
+ CarrierConfigManager.KEY_OPERATOR_SELECTION_EXPAND_BOOL)) {
+ addNetworkOperatorsCategory = false;
+ }
+
+ if (carrierConfig.getBoolean(CarrierConfigManager.KEY_CSP_ENABLED_BOOL)) {
+ if (phone.isCspPlmnEnabled()) {
+ log("[CSP] Enabling Operator Selection menu.");
+ mNetworkOperator.setEnabled(true);
+ } else {
+ log("[CSP] Disabling Operator Selection menu.");
+ addNetworkOperatorsCategory = false;
+ }
+ }
+
+ // Read platform settings for carrier settings
+ addCarrierSettings = carrierConfig.getBoolean(
+ CarrierConfigManager.KEY_CARRIER_SETTINGS_ENABLE_BOOL);
+ }
+
+ // Making no assumptions of whether they are added or removed at this point.
+ // Calling add or remove explicitly to make sure they are updated.
+
+ if (addAPNExpand) {
+ log("update: addAPNExpand");
+ mButtonAPNExpand.setDisabledByAdmin(
+ MobileNetworkSettings.isDpcApnEnforced(mButtonAPNExpand.getContext())
+ ? RestrictedLockUtilsInternal.getDeviceOwner(
+ mButtonAPNExpand.getContext())
+ : null);
+ mButtonAPNExpand.setOnPreferenceClickListener(
+ new Preference.OnPreferenceClickListener() {
+ @Override
+ public boolean onPreferenceClick(Preference preference) {
+ MetricsLogger.action(mButtonAPNExpand.getContext(),
+ MetricsEvent.ACTION_MOBILE_NETWORK_APN_SETTINGS);
+ // We need to build the Intent by hand as the Preference Framework
+ // does not allow to add an Intent with some extras into a Preference
+ // XML file
+ final Intent intent = new Intent(Settings.ACTION_APN_SETTINGS);
+ // This will setup the Home and Search affordance
+ intent.putExtra(":settings:show_fragment_as_subsetting", true);
+ intent.putExtra(EXTRA_SUB_ID, subId);
+ mPrefFragment.startActivity(intent);
+ return true;
+ }
+ });
+ mPrefScreen.addPreference(mCategoryAPNExpand);
+ } else {
+ mPrefScreen.removePreference(mCategoryAPNExpand);
+ }
+
+ if (addNetworkOperatorsCategory) {
+ mPrefScreen.addPreference(mNetworkOperator);
+ mNetworkOperator.update(subId, queryService);
+ } else {
+ mPrefScreen.removePreference(mNetworkOperator);
+ }
+
+ if (addCarrierSettings) {
+ mPrefScreen.addPreference(mCarrierSettingPref);
+ } else {
+ mPrefScreen.removePreference(mCarrierSettingPref);
+ }
+
+ }
+
+ protected boolean preferenceTreeClick(Preference preference) {
+ return mNetworkOperator.preferenceTreeClick(preference);
+ }
+
+ protected void log(String s) {
+ android.util.Log.d(LOG_TAG, s);
+ }
+}
diff --git a/src/com/android/settings/mobilenetwork/MobileDataPreference.java b/src/com/android/settings/mobilenetwork/MobileDataPreference.java
new file mode 100644
index 0000000..39f4d2c
--- /dev/null
+++ b/src/com/android/settings/mobilenetwork/MobileDataPreference.java
@@ -0,0 +1,320 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.settings.mobilenetwork;
+
+import android.app.AlertDialog;
+import android.content.Context;
+import android.content.DialogInterface;
+import android.database.ContentObserver;
+import android.net.Uri;
+import android.os.Handler;
+import android.os.Looper;
+import android.os.Parcel;
+import android.os.Parcelable;
+import android.preference.DialogPreference;
+import android.preference.PreferenceScreen;
+import android.provider.Settings.Global;
+import android.telephony.SubscriptionInfo;
+import android.telephony.SubscriptionManager;
+import android.telephony.TelephonyManager;
+import android.util.AttributeSet;
+import android.util.Log;
+import android.view.View;
+import android.widget.Checkable;
+
+import com.android.internal.logging.MetricsLogger;
+import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
+
+import java.util.List;
+
+/**
+ * Customized Preference to enable / disable mobile data.
+ * Basically copy of with com.android.settings.CellDataPreference.
+ */
+public class MobileDataPreference extends DialogPreference {
+
+ private static final boolean DBG = false;
+ private static final String TAG = "MobileDataPreference";
+
+ public int mSubId = SubscriptionManager.INVALID_SUBSCRIPTION_ID;
+ public boolean mChecked;
+ // Whether to show the dialog to ask switching default data subscription.
+ // Should be true only when a multi-sim phone only supports data connection on a single phone,
+ // and user is enabling data on the non-default phone.
+ public boolean mMultiSimDialog;
+ private TelephonyManager mTelephonyManager;
+ private SubscriptionManager mSubscriptionManager;
+
+ public MobileDataPreference(Context context, AttributeSet attrs) {
+ super(context, attrs, com.android.internal.R.attr.switchPreferenceStyle);
+ }
+
+ // Must be called to avoid binder leakage.
+ void dispose() {
+ mListener.setListener(false, mSubId, getContext());
+ }
+
+ @Override
+ protected void onRestoreInstanceState(Parcelable s) {
+ CellDataState state = (CellDataState) s;
+ super.onRestoreInstanceState(state.getSuperState());
+ mTelephonyManager = TelephonyManager.from(getContext());
+ mChecked = state.mChecked;
+ mMultiSimDialog = state.mMultiSimDialog;
+ if (mSubId == SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
+ mSubId = state.mSubId;
+ setKey(getKey() + mSubId);
+ }
+ notifyChanged();
+ }
+
+ @Override
+ protected Parcelable onSaveInstanceState() {
+ CellDataState state = new CellDataState(super.onSaveInstanceState());
+ state.mChecked = mChecked;
+ state.mMultiSimDialog = mMultiSimDialog;
+ state.mSubId = mSubId;
+ return state;
+ }
+
+ @Override
+ protected void onAttachedToActivity() {
+ super.onAttachedToActivity();
+ mListener.setListener(true, mSubId, getContext());
+ }
+
+ @Override
+ protected void onPrepareForRemoval() {
+ mListener.setListener(false, mSubId, getContext());
+ super.onPrepareForRemoval();
+ }
+
+ /**
+ * Initialize this preference with subId.
+ */
+ public void initialize(int subId) {
+ if (subId == SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
+ throw new IllegalArgumentException("MobileDataPreference needs a SubscriptionInfo");
+ }
+ mSubscriptionManager = SubscriptionManager.from(getContext());
+ mTelephonyManager = TelephonyManager.from(getContext());
+ if (mSubId != subId) {
+ mSubId = subId;
+ setKey(getKey() + subId);
+ }
+ updateChecked();
+ }
+
+ private void updateChecked() {
+ setChecked(mTelephonyManager.getDataEnabled(mSubId));
+ }
+
+ @Override
+ public void performClick(PreferenceScreen preferenceScreen) {
+ if (!isEnabled() || !SubscriptionManager.isValidSubscriptionId(mSubId)) {
+ return;
+ }
+ final SubscriptionInfo currentSir = mSubscriptionManager.getActiveSubscriptionInfo(
+ mSubId);
+ final SubscriptionInfo nextSir = mSubscriptionManager.getDefaultDataSubscriptionInfo();
+ final boolean isMultiSim = (mTelephonyManager.getSimCount() > 1);
+ final boolean isMultipleDataOnCapable =
+ (mTelephonyManager.getNumberOfModemsWithSimultaneousDataConnections() > 1);
+ final boolean isDefaultDataSubscription = (nextSir != null && currentSir != null
+ && currentSir.getSubscriptionId() == nextSir.getSubscriptionId());
+ if (mChecked) {
+ if (!isMultiSim) {
+ // disabling data; show confirmation dialog which eventually
+ // calls setMobileDataEnabled() once user confirms.
+ mMultiSimDialog = false;
+ super.performClick(preferenceScreen);
+ } else {
+ // Don't show any dialog.
+ setMobileDataEnabled(false /* enabled */, false /* disableOtherSubscriptions */);
+ }
+ } else {
+ if (isMultiSim && !isMultipleDataOnCapable && !isDefaultDataSubscription) {
+ // enabling data and setting to default; show confirmation dialog which eventually
+ // calls setMobileDataEnabled() once user confirms.
+ mMultiSimDialog = true;
+ super.performClick(preferenceScreen);
+ } else {
+ // Don't show any dialog.
+ setMobileDataEnabled(true /* enabled */, false /* disableOtherSubscriptions */);
+ }
+ }
+ }
+
+ private void setMobileDataEnabled(boolean enabled, boolean disableOtherSubscriptions) {
+ if (DBG) Log.d(TAG, "setMobileDataEnabled(" + enabled + "," + mSubId + ")");
+
+ MetricsLogger.action(getContext(), MetricsEvent.ACTION_MOBILE_NETWORK_MOBILE_DATA_TOGGLE,
+ enabled);
+
+ mTelephonyManager.setDataEnabled(mSubId, enabled);
+
+ if (disableOtherSubscriptions) {
+ disableDataForOtherSubscriptions(mSubId);
+ }
+
+ setChecked(enabled);
+ }
+
+ private void setChecked(boolean checked) {
+ if (mChecked == checked) return;
+ mChecked = checked;
+ notifyChanged();
+ }
+
+ @Override
+ protected void onBindView(View view) {
+ super.onBindView(view);
+ View checkableView = view.findViewById(com.android.internal.R.id.switch_widget);
+ checkableView.setClickable(false);
+ ((Checkable) checkableView).setChecked(mChecked);
+ }
+
+ @Override
+ protected void onPrepareDialogBuilder(AlertDialog.Builder builder) {
+ if (mMultiSimDialog) {
+ showMultiSimDialog(builder);
+ } else {
+ showDisableDialog(builder);
+ }
+ }
+
+ private void showDisableDialog(AlertDialog.Builder builder) {
+ builder.setTitle(null)
+ .setMessage(R.string.data_usage_disable_mobile)
+ .setPositiveButton(android.R.string.ok, this)
+ .setNegativeButton(android.R.string.cancel, null);
+ }
+
+ private void showMultiSimDialog(AlertDialog.Builder builder) {
+ final SubscriptionInfo currentSir = mSubscriptionManager.getActiveSubscriptionInfo(mSubId);
+ final SubscriptionInfo nextSir = mSubscriptionManager.getDefaultDataSubscriptionInfo();
+
+ final String previousName = (nextSir == null)
+ ? getContext().getResources().getString(R.string.sim_selection_required_pref)
+ : nextSir.getDisplayName().toString();
+
+ builder.setTitle(R.string.sim_change_data_title);
+ builder.setMessage(getContext().getString(R.string.sim_change_data_message,
+ String.valueOf(currentSir != null ? currentSir.getDisplayName() : null),
+ previousName));
+
+ builder.setPositiveButton(R.string.ok, this);
+ builder.setNegativeButton(R.string.cancel, null);
+ }
+
+ private void disableDataForOtherSubscriptions(int subId) {
+ List<SubscriptionInfo> subInfoList = mSubscriptionManager.getActiveSubscriptionInfoList();
+ if (subInfoList != null) {
+ for (SubscriptionInfo subInfo : subInfoList) {
+ if (subInfo.getSubscriptionId() != subId) {
+ mTelephonyManager.setDataEnabled(subInfo.getSubscriptionId(), false);
+ }
+ }
+ }
+ }
+
+ @Override
+ public void onClick(DialogInterface dialog, int which) {
+ if (which != DialogInterface.BUTTON_POSITIVE) {
+ return;
+ }
+ if (mMultiSimDialog) {
+ mSubscriptionManager.setDefaultDataSubId(mSubId);
+ setMobileDataEnabled(true /* enabled */, true /* disableOtherSubscriptions */);
+ } else {
+ // TODO: extend to modify policy enabled flag.
+ setMobileDataEnabled(false /* enabled */, false /* disableOtherSubscriptions */);
+ }
+ }
+
+ private final DataStateListener mListener = new DataStateListener() {
+ @Override
+ public void onChange(boolean selfChange) {
+ updateChecked();
+ }
+ };
+
+ /**
+ * Listener that listens mobile data state change.
+ */
+ public abstract static class DataStateListener extends ContentObserver {
+ public DataStateListener() {
+ super(new Handler(Looper.getMainLooper()));
+ }
+
+ /**
+ * Set / Unset data state listening, specifying subId.
+ */
+ public void setListener(boolean listening, int subId, Context context) {
+ if (listening) {
+ Uri uri = Global.getUriFor(Global.MOBILE_DATA);
+ if (TelephonyManager.getDefault().getSimCount() != 1) {
+ uri = Global.getUriFor(Global.MOBILE_DATA + subId);
+ }
+ context.getContentResolver().registerContentObserver(uri, false, this);
+ } else {
+ context.getContentResolver().unregisterContentObserver(this);
+ }
+ }
+ }
+
+ /**
+ * Class that represents state of mobile data state.
+ * Used by onSaveInstanceState and onRestoreInstanceState.
+ */
+ public static class CellDataState extends BaseSavedState {
+ public int mSubId;
+ public boolean mChecked;
+ public boolean mMultiSimDialog;
+
+ public CellDataState(Parcelable base) {
+ super(base);
+ }
+
+ public CellDataState(Parcel source) {
+ super(source);
+ mChecked = source.readByte() != 0;
+ mMultiSimDialog = source.readByte() != 0;
+ mSubId = source.readInt();
+ }
+
+ @Override
+ public void writeToParcel(Parcel dest, int flags) {
+ super.writeToParcel(dest, flags);
+ dest.writeByte((byte) (mChecked ? 1 : 0));
+ dest.writeByte((byte) (mMultiSimDialog ? 1 : 0));
+ dest.writeInt(mSubId);
+ }
+
+ public static final Creator<CellDataState> CREATOR = new Creator<CellDataState>() {
+ @Override
+ public CellDataState createFromParcel(Parcel source) {
+ return new CellDataState(source);
+ }
+
+ @Override
+ public CellDataState[] newArray(int size) {
+ return new CellDataState[size];
+ }
+ };
+ }
+}
diff --git a/src/com/android/settings/mobilenetwork/MobileNetworkFragment.java b/src/com/android/settings/mobilenetwork/MobileNetworkFragment.java
new file mode 100644
index 0000000..03e7d79
--- /dev/null
+++ b/src/com/android/settings/mobilenetwork/MobileNetworkFragment.java
@@ -0,0 +1,2003 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.settings.mobilenetwork;
+
+import static android.provider.Telephony.Carriers.ENFORCE_MANAGED_URI;
+
+import android.app.ActionBar;
+import android.app.Activity;
+import android.app.DialogFragment;
+import android.content.BroadcastReceiver;
+import android.content.Context;
+import android.content.Intent;
+import android.content.IntentFilter;
+import android.content.pm.PackageManager;
+import android.content.pm.ResolveInfo;
+import android.database.ContentObserver;
+import android.net.Uri;
+import android.os.AsyncTask;
+import android.os.Bundle;
+import android.os.Handler;
+import android.os.Message;
+import android.os.PersistableBundle;
+import android.os.UserHandle;
+import android.os.UserManager;
+import android.preference.ListPreference;
+import android.preference.Preference;
+import android.preference.PreferenceCategory;
+import android.preference.PreferenceFragment;
+import android.preference.PreferenceScreen;
+import android.preference.SwitchPreference;
+import android.provider.Settings;
+import android.telecom.PhoneAccountHandle;
+import android.telecom.TelecomManager;
+import android.telephony.CarrierConfigManager;
+import android.telephony.PhoneStateListener;
+import android.telephony.ServiceState;
+import android.telephony.SubscriptionInfo;
+import android.telephony.SubscriptionManager;
+import android.telephony.TelephonyManager;
+import android.telephony.euicc.EuiccManager;
+import android.text.TextUtils;
+import android.util.Log;
+import android.view.LayoutInflater;
+import android.view.MenuItem;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.TabHost;
+
+import com.android.ims.ImsConfig;
+import com.android.ims.ImsManager;
+import com.android.internal.logging.MetricsLogger;
+import com.android.internal.logging.nano.MetricsProto;
+import com.android.internal.telephony.Phone;
+import com.android.internal.telephony.PhoneConstants;
+import com.android.internal.telephony.TelephonyIntents;
+import com.android.phone.AdvancedOptionsPreference;
+import com.android.phone.CdmaOptions;
+import com.android.phone.CdmaSystemSelectListPreference;
+import com.android.phone.DataUsagePreference;
+import com.android.phone.EmergencyCallbackModeExitDialog;
+import com.android.phone.GsmUmtsOptions;
+import com.android.phone.MobileDataPreference;
+import com.android.phone.MobileNetworkSettings;
+import com.android.phone.NetworkOperators;
+import com.android.phone.NetworkSelectListPreference;
+import com.android.phone.RestrictedSwitchPreference;
+import com.android.phone.RoamingDialogFragment;
+import com.android.settingslib.RestrictedLockUtilsInternal;
+
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+
+public static class MobileNetworkFragment extends PreferenceFragment implements
+ Preference.OnPreferenceChangeListener, com.android.phone.RoamingDialogFragment.RoamingDialogListener {
+
+ // debug data
+ private static final String LOG_TAG = "NetworkSettings";
+ private static final boolean DBG = true;
+ public static final int REQUEST_CODE_EXIT_ECM = 17;
+
+ // Number of active Subscriptions to show tabs
+ private static final int TAB_THRESHOLD = 2;
+
+ // Number of last phone number digits shown in Euicc Setting tab
+ private static final int NUM_LAST_PHONE_DIGITS = 4;
+
+ // fragment tag for roaming data dialog
+ private static final String ROAMING_TAG = "RoamingDialogFragment";
+
+ //String keys for preference lookup
+ private static final String BUTTON_PREFERED_NETWORK_MODE = "preferred_network_mode_key";
+ private static final String BUTTON_ROAMING_KEY = "button_roaming_key";
+ private static final String BUTTON_CDMA_LTE_DATA_SERVICE_KEY = "cdma_lte_data_service_key";
+ private static final String BUTTON_ENABLED_NETWORKS_KEY = "enabled_networks_key";
+ private static final String BUTTON_4G_LTE_KEY = "enhanced_4g_lte";
+ private static final String BUTTON_CELL_BROADCAST_SETTINGS = "cell_broadcast_settings";
+ private static final String BUTTON_CARRIER_SETTINGS_KEY = "carrier_settings_key";
+ private static final String BUTTON_CDMA_SYSTEM_SELECT_KEY = "cdma_system_select_key";
+ private static final String BUTTON_CDMA_SUBSCRIPTION_KEY = "cdma_subscription_key";
+ private static final String BUTTON_CARRIER_SETTINGS_EUICC_KEY =
+ "carrier_settings_euicc_key";
+ private static final String BUTTON_WIFI_CALLING_KEY = "wifi_calling_key";
+ private static final String BUTTON_VIDEO_CALLING_KEY = "video_calling_key";
+ private static final String BUTTON_MOBILE_DATA_ENABLE_KEY = "mobile_data_enable";
+ private static final String BUTTON_DATA_USAGE_KEY = "data_usage_summary";
+ private static final String BUTTON_ADVANCED_OPTIONS_KEY = "advanced_options";
+ private static final String CATEGORY_CALLING_KEY = "calling";
+ private static final String CATEGORY_GSM_APN_EXPAND_KEY = "category_gsm_apn_key";
+ private static final String CATEGORY_CDMA_APN_EXPAND_KEY = "category_cdma_apn_key";
+ private static final String BUTTON_GSM_APN_EXPAND_KEY = "button_gsm_apn_key";
+ private static final String BUTTON_CDMA_APN_EXPAND_KEY = "button_cdma_apn_key";
+
+ private final BroadcastReceiver
+ mPhoneChangeReceiver = new MobileNetworkSettings.MobileNetworkFragment.PhoneChangeReceiver();
+ private final ContentObserver
+ mDpcEnforcedContentObserver = new MobileNetworkSettings.MobileNetworkFragment.DpcApnEnforcedObserver();
+
+ static final int preferredNetworkMode = Phone.PREFERRED_NT_MODE;
+
+ //Information about logical "up" Activity
+ private static final String UP_ACTIVITY_PACKAGE = "com.android.settings";
+ private static final String UP_ACTIVITY_CLASS =
+ "com.android.settings.Settings$WirelessSettingsActivity";
+
+ //Information that needs to save into Bundle.
+ private static final String EXPAND_ADVANCED_FIELDS = "expand_advanced_fields";
+ //Intent extra to indicate expand all fields.
+ private static final String EXPAND_EXTRA = "expandable";
+
+ private SubscriptionManager mSubscriptionManager;
+ private TelephonyManager mTelephonyManager;
+ private CarrierConfigManager mCarrierConfigManager;
+ private int mSubId;
+
+ //UI objects
+ private com.android.phone.AdvancedOptionsPreference mAdvancedOptions;
+ private ListPreference mButtonPreferredNetworkMode;
+ private ListPreference mButtonEnabledNetworks;
+ private RestrictedSwitchPreference mButtonDataRoam;
+ private SwitchPreference mButton4glte;
+ private Preference mLteDataServicePref;
+ private Preference mEuiccSettingsPref;
+ private PreferenceCategory mCallingCategory;
+ private Preference mWiFiCallingPref;
+ private SwitchPreference mVideoCallingPref;
+ private NetworkSelectListPreference mButtonNetworkSelect;
+ private com.android.phone.MobileDataPreference mMobileDataPref;
+ private com.android.phone.DataUsagePreference mDataUsagePref;
+
+ private static final String iface = "rmnet0"; //TODO: this will go away
+ private List<SubscriptionInfo> mActiveSubInfos;
+
+ private UserManager mUm;
+ private ImsManager mImsMgr;
+ private MobileNetworkSettings.MobileNetworkFragment.MyHandler mHandler;
+ private boolean mOkClicked;
+ private boolean mExpandAdvancedFields;
+
+ // We assume the the value returned by mTabHost.getCurrentTab() == slotId
+ private TabHost mTabHost;
+
+ //GsmUmts options and Cdma options
+ com.android.phone.GsmUmtsOptions mGsmUmtsOptions;
+ com.android.phone.CdmaOptions mCdmaOptions;
+
+ private Preference mClickedPreference;
+ private boolean mShow4GForLTE;
+ private boolean mIsGlobalCdma;
+ private boolean mOnlyAutoSelectInHomeNW;
+ private boolean mUnavailable;
+
+ private class PhoneCallStateListener extends PhoneStateListener {
+ /*
+ * Enable/disable the 'Enhanced 4G LTE Mode' when in/out of a call
+ * and depending on TTY mode and TTY support over VoLTE.
+ * @see android.telephony.PhoneStateListener#onCallStateChanged(int,
+ * java.lang.String)
+ */
+ @Override
+ public void onCallStateChanged(int state, String incomingNumber) {
+ if (DBG) log("PhoneStateListener.onCallStateChanged: state=" + state);
+
+ updateEnhanced4gLteState();
+ updateWiFiCallState();
+ updateVideoCallState();
+ updatePreferredNetworkType();
+ }
+
+ /**
+ * Listen to different subId if it's changed.
+ */
+ protected void updateSubscriptionId(Integer subId) {
+ if (subId.equals(MobileNetworkSettings.MobileNetworkFragment.PhoneCallStateListener.this.mSubId)) {
+ return;
+ }
+
+ MobileNetworkSettings.MobileNetworkFragment.PhoneCallStateListener.this.mSubId = subId;
+
+ mTelephonyManager.listen(this, PhoneStateListener.LISTEN_NONE);
+
+ // Now, listen to new subId if it's valid.
+ if (SubscriptionManager.isValidSubscriptionId(subId)) {
+ mTelephonyManager.listen(this, PhoneStateListener.LISTEN_CALL_STATE);
+ }
+ }
+ }
+
+ private final MobileNetworkSettings.MobileNetworkFragment.PhoneCallStateListener
+ mPhoneStateListener = new MobileNetworkSettings.MobileNetworkFragment.PhoneCallStateListener();
+
+ @Override
+ public void onPositiveButtonClick(DialogFragment dialog) {
+ mTelephonyManager.setDataRoamingEnabled(true);
+ mButtonDataRoam.setChecked(true);
+ MetricsLogger.action(getContext(),
+ getMetricsEventCategory(getPreferenceScreen(), mButtonDataRoam),
+ true);
+ }
+
+ @Override
+ public void onViewCreated(View view, Bundle savedInstanceState) {
+ if (getListView() != null) {
+ getListView().setDivider(null);
+ }
+ }
+
+ public void onIntentUpdate(Intent intent) {
+ if (!mUnavailable) {
+ updateCurrentTab(intent);
+ }
+ }
+
+ /**
+ * Invoked on each preference click in this hierarchy, overrides
+ * PreferenceActivity's implementation. Used to make sure we track the
+ * preference click events.
+ */
+ @Override
+ public boolean onPreferenceTreeClick(PreferenceScreen preferenceScreen,
+ Preference preference) {
+ sendMetricsEventPreferenceClicked(preferenceScreen, preference);
+
+ /** TODO: Refactor and get rid of the if's using subclasses */
+ if (preference.getKey().equals(BUTTON_4G_LTE_KEY)) {
+ return true;
+ } else if (mGsmUmtsOptions != null &&
+ mGsmUmtsOptions.preferenceTreeClick(preference) == true) {
+ return true;
+ } else if (mCdmaOptions != null &&
+ mCdmaOptions.preferenceTreeClick(preference) == true) {
+ if (mTelephonyManager.getEmergencyCallbackMode()) {
+
+ mClickedPreference = preference;
+
+ // In ECM mode launch ECM app dialog
+ startActivityForResult(
+ new Intent(TelephonyIntents.ACTION_SHOW_NOTICE_ECM_BLOCK_OTHERS, null),
+ REQUEST_CODE_EXIT_ECM);
+ }
+ return true;
+ } else if (preference == mButtonPreferredNetworkMode) {
+ //displays the value taken from the Settings.System
+ int settingsNetworkMode = android.provider.Settings.Global.getInt(
+ getContext().getContentResolver(),
+ android.provider.Settings.Global.PREFERRED_NETWORK_MODE + mSubId,
+ preferredNetworkMode);
+ mButtonPreferredNetworkMode.setValue(Integer.toString(settingsNetworkMode));
+ return true;
+ } else if (preference == mLteDataServicePref) {
+ String tmpl = android.provider.Settings.Global.getString(
+ getActivity().getContentResolver(),
+ android.provider.Settings.Global.SETUP_PREPAID_DATA_SERVICE_URL);
+ if (!TextUtils.isEmpty(tmpl)) {
+ String imsi = mTelephonyManager.getSubscriberId();
+ if (imsi == null) {
+ imsi = "";
+ }
+ final String url = TextUtils.isEmpty(tmpl) ? null
+ : TextUtils.expandTemplate(tmpl, imsi).toString();
+ Intent intent = new Intent(Intent.ACTION_VIEW, Uri.parse(url));
+ startActivity(intent);
+ } else {
+ android.util.Log.e(LOG_TAG, "Missing SETUP_PREPAID_DATA_SERVICE_URL");
+ }
+ return true;
+ } else if (preference == mButtonEnabledNetworks) {
+ int settingsNetworkMode = android.provider.Settings.Global.getInt(
+ getContext().getContentResolver(),
+ android.provider.Settings.Global.PREFERRED_NETWORK_MODE + mSubId,
+ preferredNetworkMode);
+ mButtonEnabledNetworks.setValue(Integer.toString(settingsNetworkMode));
+ return true;
+ } else if (preference == mButtonDataRoam) {
+ // Do not disable the preference screen if the user clicks Data roaming.
+ return true;
+ } else if (preference == mEuiccSettingsPref) {
+ Intent intent = new Intent(EuiccManager.ACTION_MANAGE_EMBEDDED_SUBSCRIPTIONS);
+ startActivity(intent);
+ return true;
+ } else if (preference == mWiFiCallingPref || preference == mVideoCallingPref
+ || preference == mMobileDataPref || preference == mDataUsagePref) {
+ return false;
+ } else if (preference == mAdvancedOptions) {
+ mExpandAdvancedFields = true;
+ updateBody();
+ return true;
+ } else {
+ // if the button is anything but the simple toggle preference,
+ // we'll need to disable all preferences to reject all click
+ // events until the sub-activity's UI comes up.
+ preferenceScreen.setEnabled(false);
+ // Let the intents be launched by the Preference manager
+ return false;
+ }
+ }
+
+ private final SubscriptionManager.OnSubscriptionsChangedListener
+ mOnSubscriptionsChangeListener
+ = new SubscriptionManager.OnSubscriptionsChangedListener() {
+ @Override
+ public void onSubscriptionsChanged() {
+ if (DBG) log("onSubscriptionsChanged:");
+ initializeSubscriptions();
+ }
+ };
+
+ private int getSlotIdFromIntent(Intent intent) {
+ Bundle data = intent.getExtras();
+ int subId = -1;
+ if (data != null) {
+ subId = data.getInt(Settings.EXTRA_SUB_ID, -1);
+ }
+ return SubscriptionManager.getSlotIndex(subId);
+ }
+
+ private void initializeSubscriptions() {
+ final Activity activity = getActivity();
+ if (activity == null || activity.isDestroyed()) {
+ // Process preferences in activity only if its not destroyed
+ return;
+ }
+ int currentTab = 0;
+ if (DBG) log("initializeSubscriptions:+");
+
+ // Before updating the the active subscription list check
+ // if tab updating is needed as the list is changing.
+ List<SubscriptionInfo> sil = mSubscriptionManager.getActiveSubscriptionInfoList();
+ MobileNetworkSettings.TabState state = isUpdateTabsNeeded(sil);
+
+ // Update to the active subscription list
+ mActiveSubInfos.clear();
+ if (sil != null) {
+ mActiveSubInfos.addAll(sil);
+ // If there is only 1 sim then currenTab should represent slot no. of the sim.
+ if (sil.size() == 1) {
+ currentTab = sil.get(0).getSimSlotIndex();
+ }
+ }
+
+ switch (state) {
+ case UPDATE: {
+ if (DBG) log("initializeSubscriptions: UPDATE");
+ currentTab = mTabHost != null ? mTabHost.getCurrentTab() : 0;
+
+ mTabHost = (TabHost) getActivity().findViewById(android.R.id.tabhost);
+ mTabHost.setup();
+
+ // Update the tabName. Since the mActiveSubInfos are in slot order
+ // we can iterate though the tabs and subscription info in one loop. But
+ // we need to handle the case where a slot may be empty.
+
+ Iterator<SubscriptionInfo> siIterator = mActiveSubInfos.listIterator();
+ SubscriptionInfo si = siIterator.hasNext() ? siIterator.next() : null;
+ for (int simSlotIndex = 0; simSlotIndex < mActiveSubInfos.size();
+ simSlotIndex++) {
+ String tabName;
+ if (si != null && si.getSimSlotIndex() == simSlotIndex) {
+ // Slot is not empty and we match
+ tabName = String.valueOf(si.getDisplayName());
+ si = siIterator.hasNext() ? siIterator.next() : null;
+ } else {
+ // Slot is empty, set name to unknown
+ tabName = getResources().getString(R.string.unknown);
+ }
+ if (DBG) {
+ log("initializeSubscriptions:tab=" + simSlotIndex + " name=" + tabName);
+ }
+
+ mTabHost.addTab(buildTabSpec(String.valueOf(simSlotIndex), tabName));
+ }
+
+ mTabHost.setOnTabChangedListener(mTabListener);
+ mTabHost.setCurrentTab(currentTab);
+ break;
+ }
+ case NO_TABS: {
+ if (DBG) log("initializeSubscriptions: NO_TABS");
+
+ if (mTabHost != null) {
+ mTabHost.clearAllTabs();
+ mTabHost = null;
+ }
+ break;
+ }
+ case DO_NOTHING: {
+ if (DBG) log("initializeSubscriptions: DO_NOTHING");
+ if (mTabHost != null) {
+ currentTab = mTabHost.getCurrentTab();
+ }
+ break;
+ }
+ }
+ updatePhone(currentTab);
+ updateBody();
+ if (DBG) log("initializeSubscriptions:-");
+ }
+
+ private MobileNetworkSettings.TabState isUpdateTabsNeeded(List<SubscriptionInfo> newSil) {
+ MobileNetworkSettings.TabState state = MobileNetworkSettings.TabState.DO_NOTHING;
+ if (newSil == null) {
+ if (mActiveSubInfos.size() >= TAB_THRESHOLD) {
+ if (DBG) log("isUpdateTabsNeeded: NO_TABS, size unknown and was tabbed");
+ state = MobileNetworkSettings.TabState.NO_TABS;
+ }
+ } else if (newSil.size() < TAB_THRESHOLD && mActiveSubInfos.size() >= TAB_THRESHOLD) {
+ if (DBG) log("isUpdateTabsNeeded: NO_TABS, size went to small");
+ state = MobileNetworkSettings.TabState.NO_TABS;
+ } else if (newSil.size() >= TAB_THRESHOLD && mActiveSubInfos.size() < TAB_THRESHOLD) {
+ if (DBG) log("isUpdateTabsNeeded: UPDATE, size changed");
+ state = MobileNetworkSettings.TabState.UPDATE;
+ } else if (newSil.size() >= TAB_THRESHOLD) {
+ Iterator<SubscriptionInfo> siIterator = mActiveSubInfos.iterator();
+ for(SubscriptionInfo newSi : newSil) {
+ SubscriptionInfo curSi = siIterator.next();
+ if (!newSi.getDisplayName().equals(curSi.getDisplayName())) {
+ if (DBG) log("isUpdateTabsNeeded: UPDATE, new name="
+ + newSi.getDisplayName());
+ state = MobileNetworkSettings.TabState.UPDATE;
+ break;
+ }
+ }
+ }
+ if (DBG) {
+ Log.i(LOG_TAG, "isUpdateTabsNeeded:- " + state
+ + " newSil.size()=" + ((newSil != null) ? newSil.size() : 0)
+ + " mActiveSubInfos.size()=" + mActiveSubInfos.size());
+ }
+ return state;
+ }
+
+ private TabHost.OnTabChangeListener mTabListener = new TabHost.OnTabChangeListener() {
+ @Override
+ public void onTabChanged(String tabId) {
+ if (DBG) log("onTabChanged:");
+ // The User has changed tab; update the body.
+ updatePhone(Integer.parseInt(tabId));
+ updateBody();
+ }
+ };
+
+ private void updatePhone(int slotId) {
+ final SubscriptionInfo sir = mSubscriptionManager
+ .getActiveSubscriptionInfoForSimSlotIndex(slotId);
+
+ if (sir != null) {
+ mSubId = sir.getSubscriptionId();
+
+ Log.i(LOG_TAG, "updatePhone:- slotId=" + slotId + " sir=" + sir);
+
+ mImsMgr = ImsManager.getInstance(getContext(),
+ SubscriptionManager.getPhoneId(mSubId));
+ mTelephonyManager = new TelephonyManager(getContext(), mSubId);
+ if (mImsMgr == null) {
+ log("updatePhone :: Could not get ImsManager instance!");
+ } else if (DBG) {
+ log("updatePhone :: mImsMgr=" + mImsMgr);
+ }
+ } else {
+ // There is no active subscription in the given slot.
+ mSubId = SubscriptionManager.INVALID_SUBSCRIPTION_ID;
+ }
+
+ mPhoneStateListener.updateSubscriptionId(mSubId);
+ }
+
+ private TabHost.TabContentFactory mEmptyTabContent = new TabHost.TabContentFactory() {
+ @Override
+ public View createTabContent(String tag) {
+ return new View(mTabHost.getContext());
+ }
+ };
+
+ private TabHost.TabSpec buildTabSpec(String tag, String title) {
+ return mTabHost.newTabSpec(tag).setIndicator(title).setContent(
+ mEmptyTabContent);
+ }
+
+ private void updateCurrentTab(Intent intent) {
+ int slotId = getSlotIdFromIntent(intent);
+ if (slotId >= 0 && mTabHost != null && mTabHost.getCurrentTab() != slotId) {
+ mTabHost.setCurrentTab(slotId);
+ }
+ }
+
+ @Override
+ public void onSaveInstanceState(Bundle outState) {
+ super.onSaveInstanceState(outState);
+
+ // If advanced fields are already expanded, we save it and expand it
+ // when it's re-created.
+ outState.putBoolean(EXPAND_ADVANCED_FIELDS, mExpandAdvancedFields);
+ }
+
+ @Override
+ public void onCreate(Bundle icicle) {
+ Log.i(LOG_TAG, "onCreate:+");
+ super.onCreate(icicle);
+
+ final Activity activity = getActivity();
+ if (activity == null || activity.isDestroyed()) {
+ Log.e(LOG_TAG, "onCreate:- with no valid activity.");
+ return;
+ }
+
+ mHandler = new MobileNetworkSettings.MobileNetworkFragment.MyHandler();
+ mUm = (UserManager) activity.getSystemService(Context.USER_SERVICE);
+ mSubscriptionManager = SubscriptionManager.from(activity);
+ mTelephonyManager = (TelephonyManager) activity.getSystemService(
+ Context.TELEPHONY_SERVICE);
+ mCarrierConfigManager = new CarrierConfigManager(getContext());
+
+ if (icicle != null) {
+ mExpandAdvancedFields = icicle.getBoolean(EXPAND_ADVANCED_FIELDS, false);
+ } else if (getActivity().getIntent().getBooleanExtra(EXPAND_EXTRA, false)) {
+ mExpandAdvancedFields = true;
+ }
+
+ addPreferencesFromResource(R.xml.network_setting_fragment);
+
+ mButton4glte = (SwitchPreference)findPreference(BUTTON_4G_LTE_KEY);
+ mButton4glte.setOnPreferenceChangeListener(this);
+
+ mCallingCategory = (PreferenceCategory) findPreference(CATEGORY_CALLING_KEY);
+ mWiFiCallingPref = findPreference(BUTTON_WIFI_CALLING_KEY);
+ mVideoCallingPref = (SwitchPreference) findPreference(BUTTON_VIDEO_CALLING_KEY);
+ mMobileDataPref = (MobileDataPreference) findPreference(BUTTON_MOBILE_DATA_ENABLE_KEY);
+ mDataUsagePref = (DataUsagePreference) findPreference(BUTTON_DATA_USAGE_KEY);
+
+ try {
+ Context con = activity.createPackageContext("com.android.systemui", 0);
+ int id = con.getResources().getIdentifier("config_show4GForLTE",
+ "bool", "com.android.systemui");
+ mShow4GForLTE = con.getResources().getBoolean(id);
+ } catch (PackageManager.NameNotFoundException e) {
+ Log.e(LOG_TAG, "NameNotFoundException for show4GFotLTE");
+ mShow4GForLTE = false;
+ }
+
+ //get UI object references
+ PreferenceScreen prefSet = getPreferenceScreen();
+
+ mButtonDataRoam = (RestrictedSwitchPreference) prefSet.findPreference(
+ BUTTON_ROAMING_KEY);
+ mButtonPreferredNetworkMode = (ListPreference) prefSet.findPreference(
+ BUTTON_PREFERED_NETWORK_MODE);
+ mButtonEnabledNetworks = (ListPreference) prefSet.findPreference(
+ BUTTON_ENABLED_NETWORKS_KEY);
+ mAdvancedOptions = (AdvancedOptionsPreference) prefSet.findPreference(
+ BUTTON_ADVANCED_OPTIONS_KEY);
+ mButtonDataRoam.setOnPreferenceChangeListener(this);
+
+ mLteDataServicePref = prefSet.findPreference(BUTTON_CDMA_LTE_DATA_SERVICE_KEY);
+
+ mEuiccSettingsPref = prefSet.findPreference(BUTTON_CARRIER_SETTINGS_EUICC_KEY);
+ mEuiccSettingsPref.setOnPreferenceChangeListener(this);
+
+ // Initialize mActiveSubInfo
+ int max = mSubscriptionManager.getActiveSubscriptionInfoCountMax();
+ mActiveSubInfos = new ArrayList<SubscriptionInfo>(max);
+
+ int currentTab = mTabHost != null ? mTabHost.getCurrentTab() : 0;
+ updatePhone(currentTab);
+ if (hasActiveSubscriptions()) {
+ updateEnabledNetworksEntries();
+ }
+ Log.i(LOG_TAG, "onCreate:-");
+ }
+
+ @Override
+ public View onCreateView(LayoutInflater inflater, ViewGroup container,
+ Bundle savedInstanceState) {
+ return inflater.inflate(com.android.internal.R.layout.common_tab_settings,
+ container, false);
+ }
+
+ @Override
+ public void onActivityCreated(Bundle savedInstanceState) {
+ super.onActivityCreated(savedInstanceState);
+ if (mUm.hasUserRestriction(UserManager.DISALLOW_CONFIG_MOBILE_NETWORKS)
+ || !mUm.isSystemUser()) {
+ mUnavailable = true;
+ getActivity().setContentView(R.layout.telephony_disallowed_preference_screen);
+ } else {
+ initializeSubscriptions();
+ updateCurrentTab(getActivity().getIntent());
+ }
+ }
+
+ private class PhoneChangeReceiver extends BroadcastReceiver {
+ @Override
+ public void onReceive(Context context, Intent intent) {
+ Log.i(LOG_TAG, "onReceive:");
+ if (getActivity() == null || getContext() == null) {
+ // Received broadcast and activity is in the process of being torn down.
+ return;
+ }
+ // When the radio changes (ex: CDMA->GSM), refresh all options.
+ updateBody();
+ }
+ }
+
+ private class DpcApnEnforcedObserver extends ContentObserver {
+ DpcApnEnforcedObserver() {
+ super(null);
+ }
+
+ @Override
+ public void onChange(boolean selfChange) {
+ Log.i(LOG_TAG, "DPC enforced onChange:");
+ if (getActivity() == null || getContext() == null) {
+ // Received content change and activity is in the process of being torn down.
+ return;
+ }
+ updateBody();
+ }
+ }
+
+ @Override
+ public void onDestroy() {
+ super.onDestroy();
+ if (mMobileDataPref != null) {
+ mMobileDataPref.dispose();
+ }
+ }
+
+ @Override
+ public void onResume() {
+ super.onResume();
+ Log.i(LOG_TAG, "onResume:+");
+
+ if (mUnavailable) {
+ Log.i(LOG_TAG, "onResume:- ignore mUnavailable == false");
+ return;
+ }
+
+ // upon resumption from the sub-activity, make sure we re-enable the
+ // preferences.
+ getPreferenceScreen().setEnabled(true);
+
+ // Set UI state in onResume because a user could go home, launch some
+ // app to change this setting's backend, and re-launch this settings app
+ // and the UI state would be inconsistent with actual state
+ mButtonDataRoam.setChecked(mTelephonyManager.isDataRoamingEnabled());
+
+ if (getPreferenceScreen().findPreference(BUTTON_PREFERED_NETWORK_MODE) != null
+ || getPreferenceScreen().findPreference(BUTTON_ENABLED_NETWORKS_KEY) != null) {
+ updatePreferredNetworkUIFromDb();
+ }
+
+ mTelephonyManager.listen(mPhoneStateListener, PhoneStateListener.LISTEN_CALL_STATE);
+
+ // NOTE: Buttons will be enabled/disabled in mPhoneStateListener
+ updateEnhanced4gLteState();
+
+ // Video calling and WiFi calling state might have changed.
+ updateCallingCategory();
+
+ mSubscriptionManager.addOnSubscriptionsChangedListener(mOnSubscriptionsChangeListener);
+
+ final Context context = getActivity();
+ IntentFilter intentFilter = new IntentFilter(
+ TelephonyIntents.ACTION_RADIO_TECHNOLOGY_CHANGED);
+ context.registerReceiver(mPhoneChangeReceiver, intentFilter);
+ context.getContentResolver().registerContentObserver(ENFORCE_MANAGED_URI, false,
+ mDpcEnforcedContentObserver);
+
+ Log.i(LOG_TAG, "onResume:-");
+
+ }
+
+ private boolean hasActiveSubscriptions() {
+ return mActiveSubInfos.size() > 0;
+ }
+
+ private void updateBodyBasicFields(Activity activity, PreferenceScreen prefSet,
+ int phoneSubId, boolean hasActiveSubscriptions) {
+ Context context = activity.getApplicationContext();
+
+ ActionBar actionBar = activity.getActionBar();
+ if (actionBar != null) {
+ // android.R.id.home will be triggered in onOptionsItemSelected()
+ actionBar.setDisplayHomeAsUpEnabled(true);
+ }
+
+ prefSet.addPreference(mMobileDataPref);
+ prefSet.addPreference(mButtonDataRoam);
+ prefSet.addPreference(mDataUsagePref);
+
+ mMobileDataPref.setEnabled(hasActiveSubscriptions);
+ mButtonDataRoam.setEnabled(hasActiveSubscriptions);
+ mDataUsagePref.setEnabled(hasActiveSubscriptions);
+
+ if (hasActiveSubscriptions) {
+ // Customized preferences needs to be initialized with subId.
+ mMobileDataPref.initialize(phoneSubId);
+ mDataUsagePref.initialize(phoneSubId);
+
+ // Initialize states of mButtonDataRoam.
+ mButtonDataRoam.setChecked(mTelephonyManager.isDataRoamingEnabled());
+ mButtonDataRoam.setDisabledByAdmin(false);
+ if (mButtonDataRoam.isEnabled()) {
+ if (RestrictedLockUtilsInternal.hasBaseUserRestriction(context,
+ UserManager.DISALLOW_DATA_ROAMING, UserHandle.myUserId())) {
+ mButtonDataRoam.setEnabled(false);
+ } else {
+ mButtonDataRoam.checkRestrictionAndSetDisabled(
+ UserManager.DISALLOW_DATA_ROAMING);
+ }
+ }
+ }
+ }
+
+ private void updateBody() {
+ final Activity activity = getActivity();
+ final PreferenceScreen prefSet = getPreferenceScreen();
+ final boolean hasActiveSubscriptions = hasActiveSubscriptions();
+
+ if (activity == null || activity.isDestroyed()) {
+ Log.e(LOG_TAG, "updateBody with no valid activity.");
+ return;
+ }
+
+ if (prefSet == null) {
+ Log.e(LOG_TAG, "updateBody with no null prefSet.");
+ return;
+ }
+
+ prefSet.removeAll();
+
+ updateBodyBasicFields(activity, prefSet, mSubId, hasActiveSubscriptions);
+
+ if (hasActiveSubscriptions) {
+ if (mExpandAdvancedFields) {
+ updateBodyAdvancedFields(activity, prefSet, mSubId, hasActiveSubscriptions);
+ } else {
+ prefSet.addPreference(mAdvancedOptions);
+ }
+ } else {
+ // Shows the "Carrier" preference that allows user to add a e-sim profile.
+ if (showEuiccSettings(getContext())) {
+ mEuiccSettingsPref.setSummary(null /* summary */);
+ prefSet.addPreference(mEuiccSettingsPref);
+ }
+ }
+ }
+
+ private void updateBodyAdvancedFields(Activity activity, PreferenceScreen prefSet,
+ int phoneSubId, boolean hasActiveSubscriptions) {
+ boolean isLteOnCdma = mTelephonyManager.getLteOnCdmaMode()
+ == PhoneConstants.LTE_ON_CDMA_TRUE;
+
+ if (DBG) {
+ log("updateBody: isLteOnCdma=" + isLteOnCdma + " phoneSubId=" + phoneSubId);
+ }
+
+ prefSet.addPreference(mButtonPreferredNetworkMode);
+ prefSet.addPreference(mButtonEnabledNetworks);
+ prefSet.addPreference(mButton4glte);
+
+ if (showEuiccSettings(getActivity())) {
+ prefSet.addPreference(mEuiccSettingsPref);
+ String spn = mTelephonyManager.getSimOperatorName();
+ if (TextUtils.isEmpty(spn)) {
+ mEuiccSettingsPref.setSummary(null);
+ } else {
+ mEuiccSettingsPref.setSummary(spn);
+ }
+ }
+
+ int settingsNetworkMode = android.provider.Settings.Global.getInt(
+ getContext().getContentResolver(),
+ android.provider.Settings.Global.PREFERRED_NETWORK_MODE + phoneSubId,
+ preferredNetworkMode);
+
+ PersistableBundle carrierConfig = mCarrierConfigManager.getConfigForSubId(mSubId);
+ mIsGlobalCdma = isLteOnCdma
+ && carrierConfig.getBoolean(CarrierConfigManager.KEY_SHOW_CDMA_CHOICES_BOOL);
+ if (carrierConfig.getBoolean(
+ CarrierConfigManager.KEY_HIDE_CARRIER_NETWORK_SETTINGS_BOOL)) {
+ prefSet.removePreference(mButtonPreferredNetworkMode);
+ prefSet.removePreference(mButtonEnabledNetworks);
+ prefSet.removePreference(mLteDataServicePref);
+ } else if (carrierConfig.getBoolean(CarrierConfigManager
+ .KEY_HIDE_PREFERRED_NETWORK_TYPE_BOOL)
+ && !mTelephonyManager.getServiceState().getRoaming()
+ && mTelephonyManager.getServiceState().getDataRegState()
+ == ServiceState.STATE_IN_SERVICE) {
+ prefSet.removePreference(mButtonPreferredNetworkMode);
+ prefSet.removePreference(mButtonEnabledNetworks);
+
+ final int phoneType = mTelephonyManager.getPhoneType();
+ if (phoneType == PhoneConstants.PHONE_TYPE_CDMA) {
+ updateCdmaOptions(this, prefSet, mSubId);
+ } else if (phoneType == PhoneConstants.PHONE_TYPE_GSM) {
+ updateGsmUmtsOptions(this, prefSet, phoneSubId);
+ } else {
+ throw new IllegalStateException("Unexpected phone type: " + phoneType);
+ }
+ // Since pref is being hidden from user, set network mode to default
+ // in case it is currently something else. That is possible if user
+ // changed the setting while roaming and is now back to home network.
+ settingsNetworkMode = preferredNetworkMode;
+ } else if (carrierConfig.getBoolean(
+ CarrierConfigManager.KEY_WORLD_PHONE_BOOL) == true) {
+ prefSet.removePreference(mButtonEnabledNetworks);
+ // set the listener for the mButtonPreferredNetworkMode list preference so we can issue
+ // change Preferred Network Mode.
+ mButtonPreferredNetworkMode.setOnPreferenceChangeListener(this);
+
+ updateCdmaOptions(this, prefSet, mSubId);
+ updateGsmUmtsOptions(this, prefSet, phoneSubId);
+ } else {
+ prefSet.removePreference(mButtonPreferredNetworkMode);
+ updateEnabledNetworksEntries();
+ mButtonEnabledNetworks.setOnPreferenceChangeListener(this);
+ if (DBG) log("settingsNetworkMode: " + settingsNetworkMode);
+ }
+
+ final boolean missingDataServiceUrl = TextUtils.isEmpty(
+ android.provider.Settings.Global.getString(activity.getContentResolver(),
+ android.provider.Settings.Global.SETUP_PREPAID_DATA_SERVICE_URL));
+ if (!isLteOnCdma || missingDataServiceUrl) {
+ prefSet.removePreference(mLteDataServicePref);
+ } else {
+ android.util.Log.d(LOG_TAG, "keep ltePref");
+ }
+
+ updateEnhanced4gLteState();
+ updatePreferredNetworkType();
+ updateCallingCategory();
+
+ // Enable link to CMAS app settings depending on the value in config.xml.
+ final boolean isCellBroadcastAppLinkEnabled = activity.getResources().getBoolean(
+ com.android.internal.R.bool.config_cellBroadcastAppLinks);
+ if (!mUm.isAdminUser() || !isCellBroadcastAppLinkEnabled
+ || mUm.hasUserRestriction(UserManager.DISALLOW_CONFIG_CELL_BROADCASTS)) {
+ PreferenceScreen root = getPreferenceScreen();
+ Preference ps = findPreference(BUTTON_CELL_BROADCAST_SETTINGS);
+ if (ps != null) {
+ root.removePreference(ps);
+ }
+ }
+
+ /**
+ * Listen to extra preference changes that need as Metrics events logging.
+ */
+ if (prefSet.findPreference(BUTTON_CDMA_SYSTEM_SELECT_KEY) != null) {
+ prefSet.findPreference(BUTTON_CDMA_SYSTEM_SELECT_KEY)
+ .setOnPreferenceChangeListener(this);
+ }
+
+ if (prefSet.findPreference(BUTTON_CDMA_SUBSCRIPTION_KEY) != null) {
+ prefSet.findPreference(BUTTON_CDMA_SUBSCRIPTION_KEY)
+ .setOnPreferenceChangeListener(this);
+ }
+
+ // Get the networkMode from Settings.System and displays it
+ mButtonEnabledNetworks.setValue(Integer.toString(settingsNetworkMode));
+ mButtonPreferredNetworkMode.setValue(Integer.toString(settingsNetworkMode));
+ UpdatePreferredNetworkModeSummary(settingsNetworkMode);
+ UpdateEnabledNetworksValueAndSummary(settingsNetworkMode);
+ // Display preferred network type based on what modem returns b/18676277
+ new MobileNetworkSettings.SetPreferredNetworkAsyncTask(
+ mTelephonyManager,
+ mSubId,
+ settingsNetworkMode,
+ mHandler.obtainMessage(MobileNetworkSettings.MobileNetworkFragment.MyHandler.MESSAGE_SET_PREFERRED_NETWORK_TYPE))
+ .executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
+
+ /**
+ * Enable/disable depending upon if there are any active subscriptions.
+ *
+ * I've decided to put this enable/disable code at the bottom as the
+ * code above works even when there are no active subscriptions, thus
+ * putting it afterwards is a smaller change. This can be refined later,
+ * but you do need to remember that this all needs to work when subscriptions
+ * change dynamically such as when hot swapping sims.
+ */
+ boolean useVariant4glteTitle = carrierConfig.getBoolean(
+ CarrierConfigManager.KEY_ENHANCED_4G_LTE_TITLE_VARIANT_BOOL);
+ int enhanced4glteModeTitleId = useVariant4glteTitle ?
+ R.string.enhanced_4g_lte_mode_title_variant :
+ R.string.enhanced_4g_lte_mode_title;
+
+ mOnlyAutoSelectInHomeNW = carrierConfig.getBoolean(
+ CarrierConfigManager.KEY_ONLY_AUTO_SELECT_IN_HOME_NETWORK_BOOL);
+ mButton4glte.setTitle(enhanced4glteModeTitleId);
+ mLteDataServicePref.setEnabled(hasActiveSubscriptions);
+ Preference ps;
+ ps = findPreference(BUTTON_CELL_BROADCAST_SETTINGS);
+ if (ps != null) {
+ ps.setEnabled(hasActiveSubscriptions);
+ }
+ ps = findPreference(CATEGORY_GSM_APN_EXPAND_KEY);
+ if (ps != null) {
+ ps.setEnabled(hasActiveSubscriptions);
+ }
+ ps = findPreference(CATEGORY_CDMA_APN_EXPAND_KEY);
+ if (ps != null) {
+ ps.setEnabled(hasActiveSubscriptions);
+ }
+ ps = findPreference(com.android.phone.NetworkOperators.CATEGORY_NETWORK_OPERATORS_KEY);
+ if (ps != null) {
+ ps.setEnabled(hasActiveSubscriptions);
+ }
+ ps = findPreference(BUTTON_CARRIER_SETTINGS_KEY);
+ if (ps != null) {
+ ps.setEnabled(hasActiveSubscriptions);
+ }
+ ps = findPreference(BUTTON_CDMA_SYSTEM_SELECT_KEY);
+ if (ps != null) {
+ ps.setEnabled(hasActiveSubscriptions);
+ }
+ ps = findPreference(CATEGORY_CALLING_KEY);
+ if (ps != null) {
+ ps.setEnabled(hasActiveSubscriptions);
+ }
+ ps = findPreference(com.android.phone.NetworkOperators.BUTTON_AUTO_SELECT_KEY);
+ if (ps != null) {
+ ps.setSummary(null);
+ if (mTelephonyManager.getServiceState().getRoaming()) {
+ ps.setEnabled(true);
+ } else {
+ ps.setEnabled(!mOnlyAutoSelectInHomeNW);
+ if (mOnlyAutoSelectInHomeNW) {
+ ps.setSummary(getResources().getString(
+ R.string.manual_mode_disallowed_summary,
+ mTelephonyManager.getSimOperatorName()));
+ }
+ }
+ }
+ }
+
+ // Requires that mSubId is up to date
+ void updateEnabledNetworksEntries() {
+ final int phoneType = mTelephonyManager.getPhoneType();
+ final PersistableBundle carrierConfig = mCarrierConfigManager.getConfigForSubId(mSubId);
+ if (phoneType == PhoneConstants.PHONE_TYPE_CDMA) {
+ final int lteForced = android.provider.Settings.Global.getInt(
+ getContext().getContentResolver(),
+ android.provider.Settings.Global.LTE_SERVICE_FORCED + mSubId,
+ 0);
+ final boolean isLteOnCdma = mTelephonyManager.getLteOnCdmaMode()
+ == PhoneConstants.LTE_ON_CDMA_TRUE;
+ final int settingsNetworkMode = android.provider.Settings.Global.getInt(
+ getContext().getContentResolver(),
+ android.provider.Settings.Global.PREFERRED_NETWORK_MODE + mSubId,
+ preferredNetworkMode);
+ if (isLteOnCdma) {
+ if (lteForced == 0) {
+ mButtonEnabledNetworks.setEntries(
+ R.array.enabled_networks_cdma_choices);
+ mButtonEnabledNetworks.setEntryValues(
+ R.array.enabled_networks_cdma_values);
+ } else {
+ switch (settingsNetworkMode) {
+ case TelephonyManager.NETWORK_MODE_CDMA_EVDO:
+ case TelephonyManager.NETWORK_MODE_CDMA_NO_EVDO:
+ case TelephonyManager.NETWORK_MODE_EVDO_NO_CDMA:
+ mButtonEnabledNetworks.setEntries(
+ R.array.enabled_networks_cdma_no_lte_choices);
+ mButtonEnabledNetworks.setEntryValues(
+ R.array.enabled_networks_cdma_no_lte_values);
+ break;
+ case TelephonyManager.NETWORK_MODE_GLOBAL:
+ case TelephonyManager.NETWORK_MODE_LTE_CDMA_EVDO:
+ case TelephonyManager.NETWORK_MODE_LTE_CDMA_EVDO_GSM_WCDMA:
+ case TelephonyManager.NETWORK_MODE_LTE_ONLY:
+ mButtonEnabledNetworks.setEntries(
+ R.array.enabled_networks_cdma_only_lte_choices);
+ mButtonEnabledNetworks.setEntryValues(
+ R.array.enabled_networks_cdma_only_lte_values);
+ break;
+ default:
+ mButtonEnabledNetworks.setEntries(
+ R.array.enabled_networks_cdma_choices);
+ mButtonEnabledNetworks.setEntryValues(
+ R.array.enabled_networks_cdma_values);
+ break;
+ }
+ }
+ }
+ updateCdmaOptions(this, getPreferenceScreen(), mSubId);
+
+ } else if (phoneType == PhoneConstants.PHONE_TYPE_GSM) {
+ if (isSupportTdscdma()) {
+ mButtonEnabledNetworks.setEntries(
+ R.array.enabled_networks_tdscdma_choices);
+ mButtonEnabledNetworks.setEntryValues(
+ R.array.enabled_networks_tdscdma_values);
+ } else if (!carrierConfig.getBoolean(CarrierConfigManager.KEY_PREFER_2G_BOOL)
+ && !getResources().getBoolean(R.bool.config_enabled_lte)) {
+ mButtonEnabledNetworks.setEntries(
+ R.array.enabled_networks_except_gsm_lte_choices);
+ mButtonEnabledNetworks.setEntryValues(
+ R.array.enabled_networks_except_gsm_lte_values);
+ } else if (!carrierConfig.getBoolean(CarrierConfigManager.KEY_PREFER_2G_BOOL)) {
+ int select = mShow4GForLTE
+ ? R.array.enabled_networks_except_gsm_4g_choices
+ : R.array.enabled_networks_except_gsm_choices;
+ mButtonEnabledNetworks.setEntries(select);
+ mButtonEnabledNetworks.setEntryValues(
+ R.array.enabled_networks_except_gsm_values);
+ } else if (!getResources().getBoolean(R.bool.config_enabled_lte)) {
+ mButtonEnabledNetworks.setEntries(
+ R.array.enabled_networks_except_lte_choices);
+ mButtonEnabledNetworks.setEntryValues(
+ R.array.enabled_networks_except_lte_values);
+ } else if (mIsGlobalCdma) {
+ mButtonEnabledNetworks.setEntries(
+ R.array.enabled_networks_cdma_choices);
+ mButtonEnabledNetworks.setEntryValues(
+ R.array.enabled_networks_cdma_values);
+ } else {
+ int select = mShow4GForLTE ? R.array.enabled_networks_4g_choices
+ : R.array.enabled_networks_choices;
+ mButtonEnabledNetworks.setEntries(select);
+ mButtonEnabledNetworks.setEntryValues(
+ R.array.enabled_networks_values);
+ }
+ updateGsmUmtsOptions(this, getPreferenceScreen(), mSubId);
+ } else {
+ throw new IllegalStateException("Unexpected phone type: " + phoneType);
+ }
+ if (isWorldMode()) {
+ mButtonEnabledNetworks.setEntries(
+ R.array.preferred_network_mode_choices_world_mode);
+ mButtonEnabledNetworks.setEntryValues(
+ R.array.preferred_network_mode_values_world_mode);
+ }
+ }
+
+ @Override
+ public void onPause() {
+ super.onPause();
+ if (DBG) log("onPause:+");
+
+ mTelephonyManager.listen(mPhoneStateListener, PhoneStateListener.LISTEN_NONE);
+
+ mSubscriptionManager
+ .removeOnSubscriptionsChangedListener(mOnSubscriptionsChangeListener);
+
+ final Context context = getActivity();
+ context.unregisterReceiver(mPhoneChangeReceiver);
+ context.getContentResolver().unregisterContentObserver(mDpcEnforcedContentObserver);
+ if (DBG) log("onPause:-");
+ }
+
+ /**
+ * Implemented to support onPreferenceChangeListener to look for preference
+ * changes specifically on CLIR.
+ *
+ * @param preference is the preference to be changed, should be mButtonCLIR.
+ * @param objValue should be the value of the selection, NOT its localized
+ * display value.
+ */
+ public boolean onPreferenceChange(Preference preference, Object objValue) {
+ sendMetricsEventPreferenceChanged(getPreferenceScreen(), preference, objValue);
+
+ final int phoneSubId = mSubId;
+ if (preference == mButtonPreferredNetworkMode) {
+ //NOTE onPreferenceChange seems to be called even if there is no change
+ //Check if the button value is changed from the System.Setting
+ mButtonPreferredNetworkMode.setValue((String) objValue);
+ int buttonNetworkMode;
+ buttonNetworkMode = Integer.parseInt((String) objValue);
+ int settingsNetworkMode = android.provider.Settings.Global.getInt(
+ getContext().getContentResolver(),
+ android.provider.Settings.Global.PREFERRED_NETWORK_MODE + phoneSubId,
+ preferredNetworkMode);
+ if (buttonNetworkMode != settingsNetworkMode) {
+ int modemNetworkMode;
+ // if new mode is invalid ignore it
+ switch (buttonNetworkMode) {
+ case TelephonyManager.NETWORK_MODE_WCDMA_PREF:
+ case TelephonyManager.NETWORK_MODE_GSM_ONLY:
+ case TelephonyManager.NETWORK_MODE_WCDMA_ONLY:
+ case TelephonyManager.NETWORK_MODE_GSM_UMTS:
+ case TelephonyManager.NETWORK_MODE_CDMA_EVDO:
+ case TelephonyManager.NETWORK_MODE_CDMA_NO_EVDO:
+ case TelephonyManager.NETWORK_MODE_EVDO_NO_CDMA:
+ case TelephonyManager.NETWORK_MODE_GLOBAL:
+ case TelephonyManager.NETWORK_MODE_LTE_CDMA_EVDO:
+ case TelephonyManager.NETWORK_MODE_LTE_GSM_WCDMA:
+ case TelephonyManager.NETWORK_MODE_LTE_CDMA_EVDO_GSM_WCDMA:
+ case TelephonyManager.NETWORK_MODE_LTE_ONLY:
+ case TelephonyManager.NETWORK_MODE_LTE_WCDMA:
+ case TelephonyManager.NETWORK_MODE_TDSCDMA_ONLY:
+ case TelephonyManager.NETWORK_MODE_TDSCDMA_WCDMA:
+ case TelephonyManager.NETWORK_MODE_LTE_TDSCDMA:
+ case TelephonyManager.NETWORK_MODE_TDSCDMA_GSM:
+ case TelephonyManager.NETWORK_MODE_LTE_TDSCDMA_GSM:
+ case TelephonyManager.NETWORK_MODE_TDSCDMA_GSM_WCDMA:
+ case TelephonyManager.NETWORK_MODE_LTE_TDSCDMA_WCDMA:
+ case TelephonyManager.NETWORK_MODE_LTE_TDSCDMA_GSM_WCDMA:
+ case TelephonyManager.NETWORK_MODE_TDSCDMA_CDMA_EVDO_GSM_WCDMA:
+ case TelephonyManager.NETWORK_MODE_LTE_TDSCDMA_CDMA_EVDO_GSM_WCDMA:
+ // This is one of the modes we recognize
+ modemNetworkMode = buttonNetworkMode;
+ break;
+ default:
+ loge("Invalid Network Mode (" +buttonNetworkMode+ ") chosen. Ignore.");
+ return true;
+ }
+
+ android.provider.Settings.Global.putInt(
+ getContext().getContentResolver(),
+ android.provider.Settings.Global.PREFERRED_NETWORK_MODE + phoneSubId,
+ buttonNetworkMode );
+ //Set the modem network mode
+ new MobileNetworkSettings.SetPreferredNetworkAsyncTask(
+ mTelephonyManager,
+ mSubId,
+ modemNetworkMode,
+ mHandler.obtainMessage(MobileNetworkSettings.MobileNetworkFragment.MyHandler.MESSAGE_SET_PREFERRED_NETWORK_TYPE))
+ .executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
+ }
+ } else if (preference == mButtonEnabledNetworks) {
+ mButtonEnabledNetworks.setValue((String) objValue);
+ int buttonNetworkMode;
+ buttonNetworkMode = Integer.parseInt((String) objValue);
+ if (DBG) log("buttonNetworkMode: " + buttonNetworkMode);
+ int settingsNetworkMode = android.provider.Settings.Global.getInt(
+ getContext().getContentResolver(),
+ android.provider.Settings.Global.PREFERRED_NETWORK_MODE + phoneSubId,
+ preferredNetworkMode);
+ if (buttonNetworkMode != settingsNetworkMode) {
+ int modemNetworkMode;
+ // if new mode is invalid ignore it
+ switch (buttonNetworkMode) {
+ case TelephonyManager.NETWORK_MODE_WCDMA_PREF:
+ case TelephonyManager.NETWORK_MODE_GSM_ONLY:
+ case TelephonyManager.NETWORK_MODE_LTE_GSM_WCDMA:
+ case TelephonyManager.NETWORK_MODE_LTE_CDMA_EVDO_GSM_WCDMA:
+ case TelephonyManager.NETWORK_MODE_CDMA_EVDO:
+ case TelephonyManager.NETWORK_MODE_CDMA_NO_EVDO:
+ case TelephonyManager.NETWORK_MODE_LTE_CDMA_EVDO:
+ case TelephonyManager.NETWORK_MODE_TDSCDMA_ONLY:
+ case TelephonyManager.NETWORK_MODE_TDSCDMA_WCDMA:
+ case TelephonyManager.NETWORK_MODE_LTE_TDSCDMA:
+ case TelephonyManager.NETWORK_MODE_TDSCDMA_GSM:
+ case TelephonyManager.NETWORK_MODE_LTE_TDSCDMA_GSM:
+ case TelephonyManager.NETWORK_MODE_TDSCDMA_GSM_WCDMA:
+ case TelephonyManager.NETWORK_MODE_LTE_TDSCDMA_WCDMA:
+ case TelephonyManager.NETWORK_MODE_LTE_TDSCDMA_GSM_WCDMA:
+ case TelephonyManager.NETWORK_MODE_TDSCDMA_CDMA_EVDO_GSM_WCDMA:
+ case TelephonyManager.NETWORK_MODE_LTE_TDSCDMA_CDMA_EVDO_GSM_WCDMA:
+ // This is one of the modes we recognize
+ modemNetworkMode = buttonNetworkMode;
+ break;
+ default:
+ loge("Invalid Network Mode (" +buttonNetworkMode+ ") chosen. Ignore.");
+ return true;
+ }
+
+ UpdateEnabledNetworksValueAndSummary(buttonNetworkMode);
+
+ android.provider.Settings.Global.putInt(
+ getContext().getContentResolver(),
+ android.provider.Settings.Global.PREFERRED_NETWORK_MODE + phoneSubId,
+ buttonNetworkMode );
+ //Set the modem network mode
+ new MobileNetworkSettings.SetPreferredNetworkAsyncTask(
+ mTelephonyManager,
+ mSubId,
+ modemNetworkMode,
+ mHandler.obtainMessage(MobileNetworkSettings.MobileNetworkFragment.MyHandler.MESSAGE_SET_PREFERRED_NETWORK_TYPE))
+ .executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
+ }
+ } else if (preference == mButton4glte) {
+ boolean enhanced4gMode = !mButton4glte.isChecked();
+ mButton4glte.setChecked(enhanced4gMode);
+ mImsMgr.setEnhanced4gLteModeSetting(mButton4glte.isChecked());
+ } else if (preference == mButtonDataRoam) {
+ if (DBG) log("onPreferenceTreeClick: preference == mButtonDataRoam.");
+
+ //normally called on the toggle click
+ if (!mButtonDataRoam.isChecked()) {
+ PersistableBundle carrierConfig = mCarrierConfigManager.getConfigForSubId(
+ mSubId);
+ if (carrierConfig != null && carrierConfig.getBoolean(
+ CarrierConfigManager.KEY_DISABLE_CHARGE_INDICATION_BOOL)) {
+ mTelephonyManager.setDataRoamingEnabled(true);
+ MetricsLogger.action(getContext(),
+ getMetricsEventCategory(getPreferenceScreen(), mButtonDataRoam),
+ true);
+ } else {
+ // MetricsEvent with no value update.
+ MetricsLogger.action(getContext(),
+ getMetricsEventCategory(getPreferenceScreen(), mButtonDataRoam));
+ // First confirm with a warning dialog about charges
+ mOkClicked = false;
+ com.android.phone.RoamingDialogFragment
+ fragment = new com.android.phone.RoamingDialogFragment();
+ Bundle b = new Bundle();
+ b.putInt(RoamingDialogFragment.SUB_ID_KEY, mSubId);
+ fragment.setArguments(b);
+ fragment.show(getFragmentManager(), ROAMING_TAG);
+ // Don't update the toggle unless the confirm button is actually pressed.
+ return false;
+ }
+ } else {
+ mTelephonyManager.setDataRoamingEnabled(false);
+ MetricsLogger.action(getContext(),
+ getMetricsEventCategory(getPreferenceScreen(), mButtonDataRoam),
+ false);
+ return true;
+ }
+ } else if (preference == mVideoCallingPref) {
+ // If mButton4glte is not checked, mVideoCallingPref should be disabled.
+ // So it only makes sense to call phoneMgr.enableVideoCalling if it's checked.
+ if (mButton4glte.isChecked()) {
+ mImsMgr.setVtSetting((boolean) objValue);
+ return true;
+ } else {
+ loge("mVideoCallingPref should be disabled if mButton4glte is not checked.");
+ mVideoCallingPref.setEnabled(false);
+ return false;
+ }
+ } else if (preference == getPreferenceScreen()
+ .findPreference(BUTTON_CDMA_SYSTEM_SELECT_KEY)
+ || preference == getPreferenceScreen()
+ .findPreference(BUTTON_CDMA_SUBSCRIPTION_KEY)) {
+ return true;
+ }
+
+ updateBody();
+ // always let the preference setting proceed.
+ return true;
+ }
+
+ private boolean is4gLtePrefEnabled(PersistableBundle carrierConfig) {
+ return (mTelephonyManager.getCallState(mSubId)
+ == TelephonyManager.CALL_STATE_IDLE)
+ && mImsMgr != null
+ && mImsMgr.isNonTtyOrTtyOnVolteEnabled()
+ && carrierConfig.getBoolean(
+ CarrierConfigManager.KEY_EDITABLE_ENHANCED_4G_LTE_BOOL);
+ }
+
+ private class MyHandler extends Handler {
+
+ static final int MESSAGE_SET_PREFERRED_NETWORK_TYPE = 0;
+
+ @Override
+ public void handleMessage(Message msg) {
+ switch (msg.what) {
+ case MESSAGE_SET_PREFERRED_NETWORK_TYPE:
+ handleSetPreferredNetworkTypeResponse(msg);
+ break;
+ }
+ }
+
+ private void handleSetPreferredNetworkTypeResponse(Message msg) {
+ final Activity activity = getActivity();
+ if (activity == null || activity.isDestroyed()) {
+ // Access preferences of activity only if it is not destroyed
+ // or if fragment is not attached to an activity.
+ return;
+ }
+
+ boolean success = (boolean) msg.obj;
+
+ if (success) {
+ int networkMode;
+ if (getPreferenceScreen().findPreference(
+ BUTTON_PREFERED_NETWORK_MODE) != null) {
+ networkMode = Integer.parseInt(mButtonPreferredNetworkMode.getValue());
+ android.provider.Settings.Global.putInt(
+ getContext().getContentResolver(),
+ android.provider.Settings.Global.PREFERRED_NETWORK_MODE
+ + mSubId,
+ networkMode );
+ }
+ if (getPreferenceScreen().findPreference(BUTTON_ENABLED_NETWORKS_KEY) != null) {
+ networkMode = Integer.parseInt(mButtonEnabledNetworks.getValue());
+ android.provider.Settings.Global.putInt(
+ getContext().getContentResolver(),
+ android.provider.Settings.Global.PREFERRED_NETWORK_MODE
+ + mSubId,
+ networkMode );
+ }
+ } else {
+ Log.i(LOG_TAG, "handleSetPreferredNetworkTypeResponse:" +
+ "exception in setting network mode.");
+ updatePreferredNetworkUIFromDb();
+ }
+ }
+ }
+
+ private void updatePreferredNetworkUIFromDb() {
+ int settingsNetworkMode = android.provider.Settings.Global.getInt(
+ getContext().getContentResolver(),
+ android.provider.Settings.Global.PREFERRED_NETWORK_MODE + mSubId,
+ preferredNetworkMode);
+
+ if (DBG) {
+ log("updatePreferredNetworkUIFromDb: settingsNetworkMode = " +
+ settingsNetworkMode);
+ }
+
+ UpdatePreferredNetworkModeSummary(settingsNetworkMode);
+ UpdateEnabledNetworksValueAndSummary(settingsNetworkMode);
+ // changes the mButtonPreferredNetworkMode accordingly to settingsNetworkMode
+ mButtonPreferredNetworkMode.setValue(Integer.toString(settingsNetworkMode));
+ }
+
+ private void UpdatePreferredNetworkModeSummary(int NetworkMode) {
+ switch(NetworkMode) {
+ case TelephonyManager.NETWORK_MODE_TDSCDMA_GSM_WCDMA:
+ mButtonPreferredNetworkMode.setSummary(
+ R.string.preferred_network_mode_tdscdma_gsm_wcdma_summary);
+ break;
+ case TelephonyManager.NETWORK_MODE_TDSCDMA_GSM:
+ mButtonPreferredNetworkMode.setSummary(
+ R.string.preferred_network_mode_tdscdma_gsm_summary);
+ break;
+ case TelephonyManager.NETWORK_MODE_WCDMA_PREF:
+ mButtonPreferredNetworkMode.setSummary(
+ R.string.preferred_network_mode_wcdma_perf_summary);
+ break;
+ case TelephonyManager.NETWORK_MODE_GSM_ONLY:
+ mButtonPreferredNetworkMode.setSummary(
+ R.string.preferred_network_mode_gsm_only_summary);
+ break;
+ case TelephonyManager.NETWORK_MODE_TDSCDMA_WCDMA:
+ mButtonPreferredNetworkMode.setSummary(
+ R.string.preferred_network_mode_tdscdma_wcdma_summary);
+ break;
+ case TelephonyManager.NETWORK_MODE_WCDMA_ONLY:
+ mButtonPreferredNetworkMode.setSummary(
+ R.string.preferred_network_mode_wcdma_only_summary);
+ break;
+ case TelephonyManager.NETWORK_MODE_GSM_UMTS:
+ mButtonPreferredNetworkMode.setSummary(
+ R.string.preferred_network_mode_gsm_wcdma_summary);
+ break;
+ case TelephonyManager.NETWORK_MODE_CDMA_EVDO:
+ switch (mTelephonyManager.getLteOnCdmaMode()) {
+ case PhoneConstants.LTE_ON_CDMA_TRUE:
+ mButtonPreferredNetworkMode.setSummary(
+ R.string.preferred_network_mode_cdma_summary);
+ break;
+ case PhoneConstants.LTE_ON_CDMA_FALSE:
+ default:
+ mButtonPreferredNetworkMode.setSummary(
+ R.string.preferred_network_mode_cdma_evdo_summary);
+ break;
+ }
+ break;
+ case TelephonyManager.NETWORK_MODE_CDMA_NO_EVDO:
+ mButtonPreferredNetworkMode.setSummary(
+ R.string.preferred_network_mode_cdma_only_summary);
+ break;
+ case TelephonyManager.NETWORK_MODE_EVDO_NO_CDMA:
+ mButtonPreferredNetworkMode.setSummary(
+ R.string.preferred_network_mode_evdo_only_summary);
+ break;
+ case TelephonyManager.NETWORK_MODE_LTE_TDSCDMA:
+ mButtonPreferredNetworkMode.setSummary(
+ R.string.preferred_network_mode_lte_tdscdma_summary);
+ break;
+ case TelephonyManager.NETWORK_MODE_LTE_ONLY:
+ mButtonPreferredNetworkMode.setSummary(
+ R.string.preferred_network_mode_lte_summary);
+ break;
+ case TelephonyManager.NETWORK_MODE_LTE_TDSCDMA_GSM:
+ mButtonPreferredNetworkMode.setSummary(
+ R.string.preferred_network_mode_lte_tdscdma_gsm_summary);
+ break;
+ case TelephonyManager.NETWORK_MODE_LTE_TDSCDMA_GSM_WCDMA:
+ mButtonPreferredNetworkMode.setSummary(
+ R.string.preferred_network_mode_lte_tdscdma_gsm_wcdma_summary);
+ break;
+ case TelephonyManager.NETWORK_MODE_LTE_GSM_WCDMA:
+ mButtonPreferredNetworkMode.setSummary(
+ R.string.preferred_network_mode_lte_gsm_wcdma_summary);
+ break;
+ case TelephonyManager.NETWORK_MODE_LTE_CDMA_EVDO:
+ mButtonPreferredNetworkMode.setSummary(
+ R.string.preferred_network_mode_lte_cdma_evdo_summary);
+ break;
+ case TelephonyManager.NETWORK_MODE_TDSCDMA_ONLY:
+ mButtonPreferredNetworkMode.setSummary(
+ R.string.preferred_network_mode_tdscdma_summary);
+ break;
+ case TelephonyManager.NETWORK_MODE_LTE_TDSCDMA_CDMA_EVDO_GSM_WCDMA:
+ mButtonPreferredNetworkMode.setSummary(
+ R.string.preferred_network_mode_lte_tdscdma_cdma_evdo_gsm_wcdma_summary);
+ break;
+ case TelephonyManager.NETWORK_MODE_LTE_CDMA_EVDO_GSM_WCDMA:
+ if (mTelephonyManager.getPhoneType() == PhoneConstants.PHONE_TYPE_CDMA
+ || mIsGlobalCdma
+ || isWorldMode()) {
+ mButtonPreferredNetworkMode.setSummary(
+ R.string.preferred_network_mode_global_summary);
+ } else {
+ mButtonPreferredNetworkMode.setSummary(
+ R.string.preferred_network_mode_lte_summary);
+ }
+ break;
+ case TelephonyManager.NETWORK_MODE_TDSCDMA_CDMA_EVDO_GSM_WCDMA:
+ mButtonPreferredNetworkMode.setSummary(
+ R.string.preferred_network_mode_tdscdma_cdma_evdo_gsm_wcdma_summary);
+ break;
+ case TelephonyManager.NETWORK_MODE_GLOBAL:
+ mButtonPreferredNetworkMode.setSummary(
+ R.string.preferred_network_mode_cdma_evdo_gsm_wcdma_summary);
+ break;
+ case TelephonyManager.NETWORK_MODE_LTE_TDSCDMA_WCDMA:
+ mButtonPreferredNetworkMode.setSummary(
+ R.string.preferred_network_mode_lte_tdscdma_wcdma_summary);
+ break;
+ case TelephonyManager.NETWORK_MODE_LTE_WCDMA:
+ mButtonPreferredNetworkMode.setSummary(
+ R.string.preferred_network_mode_lte_wcdma_summary);
+ break;
+ default:
+ mButtonPreferredNetworkMode.setSummary(
+ R.string.preferred_network_mode_global_summary);
+ }
+ }
+
+ private void UpdateEnabledNetworksValueAndSummary(int NetworkMode) {
+ switch (NetworkMode) {
+ case TelephonyManager.NETWORK_MODE_TDSCDMA_WCDMA:
+ case TelephonyManager.NETWORK_MODE_TDSCDMA_GSM_WCDMA:
+ case TelephonyManager.NETWORK_MODE_TDSCDMA_GSM:
+ mButtonEnabledNetworks.setValue(
+ Integer.toString(TelephonyManager.NETWORK_MODE_TDSCDMA_GSM_WCDMA));
+ mButtonEnabledNetworks.setSummary(R.string.network_3G);
+ break;
+ case TelephonyManager.NETWORK_MODE_WCDMA_ONLY:
+ case TelephonyManager.NETWORK_MODE_GSM_UMTS:
+ case TelephonyManager.NETWORK_MODE_WCDMA_PREF:
+ if (!mIsGlobalCdma) {
+ mButtonEnabledNetworks.setValue(
+ Integer.toString(TelephonyManager.NETWORK_MODE_WCDMA_PREF));
+ mButtonEnabledNetworks.setSummary(R.string.network_3G);
+ } else {
+ mButtonEnabledNetworks.setValue(
+ Integer.toString(TelephonyManager
+ .NETWORK_MODE_LTE_CDMA_EVDO_GSM_WCDMA));
+ mButtonEnabledNetworks.setSummary(R.string.network_global);
+ }
+ break;
+ case TelephonyManager.NETWORK_MODE_GSM_ONLY:
+ if (!mIsGlobalCdma) {
+ mButtonEnabledNetworks.setValue(
+ Integer.toString(TelephonyManager.NETWORK_MODE_GSM_ONLY));
+ mButtonEnabledNetworks.setSummary(R.string.network_2G);
+ } else {
+ mButtonEnabledNetworks.setValue(
+ Integer.toString(TelephonyManager
+ .NETWORK_MODE_LTE_CDMA_EVDO_GSM_WCDMA));
+ mButtonEnabledNetworks.setSummary(R.string.network_global);
+ }
+ break;
+ case TelephonyManager.NETWORK_MODE_LTE_GSM_WCDMA:
+ if (isWorldMode()) {
+ mButtonEnabledNetworks.setSummary(
+ R.string.preferred_network_mode_lte_gsm_umts_summary);
+ controlCdmaOptions(false);
+ controlGsmOptions(true);
+ break;
+ }
+ case TelephonyManager.NETWORK_MODE_LTE_ONLY:
+ case TelephonyManager.NETWORK_MODE_LTE_WCDMA:
+ if (!mIsGlobalCdma) {
+ mButtonEnabledNetworks.setValue(
+ Integer.toString(TelephonyManager.NETWORK_MODE_LTE_GSM_WCDMA));
+ mButtonEnabledNetworks.setSummary((mShow4GForLTE == true)
+ ? R.string.network_4G : R.string.network_lte);
+ } else {
+ mButtonEnabledNetworks.setValue(
+ Integer.toString(TelephonyManager
+ .NETWORK_MODE_LTE_CDMA_EVDO_GSM_WCDMA));
+ mButtonEnabledNetworks.setSummary(R.string.network_global);
+ }
+ break;
+ case TelephonyManager.NETWORK_MODE_LTE_CDMA_EVDO:
+ if (isWorldMode()) {
+ mButtonEnabledNetworks.setSummary(
+ R.string.preferred_network_mode_lte_cdma_summary);
+ controlCdmaOptions(true);
+ controlGsmOptions(false);
+ } else {
+ mButtonEnabledNetworks.setValue(
+ Integer.toString(TelephonyManager.NETWORK_MODE_LTE_CDMA_EVDO));
+ mButtonEnabledNetworks.setSummary(R.string.network_lte);
+ }
+ break;
+ case TelephonyManager.NETWORK_MODE_TDSCDMA_CDMA_EVDO_GSM_WCDMA:
+ mButtonEnabledNetworks.setValue(
+ Integer.toString(TelephonyManager
+ .NETWORK_MODE_TDSCDMA_CDMA_EVDO_GSM_WCDMA));
+ mButtonEnabledNetworks.setSummary(R.string.network_3G);
+ break;
+ case TelephonyManager.NETWORK_MODE_CDMA_EVDO:
+ case TelephonyManager.NETWORK_MODE_EVDO_NO_CDMA:
+ case TelephonyManager.NETWORK_MODE_GLOBAL:
+ mButtonEnabledNetworks.setValue(
+ Integer.toString(TelephonyManager.NETWORK_MODE_CDMA_EVDO));
+ mButtonEnabledNetworks.setSummary(R.string.network_3G);
+ break;
+ case TelephonyManager.NETWORK_MODE_CDMA_NO_EVDO:
+ mButtonEnabledNetworks.setValue(
+ Integer.toString(TelephonyManager.NETWORK_MODE_CDMA_NO_EVDO));
+ mButtonEnabledNetworks.setSummary(R.string.network_1x);
+ break;
+ case TelephonyManager.NETWORK_MODE_TDSCDMA_ONLY:
+ mButtonEnabledNetworks.setValue(
+ Integer.toString(TelephonyManager.NETWORK_MODE_TDSCDMA_ONLY));
+ mButtonEnabledNetworks.setSummary(R.string.network_3G);
+ break;
+ case TelephonyManager.NETWORK_MODE_LTE_TDSCDMA_GSM:
+ case TelephonyManager.NETWORK_MODE_LTE_TDSCDMA_GSM_WCDMA:
+ case TelephonyManager.NETWORK_MODE_LTE_TDSCDMA:
+ case TelephonyManager.NETWORK_MODE_LTE_TDSCDMA_WCDMA:
+ case TelephonyManager.NETWORK_MODE_LTE_TDSCDMA_CDMA_EVDO_GSM_WCDMA:
+ case TelephonyManager.NETWORK_MODE_LTE_CDMA_EVDO_GSM_WCDMA:
+ if (isSupportTdscdma()) {
+ mButtonEnabledNetworks.setValue(
+ Integer.toString(TelephonyManager
+ .NETWORK_MODE_LTE_TDSCDMA_CDMA_EVDO_GSM_WCDMA));
+ mButtonEnabledNetworks.setSummary(R.string.network_lte);
+ } else {
+ if (isWorldMode()) {
+ controlCdmaOptions(true);
+ controlGsmOptions(false);
+ }
+ mButtonEnabledNetworks.setValue(
+ Integer.toString(TelephonyManager
+ .NETWORK_MODE_LTE_CDMA_EVDO_GSM_WCDMA));
+ if (mTelephonyManager.getPhoneType() == PhoneConstants.PHONE_TYPE_CDMA
+ || mIsGlobalCdma
+ || isWorldMode()) {
+ mButtonEnabledNetworks.setSummary(R.string.network_global);
+ } else {
+ mButtonEnabledNetworks.setSummary((mShow4GForLTE == true)
+ ? R.string.network_4G : R.string.network_lte);
+ }
+ }
+ break;
+ default:
+ String errMsg = "Invalid Network Mode (" + NetworkMode + "). Ignore.";
+ loge(errMsg);
+ mButtonEnabledNetworks.setSummary(errMsg);
+ }
+ }
+
+ @Override
+ public void onActivityResult(int requestCode, int resultCode, Intent data) {
+ switch(requestCode) {
+ case REQUEST_CODE_EXIT_ECM:
+ Boolean isChoiceYes = data.getBooleanExtra(
+ EmergencyCallbackModeExitDialog.EXTRA_EXIT_ECM_RESULT, false);
+ if (isChoiceYes) {
+ // If the phone exits from ECM mode, show the CDMA Options
+ mCdmaOptions.showDialog(mClickedPreference);
+ } else {
+ // do nothing
+ }
+ break;
+
+ default:
+ break;
+ }
+ }
+
+ private void updateWiFiCallState() {
+ if (mWiFiCallingPref == null || mCallingCategory == null) {
+ return;
+ }
+
+ // Removes the preference if the wifi calling is disabled.
+ if (!isWifiCallingEnabled(getContext(), SubscriptionManager.getPhoneId(mSubId))) {
+ mCallingCategory.removePreference(mWiFiCallingPref);
+ return;
+ }
+
+ final PhoneAccountHandle simCallManager =
+ TelecomManager.from(getContext()).getSimCallManager();
+
+ if (simCallManager != null) {
+ Intent intent = MobileNetworkSettings.buildPhoneAccountConfigureIntent(
+ getContext(), simCallManager);
+ PackageManager pm = getContext().getPackageManager();
+ List<ResolveInfo> resolutions = pm.queryIntentActivities(intent, 0);
+ mWiFiCallingPref.setTitle(resolutions.get(0).loadLabel(pm));
+ mWiFiCallingPref.setSummary(null);
+ mWiFiCallingPref.setIntent(intent);
+ } else {
+ int resId = com.android.internal.R.string.wifi_calling_off_summary;
+ if (mImsMgr.isWfcEnabledByUser()) {
+ boolean isRoaming = mTelephonyManager.isNetworkRoaming();
+ int wfcMode = mImsMgr.getWfcMode(isRoaming);
+
+ switch (wfcMode) {
+ case ImsConfig.WfcModeFeatureValueConstants.WIFI_ONLY:
+ resId = com.android.internal.R.string.wfc_mode_wifi_only_summary;
+ break;
+ case ImsConfig.WfcModeFeatureValueConstants.CELLULAR_PREFERRED:
+ resId = com.android.internal.R.string
+ .wfc_mode_cellular_preferred_summary;
+ break;
+ case ImsConfig.WfcModeFeatureValueConstants.WIFI_PREFERRED:
+ resId = com.android.internal.R.string.wfc_mode_wifi_preferred_summary;
+ break;
+ default:
+ if (DBG) log("Unexpected WFC mode value: " + wfcMode);
+ }
+ }
+ mWiFiCallingPref.setSummary(resId);
+ }
+
+ mCallingCategory.addPreference(mWiFiCallingPref);
+ mWiFiCallingPref.setEnabled(mTelephonyManager.getCallState(mSubId)
+ == TelephonyManager.CALL_STATE_IDLE && hasActiveSubscriptions());
+ }
+
+ private void updateEnhanced4gLteState() {
+ if (mButton4glte == null) {
+ return;
+ }
+
+ PersistableBundle carrierConfig = mCarrierConfigManager.getConfigForSubId(mSubId);
+
+ if ((mImsMgr == null
+ || !mImsMgr.isVolteEnabledByPlatform()
+ || !mImsMgr.isVolteProvisionedOnDevice()
+ || !isImsServiceStateReady(mImsMgr)
+ || carrierConfig.getBoolean(
+ CarrierConfigManager.KEY_HIDE_ENHANCED_4G_LTE_BOOL))) {
+ getPreferenceScreen().removePreference(mButton4glte);
+ } else {
+ mButton4glte.setEnabled(is4gLtePrefEnabled(carrierConfig)
+ && hasActiveSubscriptions());
+ boolean enh4glteMode = mImsMgr.isEnhanced4gLteModeSettingEnabledByUser()
+ && mImsMgr.isNonTtyOrTtyOnVolteEnabled();
+ mButton4glte.setChecked(enh4glteMode);
+ }
+ }
+
+ private void updateVideoCallState() {
+ if (mVideoCallingPref == null || mCallingCategory == null) {
+ return;
+ }
+
+ PersistableBundle carrierConfig = mCarrierConfigManager.getConfigForSubId(mSubId);
+
+ if (mImsMgr != null
+ && mImsMgr.isVtEnabledByPlatform()
+ && mImsMgr.isVtProvisionedOnDevice()
+ && isImsServiceStateReady(mImsMgr)
+ && (carrierConfig.getBoolean(
+ CarrierConfigManager.KEY_IGNORE_DATA_ENABLED_CHANGED_FOR_VIDEO_CALLS)
+ || mTelephonyManager.isDataEnabled())) {
+ mCallingCategory.addPreference(mVideoCallingPref);
+ if (!mButton4glte.isChecked()) {
+ mVideoCallingPref.setEnabled(false);
+ mVideoCallingPref.setChecked(false);
+ } else {
+ mVideoCallingPref.setEnabled(mTelephonyManager.getCallState(mSubId)
+ == TelephonyManager.CALL_STATE_IDLE && hasActiveSubscriptions());
+ mVideoCallingPref.setChecked(mImsMgr.isVtEnabledByUser());
+ mVideoCallingPref.setOnPreferenceChangeListener(this);
+ }
+ } else {
+ mCallingCategory.removePreference(mVideoCallingPref);
+ }
+ }
+
+ private void updatePreferredNetworkType() {
+ boolean enabled = mTelephonyManager.getCallState(
+ mSubId) == TelephonyManager.CALL_STATE_IDLE
+ && hasActiveSubscriptions();
+ Log.i(LOG_TAG, "updatePreferredNetworkType: " + enabled);
+ // TODO: Disentangle enabled networks vs preferred network mode, it looks like
+ // both buttons are shown to the user as "Preferred network type" and the options change
+ // based on what looks like World mode.
+ if (mButtonEnabledNetworks != null) {
+ mButtonEnabledNetworks.setEnabled(enabled);
+ }
+ if (mButtonPreferredNetworkMode != null) {
+ mButtonPreferredNetworkMode.setEnabled(enabled);
+ }
+ }
+
+ private void updateCallingCategory() {
+ if (mCallingCategory == null) {
+ return;
+ }
+
+ updateWiFiCallState();
+ updateVideoCallState();
+
+ // If all items in calling category is removed, we remove it from
+ // the screen. Otherwise we'll see title of the category but nothing
+ // is in there.
+ if (mCallingCategory.getPreferenceCount() == 0) {
+ getPreferenceScreen().removePreference(mCallingCategory);
+ } else {
+ getPreferenceScreen().addPreference(mCallingCategory);
+ }
+ }
+
+ private static void log(String msg) {
+ Log.d(LOG_TAG, msg);
+ }
+
+ private static void loge(String msg) {
+ Log.e(LOG_TAG, msg);
+ }
+
+ @Override
+ public boolean onOptionsItemSelected(MenuItem item) {
+ final int itemId = item.getItemId();
+ if (itemId == android.R.id.home) { // See ActionBar#setDisplayHomeAsUpEnabled()
+ // Commenting out "logical up" capability. This is a workaround for issue 5278083.
+ //
+ // Settings app may not launch this activity via UP_ACTIVITY_CLASS but the other
+ // Activity that looks exactly same as UP_ACTIVITY_CLASS ("SubSettings" Activity).
+ // At that moment, this Activity launches UP_ACTIVITY_CLASS on top of the Activity.
+ // which confuses users.
+ // TODO: introduce better mechanism for "up" capability here.
+ /*Intent intent = new Intent(Intent.ACTION_MAIN);
+ intent.setClassName(UP_ACTIVITY_PACKAGE, UP_ACTIVITY_CLASS);
+ intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
+ startActivity(intent);*/
+ getActivity().finish();
+ return true;
+ }
+ return super.onOptionsItemSelected(item);
+ }
+
+ private boolean isWorldMode() {
+ boolean worldModeOn = false;
+ final String configString = getResources().getString(R.string.config_world_mode);
+
+ if (!TextUtils.isEmpty(configString)) {
+ String[] configArray = configString.split(";");
+ // Check if we have World mode configuration set to True only or config is set to True
+ // and SIM GID value is also set and matches to the current SIM GID.
+ if (configArray != null &&
+ ((configArray.length == 1 && configArray[0].equalsIgnoreCase("true"))
+ || (configArray.length == 2 && !TextUtils.isEmpty(configArray[1])
+ && mTelephonyManager != null
+ && configArray[1].equalsIgnoreCase(
+ mTelephonyManager.getGroupIdLevel1())))) {
+ worldModeOn = true;
+ }
+ }
+
+ Log.d(LOG_TAG, "isWorldMode=" + worldModeOn);
+
+ return worldModeOn;
+ }
+
+ private void controlGsmOptions(boolean enable) {
+ PreferenceScreen prefSet = getPreferenceScreen();
+ if (prefSet == null) {
+ return;
+ }
+
+ updateGsmUmtsOptions(this, prefSet, mSubId);
+
+ PreferenceCategory networkOperatorCategory =
+ (PreferenceCategory) prefSet.findPreference(
+ com.android.phone.NetworkOperators.CATEGORY_NETWORK_OPERATORS_KEY);
+ Preference carrierSettings = prefSet.findPreference(BUTTON_CARRIER_SETTINGS_KEY);
+ if (networkOperatorCategory != null) {
+ if (enable) {
+ networkOperatorCategory.setEnabled(true);
+ } else {
+ prefSet.removePreference(networkOperatorCategory);
+ }
+ }
+ if (carrierSettings != null) {
+ prefSet.removePreference(carrierSettings);
+ }
+ }
+
+ private void controlCdmaOptions(boolean enable) {
+ PreferenceScreen prefSet = getPreferenceScreen();
+ if (prefSet == null) {
+ return;
+ }
+ updateCdmaOptions(this, prefSet, mSubId);
+ com.android.phone.CdmaSystemSelectListPreference systemSelect =
+ (CdmaSystemSelectListPreference)prefSet.findPreference
+ (BUTTON_CDMA_SYSTEM_SELECT_KEY);
+ systemSelect.setSubscriptionId(mSubId);
+ if (systemSelect != null) {
+ systemSelect.setEnabled(enable);
+ }
+ }
+
+ private boolean isSupportTdscdma() {
+ if (getResources().getBoolean(R.bool.config_support_tdscdma)) {
+ return true;
+ }
+
+ String operatorNumeric = mTelephonyManager.getServiceState().getOperatorNumeric();
+ String[] numericArray = getResources().getStringArray(
+ R.array.config_support_tdscdma_roaming_on_networks);
+ if (numericArray.length == 0 || operatorNumeric == null) {
+ return false;
+ }
+ for (String numeric : numericArray) {
+ if (operatorNumeric.equals(numeric)) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ /**
+ * Metrics events related methods. it takes care of all preferences possible in this
+ * fragment(except a few that log on their own). It doesn't only include preferences in
+ * network_setting_fragment.xml, but also those defined in GsmUmtsOptions and CdmaOptions.
+ */
+ private void sendMetricsEventPreferenceClicked(
+ PreferenceScreen preferenceScreen, Preference preference) {
+ final int category = getMetricsEventCategory(preferenceScreen, preference);
+ if (category == MetricsProto.MetricsEvent.VIEW_UNKNOWN) {
+ return;
+ }
+
+ // Send MetricsEvent on click. It includes preferences other than SwitchPreferences,
+ // which send MetricsEvent in onPreferenceChange.
+ // For ListPreferences, we log it here without a value, only indicating it's clicked to
+ // open the list dialog. When a value is chosen, another MetricsEvent is logged with
+ // new value in onPreferenceChange.
+ if (preference == mLteDataServicePref || preference == mDataUsagePref
+ || preference == mEuiccSettingsPref || preference == mAdvancedOptions
+ || preference == mWiFiCallingPref || preference == mButtonPreferredNetworkMode
+ || preference == mButtonEnabledNetworks
+ || preference == preferenceScreen.findPreference(BUTTON_CDMA_SYSTEM_SELECT_KEY)
+ || preference == preferenceScreen.findPreference(BUTTON_CDMA_SUBSCRIPTION_KEY)
+ || preference == preferenceScreen.findPreference(BUTTON_GSM_APN_EXPAND_KEY)
+ || preference == preferenceScreen.findPreference(BUTTON_CDMA_APN_EXPAND_KEY)
+ || preference == preferenceScreen.findPreference(BUTTON_CARRIER_SETTINGS_KEY)) {
+ MetricsLogger.action(getContext(), category);
+ }
+ }
+
+ private void sendMetricsEventPreferenceChanged(
+ PreferenceScreen preferenceScreen, Preference preference, Object newValue) {
+ final int category = getMetricsEventCategory(preferenceScreen, preference);
+ if (category == MetricsProto.MetricsEvent.VIEW_UNKNOWN) {
+ return;
+ }
+
+ // MetricsEvent logging with new value, for SwitchPreferences and ListPreferences.
+ if (preference == mButton4glte || preference == mVideoCallingPref) {
+ MetricsLogger.action(getContext(), category, (Boolean) newValue);
+ } else if (preference == mButtonPreferredNetworkMode
+ || preference == mButtonEnabledNetworks
+ || preference == preferenceScreen
+ .findPreference(BUTTON_CDMA_SYSTEM_SELECT_KEY)
+ || preference == preferenceScreen
+ .findPreference(BUTTON_CDMA_SUBSCRIPTION_KEY)) {
+ // Network select preference sends metrics event in its own listener.
+ MetricsLogger.action(getContext(), category, Integer.valueOf((String) newValue));
+ }
+ }
+
+ private int getMetricsEventCategory(
+ PreferenceScreen preferenceScreen, Preference preference) {
+
+ if (preference == null) {
+ return MetricsProto.MetricsEvent.VIEW_UNKNOWN;
+ } else if (preference == mMobileDataPref) {
+ return MetricsProto.MetricsEvent.ACTION_MOBILE_NETWORK_MOBILE_DATA_TOGGLE;
+ } else if (preference == mButtonDataRoam) {
+ return MetricsProto.MetricsEvent.ACTION_MOBILE_NETWORK_DATA_ROAMING_TOGGLE;
+ } else if (preference == mDataUsagePref) {
+ return MetricsProto.MetricsEvent.ACTION_MOBILE_NETWORK_DATA_USAGE;
+ } else if (preference == mLteDataServicePref) {
+ return MetricsProto.MetricsEvent.ACTION_MOBILE_NETWORK_SET_UP_DATA_SERVICE;
+ } else if (preference == mAdvancedOptions) {
+ return MetricsProto.MetricsEvent.ACTION_MOBILE_NETWORK_EXPAND_ADVANCED_FIELDS;
+ } else if (preference == mButton4glte) {
+ return MetricsProto.MetricsEvent.ACTION_MOBILE_ENHANCED_4G_LTE_MODE_TOGGLE;
+ } else if (preference == mButtonPreferredNetworkMode) {
+ return MetricsProto.MetricsEvent.ACTION_MOBILE_NETWORK_SELECT_PREFERRED_NETWORK;
+ } else if (preference == mButtonEnabledNetworks) {
+ return MetricsProto.MetricsEvent.ACTION_MOBILE_NETWORK_SELECT_ENABLED_NETWORK;
+ } else if (preference == mEuiccSettingsPref) {
+ return MetricsProto.MetricsEvent.ACTION_MOBILE_NETWORK_EUICC_SETTING;
+ } else if (preference == mWiFiCallingPref) {
+ return MetricsProto.MetricsEvent.ACTION_MOBILE_NETWORK_WIFI_CALLING;
+ } else if (preference == mVideoCallingPref) {
+ return MetricsProto.MetricsEvent.ACTION_MOBILE_NETWORK_VIDEO_CALLING_TOGGLE;
+ } else if (preference == preferenceScreen
+ .findPreference(com.android.phone.NetworkOperators.BUTTON_AUTO_SELECT_KEY)) {
+ return MetricsProto.MetricsEvent.ACTION_MOBILE_NETWORK_AUTO_SELECT_NETWORK_TOGGLE;
+ } else if (preference == preferenceScreen
+ .findPreference(NetworkOperators.BUTTON_NETWORK_SELECT_KEY)) {
+ return MetricsProto.MetricsEvent.ACTION_MOBILE_NETWORK_MANUAL_SELECT_NETWORK;
+ } else if (preference == preferenceScreen
+ .findPreference(BUTTON_CDMA_SYSTEM_SELECT_KEY)) {
+ return MetricsProto.MetricsEvent.ACTION_MOBILE_NETWORK_CDMA_SYSTEM_SELECT;
+ } else if (preference == preferenceScreen
+ .findPreference(BUTTON_CDMA_SUBSCRIPTION_KEY)) {
+ return MetricsProto.MetricsEvent.ACTION_MOBILE_NETWORK_CDMA_SUBSCRIPTION_SELECT;
+ } else if (preference == preferenceScreen.findPreference(BUTTON_GSM_APN_EXPAND_KEY)
+ || preference == preferenceScreen.findPreference(BUTTON_CDMA_APN_EXPAND_KEY)) {
+ return MetricsProto.MetricsEvent.ACTION_MOBILE_NETWORK_APN_SETTINGS;
+ } else if (preference == preferenceScreen.findPreference(BUTTON_CARRIER_SETTINGS_KEY)) {
+ return MetricsProto.MetricsEvent.ACTION_MOBILE_NETWORK_CARRIER_SETTINGS;
+ } else {
+ return MetricsProto.MetricsEvent.VIEW_UNKNOWN;
+ }
+ }
+
+ private void updateGsmUmtsOptions(PreferenceFragment prefFragment,
+ PreferenceScreen prefScreen, final int subId) {
+ // We don't want to re-create GsmUmtsOptions if already exists. Otherwise, the
+ // preferences inside it will also be re-created which causes unexpected behavior.
+ // For example, the open dialog gets dismissed or detached after pause / resume.
+ if (mGsmUmtsOptions == null) {
+ mGsmUmtsOptions = new GsmUmtsOptions(prefFragment, prefScreen, subId);
+ } else {
+ mGsmUmtsOptions.update(subId);
+ }
+ }
+
+ private void updateCdmaOptions(PreferenceFragment prefFragment, PreferenceScreen prefScreen,
+ int subId) {
+ // We don't want to re-create CdmaOptions if already exists. Otherwise, the preferences
+ // inside it will also be re-created which causes unexpected behavior. For example,
+ // the open dialog gets dismissed or detached after pause / resume.
+ if (mCdmaOptions == null) {
+ mCdmaOptions = new CdmaOptions(prefFragment, prefScreen, subId);
+ } else {
+ mCdmaOptions.updateSubscriptionId(subId);
+ }
+ }
+}
+
+private static final class SetPreferredNetworkAsyncTask extends AsyncTask<Void, Void, Boolean> {
+
+ private final TelephonyManager mTelephonyManager;
+ private final int mSubId;
+ private final int mNetworkType;
+ private final Message mCallback;
+
+ SetPreferredNetworkAsyncTask(
+ TelephonyManager tm, int subId, int networkType, Message callback) {
+ mTelephonyManager = tm;
+ mSubId = subId;
+ mNetworkType = networkType;
+ mCallback = callback;
+ }
+
+ @Override
+ protected Boolean doInBackground(Void... voids) {
+ return mTelephonyManager.setPreferredNetworkType(mSubId, mNetworkType);
+ }
+
+ @Override
+ protected void onPostExecute(Boolean isSuccessed) {
+ mCallback.obj = isSuccessed;
+ mCallback.sendToTarget();
+ }
+}
\ No newline at end of file
diff --git a/src/com/android/settings/mobilenetwork/NetworkOperators.java b/src/com/android/settings/mobilenetwork/NetworkOperators.java
new file mode 100644
index 0000000..b07a170
--- /dev/null
+++ b/src/com/android/settings/mobilenetwork/NetworkOperators.java
@@ -0,0 +1,299 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.settings.mobilenetwork;
+
+import android.app.ProgressDialog;
+import android.content.Context;
+import android.content.Intent;
+import android.os.Handler;
+import android.os.Message;
+import android.preference.Preference;
+import android.preference.PreferenceCategory;
+import android.preference.TwoStatePreference;
+import android.telephony.ServiceState;
+import android.telephony.SubscriptionManager;
+import android.telephony.TelephonyManager;
+import android.util.AttributeSet;
+import android.util.Log;
+import android.widget.Toast;
+
+import com.android.internal.logging.MetricsLogger;
+import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
+import com.android.phone.NetworkSelectSettingActivity;
+import com.android.settingslib.utils.ThreadUtils;
+
+/**
+ * "Networks" settings UI for the Phone app.
+ */
+public class NetworkOperators extends PreferenceCategory
+ implements Preference.OnPreferenceChangeListener {
+
+ private static final String LOG_TAG = "NetworkOperators";
+ private static final boolean DBG = true;
+
+ private static final int EVENT_AUTO_SELECT_DONE = 100;
+ private static final int EVENT_GET_NETWORK_SELECTION_MODE_DONE = 200;
+
+ //String keys for preference lookup
+ public static final String BUTTON_NETWORK_SELECT_KEY = "button_network_select_key";
+ public static final String BUTTON_AUTO_SELECT_KEY = "button_auto_select_key";
+ public static final String BUTTON_CHOOSE_NETWORK_KEY = "button_choose_network_key";
+ public static final String CATEGORY_NETWORK_OPERATORS_KEY = "network_operators_category_key";
+
+ //preference objects
+ private NetworkSelectListPreference mNetworkSelect;
+ private TwoStatePreference mAutoSelect;
+ private Preference mChooseNetwork;
+ private ProgressDialog mProgressDialog;
+
+ private int mSubId;
+ private TelephonyManager mTelephonyManager;
+
+ // There's two sets of Auto-Select UI in this class.
+ // If {@code com.android.internal.R.bool.config_enableNewAutoSelectNetworkUI} set as true
+ // {@link mChooseNetwork} will be used, otherwise {@link mNetworkSelect} will be used.
+ boolean mEnableNewManualSelectNetworkUI;
+
+ public NetworkOperators(Context context, AttributeSet attrs) {
+ super(context, attrs);
+ }
+
+ public NetworkOperators(Context context) {
+ super(context);
+ }
+
+ /**
+ * Initialize NetworkOperators instance.
+ */
+ public void initialize() {
+ mEnableNewManualSelectNetworkUI = getContext().getResources().getBoolean(
+ com.android.internal.R.bool.config_enableNewAutoSelectNetworkUI);
+ mAutoSelect = (TwoStatePreference) findPreference(BUTTON_AUTO_SELECT_KEY);
+ mChooseNetwork = findPreference(BUTTON_CHOOSE_NETWORK_KEY);
+ mNetworkSelect = (NetworkSelectListPreference) findPreference(BUTTON_NETWORK_SELECT_KEY);
+ if (mEnableNewManualSelectNetworkUI) {
+ removePreference(mNetworkSelect);
+ } else {
+ removePreference(mChooseNetwork);
+ }
+ mProgressDialog = new ProgressDialog(getContext());
+ mTelephonyManager = TelephonyManager.from(getContext());
+ }
+
+ /**
+ * Update NetworkOperators instance if like subId is updated.
+ *
+ * @param subId Corresponding subscription ID of this network.
+ */
+ protected void update(final int subId) {
+ mSubId = subId;
+ mTelephonyManager = TelephonyManager.from(getContext()).createForSubscriptionId(mSubId);
+
+ if (mAutoSelect != null) {
+ mAutoSelect.setOnPreferenceChangeListener(this);
+ }
+
+ if (mEnableNewManualSelectNetworkUI) {
+ if (mChooseNetwork != null) {
+ ServiceState ss = mTelephonyManager.getServiceState();
+ if (ss != null && ss.getState() == ServiceState.STATE_IN_SERVICE) {
+ mChooseNetwork.setSummary(mTelephonyManager.getNetworkOperatorName());
+ } else {
+ mChooseNetwork.setSummary(R.string.network_disconnected);
+ }
+ }
+ } else {
+ if (mNetworkSelect != null) {
+ mNetworkSelect.initialize(mSubId, this, mProgressDialog);
+ }
+ }
+ getNetworkSelectionMode();
+ }
+
+ /**
+ * Implemented to support onPreferenceChangeListener to look for preference
+ * changes specifically on auto select button.
+ *
+ * @param preference is the preference to be changed, should be auto select button.
+ * @param newValue should be the value of whether autoSelect is checked.
+ */
+ @Override
+ public boolean onPreferenceChange(Preference preference, Object newValue) {
+ if (preference == mAutoSelect) {
+ boolean autoSelect = (Boolean) newValue;
+ if (DBG) logd("onPreferenceChange autoSelect: " + String.valueOf(autoSelect));
+ selectNetworkAutomatic(autoSelect);
+ MetricsLogger.action(getContext(),
+ MetricsEvent.ACTION_MOBILE_NETWORK_AUTO_SELECT_NETWORK_TOGGLE, autoSelect);
+ return true;
+ }
+ return false;
+ }
+
+ private final Handler mHandler = new Handler() {
+ @Override
+ public void handleMessage(Message msg) {
+ switch (msg.what) {
+ case EVENT_AUTO_SELECT_DONE:
+ mAutoSelect.setEnabled(true);
+ dismissProgressBar();
+
+ boolean isSuccessed = (boolean) msg.obj;
+
+ if (isSuccessed) {
+ if (DBG) logd("automatic network selection: succeeded!");
+ displayNetworkSelectionSucceeded();
+ } else {
+ if (DBG) logd("automatic network selection: failed!");
+ displayNetworkSelectionFailed();
+ }
+
+ break;
+ case EVENT_GET_NETWORK_SELECTION_MODE_DONE:
+ int networkSelectionMode = msg.arg1;
+ if (networkSelectionMode == TelephonyManager.NETWORK_SELECTION_MODE_UNKNOWN) {
+ if (DBG) logd("get network selection mode: failed!");
+ } else {
+ boolean autoSelect = networkSelectionMode
+ == TelephonyManager.NETWORK_SELECTION_MODE_AUTO;
+ if (DBG) {
+ logd("get network selection mode: "
+ + (autoSelect ? "auto" : "manual") + " selection");
+ }
+ if (mAutoSelect != null) {
+ mAutoSelect.setChecked(autoSelect);
+ }
+ if (mEnableNewManualSelectNetworkUI) {
+ if (mChooseNetwork != null) {
+ mChooseNetwork.setEnabled(!autoSelect);
+ }
+ } else {
+ if (mNetworkSelect != null) {
+ mNetworkSelect.setEnabled(!autoSelect);
+ }
+ }
+ }
+ }
+ return;
+ }
+ };
+
+ // Used by both mAutoSelect and mNetworkSelect buttons.
+ protected void displayNetworkSelectionFailed() {
+ Toast.makeText(getContext(), R.string.connect_later, Toast.LENGTH_LONG).show();
+ }
+
+ // Used by both mAutoSelect and mNetworkSelect buttons.
+ protected void displayNetworkSelectionSucceeded() {
+ Toast.makeText(getContext(), R.string.registration_done, Toast.LENGTH_LONG).show();
+ }
+
+ private void selectNetworkAutomatic(boolean autoSelect) {
+ if (DBG) logd("selectNetworkAutomatic: " + String.valueOf(autoSelect));
+
+ if (autoSelect) {
+ if (mEnableNewManualSelectNetworkUI) {
+ if (mChooseNetwork != null) {
+ mChooseNetwork.setEnabled(!autoSelect);
+ }
+ } else {
+ if (mNetworkSelect != null) {
+ mNetworkSelect.setEnabled(!autoSelect);
+ }
+ }
+ if (DBG) logd("select network automatically...");
+ showAutoSelectProgressBar();
+ mAutoSelect.setEnabled(false);
+ if (SubscriptionManager.isValidSubscriptionId(mSubId)) {
+ ThreadUtils.postOnBackgroundThread(() -> {
+ mTelephonyManager.setNetworkSelectionModeAutomatic();
+ // Because TelephonyManager#setNetworkSelectionModeAutomatic doesn't have a
+ // return value, we query the current network selection mode to tell if the
+ // TelephonyManager#setNetworkSelectionModeAutomatic is successed.
+ int networkSelectionMode = mTelephonyManager.getNetworkSelectionMode();
+ Message msg = mHandler.obtainMessage(EVENT_AUTO_SELECT_DONE);
+ msg.obj = networkSelectionMode == TelephonyManager.NETWORK_SELECTION_MODE_AUTO;
+ msg.sendToTarget();
+ });
+ }
+ } else {
+ if (mEnableNewManualSelectNetworkUI) {
+ if (mChooseNetwork != null) {
+ // Open the choose Network page automatically when user turn off the auto-select
+ openChooseNetworkPage();
+ }
+ } else {
+ if (mNetworkSelect != null) {
+ mNetworkSelect.onClick();
+ }
+ }
+ }
+ }
+
+ protected void getNetworkSelectionMode() {
+ if (DBG) logd("getting network selection mode...");
+ ThreadUtils.postOnBackgroundThread(() -> {
+ int networkSelectionMode = mTelephonyManager.getNetworkSelectionMode();
+ Message msg = mHandler.obtainMessage(EVENT_GET_NETWORK_SELECTION_MODE_DONE);
+ msg.arg1 = networkSelectionMode;
+ msg.sendToTarget();
+ });
+ }
+
+ private void dismissProgressBar() {
+ if (mProgressDialog != null && mProgressDialog.isShowing()) {
+ mProgressDialog.dismiss();
+ }
+ }
+
+ private void showAutoSelectProgressBar() {
+ mProgressDialog.setMessage(
+ getContext().getResources().getString(R.string.register_automatically));
+ mProgressDialog.setCanceledOnTouchOutside(false);
+ mProgressDialog.setCancelable(false);
+ mProgressDialog.setIndeterminate(true);
+ mProgressDialog.show();
+ }
+
+ /**
+ * Open the Choose network page via {@alink NetworkSelectSettingActivity}
+ */
+ public void openChooseNetworkPage() {
+ Intent intent = NetworkSelectSettingActivity.getIntent(getContext(), mSubId);
+ getContext().startActivity(intent);
+ }
+
+ protected boolean preferenceTreeClick(Preference preference) {
+ if (mEnableNewManualSelectNetworkUI) {
+ if (DBG) logd("enable New AutoSelectNetwork UI");
+ if (preference == mChooseNetwork) {
+ openChooseNetworkPage();
+ }
+ return (preference == mAutoSelect || preference == mChooseNetwork);
+ } else {
+ return (preference == mAutoSelect || preference == mNetworkSelect);
+ }
+ }
+
+ private void logd(String msg) {
+ Log.d(LOG_TAG, "[NetworksList] " + msg);
+ }
+
+ private void loge(String msg) {
+ Log.e(LOG_TAG, "[NetworksList] " + msg);
+ }
+}
diff --git a/src/com/android/settings/mobilenetwork/NetworkScanHelper.java b/src/com/android/settings/mobilenetwork/NetworkScanHelper.java
new file mode 100644
index 0000000..59908bc
--- /dev/null
+++ b/src/com/android/settings/mobilenetwork/NetworkScanHelper.java
@@ -0,0 +1,287 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.settings.mobilenetwork;
+
+import android.annotation.IntDef;
+import android.telephony.AccessNetworkConstants.AccessNetworkType;
+import android.telephony.CellInfo;
+import android.telephony.NetworkScan;
+import android.telephony.NetworkScanRequest;
+import android.telephony.RadioAccessSpecifier;
+import android.telephony.TelephonyManager;
+import android.telephony.TelephonyScanManager;
+import android.util.Log;
+
+import com.android.internal.telephony.CellNetworkScanResult;
+import com.android.phone.CellInfoUtil;
+
+import com.google.common.util.concurrent.FutureCallback;
+import com.google.common.util.concurrent.Futures;
+import com.google.common.util.concurrent.ListenableFuture;
+import com.google.common.util.concurrent.SettableFuture;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.util.List;
+import java.util.concurrent.Executor;
+import java.util.stream.Collectors;
+
+/**
+ * A helper class that builds the common interface and performs the network scan for two different
+ * network scan APIs.
+ */
+public class NetworkScanHelper {
+ public static final String TAG = "NetworkScanHelper";
+ private static final boolean DBG = true;
+
+ /**
+ * Callbacks interface to inform the network scan results.
+ */
+ public interface NetworkScanCallback {
+ /**
+ * Called when the results is returned from {@link TelephonyManager}. This method will be
+ * called at least one time if there is no error occurred during the network scan.
+ *
+ * <p> This method can be called multiple times in one network scan, until
+ * {@link #onComplete()} or {@link #onError(int)} is called.
+ *
+ * @param results
+ */
+ void onResults(List<CellInfo> results);
+
+ /**
+ * Called when the current network scan process is finished. No more
+ * {@link #onResults(List)} will be called for the current network scan after this method is
+ * called.
+ */
+ void onComplete();
+
+ /**
+ * Called when an error occurred during the network scan process.
+ *
+ * <p> There is no more result returned from {@link TelephonyManager} if an error occurred.
+ *
+ * <p> {@link #onComplete()} will not be called if an error occurred.
+ *
+ * @see {@link NetworkScan.ScanErrorCode}
+ */
+ void onError(int errorCode);
+ }
+
+ @Retention(RetentionPolicy.SOURCE)
+ @IntDef({NETWORK_SCAN_TYPE_WAIT_FOR_ALL_RESULTS, NETWORK_SCAN_TYPE_INCREMENTAL_RESULTS})
+ public @interface NetworkQueryType {}
+
+ /**
+ * Performs the network scan using {@link TelephonyManager#getAvailableNetworks()}. The network
+ * scan results won't be returned to the caller until the network scan is completed.
+ *
+ * <p> This is typically used when the modem doesn't support the new network scan api
+ * {@link TelephonyManager#requestNetworkScan(
+ * NetworkScanRequest, Executor, TelephonyScanManager.NetworkScanCallback)}.
+ */
+ public static final int NETWORK_SCAN_TYPE_WAIT_FOR_ALL_RESULTS = 1;
+
+ /**
+ * Performs the network scan using {@link TelephonyManager#requestNetworkScan(
+ * NetworkScanRequest, Executor, TelephonyScanManager.NetworkScanCallback)} The network scan
+ * results will be returned to the caller periodically in a small time window until the network
+ * scan is completed. The complete results should be returned in the last called of
+ * {@link NetworkScanCallback#onResults(List)}.
+ *
+ * <p> This is recommended to be used if modem supports the new network scan api
+ * {@link TelephonyManager#requestNetworkScan(
+ * NetworkScanRequest, Executor, TelephonyScanManager.NetworkScanCallback)}
+ */
+ public static final int NETWORK_SCAN_TYPE_INCREMENTAL_RESULTS = 2;
+
+ /** The constants below are used in the async network scan. */
+ private static final boolean INCREMENTAL_RESULTS = true;
+ private static final int SEARCH_PERIODICITY_SEC = 5;
+ private static final int MAX_SEARCH_TIME_SEC = 300;
+ private static final int INCREMENTAL_RESULTS_PERIODICITY_SEC = 3;
+
+ private static final NetworkScanRequest NETWORK_SCAN_REQUEST =
+ new NetworkScanRequest(
+ NetworkScanRequest.SCAN_TYPE_ONE_SHOT,
+ new RadioAccessSpecifier[]{
+ // GSM
+ new RadioAccessSpecifier(
+ AccessNetworkType.GERAN,
+ null /* bands */,
+ null /* channels */),
+ // LTE
+ new RadioAccessSpecifier(
+ AccessNetworkType.EUTRAN,
+ null /* bands */,
+ null /* channels */),
+ // WCDMA
+ new RadioAccessSpecifier(
+ AccessNetworkType.UTRAN,
+ null /* bands */,
+ null /* channels */)
+ },
+ SEARCH_PERIODICITY_SEC,
+ MAX_SEARCH_TIME_SEC,
+ INCREMENTAL_RESULTS,
+ INCREMENTAL_RESULTS_PERIODICITY_SEC,
+ null /* List of PLMN ids (MCC-MNC) */);
+
+ private final NetworkScanCallback mNetworkScanCallback;
+ private final TelephonyManager mTelephonyManager;
+ private final TelephonyScanManager.NetworkScanCallback mInternalNetworkScanCallback;
+ private final Executor mExecutor;
+
+ private NetworkScan mNetworkScanRequester;
+
+ /** Callbacks for sync network scan */
+ private ListenableFuture<List<CellInfo>> mNetworkScanFuture;
+
+ public NetworkScanHelper(TelephonyManager tm, NetworkScanCallback callback, Executor executor) {
+ mTelephonyManager = tm;
+ mNetworkScanCallback = callback;
+ mInternalNetworkScanCallback = new NetworkScanCallbackImpl();
+ mExecutor = executor;
+ }
+
+ /**
+ * Performs a network scan for the given type {@code type}.
+ * {@link #NETWORK_SCAN_TYPE_INCREMENTAL_RESULTS} is recommended if modem supports
+ * {@link TelephonyManager#requestNetworkScan(
+ * NetworkScanRequest, Executor, TelephonyScanManager.NetworkScanCallback)}.
+ *
+ * @param type used to tell which network scan API should be used.
+ */
+ public void startNetworkScan(@NetworkQueryType int type) {
+ if (type == NETWORK_SCAN_TYPE_WAIT_FOR_ALL_RESULTS) {
+ mNetworkScanFuture = SettableFuture.create();
+ Futures.addCallback(mNetworkScanFuture, new FutureCallback<List<CellInfo>>() {
+ @Override
+ public void onSuccess(List<CellInfo> result) {
+ onResults(result);
+ onComplete();
+ }
+
+ @Override
+ public void onFailure(Throwable t) {
+ int errCode = Integer.parseInt(t.getMessage());
+ onError(errCode);
+ }
+ });
+ mExecutor.execute(new NetworkScanSyncTask(
+ mTelephonyManager, (SettableFuture) mNetworkScanFuture));
+ } else if (type == NETWORK_SCAN_TYPE_INCREMENTAL_RESULTS) {
+ if (DBG) Log.d(TAG, "start network scan async");
+ mNetworkScanRequester = mTelephonyManager.requestNetworkScan(
+ NETWORK_SCAN_REQUEST,
+ mExecutor,
+ mInternalNetworkScanCallback);
+ }
+ }
+
+ /**
+ * The network scan of type {@link #NETWORK_SCAN_TYPE_WAIT_FOR_ALL_RESULTS} can't be stopped,
+ * however, the result of the current network scan won't be returned to the callback after
+ * calling this method.
+ */
+ public void stopNetworkQuery() {
+ if (mNetworkScanRequester != null) {
+ mNetworkScanRequester.stopScan();
+ mNetworkScanFuture = null;
+ }
+
+ if (mNetworkScanFuture != null) {
+ mNetworkScanFuture.cancel(true /* mayInterruptIfRunning */);
+ mNetworkScanFuture = null;
+ }
+ }
+
+ private void onResults(List<CellInfo> cellInfos) {
+ mNetworkScanCallback.onResults(cellInfos);
+ }
+
+ private void onComplete() {
+ mNetworkScanCallback.onComplete();
+ }
+
+ private void onError(int errCode) {
+ mNetworkScanCallback.onError(errCode);
+ }
+
+ /**
+ * Converts the status code of {@link CellNetworkScanResult} to one of the
+ * {@link NetworkScan.ScanErrorCode}.
+ * @param errCode status code from {@link CellNetworkScanResult}.
+ *
+ * @return one of the scan error code from {@link NetworkScan.ScanErrorCode}.
+ */
+ private static int convertToScanErrorCode(int errCode) {
+ switch (errCode) {
+ case CellNetworkScanResult.STATUS_RADIO_NOT_AVAILABLE:
+ return NetworkScan.ERROR_RADIO_INTERFACE_ERROR;
+ case CellNetworkScanResult.STATUS_RADIO_GENERIC_FAILURE:
+ default:
+ return NetworkScan.ERROR_MODEM_ERROR;
+ }
+ }
+
+ private final class NetworkScanCallbackImpl extends TelephonyScanManager.NetworkScanCallback {
+ public void onResults(List<CellInfo> results) {
+ if (DBG) Log.d(TAG, "async scan onResults() results = " + results);
+ NetworkScanHelper.this.onResults(results);
+ }
+
+ public void onComplete() {
+ if (DBG) Log.d(TAG, "async scan onComplete()");
+ NetworkScanHelper.this.onComplete();
+ }
+
+ public void onError(@NetworkScan.ScanErrorCode int errCode) {
+ if (DBG) Log.d(TAG, "async scan onError() errorCode = " + errCode);
+ NetworkScanHelper.this.onError(errCode);
+ }
+ }
+
+ private static final class NetworkScanSyncTask implements Runnable {
+ private final SettableFuture<List<CellInfo>> mCallback;
+ private final TelephonyManager mTelephonyManager;
+
+ NetworkScanSyncTask(
+ TelephonyManager telephonyManager, SettableFuture<List<CellInfo>> callback) {
+ mTelephonyManager = telephonyManager;
+ mCallback = callback;
+ }
+
+ @Override
+ public void run() {
+ if (DBG) Log.d(TAG, "sync scan start");
+ CellNetworkScanResult result = mTelephonyManager.getAvailableNetworks();
+ if (result.getStatus() == CellNetworkScanResult.STATUS_SUCCESS) {
+ List<CellInfo> cellInfos = result.getOperators()
+ .stream()
+ .map(operatorInfo
+ -> CellInfoUtil.convertOperatorInfoToCellInfo(operatorInfo))
+ .collect(Collectors.toList());
+ if (DBG) Log.d(TAG, "sync scan complete");
+ mCallback.set(cellInfos);
+ } else {
+ mCallback.setException(new Throwable(
+ Integer.toString(convertToScanErrorCode(result.getStatus()))));
+ }
+ }
+ }
+}
diff --git a/src/com/android/settings/mobilenetwork/NetworkSelectListPreference.java b/src/com/android/settings/mobilenetwork/NetworkSelectListPreference.java
new file mode 100644
index 0000000..95283dc
--- /dev/null
+++ b/src/com/android/settings/mobilenetwork/NetworkSelectListPreference.java
@@ -0,0 +1,505 @@
+/*
+ * Copyright (C) 2006 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.phone;
+
+import android.app.ProgressDialog;
+import android.content.Context;
+import android.content.DialogInterface;
+import android.os.AsyncTask;
+import android.os.Handler;
+import android.os.Message;
+import android.os.Parcel;
+import android.os.Parcelable;
+import android.preference.ListPreference;
+import android.preference.Preference;
+import android.telephony.CellInfo;
+import android.telephony.CellInfoCdma;
+import android.telephony.CellInfoGsm;
+import android.telephony.CellInfoLte;
+import android.telephony.CellInfoWcdma;
+import android.telephony.SubscriptionManager;
+import android.telephony.TelephonyManager;
+import android.text.BidiFormatter;
+import android.text.TextDirectionHeuristics;
+import android.text.TextUtils;
+import android.util.AttributeSet;
+import android.util.Log;
+import android.widget.Toast;
+
+import com.android.internal.logging.MetricsLogger;
+import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
+import com.android.internal.telephony.OperatorInfo;
+import com.android.phone.NetworkScanHelper.NetworkScanCallback;
+import com.android.settingslib.utils.ThreadUtils;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
+
+
+/**
+ * "Networks" preference in "Mobile network" settings UI for the Phone app.
+ * It's used to manually search and choose mobile network. Enabled only when
+ * autoSelect preference is turned off.
+ */
+public class NetworkSelectListPreference extends ListPreference
+ implements DialogInterface.OnCancelListener,
+ Preference.OnPreferenceChangeListener{
+
+ private static final String LOG_TAG = "networkSelect";
+ private static final boolean DBG = true;
+
+ private static final int EVENT_MANUALLY_NETWORK_SELECTION_DONE = 1;
+ private static final int EVENT_NETWORK_SCAN_RESULTS = 2;
+ private static final int EVENT_NETWORK_SCAN_COMPLETED = 3;
+ private static final int EVENT_NETWORK_SCAN_ERROR = 4;
+
+ //dialog ids
+ private static final int DIALOG_NETWORK_SELECTION = 100;
+ private static final int DIALOG_NETWORK_LIST_LOAD = 200;
+
+ private final ExecutorService mNetworkScanExecutor = Executors.newFixedThreadPool(1);
+
+ private List<CellInfo> mCellInfoList;
+ private CellInfo mCellInfo;
+
+ private int mSubId;
+ private TelephonyManager mTelephonyManager;
+ private NetworkScanHelper mNetworkScanHelper;
+ private NetworkOperators mNetworkOperators;
+ private List<String> mForbiddenPlmns;
+
+ private ProgressDialog mProgressDialog;
+ public NetworkSelectListPreference(Context context, AttributeSet attrs) {
+ super(context, attrs);
+ }
+
+ public NetworkSelectListPreference(Context context, AttributeSet attrs, int defStyleAttr,
+ int defStyleRes) {
+ super(context, attrs, defStyleAttr, defStyleRes);
+ }
+
+ @Override
+ protected void onClick() {
+ showProgressDialog(DIALOG_NETWORK_LIST_LOAD);
+ TelephonyManager telephonyManager = (TelephonyManager)
+ getContext().getSystemService(Context.TELEPHONY_SERVICE);
+ new AsyncTask<Void, Void, List<String>>() {
+ @Override
+ protected List<String> doInBackground(Void... voids) {
+ String[] forbiddenPlmns = telephonyManager.getForbiddenPlmns();
+ return forbiddenPlmns != null ? Arrays.asList(forbiddenPlmns) : null;
+ }
+
+ @Override
+ protected void onPostExecute(List<String> result) {
+ mForbiddenPlmns = result;
+ loadNetworksList();
+ }
+ }.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
+ }
+
+ private final Handler mHandler = new Handler() {
+ @Override
+ public void handleMessage(Message msg) {
+ switch (msg.what) {
+ case EVENT_MANUALLY_NETWORK_SELECTION_DONE:
+ if (DBG) logd("hideProgressPanel");
+ dismissProgressDialog();
+
+ boolean isSuccessed = (boolean) msg.obj;
+ if (isSuccessed) {
+ if (DBG) {
+ logd("manual network selection: succeeded! "
+ + getNetworkTitle(mCellInfo));
+ }
+ mNetworkOperators.displayNetworkSelectionSucceeded();
+ } else {
+ if (DBG) logd("manual network selection: failed!");
+ mNetworkOperators.displayNetworkSelectionFailed();
+ }
+ mNetworkOperators.getNetworkSelectionMode();
+ break;
+
+ case EVENT_NETWORK_SCAN_RESULTS:
+ List<CellInfo> results = (List<CellInfo>) msg.obj;
+ results.removeIf(cellInfo -> cellInfo == null);
+ mCellInfoList = new ArrayList<>(results);
+ if (DBG) logd("CALLBACK_SCAN_RESULTS" + mCellInfoList.toString());
+ break;
+
+ case EVENT_NETWORK_SCAN_COMPLETED:
+ if (DBG) logd("scan complete, load the cellInfosList");
+ dismissProgressDialog();
+ networksListLoaded();
+ break;
+ case EVENT_NETWORK_SCAN_ERROR:
+ dismissProgressDialog();
+ displayNetworkQueryFailed();
+ mNetworkOperators.getNetworkSelectionMode();
+ break;
+ }
+ return;
+ }
+ };
+
+ private final NetworkScanHelper.NetworkScanCallback mCallback = new NetworkScanCallback() {
+ public void onResults(List<CellInfo> results) {
+ if (DBG) logd("get scan results: " + results.toString());
+ Message msg = mHandler.obtainMessage(EVENT_NETWORK_SCAN_RESULTS, results);
+ msg.sendToTarget();
+ }
+
+ public void onComplete() {
+ if (DBG) logd("network scan completed.");
+ Message msg = mHandler.obtainMessage(EVENT_NETWORK_SCAN_COMPLETED);
+ msg.sendToTarget();
+ }
+
+ public void onError(int error) {
+ if (DBG) logd("network scan error.");
+ Message msg = mHandler.obtainMessage(EVENT_NETWORK_SCAN_ERROR);
+ msg.sendToTarget();
+ }
+ };
+
+ @Override
+ //implemented for DialogInterface.OnCancelListener
+ public void onCancel(DialogInterface dialog) {
+ if (DBG) logd("user manually close the dialog");
+ mNetworkScanHelper.stopNetworkQuery();
+
+ // If cancelled, we query NetworkSelectMode and update states of AutoSelect button.
+ mNetworkOperators.getNetworkSelectionMode();
+ }
+
+ @Override
+ protected void onDialogClosed(boolean positiveResult) {
+ super.onDialogClosed(positiveResult);
+ // If dismissed, we query NetworkSelectMode and update states of AutoSelect button.
+ if (!positiveResult) {
+ mNetworkOperators.getNetworkSelectionMode();
+ }
+ }
+
+ // This initialize method needs to be called for this preference to work properly.
+ protected void initialize(int subId, NetworkOperators networkOperators,
+ ProgressDialog progressDialog) {
+ mSubId = subId;
+ mNetworkOperators = networkOperators;
+ // This preference should share the same progressDialog with networkOperators category.
+ mProgressDialog = progressDialog;
+
+ mTelephonyManager = TelephonyManager.from(getContext()).createForSubscriptionId(mSubId);
+ mNetworkScanHelper = new NetworkScanHelper(
+ mTelephonyManager, mCallback, mNetworkScanExecutor);
+
+ setSummary(mTelephonyManager.getNetworkOperatorName());
+
+ setOnPreferenceChangeListener(this);
+ }
+
+ @Override
+ protected void onPrepareForRemoval() {
+ destroy();
+ super.onPrepareForRemoval();
+ }
+
+ private void destroy() {
+ dismissProgressDialog();
+
+ if (mNetworkScanHelper != null) {
+ mNetworkScanHelper.stopNetworkQuery();
+ }
+
+ mNetworkScanExecutor.shutdown();
+ }
+
+ private void displayEmptyNetworkList() {
+ Toast.makeText(getContext(), R.string.empty_networks_list, Toast.LENGTH_LONG).show();
+ }
+
+ private void displayNetworkQueryFailed() {
+ Toast.makeText(getContext(), R.string.network_query_error, Toast.LENGTH_LONG).show();
+ }
+
+ private void loadNetworksList() {
+ if (DBG) logd("load networks list...");
+ mNetworkScanHelper.startNetworkScan(
+ NetworkScanHelper.NETWORK_SCAN_TYPE_WAIT_FOR_ALL_RESULTS);
+ }
+
+ private void networksListLoaded() {
+ if (DBG) logd("networks list loaded");
+
+ mNetworkOperators.getNetworkSelectionMode();
+ if (mCellInfoList != null) {
+ // create a preference for each item in the list.
+ // just use the operator name instead of the mildly
+ // confusing mcc/mnc.
+ List<CharSequence> networkEntriesList = new ArrayList<>();
+ List<CharSequence> networkEntryValuesList = new ArrayList<>();
+ for (CellInfo cellInfo: mCellInfoList) {
+ // Display each operator name only once.
+ String networkTitle = getNetworkTitle(cellInfo);
+ if (CellInfoUtil.isForbidden(cellInfo, mForbiddenPlmns)) {
+ networkTitle += " "
+ + getContext().getResources().getString(R.string.forbidden_network);
+ }
+ networkEntriesList.add(networkTitle);
+ networkEntryValuesList.add(getOperatorNumeric(cellInfo));
+ }
+ setEntries(networkEntriesList.toArray(new CharSequence[networkEntriesList.size()]));
+ setEntryValues(networkEntryValuesList.toArray(
+ new CharSequence[networkEntryValuesList.size()]));
+
+ super.onClick();
+ } else {
+ displayEmptyNetworkList();
+ }
+ }
+
+ private void dismissProgressDialog() {
+ if (mProgressDialog != null && mProgressDialog.isShowing()) {
+ try {
+ mProgressDialog.dismiss();
+ } catch (IllegalArgumentException ex) {
+ loge("Can't close the progress dialog " + ex);
+ }
+ }
+ }
+
+ private void showProgressDialog(int id) {
+ if (mProgressDialog == null) {
+ mProgressDialog = new ProgressDialog(getContext());
+ } else {
+ // Dismiss progress bar if it's showing now.
+ dismissProgressDialog();
+ }
+
+ switch (id) {
+ case DIALOG_NETWORK_SELECTION:
+ final String networkSelectMsg = getContext().getResources()
+ .getString(R.string.register_on_network,
+ getNetworkTitle(mCellInfo));
+ mProgressDialog.setMessage(networkSelectMsg);
+ mProgressDialog.setCanceledOnTouchOutside(false);
+ mProgressDialog.setCancelable(false);
+ mProgressDialog.setIndeterminate(true);
+ break;
+ case DIALOG_NETWORK_LIST_LOAD:
+ mProgressDialog.setMessage(
+ getContext().getResources().getString(R.string.load_networks_progress));
+ mProgressDialog.setCanceledOnTouchOutside(false);
+ mProgressDialog.setCancelable(true);
+ mProgressDialog.setIndeterminate(false);
+ mProgressDialog.setOnCancelListener(this);
+ break;
+ default:
+ }
+ mProgressDialog.show();
+ }
+
+ /**
+ * Implemented to support onPreferenceChangeListener to look for preference
+ * changes specifically on this button.
+ *
+ * @param preference is the preference to be changed, should be network select button.
+ * @param newValue should be the value of the selection as index of operators.
+ */
+ @Override
+ public boolean onPreferenceChange(Preference preference, Object newValue) {
+ int operatorIndex = findIndexOfValue((String) newValue);
+ mCellInfo = mCellInfoList.get(operatorIndex);
+ if (DBG) logd("selected network: " + mCellInfo.toString());
+
+ MetricsLogger.action(getContext(),
+ MetricsEvent.ACTION_MOBILE_NETWORK_MANUAL_SELECT_NETWORK);
+
+ if (SubscriptionManager.isValidSubscriptionId(mSubId)) {
+ ThreadUtils.postOnBackgroundThread(() -> {
+ final OperatorInfo operatorInfo = getOperatorInfoFromCellInfo(mCellInfo);
+ if (DBG) logd("manually selected network: " + operatorInfo.toString());
+ boolean isSuccessed = mTelephonyManager.setNetworkSelectionModeManual(
+ operatorInfo, true /* persistSelection */);
+ Message msg = mHandler.obtainMessage(EVENT_MANUALLY_NETWORK_SELECTION_DONE);
+ msg.obj = isSuccessed;
+ msg.sendToTarget();
+ });
+ } else {
+ loge("Error selecting network, subscription Id is invalid " + mSubId);
+ }
+
+ return true;
+ }
+
+ /**
+ * Returns the title of the network obtained in the manual search.
+ *
+ * @param cellInfo contains the information of the network.
+ * @return Long Name if not null/empty, otherwise Short Name if not null/empty,
+ * else MCCMNC string.
+ */
+ private String getNetworkTitle(CellInfo cellInfo) {
+ OperatorInfo ni = getOperatorInfoFromCellInfo(cellInfo);
+
+ if (!TextUtils.isEmpty(ni.getOperatorAlphaLong())) {
+ return ni.getOperatorAlphaLong();
+ } else if (!TextUtils.isEmpty(ni.getOperatorAlphaShort())) {
+ return ni.getOperatorAlphaShort();
+ } else {
+ BidiFormatter bidiFormatter = BidiFormatter.getInstance();
+ return bidiFormatter.unicodeWrap(ni.getOperatorNumeric(), TextDirectionHeuristics.LTR);
+ }
+ }
+
+ /**
+ * Returns the operator numeric (MCCMNC) obtained in the manual search.
+ *
+ * @param cellInfo contains the information of the network.
+ * @return MCCMNC string.
+ */
+ private String getOperatorNumeric(CellInfo cellInfo) {
+ return getOperatorInfoFromCellInfo(cellInfo).getOperatorNumeric();
+ }
+
+ /**
+ * Wrap a cell info into an operator info.
+ */
+ private OperatorInfo getOperatorInfoFromCellInfo(CellInfo cellInfo) {
+ OperatorInfo oi;
+ if (cellInfo instanceof CellInfoLte) {
+ CellInfoLte lte = (CellInfoLte) cellInfo;
+ oi = new OperatorInfo(
+ (String) lte.getCellIdentity().getOperatorAlphaLong(),
+ (String) lte.getCellIdentity().getOperatorAlphaShort(),
+ lte.getCellIdentity().getMobileNetworkOperator());
+ } else if (cellInfo instanceof CellInfoWcdma) {
+ CellInfoWcdma wcdma = (CellInfoWcdma) cellInfo;
+ oi = new OperatorInfo(
+ (String) wcdma.getCellIdentity().getOperatorAlphaLong(),
+ (String) wcdma.getCellIdentity().getOperatorAlphaShort(),
+ wcdma.getCellIdentity().getMobileNetworkOperator());
+ } else if (cellInfo instanceof CellInfoGsm) {
+ CellInfoGsm gsm = (CellInfoGsm) cellInfo;
+ oi = new OperatorInfo(
+ (String) gsm.getCellIdentity().getOperatorAlphaLong(),
+ (String) gsm.getCellIdentity().getOperatorAlphaShort(),
+ gsm.getCellIdentity().getMobileNetworkOperator());
+ } else if (cellInfo instanceof CellInfoCdma) {
+ CellInfoCdma cdma = (CellInfoCdma) cellInfo;
+ oi = new OperatorInfo(
+ (String) cdma.getCellIdentity().getOperatorAlphaLong(),
+ (String) cdma.getCellIdentity().getOperatorAlphaShort(),
+ "" /* operator numeric */);
+ } else {
+ oi = new OperatorInfo("", "", "");
+ }
+ return oi;
+ }
+
+ @Override
+ protected Parcelable onSaveInstanceState() {
+ final Parcelable superState = super.onSaveInstanceState();
+ if (isPersistent()) {
+ // No need to save instance state since it's persistent
+ return superState;
+ }
+
+ final SavedState myState = new SavedState(superState);
+ myState.mDialogListEntries = getEntries();
+ myState.mDialogListEntryValues = getEntryValues();
+ myState.mCellInfoList = mCellInfoList;
+ return myState;
+ }
+
+ @Override
+ protected void onRestoreInstanceState(Parcelable state) {
+ if (state == null || !state.getClass().equals(SavedState.class)) {
+ // Didn't save state for us in onSaveInstanceState
+ super.onRestoreInstanceState(state);
+ return;
+ }
+
+ SavedState myState = (SavedState) state;
+
+ if (getEntries() == null && myState.mDialogListEntries != null) {
+ setEntries(myState.mDialogListEntries);
+ }
+ if (getEntryValues() == null && myState.mDialogListEntryValues != null) {
+ setEntryValues(myState.mDialogListEntryValues);
+ }
+ if (mCellInfoList == null && myState.mCellInfoList != null) {
+ mCellInfoList = myState.mCellInfoList;
+ }
+
+ super.onRestoreInstanceState(myState.getSuperState());
+ }
+
+ /**
+ * We save entries, entryValues and operatorInfoList into bundle.
+ * At onCreate of fragment, dialog will be restored if it was open. In this case,
+ * we need to restore entries, entryValues and operatorInfoList. Without those information,
+ * onPreferenceChange will fail if user select network from the dialog.
+ */
+ private static class SavedState extends BaseSavedState {
+ CharSequence[] mDialogListEntries;
+ CharSequence[] mDialogListEntryValues;
+ List<CellInfo> mCellInfoList;
+
+ SavedState(Parcel source) {
+ super(source);
+ final ClassLoader boot = Object.class.getClassLoader();
+ mDialogListEntries = source.readCharSequenceArray();
+ mDialogListEntryValues = source.readCharSequenceArray();
+ mCellInfoList = source.readParcelableList(mCellInfoList, boot);
+ }
+
+ @Override
+ public void writeToParcel(Parcel dest, int flags) {
+ super.writeToParcel(dest, flags);
+ dest.writeCharSequenceArray(mDialogListEntries);
+ dest.writeCharSequenceArray(mDialogListEntryValues);
+ dest.writeParcelableList(mCellInfoList, flags);
+ }
+
+ SavedState(Parcelable superState) {
+ super(superState);
+ }
+
+ public static final Parcelable.Creator<SavedState> CREATOR =
+ new Parcelable.Creator<SavedState>() {
+ public SavedState createFromParcel(Parcel in) {
+ return new SavedState(in);
+ }
+
+ public SavedState[] newArray(int size) {
+ return new SavedState[size];
+ }
+ };
+ }
+
+ private void logd(String msg) {
+ Log.d(LOG_TAG, "[NetworksList] " + msg);
+ }
+
+ private void loge(String msg) {
+ Log.e(LOG_TAG, "[NetworksList] " + msg);
+ }
+}
\ No newline at end of file
diff --git a/src/com/android/settings/mobilenetwork/RoamingDialogFragment.java b/src/com/android/settings/mobilenetwork/RoamingDialogFragment.java
new file mode 100644
index 0000000..1b1091b
--- /dev/null
+++ b/src/com/android/settings/mobilenetwork/RoamingDialogFragment.java
@@ -0,0 +1,93 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.settings.mobilenetwork;
+
+import android.app.AlertDialog;
+import android.app.Dialog;
+import android.app.DialogFragment;
+import android.app.Fragment;
+import android.app.FragmentManager;
+import android.content.Context;
+import android.content.DialogInterface;
+import android.content.DialogInterface.OnClickListener;
+import android.os.Bundle;
+import android.os.PersistableBundle;
+import android.telephony.CarrierConfigManager;
+
+/**
+ * A dialog fragment that asks the user if they are sure they want to turn on data roaming
+ * to avoid accidental charges.
+ */
+public class RoamingDialogFragment extends DialogFragment implements OnClickListener {
+
+ public static final String SUB_ID_KEY = "sub_id_key";
+
+ private CarrierConfigManager mCarrierConfigManager;
+ private int mSubId;
+
+ /**
+ * The interface we expect a host activity to implement.
+ */
+ public interface RoamingDialogListener {
+ void onPositiveButtonClick(DialogFragment dialog);
+ }
+
+ // the host activity which implements the listening interface
+ private RoamingDialogListener mListener;
+
+ @Override
+ public void onAttach(Context context) {
+ super.onAttach(context);
+ Bundle args = getArguments();
+ mSubId = args.getInt(SUB_ID_KEY);
+ mCarrierConfigManager = new CarrierConfigManager(context);
+
+ // Verify host activity implemented callback interface
+ FragmentManager fragmentManager = getFragmentManager();
+ Fragment fragment = fragmentManager.findFragmentById(R.id.network_setting_content);
+ try {
+ mListener = (RoamingDialogListener) fragment;
+ } catch (ClassCastException e) {
+ throw new ClassCastException(fragment.toString() +
+ "must implement RoamingDialogListener");
+ }
+ }
+
+ @Override
+ public Dialog onCreateDialog(Bundle savedInstanceState) {
+ AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
+ int title = R.string.roaming_alert_title;
+ PersistableBundle carrierConfig = mCarrierConfigManager.getConfigForSubId(mSubId);
+ if (carrierConfig != null && carrierConfig.getBoolean(
+ CarrierConfigManager.KEY_CHECK_PRICING_WITH_CARRIER_FOR_DATA_ROAMING_BOOL)) {
+ title = R.string.roaming_check_price_warning;
+ }
+ builder.setMessage(getResources().getString(R.string.roaming_warning))
+ .setTitle(title)
+ .setIconAttribute(android.R.attr.alertDialogIcon)
+ .setPositiveButton(android.R.string.yes, this)
+ .setNegativeButton(android.R.string.no, this);
+ return builder.create();
+ }
+
+ @Override
+ public void onClick(DialogInterface dialog, int which) {
+ // let the host know that the positive button has been clicked
+ if (which == dialog.BUTTON_POSITIVE) {
+ mListener.onPositiveButtonClick(this);
+ }
+ }
+}