Merge "Add option to set external temp dir"
diff --git a/AndroidManifest.xml b/AndroidManifest.xml
index f86cdef..c9281d1 100644
--- a/AndroidManifest.xml
+++ b/AndroidManifest.xml
@@ -259,6 +259,21 @@
android:targetActivity="MobileNetworkSettings" />
<!-- networks setting -->
+ <!-- "Choose network" screen. Used only when the Automatically
+ select network turned off-->
+ <activity android:name="NetworkSelectSettingActivity"
+ android:label="@string/choose_network_title"
+ android:theme="@style/NetworkOperatorsSettingsTheme"
+ android:configChanges="orientation|screenSize">
+ <intent-filter>
+ <action android:name="android.intent.action.VIEW" />
+ <action android:name="android.intent.action.MAIN" />
+ <action android:name="android.settings.NETWORK_OPERATOR_SETTINGS" />
+ <action android:name="android.settings.DATA_ROAMING_SETTINGS" />
+ <category android:name="android.intent.category.DEFAULT" />
+ </intent-filter>
+ </activity>
+
<!-- service to handle network query requests sent to RIL -->
<service android:name="NetworkQueryService" />
diff --git a/res/layout/choose_network.xml b/res/layout/choose_network.xml
new file mode 100644
index 0000000..2c327c56
--- /dev/null
+++ b/res/layout/choose_network.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2018 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+
+<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:id="@+id/choose_network_content"
+ android:layout_height="match_parent"
+ android:layout_width="match_parent">
+</FrameLayout>
\ No newline at end of file
diff --git a/res/layout/choose_network_progress_header.xml b/res/layout/choose_network_progress_header.xml
new file mode 100644
index 0000000..671c297
--- /dev/null
+++ b/res/layout/choose_network_progress_header.xml
@@ -0,0 +1,34 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright (C) 2018 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+
+<FrameLayout
+ android:layout_width="match_parent"
+ android:layout_height="3dp"
+ xmlns:android="http://schemas.android.com/apk/res/android">
+ <View
+ android:id="@+id/progress_bar_background"
+ style="@style/TrimmedHorizontalProgressBar"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:background="?android:attr/colorSecondary" />
+ <ProgressBar
+ android:id="@+id/progress_bar_animation"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ style="@style/TrimmedHorizontalProgressBar"
+ android:indeterminate="true" />
+</FrameLayout>
\ No newline at end of file
diff --git a/res/values/strings.xml b/res/values/strings.xml
index cd3f462..0f8b7e9 100644
--- a/res/values/strings.xml
+++ b/res/values/strings.xml
@@ -283,10 +283,10 @@
<string name="exception_error">Network or SIM card error.</string>
<!-- Status message displayed in the "Call settings error" dialog when
current SS request is modified to a different request by STK CC -->
- <string name="stk_cc_ss_to_dial_error">SS request modified to DIAL request.</string>
- <string name="stk_cc_ss_to_ussd_error">SS request modified to USSD request.</string>
- <string name="stk_cc_ss_to_ss_error">SS request modified to new SS request.</string>
- <string name="stk_cc_ss_to_dial_video_error">SS request modified to Video DIAL request.</string>
+ <string name="stk_cc_ss_to_dial_error">SS request changed to regular call</string>
+ <string name="stk_cc_ss_to_ussd_error">SS request changed to USSD request</string>
+ <string name="stk_cc_ss_to_ss_error">Changed to new SS request</string>
+ <string name="stk_cc_ss_to_dial_video_error">SS request changed to video call</string>
<!-- Status message displayed in the "Call settings error" dialog when operation fails due to FDN
[CHAR LIMIT=NONE] -->
@@ -369,7 +369,7 @@
<!-- Available networks screen, text when no networks are found -->
<string name="empty_networks_list">No networks found.</string>
<!-- Available networks screen, toast when an error is encountered when searching for networks -->
- <string name="network_query_error">Error while searching for networks.</string>
+ <string name="network_query_error">Couldn\'t find networks. Try again.</string>
<!-- Available networks screen, toast when registering on a specific network -->
<string name="register_on_network">Registering on <xliff:g id="network">%s</xliff:g>\u2026</string>
<!-- Available networks screen, toast when SIM card isn't allowed on a network -->
@@ -378,6 +378,8 @@
<string name="connect_later">Can\'t connect to this network right now. Try again later.</string>
<!-- Available networks screen, toast when registered on a specific network -->
<string name="registration_done">Registered on network.</string>
+ <!-- Available networks, toast when user selects automatic selection -->
+ <string name="already_auto">Already in automatic selection.</string>
<!-- Available networks screen, name of switch button for whether to select network automatically -->
<string name="select_automatically">Automatically select network</string>
<!-- Available networks screen, name of button when user wants to select network manually -->
@@ -534,7 +536,9 @@
<!-- Mobile network settings UI: notification message shown when you
lose data connectivity because you're roaming and you have the
"data roaming" feature turned off. -->
- <string name="roaming_reenable_message">You\'ve lost data connectivity because you left your home network with data roaming turned off.</string>
+ <string name="roaming_reenable_message">Data roaming is turned off. Tap to turn on.</string>
+ <!-- Roaming notification tile, notifying lost of roaming data connection -->
+ <string name="roaming_notification_title">Lost mobile data connection</string>
<!-- Mobile network settings screen, dialog message when user selects the Data roaming check box -->
<string name="roaming_warning">You may incur significant charges.</string>
<!-- Mobile network settings screen, dialog message title when user selects the Data roaming check box -->
diff --git a/res/xml/choose_network.xml b/res/xml/choose_network.xml
new file mode 100644
index 0000000..fdf2aae
--- /dev/null
+++ b/res/xml/choose_network.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2018 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+
+<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android"
+ android:title="@string/choose_network_title">
+
+ <PreferenceCategory
+ android:key="connected_network_operator_preference"/>
+
+ <PreferenceCategory
+ android:key="network_operators_preference"/>
+
+</PreferenceScreen>
\ No newline at end of file
diff --git a/res/xml/gsm_umts_options.xml b/res/xml/gsm_umts_options.xml
index e3e2617..1df4c84 100644
--- a/res/xml/gsm_umts_options.xml
+++ b/res/xml/gsm_umts_options.xml
@@ -31,6 +31,11 @@
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-->
diff --git a/src/com/android/phone/CallFeaturesSetting.java b/src/com/android/phone/CallFeaturesSetting.java
index 8da980c..fd85585 100644
--- a/src/com/android/phone/CallFeaturesSetting.java
+++ b/src/com/android/phone/CallFeaturesSetting.java
@@ -281,7 +281,9 @@
addPreferencesFromResource(R.xml.cdma_call_privacy);
}
} else if (phoneType == PhoneConstants.PHONE_TYPE_GSM) {
-
+ if (mPhone.getIccCard() == null || !mPhone.getIccCard().getIccFdnAvailable()) {
+ prefSet.removePreference(fdnButton);
+ }
if (carrierConfig.getBoolean(
CarrierConfigManager.KEY_ADDITIONAL_CALL_SETTING_BOOL)) {
addPreferencesFromResource(R.xml.gsm_umts_call_options);
diff --git a/src/com/android/phone/CarrierConfigLoader.java b/src/com/android/phone/CarrierConfigLoader.java
index 2bb8d6f..86f0aa4 100644
--- a/src/com/android/phone/CarrierConfigLoader.java
+++ b/src/com/android/phone/CarrierConfigLoader.java
@@ -56,6 +56,7 @@
import com.android.internal.telephony.IccCardConstants;
import com.android.internal.telephony.Phone;
import com.android.internal.telephony.PhoneFactory;
+import com.android.internal.telephony.TelephonyPermissions;
import com.android.internal.util.FastXmlSerializer;
import com.android.internal.util.IndentingPrintWriter;
@@ -777,12 +778,23 @@
@Override public
@NonNull
PersistableBundle getConfigForSubId(int subId) {
+ // TODO(b/73136824): Migrate to TelephonyPermissions#checkCallingOrSelfReadPhoneState.
try {
mContext.enforceCallingOrSelfPermission(READ_PRIVILEGED_PHONE_STATE, null);
// SKIP checking run-time READ_PHONE_STATE since using PRIVILEGED
} catch (SecurityException e) {
- mContext.enforceCallingOrSelfPermission(READ_PHONE_STATE, null);
+ try {
+ mContext.enforceCallingOrSelfPermission(READ_PHONE_STATE, null);
+ } catch (SecurityException securityException) {
+ // If we don't have the runtime permission, but do have carrier privileges, that
+ // suffices for reading phone state.
+ if (!SubscriptionManager.isValidSubscriptionId(subId)) {
+ throw securityException;
+ }
+ TelephonyPermissions.enforceCallingOrSelfCarrierPrivilege(subId, null);
+ }
}
+
int phoneId = SubscriptionManager.getPhoneId(subId);
PersistableBundle retConfig = CarrierConfigManager.getDefaultConfig();
if (SubscriptionManager.isValidPhoneId(phoneId)) {
diff --git a/src/com/android/phone/CellInfoUtil.java b/src/com/android/phone/CellInfoUtil.java
new file mode 100644
index 0000000..c0409d8
--- /dev/null
+++ b/src/com/android/phone/CellInfoUtil.java
@@ -0,0 +1,169 @@
+/*
+ * 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.phone;
+
+import android.telephony.CellIdentity;
+import android.telephony.CellIdentityCdma;
+import android.telephony.CellIdentityGsm;
+import android.telephony.CellIdentityLte;
+import android.telephony.CellIdentityWcdma;
+import android.telephony.CellInfo;
+import android.telephony.CellInfoCdma;
+import android.telephony.CellInfoGsm;
+import android.telephony.CellInfoLte;
+import android.telephony.CellInfoWcdma;
+import android.telephony.TelephonyManager;
+import android.text.BidiFormatter;
+import android.text.TextDirectionHeuristics;
+import android.text.TextUtils;
+import android.util.Log;
+
+import com.android.internal.telephony.OperatorInfo;
+
+/**
+ * Add static Utility functions to get information from the CellInfo object.
+ * TODO: Modify {@link CellInfo} for simplify those functions
+ */
+public final class CellInfoUtil {
+ private static final String TAG = "NetworkSelectSetting";
+
+ private CellInfoUtil() {
+ }
+
+ /**
+ * Get the network type from a CellInfo. Network types include
+ * {@link TelephonyManager#NETWORK_TYPE_LTE}, {@link TelephonyManager#NETWORK_TYPE_UMTS},
+ * {@link TelephonyManager#NETWORK_TYPE_GSM}, {@link TelephonyManager#NETWORK_TYPE_CDMA} and
+ * {@link TelephonyManager#NETWORK_TYPE_UNKNOWN}
+ * @return network types
+ */
+ public static int getNetworkType(CellInfo cellInfo) {
+ if (cellInfo instanceof CellInfoLte) {
+ return TelephonyManager.NETWORK_TYPE_LTE;
+ } else if (cellInfo instanceof CellInfoWcdma) {
+ return TelephonyManager.NETWORK_TYPE_UMTS;
+ } else if (cellInfo instanceof CellInfoGsm) {
+ return TelephonyManager.NETWORK_TYPE_GSM;
+ } else if (cellInfo instanceof CellInfoCdma) {
+ return TelephonyManager.NETWORK_TYPE_CDMA;
+ } else {
+ Log.e(TAG, "Invalid CellInfo type");
+ return TelephonyManager.NETWORK_TYPE_UNKNOWN;
+ }
+ }
+
+ /**
+ * Get signal level as an int from 0..4.
+ * @return Signal strength level
+ */
+ public static int getLevel(CellInfo cellInfo) {
+ if (cellInfo instanceof CellInfoLte) {
+ return ((CellInfoLte) cellInfo).getCellSignalStrength().getLevel();
+ } else if (cellInfo instanceof CellInfoWcdma) {
+ return ((CellInfoWcdma) cellInfo).getCellSignalStrength().getLevel();
+ } else if (cellInfo instanceof CellInfoGsm) {
+ return ((CellInfoGsm) cellInfo).getCellSignalStrength().getLevel();
+ } else if (cellInfo instanceof CellInfoCdma) {
+ return ((CellInfoCdma) cellInfo).getCellSignalStrength().getLevel();
+ } else {
+ Log.e(TAG, "Invalid CellInfo type");
+ return 0;
+ }
+ }
+
+ /**
+ * Wrap a CellIdentity into a CellInfo.
+ */
+ public static CellInfo wrapCellInfoWithCellIdentity(CellIdentity cellIdentity) {
+ if (cellIdentity instanceof CellIdentityLte) {
+ CellInfoLte cellInfo = new CellInfoLte();
+ cellInfo.setCellIdentity((CellIdentityLte) cellIdentity);
+ return cellInfo;
+ } else if (cellIdentity instanceof CellIdentityCdma) {
+ CellInfoCdma cellInfo = new CellInfoCdma();
+ cellInfo.setCellIdentity((CellIdentityCdma) cellIdentity);
+ return cellInfo;
+ } else if (cellIdentity instanceof CellIdentityWcdma) {
+ CellInfoWcdma cellInfo = new CellInfoWcdma();
+ cellInfo.setCellIdentity((CellIdentityWcdma) cellIdentity);
+ return cellInfo;
+ } else if (cellIdentity instanceof CellIdentityGsm) {
+ CellInfoGsm cellInfo = new CellInfoGsm();
+ cellInfo.setCellIdentity((CellIdentityGsm) cellIdentity);
+ return cellInfo;
+ } else {
+ Log.e(TAG, "Invalid CellInfo type");
+ return null;
+ }
+ }
+
+ /**
+ * 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.
+ */
+ public static String getNetworkTitle(CellInfo cellInfo) {
+ OperatorInfo oi = getOperatorInfoFromCellInfo(cellInfo);
+
+ if (!TextUtils.isEmpty(oi.getOperatorAlphaLong())) {
+ return oi.getOperatorAlphaLong();
+ } else if (!TextUtils.isEmpty(oi.getOperatorAlphaShort())) {
+ return oi.getOperatorAlphaShort();
+ } else {
+ BidiFormatter bidiFormatter = BidiFormatter.getInstance();
+ return bidiFormatter.unicodeWrap(oi.getOperatorNumeric(), TextDirectionHeuristics.LTR);
+ }
+ }
+
+ /**
+ * Wrap a cell info into an operator info.
+ */
+ public static 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 {
+ Log.e(TAG, "Invalid CellInfo type");
+ oi = new OperatorInfo("", "", "");
+ }
+ return oi;
+ }
+}
diff --git a/src/com/android/phone/EmergencyDialer.java b/src/com/android/phone/EmergencyDialer.java
index 4cbfb38..a98c201 100644
--- a/src/com/android/phone/EmergencyDialer.java
+++ b/src/com/android/phone/EmergencyDialer.java
@@ -33,6 +33,7 @@
import android.os.PersistableBundle;
import android.provider.Settings;
import android.telecom.PhoneAccount;
+import android.telecom.TelecomManager;
import android.telephony.CarrierConfigManager;
import android.telephony.PhoneNumberUtils;
import android.telephony.SubscriptionManager;
@@ -587,10 +588,8 @@
playTone(ToneGenerator.TONE_PROP_NACK);
return;
}
- Intent intent = new Intent(Intent.ACTION_CALL_EMERGENCY);
- intent.setData(Uri.fromParts(PhoneAccount.SCHEME_TEL, mLastNumber, null));
- intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
- startActivity(intent);
+ TelecomManager tm = (TelecomManager) getSystemService(TELECOM_SERVICE);
+ tm.placeCall(Uri.fromParts(PhoneAccount.SCHEME_TEL, mLastNumber, null), null);
} else {
if (DBG) Log.d(LOG_TAG, "rejecting bad requested number " + mLastNumber);
diff --git a/src/com/android/phone/MobileNetworkSettings.java b/src/com/android/phone/MobileNetworkSettings.java
index 47d9f05..99950a8 100644
--- a/src/com/android/phone/MobileNetworkSettings.java
+++ b/src/com/android/phone/MobileNetworkSettings.java
@@ -242,6 +242,8 @@
//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;
@@ -669,6 +671,8 @@
if (icicle != null) {
mExpandAdvancedFields = icicle.getBoolean(EXPAND_ADVANCED_FIELDS, false);
+ } else if (getActivity().getIntent().getBooleanExtra(EXPAND_EXTRA, false)) {
+ mExpandAdvancedFields = true;
}
bindNetworkQueryService();
diff --git a/src/com/android/phone/NetworkOperatorPreference.java b/src/com/android/phone/NetworkOperatorPreference.java
new file mode 100644
index 0000000..f29c038
--- /dev/null
+++ b/src/com/android/phone/NetworkOperatorPreference.java
@@ -0,0 +1,127 @@
+/*
+ * 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.phone;
+
+import android.content.Context;
+import android.graphics.Color;
+import android.graphics.drawable.ColorDrawable;
+import android.graphics.drawable.Drawable;
+import android.graphics.drawable.LayerDrawable;
+import android.preference.Preference;
+import android.telephony.CellInfo;
+import android.telephony.SignalStrength;
+import android.telephony.TelephonyManager;
+import android.util.Log;
+import android.view.Gravity;
+
+import com.android.settingslib.graph.SignalDrawable;
+
+/**
+ * A Preference represents a network operator in the NetworkSelectSetting fragment.
+ */
+public class NetworkOperatorPreference extends Preference {
+
+ private static final String TAG = "NetworkOperatorPref";
+ private static final boolean DBG = true;
+ // number of signal strength level
+ public static final int NUMBER_OF_LEVELS = SignalStrength.NUM_SIGNAL_STRENGTH_BINS;
+ private CellInfo mCellInfo;
+ private int mLevel = -1;
+
+ // The following constants are used to draw signal icon.
+ private static final Drawable EMPTY_DRAWABLE = new ColorDrawable(Color.TRANSPARENT);
+ private static final int NO_CELL_DATA_CONNECTED_ICON = 0;
+
+ public NetworkOperatorPreference(CellInfo cellinfo, Context context) {
+ super(context);
+ mCellInfo = cellinfo;
+ refresh();
+ }
+
+ public CellInfo getCellInfo() {
+ return mCellInfo;
+ }
+
+ /**
+ * Refresh the NetworkOperatorPreference by updating the title and the icon.
+ */
+ public void refresh() {
+ if (DBG) Log.d(TAG, "refresh the network: " + CellInfoUtil.getNetworkTitle(mCellInfo));
+ setTitle(CellInfoUtil.getNetworkTitle(mCellInfo));
+ int level = CellInfoUtil.getLevel(mCellInfo);
+ if (DBG) Log.d(TAG, "refresh level: " + String.valueOf(level));
+ if (mLevel != level) {
+ mLevel = level;
+ updateIcon(mLevel);
+ }
+ }
+
+ /**
+ * Update the icon according to the input signal strength level.
+ */
+ public void setIcon(int level) {
+ updateIcon(level);
+ }
+
+ private int getIconId(int networkType) {
+ if (networkType == TelephonyManager.NETWORK_TYPE_CDMA) {
+ return R.drawable.signal_strength_1x;
+ } else if (networkType == TelephonyManager.NETWORK_TYPE_LTE) {
+ return R.drawable.signal_strength_lte;
+ } else if (networkType == TelephonyManager.NETWORK_TYPE_UMTS) {
+ return R.drawable.signal_strength_3g;
+ } else if (networkType == TelephonyManager.NETWORK_TYPE_GSM) {
+ return R.drawable.signal_strength_g;
+ } else {
+ return 0;
+ }
+ }
+
+ private void updateIcon(int level) {
+ if (level < 0 || level >= NUMBER_OF_LEVELS) return;
+ Context context = getContext();
+ // Make the signal strength drawable
+ int iconId = 0;
+ if (DBG) Log.d(TAG, "updateIcon level: " + String.valueOf(level));
+ iconId = SignalDrawable.getState(level, NUMBER_OF_LEVELS, false /* cutOut */);
+
+ SignalDrawable signalDrawable = new SignalDrawable(getContext());
+ signalDrawable.setLevel(iconId);
+ signalDrawable.setDarkIntensity(0);
+
+ // Make the network type drawable
+ int iconType = getIconId(CellInfoUtil.getNetworkType(mCellInfo));
+ Drawable networkDrawable =
+ iconType == NO_CELL_DATA_CONNECTED_ICON
+ ? EMPTY_DRAWABLE
+ : getContext()
+ .getResources().getDrawable(iconType, getContext().getTheme());
+
+ // Overlay the two drawables
+ Drawable[] layers = {networkDrawable, signalDrawable};
+ final int iconSize =
+ context.getResources().getDimensionPixelSize(R.dimen.signal_strength_icon_size);
+
+ LayerDrawable icons = new LayerDrawable(layers);
+ // Set the network type icon at the top left
+ icons.setLayerGravity(0 /* index of networkDrawable */, Gravity.TOP | Gravity.LEFT);
+ // Set the signal strength icon at the bottom right
+ icons.setLayerGravity(1 /* index of SignalDrawable */, Gravity.BOTTOM | Gravity.RIGHT);
+ icons.setLayerSize(1 /* index of SignalDrawable */, iconSize, iconSize);
+ setIcon(icons);
+ }
+}
diff --git a/src/com/android/phone/NetworkOperators.java b/src/com/android/phone/NetworkOperators.java
index 05cfe42..babd283 100644
--- a/src/com/android/phone/NetworkOperators.java
+++ b/src/com/android/phone/NetworkOperators.java
@@ -18,6 +18,7 @@
import android.app.ProgressDialog;
import android.content.Context;
+import android.content.Intent;
import android.os.AsyncResult;
import android.os.Handler;
import android.os.Message;
@@ -51,17 +52,24 @@
//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";
int mPhoneId = SubscriptionManager.INVALID_PHONE_INDEX;
+ private static final int ALREADY_IN_AUTO_SELECTION = 1;
//preference objects
private NetworkSelectListPreference mNetworkSelect;
private TwoStatePreference mAutoSelect;
+ private Preference mChooseNetwork;
private int mSubId;
private ProgressDialog mProgressDialog;
+ // There's two sets of Auto-Select UI in this class. {@link mNetworkSelect} is used for all
+ // pre-Pixel 3 devices, while {@link mChooseNetwork} is used for all devices after Pixel3.
+ boolean mEnableNewManualSelectNetworkUI;
+
public NetworkOperators(Context context, AttributeSet attrs) {
super(context, attrs);
}
@@ -74,10 +82,16 @@
* Initialize NetworkOperators instance.
*/
public void initialize() {
- mNetworkSelect =
- (NetworkSelectListPreference) findPreference(BUTTON_NETWORK_SELECT_KEY);
- mAutoSelect =
- (TwoStatePreference) findPreference(BUTTON_AUTO_SELECT_KEY);
+ 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) {
+ this.removePreference(mNetworkSelect);
+ } else {
+ this.removePreference(mChooseNetwork);
+ }
mProgressDialog = new ProgressDialog(getContext());
}
@@ -95,10 +109,22 @@
mAutoSelect.setOnPreferenceChangeListener(this);
}
- if (mNetworkSelect != null) {
- mNetworkSelect.initialize(mSubId, queryService, this, mProgressDialog);
+ if (mEnableNewManualSelectNetworkUI) {
+ if (mChooseNetwork != null) {
+ TelephonyManager telephonyManager = (TelephonyManager)
+ getContext().getSystemService(Context.TELEPHONY_SERVICE);
+ logd("data connection status " + telephonyManager.getDataState());
+ if (telephonyManager.getDataState() == telephonyManager.DATA_CONNECTED) {
+ mChooseNetwork.setSummary(telephonyManager.getNetworkOperatorName());
+ } else {
+ mChooseNetwork.setSummary(R.string.network_disconnected);
+ }
+ }
+ } else {
+ if (mNetworkSelect != null) {
+ mNetworkSelect.initialize(mSubId, queryService, this, mProgressDialog);
+ }
}
-
getNetworkSelectionMode();
}
@@ -113,6 +139,7 @@
public boolean onPreferenceChange(Preference preference, Object newValue) {
if (preference == mAutoSelect) {
boolean autoSelect = (Boolean) newValue;
+ logd("onPreferenceChange autoSelect: " + String.valueOf(autoSelect));
selectNetworkAutomatic(autoSelect);
MetricsLogger.action(getContext(),
MetricsEvent.ACTION_MOBILE_NETWORK_AUTO_SELECT_NETWORK_TOGGLE, autoSelect);
@@ -136,7 +163,7 @@
displayNetworkSelectionFailed(ar.exception);
} else {
if (DBG) logd("automatic network selection: succeeded!");
- displayNetworkSelectionSucceeded();
+ displayNetworkSelectionSucceeded(msg.arg1);
}
break;
@@ -155,8 +182,14 @@
if (mAutoSelect != null) {
mAutoSelect.setChecked(autoSelect);
}
- if (mNetworkSelect != null) {
- mNetworkSelect.setEnabled(!autoSelect);
+ if (mEnableNewManualSelectNetworkUI) {
+ if (mChooseNetwork != null) {
+ mChooseNetwork.setEnabled(!autoSelect);
+ }
+ } else {
+ if (mNetworkSelect != null) {
+ mNetworkSelect.setEnabled(!autoSelect);
+ }
}
} catch (Exception e) {
if (DBG) loge("get network selection mode: unable to parse result.");
@@ -171,10 +204,9 @@
// Used by both mAutoSelect and mNetworkSelect buttons.
protected void displayNetworkSelectionFailed(Throwable ex) {
String status;
-
if ((ex != null && ex instanceof CommandException)
&& ((CommandException) ex).getCommandError()
- == CommandException.Error.ILLEGAL_SIM_OR_ME) {
+ == CommandException.Error.ILLEGAL_SIM_OR_ME) {
status = getContext().getResources().getString(R.string.not_allowed);
} else {
status = getContext().getResources().getString(R.string.connect_later);
@@ -195,8 +227,13 @@
}
// Used by both mAutoSelect and mNetworkSelect buttons.
- protected void displayNetworkSelectionSucceeded() {
- String status = getContext().getResources().getString(R.string.registration_done);
+ protected void displayNetworkSelectionSucceeded(int msgArg1) {
+ String status = null;
+ if (msgArg1 == ALREADY_IN_AUTO_SELECTION) {
+ status = getContext().getResources().getString(R.string.already_auto);
+ } else {
+ status = getContext().getResources().getString(R.string.registration_done);
+ }
final PhoneGlobals app = PhoneGlobals.getInstance();
app.notificationMgr.postTransientNotification(
@@ -204,9 +241,17 @@
}
private void selectNetworkAutomatic(boolean autoSelect) {
- if (mNetworkSelect != null) {
- mNetworkSelect.setEnabled(!autoSelect);
+ logd("selectNetworkAutomatic: " + String.valueOf(autoSelect));
+ if (mEnableNewManualSelectNetworkUI) {
+ if (mChooseNetwork != null) {
+ mChooseNetwork.setEnabled(!autoSelect);
+ }
+ } else {
+ if (mNetworkSelect != null) {
+ mNetworkSelect.setEnabled(!autoSelect);
+ }
}
+
if (autoSelect) {
if (DBG) logd("select network automatically...");
showAutoSelectProgressBar();
@@ -216,8 +261,17 @@
if (phone != null) {
phone.setNetworkSelectionModeAutomatic(msg);
}
- } else if (mNetworkSelect != null) {
- mNetworkSelect.onClick();
+ } 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();
+ }
+ }
}
}
@@ -245,8 +299,24 @@
mProgressDialog.show();
}
+ /**
+ * Open the Choose netwotk page via {@alink NetworkSelectSettingActivity}
+ */
+ public void openChooseNetworkPage() {
+ Intent intent = NetworkSelectSettingActivity.getIntent(getContext(), mPhoneId);
+ getContext().startActivity(intent);
+ }
+
protected boolean preferenceTreeClick(Preference preference) {
- return (preference == mAutoSelect || preference == mNetworkSelect);
+ if (mEnableNewManualSelectNetworkUI) {
+ 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) {
@@ -256,4 +326,4 @@
private void loge(String msg) {
Log.e(LOG_TAG, "[NetworksList] " + msg);
}
-}
+}
\ No newline at end of file
diff --git a/src/com/android/phone/NetworkQueryService.java b/src/com/android/phone/NetworkQueryService.java
index 86f4b11..22b5509 100644
--- a/src/com/android/phone/NetworkQueryService.java
+++ b/src/com/android/phone/NetworkQueryService.java
@@ -79,7 +79,7 @@
private static final boolean INCREMENTAL_RESULTS = true;
// The parameters below are in seconds
private static final int SEARCH_PERIODICITY_SEC = 5;
- private static final int MAX_SEARCH_TIME_SEC = 60;
+ private static final int MAX_SEARCH_TIME_SEC = 300;
private static final int INCREMENTAL_RESULTS_PERIODICITY_SEC = 3;
/**
diff --git a/src/com/android/phone/NetworkSelectListPreference.java b/src/com/android/phone/NetworkSelectListPreference.java
index cc54b09..a8f29c9 100644
--- a/src/com/android/phone/NetworkSelectListPreference.java
+++ b/src/com/android/phone/NetworkSelectListPreference.java
@@ -124,7 +124,7 @@
logd("manual network selection: succeeded! "
+ getNetworkTitle(mCellInfo));
}
- mNetworkOperators.displayNetworkSelectionSucceeded();
+ mNetworkOperators.displayNetworkSelectionSucceeded(msg.arg1);
}
mNetworkOperators.getNetworkSelectionMode();
break;
@@ -411,7 +411,7 @@
String networkTitle = getNetworkTitle(cellInfo);
if (!networkEntriesList.contains(networkTitle)) {
networkEntriesList.add(networkTitle);
- networkEntryValuesList.add(Integer.toString(networkEntriesList.size() + 1));
+ networkEntryValuesList.add(getOperatorNumeric(cellInfo));
}
}
setEntries(networkEntriesList.toArray(new CharSequence[networkEntriesList.size()]));
@@ -510,6 +510,16 @@
}
/**
+ * 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) {
diff --git a/src/com/android/phone/NetworkSelectSetting.java b/src/com/android/phone/NetworkSelectSetting.java
new file mode 100644
index 0000000..7ef3dea
--- /dev/null
+++ b/src/com/android/phone/NetworkSelectSetting.java
@@ -0,0 +1,634 @@
+/*
+ * 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.phone;
+
+import android.app.Activity;
+import android.content.ComponentName;
+import android.content.Context;
+import android.content.Intent;
+import android.content.ServiceConnection;
+import android.metrics.LogMaker;
+import android.os.AsyncResult;
+import android.os.Bundle;
+import android.os.Handler;
+import android.os.IBinder;
+import android.os.Message;
+import android.os.RemoteException;
+import android.preference.Preference;
+import android.preference.PreferenceCategory;
+import android.preference.PreferenceFragment;
+import android.preference.PreferenceScreen;
+import android.telephony.AccessNetworkConstants;
+import android.telephony.CellIdentity;
+import android.telephony.CellInfo;
+import android.telephony.NetworkRegistrationState;
+import android.telephony.ServiceState;
+import android.telephony.SubscriptionManager;
+import android.telephony.TelephonyManager;
+import android.util.Log;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+
+import com.android.internal.logging.MetricsLogger;
+import com.android.internal.logging.nano.MetricsProto;
+import com.android.internal.telephony.OperatorInfo;
+import com.android.internal.telephony.Phone;
+import com.android.internal.telephony.PhoneFactory;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * "Choose network" settings UI for the Phone app.
+ */
+public class NetworkSelectSetting extends PreferenceFragment {
+
+ private static final String TAG = "NetworkSelectSetting";
+ private static final boolean DBG = true;
+
+ private static final int EVENT_NETWORK_SELECTION_DONE = 1;
+ private static final int EVENT_NETWORK_SCAN_RESULTS = 2;
+ private static final int EVENT_NETWORK_SCAN_ERROR = 3;
+ private static final int EVENT_NETWORK_SCAN_COMPLETED = 4;
+
+ private static final String PREF_KEY_CONNECTED_NETWORK_OPERATOR =
+ "connected_network_operator_preference";
+ private static final String PREF_KEY_NETWORK_OPERATORS = "network_operators_preference";
+
+ // used to add/remove NetworkOperatorsPreference.
+ private PreferenceCategory mNetworkOperatorsPreferences;
+ // used to add/remove connected NetworkOperatorPreference.
+ private PreferenceCategory mConnectedNetworkOperatorsPreference;
+ // manage the progress bar on the top of the page.
+ private View mProgressHeader;
+ private Preference mStatusMessagePreference;
+ private List<CellInfo> mCellInfoList;
+ private int mPhoneId = SubscriptionManager.INVALID_PHONE_INDEX;
+ private ViewGroup mFrameLayout;
+ private NetworkOperatorPreference mSelectedNetworkOperatorPreference;
+ private TelephonyManager mTelephonyManager;
+ private NetworkOperators mNetworkOperators;
+
+ private final Runnable mUpdateNetworkOperatorsRunnable = () -> {
+ updateNetworkOperatorsPreferenceCategory();
+ };
+
+ /**
+ * Create a new instance of this fragment.
+ */
+ public static NetworkSelectSetting newInstance(int phoneId) {
+ Bundle args = new Bundle();
+ args.putInt(NetworkSelectSettingActivity.KEY_PHONE_ID, phoneId);
+ NetworkSelectSetting fragment = new NetworkSelectSetting();
+ fragment.setArguments(args);
+
+ return fragment;
+ }
+
+ @Override
+ public void onCreate(Bundle icicle) {
+ logd("onCreate");
+ super.onCreate(icicle);
+
+ mPhoneId = getArguments().getInt(NetworkSelectSettingActivity.KEY_PHONE_ID);
+
+ addPreferencesFromResource(R.xml.choose_network);
+ mConnectedNetworkOperatorsPreference =
+ (PreferenceCategory) findPreference(PREF_KEY_CONNECTED_NETWORK_OPERATOR);
+ mNetworkOperatorsPreferences =
+ (PreferenceCategory) findPreference(PREF_KEY_NETWORK_OPERATORS);
+ mStatusMessagePreference = new Preference(getContext());
+ mSelectedNetworkOperatorPreference = null;
+ mTelephonyManager = (TelephonyManager)
+ getContext().getSystemService(Context.TELEPHONY_SERVICE);
+ mNetworkOperators = new NetworkOperators(getContext());
+ setRetainInstance(true);
+ }
+
+ @Override
+ public void onViewCreated(View view, Bundle savedInstanceState) {
+ logd("onViewCreated");
+ super.onViewCreated(view, savedInstanceState);
+
+ if (getListView() != null) {
+ getListView().setDivider(null);
+ }
+ // Inflate progress bar
+ final Activity activity = getActivity();
+ if (activity != null) {
+ mFrameLayout = activity.findViewById(R.id.choose_network_content);
+ final LayoutInflater inflater = activity.getLayoutInflater();
+ final View pinnedHeader =
+ inflater.inflate(R.layout.choose_network_progress_header, mFrameLayout, false);
+ mFrameLayout.addView(pinnedHeader);
+ mFrameLayout.setVisibility(View.VISIBLE);
+ mProgressHeader = pinnedHeader.findViewById(R.id.progress_bar_animation);
+ setProgressBarVisible(false);
+ }
+ forceConfigConnectedNetworkOperatorsPreferenceCategory();
+ }
+
+ @Override
+ public void onStart() {
+ if (DBG) logd("onStart");
+ super.onStart();
+
+ // Bind the NetworkQueryService
+ bindNetworkQueryService();
+ }
+
+ /**
+ * Invoked on each preference click in this hierarchy, overrides
+ * PreferenceActivity's implementation. Used to make sure we track the
+ * preference click events.
+ * Since the connected network operator is either faked (when no data connection) or already
+ * connected, we do not allow user to click the connected network operator.
+ */
+ @Override
+ public boolean onPreferenceTreeClick(PreferenceScreen preferenceScreen,
+ Preference preference) {
+ if (DBG) logd("User clicked the screen");
+ stopNetworkQuery();
+ setProgressBarVisible(false);
+ if (preference instanceof NetworkOperatorPreference) {
+ // Refresh the last selected item in case users reselect network.
+ if (mSelectedNetworkOperatorPreference != null) {
+ mSelectedNetworkOperatorPreference.setSummary("");
+ }
+
+ mSelectedNetworkOperatorPreference = (NetworkOperatorPreference) preference;
+ CellInfo cellInfo = mSelectedNetworkOperatorPreference.getCellInfo();
+ if (DBG) logd("User click a NetworkOperatorPreference: " + cellInfo.toString());
+
+ // Send metrics event
+ final LogMaker logMaker = new LogMaker(
+ MetricsProto.MetricsEvent.ACTION_MOBILE_NETWORK_MANUAL_SELECT_NETWORK)
+ .setType(MetricsProto.MetricsEvent.TYPE_ACTION);
+ if (CellInfoUtil.getNetworkTitle(cellInfo) != null) {
+ // Since operator list is loaded dynamically from modem, we cannot know which
+ // network user chooses if we only record integer index of newValue. So a new tag
+ // and a string value (network) is added in this MetricsEvent.
+ logMaker.addTaggedData(MetricsProto.MetricsEvent.FIELD_MOBILE_NETWORK,
+ CellInfoUtil.getNetworkTitle(cellInfo));
+ }
+ MetricsLogger.action(logMaker);
+
+ // Connect to the network
+ Message msg = mHandler.obtainMessage(EVENT_NETWORK_SELECTION_DONE);
+ Phone phone = PhoneFactory.getPhone(mPhoneId);
+ if (phone != null) {
+ if (DBG) {
+ logd("Connect to the network: " + CellInfoUtil.getNetworkTitle(cellInfo));
+ }
+ // Set summary as "Connecting" to the selected network.
+ mSelectedNetworkOperatorPreference.setSummary(R.string.network_connecting);
+
+ // Set summary as "Disconnected" to the previously connected network
+ if (mConnectedNetworkOperatorsPreference.getPreferenceCount() > 0) {
+ NetworkOperatorPreference connectedNetworkOperator = (NetworkOperatorPreference)
+ (mConnectedNetworkOperatorsPreference.getPreference(0));
+ if (!CellInfoUtil.getNetworkTitle(cellInfo).equals(
+ CellInfoUtil.getNetworkTitle(connectedNetworkOperator.getCellInfo()))) {
+ connectedNetworkOperator.setSummary(R.string.network_disconnected);
+ }
+ }
+
+ // Select network manually via Phone
+ OperatorInfo operatorInfo = CellInfoUtil.getOperatorInfoFromCellInfo(cellInfo);
+ if (DBG) logd("manually selected network operator: " + operatorInfo.toString());
+ phone.selectNetworkManually(operatorInfo, true, msg);
+ setProgressBarVisible(true);
+ return true;
+ } else {
+ loge("Error selecting network. phone is null.");
+ mSelectedNetworkOperatorPreference = null;
+ return false;
+ }
+
+ } else {
+ preferenceScreen.setEnabled(false);
+ return false;
+ }
+ }
+
+ @Override
+ public void onAttach(Activity activity) {
+ super.onAttach(activity);
+ if (!(getActivity() instanceof NetworkSelectSettingActivity)) {
+ throw new IllegalStateException("Parent activity is not NetworkSelectSettingActivity");
+ }
+ }
+
+ @Override
+ public void onStop() {
+ super.onStop();
+ if (DBG) logd("onStop");
+ getView().removeCallbacks(mUpdateNetworkOperatorsRunnable);
+ stopNetworkQuery();
+ // Unbind the NetworkQueryService
+ unbindNetworkQueryService();
+ }
+
+ private final Handler mHandler = new Handler() {
+ @Override
+ public void handleMessage(Message msg) {
+ AsyncResult ar;
+ switch (msg.what) {
+ case EVENT_NETWORK_SELECTION_DONE:
+ if (DBG) logd("network selection done: hide the progress header");
+ setProgressBarVisible(false);
+
+ ar = (AsyncResult) msg.obj;
+ if (ar.exception != null) {
+ mNetworkOperators.displayNetworkSelectionFailed(ar.exception);
+ // Set summary as "Couldn't connect" to the selected network.
+ mSelectedNetworkOperatorPreference.setSummary(
+ R.string.network_could_not_connect);
+ } else {
+ if (DBG) logd("manual network selection: succeeded! ");
+ mNetworkOperators.displayNetworkSelectionSucceeded(msg.arg1);
+ // Set summary as "Connected" to the selected network.
+ mSelectedNetworkOperatorPreference.setSummary(R.string.network_connected);
+ }
+ break;
+
+ case EVENT_NETWORK_SCAN_RESULTS:
+ List<CellInfo> results = aggregateCellInfoList((List<CellInfo>) msg.obj);
+ mCellInfoList = new ArrayList<>(results);
+ if (DBG) logd("after aggregate: " + mCellInfoList.toString());
+ if (mCellInfoList != null && mCellInfoList.size() != 0) {
+ updateNetworkOperators();
+ } else {
+ addMessagePreference(R.string.empty_networks_list);
+ }
+
+ break;
+
+ case EVENT_NETWORK_SCAN_ERROR:
+ int error = msg.arg1;
+ if (DBG) logd("error while querying available networks " + error);
+ stopNetworkQuery();
+ addMessagePreference(R.string.network_query_error);
+ break;
+
+ case EVENT_NETWORK_SCAN_COMPLETED:
+ stopNetworkQuery();
+ if (DBG) logd("scan complete");
+ setProgressBarVisible(false);
+ if (mCellInfoList == null) {
+ // In case the scan timeout before getting any results
+ addMessagePreference(R.string.empty_networks_list);
+ }
+ break;
+ }
+ return;
+ }
+ };
+
+ private void loadNetworksList() {
+ if (DBG) logd("load networks list...");
+ setProgressBarVisible(true);
+ try {
+ if (mNetworkQueryService != null) {
+ if (DBG) logd("start network query");
+ mNetworkQueryService
+ .startNetworkQuery(mCallback, mPhoneId, true /* is incremental result */);
+ } else {
+ if (DBG) logd("unable to start network query, mNetworkQueryService is null");
+ addMessagePreference(R.string.network_query_error);
+ }
+ } catch (RemoteException e) {
+ loge("loadNetworksList: exception from startNetworkQuery " + e);
+ addMessagePreference(R.string.network_query_error);
+ }
+ }
+
+ /**
+ * This implementation of INetworkQueryServiceCallback is used to receive
+ * callback notifications from the network query service.
+ */
+ private final INetworkQueryServiceCallback mCallback = new INetworkQueryServiceCallback.Stub() {
+
+ /** Returns the scan results to the user, this callback will be called at lease one time. */
+ public void onResults(List<CellInfo> results) {
+ if (DBG) logd("get scan results.");
+ Message msg = mHandler.obtainMessage(EVENT_NETWORK_SCAN_RESULTS, results);
+ msg.sendToTarget();
+ }
+
+ /**
+ * Informs the user that the scan has stopped.
+ *
+ * This callback will be called when the scan is finished or cancelled by the user.
+ * The related NetworkScanRequest will be deleted after this callback.
+ */
+ public void onComplete() {
+ if (DBG) logd("network scan completed.");
+ Message msg = mHandler.obtainMessage(EVENT_NETWORK_SCAN_COMPLETED);
+ msg.sendToTarget();
+ }
+
+ /**
+ * Informs the user that there is some error about the scan.
+ *
+ * This callback will be called whenever there is any error about the scan, and the scan
+ * will be terminated. onComplete() will NOT be called.
+ */
+ public void onError(int error) {
+ if (DBG) logd("get onError callback with error code: " + error);
+ Message msg = mHandler.obtainMessage(EVENT_NETWORK_SCAN_ERROR, error, 0 /* arg2 */);
+ msg.sendToTarget();
+ }
+ };
+
+ /**
+ * Updates network operators from {@link INetworkQueryServiceCallback#onResults()}.
+ */
+ private void updateNetworkOperators() {
+ if (DBG) logd("updateNetworkOperators");
+ if (getActivity() != null) {
+ final View view = getView();
+ final Handler handler = view.getHandler();
+ if (handler != null && handler.hasCallbacks(mUpdateNetworkOperatorsRunnable)) {
+ return;
+ }
+ view.post(mUpdateNetworkOperatorsRunnable);
+ }
+ }
+
+ /**
+ * Update the currently available network operators list, which only contains the unregistered
+ * network operators. So if the device has no data and the network operator in the connected
+ * network operator category shows "Disconnected", it will also exist in the available network
+ * operator category for user to select. On the other hand, if the device has data and the
+ * network operator in the connected network operator category shows "Connected", it will not
+ * exist in the available network category.
+ */
+ private void updateNetworkOperatorsPreferenceCategory() {
+ mNetworkOperatorsPreferences.removeAll();
+
+ configConnectedNetworkOperatorsPreferenceCategory();
+ for (int index = 0; index < mCellInfoList.size(); index++) {
+ if (!mCellInfoList.get(index).isRegistered()) {
+ NetworkOperatorPreference pref =
+ new NetworkOperatorPreference(mCellInfoList.get(index), getContext());
+ pref.setKey(CellInfoUtil.getNetworkTitle(mCellInfoList.get(index)));
+ pref.setOrder(index);
+ mNetworkOperatorsPreferences.addPreference(pref);
+ }
+ }
+ }
+
+ /**
+ * Config the connected network operator preference when the page was created. When user get
+ * into this page, the device might or might not have data connection.
+ * - If the device has data:
+ * 1. use {@code ServiceState#getNetworkRegistrationStates()} to get the currently
+ * registered cellIdentity, wrap it into a CellInfo;
+ * 2. set the signal strength level as strong;
+ * 3. use {@link TelephonyManager#getNetworkOperatorName()} to get the title of the
+ * previously connected network operator, since the CellIdentity got from step 1 only has
+ * PLMN.
+ * - If the device has no data, we will remove the connected network operators list from the
+ * screen.
+ */
+ private void forceConfigConnectedNetworkOperatorsPreferenceCategory() {
+ if (DBG) logd("Force config ConnectedNetworkOperatorsPreferenceCategory");
+ if (mTelephonyManager.getDataState() == mTelephonyManager.DATA_CONNECTED) {
+ // Try to get the network registration states
+ ServiceState ss = mTelephonyManager.getServiceStateForSubscriber(mPhoneId);
+ List<NetworkRegistrationState> networkList =
+ ss.getNetworkRegistrationStates(AccessNetworkConstants.TransportType.WWAN);
+ if (networkList == null || networkList.size() == 0) {
+ loge("getNetworkRegistrationStates return null");
+ // Remove the connected network operators category
+ removeConnectedNetworkOperatorPreference();
+ return;
+ }
+ CellIdentity cellIdentity = networkList.get(0).getCellIdentity();
+ CellInfo cellInfo = CellInfoUtil.wrapCellInfoWithCellIdentity(cellIdentity);
+ if (cellInfo != null) {
+ if (DBG) logd("Currently registered cell: " + cellInfo.toString());
+ NetworkOperatorPreference pref =
+ new NetworkOperatorPreference(cellInfo, getContext());
+ pref.setTitle(mTelephonyManager.getNetworkOperatorName());
+ pref.setSummary(R.string.network_connected);
+ // Update the signal strength icon, since the default signalStrength value would be
+ // zero (it would be quite confusing why the connected network has no signal)
+ pref.setIcon(NetworkOperatorPreference.NUMBER_OF_LEVELS - 1);
+
+ mConnectedNetworkOperatorsPreference.addPreference(pref);
+ } else {
+ loge("Invalid CellIfno: " + cellInfo.toString());
+ // Remove the connected network operators category
+ removeConnectedNetworkOperatorPreference();
+ }
+ } else {
+ if (DBG) logd("No currently registered cell");
+ // Remove the connected network operators category
+ removeConnectedNetworkOperatorPreference();
+ }
+ }
+
+ /**
+ * Configure the ConnectedNetworkOperatorsPreferenceCategory. The category only need to be
+ * configured if the category is currently empty or the operator network title of the previous
+ * connected network is different from the new one.
+ */
+ private void configConnectedNetworkOperatorsPreferenceCategory() {
+ if (DBG) logd("config ConnectedNetworkOperatorsPreferenceCategory");
+ // Remove the category if the CellInfo list is empty or does not have registered cell.
+ if (mCellInfoList.size() == 0) {
+ if (DBG) logd("empty cellinfo list");
+ removeConnectedNetworkOperatorPreference();
+ }
+ CellInfo connectedNetworkOperator = null;
+ for (CellInfo cellInfo: mCellInfoList) {
+ if (cellInfo.isRegistered()) {
+ connectedNetworkOperator = cellInfo;
+ break;
+ }
+ }
+ if (connectedNetworkOperator == null) {
+ if (DBG) logd("no registered network");
+ removeConnectedNetworkOperatorPreference();
+ return;
+ }
+
+ // config the category if it is empty.
+ if (mConnectedNetworkOperatorsPreference.getPreferenceCount() == 0) {
+ if (DBG) logd("ConnectedNetworkSelectList is empty, add one");
+ addConnectedNetworkOperatorPreference(connectedNetworkOperator);
+ return;
+ }
+ NetworkOperatorPreference previousConnectedNetworkOperator = (NetworkOperatorPreference)
+ (mConnectedNetworkOperatorsPreference.getPreference(0));
+
+ // config the category if the network title of the previous connected network is different
+ // from the new one.
+ String cTitle = CellInfoUtil.getNetworkTitle(connectedNetworkOperator);
+ String pTitle = CellInfoUtil.getNetworkTitle(
+ previousConnectedNetworkOperator.getCellInfo());
+ if (!cTitle.equals(pTitle)) {
+ if (DBG) logd("reconfig the category: connected network changed");
+ addConnectedNetworkOperatorPreference(connectedNetworkOperator);
+ return;
+ }
+ if (DBG) logd("same network operator is connected, only refresh the connected network");
+ // Otherwise same network operator is connected, only refresh the connected network
+ // operator preference (first and the only one in this category).
+ ((NetworkOperatorPreference) mConnectedNetworkOperatorsPreference.getPreference(0))
+ .refresh();
+ return;
+ }
+
+ /**
+ * Creates a Preference for the given {@link CellInfo} and adds it to the
+ * {@link #mConnectedNetworkOperatorsPreference}.
+ */
+ private void addConnectedNetworkOperatorPreference(CellInfo cellInfo) {
+ if (DBG) logd("addConnectedNetworkOperatorPreference");
+ // Remove the current ConnectedNetworkOperatorsPreference
+ removeConnectedNetworkOperatorPreference();
+ final NetworkOperatorPreference pref =
+ new NetworkOperatorPreference(cellInfo, getContext());
+ pref.setSummary(R.string.network_connected);
+ mConnectedNetworkOperatorsPreference.addPreference(pref);
+ PreferenceScreen preferenceScreen = getPreferenceScreen();
+ preferenceScreen.addPreference(mConnectedNetworkOperatorsPreference);
+ }
+
+ /** Removes all preferences and hide the {@link #mConnectedNetworkOperatorsPreference}. */
+ private void removeConnectedNetworkOperatorPreference() {
+ mConnectedNetworkOperatorsPreference.removeAll();
+ PreferenceScreen preferenceScreen = getPreferenceScreen();
+ preferenceScreen.removePreference(mConnectedNetworkOperatorsPreference);
+ }
+
+ protected void setProgressBarVisible(boolean visible) {
+ if (mProgressHeader != null) {
+ mProgressHeader.setVisibility(visible ? View.VISIBLE : View.GONE);
+ }
+ }
+
+ private void addMessagePreference(int messageId) {
+ if (DBG) logd("remove callback");
+ getView().removeCallbacks(mUpdateNetworkOperatorsRunnable);
+ setProgressBarVisible(false);
+ if (DBG) logd("addMessagePreference");
+ mStatusMessagePreference.setTitle(messageId);
+ removeConnectedNetworkOperatorPreference();
+ mNetworkOperatorsPreferences.removeAll();
+ mNetworkOperatorsPreferences.addPreference(mStatusMessagePreference);
+ }
+
+ /**
+ * The Scan results may contains several cell infos with different radio technologies and signal
+ * strength for one network operator. Aggregate the CellInfoList by retaining only the cell info
+ * with the strongest signal strength.
+ */
+ private List<CellInfo> aggregateCellInfoList(List<CellInfo> cellInfoList) {
+ if (DBG) logd("before aggregate: " + cellInfoList.toString());
+ Map<String, CellInfo> map = new HashMap<>();
+ for (CellInfo cellInfo: cellInfoList) {
+ String networkTitle = CellInfoUtil.getNetworkTitle(cellInfo);
+ if (cellInfo.isRegistered() || !map.containsKey(networkTitle)) {
+ map.put(networkTitle, cellInfo);
+ } else {
+ if (map.get(networkTitle).isRegistered()
+ || CellInfoUtil.getLevel(map.get(networkTitle))
+ > CellInfoUtil.getLevel(cellInfo)) {
+ // Skip if the stored cellInfo is registered or has higher signal strength level
+ continue;
+ }
+ // Otherwise replace it with the new CellInfo
+ map.put(networkTitle, cellInfo);
+ }
+ }
+ return new ArrayList<>(map.values());
+ }
+
+ /**
+ * Service connection code for the NetworkQueryService.
+ * Handles the work of binding to a local object so that we can make
+ * the appropriate service calls.
+ */
+
+ /** Local service interface */
+ private INetworkQueryService mNetworkQueryService = null;
+ /** Flag indicating whether we have called bind on the service. */
+ boolean mShouldUnbind;
+
+ /** Service connection */
+ private final ServiceConnection mNetworkQueryServiceConnection = new ServiceConnection() {
+
+ /** Handle the task of binding the local object to the service */
+ public void onServiceConnected(ComponentName className, IBinder service) {
+ if (DBG) logd("connection created, binding local service.");
+ mNetworkQueryService = ((NetworkQueryService.LocalBinder) service).getService();
+ // Load the network list only when the service is well connected.
+ loadNetworksList();
+ }
+
+ /** Handle the task of cleaning up the local binding */
+ public void onServiceDisconnected(ComponentName className) {
+ if (DBG) logd("connection disconnected, cleaning local binding.");
+ mNetworkQueryService = null;
+ }
+ };
+
+ private void bindNetworkQueryService() {
+ if (DBG) logd("bindNetworkQueryService");
+ getContext().bindService(new Intent(getContext(), NetworkQueryService.class).setAction(
+ NetworkQueryService.ACTION_LOCAL_BINDER),
+ mNetworkQueryServiceConnection, Context.BIND_AUTO_CREATE);
+ mShouldUnbind = true;
+ }
+
+ private void unbindNetworkQueryService() {
+ if (DBG) logd("unbindNetworkQueryService");
+ if (mShouldUnbind) {
+ if (DBG) logd("mShouldUnbind is true");
+ // unbind the service.
+ getContext().unbindService(mNetworkQueryServiceConnection);
+ mShouldUnbind = false;
+ }
+ }
+
+ private void stopNetworkQuery() {
+ // Stop the network query process
+ try {
+ if (mNetworkQueryService != null) {
+ if (DBG) logd("Stop network query");
+ mNetworkQueryService.stopNetworkQuery();
+ mNetworkQueryService.unregisterCallback(mCallback);
+ }
+ } catch (RemoteException e) {
+ loge("Exception from stopNetworkQuery " + e);
+ }
+ }
+
+ private void logd(String msg) {
+ Log.d(TAG, msg);
+ }
+
+ private void loge(String msg) {
+ Log.e(TAG, msg);
+ }
+}
diff --git a/src/com/android/phone/NetworkSelectSettingActivity.java b/src/com/android/phone/NetworkSelectSettingActivity.java
new file mode 100644
index 0000000..2f730ad
--- /dev/null
+++ b/src/com/android/phone/NetworkSelectSettingActivity.java
@@ -0,0 +1,60 @@
+/*
+ * 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.phone;
+
+import android.app.Activity;
+import android.app.Fragment;
+import android.app.FragmentManager;
+import android.content.Context;
+import android.content.Intent;
+import android.os.Bundle;
+import android.util.Log;
+
+
+/**
+ * Activity associated with NetworkSelectSetting fragment
+ */
+public class NetworkSelectSettingActivity extends Activity {
+ private static final String TAG = "NetworkSelectSettingActivity";
+ public static final String KEY_PHONE_ID = "phone_id";
+
+ /**
+ * Returns the Android Intent that led to this Activity being created.
+ */
+ public static Intent getIntent(Context context, int phoneId) {
+ Intent intent = new Intent(context, NetworkSelectSettingActivity.class);
+ intent.putExtra(KEY_PHONE_ID, phoneId);
+ return intent;
+ }
+
+ @Override
+ public void onCreate(Bundle savedState) {
+ Log.d(TAG, "onCreate()");
+ super.onCreate(savedState);
+ int phoneId = getIntent().getExtras().getInt(KEY_PHONE_ID);
+ setContentView(R.layout.choose_network);
+
+ FragmentManager fragmentManager = getFragmentManager();
+ Fragment fragment = fragmentManager.findFragmentById(R.id.choose_network_content);
+ if (fragment == null) {
+ fragmentManager.beginTransaction()
+ .add(R.id.choose_network_content,
+ NetworkSelectSetting.newInstance(phoneId), TAG)
+ .commit();
+ }
+ }
+}
diff --git a/src/com/android/phone/NotificationMgr.java b/src/com/android/phone/NotificationMgr.java
index d36c761..f790c07 100644
--- a/src/com/android/phone/NotificationMgr.java
+++ b/src/com/android/phone/NotificationMgr.java
@@ -539,7 +539,7 @@
final Notification.Builder builder = new Notification.Builder(mContext)
.setSmallIcon(android.R.drawable.stat_sys_warning)
- .setContentTitle(mContext.getText(R.string.roaming))
+ .setContentTitle(mContext.getText(R.string.roaming_notification_title))
.setColor(mContext.getResources().getColor(R.color.dialer_theme_color))
.setContentText(contentText)
.setChannel(NotificationChannelController.CHANNEL_ID_MOBILE_DATA_STATUS)
@@ -613,24 +613,37 @@
PhoneFactory.getPhone(phoneId) : PhoneFactory.getDefaultPhone();
if (TelephonyCapabilities.supportsNetworkSelection(phone)) {
if (SubscriptionManager.isValidSubscriptionId(subId)) {
- // get the shared preference of network_selection.
- // empty is auto mode, otherwise it is the operator alpha name
- // in case there is no operator name, check the operator numeric
- SharedPreferences sp =
- PreferenceManager.getDefaultSharedPreferences(mContext);
- String networkSelection =
- sp.getString(Phone.NETWORK_SELECTION_NAME_KEY + subId, "");
- if (TextUtils.isEmpty(networkSelection)) {
- networkSelection =
- sp.getString(Phone.NETWORK_SELECTION_KEY + subId, "");
+ // if restoring manual selection is controlled by framework, then get network
+ // selection from shared preference, otherwise get from real network indicators.
+ boolean restoreSelection = !mContext.getResources().getBoolean(
+ com.android.internal.R.bool.skip_restoring_network_selection);
+ String selectedNetworkOperatorName;
+ boolean isManualSelection;
+ if (restoreSelection) {
+ SharedPreferences sp = PreferenceManager.getDefaultSharedPreferences(mContext);
+ selectedNetworkOperatorName =
+ sp.getString(Phone.NETWORK_SELECTION_NAME_KEY + subId, "");
+ // get the shared preference of network_selection.
+ // empty is auto mode, otherwise it is the operator alpha name
+ // in case there is no operator name, check the operator numeric
+ if (TextUtils.isEmpty(selectedNetworkOperatorName)) {
+ selectedNetworkOperatorName =
+ sp.getString(Phone.NETWORK_SELECTION_KEY + subId, "");
+ }
+ isManualSelection = !TextUtils.isEmpty(selectedNetworkOperatorName);
+ } else {
+ selectedNetworkOperatorName = phone.getServiceStateTracker().mSS
+ .getOperatorAlpha();
+ isManualSelection = phone.getServiceStateTracker().mSS.getIsManualSelection();
}
- if (DBG) log("updateNetworkSelection()..." + "state = " +
- serviceState + " new network " + networkSelection);
+ if (DBG) {
+ log("updateNetworkSelection()..." + "state = " + serviceState + " new network "
+ + (isManualSelection ? selectedNetworkOperatorName : ""));
+ }
- if (serviceState == ServiceState.STATE_OUT_OF_SERVICE
- && !TextUtils.isEmpty(networkSelection)) {
- showNetworkSelection(networkSelection, subId);
+ if (serviceState == ServiceState.STATE_OUT_OF_SERVICE && isManualSelection) {
+ showNetworkSelection(selectedNetworkOperatorName, subId);
mSelectedUnavailableNotify = true;
} else {
if (mSelectedUnavailableNotify) {
diff --git a/src/com/android/phone/PhoneInterfaceManager.java b/src/com/android/phone/PhoneInterfaceManager.java
index c55ce17..de41481 100755
--- a/src/com/android/phone/PhoneInterfaceManager.java
+++ b/src/com/android/phone/PhoneInterfaceManager.java
@@ -1257,7 +1257,7 @@
@Override
public boolean isOffhookForSubscriber(int subId, String callingPackage) {
if (!TelephonyPermissions.checkCallingOrSelfReadPhoneState(
- mApp, callingPackage, "isOffhookForSubscriber")) {
+ mApp, subId, callingPackage, "isOffhookForSubscriber")) {
return false;
}
@@ -1277,7 +1277,7 @@
@Override
public boolean isRingingForSubscriber(int subId, String callingPackage) {
if (!TelephonyPermissions.checkCallingOrSelfReadPhoneState(
- mApp, callingPackage, "isRingingForSubscriber")) {
+ mApp, subId, callingPackage, "isRingingForSubscriber")) {
return false;
}
@@ -1297,7 +1297,7 @@
@Override
public boolean isIdleForSubscriber(int subId, String callingPackage) {
if (!TelephonyPermissions.checkCallingOrSelfReadPhoneState(
- mApp, callingPackage, "isIdleForSubscriber")) {
+ mApp, subId, callingPackage, "isIdleForSubscriber")) {
return false;
}
@@ -1473,7 +1473,7 @@
@Override
public boolean isRadioOnForSubscriber(int subId, String callingPackage) {
if (!TelephonyPermissions.checkCallingOrSelfReadPhoneState(
- mApp, callingPackage, "isRadioOnForSubscriber")) {
+ mApp, subId, callingPackage, "isRadioOnForSubscriber")) {
return false;
}
return isRadioOnForSubscriber(subId);
@@ -1786,32 +1786,44 @@
@Override
public String getImeiForSlot(int slotIndex, String callingPackage) {
- if (!TelephonyPermissions.checkCallingOrSelfReadPhoneState(
- mApp, callingPackage, "getImeiForSlot")) {
+ Phone phone = PhoneFactory.getPhone(slotIndex);
+ if (phone == null) {
return null;
}
- Phone phone = PhoneFactory.getPhone(slotIndex);
- return phone == null ? null : phone.getImei();
+ int subId = phone.getSubId();
+ if (!TelephonyPermissions.checkCallingOrSelfReadPhoneState(
+ mApp, subId, callingPackage, "getImeiForSlot")) {
+ return null;
+ }
+ return phone.getImei();
}
@Override
public String getMeidForSlot(int slotIndex, String callingPackage) {
- if (!TelephonyPermissions.checkCallingOrSelfReadPhoneState(
- mApp, callingPackage, "getMeidForSlot")) {
+ Phone phone = PhoneFactory.getPhone(slotIndex);
+ if (phone == null) {
return null;
}
- Phone phone = PhoneFactory.getPhone(slotIndex);
- return phone == null ? null : phone.getMeid();
+ int subId = phone.getSubId();
+ if (!TelephonyPermissions.checkCallingOrSelfReadPhoneState(
+ mApp, subId, callingPackage, "getMeidForSlot")) {
+ return null;
+ }
+ return phone.getMeid();
}
@Override
public String getDeviceSoftwareVersionForSlot(int slotIndex, String callingPackage) {
- if (!TelephonyPermissions.checkCallingOrSelfReadPhoneState(
- mApp, callingPackage, "getDeviceSoftwareVersionForSlot")) {
+ Phone phone = PhoneFactory.getPhone(slotIndex);
+ if (phone == null) {
return null;
}
- Phone phone = PhoneFactory.getPhone(slotIndex);
- return phone == null ? null : phone.getDeviceSvn();
+ int subId = phone.getSubId();
+ if (!TelephonyPermissions.checkCallingOrSelfReadPhoneState(
+ mApp, subId, callingPackage, "getDeviceSoftwareVersionForSlot")) {
+ return null;
+ }
+ return phone.getDeviceSvn();
}
@Override
@@ -1900,7 +1912,7 @@
@Override
public int getCdmaEriIconIndexForSubscriber(int subId, String callingPackage) {
if (!TelephonyPermissions.checkCallingOrSelfReadPhoneState(
- mApp, callingPackage, "getCdmaEriIconIndexForSubscriber")) {
+ mApp, subId, callingPackage, "getCdmaEriIconIndexForSubscriber")) {
return -1;
}
final Phone phone = getPhone(subId);
@@ -1924,7 +1936,7 @@
@Override
public int getCdmaEriIconModeForSubscriber(int subId, String callingPackage) {
if (!TelephonyPermissions.checkCallingOrSelfReadPhoneState(
- mApp, callingPackage, "getCdmaEriIconModeForSubscriber")) {
+ mApp, subId, callingPackage, "getCdmaEriIconModeForSubscriber")) {
return -1;
}
final Phone phone = getPhone(subId);
@@ -1946,7 +1958,7 @@
@Override
public String getCdmaEriTextForSubscriber(int subId, String callingPackage) {
if (!TelephonyPermissions.checkCallingOrSelfReadPhoneState(
- mApp, callingPackage, "getCdmaEriIconTextForSubscriber")) {
+ mApp, subId, callingPackage, "getCdmaEriIconTextForSubscriber")) {
return null;
}
final Phone phone = getPhone(subId);
@@ -2023,10 +2035,16 @@
public String getVisualVoicemailPackageName(String callingPackage, int subId) {
mAppOps.checkPackage(Binder.getCallingUid(), callingPackage);
if (!TelephonyPermissions.checkCallingOrSelfReadPhoneState(
- mApp, callingPackage, "getVisualVoicemailPackageName")) {
+ mApp, subId, callingPackage, "getVisualVoicemailPackageName")) {
return null;
}
- return RemoteVvmTaskManager.getRemotePackage(mPhone.getContext(), subId).getPackageName();
+ final long identity = Binder.clearCallingIdentity();
+ try {
+ return RemoteVvmTaskManager
+ .getRemotePackage(mPhone.getContext(), subId).getPackageName();
+ } finally {
+ Binder.restoreCallingIdentity(identity);
+ }
}
@Override
@@ -2118,7 +2136,7 @@
@Override
public int getVoiceActivationState(int subId, String callingPackage) {
if (!TelephonyPermissions.checkCallingOrSelfReadPhoneState(
- mApp, callingPackage, "getVoiceActivationStateForSubscriber")) {
+ mApp, subId, callingPackage, "getVoiceActivationStateForSubscriber")) {
return TelephonyManager.SIM_ACTIVATION_STATE_UNKNOWN;
}
final Phone phone = getPhone(subId);
@@ -2135,7 +2153,7 @@
@Override
public int getDataActivationState(int subId, String callingPackage) {
if (!TelephonyPermissions.checkCallingOrSelfReadPhoneState(
- mApp, callingPackage, "getDataActivationStateForSubscriber")) {
+ mApp, subId, callingPackage, "getDataActivationStateForSubscriber")) {
return TelephonyManager.SIM_ACTIVATION_STATE_UNKNOWN;
}
final Phone phone = getPhone(subId);
@@ -2214,7 +2232,7 @@
@Override
public int getNetworkTypeForSubscriber(int subId, String callingPackage) {
if (!TelephonyPermissions.checkCallingOrSelfReadPhoneState(
- mApp, callingPackage, "getNetworkTypeForSubscriber")) {
+ mApp, subId, callingPackage, "getNetworkTypeForSubscriber")) {
return TelephonyManager.NETWORK_TYPE_UNKNOWN;
}
@@ -2240,7 +2258,7 @@
@Override
public int getDataNetworkTypeForSubscriber(int subId, String callingPackage) {
if (!TelephonyPermissions.checkCallingOrSelfReadPhoneState(
- mApp, callingPackage, "getDataNetworkTypeForSubscriber")) {
+ mApp, subId, callingPackage, "getDataNetworkTypeForSubscriber")) {
return TelephonyManager.NETWORK_TYPE_UNKNOWN;
}
@@ -2258,7 +2276,7 @@
@Override
public int getVoiceNetworkTypeForSubscriber(int subId, String callingPackage) {
if (!TelephonyPermissions.checkCallingOrSelfReadPhoneState(
- mApp, callingPackage, "getDataNetworkTypeForSubscriber")) {
+ mApp, subId, callingPackage, "getDataNetworkTypeForSubscriber")) {
return TelephonyManager.NETWORK_TYPE_UNKNOWN;
}
@@ -2309,7 +2327,7 @@
@Override
public int getLteOnCdmaModeForSubscriber(int subId, String callingPackage) {
if (!TelephonyPermissions.checkCallingOrSelfReadPhoneState(
- mApp, callingPackage, "getLteOnCdmaModeForSubscriber")) {
+ mApp, subId, callingPackage, "getLteOnCdmaModeForSubscriber")) {
return PhoneConstants.LTE_ON_CDMA_UNKNOWN;
}
@@ -2508,6 +2526,7 @@
* on a particular subscription
*/
public String[] getForbiddenPlmns(int subId, int appType) {
+ // TODO(b/73884967): Migrate to TelephonyPermissions check.
mApp.enforceCallingOrSelfPermission(android.Manifest.permission.READ_PHONE_STATE,
"Requires READ_PHONE_STATE");
if (appType != TelephonyManager.APPTYPE_USIM && appType != TelephonyManager.APPTYPE_SIM) {
@@ -2612,7 +2631,7 @@
public String[] getPcscfAddress(String apnType, String callingPackage) {
if (!TelephonyPermissions.checkCallingOrSelfReadPhoneState(
- mApp, callingPackage, "getPcscfAddress")) {
+ mApp, mPhone.getSubId(), callingPackage, "getPcscfAddress")) {
return new String[0];
}
@@ -2775,7 +2794,7 @@
@Override
public int getCalculatedPreferredNetworkType(String callingPackage) {
if (!TelephonyPermissions.checkCallingOrSelfReadPhoneState(
- mApp, callingPackage, "getCalculatedPreferredNetworkType")) {
+ mApp, mPhone.getSubId(), callingPackage, "getCalculatedPreferredNetworkType")) {
return RILConstants.PREFERRED_NETWORK_MODE;
}
@@ -3120,7 +3139,7 @@
public String getLine1NumberForDisplay(int subId, String callingPackage) {
// This is open to apps with WRITE_SMS.
if (!TelephonyPermissions.checkCallingOrSelfReadPhoneNumber(
- mApp, callingPackage, "getLine1NumberForDisplay")) {
+ mApp, subId, callingPackage, "getLine1NumberForDisplay")) {
if (DBG_MERGE) log("getLine1NumberForDisplay returning null due to permission");
return null;
}
@@ -3141,7 +3160,7 @@
@Override
public String getLine1AlphaTagForDisplay(int subId, String callingPackage) {
if (!TelephonyPermissions.checkCallingOrSelfReadPhoneState(
- mApp, callingPackage, "getLine1AlphaTagForDisplay")) {
+ mApp, subId, callingPackage, "getLine1AlphaTagForDisplay")) {
return null;
}
@@ -3155,8 +3174,11 @@
@Override
public String[] getMergedSubscriberIds(String callingPackage) {
+ // This API isn't public, so no need to provide a valid subscription ID - we're not worried
+ // about carrier-privileged callers not having access.
if (!TelephonyPermissions.checkCallingOrSelfReadPhoneState(
- mApp, callingPackage, "getMergedSubscriberIds")) {
+ mApp, SubscriptionManager.INVALID_SUBSCRIPTION_ID, callingPackage,
+ "getMergedSubscriberIds")) {
return null;
}
final Context context = mPhone.getContext();
@@ -3259,8 +3281,13 @@
@Override
public int getRadioAccessFamily(int phoneId, String callingPackage) {
+ Phone phone = PhoneFactory.getPhone(phoneId);
+ if (phone == null) {
+ return RadioAccessFamily.RAF_UNKNOWN;
+ }
+ int subId = phone.getSubId();
if (!TelephonyPermissions.checkCallingOrSelfReadPhoneState(
- mApp, callingPackage, "getRadioAccessFamily")) {
+ mApp, subId, callingPackage, "getRadioAccessFamily")) {
return RadioAccessFamily.RAF_UNKNOWN;
}
@@ -3276,7 +3303,7 @@
@Override
public boolean isVideoCallingEnabled(String callingPackage) {
if (!TelephonyPermissions.checkCallingOrSelfReadPhoneState(
- mApp, callingPackage, "isVideoCallingEnabled")) {
+ mApp, mPhone.getSubId(), callingPackage, "isVideoCallingEnabled")) {
return false;
}
@@ -3330,17 +3357,16 @@
*/
@Override
public String getDeviceId(String callingPackage) {
- if (!TelephonyPermissions.checkCallingOrSelfReadPhoneState(
- mApp, callingPackage, "getDeviceId")) {
- return null;
- }
-
final Phone phone = PhoneFactory.getPhone(0);
- if (phone != null) {
- return phone.getDeviceId();
- } else {
+ if (phone == null) {
return null;
}
+ int subId = phone.getSubId();
+ if (!TelephonyPermissions.checkCallingOrSelfReadPhoneState(
+ mApp, subId, callingPackage, "getDeviceId")) {
+ return null;
+ }
+ return phone.getDeviceId();
}
/**
@@ -3549,7 +3575,7 @@
public ServiceState getServiceStateForSubscriber(int subId, String callingPackage) {
if (!TelephonyPermissions.checkCallingOrSelfReadPhoneState(
- mApp, callingPackage, "getServiceStateForSubscriber")) {
+ mApp, subId, callingPackage, "getServiceStateForSubscriber")) {
return null;
}
@@ -3935,7 +3961,7 @@
@Override
public List<ClientRequestStats> getClientRequestStats(String callingPackage, int subId) {
if (!TelephonyPermissions.checkCallingOrSelfReadPhoneState(
- mApp, callingPackage, "getClientRequestStats")) {
+ mApp, subId, callingPackage, "getClientRequestStats")) {
return null;
}
@@ -4055,7 +4081,12 @@
}
infos[i] = new UiccSlotInfo(
- slot.isActive(), slot.isEuicc(), cardId, cardState, slot.getPhoneId());
+ slot.isActive(),
+ slot.isEuicc(),
+ cardId,
+ cardState,
+ slot.getPhoneId(),
+ slot.isExtendedApduSupported());
}
return infos;
}
diff --git a/src/com/android/phone/PhoneSearchIndexablesProvider.java b/src/com/android/phone/PhoneSearchIndexablesProvider.java
index 9c5f354..75e6bab 100644
--- a/src/com/android/phone/PhoneSearchIndexablesProvider.java
+++ b/src/com/android/phone/PhoneSearchIndexablesProvider.java
@@ -99,8 +99,8 @@
MatrixCursor cursor = new MatrixCursor(NON_INDEXABLES_KEYS_COLUMNS);
if (!mUserManager.isAdminUser()) {
- final String[] values = new String[]{"preferred_network_mode_key", "button_roaming_key",
- "cdma_lte_data_service_key", "enabled_networks_key", "enhanced_4g_lte",
+ final String[] values = new String[]{"preferred_network_mode_key",
+ "button_roaming_key", "cdma_lte_data_service_key", "enhanced_4g_lte",
"button_apn_key", "button_network_select_key", "carrier_settings_key",
"cdma_system_select_key", "esim_list_profile", "mobile_data_enable",
"data_usage_summary", "wifi_calling_key", "video_calling_key"};
@@ -115,6 +115,11 @@
cursor.addRow(createNonIndexableRow("enhanced_4g_lte" /* key */));
}
}
+ // enabled_networks button and preferred_network_mode button share the same title
+ // "Preferred network type"and are mutual exclusive. Thus we remove one from search
+ // result to avoid duplicate search result.
+ // TODO: b/63381516 all hidden buttons should dynamically be removed from search result.
+ cursor.addRow(createNonIndexableRow("enabled_networks_key" /* key */));
cursor.addRow(createNonIndexableRow("carrier_settings_euicc_key" /* key */));
cursor.addRow(createNonIndexableRow("advanced_options" /* key */));
return cursor;
diff --git a/src/com/android/phone/vvm/RemoteVvmTaskManager.java b/src/com/android/phone/vvm/RemoteVvmTaskManager.java
index 4fc8c57..cf5011e 100644
--- a/src/com/android/phone/vvm/RemoteVvmTaskManager.java
+++ b/src/com/android/phone/vvm/RemoteVvmTaskManager.java
@@ -119,6 +119,8 @@
TelecomManager telecomManager = context.getSystemService(TelecomManager.class);
List<String> packages = new ArrayList<>();
packages.add(telecomManager.getDefaultDialerPackage());
+ // TODO(b/73136824): Check permissions in the calling function and avoid relying on the
+ // binder caller's permissions to access the carrier config.
PersistableBundle carrierConfig = context
.getSystemService(CarrierConfigManager.class).getConfigForSubId(subId);
packages.add(
diff --git a/src/com/android/services/telephony/ImsConferenceController.java b/src/com/android/services/telephony/ImsConferenceController.java
index 4bae058..971dd7b 100644
--- a/src/com/android/services/telephony/ImsConferenceController.java
+++ b/src/com/android/services/telephony/ImsConferenceController.java
@@ -389,5 +389,8 @@
android.telephony.DisconnectCause.IMS_MERGED_SUCCESSFULLY)));
connection.destroy();
mImsConferences.add(conference);
+ // If one of the participants failed to join the conference, recalculate will set the
+ // conferenceable connections for the conference to show merge calls option.
+ recalculateConferenceable();
}
}
diff --git a/testapps/EmbmsServiceTestApp/src/com/android/phone/testapps/embmsmw/EmbmsSampleDownloadService.java b/testapps/EmbmsServiceTestApp/src/com/android/phone/testapps/embmsmw/EmbmsSampleDownloadService.java
index 7bd0f70..6ddebb8 100644
--- a/testapps/EmbmsServiceTestApp/src/com/android/phone/testapps/embmsmw/EmbmsSampleDownloadService.java
+++ b/testapps/EmbmsServiceTestApp/src/com/android/phone/testapps/embmsmw/EmbmsSampleDownloadService.java
@@ -31,8 +31,9 @@
import android.os.ParcelFileDescriptor;
import android.os.RemoteException;
import android.telephony.MbmsDownloadSession;
+import android.telephony.mbms.DownloadProgressListener;
import android.telephony.mbms.DownloadRequest;
-import android.telephony.mbms.DownloadStateCallback;
+import android.telephony.mbms.DownloadStatusListener;
import android.telephony.mbms.FileInfo;
import android.telephony.mbms.FileServiceInfo;
import android.telephony.mbms.MbmsDownloadSessionCallback;
@@ -143,9 +144,16 @@
}
@Override
- public int registerStateCallback(DownloadRequest downloadRequest,
- DownloadStateCallback callback) throws RemoteException {
- mDownloadStateCallbacks.put(downloadRequest, callback);
+ public int addStatusListener(DownloadRequest downloadRequest,
+ DownloadStatusListener callback) throws RemoteException {
+ mDownloadStatusCallbacks.put(downloadRequest, callback);
+ return MbmsErrors.SUCCESS;
+ }
+
+ @Override
+ public int addProgressListener(DownloadRequest downloadRequest,
+ DownloadProgressListener callback) throws RemoteException {
+ mDownloadProgressCallbacks.put(downloadRequest, callback);
return MbmsErrors.SUCCESS;
}
@@ -183,7 +191,9 @@
// A map of app-identifiers to (maps of service-ids to sets of temp file uris in use)
private final Map<FrontendAppIdentifier, Map<String, Set<Uri>>> mTempFilesInUse =
new ConcurrentHashMap<>();
- private final Map<DownloadRequest, DownloadStateCallback> mDownloadStateCallbacks =
+ private final Map<DownloadRequest, DownloadStatusListener> mDownloadStatusCallbacks =
+ new ConcurrentHashMap<>();
+ private final Map<DownloadRequest, DownloadProgressListener> mDownloadProgressCallbacks =
new ConcurrentHashMap<>();
private HandlerThread mHandlerThread;
@@ -334,13 +344,14 @@
UriPathPair tempFile, FileInfo fileToDownload) {
int result = MbmsDownloadSession.RESULT_SUCCESSFUL;
// Test Callback
- DownloadStateCallback c = mDownloadStateCallbacks.get(request);
- if (c != null) {
- c.onProgressUpdated(request, fileToDownload, 0, 10, 0, 10);
+ DownloadStatusListener statusListener = mDownloadStatusCallbacks.get(request);
+ DownloadProgressListener progressListener = mDownloadProgressCallbacks.get(request);
+ if (progressListener != null) {
+ progressListener.onProgressUpdated(request, fileToDownload, 0, 10, 0, 10);
}
// Test Callback
- if (c != null) {
- c.onStateUpdated(request, fileToDownload,
+ if (statusListener != null) {
+ statusListener.onStatusUpdated(request, fileToDownload,
MbmsDownloadSession.STATUS_ACTIVELY_DOWNLOADING);
}
try {
@@ -367,8 +378,8 @@
result = MbmsDownloadSession.RESULT_CANCELLED;
}
// Test Callback
- if (c != null) {
- c.onProgressUpdated(request, fileToDownload, 10, 10, 10, 10);
+ if (progressListener != null) {
+ progressListener.onProgressUpdated(request, fileToDownload, 10, 10, 10, 10);
}
// Take a round-trip through the download request serialization to exercise it
DownloadRequest request1 = DownloadRequest.Builder.fromSerializedRequest(
diff --git a/testapps/EmbmsTestDownloadApp/src/com/android/phone/testapps/embmsdownload/EmbmsTestDownloadApp.java b/testapps/EmbmsTestDownloadApp/src/com/android/phone/testapps/embmsdownload/EmbmsTestDownloadApp.java
index 8b8a67d..acdbdcb 100644
--- a/testapps/EmbmsTestDownloadApp/src/com/android/phone/testapps/embmsdownload/EmbmsTestDownloadApp.java
+++ b/testapps/EmbmsTestDownloadApp/src/com/android/phone/testapps/embmsdownload/EmbmsTestDownloadApp.java
@@ -27,8 +27,9 @@
import android.support.v7.widget.RecyclerView;
import android.telephony.MbmsDownloadSession;
import android.telephony.SubscriptionManager;
+import android.telephony.mbms.DownloadProgressListener;
import android.telephony.mbms.DownloadRequest;
-import android.telephony.mbms.DownloadStateCallback;
+import android.telephony.mbms.DownloadStatusListener;
import android.telephony.mbms.FileInfo;
import android.telephony.mbms.FileServiceInfo;
import android.telephony.mbms.MbmsDownloadSessionCallback;
@@ -306,8 +307,8 @@
"No DownloadRequest Pending for progress...", Toast.LENGTH_SHORT).show();
return;
}
- mDownloadManager.registerStateCallback(req, sInstance.getMainThreadHandler()::post,
- new DownloadStateCallback(DownloadStateCallback.PROGRESS_UPDATES) {
+ mDownloadManager.addProgressListener(req, sInstance.getMainThreadHandler()::post,
+ new DownloadProgressListener() {
@Override
public void onProgressUpdated(DownloadRequest request, FileInfo fileInfo,
int currentDownloadSize, int fullDownloadSize,
@@ -317,16 +318,6 @@
+ " fd: " + fullDownloadSize, Toast.LENGTH_SHORT)
.show();
}
-
- @Override
- public void onStateUpdated(DownloadRequest request, FileInfo fileInfo,
- @MbmsDownloadSession.DownloadStatus int state) {
- // only registered for state callback, this shouldn't happen!
- Toast.makeText(EmbmsTestDownloadApp.this,
- "State ERROR: received state update for callback that didn't"
- + " filter it",
- Toast.LENGTH_SHORT).show();
- }
});
});
@@ -344,21 +335,10 @@
"No DownloadRequest Pending for state...", Toast.LENGTH_SHORT).show();
return;
}
- mDownloadManager.registerStateCallback(req, sInstance.getMainThreadHandler()::post,
- new DownloadStateCallback(DownloadStateCallback.STATE_UPDATES) {
+ mDownloadManager.addStatusListener(req, sInstance.getMainThreadHandler()::post,
+ new DownloadStatusListener() {
@Override
- public void onProgressUpdated(DownloadRequest request, FileInfo fileInfo,
- int currentDownloadSize, int fullDownloadSize,
- int currentDecodedSize, int fullDecodedSize) {
- // only registered for state callback, this shouldn't happen!
- Toast.makeText(EmbmsTestDownloadApp.this,
- "Progress ERROR: received progress update for"
- + " callback that didn't "
- + "filter it", Toast.LENGTH_SHORT).show();
- }
-
- @Override
- public void onStateUpdated(DownloadRequest request, FileInfo fileInfo,
+ public void onStatusUpdated(DownloadRequest request, FileInfo fileInfo,
@MbmsDownloadSession.DownloadStatus int state) {
Toast.makeText(EmbmsTestDownloadApp.this,
"State Updated (" + fileInfo + ") state: " + state,
@@ -381,8 +361,20 @@
"No DownloadRequest Pending for state...", Toast.LENGTH_SHORT).show();
return;
}
- mDownloadManager.registerStateCallback(req, sInstance.getMainThreadHandler()::post,
- new DownloadStateCallback() {
+
+ mDownloadManager.addStatusListener(req, sInstance.getMainThreadHandler()::post,
+ new DownloadStatusListener() {
+ @Override
+ public void onStatusUpdated(DownloadRequest request, FileInfo fileInfo,
+ @MbmsDownloadSession.DownloadStatus int state) {
+ Toast.makeText(EmbmsTestDownloadApp.this,
+ "State Updated (" + fileInfo + ") state: " + state,
+ Toast.LENGTH_SHORT).show();
+ }
+ });
+
+ mDownloadManager.addProgressListener(req, sInstance.getMainThreadHandler()::post,
+ new DownloadProgressListener() {
@Override
public void onProgressUpdated(DownloadRequest request, FileInfo fileInfo,
int currentDownloadSize, int fullDownloadSize,
@@ -392,14 +384,6 @@
+ " fd: " + fullDownloadSize, Toast.LENGTH_SHORT)
.show();
}
-
- @Override
- public void onStateUpdated(DownloadRequest request, FileInfo fileInfo,
- @MbmsDownloadSession.DownloadStatus int state) {
- Toast.makeText(EmbmsTestDownloadApp.this,
- "State Updated (" + fileInfo + ") state: " + state,
- Toast.LENGTH_SHORT).show();
- }
});
});
}
diff --git a/tests/src/com/android/phone/CallFeaturesSettingTest.java b/tests/src/com/android/phone/CallFeaturesSettingTest.java
new file mode 100644
index 0000000..816642a
--- /dev/null
+++ b/tests/src/com/android/phone/CallFeaturesSettingTest.java
@@ -0,0 +1,106 @@
+/*
+ * 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.phone;
+
+import static android.support.test.espresso.Espresso.onView;
+import static android.support.test.espresso.assertion.ViewAssertions.doesNotExist;
+import static android.support.test.espresso.assertion.ViewAssertions.matches;
+import static android.support.test.espresso.matcher.ViewMatchers.isDisplayed;
+import static android.support.test.espresso.matcher.ViewMatchers.withText;
+
+import static org.mockito.Mockito.when;
+
+import android.support.test.filters.FlakyTest;
+import android.support.test.rule.ActivityTestRule;
+
+import com.android.internal.telephony.IccCard;
+import com.android.internal.telephony.Phone;
+import com.android.internal.telephony.PhoneConstants;
+
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+
+import java.lang.reflect.Field;
+
+public class CallFeaturesSettingTest {
+ @Mock
+ Phone mMockPhone;
+ @Mock
+ IccCard mMockIccCard;
+ @Rule
+ public ActivityTestRule<CallFeaturesSetting> mRule =
+ new ActivityTestRule<>(CallFeaturesSetting.class);
+ private CallFeaturesSetting mActivity;
+
+ @Before
+ public void setUp() {
+ MockitoAnnotations.initMocks(this);
+ mActivity = mRule.getActivity();
+ }
+
+ @FlakyTest
+ @Test
+ public void onResume_fdnIsAvailable_shouldShowFdnMenu() throws NoSuchFieldException,
+ IllegalAccessException {
+ when(mMockPhone.getPhoneType()).thenReturn(PhoneConstants.PHONE_TYPE_GSM);
+ when(mMockPhone.getIccCard()).thenReturn(mMockIccCard);
+ when(mMockIccCard.getIccFdnAvailable()).thenReturn(true);
+ getField("mPhone").set(mActivity, mMockPhone);
+
+ mActivity.onResume();
+
+ // Check the FDN menu is displayed.
+ onView(withText(R.string.fdn)).check(matches(isDisplayed()));
+ }
+
+ @FlakyTest
+ @Test
+ public void onResume_iccCardIsNull_shouldNotShowFdnMenu() throws NoSuchFieldException,
+ IllegalAccessException {
+ when(mMockPhone.getPhoneType()).thenReturn(PhoneConstants.PHONE_TYPE_GSM);
+ when(mMockPhone.getIccCard()).thenReturn(null);
+ getField("mPhone").set(mActivity, mMockPhone);
+
+ mActivity.onResume();
+
+ // Check the FDN menu is not displayed.
+ onView(withText(R.string.fdn)).check(doesNotExist());
+ }
+
+ @FlakyTest
+ @Test
+ public void onResume_fdnIsNotAvailable_shouldNotShowFdnMenu() throws NoSuchFieldException,
+ IllegalAccessException {
+ when(mMockPhone.getPhoneType()).thenReturn(PhoneConstants.PHONE_TYPE_GSM);
+ when(mMockPhone.getIccCard()).thenReturn(mMockIccCard);
+ when(mMockIccCard.getIccFdnAvailable()).thenReturn(false);
+ getField("mPhone").set(mActivity, mMockPhone);
+
+ mActivity.onResume();
+
+ // Check the FDN menu is not displayed.
+ onView(withText(R.string.fdn)).check(doesNotExist());
+ }
+
+ private Field getField(String fieldName) throws NoSuchFieldException {
+ Field field = mActivity.getClass().getDeclaredField(fieldName);
+ field.setAccessible(true);
+ return field;
+ }
+}
diff --git a/tests/src/com/android/phone/PhoneSearchIndexablesProviderTest.java b/tests/src/com/android/phone/PhoneSearchIndexablesProviderTest.java
index 2176d6b..6b7f825 100644
--- a/tests/src/com/android/phone/PhoneSearchIndexablesProviderTest.java
+++ b/tests/src/com/android/phone/PhoneSearchIndexablesProviderTest.java
@@ -124,16 +124,16 @@
when(mUserManager.isAdminUser()).thenReturn(true);
Cursor cursor2 = mProvider
.queryNonIndexableKeys(SearchIndexablesContract.NON_INDEXABLES_KEYS_COLUMNS);
- assertThat(cursor2.getCount()).isEqualTo(2);
+ assertThat(cursor2.getCount()).isEqualTo(3);
mProvider.setIsEuiccSettingsHidden(true /* isEuiccSettingsHidden */);
Cursor cursor3 = mProvider
.queryNonIndexableKeys(SearchIndexablesContract.NON_INDEXABLES_KEYS_COLUMNS);
- assertThat(cursor3.getCount()).isEqualTo(3);
+ assertThat(cursor3.getCount()).isEqualTo(4);
mProvider.setIsEnhanced4gLteHidden(true /* isEnhanced4gLteHidden */);
Cursor cursor4 = mProvider
.queryNonIndexableKeys(SearchIndexablesContract.NON_INDEXABLES_KEYS_COLUMNS);
- assertThat(cursor4.getCount()).isEqualTo(4);
+ assertThat(cursor4.getCount()).isEqualTo(5);
}
}