[Wi-Fi] Support multi-SIM for SIM dependent EAP methods

Before this change, users are not able to choose SIM
card for SIM dependent EAP methods when a device supports
multi-SIM.

This change support to choose a SIM when adding an EAP
Wi-Fi network. And this change support to show the related
SIM information on Wi-Fi detail screen.

Bug: 142792009
Test: make RunSettingsRoboTests ROBOTEST_FILTER=com.android.settings.wifi.WifiConfigControllerTest
      make RunSettingsRoboTests ROBOTEST_FILTER=com.android.settings.wifi.WifiConfigController2Test
      make RunSettingsRoboTests ROBOTEST_FILTER=com.android.settings.wifi.details2.WifiDetailPreferenceController2Test
      Manually add an EAP Wi-Fi network of EAP-SIM type, observe the
      value in Wi-Fi detail screen.
Change-Id: I2910931166dc6541897663857c46abcc1b3115fa
diff --git a/res/layout/wifi_dialog.xml b/res/layout/wifi_dialog.xml
index 45ecd61..92fff9a 100644
--- a/res/layout/wifi_dialog.xml
+++ b/res/layout/wifi_dialog.xml
@@ -141,6 +141,24 @@
                             android:prompt="@string/wifi_eap_method" />
                 </LinearLayout>
 
+                <LinearLayout android:id="@+id/l_sim"
+                        android:layout_width="match_parent"
+                        android:layout_height="wrap_content"
+                        android:visibility="gone"
+                        style="@style/wifi_item" >
+                    <TextView
+                            android:layout_width="wrap_content"
+                            android:layout_height="wrap_content"
+                            style="@style/wifi_item_label"
+                            android:text="@string/sim_card" />
+
+                    <Spinner android:id="@+id/sim"
+                            android:layout_width="match_parent"
+                            android:layout_height="wrap_content"
+                            style="@style/wifi_item_spinner"
+                            android:prompt="@string/sim_card" />
+                </LinearLayout>
+
                 <LinearLayout android:id="@+id/l_phase2"
                         android:layout_width="match_parent"
                         android:layout_height="wrap_content"
diff --git a/res/values/strings.xml b/res/values/strings.xml
index 2673aa7..c547943 100644
--- a/res/values/strings.xml
+++ b/res/values/strings.xml
@@ -11485,6 +11485,17 @@
     <!-- Message informs the user that has no SIM card in personalized Settings [CHAR LIMIT=30] -->
     <string name="no_sim_card">No SIM card</string>
 
+    <!-- A title for a SIM card spinner UI component which users can choose a SIM card. [CHAR LIMIT=NONE] -->
+    <string name="sim_card">SIM</string>
+    <!-- A label when there is no SIM card to choose. [CHAR LIMIT=NONE] -->
+    <string name="wifi_no_sim_card">No SIM</string>
+    <!-- A label when there is no SIM card information of a Wi-Fi network. [CHAR LIMIT=NONE] -->
+    <string name="wifi_no_related_sim_card">None</string>
+    <!-- A label wen a user needs a SIM to connect to the Wi-Fi network. [CHAR LIMIT=NONE] -->
+    <string name="wifi_require_sim_card_to_connect">Requires SIM to connect</string>
+    <!-- A label wen a user needs a specific SIM to connect to the Wi-Fi network. [CHAR LIMIT=NONE] -->
+    <string name="wifi_require_specific_sim_card_to_connect">Requires <xliff:g id="wireless_carrier" example="Verizon">%s</xliff:g> SIM to connect</string>
+
     <!-- The following strings are summaries for preferred network modes in Mobile network settings,
      and have a character limit of 100 -->
     <!-- WCDMA preferred [CHAR LIMIT=NONE] -->
diff --git a/res/xml/wifi_network_details_fragment2.xml b/res/xml/wifi_network_details_fragment2.xml
index 92f68cc..181b799 100644
--- a/res/xml/wifi_network_details_fragment2.xml
+++ b/res/xml/wifi_network_details_fragment2.xml
@@ -106,6 +106,11 @@
                 android:selectable="false"
                 settings:enableCopying="true"/>
         <Preference
+                android:key="eap_sim_subscription"
+                android:title="@string/sim_card"
+                android:selectable="false"
+                settings:enableCopying="true"/>
+        <Preference
                 android:key="mac_address"
                 android:title="@string/wifi_advanced_randomized_mac_address_title"
                 android:selectable="false"
diff --git a/src/com/android/settings/wifi/WifiConfigController.java b/src/com/android/settings/wifi/WifiConfigController.java
index 1579188..c7ae688 100644
--- a/src/com/android/settings/wifi/WifiConfigController.java
+++ b/src/com/android/settings/wifi/WifiConfigController.java
@@ -37,6 +37,8 @@
 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;
@@ -80,7 +82,9 @@
 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 @@
 
     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 @@
 
     private final WifiManager mWifiManager;
 
+    private final List<SubscriptionInfo> mActiveSubscriptionInfos = new ArrayList<>();
+
     public WifiConfigController(WifiConfigUiBase parent, View view, AccessPoint accessPoint,
             int mode) {
         this (parent, view, accessPoint, mode, true /* requestFocus */);
@@ -825,6 +832,12 @@
                 return null;
         }
 
+        if (config.enterpriseConfig.isAuthenticationSimBased()
+                && mActiveSubscriptionInfos.size() > 0) {
+            config.carrierId = mActiveSubscriptionInfos
+                    .get(mEapSimSpinner.getSelectedItemPosition()).getCarrierId();
+        }
+
         config.setIpConfiguration(
                 new IpConfiguration(mIpAssignment, mProxySettings,
                                     mStaticIpConfiguration, mHttpProxy));
@@ -1013,6 +1026,7 @@
             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);
@@ -1049,6 +1063,8 @@
         }
 
         if (refreshCertificates) {
+            loadSims();
+
             loadCertificates(
                     mEapCaCertSpinner,
                     Credentials.CA_CERTIFICATE,
@@ -1070,9 +1086,10 @@
 
         // 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) {
@@ -1120,6 +1137,16 @@
                 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 {
@@ -1208,6 +1235,7 @@
         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) {
@@ -1218,12 +1246,14 @@
                 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
@@ -1245,6 +1275,7 @@
                 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:
@@ -1282,11 +1313,13 @@
             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);
         }
     }
 
@@ -1450,6 +1483,44 @@
     }
 
     @VisibleForTesting
+    void loadSims() {
+        List<SubscriptionInfo> 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,
             String prefix,
diff --git a/src/com/android/settings/wifi/WifiConfigController2.java b/src/com/android/settings/wifi/WifiConfigController2.java
index 99907f3..eec35ad 100644
--- a/src/com/android/settings/wifi/WifiConfigController2.java
+++ b/src/com/android/settings/wifi/WifiConfigController2.java
@@ -35,6 +35,8 @@
 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;
@@ -80,7 +82,9 @@
 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;
 
 /**
@@ -160,7 +164,8 @@
 
     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;
@@ -205,6 +210,8 @@
 
     private final WifiManager mWifiManager;
 
+    private final List<SubscriptionInfo> mActiveSubscriptionInfos = new ArrayList<>();
+
     public WifiConfigController2(WifiConfigUiBase2 parent, View view, WifiEntry wifiEntry,
             int mode) {
         mConfigUi = parent;
@@ -714,6 +721,12 @@
                         break;
                 }
 
+                if (config.enterpriseConfig.isAuthenticationSimBased()
+                        && mActiveSubscriptionInfos.size() > 0) {
+                    config.carrierId = mActiveSubscriptionInfos
+                            .get(mEapSimSpinner.getSelectedItemPosition()).getCarrierId();
+                }
+
                 String caCert = (String) mEapCaCertSpinner.getSelectedItem();
                 config.enterpriseConfig.setCaCertificateAliases(null);
                 config.enterpriseConfig.setCaPath(null);
@@ -994,6 +1007,7 @@
             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);
@@ -1031,6 +1045,8 @@
         }
 
         if (refreshCertificates) {
+            loadSims();
+
             loadCertificates(
                     mEapCaCertSpinner,
                     Credentials.CA_CERTIFICATE,
@@ -1052,10 +1068,10 @@
 
         // Modifying an existing network
         if (initiateEnterpriseNetworkUi && mWifiEntry != null && mWifiEntry.isSaved()) {
-            WifiEnterpriseConfig enterpriseConfig = mWifiEntry.getWifiConfiguration()
-                    .enterpriseConfig;
-            int eapMethod = enterpriseConfig.getEapMethod();
-            int phase2Method = enterpriseConfig.getPhase2Method();
+            final WifiConfiguration wifiConfig = mWifiEntry.getWifiConfiguration();
+            final WifiEnterpriseConfig enterpriseConfig = wifiConfig.enterpriseConfig;
+            final int eapMethod = enterpriseConfig.getEapMethod();
+            final int phase2Method = enterpriseConfig.getPhase2Method();
             mEapMethodSpinner.setSelection(eapMethod);
             showEapFieldsByMethod(eapMethod);
             switch (eapMethod) {
@@ -1103,6 +1119,16 @@
                 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 {
@@ -1191,6 +1217,7 @@
         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) {
@@ -1201,12 +1228,14 @@
                 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
@@ -1228,6 +1257,7 @@
                 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:
@@ -1265,11 +1295,13 @@
             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);
         }
     }
 
@@ -1433,6 +1465,44 @@
     }
 
     @VisibleForTesting
+    void loadSims() {
+        List<SubscriptionInfo> 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,
             String prefix,
diff --git a/src/com/android/settings/wifi/details2/WifiDetailPreferenceController2.java b/src/com/android/settings/wifi/details2/WifiDetailPreferenceController2.java
index 5c48dfd..ef57e54 100644
--- a/src/com/android/settings/wifi/details2/WifiDetailPreferenceController2.java
+++ b/src/com/android/settings/wifi/details2/WifiDetailPreferenceController2.java
@@ -23,8 +23,10 @@
 import android.app.Activity;
 import android.app.AlertDialog;
 import android.app.settings.SettingsEnums;
+import android.content.AsyncQueryHandler;
 import android.content.Context;
 import android.content.Intent;
+import android.database.Cursor;
 import android.graphics.Bitmap;
 import android.graphics.drawable.BitmapDrawable;
 import android.graphics.drawable.Drawable;
@@ -41,9 +43,14 @@
 import android.net.NetworkUtils;
 import android.net.RouteInfo;
 import android.net.Uri;
+import android.net.wifi.WifiConfiguration;
 import android.net.wifi.WifiInfo;
 import android.net.wifi.WifiManager;
 import android.os.Handler;
+import android.provider.Telephony.CarrierId;
+import android.telephony.SubscriptionInfo;
+import android.telephony.SubscriptionManager;
+import android.telephony.TelephonyManager;
 import android.text.TextUtils;
 import android.util.FeatureFlagUtils;
 import android.util.Log;
@@ -98,6 +105,7 @@
 import java.time.ZonedDateTime;
 import java.time.format.DateTimeFormatter;
 import java.time.format.FormatStyle;
+import java.util.List;
 import java.util.StringJoiner;
 import java.util.stream.Collectors;
 
@@ -133,6 +141,8 @@
     @VisibleForTesting
     static final String KEY_SSID_PREF = "ssid";
     @VisibleForTesting
+    static final String KEY_EAP_SIM_SUBSCRIPTION_PREF = "eap_sim_subscription";
+    @VisibleForTesting
     static final String KEY_MAC_ADDRESS_PREF = "mac_address";
     @VisibleForTesting
     static final String KEY_IP_ADDRESS_PREF = "ip_address";
@@ -170,6 +180,7 @@
     private Preference mFrequencyPref;
     private Preference mSecurityPref;
     private Preference mSsidPref;
+    private Preference mEapSimSubscriptionPref;
     private Preference mMacAddressPref;
     private Preference mIpAddressPref;
     private Preference mGatewayPref;
@@ -187,6 +198,35 @@
     private final NetworkRequest mNetworkRequest = new NetworkRequest.Builder()
             .clearCapabilities().addTransportType(TRANSPORT_WIFI).build();
 
+    private CarrierIdAsyncQueryHandler mCarrierIdAsyncQueryHandler;
+    private static final int TOKEN_QUERY_CARRIER_ID_AND_UPDATE_SIM_SUMMARY = 1;
+    private static final int COLUMN_CARRIER_NAME = 0;
+
+    private class CarrierIdAsyncQueryHandler extends AsyncQueryHandler {
+
+        private CarrierIdAsyncQueryHandler(Context context) {
+            super(context.getContentResolver());
+        }
+
+        @Override
+        protected void onQueryComplete(int token, Object cookie, Cursor cursor) {
+            if (token == TOKEN_QUERY_CARRIER_ID_AND_UPDATE_SIM_SUMMARY) {
+                if (mContext == null || cursor == null || !cursor.moveToFirst()) {
+                    if (cursor != null) {
+                        cursor.close();
+                    }
+                    mEapSimSubscriptionPref.setSummary(R.string.wifi_require_sim_card_to_connect);
+                    return;
+                }
+                mEapSimSubscriptionPref.setSummary(mContext.getString(
+                        R.string.wifi_require_specific_sim_card_to_connect,
+                        cursor.getString(COLUMN_CARRIER_NAME)));
+                cursor.close();
+                return;
+            }
+        }
+    }
+
     // Must be run on the UI thread since it directly manipulates UI state.
     private final NetworkCallback mNetworkCallback = new NetworkCallback() {
         @Override
@@ -336,6 +376,7 @@
         mSecurityPref = screen.findPreference(KEY_SECURITY_PREF);
 
         mSsidPref = screen.findPreference(KEY_SSID_PREF);
+        mEapSimSubscriptionPref = screen.findPreference(KEY_EAP_SIM_SUBSCRIPTION_PREF);
         mMacAddressPref = screen.findPreference(KEY_MAC_ADDRESS_PREF);
         mIpAddressPref = screen.findPreference(KEY_IP_ADDRESS_PREF);
         mGatewayPref = screen.findPreference(KEY_GATEWAY_PREF);
@@ -507,6 +548,8 @@
         refreshIpLayerInfo();
         // SSID Pref
         refreshSsid();
+        // EAP SIM subscription
+        refreshEapSimSubscription();
         // MAC Address Pref
         refreshMacAddress();
     }
@@ -630,6 +673,62 @@
         }
     }
 
+    private void refreshEapSimSubscription() {
+        mEapSimSubscriptionPref.setVisible(false);
+
+        if (mWifiEntry.getSecurity() != WifiEntry.SECURITY_EAP) {
+            return;
+        }
+        final WifiConfiguration config = mWifiEntry.getWifiConfiguration();
+        if (config == null || config.enterpriseConfig == null) {
+            return;
+        }
+        if (!config.enterpriseConfig.isAuthenticationSimBased()) {
+            return;
+        }
+
+        mEapSimSubscriptionPref.setVisible(true);
+
+        // Checks if the SIM subscription is active.
+        final List<SubscriptionInfo> activeSubscriptionInfos = mContext
+                .getSystemService(SubscriptionManager.class).getActiveSubscriptionInfoList();
+        final int defaultDataSubscriptionId = SubscriptionManager.getDefaultDataSubscriptionId();
+        if (activeSubscriptionInfos != null) {
+            for (SubscriptionInfo subscriptionInfo : activeSubscriptionInfos) {
+                if (config.carrierId == subscriptionInfo.getCarrierId()) {
+                    mEapSimSubscriptionPref.setSummary(subscriptionInfo.getDisplayName());
+                    return;
+                }
+
+                // When it's UNKNOWN_CARRIER_ID, devices connects it with the SIM subscription of
+                // defaultDataSubscriptionId.
+                if (config.carrierId == TelephonyManager.UNKNOWN_CARRIER_ID
+                        && defaultDataSubscriptionId == subscriptionInfo.getSubscriptionId()) {
+                    mEapSimSubscriptionPref.setSummary(subscriptionInfo.getDisplayName());
+                    return;
+                }
+            }
+        }
+
+        if (config.carrierId == TelephonyManager.UNKNOWN_CARRIER_ID) {
+            mEapSimSubscriptionPref.setSummary(R.string.wifi_no_related_sim_card);
+            return;
+        }
+
+        // The Wi-Fi network has specified carrier id, query carrier name from CarrierIdProvider.
+        if (mCarrierIdAsyncQueryHandler == null) {
+            mCarrierIdAsyncQueryHandler = new CarrierIdAsyncQueryHandler(mContext);
+        }
+        mCarrierIdAsyncQueryHandler.cancelOperation(TOKEN_QUERY_CARRIER_ID_AND_UPDATE_SIM_SUMMARY);
+        mCarrierIdAsyncQueryHandler.startQuery(TOKEN_QUERY_CARRIER_ID_AND_UPDATE_SIM_SUMMARY,
+                null /* cookie */,
+                CarrierId.All.CONTENT_URI,
+                new String[]{CarrierId.CARRIER_NAME},
+                CarrierId.CARRIER_ID + "=?",
+                new String[] {Integer.toString(config.carrierId)},
+                null /* orderBy */);
+    }
+
     private void refreshMacAddress() {
         final String macAddress = mWifiEntry.getMacAddress();
         if (TextUtils.isEmpty(macAddress)) {
diff --git a/tests/robotests/src/com/android/settings/wifi/WifiConfigController2Test.java b/tests/robotests/src/com/android/settings/wifi/WifiConfigController2Test.java
index e588799..cd26893 100644
--- a/tests/robotests/src/com/android/settings/wifi/WifiConfigController2Test.java
+++ b/tests/robotests/src/com/android/settings/wifi/WifiConfigController2Test.java
@@ -21,6 +21,7 @@
 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;
@@ -32,6 +33,9 @@
 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;
@@ -56,6 +60,9 @@
 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)
@@ -71,6 +78,7 @@
     private KeyStore mKeyStore;
     private View mView;
     private Spinner mHiddenSettingsSpinner;
+    private ShadowSubscriptionManager mShadowSubscriptionManager;
 
     public WifiConfigController2 mController;
     private static final String HEX_PSK = "01234567012345670123456701234567012345670123456701234567"
@@ -101,6 +109,7 @@
         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 TestWifiConfigController2(mConfigUiBase, mView, mWifiEntry,
                 WifiConfigUiBase2.MODE_CONNECT);
@@ -760,4 +769,41 @@
         mController = new TestWifiConfigController2(mConfigUiBase, mView, mWifiEntry,
                 WifiConfigUiBase2.MODE_MODIFY);
     }
+
+    @Test
+    public void loadSims_noSim_simSpinnerDefaultNoSim() {
+        when(mWifiEntry.getSecurity()).thenReturn(WifiEntry.SECURITY_EAP);
+        mController = new TestWifiConfigController2(mConfigUiBase, mView, mWifiEntry,
+                WifiConfigUiBase2.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(mWifiEntry.getSecurity()).thenReturn(WifiEntry.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 TestWifiConfigController2(mConfigUiBase, mView, mWifiEntry,
+                WifiConfigUiBase2.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);
+    }
 }
diff --git a/tests/robotests/src/com/android/settings/wifi/WifiConfigControllerTest.java b/tests/robotests/src/com/android/settings/wifi/WifiConfigControllerTest.java
index 9146998..69b40c3 100644
--- a/tests/robotests/src/com/android/settings/wifi/WifiConfigControllerTest.java
+++ b/tests/robotests/src/com/android/settings/wifi/WifiConfigControllerTest.java
@@ -21,6 +21,7 @@
 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;
@@ -32,6 +33,9 @@
 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;
@@ -56,6 +60,9 @@
 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)
@@ -71,6 +78,7 @@
     private KeyStore mKeyStore;
     private View mView;
     private Spinner mHiddenSettingsSpinner;
+    private ShadowSubscriptionManager mShadowSubscriptionManager;
 
     public WifiConfigController mController;
     private static final String HEX_PSK = "01234567012345670123456701234567012345670123456701234567"
@@ -95,6 +103,7 @@
         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);
@@ -575,4 +584,41 @@
 
         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);
+    }
 }
diff --git a/tests/robotests/src/com/android/settings/wifi/details2/WifiDetailPreferenceController2Test.java b/tests/robotests/src/com/android/settings/wifi/details2/WifiDetailPreferenceController2Test.java
index 8d3405c..9aaaa43 100644
--- a/tests/robotests/src/com/android/settings/wifi/details2/WifiDetailPreferenceController2Test.java
+++ b/tests/robotests/src/com/android/settings/wifi/details2/WifiDetailPreferenceController2Test.java
@@ -53,10 +53,12 @@
 import android.net.RouteInfo;
 import android.net.Uri;
 import android.net.wifi.WifiConfiguration;
+import android.net.wifi.WifiEnterpriseConfig;
 import android.net.wifi.WifiInfo;
 import android.net.wifi.WifiManager;
 import android.os.Handler;
 import android.provider.Settings;
+import android.telephony.TelephonyManager;
 import android.view.View;
 import android.view.View.OnClickListener;
 import android.widget.ImageView;
@@ -175,6 +177,8 @@
     @Mock
     private Preference mMockSsidPref;
     @Mock
+    private Preference mMockEapSimSubscriptionPref;
+    @Mock
     private Preference mMockMacAddressPref;
     @Mock
     private Preference mMockIpAddressPref;
@@ -374,6 +378,8 @@
                 .thenReturn(mMockSecurityPref);
         when(mMockScreen.findPreference(WifiDetailPreferenceController2.KEY_SSID_PREF))
                 .thenReturn(mMockSsidPref);
+        when(mMockScreen.findPreference(WifiDetailPreferenceController2
+                .KEY_EAP_SIM_SUBSCRIPTION_PREF)).thenReturn(mMockEapSimSubscriptionPref);
         when(mMockScreen.findPreference(WifiDetailPreferenceController2.KEY_MAC_ADDRESS_PREF))
                 .thenReturn(mMockMacAddressPref);
         when(mMockScreen.findPreference(WifiDetailPreferenceController2.KEY_IP_ADDRESS_PREF))
@@ -1582,6 +1588,82 @@
         verify(mMockHeaderController).setSummary(expired);
     }
 
+    @Test
+    public void refreshEapSimSubscription_nonEapSecurity_invisibleEapSimSubscriptionPref() {
+        setUpForDisconnectedNetwork();
+        when(mMockWifiEntry.getSecurity()).thenReturn(WifiEntry.SECURITY_NONE);
+
+        displayAndResume();
+
+        verify(mMockEapSimSubscriptionPref, times(1)).setVisible(false);
+
+        when(mMockWifiEntry.getSecurity()).thenReturn(WifiEntry.SECURITY_OWE);
+
+        displayAndResume();
+
+        verify(mMockEapSimSubscriptionPref, times(2)).setVisible(false);
+
+        when(mMockWifiEntry.getSecurity()).thenReturn(WifiEntry.SECURITY_PSK);
+
+        displayAndResume();
+
+        verify(mMockEapSimSubscriptionPref, times(3)).setVisible(false);
+
+        when(mMockWifiEntry.getSecurity()).thenReturn(WifiEntry.SECURITY_SAE);
+
+        displayAndResume();
+
+        verify(mMockEapSimSubscriptionPref, times(4)).setVisible(false);
+        verify(mMockEapSimSubscriptionPref, never()).setVisible(true);
+    }
+
+    @Test
+    public void refreshEapSimSubscription_nonSimEapMethod_invisibleEapSimSubscriptionPref() {
+        setUpForDisconnectedNetwork();
+        when(mMockWifiEntry.getSecurity()).thenReturn(WifiEntry.SECURITY_EAP);
+        final WifiConfiguration mockWifiConfiguration = mock(WifiConfiguration.class);
+        final WifiEnterpriseConfig mockWifiEnterpriseConfig = mock(WifiEnterpriseConfig.class);
+        when(mockWifiEnterpriseConfig.isAuthenticationSimBased()).thenReturn(false);
+        mockWifiConfiguration.enterpriseConfig = mockWifiEnterpriseConfig;
+        when(mMockWifiEntry.getWifiConfiguration()).thenReturn(mockWifiConfiguration);
+
+        displayAndResume();
+
+        verify(mMockEapSimSubscriptionPref, times(1)).setVisible(false);
+    }
+
+    @Test
+    public void refreshEapSimSubscription_simEapMethod_visibleEapSimSubscriptionPref() {
+        setUpForDisconnectedNetwork();
+        when(mMockWifiEntry.getSecurity()).thenReturn(WifiEntry.SECURITY_EAP);
+        final WifiConfiguration mockWifiConfiguration = mock(WifiConfiguration.class);
+        final WifiEnterpriseConfig mockWifiEnterpriseConfig = mock(WifiEnterpriseConfig.class);
+        when(mockWifiEnterpriseConfig.isAuthenticationSimBased()).thenReturn(true);
+        mockWifiConfiguration.enterpriseConfig = mockWifiEnterpriseConfig;
+        when(mMockWifiEntry.getWifiConfiguration()).thenReturn(mockWifiConfiguration);
+
+        displayAndResume();
+
+        verify(mMockEapSimSubscriptionPref).setVisible(true);
+    }
+
+    @Test
+    public void refreshEapSimSubscription_unknownCarrierId_noSimEapSimSubscriptionPref() {
+        setUpForDisconnectedNetwork();
+        when(mMockWifiEntry.getSecurity()).thenReturn(WifiEntry.SECURITY_EAP);
+        final WifiConfiguration mockWifiConfiguration = mock(WifiConfiguration.class);
+        mockWifiConfiguration.carrierId = TelephonyManager.UNKNOWN_CARRIER_ID;
+        final WifiEnterpriseConfig mockWifiEnterpriseConfig = mock(WifiEnterpriseConfig.class);
+        when(mockWifiEnterpriseConfig.isAuthenticationSimBased()).thenReturn(true);
+        mockWifiConfiguration.enterpriseConfig = mockWifiEnterpriseConfig;
+        when(mMockWifiEntry.getWifiConfiguration()).thenReturn(mockWifiConfiguration);
+
+        displayAndResume();
+
+        verify(mMockEapSimSubscriptionPref).setVisible(true);
+        verify(mMockEapSimSubscriptionPref).setSummary(R.string.wifi_no_related_sim_card);
+    }
+
     private ActionButtonsPreference createMock() {
         final ActionButtonsPreference pref = mock(ActionButtonsPreference.class);
         when(pref.setButton1Text(anyInt())).thenReturn(pref);