[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
This commit is contained in:
Bonian Chen
2019-10-29 17:07:17 +08:00
parent 7d744c8f18
commit ef1481f589
6 changed files with 415 additions and 262 deletions

View File

@@ -19,9 +19,6 @@
android:key="mobile_choose_network_pref_screen"
android:title="@string/choose_network_title">
<PreferenceCategory
android:key="connected_network_operator_preference"/>
<PreferenceCategory
android:key="network_operators_preference"/>

View File

@@ -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<String> 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<CellInfo> 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());
}
}

View File

@@ -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<String> mForbiddenPlmns;
private int mLevel = LEVEL_NONE;
private boolean mShow4GForLTE;
private boolean mUseNewApi;
public NetworkOperatorPreference(
CellInfo cellinfo, Context context, List<String> forbiddenPlmns, boolean show4GForLTE) {
public NetworkOperatorPreference(Context context, CellInfo cellinfo,
List<String> forbiddenPlmns, boolean show4GForLTE) {
this(context, forbiddenPlmns, show4GForLTE);
updateCell(cellinfo);
}
public NetworkOperatorPreference(Context context, CellIdentity connectedCellId,
List<String> forbiddenPlmns, boolean show4GForLTE) {
this(context, forbiddenPlmns, show4GForLTE);
mCellInfo = null;
mCellId = connectedCellId;
refresh();
}
private NetworkOperatorPreference(
Context context, List<String> 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));
}

View File

@@ -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<CellInfo> results = aggregateCellInfoList((List<CellInfo>) 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<CellInfo> results = (List<CellInfo>) 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<CellInfo> 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<NetworkRegistrationInfo> networkList =
final ServiceState ss = mTelephonyManager.getServiceState();
final List<NetworkRegistrationInfo> 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<CellInfo> aggregateCellInfoList(List<CellInfo> cellInfoList) {
Map<String, CellInfo> 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();
}
}

View File

@@ -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);

View File

@@ -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