Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit b42d09f8 authored by Arc Wang's avatar Arc Wang Committed by Android (Google) Code Review
Browse files

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

parents 88e43633 e410325b
Loading
Loading
Loading
Loading
+18 −0
Original line number Diff line number Diff line
@@ -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"
+11 −0
Original line number Diff line number Diff line
@@ -11521,6 +11521,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] -->
+5 −0
Original line number Diff line number Diff line
@@ -105,6 +105,11 @@
                android:title="@string/wifi_advanced_ssid_title"
                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"
+75 −5
Original line number Diff line number Diff line
@@ -35,6 +35,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;

/**
@@ -157,7 +161,8 @@ public class WifiConfigController2 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;
@@ -202,6 +207,8 @@ public class WifiConfigController2 implements TextWatcher,

    private final WifiManager mWifiManager;

    private final List<SubscriptionInfo> mActiveSubscriptionInfos = new ArrayList<>();

    public WifiConfigController2(WifiConfigUiBase2 parent, View view, WifiEntry wifiEntry,
            int mode) {
        mConfigUi = parent;
@@ -690,6 +697,12 @@ public class WifiConfigController2 implements TextWatcher,
                        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);
@@ -964,6 +977,7 @@ public class WifiConfigController2 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);
@@ -1001,6 +1015,8 @@ public class WifiConfigController2 implements TextWatcher,
        }

        if (refreshCertificates) {
            loadSims();

            loadCertificates(
                    mEapCaCertSpinner,
                    Credentials.CA_CERTIFICATE,
@@ -1022,10 +1038,10 @@ public class WifiConfigController2 implements TextWatcher,

        // 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) {
@@ -1073,6 +1089,16 @@ public class WifiConfigController2 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 {
@@ -1161,6 +1187,7 @@ public class WifiConfigController2 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) {
@@ -1171,12 +1198,14 @@ public class WifiConfigController2 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
@@ -1198,6 +1227,7 @@ public class WifiConfigController2 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:
@@ -1235,11 +1265,13 @@ public class WifiConfigController2 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);
        }
    }

@@ -1402,6 +1434,44 @@ public class WifiConfigController2 implements TextWatcher,
        return KeyStore.getInstance();
    }

    @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,
+99 −0
Original line number Diff line number Diff line
@@ -23,8 +23,10 @@ import static android.net.NetworkCapabilities.TRANSPORT_WIFI;
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.NetworkRequest;
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;
@@ -97,6 +104,7 @@ import java.time.Instant;
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;

@@ -132,6 +140,8 @@ public class WifiDetailPreferenceController2 extends AbstractPreferenceControlle
    @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";
@@ -169,6 +179,7 @@ public class WifiDetailPreferenceController2 extends AbstractPreferenceControlle
    private Preference mFrequencyPref;
    private Preference mSecurityPref;
    private Preference mSsidPref;
    private Preference mEapSimSubscriptionPref;
    private Preference mMacAddressPref;
    private Preference mIpAddressPref;
    private Preference mGatewayPref;
@@ -186,6 +197,35 @@ public class WifiDetailPreferenceController2 extends AbstractPreferenceControlle
    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
@@ -335,6 +375,7 @@ public class WifiDetailPreferenceController2 extends AbstractPreferenceControlle
        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);
@@ -506,6 +547,8 @@ public class WifiDetailPreferenceController2 extends AbstractPreferenceControlle
        refreshIpLayerInfo();
        // SSID Pref
        refreshSsid();
        // EAP SIM subscription
        refreshEapSimSubscription();
        // MAC Address Pref
        refreshMacAddress();
    }
@@ -627,6 +670,62 @@ public class WifiDetailPreferenceController2 extends AbstractPreferenceControlle
        }
    }

    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)) {
Loading