From ef1481f589bb286e623c2e8baa95446e93d4f9a0 Mon Sep 17 00:00:00 2001 From: Bonian Chen Date: Tue, 29 Oct 2019 17:07:17 +0800 Subject: [PATCH] [Settings] Manual network select without aggregate Remove the feature of aggregation when performing manual network selection. Bug: 141287649 Test: Manual make RunSettingsRoboTests -j ROBOTEST_FILTER=NetworkSelectSettingsTest make RunSettingsRoboTests -j ROBOTEST_FILTER=NetworkOperatorPreferenceTest Change-Id: I813ad31f9d5cf310877442f5558e236671ab5d23 --- res/xml/choose_network.xml | 5 +- .../network/telephony/CellInfoUtil.java | 151 ++++----- .../telephony/NetworkOperatorPreference.java | 164 +++++++-- .../telephony/NetworkSelectSettings.java | 316 ++++++++++-------- .../NetworkOperatorPreferenceTest.java | 2 +- .../telephony/NetworkSelectSettingsTest.java | 39 ++- 6 files changed, 415 insertions(+), 262 deletions(-) diff --git a/res/xml/choose_network.xml b/res/xml/choose_network.xml index 97ea9be2fd5..4ae1ffb9364 100644 --- a/res/xml/choose_network.xml +++ b/res/xml/choose_network.xml @@ -19,10 +19,7 @@ android:key="mobile_choose_network_pref_screen" android:title="@string/choose_network_title"> - - - \ No newline at end of file + diff --git a/src/com/android/settings/network/telephony/CellInfoUtil.java b/src/com/android/settings/network/telephony/CellInfoUtil.java index def81a10c64..31296945ff7 100644 --- a/src/com/android/settings/network/telephony/CellInfoUtil.java +++ b/src/com/android/settings/network/telephony/CellInfoUtil.java @@ -17,23 +17,26 @@ package com.android.settings.network.telephony; import android.telephony.CellIdentity; -import android.telephony.CellIdentityCdma; import android.telephony.CellIdentityGsm; import android.telephony.CellIdentityLte; +import android.telephony.CellIdentityNr; +import android.telephony.CellIdentityTdscdma; import android.telephony.CellIdentityWcdma; import android.telephony.CellInfo; import android.telephony.CellInfoCdma; import android.telephony.CellInfoGsm; import android.telephony.CellInfoLte; +import android.telephony.CellInfoNr; +import android.telephony.CellInfoTdscdma; import android.telephony.CellInfoWcdma; import android.text.BidiFormatter; import android.text.TextDirectionHeuristics; import android.text.TextUtils; -import android.util.Log; import com.android.internal.telephony.OperatorInfo; import java.util.List; +import java.util.Objects; import java.util.stream.Collectors; /** @@ -46,86 +49,56 @@ public final class CellInfoUtil { private CellInfoUtil() { } - /** - * 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. + * @param cellId contains the information of the network. + * @param networkMccMnc contains the MCCMNC string 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); + public static String getNetworkTitle(CellIdentity cellId, String networkMccMnc) { + if (cellId != null) { + String title = Objects.toString(cellId.getOperatorAlphaLong(), ""); + if (TextUtils.isEmpty(title)) { + title = Objects.toString(cellId.getOperatorAlphaShort(), ""); + } + if (!TextUtils.isEmpty(title)) { + return title; + } } + if (TextUtils.isEmpty(networkMccMnc)) { + return ""; + } + final BidiFormatter bidiFormatter = BidiFormatter.getInstance(); + return bidiFormatter.unicodeWrap(networkMccMnc, TextDirectionHeuristics.LTR); } /** - * Wrap a cell info into an operator info. + * Returns the CellIdentity from CellInfo + * + * @param cellInfo contains the information of the network. + * @return CellIdentity within CellInfo */ - 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("", "", ""); + public static CellIdentity getCellIdentity(CellInfo cellInfo) { + if (cellInfo == null) { + return null; } - return oi; + CellIdentity cellId = null; + if (cellInfo instanceof CellInfoGsm) { + cellId = ((CellInfoGsm) cellInfo).getCellIdentity(); + } else if (cellInfo instanceof CellInfoCdma) { + cellId = ((CellInfoCdma) cellInfo).getCellIdentity(); + } else if (cellInfo instanceof CellInfoWcdma) { + cellId = ((CellInfoWcdma) cellInfo).getCellIdentity(); + } else if (cellInfo instanceof CellInfoTdscdma) { + cellId = ((CellInfoTdscdma) cellInfo).getCellIdentity(); + } else if (cellInfo instanceof CellInfoLte) { + cellId = ((CellInfoLte) cellInfo).getCellIdentity(); + } else if (cellInfo instanceof CellInfoNr) { + cellId = ((CellInfoNr) cellInfo).getCellIdentity(); + } + return cellId; } /** @@ -135,14 +108,14 @@ public final class CellInfoUtil { * we only want to wrap the operator info and PLMN to a CellInfo object. */ public static CellInfo convertOperatorInfoToCellInfo(OperatorInfo operatorInfo) { - String operatorNumeric = operatorInfo.getOperatorNumeric(); + final String operatorNumeric = operatorInfo.getOperatorNumeric(); String mcc = null; String mnc = null; if (operatorNumeric != null && operatorNumeric.matches("^[0-9]{5,6}$")) { mcc = operatorNumeric.substring(0, 3); mnc = operatorNumeric.substring(3); } - CellIdentityGsm cig = new CellIdentityGsm( + final CellIdentityGsm cig = new CellIdentityGsm( Integer.MAX_VALUE /* lac */, Integer.MAX_VALUE /* cid */, Integer.MAX_VALUE /* arfcn */, @@ -152,17 +125,11 @@ public final class CellInfoUtil { operatorInfo.getOperatorAlphaLong(), operatorInfo.getOperatorAlphaShort()); - CellInfoGsm ci = new CellInfoGsm(); + final CellInfoGsm ci = new CellInfoGsm(); ci.setCellIdentity(cig); return ci; } - /** Checks whether the network operator is forbidden. */ - public static boolean isForbidden(CellInfo cellInfo, List forbiddenPlmns) { - String plmn = CellInfoUtil.getOperatorInfoFromCellInfo(cellInfo).getOperatorNumeric(); - return forbiddenPlmns != null && forbiddenPlmns.contains(plmn); - } - /** Convert a list of cellInfos to readable string without sensitive info. */ public static String cellInfoListToString(List cellInfos) { return cellInfos.stream() @@ -172,11 +139,31 @@ public final class CellInfoUtil { /** Convert {@code cellInfo} to a readable string without sensitive info. */ public static String cellInfoToString(CellInfo cellInfo) { - String cellType = cellInfo.getClass().getSimpleName(); - CellIdentity cid = cellInfo.getCellIdentity(); + final String cellType = cellInfo.getClass().getSimpleName(); + final CellIdentity cid = getCellIdentity(cellInfo); + String mcc = null; + String mnc = null; + if (cid != null) { + if (cid instanceof CellIdentityGsm) { + mcc = ((CellIdentityGsm) cid).getMccString(); + mnc = ((CellIdentityGsm) cid).getMncString(); + } else if (cid instanceof CellIdentityWcdma) { + mcc = ((CellIdentityWcdma) cid).getMccString(); + mnc = ((CellIdentityWcdma) cid).getMncString(); + } else if (cid instanceof CellIdentityTdscdma) { + mcc = ((CellIdentityTdscdma) cid).getMccString(); + mnc = ((CellIdentityTdscdma) cid).getMncString(); + } else if (cid instanceof CellIdentityLte) { + mcc = ((CellIdentityLte) cid).getMccString(); + mnc = ((CellIdentityLte) cid).getMncString(); + } else if (cid instanceof CellIdentityNr) { + mcc = ((CellIdentityNr) cid).getMccString(); + mnc = ((CellIdentityNr) cid).getMncString(); + } + } return String.format( "{CellType = %s, isRegistered = %b, mcc = %s, mnc = %s, alphaL = %s, alphaS = %s}", - cellType, cellInfo.isRegistered(), cid.getMccString(), cid.getMncString(), + cellType, cellInfo.isRegistered(), mcc, mnc, cid.getOperatorAlphaLong(), cid.getOperatorAlphaShort()); } } diff --git a/src/com/android/settings/network/telephony/NetworkOperatorPreference.java b/src/com/android/settings/network/telephony/NetworkOperatorPreference.java index 77f40da7f17..db7c8644d8a 100644 --- a/src/com/android/settings/network/telephony/NetworkOperatorPreference.java +++ b/src/com/android/settings/network/telephony/NetworkOperatorPreference.java @@ -19,16 +19,28 @@ package com.android.settings.network.telephony; import static android.telephony.SignalStrength.NUM_SIGNAL_STRENGTH_BINS; import android.content.Context; +import android.telephony.CellIdentity; +import android.telephony.CellIdentityGsm; +import android.telephony.CellIdentityLte; +import android.telephony.CellIdentityNr; +import android.telephony.CellIdentityTdscdma; +import android.telephony.CellIdentityWcdma; import android.telephony.CellInfo; +import android.telephony.CellInfoCdma; +import android.telephony.CellInfoGsm; +import android.telephony.CellInfoLte; +import android.telephony.CellInfoNr; +import android.telephony.CellInfoTdscdma; +import android.telephony.CellInfoWcdma; import android.telephony.CellSignalStrength; import android.util.Log; import androidx.preference.Preference; import com.android.settings.R; -import com.android.settings.Utils; import java.util.List; +import java.util.Objects; /** * A Preference represents a network operator in the NetworkSelectSetting fragment. @@ -41,38 +53,74 @@ public class NetworkOperatorPreference extends Preference { private static final int LEVEL_NONE = -1; private CellInfo mCellInfo; + private CellIdentity mCellId; private List mForbiddenPlmns; private int mLevel = LEVEL_NONE; private boolean mShow4GForLTE; private boolean mUseNewApi; - public NetworkOperatorPreference( - CellInfo cellinfo, Context context, List forbiddenPlmns, boolean show4GForLTE) { + public NetworkOperatorPreference(Context context, CellInfo cellinfo, + List forbiddenPlmns, boolean show4GForLTE) { + this(context, forbiddenPlmns, show4GForLTE); + updateCell(cellinfo); + } + + public NetworkOperatorPreference(Context context, CellIdentity connectedCellId, + List forbiddenPlmns, boolean show4GForLTE) { + this(context, forbiddenPlmns, show4GForLTE); + mCellInfo = null; + mCellId = connectedCellId; + refresh(); + } + + private NetworkOperatorPreference( + Context context, List forbiddenPlmns, boolean show4GForLTE) { super(context); - mCellInfo = cellinfo; mForbiddenPlmns = forbiddenPlmns; mShow4GForLTE = show4GForLTE; mUseNewApi = context.getResources().getBoolean( com.android.internal.R.bool.config_enableNewAutoSelectNetworkUI); + } + + /** + * Change cell information + */ + public void updateCell(CellInfo cellinfo) { + mCellInfo = cellinfo; + mCellId = CellInfoUtil.getCellIdentity(cellinfo); refresh(); } - public CellInfo getCellInfo() { - return mCellInfo; + /** + * Compare cell within preference + */ + public boolean isSameCell(CellInfo cellinfo) { + if (cellinfo == null) { + return false; + } + return mCellId.equals(CellInfoUtil.getCellIdentity(cellinfo)); } /** * Refresh the NetworkOperatorPreference by updating the title and the icon. */ public void refresh() { - if (DBG) Log.d(TAG, "refresh the network: " + CellInfoUtil.getNetworkTitle(mCellInfo)); - String networkTitle = CellInfoUtil.getNetworkTitle(mCellInfo); - if (CellInfoUtil.isForbidden(mCellInfo, mForbiddenPlmns)) { - networkTitle += " " + getContext().getResources().getString(R.string.forbidden_network); - } - setTitle(networkTitle); + String networkTitle = getOperatorName(); - final CellSignalStrength signalStrength = mCellInfo.getCellSignalStrength(); + if ((mForbiddenPlmns != null) && mForbiddenPlmns.contains(getOperatorNumeric())) { + if (DBG) Log.d(TAG, "refresh forbidden network: " + networkTitle); + networkTitle += " " + + getContext().getResources().getString(R.string.forbidden_network); + } else { + if (DBG) Log.d(TAG, "refresh the network: " + networkTitle); + } + setTitle(Objects.toString(networkTitle, "")); + + if (mCellInfo == null) { + return; + } + + final CellSignalStrength signalStrength = getCellSignalStrength(mCellInfo); final int level = signalStrength != null ? signalStrength.getLevel() : LEVEL_NONE; if (DBG) Log.d(TAG, "refresh level: " + String.valueOf(level)); if (mLevel != level) { @@ -88,29 +136,87 @@ public class NetworkOperatorPreference extends Preference { updateIcon(level); } - private int getIconIdForCell(CellInfo ci) { - final int type = ci.getCellIdentity().getType(); - switch (type) { - case CellInfo.TYPE_GSM: - return R.drawable.signal_strength_g; - case CellInfo.TYPE_WCDMA: // fall through - case CellInfo.TYPE_TDSCDMA: - return R.drawable.signal_strength_3g; - case CellInfo.TYPE_LTE: - return mShow4GForLTE - ? R.drawable.ic_signal_strength_4g : R.drawable.signal_strength_lte; - case CellInfo.TYPE_CDMA: - return R.drawable.signal_strength_1x; - default: - return MobileNetworkUtils.NO_CELL_DATA_TYPE_ICON; + /** + * Operator numeric of this cell + */ + public String getOperatorNumeric() { + final CellIdentity cellId = mCellId; + if (cellId == null) { + return null; } + if (cellId instanceof CellIdentityGsm) { + return ((CellIdentityGsm) cellId).getMobileNetworkOperator(); + } + if (cellId instanceof CellIdentityWcdma) { + return ((CellIdentityWcdma) cellId).getMobileNetworkOperator(); + } + if (cellId instanceof CellIdentityTdscdma) { + return ((CellIdentityTdscdma) cellId).getMobileNetworkOperator(); + } + if (cellId instanceof CellIdentityLte) { + return ((CellIdentityLte) cellId).getMobileNetworkOperator(); + } + if (cellId instanceof CellIdentityNr) { + final String mcc = ((CellIdentityNr) cellId).getMccString(); + if (mcc == null) { + return null; + } + return mcc.concat(((CellIdentityNr) cellId).getMncString()); + } + return null; + } + + /** + * Operator name of this cell + */ + public String getOperatorName() { + return CellInfoUtil.getNetworkTitle(mCellId, getOperatorNumeric()); + } + + private int getIconIdForCell(CellInfo ci) { + if (ci instanceof CellInfoGsm) { + return R.drawable.signal_strength_g; + } + if (ci instanceof CellInfoCdma) { + return R.drawable.signal_strength_1x; + } + if ((ci instanceof CellInfoWcdma) || (ci instanceof CellInfoTdscdma)) { + return R.drawable.signal_strength_3g; + } + if (ci instanceof CellInfoLte) { + return mShow4GForLTE + ? R.drawable.ic_signal_strength_4g : R.drawable.signal_strength_lte; + } + return MobileNetworkUtils.NO_CELL_DATA_TYPE_ICON; + } + + private CellSignalStrength getCellSignalStrength(CellInfo ci) { + if (ci instanceof CellInfoGsm) { + return ((CellInfoGsm) ci).getCellSignalStrength(); + } + if (ci instanceof CellInfoCdma) { + return ((CellInfoCdma) ci).getCellSignalStrength(); + } + if (ci instanceof CellInfoWcdma) { + return ((CellInfoWcdma) ci).getCellSignalStrength(); + } + if (ci instanceof CellInfoTdscdma) { + return ((CellInfoTdscdma) ci).getCellSignalStrength(); + } + if (ci instanceof CellInfoLte) { + return ((CellInfoLte) ci).getCellSignalStrength(); + } + if (ci instanceof CellInfoNr) { + return ((CellInfoNr) ci).getCellSignalStrength(); + } + return null; } private void updateIcon(int level) { if (!mUseNewApi || level < 0 || level >= NUM_SIGNAL_STRENGTH_BINS) { return; } - Context context = getContext(); + final Context context = getContext(); setIcon(MobileNetworkUtils.getSignalStrengthIcon(context, level, NUM_SIGNAL_STRENGTH_BINS, getIconIdForCell(mCellInfo), false)); } diff --git a/src/com/android/settings/network/telephony/NetworkSelectSettings.java b/src/com/android/settings/network/telephony/NetworkSelectSettings.java index 4c62de2b5a8..2835b6e96f0 100644 --- a/src/com/android/settings/network/telephony/NetworkSelectSettings.java +++ b/src/com/android/settings/network/telephony/NetworkSelectSettings.java @@ -13,6 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + package com.android.settings.network.telephony; import android.app.Activity; @@ -39,7 +40,6 @@ import androidx.annotation.VisibleForTesting; import androidx.preference.Preference; import androidx.preference.PreferenceCategory; -import com.android.internal.telephony.OperatorInfo; import com.android.settings.R; import com.android.settings.dashboard.DashboardFragment; import com.android.settings.overlay.FeatureFactory; @@ -48,14 +48,12 @@ import com.android.settingslib.utils.ThreadUtils; import java.util.ArrayList; import java.util.Arrays; -import java.util.HashMap; import java.util.List; -import java.util.Map; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; /** - * "Choose network" settings UI for the Phone app. + * "Choose network" settings UI for the Settings app. */ public class NetworkSelectSettings extends DashboardFragment { @@ -66,15 +64,11 @@ public class NetworkSelectSettings extends DashboardFragment { 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"; @VisibleForTesting PreferenceCategory mPreferenceCategory; @VisibleForTesting - PreferenceCategory mConnectedPreferenceCategory; - @VisibleForTesting NetworkOperatorPreference mSelectedPreference; private View mProgressHeader; private Preference mStatusMessagePreference; @@ -89,6 +83,12 @@ public class NetworkSelectSettings extends DashboardFragment { private final ExecutorService mNetworkScanExecutor = Executors.newFixedThreadPool(1); private MetricsFeatureProvider mMetricsFeatureProvider; private boolean mUseNewApi; + private long mRequestIdManualNetworkSelect; + private long mRequestIdManualNetworkScan; + private boolean mScreenIsOn; + private long mWaitingForNumberOfScanResults; + + private static final int MIN_NUMBER_OF_SCAN_REQUIRED = 2; @Override public void onCreate(Bundle icicle) { @@ -98,12 +98,12 @@ public class NetworkSelectSettings extends DashboardFragment { com.android.internal.R.bool.config_enableNewAutoSelectNetworkUI); mSubId = getArguments().getInt(Settings.EXTRA_SUB_ID); - mConnectedPreferenceCategory = findPreference(PREF_KEY_CONNECTED_NETWORK_OPERATOR); mPreferenceCategory = findPreference(PREF_KEY_NETWORK_OPERATORS); mStatusMessagePreference = new Preference(getContext()); mStatusMessagePreference.setSelectable(false); mSelectedPreference = null; - mTelephonyManager = TelephonyManager.from(getContext()).createForSubscriptionId(mSubId); + mTelephonyManager = getContext().getSystemService(TelephonyManager.class) + .createForSubscriptionId(mSubId); mNetworkScanHelper = new NetworkScanHelper( mTelephonyManager, mCallback, mNetworkScanExecutor); PersistableBundle bundle = ((CarrierConfigManager) getContext().getSystemService( @@ -138,12 +138,10 @@ public class NetworkSelectSettings extends DashboardFragment { if (isProgressBarVisible()) { return; } - setProgressBarVisible(true); - - mNetworkScanHelper.startNetworkScan( - mUseNewApi - ? NetworkScanHelper.NETWORK_SCAN_TYPE_INCREMENTAL_RESULTS - : NetworkScanHelper.NETWORK_SCAN_TYPE_WAIT_FOR_ALL_RESULTS); + mScreenIsOn = true; + if (mWaitingForNumberOfScanResults <= 0) { + startNetworkQuery(); + } } /** @@ -160,43 +158,42 @@ public class NetworkSelectSettings extends DashboardFragment { @Override public void onStop() { super.onStop(); + mScreenIsOn = false; + if (mWaitingForNumberOfScanResults <= 0) { + stopNetworkQuery(); + } } @Override public boolean onPreferenceTreeClick(Preference preference) { if (preference != mSelectedPreference) { stopNetworkQuery(); + // Refresh the last selected item in case users reselect network. + clearPreferenceSummary(); if (mSelectedPreference != null) { - mSelectedPreference.setSummary(null); + // Set summary as "Disconnected" to the previously connected network + mSelectedPreference.setSummary(R.string.network_disconnected); } mSelectedPreference = (NetworkOperatorPreference) preference; - CellInfo cellInfo = mSelectedPreference.getCellInfo(); mSelectedPreference.setSummary(R.string.network_connecting); mMetricsFeatureProvider.action(getContext(), SettingsEnums.ACTION_MOBILE_NETWORK_MANUAL_SELECT_NETWORK); - // Set summary as "Disconnected" to the previously connected network - if (mConnectedPreferenceCategory.getPreferenceCount() > 0) { - NetworkOperatorPreference connectedNetworkOperator = (NetworkOperatorPreference) - (mConnectedPreferenceCategory.getPreference(0)); - if (!CellInfoUtil.getNetworkTitle(cellInfo).equals( - CellInfoUtil.getNetworkTitle(connectedNetworkOperator.getCellInfo()))) { - connectedNetworkOperator.setSummary(R.string.network_disconnected); - } - } - setProgressBarVisible(true); // Disable the screen until network is manually set getPreferenceScreen().setEnabled(false); - final OperatorInfo operatorInfo = CellInfoUtil.getOperatorInfoFromCellInfo(cellInfo); + mRequestIdManualNetworkSelect = getNewRequestId(); + mWaitingForNumberOfScanResults = MIN_NUMBER_OF_SCAN_REQUIRED; + final String operatorNumeric = mSelectedPreference.getOperatorNumeric(); ThreadUtils.postOnBackgroundThread(() -> { - Message msg = mHandler.obtainMessage(EVENT_SET_NETWORK_SELECTION_MANUALLY_DONE); + final Message msg = mHandler.obtainMessage( + EVENT_SET_NETWORK_SELECTION_MANUALLY_DONE); msg.obj = mTelephonyManager.setNetworkSelectionModeManual( - operatorInfo, true /* persistSelection */); + operatorNumeric, true /* persistSelection */); msg.sendToTarget(); }); } @@ -224,35 +221,85 @@ public class NetworkSelectSettings extends DashboardFragment { public void handleMessage(Message msg) { switch (msg.what) { case EVENT_SET_NETWORK_SELECTION_MANUALLY_DONE: - setProgressBarVisible(false); - getPreferenceScreen().setEnabled(true); - - boolean isSucceed = (boolean) msg.obj; - mSelectedPreference.setSummary(isSucceed - ? R.string.network_connected - : R.string.network_could_not_connect); + final boolean isSucceed = (boolean) msg.obj; + if (isSucceed) { + // Don't enable screen here. Wait until result of network re-scan. + startNetworkQuery(); + } else { + stopNetworkQuery(); + setProgressBarVisible(false); + getPreferenceScreen().setEnabled(true); + // For failure case, only update the summary of selected item. + mSelectedPreference.setSummary(R.string.network_could_not_connect); + } break; case EVENT_NETWORK_SCAN_RESULTS: - List results = aggregateCellInfoList((List) msg.obj); - Log.d(TAG, "CellInfoList after aggregation: " - + CellInfoUtil.cellInfoListToString(results)); - mCellInfoList = new ArrayList<>(results); - if (mCellInfoList != null && mCellInfoList.size() != 0) { - updateAllPreferenceCategory(); - } else { - addMessagePreference(R.string.empty_networks_list); + final List results = (List) msg.obj; + if (mRequestIdManualNetworkScan < mRequestIdManualNetworkSelect) { + Log.d(TAG, "CellInfoList (drop): " + + CellInfoUtil.cellInfoListToString(new ArrayList<>(results))); + break; + } + mWaitingForNumberOfScanResults--; + if ((!mScreenIsOn) && (mWaitingForNumberOfScanResults <= 0)) { + stopNetworkQuery(); } + mCellInfoList = new ArrayList<>(results); + Log.d(TAG, "CellInfoList: " + CellInfoUtil.cellInfoListToString(mCellInfoList)); + if (mCellInfoList != null && mCellInfoList.size() != 0) { + final NetworkOperatorPreference connectedPref = + updateAllPreferenceCategory(); + if (connectedPref != null) { + // update selected preference instance into connected preference + if (mSelectedPreference != null) { + mSelectedPreference = connectedPref; + } + } else if (!getPreferenceScreen().isEnabled()) { + if (connectedPref == null) { + mSelectedPreference.setSummary(R.string.network_connecting); + } + } + getPreferenceScreen().setEnabled(true); + } else if (getPreferenceScreen().isEnabled()) { + addMessagePreference(R.string.empty_networks_list); + // keep showing progress bar, it will be stopped when error or completed + setProgressBarVisible(true); + } break; case EVENT_NETWORK_SCAN_ERROR: stopNetworkQuery(); - addMessagePreference(R.string.network_query_error); + Log.i(TAG, "Network scan failure " + msg.arg1 + ":" + + " scan request 0x" + Long.toHexString(mRequestIdManualNetworkScan) + + ", waiting for scan results = " + mWaitingForNumberOfScanResults + + ", select request 0x" + + Long.toHexString(mRequestIdManualNetworkSelect)); + if (mRequestIdManualNetworkScan < mRequestIdManualNetworkSelect) { + break; + } + if (!getPreferenceScreen().isEnabled()) { + clearPreferenceSummary(); + getPreferenceScreen().setEnabled(true); + } else { + addMessagePreference(R.string.network_query_error); + } break; case EVENT_NETWORK_SCAN_COMPLETED: stopNetworkQuery(); - if (mCellInfoList == null) { + Log.d(TAG, "Network scan complete:" + + " scan request 0x" + Long.toHexString(mRequestIdManualNetworkScan) + + ", waiting for scan results = " + mWaitingForNumberOfScanResults + + ", select request 0x" + + Long.toHexString(mRequestIdManualNetworkSelect)); + if (mRequestIdManualNetworkScan < mRequestIdManualNetworkSelect) { + break; + } + if (!getPreferenceScreen().isEnabled()) { + clearPreferenceSummary(); + getPreferenceScreen().setEnabled(true); + } else if (mCellInfoList == null) { // In case the scan timeout before getting any results addMessagePreference(R.string.empty_networks_list); } @@ -265,48 +312,86 @@ public class NetworkSelectSettings extends DashboardFragment { private final NetworkScanHelper.NetworkScanCallback mCallback = new NetworkScanHelper.NetworkScanCallback() { public void onResults(List results) { - Message msg = mHandler.obtainMessage(EVENT_NETWORK_SCAN_RESULTS, results); + final Message msg = mHandler.obtainMessage(EVENT_NETWORK_SCAN_RESULTS, results); msg.sendToTarget(); } public void onComplete() { - Message msg = mHandler.obtainMessage(EVENT_NETWORK_SCAN_COMPLETED); + final Message msg = mHandler.obtainMessage(EVENT_NETWORK_SCAN_COMPLETED); msg.sendToTarget(); } public void onError(int error) { - Message msg = mHandler.obtainMessage(EVENT_NETWORK_SCAN_ERROR, error, + final Message msg = mHandler.obtainMessage(EVENT_NETWORK_SCAN_ERROR, error, 0 /* arg2 */); msg.sendToTarget(); } }; /** - * 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. + * Update the content of network operators list. + * + * @return preference which shows connected */ @VisibleForTesting - void updateAllPreferenceCategory() { - updateConnectedPreferenceCategory(); + NetworkOperatorPreference updateAllPreferenceCategory() { + int numberOfPreferences = mPreferenceCategory.getPreferenceCount(); - mPreferenceCategory.removeAll(); + // remove unused preferences + while (numberOfPreferences > mCellInfoList.size()) { + numberOfPreferences--; + mPreferenceCategory.removePreference( + mPreferenceCategory.getPreference(numberOfPreferences)); + } + + // update selected preference instance by index for (int index = 0; index < mCellInfoList.size(); index++) { - if (!mCellInfoList.get(index).isRegistered()) { - NetworkOperatorPreference pref = new NetworkOperatorPreference( - mCellInfoList.get(index), getPrefContext(), mForbiddenPlmns, mShow4GForLTE); - pref.setKey(CellInfoUtil.getNetworkTitle(mCellInfoList.get(index))); + final CellInfo cellInfo = mCellInfoList.get(index); + + if ((mSelectedPreference != null) && mSelectedPreference.isSameCell(cellInfo)) { + mSelectedPreference = (NetworkOperatorPreference) + (mPreferenceCategory.getPreference(index)); + } + } + + // update the content of preference + NetworkOperatorPreference connectedPref = null; + for (int index = 0; index < mCellInfoList.size(); index++) { + final CellInfo cellInfo = mCellInfoList.get(index); + + NetworkOperatorPreference pref = null; + if (index < numberOfPreferences) { + final Preference rawPref = mPreferenceCategory.getPreference(index); + if (rawPref instanceof NetworkOperatorPreference) { + // replace existing preference + pref = (NetworkOperatorPreference) rawPref; + pref.updateCell(cellInfo); + } else { + mPreferenceCategory.removePreference(rawPref); + } + } + if (pref == null) { + // add new preference + pref = new NetworkOperatorPreference(getPrefContext(), + cellInfo, mForbiddenPlmns, mShow4GForLTE); pref.setOrder(index); mPreferenceCategory.addPreference(pref); } + pref.setKey(pref.getOperatorName()); + + if (mCellInfoList.get(index).isRegistered()) { + pref.setSummary(R.string.network_connected); + connectedPref = pref; + } else { + pref.setSummary(null); + } } + + return connectedPref; } /** - * Config the connected network operator preference when the page was created. When user get + * Config the network operator list 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#getNetworkRegistrationInfoList()} to get the currently @@ -320,63 +405,45 @@ public class NetworkSelectSettings extends DashboardFragment { private void forceUpdateConnectedPreferenceCategory() { if (mTelephonyManager.getDataState() == mTelephonyManager.DATA_CONNECTED) { // Try to get the network registration states - ServiceState ss = mTelephonyManager.getServiceState(); - List networkList = + final ServiceState ss = mTelephonyManager.getServiceState(); + final List networkList = ss.getNetworkRegistrationInfoListForTransportType( AccessNetworkConstants.TRANSPORT_TYPE_WWAN); if (networkList == null || networkList.size() == 0) { - // Remove the connected network operators category - mConnectedPreferenceCategory.setVisible(false); return; } - CellIdentity cellIdentity = networkList.get(0).getCellIdentity(); - CellInfo cellInfo = CellInfoUtil.wrapCellInfoWithCellIdentity(cellIdentity); - if (cellInfo != null) { - NetworkOperatorPreference pref = new NetworkOperatorPreference( - cellInfo, getPrefContext(), mForbiddenPlmns, mShow4GForLTE); - pref.setTitle(MobileNetworkUtils.getCurrentCarrierNameForDisplay( - getPrefContext(), mSubId)); - 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(SignalStrength.NUM_SIGNAL_STRENGTH_BINS - 1); - mConnectedPreferenceCategory.addPreference(pref); - } else { - // Remove the connected network operators category - mConnectedPreferenceCategory.setVisible(false); + for (NetworkRegistrationInfo regInfo : networkList) { + final CellIdentity cellIdentity = regInfo.getCellIdentity(); + if (cellIdentity != null) { + final NetworkOperatorPreference pref = new NetworkOperatorPreference( + getPrefContext(), cellIdentity, mForbiddenPlmns, mShow4GForLTE); + 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(SignalStrength.NUM_SIGNAL_STRENGTH_BINS - 1); + mPreferenceCategory.addPreference(pref); + } } - } else { - // Remove the connected network operators category - mConnectedPreferenceCategory.setVisible(false); } } /** - * 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. + * Clear all of the preference summary */ - private void updateConnectedPreferenceCategory() { - CellInfo connectedNetworkOperator = null; - for (CellInfo cellInfo : mCellInfoList) { - if (cellInfo.isRegistered()) { - connectedNetworkOperator = cellInfo; - break; - } - } - - if (connectedNetworkOperator != null) { - addConnectedNetworkOperatorPreference(connectedNetworkOperator); + private void clearPreferenceSummary() { + int idxPreference = mPreferenceCategory.getPreferenceCount(); + while (idxPreference > 0) { + idxPreference--; + final NetworkOperatorPreference networkOperator = (NetworkOperatorPreference) + (mPreferenceCategory.getPreference(idxPreference)); + networkOperator.setSummary(null); } } - private void addConnectedNetworkOperatorPreference(CellInfo cellInfo) { - mConnectedPreferenceCategory.removeAll(); - final NetworkOperatorPreference pref = new NetworkOperatorPreference( - cellInfo, getPrefContext(), mForbiddenPlmns, mShow4GForLTE); - pref.setSummary(R.string.network_connected); - mConnectedPreferenceCategory.addPreference(pref); - mConnectedPreferenceCategory.setVisible(true); + private long getNewRequestId() { + return Math.max(mRequestIdManualNetworkSelect, + mRequestIdManualNetworkScan) + 1; } private boolean isProgressBarVisible() { @@ -395,39 +462,26 @@ public class NetworkSelectSettings extends DashboardFragment { private void addMessagePreference(int messageId) { setProgressBarVisible(false); mStatusMessagePreference.setTitle(messageId); - mConnectedPreferenceCategory.setVisible(false); mPreferenceCategory.removeAll(); mPreferenceCategory.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 aggregateCellInfoList(List cellInfoList) { - Map map = new HashMap<>(); - for (CellInfo cellInfo : cellInfoList) { - String plmn = CellInfoUtil.getOperatorInfoFromCellInfo(cellInfo).getOperatorNumeric(); - if (cellInfo.isRegistered() || !map.containsKey(plmn)) { - map.put(plmn, cellInfo); - } else { - if (map.get(plmn).isRegistered() - || map.get(plmn).getCellSignalStrength().getLevel() - > cellInfo.getCellSignalStrength().getLevel()) { - // Skip if the stored cellInfo is registered or has higher signal strength level - continue; - } - // Otherwise replace it with the new CellInfo - map.put(plmn, cellInfo); - } + private void startNetworkQuery() { + setProgressBarVisible(true); + if (mNetworkScanHelper != null) { + mRequestIdManualNetworkScan = getNewRequestId(); + mWaitingForNumberOfScanResults = MIN_NUMBER_OF_SCAN_REQUIRED; + mNetworkScanHelper.startNetworkScan( + mUseNewApi + ? NetworkScanHelper.NETWORK_SCAN_TYPE_INCREMENTAL_RESULTS + : NetworkScanHelper.NETWORK_SCAN_TYPE_WAIT_FOR_ALL_RESULTS); } - return new ArrayList<>(map.values()); } private void stopNetworkQuery() { setProgressBarVisible(false); if (mNetworkScanHelper != null) { + mWaitingForNumberOfScanResults = 0; mNetworkScanHelper.stopNetworkQuery(); } } diff --git a/tests/robotests/src/com/android/settings/network/telephony/NetworkOperatorPreferenceTest.java b/tests/robotests/src/com/android/settings/network/telephony/NetworkOperatorPreferenceTest.java index 704dd95f00c..3a61195018c 100644 --- a/tests/robotests/src/com/android/settings/network/telephony/NetworkOperatorPreferenceTest.java +++ b/tests/robotests/src/com/android/settings/network/telephony/NetworkOperatorPreferenceTest.java @@ -60,7 +60,7 @@ public class NetworkOperatorPreferenceTest { when(mResources.getBoolean(com.android.internal.R.bool.config_enableNewAutoSelectNetworkUI)) .thenReturn(false); final NetworkOperatorPreference preference = spy( - new NetworkOperatorPreference(mCellInfo, mContext, + new NetworkOperatorPreference(mContext, mCellInfo, new ArrayList<>() /* forbiddenPlmns */, false /* show4GForLTE */)); preference.setIcon(LEVEL); diff --git a/tests/robotests/src/com/android/settings/network/telephony/NetworkSelectSettingsTest.java b/tests/robotests/src/com/android/settings/network/telephony/NetworkSelectSettingsTest.java index 7dfc8a35323..6bee38fba9e 100644 --- a/tests/robotests/src/com/android/settings/network/telephony/NetworkSelectSettingsTest.java +++ b/tests/robotests/src/com/android/settings/network/telephony/NetworkSelectSettingsTest.java @@ -23,7 +23,11 @@ import static org.mockito.Mockito.spy; import static org.mockito.Mockito.when; import android.content.Context; -import android.telephony.CellInfo; +import android.content.SharedPreferences; +import android.telephony.CellIdentityLte; +import android.telephony.CellIdentityWcdma; +import android.telephony.CellInfoLte; +import android.telephony.CellInfoWcdma; import android.telephony.SubscriptionManager; import android.telephony.TelephonyManager; @@ -43,20 +47,27 @@ import java.util.Arrays; @RunWith(RobolectricTestRunner.class) public class NetworkSelectSettingsTest { private static final int SUB_ID = 2; + private static final String CARRIER_NAME1 = "CarrierName1"; + private static final String CARRIER_NAME2 = "CarrierName2"; @Mock private TelephonyManager mTelephonyManager; @Mock private SubscriptionManager mSubscriptionManager; @Mock - private CellInfo mCellInfo1; + private CellInfoWcdma mCellInfo1; @Mock - private CellInfo mCellInfo2; + private CellIdentityWcdma mCellId1; + @Mock + private CellInfoLte mCellInfo2; + @Mock + private CellIdentityLte mCellId2; @Mock private PreferenceManager mPreferenceManager; + @Mock + private SharedPreferences mSharedPreferences; private Context mContext; - private PreferenceCategory mConnectedPreferenceCategory; private PreferenceCategory mPreferenceCategory; private NetworkSelectSettings mNetworkSelectSettings; @@ -71,10 +82,13 @@ public class NetworkSelectSettingsTest { when(mTelephonyManager.createForSubscriptionId(SUB_ID)).thenReturn(mTelephonyManager); when(mCellInfo1.isRegistered()).thenReturn(true); + when(mCellInfo1.getCellIdentity()).thenReturn(mCellId1); + when(mCellId1.getOperatorAlphaLong()).thenReturn(CARRIER_NAME1); when(mCellInfo2.isRegistered()).thenReturn(false); + when(mCellInfo2.getCellIdentity()).thenReturn(mCellId2); + when(mCellId2.getOperatorAlphaLong()).thenReturn(CARRIER_NAME2); - mConnectedPreferenceCategory = spy(new PreferenceCategory(mContext)); - doReturn(mPreferenceManager).when(mConnectedPreferenceCategory).getPreferenceManager(); + doReturn(mSharedPreferences).when(mPreferenceManager).getSharedPreferences(); mPreferenceCategory = spy(new PreferenceCategory(mContext)); doReturn(mPreferenceManager).when(mPreferenceCategory).getPreferenceManager(); @@ -84,23 +98,18 @@ public class NetworkSelectSettingsTest { doReturn(mContext).when(mPreferenceManager).getContext(); mNetworkSelectSettings.mTelephonyManager = mTelephonyManager; - mNetworkSelectSettings.mConnectedPreferenceCategory = mConnectedPreferenceCategory; mNetworkSelectSettings.mPreferenceCategory = mPreferenceCategory; mNetworkSelectSettings.mCellInfoList = Arrays.asList(mCellInfo1, mCellInfo2); } @Test - public void updateAllPreferenceCategory_containCorrectPreference() { + public void updateAllPreferenceCategory_correctOrderingPreference() { mNetworkSelectSettings.updateAllPreferenceCategory(); - assertThat(mConnectedPreferenceCategory.getPreferenceCount()).isEqualTo(1); - final NetworkOperatorPreference connectedPreference = - (NetworkOperatorPreference) mConnectedPreferenceCategory.getPreference(0); - assertThat(connectedPreference.getCellInfo()).isEqualTo(mCellInfo1); - assertThat(mPreferenceCategory.getPreferenceCount()).isEqualTo(1); + assertThat(mPreferenceCategory.getPreferenceCount()).isEqualTo(2); final NetworkOperatorPreference preference = - (NetworkOperatorPreference) mPreferenceCategory.getPreference(0); - assertThat(preference.getCellInfo()).isEqualTo(mCellInfo2); + (NetworkOperatorPreference) mPreferenceCategory.getPreference(1); + assertThat(preference.getOperatorName()).isEqualTo(mCellId2.getOperatorAlphaLong()); } @Test