diff --git a/src/com/android/settings/wifi/WifiConfigController.java b/src/com/android/settings/wifi/WifiConfigController.java index 5651fa5a801..59de675c69d 100644 --- a/src/com/android/settings/wifi/WifiConfigController.java +++ b/src/com/android/settings/wifi/WifiConfigController.java @@ -37,6 +37,8 @@ import android.os.IBinder; import android.os.UserManager; import android.security.Credentials; import android.security.KeyStore; +import android.telephony.SubscriptionInfo; +import android.telephony.SubscriptionManager; import android.text.Editable; import android.text.InputType; import android.text.SpannableString; @@ -77,7 +79,9 @@ import java.net.Inet4Address; import java.net.InetAddress; import java.util.ArrayList; import java.util.Arrays; +import java.util.Collections; import java.util.Iterator; +import java.util.List; import java.util.stream.Collectors; /** @@ -163,7 +167,8 @@ public class WifiConfigController implements TextWatcher, private ScrollView mDialogContainer; private Spinner mSecuritySpinner; - private Spinner mEapMethodSpinner; + @VisibleForTesting Spinner mEapMethodSpinner; + @VisibleForTesting Spinner mEapSimSpinner; // For EAP-SIM, EAP-AKA and EAP-AKA-PRIME. private Spinner mEapCaCertSpinner; private Spinner mEapOcspSpinner; private TextView mEapDomainView; @@ -209,6 +214,8 @@ public class WifiConfigController implements TextWatcher, private final WifiManager mWifiManager; + private final List mActiveSubscriptionInfos = new ArrayList<>(); + public WifiConfigController(WifiConfigUiBase parent, View view, AccessPoint accessPoint, int mode) { this (parent, view, accessPoint, mode, true /* requestFocus */); @@ -804,6 +811,12 @@ public class WifiConfigController implements TextWatcher, return null; } + if (config.enterpriseConfig.isAuthenticationSimBased() + && mActiveSubscriptionInfos.size() > 0) { + config.carrierId = mActiveSubscriptionInfos + .get(mEapSimSpinner.getSelectedItemPosition()).getCarrierId(); + } + config.setIpConfiguration( new IpConfiguration(mIpAssignment, mProxySettings, mStaticIpConfiguration, mHttpProxy)); @@ -987,6 +1000,7 @@ public class WifiConfigController implements TextWatcher, initiateEnterpriseNetworkUi = true; mEapMethodSpinner = (Spinner) mView.findViewById(R.id.method); mEapMethodSpinner.setOnItemSelectedListener(this); + mEapSimSpinner = (Spinner) mView.findViewById(R.id.sim); mPhase2Spinner = (Spinner) mView.findViewById(R.id.phase2); mPhase2Spinner.setOnItemSelectedListener(this); mEapCaCertSpinner = (Spinner) mView.findViewById(R.id.ca_cert); @@ -1023,6 +1037,8 @@ public class WifiConfigController implements TextWatcher, } if (refreshCertificates) { + loadSims(); + loadCertificates( mEapCaCertSpinner, Credentials.CA_CERTIFICATE, @@ -1044,9 +1060,10 @@ public class WifiConfigController implements TextWatcher, // Modifying an existing network if (initiateEnterpriseNetworkUi && mAccessPoint != null && mAccessPoint.isSaved()) { - WifiEnterpriseConfig enterpriseConfig = mAccessPoint.getConfig().enterpriseConfig; - int eapMethod = enterpriseConfig.getEapMethod(); - int phase2Method = enterpriseConfig.getPhase2Method(); + final WifiConfiguration wifiConfig = mAccessPoint.getConfig(); + final WifiEnterpriseConfig enterpriseConfig = wifiConfig.enterpriseConfig; + final int eapMethod = enterpriseConfig.getEapMethod(); + final int phase2Method = enterpriseConfig.getPhase2Method(); mEapMethodSpinner.setSelection(eapMethod); showEapFieldsByMethod(eapMethod); switch (eapMethod) { @@ -1094,6 +1111,16 @@ public class WifiConfigController implements TextWatcher, default: break; } + + if (enterpriseConfig.isAuthenticationSimBased()) { + for (int i = 0; i < mActiveSubscriptionInfos.size(); i++) { + if (wifiConfig.carrierId == mActiveSubscriptionInfos.get(i).getCarrierId()) { + mEapSimSpinner.setSelection(i); + break; + } + } + } + if (!TextUtils.isEmpty(enterpriseConfig.getCaPath())) { setSelection(mEapCaCertSpinner, mUseSystemCertsString); } else { @@ -1182,6 +1209,7 @@ public class WifiConfigController implements TextWatcher, mView.findViewById(R.id.l_ocsp).setVisibility(View.VISIBLE); mView.findViewById(R.id.password_layout).setVisibility(View.VISIBLE); mView.findViewById(R.id.show_password_layout).setVisibility(View.VISIBLE); + mView.findViewById(R.id.l_sim).setVisibility(View.VISIBLE); Context context = mConfigUi.getContext(); switch (eapMethod) { @@ -1192,12 +1220,14 @@ public class WifiConfigController implements TextWatcher, setDomainInvisible(); setAnonymousIdentInvisible(); setUserCertInvisible(); + mView.findViewById(R.id.l_sim).setVisibility(View.GONE); break; case WIFI_EAP_METHOD_TLS: mView.findViewById(R.id.l_user_cert).setVisibility(View.VISIBLE); setPhase2Invisible(); setAnonymousIdentInvisible(); setPasswordInvisible(); + mView.findViewById(R.id.l_sim).setVisibility(View.GONE); break; case WIFI_EAP_METHOD_PEAP: // Reset adapter if needed @@ -1219,6 +1249,7 @@ public class WifiConfigController implements TextWatcher, mView.findViewById(R.id.l_phase2).setVisibility(View.VISIBLE); mView.findViewById(R.id.l_anonymous).setVisibility(View.VISIBLE); setUserCertInvisible(); + mView.findViewById(R.id.l_sim).setVisibility(View.GONE); break; case WIFI_EAP_METHOD_SIM: case WIFI_EAP_METHOD_AKA: @@ -1255,11 +1286,13 @@ public class WifiConfigController implements TextWatcher, mEapIdentityView.setText(""); mView.findViewById(R.id.l_identity).setVisibility(View.GONE); setPasswordInvisible(); + mView.findViewById(R.id.l_sim).setVisibility(View.VISIBLE); } else { mView.findViewById(R.id.l_identity).setVisibility(View.VISIBLE); mView.findViewById(R.id.l_anonymous).setVisibility(View.VISIBLE); mView.findViewById(R.id.password_layout).setVisibility(View.VISIBLE); mView.findViewById(R.id.show_password_layout).setVisibility(View.VISIBLE); + mView.findViewById(R.id.l_sim).setVisibility(View.GONE); } } @@ -1422,6 +1455,44 @@ public class WifiConfigController implements TextWatcher, return KeyStore.getInstance(); } + @VisibleForTesting + void loadSims() { + List activeSubscriptionInfos = mContext + .getSystemService(SubscriptionManager.class).getActiveSubscriptionInfoList(); + if (activeSubscriptionInfos == null) { + activeSubscriptionInfos = Collections.EMPTY_LIST; + } + mActiveSubscriptionInfos.clear(); + + // De-duplicates active subscriptions and caches in mActiveSubscriptionInfos. + for (SubscriptionInfo newInfo : activeSubscriptionInfos) { + for (SubscriptionInfo cachedInfo : mActiveSubscriptionInfos) { + if (newInfo.getCarrierId() == cachedInfo.getCarrierId()) { + continue; + } + } + mActiveSubscriptionInfos.add(newInfo); + } + + // Shows disabled 'No SIM' when there is no active subscription. + if (mActiveSubscriptionInfos.size() == 0) { + final String[] noSim = new String[]{mContext.getString(R.string.wifi_no_sim_card)}; + mEapSimSpinner.setAdapter(getSpinnerAdapter(noSim)); + mEapSimSpinner.setSelection(0 /* position */); + mEapSimSpinner.setEnabled(false); + return; + } + + // Shows display name of each active subscription. + final String[] displayNames = mActiveSubscriptionInfos.stream().map( + SubscriptionInfo::getDisplayName).toArray(String[]::new); + mEapSimSpinner.setAdapter(getSpinnerAdapter(displayNames)); + mEapSimSpinner.setSelection(0 /* position */); + if (displayNames.length == 1) { + mEapSimSpinner.setEnabled(false); + } + } + @VisibleForTesting void loadCertificates( Spinner spinner, diff --git a/tests/robotests/src/com/android/settings/wifi/WifiConfigControllerTest.java b/tests/robotests/src/com/android/settings/wifi/WifiConfigControllerTest.java index 4ae70b5183c..8f73bc37bea 100644 --- a/tests/robotests/src/com/android/settings/wifi/WifiConfigControllerTest.java +++ b/tests/robotests/src/com/android/settings/wifi/WifiConfigControllerTest.java @@ -24,6 +24,7 @@ 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; import android.content.Context; import android.content.res.Resources; @@ -35,6 +36,9 @@ 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; import android.view.LayoutInflater; import android.view.View; import android.view.inputmethod.InputMethodManager; @@ -58,6 +62,9 @@ import org.robolectric.RuntimeEnvironment; import org.robolectric.Shadows; import org.robolectric.annotation.Config; import org.robolectric.shadows.ShadowInputMethodManager; +import org.robolectric.shadows.ShadowSubscriptionManager; + +import java.util.Arrays; @RunWith(RobolectricTestRunner.class) @Config(shadows = ShadowConnectivityManager.class) @@ -73,6 +80,7 @@ public class WifiConfigControllerTest { private KeyStore mKeyStore; private View mView; private Spinner mHiddenSettingsSpinner; + private ShadowSubscriptionManager mShadowSubscriptionManager; public WifiConfigController mController; private static final String HEX_PSK = "01234567012345670123456701234567012345670123456701234567" @@ -97,6 +105,7 @@ public class WifiConfigControllerTest { final Spinner ipSettingsSpinner = mView.findViewById(R.id.ip_settings); mHiddenSettingsSpinner = mView.findViewById(R.id.hidden_settings); ipSettingsSpinner.setSelection(DHCP); + mShadowSubscriptionManager = shadowOf(mContext.getSystemService(SubscriptionManager.class)); mController = new TestWifiConfigController(mConfigUiBase, mView, mAccessPoint, WifiConfigUiBase.MODE_CONNECT); @@ -599,4 +608,41 @@ public class WifiConfigControllerTest { assertThat(advButton.getVisibility()).isEqualTo(View.GONE); } + + @Test + public void loadSims_noSim_simSpinnerDefaultNoSim() { + when(mAccessPoint.getSecurity()).thenReturn(AccessPoint.SECURITY_EAP); + mController = new TestWifiConfigController(mConfigUiBase, mView, mAccessPoint, + WifiConfigUiBase.MODE_CONNECT); + final Spinner eapMethodSpinner = mock(Spinner.class); + when(eapMethodSpinner.getSelectedItemPosition()).thenReturn( + WifiConfigController2.WIFI_EAP_METHOD_SIM); + mController.mEapMethodSpinner = eapMethodSpinner; + + mController.loadSims(); + + final WifiConfiguration wifiConfiguration = mController.getConfig(); + assertThat(wifiConfiguration.carrierId).isEqualTo(TelephonyManager.UNKNOWN_CARRIER_ID); + } + + @Test + public void loadSims_oneSim_simSpinnerDefaultSubscription() { + when(mAccessPoint.getSecurity()).thenReturn(AccessPoint.SECURITY_EAP); + final SubscriptionInfo subscriptionInfo = mock(SubscriptionInfo.class); + final int carrierId = 6; + when(subscriptionInfo.getCarrierId()).thenReturn(carrierId); + when(subscriptionInfo.getCarrierName()).thenReturn("FAKE-CARRIER"); + mShadowSubscriptionManager.setActiveSubscriptionInfoList(Arrays.asList(subscriptionInfo)); + mController = new TestWifiConfigController(mConfigUiBase, mView, mAccessPoint, + WifiConfigUiBase.MODE_CONNECT); + final Spinner eapMethodSpinner = mock(Spinner.class); + when(eapMethodSpinner.getSelectedItemPosition()).thenReturn( + WifiConfigController2.WIFI_EAP_METHOD_SIM); + mController.mEapMethodSpinner = eapMethodSpinner; + + mController.loadSims(); + + final WifiConfiguration wifiConfiguration = mController.getConfig(); + assertThat(wifiConfiguration.carrierId).isEqualTo(carrierId); + } }