19c7730dd2cbf7c8d0d42052bee15a7a1323b8133Randy Pan/*
29c7730dd2cbf7c8d0d42052bee15a7a1323b8133Randy Pan * Copyright (C) 2017 The Android Open Source Project
39c7730dd2cbf7c8d0d42052bee15a7a1323b8133Randy Pan *
49c7730dd2cbf7c8d0d42052bee15a7a1323b8133Randy Pan * Licensed under the Apache License, Version 2.0 (the "License");
59c7730dd2cbf7c8d0d42052bee15a7a1323b8133Randy Pan * you may not use this file except in compliance with the License.
69c7730dd2cbf7c8d0d42052bee15a7a1323b8133Randy Pan * You may obtain a copy of the License at
79c7730dd2cbf7c8d0d42052bee15a7a1323b8133Randy Pan *
89c7730dd2cbf7c8d0d42052bee15a7a1323b8133Randy Pan *      http://www.apache.org/licenses/LICENSE-2.0
99c7730dd2cbf7c8d0d42052bee15a7a1323b8133Randy Pan *
109c7730dd2cbf7c8d0d42052bee15a7a1323b8133Randy Pan * Unless required by applicable law or agreed to in writing, software
119c7730dd2cbf7c8d0d42052bee15a7a1323b8133Randy Pan * distributed under the License is distributed on an "AS IS" BASIS,
129c7730dd2cbf7c8d0d42052bee15a7a1323b8133Randy Pan * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
139c7730dd2cbf7c8d0d42052bee15a7a1323b8133Randy Pan * See the License for the specific language governing permissions and
149c7730dd2cbf7c8d0d42052bee15a7a1323b8133Randy Pan * limitations under the License.
159c7730dd2cbf7c8d0d42052bee15a7a1323b8133Randy Pan */
169c7730dd2cbf7c8d0d42052bee15a7a1323b8133Randy Pan
179c7730dd2cbf7c8d0d42052bee15a7a1323b8133Randy Panpackage com.android.server.wifi;
189c7730dd2cbf7c8d0d42052bee15a7a1323b8133Randy Pan
199c7730dd2cbf7c8d0d42052bee15a7a1323b8133Randy Panimport static android.net.wifi.WifiManager.WIFI_FEATURE_CONTROL_ROAMING;
209c7730dd2cbf7c8d0d42052bee15a7a1323b8133Randy Pan
219c7730dd2cbf7c8d0d42052bee15a7a1323b8133Randy Panimport android.util.Log;
229c7730dd2cbf7c8d0d42052bee15a7a1323b8133Randy Pan
239c7730dd2cbf7c8d0d42052bee15a7a1323b8133Randy Panimport com.android.internal.annotations.VisibleForTesting;
249c7730dd2cbf7c8d0d42052bee15a7a1323b8133Randy Pan
259c7730dd2cbf7c8d0d42052bee15a7a1323b8133Randy Panimport java.util.ArrayList;
269c7730dd2cbf7c8d0d42052bee15a7a1323b8133Randy Pan
279c7730dd2cbf7c8d0d42052bee15a7a1323b8133Randy Pan/**
289c7730dd2cbf7c8d0d42052bee15a7a1323b8133Randy Pan * This class provides helper functions for Wifi connectivity related modules to
299c7730dd2cbf7c8d0d42052bee15a7a1323b8133Randy Pan * access WifiNative. It starts with firmware roaming. TODO(b/34819513): Move operations
309c7730dd2cbf7c8d0d42052bee15a7a1323b8133Randy Pan * such as connection to network and legacy framework roaming here.
319c7730dd2cbf7c8d0d42052bee15a7a1323b8133Randy Pan *
329c7730dd2cbf7c8d0d42052bee15a7a1323b8133Randy Pan * NOTE: This class is not thread safe and should only be used from the WifiStateMachine thread.
339c7730dd2cbf7c8d0d42052bee15a7a1323b8133Randy Pan */
349c7730dd2cbf7c8d0d42052bee15a7a1323b8133Randy Panpublic class WifiConnectivityHelper {
359c7730dd2cbf7c8d0d42052bee15a7a1323b8133Randy Pan    private static final String TAG = "WifiConnectivityHelper";
369c7730dd2cbf7c8d0d42052bee15a7a1323b8133Randy Pan    @VisibleForTesting
379c7730dd2cbf7c8d0d42052bee15a7a1323b8133Randy Pan    public static int INVALID_LIST_SIZE = -1;
389c7730dd2cbf7c8d0d42052bee15a7a1323b8133Randy Pan    private final WifiNative mWifiNative;
399c7730dd2cbf7c8d0d42052bee15a7a1323b8133Randy Pan    private boolean mFirmwareRoamingSupported = false;
409c7730dd2cbf7c8d0d42052bee15a7a1323b8133Randy Pan    private int mMaxNumBlacklistBssid = INVALID_LIST_SIZE;
419c7730dd2cbf7c8d0d42052bee15a7a1323b8133Randy Pan    private int mMaxNumWhitelistSsid = INVALID_LIST_SIZE;
429c7730dd2cbf7c8d0d42052bee15a7a1323b8133Randy Pan
439c7730dd2cbf7c8d0d42052bee15a7a1323b8133Randy Pan    WifiConnectivityHelper(WifiNative wifiNative) {
449c7730dd2cbf7c8d0d42052bee15a7a1323b8133Randy Pan        mWifiNative = wifiNative;
459c7730dd2cbf7c8d0d42052bee15a7a1323b8133Randy Pan    }
469c7730dd2cbf7c8d0d42052bee15a7a1323b8133Randy Pan
479c7730dd2cbf7c8d0d42052bee15a7a1323b8133Randy Pan    /**
489c7730dd2cbf7c8d0d42052bee15a7a1323b8133Randy Pan     * Query firmware if it supports
499c7730dd2cbf7c8d0d42052bee15a7a1323b8133Randy Pan     * {@link android.net.wifi.WifiManager#WIFI_FEATURE_CONTROL_ROAMING}. If yes, get the firmware
509c7730dd2cbf7c8d0d42052bee15a7a1323b8133Randy Pan     * roaming capabilities. If firmware roaming is supported but we fail to get the roaming
519c7730dd2cbf7c8d0d42052bee15a7a1323b8133Randy Pan     * capabilities or the returned capability values are invalid, we fall back to framework
529c7730dd2cbf7c8d0d42052bee15a7a1323b8133Randy Pan     * roaming.
539c7730dd2cbf7c8d0d42052bee15a7a1323b8133Randy Pan     *
549c7730dd2cbf7c8d0d42052bee15a7a1323b8133Randy Pan     * @return true if succeed, false if firmware roaming is supported but fail to get valid
559c7730dd2cbf7c8d0d42052bee15a7a1323b8133Randy Pan     * roaming capabilities.
569c7730dd2cbf7c8d0d42052bee15a7a1323b8133Randy Pan     */
579c7730dd2cbf7c8d0d42052bee15a7a1323b8133Randy Pan    public boolean getFirmwareRoamingInfo() {
589c7730dd2cbf7c8d0d42052bee15a7a1323b8133Randy Pan        mFirmwareRoamingSupported = false;
599c7730dd2cbf7c8d0d42052bee15a7a1323b8133Randy Pan        mMaxNumBlacklistBssid = INVALID_LIST_SIZE;
609c7730dd2cbf7c8d0d42052bee15a7a1323b8133Randy Pan        mMaxNumWhitelistSsid = INVALID_LIST_SIZE;
619c7730dd2cbf7c8d0d42052bee15a7a1323b8133Randy Pan
6252ed1731664f7e0b76adb14eec7a76eaa95144c3Roshan Pius        int fwFeatureSet = mWifiNative.getSupportedFeatureSet(mWifiNative.getClientInterfaceName());
639c7730dd2cbf7c8d0d42052bee15a7a1323b8133Randy Pan        Log.d(TAG, "Firmware supported feature set: " + Integer.toHexString(fwFeatureSet));
649c7730dd2cbf7c8d0d42052bee15a7a1323b8133Randy Pan
659c7730dd2cbf7c8d0d42052bee15a7a1323b8133Randy Pan        if ((fwFeatureSet & WIFI_FEATURE_CONTROL_ROAMING) == 0) {
669c7730dd2cbf7c8d0d42052bee15a7a1323b8133Randy Pan            Log.d(TAG, "Firmware roaming is not supported");
679c7730dd2cbf7c8d0d42052bee15a7a1323b8133Randy Pan            return true;
689c7730dd2cbf7c8d0d42052bee15a7a1323b8133Randy Pan        }
699c7730dd2cbf7c8d0d42052bee15a7a1323b8133Randy Pan
709c7730dd2cbf7c8d0d42052bee15a7a1323b8133Randy Pan        WifiNative.RoamingCapabilities roamingCap = new WifiNative.RoamingCapabilities();
7152ed1731664f7e0b76adb14eec7a76eaa95144c3Roshan Pius        if (mWifiNative.getRoamingCapabilities(mWifiNative.getClientInterfaceName(), roamingCap)) {
729c7730dd2cbf7c8d0d42052bee15a7a1323b8133Randy Pan            if (roamingCap.maxBlacklistSize < 0 || roamingCap.maxWhitelistSize < 0) {
739c7730dd2cbf7c8d0d42052bee15a7a1323b8133Randy Pan                Log.e(TAG, "Invalid firmware roaming capabilities: max num blacklist bssid="
749c7730dd2cbf7c8d0d42052bee15a7a1323b8133Randy Pan                        + roamingCap.maxBlacklistSize + " max num whitelist ssid="
759c7730dd2cbf7c8d0d42052bee15a7a1323b8133Randy Pan                        + roamingCap.maxWhitelistSize);
769c7730dd2cbf7c8d0d42052bee15a7a1323b8133Randy Pan            } else {
779c7730dd2cbf7c8d0d42052bee15a7a1323b8133Randy Pan                mFirmwareRoamingSupported = true;
789c7730dd2cbf7c8d0d42052bee15a7a1323b8133Randy Pan                mMaxNumBlacklistBssid = roamingCap.maxBlacklistSize;
799c7730dd2cbf7c8d0d42052bee15a7a1323b8133Randy Pan                mMaxNumWhitelistSsid = roamingCap.maxWhitelistSize;
809c7730dd2cbf7c8d0d42052bee15a7a1323b8133Randy Pan                Log.d(TAG, "Firmware roaming supported with capabilities: max num blacklist bssid="
819c7730dd2cbf7c8d0d42052bee15a7a1323b8133Randy Pan                        + mMaxNumBlacklistBssid + " max num whitelist ssid="
829c7730dd2cbf7c8d0d42052bee15a7a1323b8133Randy Pan                        + mMaxNumWhitelistSsid);
839c7730dd2cbf7c8d0d42052bee15a7a1323b8133Randy Pan                return true;
849c7730dd2cbf7c8d0d42052bee15a7a1323b8133Randy Pan            }
859c7730dd2cbf7c8d0d42052bee15a7a1323b8133Randy Pan        } else {
869c7730dd2cbf7c8d0d42052bee15a7a1323b8133Randy Pan            Log.e(TAG, "Failed to get firmware roaming capabilities");
879c7730dd2cbf7c8d0d42052bee15a7a1323b8133Randy Pan        }
889c7730dd2cbf7c8d0d42052bee15a7a1323b8133Randy Pan
899c7730dd2cbf7c8d0d42052bee15a7a1323b8133Randy Pan        return false;
909c7730dd2cbf7c8d0d42052bee15a7a1323b8133Randy Pan    }
919c7730dd2cbf7c8d0d42052bee15a7a1323b8133Randy Pan
929c7730dd2cbf7c8d0d42052bee15a7a1323b8133Randy Pan    /**
939c7730dd2cbf7c8d0d42052bee15a7a1323b8133Randy Pan     * Return if firmware roaming is supported.
949c7730dd2cbf7c8d0d42052bee15a7a1323b8133Randy Pan     */
959c7730dd2cbf7c8d0d42052bee15a7a1323b8133Randy Pan    public boolean isFirmwareRoamingSupported() {
969c7730dd2cbf7c8d0d42052bee15a7a1323b8133Randy Pan        return mFirmwareRoamingSupported;
979c7730dd2cbf7c8d0d42052bee15a7a1323b8133Randy Pan    }
989c7730dd2cbf7c8d0d42052bee15a7a1323b8133Randy Pan
999c7730dd2cbf7c8d0d42052bee15a7a1323b8133Randy Pan    /**
1009c7730dd2cbf7c8d0d42052bee15a7a1323b8133Randy Pan     * Get the maximum size of BSSID blacklist firmware supports.
1019c7730dd2cbf7c8d0d42052bee15a7a1323b8133Randy Pan     *
1029c7730dd2cbf7c8d0d42052bee15a7a1323b8133Randy Pan     * @return INVALID_LIST_SIZE if firmware roaming is not supported, or
1039c7730dd2cbf7c8d0d42052bee15a7a1323b8133Randy Pan     * maximum size of the BSSID blacklist firmware supports.
1049c7730dd2cbf7c8d0d42052bee15a7a1323b8133Randy Pan     */
1059c7730dd2cbf7c8d0d42052bee15a7a1323b8133Randy Pan    public int getMaxNumBlacklistBssid() {
1069c7730dd2cbf7c8d0d42052bee15a7a1323b8133Randy Pan        if (mFirmwareRoamingSupported) {
1079c7730dd2cbf7c8d0d42052bee15a7a1323b8133Randy Pan            return mMaxNumBlacklistBssid;
1089c7730dd2cbf7c8d0d42052bee15a7a1323b8133Randy Pan        } else {
1099c7730dd2cbf7c8d0d42052bee15a7a1323b8133Randy Pan            Log.e(TAG, "getMaxNumBlacklistBssid: Firmware roaming is not supported");
1109c7730dd2cbf7c8d0d42052bee15a7a1323b8133Randy Pan            return INVALID_LIST_SIZE;
1119c7730dd2cbf7c8d0d42052bee15a7a1323b8133Randy Pan        }
1129c7730dd2cbf7c8d0d42052bee15a7a1323b8133Randy Pan    }
1139c7730dd2cbf7c8d0d42052bee15a7a1323b8133Randy Pan
1149c7730dd2cbf7c8d0d42052bee15a7a1323b8133Randy Pan    /**
1159c7730dd2cbf7c8d0d42052bee15a7a1323b8133Randy Pan     * Get the maximum size of SSID whitelist firmware supports.
1169c7730dd2cbf7c8d0d42052bee15a7a1323b8133Randy Pan     *
1179c7730dd2cbf7c8d0d42052bee15a7a1323b8133Randy Pan     * @return INVALID_LIST_SIZE if firmware roaming is not supported, or
1189c7730dd2cbf7c8d0d42052bee15a7a1323b8133Randy Pan     * maximum size of the SSID whitelist firmware supports.
1199c7730dd2cbf7c8d0d42052bee15a7a1323b8133Randy Pan     */
1209c7730dd2cbf7c8d0d42052bee15a7a1323b8133Randy Pan    public int getMaxNumWhitelistSsid() {
1219c7730dd2cbf7c8d0d42052bee15a7a1323b8133Randy Pan        if (mFirmwareRoamingSupported) {
1229c7730dd2cbf7c8d0d42052bee15a7a1323b8133Randy Pan            return mMaxNumWhitelistSsid;
1239c7730dd2cbf7c8d0d42052bee15a7a1323b8133Randy Pan        } else {
1249c7730dd2cbf7c8d0d42052bee15a7a1323b8133Randy Pan            Log.e(TAG, "getMaxNumWhitelistSsid: Firmware roaming is not supported");
1259c7730dd2cbf7c8d0d42052bee15a7a1323b8133Randy Pan            return INVALID_LIST_SIZE;
1269c7730dd2cbf7c8d0d42052bee15a7a1323b8133Randy Pan        }
1279c7730dd2cbf7c8d0d42052bee15a7a1323b8133Randy Pan    }
1289c7730dd2cbf7c8d0d42052bee15a7a1323b8133Randy Pan
1299c7730dd2cbf7c8d0d42052bee15a7a1323b8133Randy Pan    /**
1309c7730dd2cbf7c8d0d42052bee15a7a1323b8133Randy Pan     * Write firmware roaming configuration to firmware.
1319c7730dd2cbf7c8d0d42052bee15a7a1323b8133Randy Pan     *
1329c7730dd2cbf7c8d0d42052bee15a7a1323b8133Randy Pan     * @param blacklistBssids BSSIDs to be blacklisted
1339c7730dd2cbf7c8d0d42052bee15a7a1323b8133Randy Pan     * @param whitelistSsids  SSIDs to be whitelisted
1349c7730dd2cbf7c8d0d42052bee15a7a1323b8133Randy Pan     * @return true if succeeded, false otherwise.
1359c7730dd2cbf7c8d0d42052bee15a7a1323b8133Randy Pan     */
1369c7730dd2cbf7c8d0d42052bee15a7a1323b8133Randy Pan    public boolean setFirmwareRoamingConfiguration(ArrayList<String> blacklistBssids,
1379c7730dd2cbf7c8d0d42052bee15a7a1323b8133Randy Pan            ArrayList<String> whitelistSsids) {
1389c7730dd2cbf7c8d0d42052bee15a7a1323b8133Randy Pan        if (!mFirmwareRoamingSupported) {
1399c7730dd2cbf7c8d0d42052bee15a7a1323b8133Randy Pan            Log.e(TAG, "Firmware roaming is not supported");
1409c7730dd2cbf7c8d0d42052bee15a7a1323b8133Randy Pan            return false;
1419c7730dd2cbf7c8d0d42052bee15a7a1323b8133Randy Pan        }
1429c7730dd2cbf7c8d0d42052bee15a7a1323b8133Randy Pan
1439c7730dd2cbf7c8d0d42052bee15a7a1323b8133Randy Pan        if (blacklistBssids == null || whitelistSsids == null) {
1449c7730dd2cbf7c8d0d42052bee15a7a1323b8133Randy Pan            Log.e(TAG, "Invalid firmware roaming configuration settings");
1459c7730dd2cbf7c8d0d42052bee15a7a1323b8133Randy Pan            return false;
1469c7730dd2cbf7c8d0d42052bee15a7a1323b8133Randy Pan        }
1479c7730dd2cbf7c8d0d42052bee15a7a1323b8133Randy Pan
1489c7730dd2cbf7c8d0d42052bee15a7a1323b8133Randy Pan        int blacklistSize = blacklistBssids.size();
1499c7730dd2cbf7c8d0d42052bee15a7a1323b8133Randy Pan        int whitelistSize = whitelistSsids.size();
1509c7730dd2cbf7c8d0d42052bee15a7a1323b8133Randy Pan
1519c7730dd2cbf7c8d0d42052bee15a7a1323b8133Randy Pan        if (blacklistSize > mMaxNumBlacklistBssid || whitelistSize > mMaxNumWhitelistSsid) {
1529c7730dd2cbf7c8d0d42052bee15a7a1323b8133Randy Pan            Log.e(TAG, "Invalid BSSID blacklist size " + blacklistSize + " SSID whitelist size "
1539c7730dd2cbf7c8d0d42052bee15a7a1323b8133Randy Pan                    + whitelistSize + ". Max blacklist size: " + mMaxNumBlacklistBssid
1549c7730dd2cbf7c8d0d42052bee15a7a1323b8133Randy Pan                    + ", max whitelist size: " + mMaxNumWhitelistSsid);
1559c7730dd2cbf7c8d0d42052bee15a7a1323b8133Randy Pan            return false;
1569c7730dd2cbf7c8d0d42052bee15a7a1323b8133Randy Pan        }
1579c7730dd2cbf7c8d0d42052bee15a7a1323b8133Randy Pan
1589c7730dd2cbf7c8d0d42052bee15a7a1323b8133Randy Pan        WifiNative.RoamingConfig roamConfig = new WifiNative.RoamingConfig();
1599c7730dd2cbf7c8d0d42052bee15a7a1323b8133Randy Pan        roamConfig.blacklistBssids = blacklistBssids;
1609c7730dd2cbf7c8d0d42052bee15a7a1323b8133Randy Pan        roamConfig.whitelistSsids = whitelistSsids;
1619c7730dd2cbf7c8d0d42052bee15a7a1323b8133Randy Pan
16252ed1731664f7e0b76adb14eec7a76eaa95144c3Roshan Pius        return mWifiNative.configureRoaming(mWifiNative.getClientInterfaceName(), roamConfig);
1639c7730dd2cbf7c8d0d42052bee15a7a1323b8133Randy Pan    }
164403df479e25031276c738dbea334f09bb7e4bf37Ningyuan Wang
165403df479e25031276c738dbea334f09bb7e4bf37Ningyuan Wang    /**
166403df479e25031276c738dbea334f09bb7e4bf37Ningyuan Wang     * Remove the request |networkId| from supplicant if it's the current network,
167403df479e25031276c738dbea334f09bb7e4bf37Ningyuan Wang     * if the current configured network matches |networkId|.
168403df479e25031276c738dbea334f09bb7e4bf37Ningyuan Wang     *
169403df479e25031276c738dbea334f09bb7e4bf37Ningyuan Wang     * @param networkId network id of the network to be removed from supplicant.
170403df479e25031276c738dbea334f09bb7e4bf37Ningyuan Wang     */
171403df479e25031276c738dbea334f09bb7e4bf37Ningyuan Wang    public void removeNetworkIfCurrent(int networkId) {
17252ed1731664f7e0b76adb14eec7a76eaa95144c3Roshan Pius        mWifiNative.removeNetworkIfCurrent(mWifiNative.getClientInterfaceName(), networkId);
173403df479e25031276c738dbea334f09bb7e4bf37Ningyuan Wang    }
1749c7730dd2cbf7c8d0d42052bee15a7a1323b8133Randy Pan}
175