From 5691d502729c286f9a8eb50e0b6130a36b734230 Mon Sep 17 00:00:00 2001 From: Calvin Pan Date: Mon, 22 Feb 2021 11:57:03 +0800 Subject: [PATCH 01/10] Show VoLTE UI when VoIMS opt-in enabled Show VoLTE settings if VoIMS opt-in has been enabled irrespective of other VoLTE settings. Bug: 177010560 Test: Override hide_enhanced_4g_lte_bool to true and check the UI. Change-Id: Ib305bae904f0028571874e204a415dfcd4457982 --- .../settings/network/ims/VolteQueryImsState.java | 14 ++++++++++++++ .../Enhanced4gBasePreferenceController.java | 8 +++++++- 2 files changed, 21 insertions(+), 1 deletion(-) diff --git a/src/com/android/settings/network/ims/VolteQueryImsState.java b/src/com/android/settings/network/ims/VolteQueryImsState.java index 167b4b13a3e..b09a1304136 100644 --- a/src/com/android/settings/network/ims/VolteQueryImsState.java +++ b/src/com/android/settings/network/ims/VolteQueryImsState.java @@ -16,11 +16,14 @@ package com.android.settings.network.ims; +import static android.telephony.ims.ProvisioningManager.KEY_VOIMS_OPT_IN_STATUS; + import android.content.Context; import android.telecom.TelecomManager; import android.telephony.AccessNetworkConstants; import android.telephony.SubscriptionManager; import android.telephony.ims.ImsException; +import android.telephony.ims.ProvisioningManager; import android.telephony.ims.feature.MmTelFeature; import android.telephony.ims.stub.ImsRegistrationImplBase; import android.util.Log; @@ -133,4 +136,15 @@ public class VolteQueryImsState extends ImsQueryController { } return isEnabledByUser(mSubId); } + + /** + * Get VoIMS opt-in configuration. + * + * @return true when VoIMS opt-in has been enabled, otherwise false + */ + public boolean isVoImsOptInEnabled() { + int voImsOptInStatus = ProvisioningManager.createForSubscriptionId(mSubId) + .getProvisioningIntValue(KEY_VOIMS_OPT_IN_STATUS); + return voImsOptInStatus == ProvisioningManager.PROVISIONING_VALUE_ENABLED; + } } diff --git a/src/com/android/settings/network/telephony/Enhanced4gBasePreferenceController.java b/src/com/android/settings/network/telephony/Enhanced4gBasePreferenceController.java index fbbdabc701d..c2b1fc4f453 100644 --- a/src/com/android/settings/network/telephony/Enhanced4gBasePreferenceController.java +++ b/src/com/android/settings/network/telephony/Enhanced4gBasePreferenceController.java @@ -107,12 +107,18 @@ public class Enhanced4gBasePreferenceController extends TelephonyTogglePreferenc if (!isModeMatched()) { return CONDITIONALLY_UNAVAILABLE; } + final VolteQueryImsState queryState = queryImsState(subId); + // Show VoLTE settings if VoIMS opt-in has been enabled irrespective of other VoLTE settings + if (queryState.isVoImsOptInEnabled()) { + return AVAILABLE; + } + final PersistableBundle carrierConfig = getCarrierConfigForSubId(subId); if ((carrierConfig == null) || carrierConfig.getBoolean(CarrierConfigManager.KEY_HIDE_ENHANCED_4G_LTE_BOOL)) { return CONDITIONALLY_UNAVAILABLE; } - final VolteQueryImsState queryState = queryImsState(subId); + if (!queryState.isReadyToVoLte()) { return CONDITIONALLY_UNAVAILABLE; } From 2c74864579f76543d2c3e8a3bdf532e0a1551902 Mon Sep 17 00:00:00 2001 From: Janis Danisevskis Date: Mon, 25 Jan 2021 14:56:47 -0800 Subject: [PATCH 02/10] Keystore 2.0: Update Wifi settings to use mostly public keystore API. Test: N/A Bug: 171305607 Bug: 171305388 Merged-In: Ib794c5f2d904c2b187d7d5fd00b81afc852d0052 Change-Id: Ib794c5f2d904c2b187d7d5fd00b81afc852d0052 --- .../utils/AndroidKeystoreAliasLoader.java | 123 ++++++++++++++++++ .../settings/wifi/WifiConfigController.java | 33 +++-- .../settings/wifi/WifiConfigController2.java | 32 +++-- .../wifi/WifiConfigController2Test.java | 42 ++---- .../wifi/WifiConfigControllerTest.java | 26 +--- 5 files changed, 167 insertions(+), 89 deletions(-) create mode 100644 src/com/android/settings/utils/AndroidKeystoreAliasLoader.java diff --git a/src/com/android/settings/utils/AndroidKeystoreAliasLoader.java b/src/com/android/settings/utils/AndroidKeystoreAliasLoader.java new file mode 100644 index 00000000000..9c45ef40bca --- /dev/null +++ b/src/com/android/settings/utils/AndroidKeystoreAliasLoader.java @@ -0,0 +1,123 @@ +/* + * 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.utils; + +import android.os.Process; +import android.security.keystore.AndroidKeyStoreProvider; +import android.security.keystore.KeyProperties; +import android.security.keystore2.AndroidKeyStoreLoadStoreParameter; +import android.util.Log; + +import java.security.Key; +import java.security.KeyStore; +import java.security.KeyStoreException; +import java.security.NoSuchAlgorithmException; +import java.security.PrivateKey; +import java.security.UnrecoverableKeyException; +import java.util.ArrayList; +import java.util.Collection; +import java.util.Enumeration; + +/** + * This class provides a portable and unified way to load the content of AndroidKeyStore through + * public API. + * @hide + */ +public class AndroidKeystoreAliasLoader { + private static final String TAG = "SettingsKeystoreUtils"; + + private final Collection mKeyCertAliases; + private final Collection mCaCertAliases; + /** + * This Constructor loads all aliases of asymmetric keys pairs and certificates in the + * AndroidKeyStore within the given namespace. + * Viable namespaces are {@link KeyProperties#NAMESPACE_WIFI}, + * {@link KeyProperties#NAMESPACE_APPLICATION}, or null. The latter two are equivalent in + * that they will load the keystore content of the app's own namespace. In case of settings, + * this is the namespace of the AID_SYSTEM. + * + * @param namespace {@link KeyProperties#NAMESPACE_WIFI}, + * {@link KeyProperties#NAMESPACE_APPLICATION}, or null + * @hide + */ + public AndroidKeystoreAliasLoader(Integer namespace) { + mKeyCertAliases = new ArrayList<>(); + mCaCertAliases = new ArrayList<>(); + KeyStore keyStore = null; + final Enumeration aliases; + try { + if (namespace != null && namespace != KeyProperties.NAMESPACE_APPLICATION) { + if (AndroidKeyStoreProvider.isKeystore2Enabled()) { + keyStore = KeyStore.getInstance("AndroidKeyStore"); + keyStore.load(new AndroidKeyStoreLoadStoreParameter(namespace)); + } else { + // In the legacy case we pass in the WIFI UID because that is the only + // possible special namespace that existed as of this writing, + // and new namespaces must only be added using the new mechanism. + keyStore = AndroidKeyStoreProvider.getKeyStoreForUid(Process.WIFI_UID); + } + } else { + keyStore = KeyStore.getInstance("AndroidKeyStore"); + keyStore.load(null); + } + aliases = keyStore.aliases(); + } catch (Exception e) { + Log.e(TAG, "Failed to open Android Keystore.", e); + // Will return empty lists. + return; + } + + while (aliases.hasMoreElements()) { + final String alias = aliases.nextElement(); + try { + final Key key = keyStore.getKey(alias, null); + if (key != null) { + if (key instanceof PrivateKey) { + mKeyCertAliases.add(alias); + } + } else { + if (keyStore.getCertificate(alias) != null) { + mCaCertAliases.add(alias); + } + } + } catch (KeyStoreException | NoSuchAlgorithmException | UnrecoverableKeyException e) { + Log.e(TAG, "Failed to load alias: " + + alias + " from Android Keystore. Ignoring.", e); + } + } + } + + /** + * Returns the aliases of the key pairs and certificates stored in the Android KeyStore at the + * time the constructor was called. + * @return Collection of keystore aliases. + * @hide + */ + public Collection getKeyCertAliases() { + return mKeyCertAliases; + } + + /** + * Returns the aliases of the trusted certificates stored in the Android KeyStore at the + * time the constructor was called. + * @return Collection of keystore aliases. + * @hide + */ + public Collection getCaCertAliases() { + return mCaCertAliases; + } +} diff --git a/src/com/android/settings/wifi/WifiConfigController.java b/src/com/android/settings/wifi/WifiConfigController.java index d0b5a4094b2..6e96ae2fefa 100644 --- a/src/com/android/settings/wifi/WifiConfigController.java +++ b/src/com/android/settings/wifi/WifiConfigController.java @@ -35,8 +35,7 @@ import android.net.wifi.WifiInfo; import android.net.wifi.WifiManager; import android.os.IBinder; import android.os.UserManager; -import android.security.Credentials; -import android.security.KeyStore; +import android.security.keystore.KeyProperties; import android.telephony.SubscriptionInfo; import android.telephony.SubscriptionManager; import android.text.Editable; @@ -73,6 +72,7 @@ import com.android.net.module.util.NetUtils; import com.android.net.module.util.ProxyUtils; import com.android.settings.ProxySelector; import com.android.settings.R; +import com.android.settings.utils.AndroidKeystoreAliasLoader; import com.android.settings.wifi.details.WifiPrivacyPreferenceController; import com.android.settings.wifi.details2.WifiPrivacyPreferenceController2; import com.android.settings.wifi.dpp.WifiDppUtils; @@ -83,7 +83,7 @@ import com.android.settingslib.wifi.AccessPoint; import java.net.Inet4Address; import java.net.InetAddress; import java.util.ArrayList; -import java.util.Arrays; +import java.util.Collection; import java.util.Collections; import java.util.Iterator; import java.util.List; @@ -1051,15 +1051,17 @@ public class WifiConfigController implements TextWatcher, if (refreshCertificates) { loadSims(); + final AndroidKeystoreAliasLoader androidKeystoreAliasLoader = + getAndroidKeystoreAliasLoader(); loadCertificates( mEapCaCertSpinner, - Credentials.CA_CERTIFICATE, + androidKeystoreAliasLoader.getCaCertAliases(), null /* noCertificateString */, false /* showMultipleCerts */, true /* showUsePreinstalledCertOption */); loadCertificates( mEapUserCertSpinner, - Credentials.USER_PRIVATE_KEY, + androidKeystoreAliasLoader.getKeyCertAliases(), mDoNotProvideEapUserCertString, false /* showMultipleCerts */, false /* showUsePreinstalledCertOption */); @@ -1142,10 +1144,13 @@ public class WifiConfigController implements TextWatcher, } else if (caCerts.length == 1) { setSelection(mEapCaCertSpinner, caCerts[0]); } else { + final AndroidKeystoreAliasLoader androidKeystoreAliasLoader = + getAndroidKeystoreAliasLoader(); + // Reload the cert spinner with an extra "multiple certificates added" item. loadCertificates( mEapCaCertSpinner, - Credentials.CA_CERTIFICATE, + androidKeystoreAliasLoader.getCaCertAliases(), null /* noCertificateString */, true /* showMultipleCerts */, true /* showUsePreinstalledCertOption */); @@ -1464,8 +1469,8 @@ public class WifiConfigController implements TextWatcher, } @VisibleForTesting - KeyStore getKeyStore() { - return KeyStore.getInstance(); + AndroidKeystoreAliasLoader getAndroidKeystoreAliasLoader() { + return new AndroidKeystoreAliasLoader(KeyProperties.NAMESPACE_WIFI); } @VisibleForTesting @@ -1509,7 +1514,7 @@ public class WifiConfigController implements TextWatcher, @VisibleForTesting void loadCertificates( Spinner spinner, - String prefix, + Collection choices, String noCertificateString, boolean showMultipleCerts, boolean showUsePreinstalledCertOption) { @@ -1524,14 +1529,8 @@ public class WifiConfigController implements TextWatcher, certs.add(mUseSystemCertsString); } - String[] certificateNames = null; - try { - certificateNames = getKeyStore().list(prefix, android.os.Process.WIFI_UID); - } catch (Exception e) { - Log.e(TAG, "can't get the certificate list from KeyStore"); - } - if (certificateNames != null && certificateNames.length != 0) { - certs.addAll(Arrays.stream(certificateNames) + if (choices != null && choices.size() != 0) { + certs.addAll(choices.stream() .filter(certificateName -> { for (String undesired : UNDESIRED_CERTIFICATES) { if (certificateName.startsWith(undesired)) { diff --git a/src/com/android/settings/wifi/WifiConfigController2.java b/src/com/android/settings/wifi/WifiConfigController2.java index 79acc597b00..467f32e60fe 100644 --- a/src/com/android/settings/wifi/WifiConfigController2.java +++ b/src/com/android/settings/wifi/WifiConfigController2.java @@ -33,8 +33,7 @@ import android.net.wifi.WifiEnterpriseConfig.Phase2; import android.net.wifi.WifiManager; import android.os.IBinder; import android.os.UserManager; -import android.security.Credentials; -import android.security.KeyStore; +import android.security.keystore.KeyProperties; import android.telephony.SubscriptionInfo; import android.telephony.SubscriptionManager; import android.text.Editable; @@ -71,6 +70,7 @@ import com.android.net.module.util.NetUtils; import com.android.net.module.util.ProxyUtils; import com.android.settings.ProxySelector; import com.android.settings.R; +import com.android.settings.utils.AndroidKeystoreAliasLoader; import com.android.settings.wifi.details.WifiPrivacyPreferenceController; import com.android.settings.wifi.details2.WifiPrivacyPreferenceController2; import com.android.settings.wifi.dpp.WifiDppUtils; @@ -83,7 +83,7 @@ import com.android.wifitrackerlib.WifiEntry.ConnectedInfo; import java.net.Inet4Address; import java.net.InetAddress; import java.util.ArrayList; -import java.util.Arrays; +import java.util.Collection; import java.util.Collections; import java.util.Iterator; import java.util.List; @@ -1034,15 +1034,17 @@ public class WifiConfigController2 implements TextWatcher, if (refreshCertificates) { loadSims(); + final AndroidKeystoreAliasLoader androidKeystoreAliasLoader = + getAndroidKeystoreAliasLoader(); loadCertificates( mEapCaCertSpinner, - Credentials.CA_CERTIFICATE, + androidKeystoreAliasLoader.getCaCertAliases(), null /* noCertificateString */, false /* showMultipleCerts */, true /* showUsePreinstalledCertOption */); loadCertificates( mEapUserCertSpinner, - Credentials.USER_PRIVATE_KEY, + androidKeystoreAliasLoader.getKeyCertAliases(), mDoNotProvideEapUserCertString, false /* showMultipleCerts */, false /* showUsePreinstalledCertOption */); @@ -1127,9 +1129,11 @@ public class WifiConfigController2 implements TextWatcher, setSelection(mEapCaCertSpinner, caCerts[0]); } else { // Reload the cert spinner with an extra "multiple certificates added" item. + final AndroidKeystoreAliasLoader androidKeystoreAliasLoader = + getAndroidKeystoreAliasLoader(); loadCertificates( mEapCaCertSpinner, - Credentials.CA_CERTIFICATE, + androidKeystoreAliasLoader.getCaCertAliases(), null /* noCertificateString */, true /* showMultipleCerts */, true /* showUsePreinstalledCertOption */); @@ -1448,8 +1452,8 @@ public class WifiConfigController2 implements TextWatcher, } @VisibleForTesting - KeyStore getKeyStore() { - return KeyStore.getInstance(); + AndroidKeystoreAliasLoader getAndroidKeystoreAliasLoader() { + return new AndroidKeystoreAliasLoader(KeyProperties.NAMESPACE_WIFI); } @VisibleForTesting @@ -1493,7 +1497,7 @@ public class WifiConfigController2 implements TextWatcher, @VisibleForTesting void loadCertificates( Spinner spinner, - String prefix, + Collection choices, String noCertificateString, boolean showMultipleCerts, boolean showUsePreinstalledCertOption) { @@ -1508,14 +1512,8 @@ public class WifiConfigController2 implements TextWatcher, certs.add(mUseSystemCertsString); } - String[] certificateNames = null; - try { - certificateNames = getKeyStore().list(prefix, android.os.Process.WIFI_UID); - } catch (Exception e) { - Log.e(TAG, "can't get the certificate list from KeyStore"); - } - if (certificateNames != null && certificateNames.length != 0) { - certs.addAll(Arrays.stream(certificateNames) + if (choices != null && choices.size() != 0) { + certs.addAll(choices.stream() .filter(certificateName -> { for (String undesired : UNDESIRED_CERTIFICATES) { if (certificateName.startsWith(undesired)) { diff --git a/tests/robotests/src/com/android/settings/wifi/WifiConfigController2Test.java b/tests/robotests/src/com/android/settings/wifi/WifiConfigController2Test.java index 869658264c2..a31e082e29c 100644 --- a/tests/robotests/src/com/android/settings/wifi/WifiConfigController2Test.java +++ b/tests/robotests/src/com/android/settings/wifi/WifiConfigController2Test.java @@ -18,9 +18,6 @@ package com.android.settings.wifi; import static com.google.common.truth.Truth.assertThat; -import static org.mockito.Mockito.anyInt; -import static org.mockito.Mockito.anyString; -import static org.mockito.Mockito.eq; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.when; import static org.robolectric.Shadows.shadowOf; @@ -33,9 +30,6 @@ import android.net.wifi.WifiEnterpriseConfig; import android.net.wifi.WifiEnterpriseConfig.Eap; import android.net.wifi.WifiEnterpriseConfig.Phase2; import android.net.wifi.WifiManager; -import android.os.ServiceSpecificException; -import android.security.Credentials; -import android.security.KeyStore; import android.telephony.SubscriptionInfo; import android.telephony.SubscriptionManager; import android.telephony.TelephonyManager; @@ -50,9 +44,12 @@ import android.widget.TextView; import com.android.settings.R; import com.android.settings.testutils.shadow.ShadowConnectivityManager; +import com.android.settings.utils.AndroidKeystoreAliasLoader; import com.android.settings.wifi.details.WifiPrivacyPreferenceController; import com.android.wifitrackerlib.WifiEntry; +import com.google.common.collect.ImmutableList; + import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; @@ -78,7 +75,7 @@ public class WifiConfigController2Test { @Mock private WifiEntry mWifiEntry; @Mock - private KeyStore mKeyStore; + private AndroidKeystoreAliasLoader mAndroidKeystoreAliasLoader; private View mView; private Spinner mHiddenSettingsSpinner; private Spinner mEapCaCertSpinner; @@ -284,28 +281,12 @@ public class WifiConfigController2Test { assertThat(mController.getSignalString()).isNull(); } - @Test - public void loadCertificates_keyStoreListFail_shouldNotCrash() { - // Set up - when(mWifiEntry.getSecurity()).thenReturn(WifiEntry.SECURITY_EAP); - when(mKeyStore.list(anyString())) - .thenThrow(new ServiceSpecificException(-1, "permission error")); - - mController = new TestWifiConfigController2(mConfigUiBase, mView, mWifiEntry, - WifiConfigUiBase2.MODE_CONNECT); - - // Verify that the EAP method menu is visible. - assertThat(mView.findViewById(R.id.eap).getVisibility()).isEqualTo(View.VISIBLE); - // No Crash - } - @Test public void loadCertificates_undesiredCertificates_shouldNotLoadUndesiredCertificates() { final Spinner spinner = new Spinner(mContext); - when(mKeyStore.list(anyString())).thenReturn(WifiConfigController.UNDESIRED_CERTIFICATES); mController.loadCertificates(spinner, - "prefix", + Arrays.asList(WifiConfigController.UNDESIRED_CERTIFICATES), "doNotProvideEapUserCertString", false /* showMultipleCerts */, false /* showUsePreinstalledCertOption */); @@ -436,8 +417,8 @@ public class WifiConfigController2Test { } @Override - KeyStore getKeyStore() { - return mKeyStore; + AndroidKeystoreAliasLoader getAndroidKeystoreAliasLoader() { + return mAndroidKeystoreAliasLoader; } } @@ -883,6 +864,7 @@ public class WifiConfigController2Test { String savedUserCertificate) { final WifiConfiguration mockWifiConfig = mock(WifiConfiguration.class); final WifiEnterpriseConfig mockWifiEnterpriseConfig = mock(WifiEnterpriseConfig.class); + mockWifiConfig.enterpriseConfig = mockWifiEnterpriseConfig; when(mWifiEntry.isSaved()).thenReturn(true); when(mWifiEntry.getSecurity()).thenReturn(WifiEntry.SECURITY_EAP); @@ -893,15 +875,15 @@ public class WifiConfigController2Test { String[] savedCaCertificates = new String[]{savedCaCertificate}; when(mockWifiEnterpriseConfig.getCaCertificateAliases()) .thenReturn(savedCaCertificates); - when(mKeyStore.list(eq(Credentials.CA_CERTIFICATE), anyInt())) - .thenReturn(savedCaCertificates); + when(mAndroidKeystoreAliasLoader.getCaCertAliases()) + .thenReturn(ImmutableList.of(savedCaCertificate)); } if (savedUserCertificate != null) { String[] savedUserCertificates = new String[]{savedUserCertificate}; when(mockWifiEnterpriseConfig.getClientCertificateAlias()) .thenReturn(savedUserCertificate); - when(mKeyStore.list(eq(Credentials.USER_PRIVATE_KEY), anyInt())) - .thenReturn(savedUserCertificates); + when(mAndroidKeystoreAliasLoader.getKeyCertAliases()) + .thenReturn(ImmutableList.of(savedUserCertificate)); } mController = new TestWifiConfigController2(mConfigUiBase, mView, mWifiEntry, diff --git a/tests/robotests/src/com/android/settings/wifi/WifiConfigControllerTest.java b/tests/robotests/src/com/android/settings/wifi/WifiConfigControllerTest.java index 9e62b251850..40a0dd6cb86 100644 --- a/tests/robotests/src/com/android/settings/wifi/WifiConfigControllerTest.java +++ b/tests/robotests/src/com/android/settings/wifi/WifiConfigControllerTest.java @@ -18,7 +18,6 @@ package com.android.settings.wifi; import static com.google.common.truth.Truth.assertThat; -import static org.mockito.Mockito.anyString; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.when; import static org.robolectric.Shadows.shadowOf; @@ -31,8 +30,6 @@ import android.net.wifi.WifiEnterpriseConfig; import android.net.wifi.WifiEnterpriseConfig.Eap; import android.net.wifi.WifiEnterpriseConfig.Phase2; import android.net.wifi.WifiManager; -import android.os.ServiceSpecificException; -import android.security.KeyStore; import android.telephony.SubscriptionInfo; import android.telephony.SubscriptionManager; import android.telephony.TelephonyManager; @@ -74,8 +71,6 @@ public class WifiConfigControllerTest { private Context mContext; @Mock private AccessPoint mAccessPoint; - @Mock - private KeyStore mKeyStore; private View mView; private Spinner mHiddenSettingsSpinner; private ShadowSubscriptionManager mShadowSubscriptionManager; @@ -263,28 +258,12 @@ public class WifiConfigControllerTest { assertThat(mController.getSignalString()).isNull(); } - @Test - public void loadCertificates_keyStoreListFail_shouldNotCrash() { - // Set up - when(mAccessPoint.getSecurity()).thenReturn(AccessPoint.SECURITY_EAP); - when(mKeyStore.list(anyString())) - .thenThrow(new ServiceSpecificException(-1, "permission error")); - - mController = new TestWifiConfigController(mConfigUiBase, mView, mAccessPoint, - WifiConfigUiBase.MODE_CONNECT); - - // Verify that the EAP method menu is visible. - assertThat(mView.findViewById(R.id.eap).getVisibility()).isEqualTo(View.VISIBLE); - // No Crash - } - @Test public void loadCertificates_undesiredCertificates_shouldNotLoadUndesiredCertificates() { final Spinner spinner = new Spinner(mContext); - when(mKeyStore.list(anyString())).thenReturn(WifiConfigController.UNDESIRED_CERTIFICATES); mController.loadCertificates(spinner, - "prefix", + Arrays.asList(WifiConfigController.UNDESIRED_CERTIFICATES), "doNotProvideEapUserCertString", false /* showMultipleCerts */, false /* showUsePreinstalledCertOption */); @@ -413,9 +392,6 @@ public class WifiConfigControllerTest { boolean isSplitSystemUser() { return false; } - - @Override - KeyStore getKeyStore() { return mKeyStore; } } @Test From 2e763e52cfc50818bed979f7c3f953c38718e292 Mon Sep 17 00:00:00 2001 From: changbetty Date: Mon, 17 Aug 2020 20:33:00 +0800 Subject: [PATCH 03/10] [Testing] Use AndroidJUnit4 instead in MobileNetworkUtilsTest 1. Use AndroidJunit4 instead of RobolectricTestRunner 2. Use ApplicationProvider instead of RuntimeEnvironment to get context 3. Change the Copy Right 4. Create the real object for PhoneAccountHandle and ComponentName Bug: 164989754 Test: atest -c MobileNetworkUtilsTest Change-Id: I1778832b0602062adb24928343c0c1d0e525942d Merged-In: I1778832b0602062adb24928343c0c1d0e525942d --- .../telephony/MobileNetworkUtilsTest.java | 336 ++++++++++++++++++ 1 file changed, 336 insertions(+) create mode 100644 tests/unit/src/com/android/settings/network/telephony/MobileNetworkUtilsTest.java diff --git a/tests/unit/src/com/android/settings/network/telephony/MobileNetworkUtilsTest.java b/tests/unit/src/com/android/settings/network/telephony/MobileNetworkUtilsTest.java new file mode 100644 index 00000000000..ee8157d6c60 --- /dev/null +++ b/tests/unit/src/com/android/settings/network/telephony/MobileNetworkUtilsTest.java @@ -0,0 +1,336 @@ +/* + * Copyright (C) 2020 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.ArgumentMatchers.anyBoolean; +import static org.mockito.ArgumentMatchers.anyInt; +import static org.mockito.ArgumentMatchers.nullable; +import static org.mockito.Mockito.never; +import static org.mockito.Mockito.spy; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; + +import android.content.ComponentName; +import android.content.Context; +import android.content.Intent; +import android.content.pm.PackageManager; +import android.content.pm.ResolveInfo; +import android.os.PersistableBundle; +import android.provider.Settings; +import android.telecom.PhoneAccountHandle; +import android.telephony.CarrierConfigManager; +import android.telephony.SubscriptionInfo; +import android.telephony.SubscriptionManager; +import android.telephony.TelephonyManager; + +import androidx.test.core.app.ApplicationProvider; +import androidx.test.ext.junit.runners.AndroidJUnit4; + +import com.android.settings.network.telephony.TelephonyConstants.TelephonyManagerConstants; + +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.Mock; +import org.mockito.MockitoAnnotations; + +import java.util.ArrayList; +import java.util.Arrays; + +@RunWith(AndroidJUnit4.class) +public class MobileNetworkUtilsTest { + private static final String PACKAGE_NAME = "com.android.app"; + private static final int SUB_ID_1 = 1; + private static final int SUB_ID_2 = 2; + private static final int SUB_ID_INVALID = -1; + private static final String PLMN_FROM_TELEPHONY_MANAGER_API = "testPlmn"; + private static final String PLMN_FROM_SUB_ID_1 = "testPlmnSub1"; + private static final String PLMN_FROM_SUB_ID_2 = "testPlmnSub2"; + + @Mock + private TelephonyManager mTelephonyManager; + @Mock + private TelephonyManager mTelephonyManager2; + @Mock + private SubscriptionManager mSubscriptionManager; + @Mock + private SubscriptionInfo mSubscriptionInfo1; + @Mock + private SubscriptionInfo mSubscriptionInfo2; + @Mock + private PackageManager mPackageManager; + @Mock + private ResolveInfo mResolveInfo; + @Mock + private CarrierConfigManager mCarrierConfigManager; + + private Context mContext; + private PersistableBundle mCarrierConfig; + private PhoneAccountHandle mPhoneAccountHandle; + private ComponentName mComponentName; + + @Before + public void setUp() { + MockitoAnnotations.initMocks(this); + + mContext = spy(ApplicationProvider.getApplicationContext()); + when(mContext.getSystemService(SubscriptionManager.class)).thenReturn(mSubscriptionManager); + when(mContext.getSystemService(TelephonyManager.class)).thenReturn(mTelephonyManager); + when(mContext.getSystemService(Context.TELEPHONY_SERVICE)).thenReturn(mTelephonyManager); + when(mTelephonyManager.createForSubscriptionId(SUB_ID_1)).thenReturn(mTelephonyManager); + when(mTelephonyManager.createForSubscriptionId(SUB_ID_2)).thenReturn(mTelephonyManager2); + when(mContext.getPackageManager()).thenReturn(mPackageManager); + + when(mContext.getSystemService(CarrierConfigManager.class)).thenReturn( + mCarrierConfigManager); + + mCarrierConfig = new PersistableBundle(); + when(mCarrierConfigManager.getConfigForSubId(SUB_ID_1)).thenReturn(mCarrierConfig); + + when(mSubscriptionInfo1.getSubscriptionId()).thenReturn(SUB_ID_1); + when(mSubscriptionInfo1.getCarrierName()).thenReturn(PLMN_FROM_SUB_ID_1); + when(mSubscriptionInfo2.getSubscriptionId()).thenReturn(SUB_ID_2); + when(mSubscriptionInfo2.getCarrierName()).thenReturn(PLMN_FROM_SUB_ID_2); + + when(mSubscriptionManager.getActiveSubscriptionInfoList()).thenReturn( + Arrays.asList(mSubscriptionInfo1, mSubscriptionInfo2)); + when(mSubscriptionManager.getAccessibleSubscriptionInfoList()).thenReturn( + Arrays.asList(mSubscriptionInfo1, mSubscriptionInfo2)); + + when(mTelephonyManager.getNetworkOperatorName()).thenReturn( + PLMN_FROM_TELEPHONY_MANAGER_API); + } + + @Test + public void setMobileDataEnabled_setEnabled_enabled() { + MobileNetworkUtils.setMobileDataEnabled(mContext, SUB_ID_1, true, false); + + verify(mTelephonyManager).setDataEnabled(true); + verify(mTelephonyManager2, never()).setDataEnabled(anyBoolean()); + } + + @Test + public void setMobileDataEnabled_setDisabled_disabled() { + MobileNetworkUtils.setMobileDataEnabled(mContext, SUB_ID_2, true, false); + + verify(mTelephonyManager2).setDataEnabled(true); + verify(mTelephonyManager, never()).setDataEnabled(anyBoolean()); + } + + @Test + public void setMobileDataEnabled_disableOtherSubscriptions() { + MobileNetworkUtils.setMobileDataEnabled(mContext, SUB_ID_1, true, true); + + verify(mTelephonyManager).setDataEnabled(true); + verify(mTelephonyManager2).setDataEnabled(false); + } + + @Test + public void buildConfigureIntent_nullHandle_returnNull() { + assertThat(MobileNetworkUtils.buildPhoneAccountConfigureIntent(mContext, null)).isNull(); + } + + @Test + public void buildConfigureIntent_noActivityHandleIntent_returnNull() { + when(mPackageManager.queryIntentActivities(nullable(Intent.class), anyInt())) + .thenReturn(new ArrayList<>()); + + assertThat(MobileNetworkUtils.buildPhoneAccountConfigureIntent(mContext, + mPhoneAccountHandle)).isNull(); + } + + @Test + public void buildConfigureIntent_hasActivityHandleIntent_returnIntent() { + mComponentName = new ComponentName(PACKAGE_NAME, "testClass"); + mPhoneAccountHandle = new PhoneAccountHandle(mComponentName, ""); + when(mPackageManager.queryIntentActivities(nullable(Intent.class), anyInt())) + .thenReturn(Arrays.asList(mResolveInfo)); + + assertThat(MobileNetworkUtils.buildPhoneAccountConfigureIntent(mContext, + mPhoneAccountHandle)).isNotNull(); + } + + @Test + public void isCdmaOptions_phoneTypeCdma_returnTrue() { + when(mTelephonyManager.getPhoneType()).thenReturn(TelephonyManager.PHONE_TYPE_CDMA); + + assertThat(MobileNetworkUtils.isCdmaOptions(mContext, SUB_ID_1)).isTrue(); + } + + @Test + public void isCdmaOptions_worldModeWithGsmWcdma_returnTrue() { + when(mTelephonyManager.getPhoneType()).thenReturn(TelephonyManager.PHONE_TYPE_GSM); + mCarrierConfig.putBoolean(CarrierConfigManager.KEY_WORLD_MODE_ENABLED_BOOL, true); + + Settings.Global.putInt(mContext.getContentResolver(), + android.provider.Settings.Global.PREFERRED_NETWORK_MODE + SUB_ID_1, + TelephonyManagerConstants.NETWORK_MODE_LTE_GSM_WCDMA); + + assertThat(MobileNetworkUtils.isCdmaOptions(mContext, SUB_ID_1)).isTrue(); + } + + @Test + public void isCdmaOptions_carrierWorldModeWithoutHideCarrier_returnTrue() { + when(mTelephonyManager.getPhoneType()).thenReturn(TelephonyManager.PHONE_TYPE_GSM); + mCarrierConfig.putBoolean(CarrierConfigManager.KEY_HIDE_CARRIER_NETWORK_SETTINGS_BOOL, + false); + mCarrierConfig.putBoolean(CarrierConfigManager.KEY_WORLD_PHONE_BOOL, true); + + assertThat(MobileNetworkUtils.isCdmaOptions(mContext, SUB_ID_1)).isTrue(); + } + + @Test + public void getSearchableSubscriptionId_oneActive_returnValid() { + when(mSubscriptionManager.getActiveSubscriptionInfoList()).thenReturn( + Arrays.asList(mSubscriptionInfo1)); + assertThat(MobileNetworkUtils.getSearchableSubscriptionId(mContext)).isEqualTo(SUB_ID_1); + } + + @Test + public void getSearchableSubscriptionId_nonActive_returnInvalid() { + when(mSubscriptionManager.getActiveSubscriptionInfoList()).thenReturn(new ArrayList<>()); + + assertThat(MobileNetworkUtils.getSearchableSubscriptionId(mContext)) + .isEqualTo(SubscriptionManager.INVALID_SUBSCRIPTION_ID); + } + + @Test + public void shouldDisplayNetworkSelectOptions_HideCarrierNetwork_returnFalse() { + mCarrierConfig.putBoolean(CarrierConfigManager.KEY_HIDE_CARRIER_NETWORK_SETTINGS_BOOL, + true); + + assertThat(MobileNetworkUtils.shouldDisplayNetworkSelectOptions(mContext, SUB_ID_1)) + .isFalse(); + } + + @Test + public void shouldDisplayNetworkSelectOptions_allCheckPass_returnTrue() { + mCarrierConfig.putBoolean(CarrierConfigManager.KEY_HIDE_CARRIER_NETWORK_SETTINGS_BOOL, + false); + mCarrierConfig.putBoolean(CarrierConfigManager.KEY_OPERATOR_SELECTION_EXPAND_BOOL, true); + mCarrierConfig.putBoolean(CarrierConfigManager.KEY_CSP_ENABLED_BOOL, false); + when(mTelephonyManager.getPhoneType()).thenReturn(TelephonyManager.PHONE_TYPE_GSM); + + assertThat(MobileNetworkUtils.shouldDisplayNetworkSelectOptions(mContext, SUB_ID_1)) + .isTrue(); + } + + @Test + public void shouldSpeciallyUpdateGsmCdma_notWorldMode_returnFalse() { + mCarrierConfig.putBoolean(CarrierConfigManager.KEY_WORLD_MODE_ENABLED_BOOL, false); + mCarrierConfig.putBoolean(CarrierConfigManager.KEY_SUPPORT_TDSCDMA_BOOL, false); + + assertThat(MobileNetworkUtils.shouldSpeciallyUpdateGsmCdma(mContext, SUB_ID_1)).isFalse(); + } + + @Test + public void shouldSpeciallyUpdateGsmCdma_supportTdscdma_returnFalse() { + when(mCarrierConfigManager.getConfig()).thenReturn(mCarrierConfig); + mCarrierConfig.putBoolean(CarrierConfigManager.KEY_WORLD_MODE_ENABLED_BOOL, true); + mCarrierConfig.putBoolean(CarrierConfigManager.KEY_SUPPORT_TDSCDMA_BOOL, true); + + assertThat(MobileNetworkUtils.shouldSpeciallyUpdateGsmCdma(mContext, SUB_ID_1)).isFalse(); + } + + @Test + public void shouldSpeciallyUpdateGsmCdma_ModeLteTdscdmaGsm_returnTrue() { + mCarrierConfig.putBoolean(CarrierConfigManager.KEY_WORLD_MODE_ENABLED_BOOL, true); + mCarrierConfig.putBoolean(CarrierConfigManager.KEY_SUPPORT_TDSCDMA_BOOL, false); + Settings.Global.putInt(mContext.getContentResolver(), + android.provider.Settings.Global.PREFERRED_NETWORK_MODE + SUB_ID_1, + TelephonyManagerConstants.NETWORK_MODE_LTE_TDSCDMA_GSM); + + assertThat(MobileNetworkUtils.shouldSpeciallyUpdateGsmCdma(mContext, SUB_ID_1)).isTrue(); + } + + @Test + public void shouldSpeciallyUpdateGsmCdma_ModeLteTdscdmaGsmWcdma_returnTrue() { + mCarrierConfig.putBoolean(CarrierConfigManager.KEY_WORLD_MODE_ENABLED_BOOL, true); + mCarrierConfig.putBoolean(CarrierConfigManager.KEY_SUPPORT_TDSCDMA_BOOL, false); + Settings.Global.putInt(mContext.getContentResolver(), + android.provider.Settings.Global.PREFERRED_NETWORK_MODE + SUB_ID_1, + TelephonyManagerConstants.NETWORK_MODE_LTE_TDSCDMA_GSM_WCDMA); + + assertThat(MobileNetworkUtils.shouldSpeciallyUpdateGsmCdma(mContext, SUB_ID_1)).isTrue(); + } + + @Test + public void shouldSpeciallyUpdateGsmCdma_ModeLteTdscdma_returnTrue() { + mCarrierConfig.putBoolean(CarrierConfigManager.KEY_WORLD_MODE_ENABLED_BOOL, true); + mCarrierConfig.putBoolean(CarrierConfigManager.KEY_SUPPORT_TDSCDMA_BOOL, false); + Settings.Global.putInt(mContext.getContentResolver(), + android.provider.Settings.Global.PREFERRED_NETWORK_MODE + SUB_ID_1, + TelephonyManagerConstants.NETWORK_MODE_LTE_TDSCDMA); + + assertThat(MobileNetworkUtils.shouldSpeciallyUpdateGsmCdma(mContext, SUB_ID_1)).isTrue(); + } + + @Test + public void shouldSpeciallyUpdateGsmCdma_ModeLteTdscdmaWcdma_returnTrue() { + mCarrierConfig.putBoolean(CarrierConfigManager.KEY_WORLD_MODE_ENABLED_BOOL, true); + mCarrierConfig.putBoolean(CarrierConfigManager.KEY_SUPPORT_TDSCDMA_BOOL, false); + Settings.Global.putInt(mContext.getContentResolver(), + android.provider.Settings.Global.PREFERRED_NETWORK_MODE + SUB_ID_1, + TelephonyManagerConstants.NETWORK_MODE_LTE_TDSCDMA_WCDMA); + + assertThat(MobileNetworkUtils.shouldSpeciallyUpdateGsmCdma(mContext, SUB_ID_1)).isTrue(); + } + + @Test + public void shouldSpeciallyUpdateGsmCdma_ModeLteTdscdmaCdmaEvdoGsmWcdma_returnTrue() { + mCarrierConfig.putBoolean(CarrierConfigManager.KEY_WORLD_MODE_ENABLED_BOOL, true); + mCarrierConfig.putBoolean(CarrierConfigManager.KEY_SUPPORT_TDSCDMA_BOOL, false); + Settings.Global.putInt(mContext.getContentResolver(), + android.provider.Settings.Global.PREFERRED_NETWORK_MODE + SUB_ID_1, + TelephonyManagerConstants.NETWORK_MODE_LTE_TDSCDMA_CDMA_EVDO_GSM_WCDMA); + + assertThat(MobileNetworkUtils.shouldSpeciallyUpdateGsmCdma(mContext, SUB_ID_1)).isTrue(); + } + + @Test + public void shouldSpeciallyUpdateGsmCdma_ModeLteCdmaEvdoGsmWcdma_returnTrue() { + mCarrierConfig.putBoolean(CarrierConfigManager.KEY_WORLD_MODE_ENABLED_BOOL, true); + mCarrierConfig.putBoolean(CarrierConfigManager.KEY_SUPPORT_TDSCDMA_BOOL, false); + Settings.Global.putInt(mContext.getContentResolver(), + android.provider.Settings.Global.PREFERRED_NETWORK_MODE + SUB_ID_1, + TelephonyManagerConstants.NETWORK_MODE_LTE_CDMA_EVDO_GSM_WCDMA); + + assertThat(MobileNetworkUtils.shouldSpeciallyUpdateGsmCdma(mContext, SUB_ID_1)).isTrue(); + } + + @Test + public void getCurrentCarrierNameForDisplay_withoutValidSubId_returnNetworkOperatorName() { + assertThat(MobileNetworkUtils.getCurrentCarrierNameForDisplay( + mContext, SUB_ID_INVALID)).isEqualTo(PLMN_FROM_TELEPHONY_MANAGER_API); + } + + @Test + public void getCurrentCarrierNameForDisplay_withValidSubId_returnCurrentCarrierName() { + assertThat(MobileNetworkUtils.getCurrentCarrierNameForDisplay( + mContext, SUB_ID_1)).isEqualTo(PLMN_FROM_SUB_ID_1); + assertThat(MobileNetworkUtils.getCurrentCarrierNameForDisplay( + mContext, SUB_ID_2)).isEqualTo(PLMN_FROM_SUB_ID_2); + } + + @Test + public void getCurrentCarrierNameForDisplay_withoutSubId_returnNotNull() { + assertThat(MobileNetworkUtils.getCurrentCarrierNameForDisplay( + mContext)).isNotNull(); + } +} From fbb61ba4d0b88211c5b7322fc749d97a2872a698 Mon Sep 17 00:00:00 2001 From: changbetty Date: Fri, 21 Aug 2020 17:44:53 +0800 Subject: [PATCH 04/10] [Testing] Use AndroidJUnit4 instead in telephony/cdma/ test files 1. Use AndroidJunit4 instead of RobolectricTestRunner 2. Use ApplicationProvider instead of RuntimeEnvironment to get context 3. Change Copy Right 4. To get the original value and add @After to restore the data Bug: Test: atest -c CdmaListPreferenceTest atest -c CdmaSubscriptionPreferenceControllerTest atest -c CdmaSystemSelectPreferenceControllerTest Change-Id: I110727b643a6755ee888708bd1fb2a39cf524a2d Merged-In: I110727b643a6755ee888708bd1fb2a39cf524a2d --- .../cdma/CdmaListPreferenceTest.java | 69 ++++++++ ...aSubscriptionPreferenceControllerTest.java | 133 ++++++++++++++++ ...aSystemSelectPreferenceControllerTest.java | 149 ++++++++++++++++++ 3 files changed, 351 insertions(+) create mode 100644 tests/unit/src/com/android/settings/network/telephony/cdma/CdmaListPreferenceTest.java create mode 100644 tests/unit/src/com/android/settings/network/telephony/cdma/CdmaSubscriptionPreferenceControllerTest.java create mode 100644 tests/unit/src/com/android/settings/network/telephony/cdma/CdmaSystemSelectPreferenceControllerTest.java diff --git a/tests/unit/src/com/android/settings/network/telephony/cdma/CdmaListPreferenceTest.java b/tests/unit/src/com/android/settings/network/telephony/cdma/CdmaListPreferenceTest.java new file mode 100644 index 00000000000..027a53bb8c4 --- /dev/null +++ b/tests/unit/src/com/android/settings/network/telephony/cdma/CdmaListPreferenceTest.java @@ -0,0 +1,69 @@ +/* + * Copyright (C) 2020 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.cdma; + +import static org.mockito.Mockito.doReturn; +import static org.mockito.Mockito.never; +import static org.mockito.Mockito.spy; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; + +import android.content.Context; +import android.telephony.TelephonyManager; + +import androidx.preference.PreferenceManager; +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; + +@RunWith(AndroidJUnit4.class) +public class CdmaListPreferenceTest { + private static final int SUB_ID = 2; + + @Mock + private TelephonyManager mTelephonyManager; + @Mock + private PreferenceManager mPreferenceManager; + + private CdmaListPreference mPreference; + private Context mContext; + + @Before + public void setUp() { + MockitoAnnotations.initMocks(this); + + mContext = spy(ApplicationProvider.getApplicationContext()); + when(mContext.getSystemService(TelephonyManager.class)).thenReturn(mTelephonyManager); + when(mTelephonyManager.createForSubscriptionId(SUB_ID)).thenReturn(mTelephonyManager); + mPreference = spy(new CdmaListPreference(mContext, null)); + mPreference.setSubId(SUB_ID); + } + + @Test + public void onClick_inEcm_doNothing() { + doReturn(true).when(mTelephonyManager).getEmergencyCallbackMode(); + + mPreference.onClick(); + + verify(mPreferenceManager, never()).showDialog(mPreference); + } +} diff --git a/tests/unit/src/com/android/settings/network/telephony/cdma/CdmaSubscriptionPreferenceControllerTest.java b/tests/unit/src/com/android/settings/network/telephony/cdma/CdmaSubscriptionPreferenceControllerTest.java new file mode 100644 index 00000000000..86488c655aa --- /dev/null +++ b/tests/unit/src/com/android/settings/network/telephony/cdma/CdmaSubscriptionPreferenceControllerTest.java @@ -0,0 +1,133 @@ +/* + * Copyright (C) 2020 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.cdma; + +import static com.google.common.truth.Truth.assertThat; + +import static org.mockito.ArgumentMatchers.anyInt; +import static org.mockito.Mockito.doReturn; +import static org.mockito.Mockito.spy; +import static org.mockito.Mockito.when; + +import android.content.Context; +import android.os.SystemProperties; +import android.provider.Settings; +import android.telephony.TelephonyManager; + +import androidx.preference.ListPreference; +import androidx.preference.PreferenceManager; +import androidx.test.core.app.ApplicationProvider; +import androidx.test.ext.junit.runners.AndroidJUnit4; + +import org.junit.After; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.Mock; +import org.mockito.MockitoAnnotations; + +@RunWith(AndroidJUnit4.class) +public class CdmaSubscriptionPreferenceControllerTest { + private static final int SUB_ID = 2; + + @Mock + private PreferenceManager mPreferenceManager; + @Mock + private TelephonyManager mTelephonyManager; + + private CdmaSubscriptionPreferenceController mController; + private ListPreference mPreference; + private Context mContext; + private int mCdmaMode; + private String mSubscriptionsSupported; + + @Before + public void setUp() { + MockitoAnnotations.initMocks(this); + + mContext = spy(ApplicationProvider.getApplicationContext()); + when(mContext.getSystemService(TelephonyManager.class)).thenReturn(mTelephonyManager); + doReturn(mTelephonyManager).when(mTelephonyManager).createForSubscriptionId(SUB_ID); + + mPreference = new ListPreference(mContext); + mController = new CdmaSubscriptionPreferenceController(mContext, "mobile_data"); + mController.init(mPreferenceManager, SUB_ID); + mController.mPreference = mPreference; + mPreference.setKey(mController.getPreferenceKey()); + + mCdmaMode = Settings.Global.getInt(mContext.getContentResolver(), + Settings.Global.CDMA_SUBSCRIPTION_MODE, + TelephonyManager.CDMA_SUBSCRIPTION_RUIM_SIM); + + mSubscriptionsSupported = SystemProperties.get("ril.subscription.types"); + } + + @After + public void tearDown() { + Settings.Global.putInt(mContext.getContentResolver(), + Settings.Global.CDMA_SUBSCRIPTION_MODE, mCdmaMode); + + SystemProperties.set("ril.subscription.types", mSubscriptionsSupported); + } + + @Test + public void onPreferenceChange_selectNV_returnNVMode() { + doReturn(true).when(mTelephonyManager).setCdmaSubscriptionMode(anyInt()); + + mController.onPreferenceChange(mPreference, Integer.toString( + TelephonyManager.CDMA_SUBSCRIPTION_NV)); + + assertThat(Settings.Global.getInt(mContext.getContentResolver(), + Settings.Global.CDMA_SUBSCRIPTION_MODE, + TelephonyManager.CDMA_SUBSCRIPTION_RUIM_SIM)).isEqualTo( + TelephonyManager.CDMA_SUBSCRIPTION_NV); + } + + @Test + public void updateState_stateRUIM_displayRUIM() { + Settings.Global.putInt(mContext.getContentResolver(), + Settings.Global.CDMA_SUBSCRIPTION_MODE, TelephonyManager.CDMA_SUBSCRIPTION_NV); + + mController.updateState(mPreference); + + assertThat(mPreference.getValue()).isEqualTo(Integer.toString( + TelephonyManager.CDMA_SUBSCRIPTION_NV)); + } + + @Test + public void updateState_stateUnknown_doNothing() { + mPreference.setValue(Integer.toString(TelephonyManager.CDMA_SUBSCRIPTION_NV)); + Settings.Global.putInt(mContext.getContentResolver(), + Settings.Global.CDMA_SUBSCRIPTION_MODE, TelephonyManager.CDMA_SUBSCRIPTION_UNKNOWN); + + mController.updateState(mPreference); + + // Still NV mode + assertThat(mPreference.getValue()).isEqualTo(Integer.toString( + TelephonyManager.CDMA_SUBSCRIPTION_NV)); + } + + @Test + public void deviceSupportsNvAndRuim() { + SystemProperties.set("ril.subscription.types", "NV,RUIM"); + assertThat(mController.deviceSupportsNvAndRuim()).isTrue(); + + SystemProperties.set("ril.subscription.types", ""); + + assertThat(mController.deviceSupportsNvAndRuim()).isFalse(); + } +} diff --git a/tests/unit/src/com/android/settings/network/telephony/cdma/CdmaSystemSelectPreferenceControllerTest.java b/tests/unit/src/com/android/settings/network/telephony/cdma/CdmaSystemSelectPreferenceControllerTest.java new file mode 100644 index 00000000000..4f44a29aae3 --- /dev/null +++ b/tests/unit/src/com/android/settings/network/telephony/cdma/CdmaSystemSelectPreferenceControllerTest.java @@ -0,0 +1,149 @@ +/* + * Copyright (C) 2020 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.cdma; + +import static com.google.common.truth.Truth.assertThat; + +import static org.mockito.ArgumentMatchers.anyInt; +import static org.mockito.Mockito.doReturn; +import static org.mockito.Mockito.spy; +import static org.mockito.Mockito.when; + +import android.content.Context; +import android.provider.Settings; +import android.telephony.TelephonyManager; + +import androidx.preference.ListPreference; +import androidx.preference.PreferenceManager; +import androidx.test.core.app.ApplicationProvider; +import androidx.test.ext.junit.runners.AndroidJUnit4; + +import com.android.settings.network.telephony.TelephonyConstants.TelephonyManagerConstants; + +import org.junit.After; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.Mock; +import org.mockito.MockitoAnnotations; + +@RunWith(AndroidJUnit4.class) +public class CdmaSystemSelectPreferenceControllerTest { + private static final int SUB_ID = 2; + + @Mock + private PreferenceManager mPreferenceManager; + @Mock + private TelephonyManager mTelephonyManager; + + private CdmaSystemSelectPreferenceController mController; + private ListPreference mPreference; + private Context mContext; + private int mCdmaRoamingMode; + private int mSettingsNetworkMode; + + @Before + public void setUp() { + MockitoAnnotations.initMocks(this); + + mContext = spy(ApplicationProvider.getApplicationContext()); + when(mContext.getSystemService(TelephonyManager.class)).thenReturn(mTelephonyManager); + doReturn(mTelephonyManager).when(mTelephonyManager).createForSubscriptionId(SUB_ID); + + mPreference = new ListPreference(mContext); + mController = new CdmaSystemSelectPreferenceController(mContext, "mobile_data"); + mController.init(mPreferenceManager, SUB_ID); + mController.mPreference = mPreference; + mPreference.setKey(mController.getPreferenceKey()); + + mCdmaRoamingMode = Settings.Global.getInt(mContext.getContentResolver(), + Settings.Global.CDMA_ROAMING_MODE, + TelephonyManager.CDMA_ROAMING_MODE_ANY); + + mSettingsNetworkMode = Settings.Global.getInt( + mContext.getContentResolver(), + Settings.Global.PREFERRED_NETWORK_MODE + SUB_ID, + TelephonyManager.DEFAULT_PREFERRED_NETWORK_MODE); + } + + @After + public void tearDown() { + Settings.Global.putInt(mContext.getContentResolver(), + Settings.Global.CDMA_ROAMING_MODE, mCdmaRoamingMode); + + Settings.Global.putInt(mContext.getContentResolver(), + Settings.Global.PREFERRED_NETWORK_MODE + SUB_ID, mSettingsNetworkMode); + } + + @Test + public void onPreferenceChange_selectHome_returnHomeMode() { + Settings.Global.putInt(mContext.getContentResolver(), + Settings.Global.CDMA_ROAMING_MODE, + TelephonyManager.CDMA_ROAMING_MODE_ANY); + doReturn(true).when(mTelephonyManager).setCdmaRoamingMode(anyInt()); + + mController.onPreferenceChange(mPreference, + Integer.toString(TelephonyManager.CDMA_ROAMING_MODE_HOME)); + + assertThat(Settings.Global.getInt(mContext.getContentResolver(), + Settings.Global.CDMA_ROAMING_MODE, + TelephonyManager.CDMA_ROAMING_MODE_ANY)).isEqualTo( + TelephonyManager.CDMA_ROAMING_MODE_HOME); + } + + @Test + public void updateState_stateHome_displayHome() { + doReturn(TelephonyManager.CDMA_ROAMING_MODE_HOME).when( + mTelephonyManager).getCdmaRoamingMode(); + + mController.updateState(mPreference); + + assertThat(mPreference.getValue()).isEqualTo( + Integer.toString(TelephonyManager.CDMA_ROAMING_MODE_HOME)); + } + + @Test + public void updateState_LteGSMWcdma_disabled() { + doReturn(TelephonyManager.CDMA_ROAMING_MODE_HOME).when( + mTelephonyManager).getCdmaRoamingMode(); + Settings.Global.putInt(mContext.getContentResolver(), + Settings.Global.PREFERRED_NETWORK_MODE + SUB_ID, + TelephonyManagerConstants.NETWORK_MODE_LTE_GSM_WCDMA); + + mController.updateState(mPreference); + + assertThat(mPreference.isEnabled()).isFalse(); + } + + @Test + public void updateState_stateOther_resetToDefault() { + Settings.Global.putInt(mContext.getContentResolver(), + Settings.Global.CDMA_ROAMING_MODE, + TelephonyManager.CDMA_ROAMING_MODE_HOME); + doReturn(TelephonyManager.CDMA_ROAMING_MODE_AFFILIATED).when( + mTelephonyManager).getCdmaRoamingMode(); + + mController.updateState(mPreference); + + assertThat(mPreference.getValue()).isEqualTo( + Integer.toString(TelephonyManager.CDMA_ROAMING_MODE_ANY)); + assertThat(Settings.Global.getInt(mContext.getContentResolver(), + Settings.Global.CDMA_ROAMING_MODE, + TelephonyManager.CDMA_ROAMING_MODE_HOME)).isEqualTo( + TelephonyManager.CDMA_ROAMING_MODE_ANY); + } +} From 3611c3e22f77b098d04c1427519cad749f311f6d Mon Sep 17 00:00:00 2001 From: Jeremy Goldman Date: Fri, 11 Dec 2020 20:09:31 +0800 Subject: [PATCH 05/10] Settings JUnit test for PreferredNetworkModeContentObserverTest Biggest difference here: the use of a MockContentProvider Bug: 175389659 Test: atest -c PreferredNetworkModeContentObserverTest Change-Id: I891620118f7e84aa1c7f9e0ccdaeb21a225dc31a Merged-In: I891620118f7e84aa1c7f9e0ccdaeb21a225dc31a --- ...eferredNetworkModeContentObserverTest.java | 27 ++++++++++--------- 1 file changed, 14 insertions(+), 13 deletions(-) rename tests/{robotests => unit}/src/com/android/settings/network/PreferredNetworkModeContentObserverTest.java (79%) diff --git a/tests/robotests/src/com/android/settings/network/PreferredNetworkModeContentObserverTest.java b/tests/unit/src/com/android/settings/network/PreferredNetworkModeContentObserverTest.java similarity index 79% rename from tests/robotests/src/com/android/settings/network/PreferredNetworkModeContentObserverTest.java rename to tests/unit/src/com/android/settings/network/PreferredNetworkModeContentObserverTest.java index 657b8b3dc9d..e07a8f140e0 100644 --- a/tests/robotests/src/com/android/settings/network/PreferredNetworkModeContentObserverTest.java +++ b/tests/unit/src/com/android/settings/network/PreferredNetworkModeContentObserverTest.java @@ -16,41 +16,43 @@ package com.android.settings.network; -import static org.mockito.Mockito.mock; import static org.mockito.Mockito.spy; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; -import android.content.ContentResolver; import android.content.Context; import android.provider.Settings; +import android.test.mock.MockContentResolver; + +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 org.robolectric.RobolectricTestRunner; -import org.robolectric.RuntimeEnvironment; -@RunWith(RobolectricTestRunner.class) +@RunWith(AndroidJUnit4.class) public class PreferredNetworkModeContentObserverTest { private static final int SUB_ID = 1; - @Mock - private ContentResolver mResolver; - @Mock private Context mContext; + private MockContentResolver mResolver; + private PreferredNetworkModeContentObserver mPreferredNetworkModeContentObserver; + @Mock private PreferredNetworkModeContentObserver.OnPreferredNetworkModeChangedListener mListener; - private PreferredNetworkModeContentObserver mPreferredNetworkModeContentObserver; @Before public void setUp() { MockitoAnnotations.initMocks(this); - when(mContext.getContentResolver()).thenReturn(mResolver); + mContext = spy(ApplicationProvider.getApplicationContext()); + + mResolver = spy(new MockContentResolver(mContext)); + when(mContext.getContentResolver()).thenReturn(mResolver); mPreferredNetworkModeContentObserver = spy(new PreferredNetworkModeContentObserver(null)); } @@ -68,8 +70,8 @@ public class PreferredNetworkModeContentObserverTest { mPreferredNetworkModeContentObserver.register(mContext, SUB_ID); verify(mResolver).registerContentObserver( - Settings.Global.getUriFor(Settings.Global.PREFERRED_NETWORK_MODE + SUB_ID), false, - mPreferredNetworkModeContentObserver); + Settings.Global.getUriFor(Settings.Global.PREFERRED_NETWORK_MODE + SUB_ID), false, + mPreferredNetworkModeContentObserver); } @Test @@ -78,5 +80,4 @@ public class PreferredNetworkModeContentObserverTest { verify(mResolver).unregisterContentObserver(mPreferredNetworkModeContentObserver); } - } From 3b70c6c41af7ce53dce37eba434ebcc081a9c03d Mon Sep 17 00:00:00 2001 From: Stanley Wang Date: Wed, 3 Mar 2021 12:06:14 +0800 Subject: [PATCH 06/10] Fix the overlap issue of MainSwitch and list view. This issue happen on Developer and Wi-Fi pages, so the problem should be solved on SettingsActivity. Fix: 181341927 Test: Run robotest and see the ui Change-Id: I57722cfcbeb6390c88101d808429346045e57c92 --- src/com/android/settings/SettingsActivity.java | 1 + .../development/DevelopmentSettingsDashboardFragment.java | 2 -- 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/src/com/android/settings/SettingsActivity.java b/src/com/android/settings/SettingsActivity.java index d22a38117a2..b6729179d11 100644 --- a/src/com/android/settings/SettingsActivity.java +++ b/src/com/android/settings/SettingsActivity.java @@ -309,6 +309,7 @@ public class SettingsActivity extends SettingsBaseActivity mMainSwitch = findViewById(R.id.switch_bar); if (mMainSwitch != null) { mMainSwitch.setMetricsTag(getMetricsTag()); + mMainSwitch.setTranslationZ(findViewById(R.id.main_content).getTranslationZ() + 1); } // see if we should show Back/Next buttons diff --git a/src/com/android/settings/development/DevelopmentSettingsDashboardFragment.java b/src/com/android/settings/development/DevelopmentSettingsDashboardFragment.java index 367e7c5086a..e34ae9b6ef7 100644 --- a/src/com/android/settings/development/DevelopmentSettingsDashboardFragment.java +++ b/src/com/android/settings/development/DevelopmentSettingsDashboardFragment.java @@ -200,8 +200,6 @@ public class DevelopmentSettingsDashboardFragment extends RestrictedDashboardFra mSwitchBar = ((SettingsActivity) getActivity()).getSwitchBar(); mSwitchBar.setTitle(getContext().getString(R.string.developer_options_main_switch_title)); mSwitchBar.show(); - mSwitchBar.setTranslationZ( - getActivity().findViewById(R.id.main_content).getTranslationZ() + 1); mSwitchBarController = new DevelopmentSwitchBarController( this /* DevelopmentSettings */, mSwitchBar, mIsAvailable, getSettingsLifecycle()); From b69896ae6070d4d8eb340842b513885217a2443f Mon Sep 17 00:00:00 2001 From: Stanley Wang Date: Wed, 3 Mar 2021 20:18:05 +0800 Subject: [PATCH 07/10] Fix that when scrolling to the top on Wi-Fi page, the "Turn off SIM" notification will pop up. The root cause of the problem is that the switch preference and switch bar status are not sync when using setCheckedInternal API. Fix: 179498532 Test: Run robotest and see the ui Change-Id: Ib51dc2ef27ce49b9c8ba69eb32757bf6b9945baf --- .../android/settings/widget/SettingsMainSwitchPreference.java | 1 + 1 file changed, 1 insertion(+) diff --git a/src/com/android/settings/widget/SettingsMainSwitchPreference.java b/src/com/android/settings/widget/SettingsMainSwitchPreference.java index 76f9b41d807..80a0021e44e 100644 --- a/src/com/android/settings/widget/SettingsMainSwitchPreference.java +++ b/src/com/android/settings/widget/SettingsMainSwitchPreference.java @@ -176,6 +176,7 @@ public class SettingsMainSwitchPreference extends TwoStatePreference { * Update the status of switch but doesn't notify the mOnBeforeListener. */ public void setCheckedInternal(boolean checked) { + super.setChecked(checked); if (mMainSwitchBar != null) { mMainSwitchBar.setCheckedInternal(checked); } From bc6ec1712033009436ffc616941bc22dfea9c993 Mon Sep 17 00:00:00 2001 From: Yi Jiang Date: Wed, 3 Mar 2021 23:29:52 -0800 Subject: [PATCH 08/10] Adds 'more details' hyper link. Adds a 'more details' hyper link in the footer when options are disabled by admin. Test: make ROBOTEST_FILTER=ScreenTimeoutSettingsTest RunSettingsRoboTests Bug: 180314728 Change-Id: I880ccd73f4b2ef0b695619ef42ec87559dc2b65b --- .../display/ScreenTimeoutSettings.java | 59 ++++++++++++------- .../display/ScreenTimeoutSettingsTest.java | 2 + 2 files changed, 40 insertions(+), 21 deletions(-) diff --git a/src/com/android/settings/display/ScreenTimeoutSettings.java b/src/com/android/settings/display/ScreenTimeoutSettings.java index b5186462b3b..b187c876ac8 100644 --- a/src/com/android/settings/display/ScreenTimeoutSettings.java +++ b/src/com/android/settings/display/ScreenTimeoutSettings.java @@ -26,8 +26,13 @@ import android.graphics.drawable.Drawable; import android.os.Bundle; import android.os.UserHandle; import android.provider.Settings; +import android.text.SpannableString; +import android.text.Spanned; +import android.text.style.ClickableSpan; import android.util.Log; +import android.view.View; +import androidx.annotation.NonNull; import androidx.preference.Preference; import androidx.preference.PreferenceScreen; @@ -97,15 +102,6 @@ public class ScreenTimeoutSettings extends RadioButtonPickerFragment implements mPrivacyPreference.setTitle(R.string.adaptive_sleep_privacy); mPrivacyPreference.setSelectable(false); mPrivacyPreference.setLayoutResource(R.layout.preference_footer); - - mDisableOptionsPreference = new FooterPreference(context); - mDisableOptionsPreference.setLayoutResource(R.layout.preference_footer); - mDisableOptionsPreference.setTitle(R.string.admin_disabled_other_options); - mDisableOptionsPreference.setIcon(R.drawable.ic_info_outline_24dp); - - // The 'disabled by admin' preference should always be at the end of the setting page. - mDisableOptionsPreference.setOrder(DEFAULT_ORDER_OF_LOWEST_PREFERENCE); - mPrivacyPreference.setOrder(DEFAULT_ORDER_OF_LOWEST_PREFERENCE - 1); } @Override @@ -138,14 +134,6 @@ public class ScreenTimeoutSettings extends RadioButtonPickerFragment implements final PreferenceScreen screen = getPreferenceScreen(); screen.removeAll(); - if (mAdmin != null) { - mDisableOptionsPreference.setOnPreferenceClickListener(p -> { - RestrictedLockUtils.sendShowAdminSupportDetailsIntent(getContext(), mAdmin); - return true; - }); - screen.addPreference(mDisableOptionsPreference); - } - final List candidateList = getCandidates(); if (candidateList == null) { return; @@ -165,14 +153,43 @@ public class ScreenTimeoutSettings extends RadioButtonPickerFragment implements } if (mAdmin != null) { - mDisableOptionsPreference.setOnPreferenceClickListener(p -> { - RestrictedLockUtils.sendShowAdminSupportDetailsIntent(getContext(), mAdmin); - return true; - }); + setupDisabledFooterPreference(); screen.addPreference(mDisableOptionsPreference); } } + @VisibleForTesting + void setupDisabledFooterPreference() { + final String textDisabledByAdmin = getResources().getString( + R.string.admin_disabled_other_options); + final String textMoreDetails = getResources().getString(R.string.admin_more_details); + + final SpannableString spannableString = new SpannableString( + textDisabledByAdmin + System.lineSeparator() + textMoreDetails); + final ClickableSpan clickableSpan = new ClickableSpan() { + @Override + public void onClick(@NonNull View widget) { + RestrictedLockUtils.sendShowAdminSupportDetailsIntent(getContext(), mAdmin); + } + }; + + if (textDisabledByAdmin != null && textMoreDetails != null) { + spannableString.setSpan(clickableSpan, textDisabledByAdmin.length() + 1, + textDisabledByAdmin.length() + textMoreDetails.length() + 1, + Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); + } + + mDisableOptionsPreference = new FooterPreference(getContext()); + mDisableOptionsPreference.setLayoutResource(R.layout.preference_footer); + mDisableOptionsPreference.setTitle(spannableString); + mDisableOptionsPreference.setSelectable(false); + mDisableOptionsPreference.setIcon(R.drawable.ic_info_outline_24dp); + + // The 'disabled by admin' preference should always be at the end of the setting page. + mDisableOptionsPreference.setOrder(DEFAULT_ORDER_OF_LOWEST_PREFERENCE); + mPrivacyPreference.setOrder(DEFAULT_ORDER_OF_LOWEST_PREFERENCE - 1); + } + @Override protected String getDefaultKey() { return getCurrentSystemScreenTimeout(getContext()); diff --git a/tests/robotests/src/com/android/settings/display/ScreenTimeoutSettingsTest.java b/tests/robotests/src/com/android/settings/display/ScreenTimeoutSettingsTest.java index efc45e02fe8..f0bf95c38fd 100644 --- a/tests/robotests/src/com/android/settings/display/ScreenTimeoutSettingsTest.java +++ b/tests/robotests/src/com/android/settings/display/ScreenTimeoutSettingsTest.java @@ -23,6 +23,7 @@ import static androidx.test.core.app.ApplicationProvider.getApplicationContext; import static com.google.common.truth.Truth.assertThat; import static org.mockito.Mockito.atLeast; +import static org.mockito.Mockito.doNothing; import static org.mockito.Mockito.doReturn; import static org.mockito.Mockito.never; import static org.mockito.Mockito.spy; @@ -138,6 +139,7 @@ public class ScreenTimeoutSettingsTest { public void updateCandidates_enforcedAdmin_showDisabledByAdminPreference() { mSettings.mAdmin = new RestrictedLockUtils.EnforcedAdmin(); mSettings.mDisableOptionsPreference = mDisableOptionsPreference; + doNothing().when(mSettings).setupDisabledFooterPreference(); mSettings.updateCandidates(); From 766f78e8ed23327495dd262614a92085a9f5a62c Mon Sep 17 00:00:00 2001 From: SongFerngWang Date: Thu, 5 Nov 2020 21:27:10 +0800 Subject: [PATCH 09/10] Use SubscriptionManager.getResourcesForSubId to get Resources To support multi-SIM card case. The code uses the SubscriptionManager.getResourcesForSubId to get Resources. Bug: 171843666 Test: make RunSettingsRoboTests ROBOTEST_FILTER=\ EnabledNetworkModePreferenceControllerTest Change-Id: Ib31e23b81bdbd3b5336b45fc73994f40d021718b Merged-In: Ib31e23b81bdbd3b5336b45fc73994f40d021718b --- ...nabledNetworkModePreferenceController.java | 112 ++++++++++-------- .../TelephonyBasePreferenceController.java | 10 ++ ...edNetworkModePreferenceControllerTest.java | 20 ++-- 3 files changed, 81 insertions(+), 61 deletions(-) diff --git a/src/com/android/settings/network/telephony/EnabledNetworkModePreferenceController.java b/src/com/android/settings/network/telephony/EnabledNetworkModePreferenceController.java index fd585a151d2..8a32a95712c 100644 --- a/src/com/android/settings/network/telephony/EnabledNetworkModePreferenceController.java +++ b/src/com/android/settings/network/telephony/EnabledNetworkModePreferenceController.java @@ -164,7 +164,22 @@ public class EnabledNetworkModePreferenceController extends } } - private final static class PreferenceEntriesBuilder { + enum EnabledNetworks { + ENABLED_NETWORKS_UNKNOWN, + ENABLED_NETWORKS_CDMA_CHOICES, + ENABLED_NETWORKS_CDMA_NO_LTE_CHOICES, + ENABLED_NETWORKS_CDMA_ONLY_LTE_CHOICES, + ENABLED_NETWORKS_TDSCDMA_CHOICES, + ENABLED_NETWORKS_EXCEPT_GSM_LTE_CHOICES, + ENABLED_NETWORKS_EXCEPT_GSM_4G_CHOICES, + ENABLED_NETWORKS_EXCEPT_GSM_CHOICES, + ENABLED_NETWORKS_EXCEPT_LTE_CHOICES, + ENABLED_NETWORKS_4G_CHOICES, + ENABLED_NETWORKS_CHOICES, + PREFERRED_NETWORK_MODE_CHOICES_WORLD_MODE + } + + private final class PreferenceEntriesBuilder { private CarrierConfigManager mCarrierConfigManager; private Context mContext; private TelephonyManager mTelephonyManager; @@ -181,21 +196,6 @@ public class EnabledNetworkModePreferenceController extends private List mEntries = new ArrayList<>(); private List mEntriesValue = new ArrayList<>(); - enum EnabledNetworks { - ENABLED_NETWORKS_UNKNOWN, - ENABLED_NETWORKS_CDMA_CHOICES, - ENABLED_NETWORKS_CDMA_NO_LTE_CHOICES, - ENABLED_NETWORKS_CDMA_ONLY_LTE_CHOICES, - ENABLED_NETWORKS_TDSCDMA_CHOICES, - ENABLED_NETWORKS_EXCEPT_GSM_LTE_CHOICES, - ENABLED_NETWORKS_EXCEPT_GSM_4G_CHOICES, - ENABLED_NETWORKS_EXCEPT_GSM_CHOICES, - ENABLED_NETWORKS_EXCEPT_LTE_CHOICES, - ENABLED_NETWORKS_4G_CHOICES, - ENABLED_NETWORKS_CHOICES, - PREFERRED_NETWORK_MODE_CHOICES_WORLD_MODE - } - PreferenceEntriesBuilder(Context context, int subId) { this.mContext = context; this.mSubId = subId; @@ -226,7 +226,7 @@ public class EnabledNetworkModePreferenceController extends int[] entryValuesInt; switch (getEnabledNetworkType()) { case ENABLED_NETWORKS_CDMA_CHOICES: - entryValues = mContext.getResources().getStringArray( + entryValues = getResourcesForSubId().getStringArray( R.array.enabled_networks_cdma_values); entryValuesInt = Stream.of(entryValues).mapToInt(Integer::parseInt).toArray(); if (entryValuesInt.length < 4) { @@ -240,7 +240,7 @@ public class EnabledNetworkModePreferenceController extends addGlobalEntry(entryValuesInt[3]); break; case ENABLED_NETWORKS_CDMA_NO_LTE_CHOICES: - entryValues = mContext.getResources().getStringArray( + entryValues = getResourcesForSubId().getStringArray( R.array.enabled_networks_cdma_no_lte_values); entryValuesInt = Stream.of(entryValues).mapToInt(Integer::parseInt).toArray(); if (entryValuesInt.length < 2) { @@ -251,7 +251,7 @@ public class EnabledNetworkModePreferenceController extends add1xEntry(entryValuesInt[1]); break; case ENABLED_NETWORKS_CDMA_ONLY_LTE_CHOICES: - entryValues = mContext.getResources().getStringArray( + entryValues = getResourcesForSubId().getStringArray( R.array.enabled_networks_cdma_only_lte_values); entryValuesInt = Stream.of(entryValues).mapToInt(Integer::parseInt).toArray(); if (entryValuesInt.length < 2) { @@ -262,7 +262,7 @@ public class EnabledNetworkModePreferenceController extends addGlobalEntry(entryValuesInt[1]); break; case ENABLED_NETWORKS_TDSCDMA_CHOICES: - entryValues = mContext.getResources().getStringArray( + entryValues = getResourcesForSubId().getStringArray( R.array.enabled_networks_tdscdma_values); entryValuesInt = Stream.of(entryValues).mapToInt(Integer::parseInt).toArray(); if (entryValuesInt.length < 3) { @@ -275,7 +275,7 @@ public class EnabledNetworkModePreferenceController extends add2gEntry(entryValuesInt[2]); break; case ENABLED_NETWORKS_EXCEPT_GSM_LTE_CHOICES: - entryValues = mContext.getResources().getStringArray( + entryValues = getResourcesForSubId().getStringArray( R.array.enabled_networks_except_gsm_lte_values); entryValuesInt = Stream.of(entryValues).mapToInt(Integer::parseInt).toArray(); if (entryValuesInt.length < 1) { @@ -285,7 +285,7 @@ public class EnabledNetworkModePreferenceController extends add3gEntry(entryValuesInt[0]); break; case ENABLED_NETWORKS_EXCEPT_GSM_4G_CHOICES: - entryValues = mContext.getResources().getStringArray( + entryValues = getResourcesForSubId().getStringArray( R.array.enabled_networks_except_gsm_values); entryValuesInt = Stream.of(entryValues).mapToInt(Integer::parseInt).toArray(); if (entryValuesInt.length < 2) { @@ -297,7 +297,7 @@ public class EnabledNetworkModePreferenceController extends add3gEntry(entryValuesInt[1]); break; case ENABLED_NETWORKS_EXCEPT_GSM_CHOICES: - entryValues = mContext.getResources().getStringArray( + entryValues = getResourcesForSubId().getStringArray( R.array.enabled_networks_except_gsm_values); entryValuesInt = Stream.of(entryValues).mapToInt(Integer::parseInt).toArray(); if (entryValuesInt.length < 2) { @@ -309,7 +309,7 @@ public class EnabledNetworkModePreferenceController extends add3gEntry(entryValuesInt[1]); break; case ENABLED_NETWORKS_EXCEPT_LTE_CHOICES: - entryValues = mContext.getResources().getStringArray( + entryValues = getResourcesForSubId().getStringArray( R.array.enabled_networks_except_lte_values); entryValuesInt = Stream.of(entryValues).mapToInt(Integer::parseInt).toArray(); if (entryValuesInt.length < 2) { @@ -320,7 +320,7 @@ public class EnabledNetworkModePreferenceController extends add2gEntry(entryValuesInt[1]); break; case ENABLED_NETWORKS_4G_CHOICES: - entryValues = mContext.getResources().getStringArray( + entryValues = getResourcesForSubId().getStringArray( R.array.enabled_networks_values); entryValuesInt = Stream.of(entryValues).mapToInt(Integer::parseInt).toArray(); if (entryValuesInt.length < 3) { @@ -334,7 +334,7 @@ public class EnabledNetworkModePreferenceController extends add2gEntry(entryValuesInt[2]); break; case ENABLED_NETWORKS_CHOICES: - entryValues = mContext.getResources().getStringArray( + entryValues = getResourcesForSubId().getStringArray( R.array.enabled_networks_values); entryValuesInt = Stream.of(entryValues).mapToInt(Integer::parseInt).toArray(); if (entryValuesInt.length < 3) { @@ -346,7 +346,7 @@ public class EnabledNetworkModePreferenceController extends add2gEntry(entryValuesInt[2]); break; case PREFERRED_NETWORK_MODE_CHOICES_WORLD_MODE: - entryValues = mContext.getResources().getStringArray( + entryValues = getResourcesForSubId().getStringArray( R.array.preferred_network_mode_values_world_mode); entryValuesInt = Stream.of(entryValues).mapToInt(Integer::parseInt).toArray(); if (entryValuesInt.length < 3) { @@ -354,9 +354,14 @@ public class EnabledNetworkModePreferenceController extends "PREFERRED_NETWORK_MODE_CHOICES_WORLD_MODE index error."); } addGlobalEntry(entryValuesInt[0]); - addCustomEntry(mContext.getString(R.string.network_world_mode_cdma_lte), + + addCustomEntry( + getResourcesForSubId().getString( + R.string.network_world_mode_cdma_lte), entryValuesInt[1]); - addCustomEntry(mContext.getString(R.string.network_world_mode_gsm_lte), + addCustomEntry( + getResourcesForSubId().getString( + R.string.network_world_mode_gsm_lte), entryValuesInt[2]); break; default: @@ -571,8 +576,9 @@ public class EnabledNetworkModePreferenceController extends case TelephonyManagerConstants.NETWORK_MODE_NR_LTE_WCDMA: setSelectedEntry( TelephonyManagerConstants.NETWORK_MODE_NR_LTE_GSM_WCDMA); - setSummary(mContext.getString(R.string.network_5G) - + mContext.getString(R.string.network_recommended)); + setSummary(getResourcesForSubId().getString(R.string.network_5G) + + getResourcesForSubId().getString( + R.string.network_recommended)); break; case TelephonyManagerConstants.NETWORK_MODE_NR_LTE_TDSCDMA: case TelephonyManagerConstants.NETWORK_MODE_NR_LTE_TDSCDMA_GSM: @@ -581,13 +587,15 @@ public class EnabledNetworkModePreferenceController extends case TelephonyManagerConstants.NETWORK_MODE_NR_LTE_TDSCDMA_CDMA_EVDO_GSM_WCDMA: setSelectedEntry(TelephonyManagerConstants .NETWORK_MODE_NR_LTE_TDSCDMA_CDMA_EVDO_GSM_WCDMA); - setSummary(mContext.getString(R.string.network_5G) - + mContext.getString(R.string.network_recommended)); + setSummary(getResourcesForSubId().getString(R.string.network_5G) + + getResourcesForSubId().getString( + R.string.network_recommended)); break; case TelephonyManagerConstants.NETWORK_MODE_NR_LTE_CDMA_EVDO: setSelectedEntry(TelephonyManagerConstants.NETWORK_MODE_NR_LTE_CDMA_EVDO); - setSummary(mContext.getString(R.string.network_5G) - + mContext.getString(R.string.network_recommended)); + setSummary(getResourcesForSubId().getString(R.string.network_5G) + + getResourcesForSubId().getString( + R.string.network_recommended)); break; case TelephonyManagerConstants.NETWORK_MODE_NR_LTE_CDMA_EVDO_GSM_WCDMA: setSelectedEntry( @@ -597,13 +605,15 @@ public class EnabledNetworkModePreferenceController extends || MobileNetworkUtils.isWorldMode(mContext, mSubId)) { setSummary(R.string.network_global); } else { - setSummary(mContext.getString(R.string.network_5G) - + mContext.getString(R.string.network_recommended)); + setSummary(getResourcesForSubId().getString(R.string.network_5G) + + getResourcesForSubId().getString( + R.string.network_recommended)); } break; default: setSummary( - mContext.getString(R.string.mobile_network_mode_error, networkMode)); + getResourcesForSubId().getString( + R.string.mobile_network_mode_error, networkMode)); } } @@ -613,7 +623,7 @@ public class EnabledNetworkModePreferenceController extends * @param networkType an LTE network mode without 5G. * @return the corresponding network mode with 5G. */ - private static int addNrToLteNetworkType(int networkType) { + private int addNrToLteNetworkType(int networkType) { switch(networkType) { case TelephonyManagerConstants.NETWORK_MODE_LTE_ONLY: return TelephonyManagerConstants.NETWORK_MODE_NR_LTE; @@ -647,7 +657,7 @@ public class EnabledNetworkModePreferenceController extends * @param networkType an 5G network mode. * @return the corresponding network mode without 5G. */ - private static int reduceNrToLteNetworkType(int networkType) { + private int reduceNrToLteNetworkType(int networkType) { switch(networkType) { case TelephonyManagerConstants.NETWORK_MODE_NR_LTE: return TelephonyManagerConstants.NETWORK_MODE_LTE_ONLY; @@ -689,8 +699,8 @@ public class EnabledNetworkModePreferenceController extends private void add5gEntry(int value) { boolean isNRValue = value >= TelephonyManagerConstants.NETWORK_MODE_NR_ONLY; if (showNrList() && isNRValue) { - mEntries.add(mContext.getString(R.string.network_5G) - + mContext.getString(R.string.network_recommended)); + mEntries.add(getResourcesForSubId().getString(R.string.network_5G) + + getResourcesForSubId().getString(R.string.network_recommended)); mEntriesValue.add(value); mIs5gEntryDisplayed = true; } else { @@ -706,7 +716,7 @@ public class EnabledNetworkModePreferenceController extends Log.d(LOG_TAG, "addGlobalEntry. " + " supported5GRadioAccessFamily: " + mSupported5gRadioAccessFamily + " allowed5GNetworkType: " + mAllowed5gNetworkType); - mEntries.add(mContext.getString(R.string.network_global)); + mEntries.add(getResourcesForSubId().getString(R.string.network_global)); if (showNrList()) { value = addNrToLteNetworkType(value); } @@ -722,9 +732,9 @@ public class EnabledNetworkModePreferenceController extends */ private void addLteEntry(int value) { if (showNrList()) { - mEntries.add(mContext.getString(R.string.network_lte_pure)); + mEntries.add(getResourcesForSubId().getString(R.string.network_lte_pure)); } else { - mEntries.add(mContext.getString(R.string.network_lte)); + mEntries.add(getResourcesForSubId().getString(R.string.network_lte)); } mEntriesValue.add(value); } @@ -734,25 +744,25 @@ public class EnabledNetworkModePreferenceController extends */ private void add4gEntry(int value) { if (showNrList()) { - mEntries.add(mContext.getString(R.string.network_4G_pure)); + mEntries.add(getResourcesForSubId().getString(R.string.network_4G_pure)); } else { - mEntries.add(mContext.getString(R.string.network_4G)); + mEntries.add(getResourcesForSubId().getString(R.string.network_4G)); } mEntriesValue.add(value); } private void add3gEntry(int value) { - mEntries.add(mContext.getString(R.string.network_3G)); + mEntries.add(getResourcesForSubId().getString(R.string.network_3G)); mEntriesValue.add(value); } private void add2gEntry(int value) { - mEntries.add(mContext.getString(R.string.network_2G)); + mEntries.add(getResourcesForSubId().getString(R.string.network_2G)); mEntriesValue.add(value); } private void add1xEntry(int value) { - mEntries.add(mContext.getString(R.string.network_1x)); + mEntries.add(getResourcesForSubId().getString(R.string.network_1x)); mEntriesValue.add(value); } @@ -800,7 +810,7 @@ public class EnabledNetworkModePreferenceController extends } private void setSummary(int summaryResId) { - setSummary(mContext.getString(summaryResId)); + setSummary(getResourcesForSubId().getString(summaryResId)); } private void setSummary(String summary) { diff --git a/src/com/android/settings/network/telephony/TelephonyBasePreferenceController.java b/src/com/android/settings/network/telephony/TelephonyBasePreferenceController.java index 2bd7de9d500..3972f3900f3 100644 --- a/src/com/android/settings/network/telephony/TelephonyBasePreferenceController.java +++ b/src/com/android/settings/network/telephony/TelephonyBasePreferenceController.java @@ -17,6 +17,7 @@ package com.android.settings.network.telephony; import android.content.Context; +import android.content.res.Resources; import android.os.PersistableBundle; import android.telephony.CarrierConfigManager; import android.telephony.SubscriptionManager; @@ -74,4 +75,13 @@ public abstract class TelephonyBasePreferenceController extends BasePreferenceCo mContext.getSystemService(CarrierConfigManager.class); return carrierConfigMgr.getConfigForSubId(subId); } + + /** + * Returns the resources associated with Subscription. + * + * @return Resources associated with Subscription. + */ + public Resources getResourcesForSubId() { + return SubscriptionManager.getResourcesForSubId(mContext, mSubId); + } } diff --git a/tests/robotests/src/com/android/settings/network/telephony/EnabledNetworkModePreferenceControllerTest.java b/tests/robotests/src/com/android/settings/network/telephony/EnabledNetworkModePreferenceControllerTest.java index e519b9ad264..ca36f1f83c8 100644 --- a/tests/robotests/src/com/android/settings/network/telephony/EnabledNetworkModePreferenceControllerTest.java +++ b/tests/robotests/src/com/android/settings/network/telephony/EnabledNetworkModePreferenceControllerTest.java @@ -363,43 +363,43 @@ public class EnabledNetworkModePreferenceControllerTest { @Test public void checkResource_stringArrayLength() { - String[] entryValues = mContext.getResources().getStringArray( + String[] entryValues = mController.getResourcesForSubId().getStringArray( R.array.enabled_networks_cdma_values); assertEquals(4, entryValues.length); - entryValues = mContext.getResources().getStringArray( + entryValues = mController.getResourcesForSubId().getStringArray( R.array.enabled_networks_cdma_no_lte_values); assertEquals(2, entryValues.length); - entryValues = mContext.getResources().getStringArray( + entryValues = mController.getResourcesForSubId().getStringArray( R.array.enabled_networks_cdma_only_lte_values); assertEquals(2, entryValues.length); - entryValues = mContext.getResources().getStringArray( + entryValues = mController.getResourcesForSubId().getStringArray( R.array.enabled_networks_tdscdma_values); assertEquals(3, entryValues.length); - entryValues = mContext.getResources().getStringArray( + entryValues = mController.getResourcesForSubId().getStringArray( R.array.enabled_networks_except_gsm_lte_values); assertEquals(1, entryValues.length); - entryValues = mContext.getResources().getStringArray( + entryValues = mController.getResourcesForSubId().getStringArray( R.array.enabled_networks_except_gsm_values); assertEquals(2, entryValues.length); - entryValues = mContext.getResources().getStringArray( + entryValues = mController.getResourcesForSubId().getStringArray( R.array.enabled_networks_except_lte_values); assertEquals(2, entryValues.length); - entryValues = mContext.getResources().getStringArray( + entryValues = mController.getResourcesForSubId().getStringArray( R.array.enabled_networks_values); assertEquals(3, entryValues.length); - entryValues = mContext.getResources().getStringArray( + entryValues = mController.getResourcesForSubId().getStringArray( R.array.enabled_networks_values); assertEquals(3, entryValues.length); - entryValues = mContext.getResources().getStringArray( + entryValues = mController.getResourcesForSubId().getStringArray( R.array.preferred_network_mode_values_world_mode); assertEquals(3, entryValues.length); } From 1ffba4af4e98a4de8fce85875e0bb1a5c2cc51b8 Mon Sep 17 00:00:00 2001 From: SongFerngWang Date: Wed, 11 Nov 2020 16:29:35 +0800 Subject: [PATCH 10/10] [Testcase] To migration DisabledSubscriptionControllerTest 1. Use AndroidJunit4 instead of RobolectricTestRunner 2. Use ApplicationProvider instead of RuntimeEnvironment to get context 3. Change Copy Right 4. remove the mock of PreferenceScreen Bug: 173003522 Test: atest DisabledSubscriptionControllerTest.java Change-Id: Ia99a4cf4618fcb32162485e7da5e48e3b313ce67 Merged-In: Ia99a4cf4618fcb32162485e7da5e48e3b313ce67 --- .../DisabledSubscriptionControllerTest.java | 34 ++++++++++++------- 1 file changed, 21 insertions(+), 13 deletions(-) rename tests/{robotests => unit}/src/com/android/settings/network/telephony/DisabledSubscriptionControllerTest.java (79%) diff --git a/tests/robotests/src/com/android/settings/network/telephony/DisabledSubscriptionControllerTest.java b/tests/unit/src/com/android/settings/network/telephony/DisabledSubscriptionControllerTest.java similarity index 79% rename from tests/robotests/src/com/android/settings/network/telephony/DisabledSubscriptionControllerTest.java rename to tests/unit/src/com/android/settings/network/telephony/DisabledSubscriptionControllerTest.java index 38223b8ff56..b2696600bad 100644 --- a/tests/robotests/src/com/android/settings/network/telephony/DisabledSubscriptionControllerTest.java +++ b/tests/unit/src/com/android/settings/network/telephony/DisabledSubscriptionControllerTest.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2019 The Android Open Source Project + * Copyright (C) 2020 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. @@ -11,7 +11,7 @@ * 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 + * limitations under the License. */ package com.android.settings.network.telephony; @@ -20,13 +20,17 @@ 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.os.Looper; import android.telephony.SubscriptionManager; -import androidx.lifecycle.LifecycleOwner; import androidx.preference.PreferenceCategory; +import androidx.preference.PreferenceManager; import androidx.preference.PreferenceScreen; +import androidx.test.core.app.ApplicationProvider; +import androidx.test.ext.junit.runners.AndroidJUnit4; import com.android.settingslib.core.lifecycle.Lifecycle; @@ -35,10 +39,8 @@ 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; -@RunWith(RobolectricTestRunner.class) +@RunWith(AndroidJUnit4.class) public class DisabledSubscriptionControllerTest { private static final String KEY = "disabled_subscription_category"; @@ -47,22 +49,28 @@ public class DisabledSubscriptionControllerTest { @Mock private SubscriptionManager mSubscriptionManager; @Mock - private PreferenceScreen mScreen; + private Lifecycle mLifecycle; + private PreferenceScreen mScreen; + private PreferenceManager mPreferenceManager; private PreferenceCategory mCategory; private Context mContext; - private Lifecycle mLifecycle; private DisabledSubscriptionController mController; @Before public void setUp() { MockitoAnnotations.initMocks(this); - mContext = spy(RuntimeEnvironment.application); - LifecycleOwner lifecycleOwner = () -> mLifecycle; - mLifecycle = new Lifecycle(lifecycleOwner); - doReturn(mSubscriptionManager).when(mContext).getSystemService(SubscriptionManager.class); + mContext = spy(ApplicationProvider.getApplicationContext()); + when(mContext.getSystemService(SubscriptionManager.class)).thenReturn(mSubscriptionManager); + if (Looper.myLooper() == null) { + Looper.prepare(); + } + mPreferenceManager = new PreferenceManager(mContext); + mScreen = mPreferenceManager.createPreferenceScreen(mContext); mCategory = new PreferenceCategory(mContext); - doReturn(mCategory).when(mScreen).findPreference(KEY); + mCategory.setKey(KEY); + mScreen.addPreference(mCategory); + mController = new DisabledSubscriptionController(mContext, KEY); mController.init(mLifecycle, SUB_ID); }