diff --git a/res/values/config.xml b/res/values/config.xml index 8c158e78525..9ed7536e5f7 100755 --- a/res/values/config.xml +++ b/res/values/config.xml @@ -545,4 +545,7 @@ 2 3 + + + false diff --git a/src/com/android/settings/network/telephony/CellInfoUtil.java b/src/com/android/settings/network/telephony/CellInfoUtil.java index d7d2b18c8d0..58b668b7d01 100644 --- a/src/com/android/settings/network/telephony/CellInfoUtil.java +++ b/src/com/android/settings/network/telephony/CellInfoUtil.java @@ -143,29 +143,71 @@ public final class CellInfoUtil { public static String cellInfoToString(CellInfo cellInfo) { 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(); - } - } + String mcc = getCellIdentityMcc(cid); + String mnc = getCellIdentityMnc(cid); return String.format( "{CellType = %s, isRegistered = %b, mcc = %s, mnc = %s, alphaL = %s, alphaS = %s}", cellType, cellInfo.isRegistered(), mcc, mnc, cid.getOperatorAlphaLong(), cid.getOperatorAlphaShort()); } + + /** + * Returns the MccMnc. + * + * @param cid contains the identity of the network. + * @return MccMnc string. + */ + public static String getCellIdentityMccMnc(CellIdentity cid) { + String mcc = getCellIdentityMcc(cid); + String mnc = getCellIdentityMnc(cid); + return (mcc == null || mnc == null) ? null : mcc + mnc; + } + + /** + * Returns the Mcc. + * + * @param cid contains the identity of the network. + * @return Mcc string. + */ + public static String getCellIdentityMcc(CellIdentity cid) { + String mcc = null; + if (cid != null) { + if (cid instanceof CellIdentityGsm) { + mcc = ((CellIdentityGsm) cid).getMccString(); + } else if (cid instanceof CellIdentityWcdma) { + mcc = ((CellIdentityWcdma) cid).getMccString(); + } else if (cid instanceof CellIdentityTdscdma) { + mcc = ((CellIdentityTdscdma) cid).getMccString(); + } else if (cid instanceof CellIdentityLte) { + mcc = ((CellIdentityLte) cid).getMccString(); + } else if (cid instanceof CellIdentityNr) { + mcc = ((CellIdentityNr) cid).getMccString(); + } + } + return (mcc == null) ? null : mcc; + } + + /** + * Returns the Mnc. + * + * @param cid contains the identity of the network. + * @return Mcc string. + */ + public static String getCellIdentityMnc(CellIdentity cid) { + String mnc = null; + if (cid != null) { + if (cid instanceof CellIdentityGsm) { + mnc = ((CellIdentityGsm) cid).getMncString(); + } else if (cid instanceof CellIdentityWcdma) { + mnc = ((CellIdentityWcdma) cid).getMncString(); + } else if (cid instanceof CellIdentityTdscdma) { + mnc = ((CellIdentityTdscdma) cid).getMncString(); + } else if (cid instanceof CellIdentityLte) { + mnc = ((CellIdentityLte) cid).getMncString(); + } else if (cid instanceof CellIdentityNr) { + mnc = ((CellIdentityNr) cid).getMncString(); + } + } + return (mnc == null) ? null : mnc; + } } diff --git a/src/com/android/settings/network/telephony/NetworkSelectSettings.java b/src/com/android/settings/network/telephony/NetworkSelectSettings.java index 6f315be8972..62eb690b8d9 100644 --- a/src/com/android/settings/network/telephony/NetworkSelectSettings.java +++ b/src/com/android/settings/network/telephony/NetworkSelectSettings.java @@ -66,6 +66,7 @@ public class NetworkSelectSettings extends DashboardFragment { private static final int EVENT_NETWORK_SCAN_COMPLETED = 4; private static final String PREF_KEY_NETWORK_OPERATORS = "network_operators_preference"; + private static final int MIN_NUMBER_OF_SCAN_REQUIRED = 2; @VisibleForTesting PreferenceCategory mPreferenceCategory; @@ -87,8 +88,8 @@ public class NetworkSelectSettings extends DashboardFragment { private long mRequestIdManualNetworkSelect; private long mRequestIdManualNetworkScan; private long mWaitingForNumberOfScanResults; - - private static final int MIN_NUMBER_OF_SCAN_REQUIRED = 2; + @VisibleForTesting + boolean mIsAggregationEnabled = false; @Override public void onCreate(Bundle icicle) { @@ -115,6 +116,11 @@ public class NetworkSelectSettings extends DashboardFragment { mMetricsFeatureProvider = FeatureFactory .getFactory(getContext()).getMetricsFeatureProvider(); + + mIsAggregationEnabled = getContext().getResources().getBoolean( + R.bool.config_network_selection_list_aggregation_enabled); + Log.d(TAG, "init: mUseNewApi:" + mUseNewApi + + " ,mIsAggregationEnabled:" + mIsAggregationEnabled); } @Override @@ -244,7 +250,7 @@ public class NetworkSelectSettings extends DashboardFragment { stopNetworkQuery(); } - mCellInfoList = new ArrayList<>(results); + mCellInfoList = doAggregation(results); Log.d(TAG, "CellInfoList: " + CellInfoUtil.cellInfoListToString(mCellInfoList)); if (mCellInfoList != null && mCellInfoList.size() != 0) { final NetworkOperatorPreference connectedPref = @@ -308,6 +314,31 @@ public class NetworkSelectSettings extends DashboardFragment { } }; + @VisibleForTesting + List doAggregation(List cellInfoListInput) { + if (!mIsAggregationEnabled) { + Log.d(TAG, "no aggregation"); + return new ArrayList<>(cellInfoListInput); + } + ArrayList aggregatedList = new ArrayList<>(); + for (CellInfo cellInfo : cellInfoListInput) { + String plmn = CellInfoUtil.getNetworkTitle(cellInfo.getCellIdentity(), + CellInfoUtil.getCellIdentityMccMnc(cellInfo.getCellIdentity())); + Class className = cellInfo.getClass(); + + if (aggregatedList.stream().anyMatch( + i -> { + return (CellInfoUtil.getNetworkTitle(i.getCellIdentity(), + CellInfoUtil.getCellIdentityMccMnc(i.getCellIdentity())) == plmn) + && i.getClass().equals(className); + })) { + continue; + } + aggregatedList.add(cellInfo); + } + return aggregatedList; + } + private final NetworkScanHelper.NetworkScanCallback mCallback = new NetworkScanHelper.NetworkScanCallback() { public void onResults(List results) { diff --git a/tests/robotests/src/com/android/settings/network/telephony/NetworkSelectSettingsTest.java b/tests/robotests/src/com/android/settings/network/telephony/NetworkSelectSettingsTest.java deleted file mode 100644 index 6bee38fba9e..00000000000 --- a/tests/robotests/src/com/android/settings/network/telephony/NetworkSelectSettingsTest.java +++ /dev/null @@ -1,122 +0,0 @@ -/* - * Copyright (C) 2018 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.settings.network.telephony; - -import static com.google.common.truth.Truth.assertThat; - -import static org.mockito.Mockito.doReturn; -import static org.mockito.Mockito.spy; -import static org.mockito.Mockito.when; - -import android.content.Context; -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; - -import androidx.preference.PreferenceCategory; -import androidx.preference.PreferenceManager; - -import org.junit.Before; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.mockito.Mock; -import org.mockito.MockitoAnnotations; -import org.robolectric.RobolectricTestRunner; -import org.robolectric.RuntimeEnvironment; - -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 CellInfoWcdma mCellInfo1; - @Mock - private CellIdentityWcdma mCellId1; - @Mock - private CellInfoLte mCellInfo2; - @Mock - private CellIdentityLte mCellId2; - @Mock - private PreferenceManager mPreferenceManager; - @Mock - private SharedPreferences mSharedPreferences; - private Context mContext; - - private PreferenceCategory mPreferenceCategory; - - private NetworkSelectSettings mNetworkSelectSettings; - - @Before - public void setUp() { - MockitoAnnotations.initMocks(this); - - mContext = spy(RuntimeEnvironment.application); - when(mContext.getSystemService(Context.TELEPHONY_SERVICE)).thenReturn(mTelephonyManager); - when(mContext.getSystemService(SubscriptionManager.class)).thenReturn(mSubscriptionManager); - 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); - - doReturn(mSharedPreferences).when(mPreferenceManager).getSharedPreferences(); - mPreferenceCategory = spy(new PreferenceCategory(mContext)); - doReturn(mPreferenceManager).when(mPreferenceCategory).getPreferenceManager(); - - mNetworkSelectSettings = spy(new NetworkSelectSettings()); - doReturn(mContext).when(mNetworkSelectSettings).getContext(); - doReturn(mPreferenceManager).when(mNetworkSelectSettings).getPreferenceManager(); - doReturn(mContext).when(mPreferenceManager).getContext(); - - mNetworkSelectSettings.mTelephonyManager = mTelephonyManager; - mNetworkSelectSettings.mPreferenceCategory = mPreferenceCategory; - mNetworkSelectSettings.mCellInfoList = Arrays.asList(mCellInfo1, mCellInfo2); - } - - @Test - public void updateAllPreferenceCategory_correctOrderingPreference() { - mNetworkSelectSettings.updateAllPreferenceCategory(); - - assertThat(mPreferenceCategory.getPreferenceCount()).isEqualTo(2); - final NetworkOperatorPreference preference = - (NetworkOperatorPreference) mPreferenceCategory.getPreference(1); - assertThat(preference.getOperatorName()).isEqualTo(mCellId2.getOperatorAlphaLong()); - } - - @Test - public void updateForbiddenPlmns_forbiddenPlmnsNull_shouldNotCrash() { - when(mTelephonyManager.getForbiddenPlmns()).thenReturn(null); - - // Should not Crash - mNetworkSelectSettings.updateForbiddenPlmns(); - } -} diff --git a/tests/unit/src/com/android/settings/network/telephony/NetworkSelectSettingsTest.java b/tests/unit/src/com/android/settings/network/telephony/NetworkSelectSettingsTest.java new file mode 100644 index 00000000000..769cbca2592 --- /dev/null +++ b/tests/unit/src/com/android/settings/network/telephony/NetworkSelectSettingsTest.java @@ -0,0 +1,198 @@ +/* + * Copyright (C) 2021 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.settings.network.telephony; + +import static com.google.common.truth.Truth.assertThat; + +import static org.mockito.Mockito.doReturn; +import static org.mockito.Mockito.spy; +import static org.mockito.Mockito.when; + +import android.content.Context; +import android.content.SharedPreferences; +import android.telephony.CellIdentityGsm; +import android.telephony.CellIdentityLte; +import android.telephony.CellInfo; +import android.telephony.CellInfoGsm; +import android.telephony.CellInfoLte; +import android.telephony.CellSignalStrengthGsm; +import android.telephony.CellSignalStrengthLte; +import android.telephony.SubscriptionManager; +import android.telephony.TelephonyManager; + +import androidx.preference.PreferenceCategory; +import androidx.preference.PreferenceManager; +import androidx.test.annotation.UiThreadTest; +import androidx.test.core.app.ApplicationProvider; +import androidx.test.ext.junit.runners.AndroidJUnit4; + +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.Mock; +import org.mockito.MockitoAnnotations; + +import java.util.Arrays; +import java.util.Collections; +import java.util.List; + +@RunWith(AndroidJUnit4.class) +public class NetworkSelectSettingsTest { + private static final int SUB_ID = 2; + + @Mock + private TelephonyManager mTelephonyManager; + @Mock + private SubscriptionManager mSubscriptionManager; + @Mock + private PreferenceManager mPreferenceManager; + @Mock + private SharedPreferences mSharedPreferences; + + private Context mContext; + private PreferenceCategory mPreferenceCategory; + private NetworkSelectSettings mNetworkSelectSettings; + + @Before + @UiThreadTest + public void setUp() { + MockitoAnnotations.initMocks(this); + mContext = spy(ApplicationProvider.getApplicationContext()); + + when(mContext.getSystemService(Context.TELEPHONY_SERVICE)).thenReturn(mTelephonyManager); + when(mContext.getSystemService(SubscriptionManager.class)).thenReturn(mSubscriptionManager); + when(mTelephonyManager.createForSubscriptionId(SUB_ID)).thenReturn(mTelephonyManager); + + doReturn(mSharedPreferences).when(mPreferenceManager).getSharedPreferences(); + mPreferenceCategory = spy(new PreferenceCategory(mContext)); + doReturn(mPreferenceManager).when(mPreferenceCategory).getPreferenceManager(); + + mNetworkSelectSettings = spy(new NetworkSelectSettings()); + doReturn(mContext).when(mNetworkSelectSettings).getContext(); + doReturn(mPreferenceManager).when(mNetworkSelectSettings).getPreferenceManager(); + doReturn(mContext).when(mPreferenceManager).getContext(); + + mNetworkSelectSettings.mTelephonyManager = mTelephonyManager; + mNetworkSelectSettings.mPreferenceCategory = mPreferenceCategory; + mNetworkSelectSettings.mCellInfoList = + Arrays.asList(createLteCellInfo(true, 123, "123", "232", "CarrierA"), + createGsmCellInfo(false, 123, "123", "232", "CarrierB")); + mNetworkSelectSettings.mIsAggregationEnabled = true; + } + + @Test + @UiThreadTest + public void updateAllPreferenceCategory_correctOrderingPreference() { + mNetworkSelectSettings.updateAllPreferenceCategory(); + + assertThat(mPreferenceCategory.getPreferenceCount()).isEqualTo(2); + final NetworkOperatorPreference preference = + (NetworkOperatorPreference) mPreferenceCategory.getPreference(1); + assertThat(preference.getOperatorName()).isEqualTo("CarrierB"); + } + + @Test + @UiThreadTest + public void updateForbiddenPlmns_forbiddenPlmnsNull_shouldNotCrash() { + when(mTelephonyManager.getForbiddenPlmns()).thenReturn(null); + + // Should not Crash + mNetworkSelectSettings.updateForbiddenPlmns(); + } + + @Test + public void doAggregation_hasDuplicateItemsDiffCellIdCase1_removeSamePlmnRatItem() { + List testList = Arrays.asList( + createLteCellInfo(true, 123, "123", "232", "CarrierA"), + createLteCellInfo(true, 1234, "123", "232", "CarrierA"), + createGsmCellInfo(false, 123, "123", "232", "CarrierB")); + List expected = Arrays.asList( + createLteCellInfo(true, 123, "123", "232", "CarrierA"), + createGsmCellInfo(false, 123, "123", "232", "CarrierB")); + assertThat(mNetworkSelectSettings.doAggregation(testList)).isEqualTo(expected); + } + + @Test + public void doAggregation_hasDuplicateItemsDiffCellIdCase2_removeSamePlmnRatItem() { + List testList = Arrays.asList( + createLteCellInfo(true, 123, "123", "232", "CarrierA"), + createGsmCellInfo(false, 123, "123", "232", "CarrierB"), + createLteCellInfo(false, 1234, "123", "232", "CarrierB"), + createGsmCellInfo(false, 1234, "123", "232", "CarrierB")); + List expected = Arrays.asList( + createLteCellInfo(true, 123, "123", "232", "CarrierA"), + createGsmCellInfo(false, 123, "123", "232", "CarrierB"), + createLteCellInfo(false, 1234, "123", "232", "CarrierB")); + assertThat(mNetworkSelectSettings.doAggregation(testList)).isEqualTo(expected); + } + + @Test + public void doAggregation_hasDuplicateItemsDiffMccMncCase1_removeSamePlmnRatItem() { + List testList = Arrays.asList( + createLteCellInfo(true, 123, "123", "232", "CarrierA"), + createLteCellInfo(true, 123, "456", "232", "CarrierA"), + createGsmCellInfo(false, 123, "123", "232", "CarrierB")); + List expected = Arrays.asList( + createLteCellInfo(true, 123, "123", "232", "CarrierA"), + createGsmCellInfo(false, 123, "123", "232", "CarrierB")); + assertThat(mNetworkSelectSettings.doAggregation(testList)).isEqualTo(expected); + } + + @Test + public void doAggregation_hasDuplicateItemsDiffMccMncCase2_removeSamePlmnRatItem() { + List testList = Arrays.asList( + createLteCellInfo(true, 123, "123", "232", "CarrierA"), + createGsmCellInfo(false, 123, "123", "232", "CarrierB"), + createLteCellInfo(false, 1234, "123", "232", "CarrierB"), + createGsmCellInfo(false, 123, "456", "232", "CarrierB")); + List expected = Arrays.asList( + createLteCellInfo(true, 123, "123", "232", "CarrierA"), + createGsmCellInfo(false, 123, "123", "232", "CarrierB"), + createLteCellInfo(false, 1234, "123", "232", "CarrierB")); + assertThat(mNetworkSelectSettings.doAggregation(testList)).isEqualTo(expected); + } + + private CellInfoLte createLteCellInfo(boolean registered, int cellId, String mcc, String mnc, + String plmnName) { + CellIdentityLte cil = new CellIdentityLte( + cellId, 5, 200, 2000, new int[]{1, 2}, 10000, mcc, + mnc, plmnName, plmnName, + Collections.emptyList(), null); + CellSignalStrengthLte cssl = new CellSignalStrengthLte(15, 16, 17, 18, 19, 20); + + CellInfoLte cellInfoLte = new CellInfoLte(); + cellInfoLte.setRegistered(registered); + cellInfoLte.setTimeStamp(22); + cellInfoLte.setCellIdentity(cil); + cellInfoLte.setCellSignalStrength(cssl); + return cellInfoLte; + } + + private CellInfoGsm createGsmCellInfo(boolean registered, int cellId, String mcc, String mnc, + String plmnName) { + CellIdentityGsm cig = new CellIdentityGsm(1, cellId, 40, 5, mcc, + mnc, plmnName, plmnName, + Collections.emptyList()); + CellSignalStrengthGsm cssg = new CellSignalStrengthGsm(5, 6, 7); + CellInfoGsm cellInfoGsm = new CellInfoGsm(); + cellInfoGsm.setRegistered(registered); + cellInfoGsm.setTimeStamp(9); + cellInfoGsm.setCellIdentity(cig); + cellInfoGsm.setCellSignalStrength(cssg); + return cellInfoGsm; + } +}