174390d669cf29f102a7a3804cfffc5934a39d4bcPeter Qiu/*
274390d669cf29f102a7a3804cfffc5934a39d4bcPeter Qiu * Copyright (C) 2017 The Android Open Source Project
374390d669cf29f102a7a3804cfffc5934a39d4bcPeter Qiu *
474390d669cf29f102a7a3804cfffc5934a39d4bcPeter Qiu * Licensed under the Apache License, Version 2.0 (the "License");
574390d669cf29f102a7a3804cfffc5934a39d4bcPeter Qiu * you may not use this file except in compliance with the License.
674390d669cf29f102a7a3804cfffc5934a39d4bcPeter Qiu * You may obtain a copy of the License at
774390d669cf29f102a7a3804cfffc5934a39d4bcPeter Qiu *
874390d669cf29f102a7a3804cfffc5934a39d4bcPeter Qiu *      http://www.apache.org/licenses/LICENSE-2.0
974390d669cf29f102a7a3804cfffc5934a39d4bcPeter Qiu *
1074390d669cf29f102a7a3804cfffc5934a39d4bcPeter Qiu * Unless required by applicable law or agreed to in writing, software
1174390d669cf29f102a7a3804cfffc5934a39d4bcPeter Qiu * distributed under the License is distributed on an "AS IS" BASIS,
1274390d669cf29f102a7a3804cfffc5934a39d4bcPeter Qiu * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1374390d669cf29f102a7a3804cfffc5934a39d4bcPeter Qiu * See the License for the specific language governing permissions and
1474390d669cf29f102a7a3804cfffc5934a39d4bcPeter Qiu * limitations under the License.
1574390d669cf29f102a7a3804cfffc5934a39d4bcPeter Qiu */
1674390d669cf29f102a7a3804cfffc5934a39d4bcPeter Qiu
1774390d669cf29f102a7a3804cfffc5934a39d4bcPeter Qiupackage com.android.server.wifi;
1874390d669cf29f102a7a3804cfffc5934a39d4bcPeter Qiu
1974390d669cf29f102a7a3804cfffc5934a39d4bcPeter Qiuimport android.content.BroadcastReceiver;
2074390d669cf29f102a7a3804cfffc5934a39d4bcPeter Qiuimport android.content.Context;
2174390d669cf29f102a7a3804cfffc5934a39d4bcPeter Qiuimport android.content.Intent;
2274390d669cf29f102a7a3804cfffc5934a39d4bcPeter Qiuimport android.content.IntentFilter;
2374390d669cf29f102a7a3804cfffc5934a39d4bcPeter Qiuimport android.net.wifi.EAPConstants;
2474390d669cf29f102a7a3804cfffc5934a39d4bcPeter Qiuimport android.net.wifi.WifiEnterpriseConfig;
2574390d669cf29f102a7a3804cfffc5934a39d4bcPeter Qiuimport android.os.PersistableBundle;
2674390d669cf29f102a7a3804cfffc5934a39d4bcPeter Qiuimport android.telephony.CarrierConfigManager;
2774390d669cf29f102a7a3804cfffc5934a39d4bcPeter Qiuimport android.telephony.SubscriptionInfo;
2874390d669cf29f102a7a3804cfffc5934a39d4bcPeter Qiuimport android.telephony.SubscriptionManager;
2974390d669cf29f102a7a3804cfffc5934a39d4bcPeter Qiuimport android.util.Base64;
3074390d669cf29f102a7a3804cfffc5934a39d4bcPeter Qiuimport android.util.Log;
3174390d669cf29f102a7a3804cfffc5934a39d4bcPeter Qiu
3274390d669cf29f102a7a3804cfffc5934a39d4bcPeter Qiuimport java.util.HashMap;
3374390d669cf29f102a7a3804cfffc5934a39d4bcPeter Qiuimport java.util.List;
3474390d669cf29f102a7a3804cfffc5934a39d4bcPeter Qiuimport java.util.Map;
3574390d669cf29f102a7a3804cfffc5934a39d4bcPeter Qiu
3674390d669cf29f102a7a3804cfffc5934a39d4bcPeter Qiu/**
3774390d669cf29f102a7a3804cfffc5934a39d4bcPeter Qiu * Class for maintaining/caching carrier Wi-Fi network configurations.
3874390d669cf29f102a7a3804cfffc5934a39d4bcPeter Qiu */
3974390d669cf29f102a7a3804cfffc5934a39d4bcPeter Qiupublic class CarrierNetworkConfig {
4074390d669cf29f102a7a3804cfffc5934a39d4bcPeter Qiu    private static final String TAG = "CarrierNetworkConfig";
4174390d669cf29f102a7a3804cfffc5934a39d4bcPeter Qiu
4274390d669cf29f102a7a3804cfffc5934a39d4bcPeter Qiu    private static final String NETWORK_CONFIG_SEPARATOR = ",";
4374390d669cf29f102a7a3804cfffc5934a39d4bcPeter Qiu    private static final int ENCODED_SSID_INDEX = 0;
4474390d669cf29f102a7a3804cfffc5934a39d4bcPeter Qiu    private static final int EAP_TYPE_INDEX = 1;
4574390d669cf29f102a7a3804cfffc5934a39d4bcPeter Qiu    private static final int CONFIG_ELEMENT_SIZE = 2;
4674390d669cf29f102a7a3804cfffc5934a39d4bcPeter Qiu
4774390d669cf29f102a7a3804cfffc5934a39d4bcPeter Qiu    private final Map<String, NetworkInfo> mCarrierNetworkMap;
4874390d669cf29f102a7a3804cfffc5934a39d4bcPeter Qiu
4974390d669cf29f102a7a3804cfffc5934a39d4bcPeter Qiu    public CarrierNetworkConfig(Context context) {
5074390d669cf29f102a7a3804cfffc5934a39d4bcPeter Qiu        mCarrierNetworkMap = new HashMap<>();
5174390d669cf29f102a7a3804cfffc5934a39d4bcPeter Qiu        updateNetworkConfig(context);
5274390d669cf29f102a7a3804cfffc5934a39d4bcPeter Qiu
5374390d669cf29f102a7a3804cfffc5934a39d4bcPeter Qiu        // Monitor for carrier config changes.
5474390d669cf29f102a7a3804cfffc5934a39d4bcPeter Qiu        IntentFilter filter = new IntentFilter();
5574390d669cf29f102a7a3804cfffc5934a39d4bcPeter Qiu        filter.addAction(CarrierConfigManager.ACTION_CARRIER_CONFIG_CHANGED);
5674390d669cf29f102a7a3804cfffc5934a39d4bcPeter Qiu        context.registerReceiver(new BroadcastReceiver() {
5774390d669cf29f102a7a3804cfffc5934a39d4bcPeter Qiu            @Override
5874390d669cf29f102a7a3804cfffc5934a39d4bcPeter Qiu            public void onReceive(Context context, Intent intent) {
5974390d669cf29f102a7a3804cfffc5934a39d4bcPeter Qiu                updateNetworkConfig(context);
6074390d669cf29f102a7a3804cfffc5934a39d4bcPeter Qiu            }
6174390d669cf29f102a7a3804cfffc5934a39d4bcPeter Qiu        }, filter);
6274390d669cf29f102a7a3804cfffc5934a39d4bcPeter Qiu    }
6374390d669cf29f102a7a3804cfffc5934a39d4bcPeter Qiu
6474390d669cf29f102a7a3804cfffc5934a39d4bcPeter Qiu    /**
6574390d669cf29f102a7a3804cfffc5934a39d4bcPeter Qiu     * @return true if the given SSID is associated with a carrier network
6674390d669cf29f102a7a3804cfffc5934a39d4bcPeter Qiu     */
6774390d669cf29f102a7a3804cfffc5934a39d4bcPeter Qiu    public boolean isCarrierNetwork(String ssid) {
6874390d669cf29f102a7a3804cfffc5934a39d4bcPeter Qiu        return mCarrierNetworkMap.containsKey(ssid);
6974390d669cf29f102a7a3804cfffc5934a39d4bcPeter Qiu    }
7074390d669cf29f102a7a3804cfffc5934a39d4bcPeter Qiu
7174390d669cf29f102a7a3804cfffc5934a39d4bcPeter Qiu    /**
7274390d669cf29f102a7a3804cfffc5934a39d4bcPeter Qiu     * @return the EAP type associated with a carrier AP, or -1 if the specified AP
7374390d669cf29f102a7a3804cfffc5934a39d4bcPeter Qiu     * is not associated with a carrier network
7474390d669cf29f102a7a3804cfffc5934a39d4bcPeter Qiu     */
7574390d669cf29f102a7a3804cfffc5934a39d4bcPeter Qiu    public int getNetworkEapType(String ssid) {
7674390d669cf29f102a7a3804cfffc5934a39d4bcPeter Qiu        NetworkInfo info = mCarrierNetworkMap.get(ssid);
7774390d669cf29f102a7a3804cfffc5934a39d4bcPeter Qiu        return info == null ? -1 : info.mEapType;
7874390d669cf29f102a7a3804cfffc5934a39d4bcPeter Qiu    }
7974390d669cf29f102a7a3804cfffc5934a39d4bcPeter Qiu
8074390d669cf29f102a7a3804cfffc5934a39d4bcPeter Qiu    /**
8174390d669cf29f102a7a3804cfffc5934a39d4bcPeter Qiu     * @return the name of carrier associated with a carrier AP, or null if the specified AP
8274390d669cf29f102a7a3804cfffc5934a39d4bcPeter Qiu     * is not associated with a carrier network.
8374390d669cf29f102a7a3804cfffc5934a39d4bcPeter Qiu     */
8474390d669cf29f102a7a3804cfffc5934a39d4bcPeter Qiu    public String getCarrierName(String ssid) {
8574390d669cf29f102a7a3804cfffc5934a39d4bcPeter Qiu        NetworkInfo info = mCarrierNetworkMap.get(ssid);
8674390d669cf29f102a7a3804cfffc5934a39d4bcPeter Qiu        return info == null ? null : info.mCarrierName;
8774390d669cf29f102a7a3804cfffc5934a39d4bcPeter Qiu    }
8874390d669cf29f102a7a3804cfffc5934a39d4bcPeter Qiu
8974390d669cf29f102a7a3804cfffc5934a39d4bcPeter Qiu    /**
9074390d669cf29f102a7a3804cfffc5934a39d4bcPeter Qiu     * Utility class for storing carrier network information.
9174390d669cf29f102a7a3804cfffc5934a39d4bcPeter Qiu     */
9274390d669cf29f102a7a3804cfffc5934a39d4bcPeter Qiu    private static class NetworkInfo {
9374390d669cf29f102a7a3804cfffc5934a39d4bcPeter Qiu        final int mEapType;
9474390d669cf29f102a7a3804cfffc5934a39d4bcPeter Qiu        final String mCarrierName;
9574390d669cf29f102a7a3804cfffc5934a39d4bcPeter Qiu
9674390d669cf29f102a7a3804cfffc5934a39d4bcPeter Qiu        NetworkInfo(int eapType, String carrierName) {
9774390d669cf29f102a7a3804cfffc5934a39d4bcPeter Qiu            mEapType = eapType;
9874390d669cf29f102a7a3804cfffc5934a39d4bcPeter Qiu            mCarrierName = carrierName;
9974390d669cf29f102a7a3804cfffc5934a39d4bcPeter Qiu        }
10074390d669cf29f102a7a3804cfffc5934a39d4bcPeter Qiu    }
10174390d669cf29f102a7a3804cfffc5934a39d4bcPeter Qiu
10274390d669cf29f102a7a3804cfffc5934a39d4bcPeter Qiu    /**
10374390d669cf29f102a7a3804cfffc5934a39d4bcPeter Qiu     * Update the carrier network map based on the current carrier configuration of the active
10474390d669cf29f102a7a3804cfffc5934a39d4bcPeter Qiu     * subscriptions.
10574390d669cf29f102a7a3804cfffc5934a39d4bcPeter Qiu     *
10674390d669cf29f102a7a3804cfffc5934a39d4bcPeter Qiu     * @param context Current application context
10774390d669cf29f102a7a3804cfffc5934a39d4bcPeter Qiu     */
10874390d669cf29f102a7a3804cfffc5934a39d4bcPeter Qiu    private void updateNetworkConfig(Context context) {
10974390d669cf29f102a7a3804cfffc5934a39d4bcPeter Qiu        // Reset network map.
11074390d669cf29f102a7a3804cfffc5934a39d4bcPeter Qiu        mCarrierNetworkMap.clear();
11174390d669cf29f102a7a3804cfffc5934a39d4bcPeter Qiu
11274390d669cf29f102a7a3804cfffc5934a39d4bcPeter Qiu        CarrierConfigManager carrierConfigManager =
11374390d669cf29f102a7a3804cfffc5934a39d4bcPeter Qiu                (CarrierConfigManager) context.getSystemService(Context.CARRIER_CONFIG_SERVICE);
11474390d669cf29f102a7a3804cfffc5934a39d4bcPeter Qiu        if (carrierConfigManager == null) {
11574390d669cf29f102a7a3804cfffc5934a39d4bcPeter Qiu            return;
11674390d669cf29f102a7a3804cfffc5934a39d4bcPeter Qiu        }
11774390d669cf29f102a7a3804cfffc5934a39d4bcPeter Qiu
11874390d669cf29f102a7a3804cfffc5934a39d4bcPeter Qiu        SubscriptionManager subscriptionManager = (SubscriptionManager) context.getSystemService(
11974390d669cf29f102a7a3804cfffc5934a39d4bcPeter Qiu                Context.TELEPHONY_SUBSCRIPTION_SERVICE);
12074390d669cf29f102a7a3804cfffc5934a39d4bcPeter Qiu        if (subscriptionManager == null) {
12174390d669cf29f102a7a3804cfffc5934a39d4bcPeter Qiu            return;
12274390d669cf29f102a7a3804cfffc5934a39d4bcPeter Qiu        }
12374390d669cf29f102a7a3804cfffc5934a39d4bcPeter Qiu        List<SubscriptionInfo> subInfoList = subscriptionManager.getActiveSubscriptionInfoList();
12474390d669cf29f102a7a3804cfffc5934a39d4bcPeter Qiu        if (subInfoList == null) {
12574390d669cf29f102a7a3804cfffc5934a39d4bcPeter Qiu            return;
12674390d669cf29f102a7a3804cfffc5934a39d4bcPeter Qiu        }
12774390d669cf29f102a7a3804cfffc5934a39d4bcPeter Qiu
12874390d669cf29f102a7a3804cfffc5934a39d4bcPeter Qiu        // Process the carrier config for each active subscription.
12974390d669cf29f102a7a3804cfffc5934a39d4bcPeter Qiu        for (SubscriptionInfo subInfo : subInfoList) {
13074390d669cf29f102a7a3804cfffc5934a39d4bcPeter Qiu            processNetworkConfig(
13174390d669cf29f102a7a3804cfffc5934a39d4bcPeter Qiu                    carrierConfigManager.getConfigForSubId(subInfo.getSubscriptionId()),
13274390d669cf29f102a7a3804cfffc5934a39d4bcPeter Qiu                    subInfo.getDisplayName().toString());
13374390d669cf29f102a7a3804cfffc5934a39d4bcPeter Qiu        }
13474390d669cf29f102a7a3804cfffc5934a39d4bcPeter Qiu    }
13574390d669cf29f102a7a3804cfffc5934a39d4bcPeter Qiu
13674390d669cf29f102a7a3804cfffc5934a39d4bcPeter Qiu    /**
13774390d669cf29f102a7a3804cfffc5934a39d4bcPeter Qiu     * Process the carrier network config, the network config string is formatted as follow:
13874390d669cf29f102a7a3804cfffc5934a39d4bcPeter Qiu     *
13974390d669cf29f102a7a3804cfffc5934a39d4bcPeter Qiu     * "[Base64 Encoded SSID],[EAP Type]"
14074390d669cf29f102a7a3804cfffc5934a39d4bcPeter Qiu     * Where EAP Type is the standard EAP method number, refer to
14174390d669cf29f102a7a3804cfffc5934a39d4bcPeter Qiu     * http://www.iana.org/assignments/eap-numbers/eap-numbers.xhtml for more info.
14274390d669cf29f102a7a3804cfffc5934a39d4bcPeter Qiu
14374390d669cf29f102a7a3804cfffc5934a39d4bcPeter Qiu     * @param carrierConfig The bundle containing the carrier configuration
14474390d669cf29f102a7a3804cfffc5934a39d4bcPeter Qiu     * @param carrierName The display name of the associated carrier
14574390d669cf29f102a7a3804cfffc5934a39d4bcPeter Qiu     */
14674390d669cf29f102a7a3804cfffc5934a39d4bcPeter Qiu    private void processNetworkConfig(PersistableBundle carrierConfig, String carrierName) {
14774390d669cf29f102a7a3804cfffc5934a39d4bcPeter Qiu        if (carrierConfig == null) {
14874390d669cf29f102a7a3804cfffc5934a39d4bcPeter Qiu            return;
14974390d669cf29f102a7a3804cfffc5934a39d4bcPeter Qiu        }
15074390d669cf29f102a7a3804cfffc5934a39d4bcPeter Qiu        String[] networkConfigs = carrierConfig.getStringArray(
15174390d669cf29f102a7a3804cfffc5934a39d4bcPeter Qiu                CarrierConfigManager.KEY_CARRIER_WIFI_STRING_ARRAY);
15274390d669cf29f102a7a3804cfffc5934a39d4bcPeter Qiu        if (networkConfigs == null) {
15374390d669cf29f102a7a3804cfffc5934a39d4bcPeter Qiu            return;
15474390d669cf29f102a7a3804cfffc5934a39d4bcPeter Qiu        }
15574390d669cf29f102a7a3804cfffc5934a39d4bcPeter Qiu
15674390d669cf29f102a7a3804cfffc5934a39d4bcPeter Qiu        for (String networkConfig : networkConfigs) {
15774390d669cf29f102a7a3804cfffc5934a39d4bcPeter Qiu            String[] configArr = networkConfig.split(NETWORK_CONFIG_SEPARATOR);
15874390d669cf29f102a7a3804cfffc5934a39d4bcPeter Qiu            if (configArr.length != CONFIG_ELEMENT_SIZE) {
15974390d669cf29f102a7a3804cfffc5934a39d4bcPeter Qiu                Log.e(TAG, "Ignore invalid config: " + networkConfig);
16074390d669cf29f102a7a3804cfffc5934a39d4bcPeter Qiu                continue;
16174390d669cf29f102a7a3804cfffc5934a39d4bcPeter Qiu            }
16274390d669cf29f102a7a3804cfffc5934a39d4bcPeter Qiu            try {
16374390d669cf29f102a7a3804cfffc5934a39d4bcPeter Qiu                String ssid = new String(Base64.decode(
16474390d669cf29f102a7a3804cfffc5934a39d4bcPeter Qiu                        configArr[ENCODED_SSID_INDEX], Base64.DEFAULT));
16574390d669cf29f102a7a3804cfffc5934a39d4bcPeter Qiu                int eapType = parseEapType(Integer.parseInt(configArr[EAP_TYPE_INDEX]));
16674390d669cf29f102a7a3804cfffc5934a39d4bcPeter Qiu                // Verify EAP type, must be a SIM based EAP type.
16774390d669cf29f102a7a3804cfffc5934a39d4bcPeter Qiu                if (eapType == -1) {
16874390d669cf29f102a7a3804cfffc5934a39d4bcPeter Qiu                    Log.e(TAG, "Invalid EAP type: " + configArr[EAP_TYPE_INDEX]);
16974390d669cf29f102a7a3804cfffc5934a39d4bcPeter Qiu                    continue;
17074390d669cf29f102a7a3804cfffc5934a39d4bcPeter Qiu                }
17174390d669cf29f102a7a3804cfffc5934a39d4bcPeter Qiu                mCarrierNetworkMap.put(ssid, new NetworkInfo(eapType, carrierName));
17274390d669cf29f102a7a3804cfffc5934a39d4bcPeter Qiu            } catch (NumberFormatException e) {
17374390d669cf29f102a7a3804cfffc5934a39d4bcPeter Qiu                Log.e(TAG, "Failed to parse EAP type: " + e.getMessage());
17474390d669cf29f102a7a3804cfffc5934a39d4bcPeter Qiu            } catch (IllegalArgumentException e) {
17574390d669cf29f102a7a3804cfffc5934a39d4bcPeter Qiu                Log.e(TAG, "Failed to decode SSID: " + e.getMessage());
17674390d669cf29f102a7a3804cfffc5934a39d4bcPeter Qiu            }
17774390d669cf29f102a7a3804cfffc5934a39d4bcPeter Qiu        }
17874390d669cf29f102a7a3804cfffc5934a39d4bcPeter Qiu    }
17974390d669cf29f102a7a3804cfffc5934a39d4bcPeter Qiu
18074390d669cf29f102a7a3804cfffc5934a39d4bcPeter Qiu    /**
18174390d669cf29f102a7a3804cfffc5934a39d4bcPeter Qiu     * Convert a standard SIM-based EAP type (SIM, AKA, AKA') to the internal EAP type as defined in
18274390d669cf29f102a7a3804cfffc5934a39d4bcPeter Qiu     * {@link WifiEnterpriseConfig.Eap}. -1 will be returned if the given EAP type is not
18374390d669cf29f102a7a3804cfffc5934a39d4bcPeter Qiu     * SIM-based.
18474390d669cf29f102a7a3804cfffc5934a39d4bcPeter Qiu     *
18574390d669cf29f102a7a3804cfffc5934a39d4bcPeter Qiu     * @return SIM-based EAP type as defined in {@link WifiEnterpriseConfig.Eap}, or -1 if not
18674390d669cf29f102a7a3804cfffc5934a39d4bcPeter Qiu     * SIM-based EAP type
18774390d669cf29f102a7a3804cfffc5934a39d4bcPeter Qiu     */
18874390d669cf29f102a7a3804cfffc5934a39d4bcPeter Qiu    private static int parseEapType(int eapType) {
18974390d669cf29f102a7a3804cfffc5934a39d4bcPeter Qiu        if (eapType == EAPConstants.EAP_SIM) {
19074390d669cf29f102a7a3804cfffc5934a39d4bcPeter Qiu            return WifiEnterpriseConfig.Eap.SIM;
19174390d669cf29f102a7a3804cfffc5934a39d4bcPeter Qiu        } else if (eapType == EAPConstants.EAP_AKA) {
19274390d669cf29f102a7a3804cfffc5934a39d4bcPeter Qiu            return WifiEnterpriseConfig.Eap.AKA;
19374390d669cf29f102a7a3804cfffc5934a39d4bcPeter Qiu        } else if (eapType == EAPConstants.EAP_AKA_PRIME) {
19474390d669cf29f102a7a3804cfffc5934a39d4bcPeter Qiu            return WifiEnterpriseConfig.Eap.AKA_PRIME;
19574390d669cf29f102a7a3804cfffc5934a39d4bcPeter Qiu        }
19674390d669cf29f102a7a3804cfffc5934a39d4bcPeter Qiu        return -1;
19774390d669cf29f102a7a3804cfffc5934a39d4bcPeter Qiu    }
19874390d669cf29f102a7a3804cfffc5934a39d4bcPeter Qiu}
199