/*
 * Copyright (C) 2016 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.android.server.wifi;

import android.annotation.NonNull;
import android.annotation.Nullable;
import android.content.Context;
import android.net.NetworkKey;
import android.net.wifi.ScanResult;
import android.net.wifi.WifiConfiguration;
import android.net.wifi.WifiInfo;
import android.text.TextUtils;
import android.util.LocalLog;
import android.util.Log;
import android.util.Pair;

import com.android.internal.R;
import com.android.internal.annotations.VisibleForTesting;

import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;

/**
 * This class looks at all the connectivity scan results then
 * selects a network for the phone to connect or roam to.
 */
public class WifiNetworkSelector {
    private static final String TAG = "WifiNetworkSelector";

    private static final long INVALID_TIME_STAMP = Long.MIN_VALUE;
    // Minimum time gap between last successful network selection and a new selection
    // attempt.
    @VisibleForTesting
    public static final int MINIMUM_NETWORK_SELECTION_INTERVAL_MS = 10 * 1000;

    private final WifiConfigManager mWifiConfigManager;
    private final Clock mClock;
    private final LocalLog mLocalLog;
    private long mLastNetworkSelectionTimeStamp = INVALID_TIME_STAMP;
    // Buffer of filtered scan results (Scan results considered by network selection) & associated
    // WifiConfiguration (if any).
    private volatile List<Pair<ScanDetail, WifiConfiguration>> mConnectableNetworks =
            new ArrayList<>();
    private List<ScanDetail> mFilteredNetworks = new ArrayList<>();
    private final int mThresholdQualifiedRssi24;
    private final int mThresholdQualifiedRssi5;
    private final int mThresholdMinimumRssi24;
    private final int mThresholdMinimumRssi5;
    private final boolean mEnableAutoJoinWhenAssociated;

    /**
     * WiFi Network Selector supports various types of networks. Each type can
     * have its evaluator to choose the best WiFi network for the device to connect
     * to. When registering a WiFi network evaluator with the WiFi Network Selector,
     * the priority of the network must be specified, and it must be a value between
     * 0 and (EVALUATOR_MIN_PIRORITY - 1) with 0 being the highest priority. Wifi
     * Network Selector iterates through the registered scorers from the highest priority
     * to the lowest till a network is selected.
     */
    public static final int EVALUATOR_MIN_PRIORITY = 6;

    /**
     * Maximum number of evaluators can be registered with Wifi Network Selector.
     */
    public static final int MAX_NUM_EVALUATORS = EVALUATOR_MIN_PRIORITY;

    /**
     * Interface for WiFi Network Evaluator
     *
     * A network scorer evaulates all the networks from the scan results and
     * recommends the best network in its category to connect or roam to.
     */
    public interface NetworkEvaluator {
        /**
         * Get the evaluator name.
         */
        String getName();

        /**
         * Update the evaluator.
         *
         * Certain evaluators have to be updated with the new scan results. For example
         * the ExternalScoreEvalutor needs to refresh its Score Cache.
         *
         * @param scanDetails    a list of scan details constructed from the scan results
         */
        void update(List<ScanDetail> scanDetails);

        /**
         * Evaluate all the networks from the scan results.
         *
         * @param scanDetails    a list of scan details constructed from the scan results
         * @param currentNetwork configuration of the current connected network
         *                       or null if disconnected
         * @param currentBssid   BSSID of the current connected network or null if
         *                       disconnected
         * @param connected      a flag to indicate if WifiStateMachine is in connected
         *                       state
         * @param untrustedNetworkAllowed a flag to indidate if untrusted networks like
         *                                ephemeral networks are allowed
         * @param connectableNetworks     a list of the ScanDetail and WifiConfiguration
         *                                pair which is used by the WifiLastResortWatchdog
         * @return configuration of the chosen network;
         *         null if no network in this category is available.
         */
        @Nullable
        WifiConfiguration evaluateNetworks(List<ScanDetail> scanDetails,
                        WifiConfiguration currentNetwork, String currentBssid,
                        boolean connected, boolean untrustedNetworkAllowed,
                        List<Pair<ScanDetail, WifiConfiguration>> connectableNetworks);
    }

    private final NetworkEvaluator[] mEvaluators = new NetworkEvaluator[MAX_NUM_EVALUATORS];

    // A helper to log debugging information in the local log buffer, which can
    // be retrieved in bugreport.
    private void localLog(String log) {
        mLocalLog.log(log);
    }

    private boolean isCurrentNetworkSufficient(WifiInfo wifiInfo, List<ScanDetail> scanDetails) {
        WifiConfiguration network =
                            mWifiConfigManager.getConfiguredNetwork(wifiInfo.getNetworkId());

        // Currently connected?
        if (network == null) {
            localLog("No current connected network.");
            return false;
        } else {
            localLog("Current connected network: " + network.SSID
                    + " , ID: " + network.networkId);
        }

        // Ephemeral network is not qualified.
        if (network.ephemeral) {
            localLog("Current network is an ephemeral one.");
            return false;
        }

        // Open network is not qualified.
        if (WifiConfigurationUtil.isConfigForOpenNetwork(network)) {
            localLog("Current network is a open one.");
            return false;
        }

        int currentRssi = wifiInfo.getRssi();
        if (wifiInfo.is24GHz()) {
            // 2.4GHz networks is not qualified whenever 5GHz is available
            if (is5GHzNetworkAvailable(scanDetails)) {
                localLog("Current network is 2.4GHz. 5GHz networks available.");
                return false;
            }
            // When 5GHz is not available, we go through normal 2.4GHz qualification
            if (currentRssi < mThresholdQualifiedRssi24) {
                localLog("Current network band=2.4GHz, RSSI["
                        + currentRssi + "]-acceptable but not qualified.");
                return false;
            }
        } else if (wifiInfo.is5GHz()) {
            // Must be 5GHz, so we always apply qualification checks
            if (currentRssi < mThresholdQualifiedRssi5) {
                localLog("Current network band=5GHz, RSSI["
                        + currentRssi + "]-acceptable but not qualified.");
                return false;
            }
        } else {
            Log.e(TAG, "We're on a wifi network that's neither 2.4 or 5GHz... aliens!");
            return false;
        }

        return true;
    }

    // Determine whether there are any 5GHz networks in the scan result
    private boolean is5GHzNetworkAvailable(List<ScanDetail> scanDetails) {
        for (ScanDetail detail : scanDetails) {
            ScanResult result = detail.getScanResult();
            if (result.is5GHz()) return true;
        }
        return false;
    }

    private boolean isNetworkSelectionNeeded(List<ScanDetail> scanDetails, WifiInfo wifiInfo,
                        boolean connected, boolean disconnected) {
        if (scanDetails.size() == 0) {
            localLog("Empty connectivity scan results. Skip network selection.");
            return false;
        }

        if (connected) {
            // Is roaming allowed?
            if (!mEnableAutoJoinWhenAssociated) {
                localLog("Switching networks in connected state is not allowed."
                        + " Skip network selection.");
                return false;
            }

            // Has it been at least the minimum interval since last network selection?
            if (mLastNetworkSelectionTimeStamp != INVALID_TIME_STAMP) {
                long gap = mClock.getElapsedSinceBootMillis()
                            - mLastNetworkSelectionTimeStamp;
                if (gap < MINIMUM_NETWORK_SELECTION_INTERVAL_MS) {
                    localLog("Too short since last network selection: " + gap + " ms."
                            + " Skip network selection.");
                    return false;
                }
            }

            if (isCurrentNetworkSufficient(wifiInfo, scanDetails)) {
                localLog("Current connected network already sufficient. Skip network selection.");
                return false;
            } else {
                localLog("Current connected network is not sufficient.");
                return true;
            }
        } else if (disconnected) {
            return true;
        } else {
            // No network selection if WifiStateMachine is in a state other than
            // CONNECTED or DISCONNECTED.
            localLog("WifiStateMachine is in neither CONNECTED nor DISCONNECTED state."
                    + " Skip network selection.");
            return false;
        }
    }

    /**
     * Format the given ScanResult as a scan ID for logging.
     */
    public static String toScanId(@Nullable ScanResult scanResult) {
        return scanResult == null ? "NULL"
                                  : String.format("%s:%s", scanResult.SSID, scanResult.BSSID);
    }

    /**
     * Format the given WifiConfiguration as a SSID:netId string
     */
    public static String toNetworkString(WifiConfiguration network) {
        if (network == null) {
            return null;
        }

        return (network.SSID + ":" + network.networkId);
    }

    private List<ScanDetail> filterScanResults(List<ScanDetail> scanDetails,
                HashSet<String> bssidBlacklist, boolean isConnected, String currentBssid) {
        ArrayList<NetworkKey> unscoredNetworks = new ArrayList<NetworkKey>();
        List<ScanDetail> validScanDetails = new ArrayList<ScanDetail>();
        StringBuffer noValidSsid = new StringBuffer();
        StringBuffer blacklistedBssid = new StringBuffer();
        StringBuffer lowRssi = new StringBuffer();
        boolean scanResultsHaveCurrentBssid = false;

        for (ScanDetail scanDetail : scanDetails) {
            ScanResult scanResult = scanDetail.getScanResult();

            if (TextUtils.isEmpty(scanResult.SSID)) {
                noValidSsid.append(scanResult.BSSID).append(" / ");
                continue;
            }

            // Check if the scan results contain the currently connected BSSID
            if (scanResult.BSSID.equals(currentBssid)) {
                scanResultsHaveCurrentBssid = true;
            }

            final String scanId = toScanId(scanResult);

            if (bssidBlacklist.contains(scanResult.BSSID)) {
                blacklistedBssid.append(scanId).append(" / ");
                continue;
            }

            // Skip network with too weak signals.
            if ((scanResult.is24GHz() && scanResult.level
                    < mThresholdMinimumRssi24)
                    || (scanResult.is5GHz() && scanResult.level
                    < mThresholdMinimumRssi5)) {
                lowRssi.append(scanId).append("(")
                    .append(scanResult.is24GHz() ? "2.4GHz" : "5GHz")
                    .append(")").append(scanResult.level).append(" / ");
                continue;
            }

            validScanDetails.add(scanDetail);
        }

        // WNS listens to all single scan results. Some scan requests may not include
        // the channel of the currently connected network, so the currently connected
        // network won't show up in the scan results. We don't act on these scan results
        // to avoid aggressive network switching which might trigger disconnection.
        if (isConnected && !scanResultsHaveCurrentBssid) {
            localLog("Current connected BSSID " + currentBssid + " is not in the scan results."
                    + " Skip network selection.");
            validScanDetails.clear();
            return validScanDetails;
        }

        if (noValidSsid.length() != 0) {
            localLog("Networks filtered out due to invalid SSID: " + noValidSsid);
        }

        if (blacklistedBssid.length() != 0) {
            localLog("Networks filtered out due to blacklist: " + blacklistedBssid);
        }

        if (lowRssi.length() != 0) {
            localLog("Networks filtered out due to low signal strength: " + lowRssi);
        }

        return validScanDetails;
    }

    /**
     * This returns a list of ScanDetails that were filtered in the process of network selection.
     * The list is further filtered for only open unsaved networks.
     *
     * @return the list of ScanDetails for open unsaved networks that do not have invalid SSIDS,
     * blacklisted BSSIDS, or low signal strength. This will return an empty list when there are
     * no open unsaved networks, or when network selection has not been run.
     */
    public List<ScanDetail> getFilteredScanDetailsForOpenUnsavedNetworks() {
        List<ScanDetail> openUnsavedNetworks = new ArrayList<>();
        for (ScanDetail scanDetail : mFilteredNetworks) {
            ScanResult scanResult = scanDetail.getScanResult();

            // A capability of [ESS] represents an open access point
            // that is available for an STA to connect
            if (scanResult.capabilities == null || !scanResult.capabilities.equals("[ESS]")) {
                continue;
            }

            // Skip saved networks
            if (mWifiConfigManager.getConfiguredNetworkForScanDetailAndCache(scanDetail) != null) {
                continue;
            }

            openUnsavedNetworks.add(scanDetail);
        }
        return openUnsavedNetworks;
    }

    /**
     * @return the list of ScanDetails scored as potential candidates by the last run of
     * selectNetwork, this will be empty if Network selector determined no selection was
     * needed on last run. This includes scan details of sufficient signal strength, and
     * had an associated WifiConfiguration.
     */
    public List<Pair<ScanDetail, WifiConfiguration>> getConnectableScanDetails() {
        return mConnectableNetworks;
    }

    /**
     * This API is called when user explicitly selects a network. Currently, it is used in following
     * cases:
     * (1) User explicitly chooses to connect to a saved network.
     * (2) User saves a network after adding a new network.
     * (3) User saves a network after modifying a saved network.
     * Following actions will be triggered:
     * 1. If this network is disabled, we need re-enable it again.
     * 2. This network is favored over all the other networks visible in latest network
     *    selection procedure.
     *
     * @param netId  ID for the network chosen by the user
     * @return true -- There is change made to connection choice of any saved network.
     *         false -- There is no change made to connection choice of any saved network.
     */
    public boolean setUserConnectChoice(int netId) {
        localLog("userSelectNetwork: network ID=" + netId);
        WifiConfiguration selected = mWifiConfigManager.getConfiguredNetwork(netId);

        if (selected == null || selected.SSID == null) {
            localLog("userSelectNetwork: Invalid configuration with nid=" + netId);
            return false;
        }

        // Enable the network if it is disabled.
        if (!selected.getNetworkSelectionStatus().isNetworkEnabled()) {
            mWifiConfigManager.updateNetworkSelectionStatus(netId,
                    WifiConfiguration.NetworkSelectionStatus.NETWORK_SELECTION_ENABLE);
        }

        boolean change = false;
        String key = selected.configKey();
        // This is only used for setting the connect choice timestamp for debugging purposes.
        long currentTime = mClock.getWallClockMillis();
        List<WifiConfiguration> savedNetworks = mWifiConfigManager.getSavedNetworks();

        for (WifiConfiguration network : savedNetworks) {
            WifiConfiguration.NetworkSelectionStatus status = network.getNetworkSelectionStatus();
            if (network.networkId == selected.networkId) {
                if (status.getConnectChoice() != null) {
                    localLog("Remove user selection preference of " + status.getConnectChoice()
                            + " Set Time: " + status.getConnectChoiceTimestamp() + " from "
                            + network.SSID + " : " + network.networkId);
                    mWifiConfigManager.clearNetworkConnectChoice(network.networkId);
                    change = true;
                }
                continue;
            }

            if (status.getSeenInLastQualifiedNetworkSelection()
                    && (status.getConnectChoice() == null
                    || !status.getConnectChoice().equals(key))) {
                localLog("Add key: " + key + " Set Time: " + currentTime + " to "
                        + toNetworkString(network));
                mWifiConfigManager.setNetworkConnectChoice(network.networkId, key, currentTime);
                change = true;
            }
        }

        return change;
    }

    /**
     * Overrides the {@code candidate} chosen by the {@link #mEvaluators} with the user chosen
     * {@link WifiConfiguration} if one exists.
     *
     * @return the user chosen {@link WifiConfiguration} if one exists, {@code candidate} otherwise
     */
    private WifiConfiguration overrideCandidateWithUserConnectChoice(
            @NonNull WifiConfiguration candidate) {
        WifiConfiguration tempConfig = candidate;
        WifiConfiguration originalCandidate = candidate;
        ScanResult scanResultCandidate = candidate.getNetworkSelectionStatus().getCandidate();

        while (tempConfig.getNetworkSelectionStatus().getConnectChoice() != null) {
            String key = tempConfig.getNetworkSelectionStatus().getConnectChoice();
            tempConfig = mWifiConfigManager.getConfiguredNetwork(key);

            if (tempConfig != null) {
                WifiConfiguration.NetworkSelectionStatus tempStatus =
                        tempConfig.getNetworkSelectionStatus();
                if (tempStatus.getCandidate() != null && tempStatus.isNetworkEnabled()) {
                    scanResultCandidate = tempStatus.getCandidate();
                    candidate = tempConfig;
                }
            } else {
                localLog("Connect choice: " + key + " has no corresponding saved config.");
                break;
            }
        }

        if (candidate != originalCandidate) {
            localLog("After user selection adjustment, the final candidate is:"
                    + WifiNetworkSelector.toNetworkString(candidate) + " : "
                    + scanResultCandidate.BSSID);
        }
        return candidate;
    }

    /**
     * Select the best network from the ones in range.
     *
     * @param scanDetails    List of ScanDetail for all the APs in range
     * @param bssidBlacklist Blacklisted BSSIDs
     * @param wifiInfo       Currently connected network
     * @param connected      True if the device is connected
     * @param disconnected   True if the device is disconnected
     * @param untrustedNetworkAllowed True if untrusted networks are allowed for connection
     * @return Configuration of the selected network, or Null if nothing
     */
    @Nullable
    public WifiConfiguration selectNetwork(List<ScanDetail> scanDetails,
            HashSet<String> bssidBlacklist, WifiInfo wifiInfo,
            boolean connected, boolean disconnected, boolean untrustedNetworkAllowed) {
        mFilteredNetworks.clear();
        mConnectableNetworks.clear();
        if (scanDetails.size() == 0) {
            localLog("Empty connectivity scan result");
            return null;
        }

        WifiConfiguration currentNetwork =
                mWifiConfigManager.getConfiguredNetwork(wifiInfo.getNetworkId());

        // Always get the current BSSID from WifiInfo in case that firmware initiated
        // roaming happened.
        String currentBssid = wifiInfo.getBSSID();

        // Shall we start network selection at all?
        if (!isNetworkSelectionNeeded(scanDetails, wifiInfo, connected, disconnected)) {
            return null;
        }

        // Update the registered network evaluators.
        for (NetworkEvaluator registeredEvaluator : mEvaluators) {
            if (registeredEvaluator != null) {
                registeredEvaluator.update(scanDetails);
            }
        }

        // Filter out unwanted networks.
        mFilteredNetworks = filterScanResults(scanDetails, bssidBlacklist,
                connected, currentBssid);
        if (mFilteredNetworks.size() == 0) {
            return null;
        }

        // Go through the registered network evaluators from the highest priority
        // one to the lowest till a network is selected.
        WifiConfiguration selectedNetwork = null;
        for (NetworkEvaluator registeredEvaluator : mEvaluators) {
            if (registeredEvaluator != null) {
                localLog("About to run " + registeredEvaluator.getName() + " :");
                selectedNetwork = registeredEvaluator.evaluateNetworks(
                        new ArrayList<>(mFilteredNetworks), currentNetwork, currentBssid, connected,
                        untrustedNetworkAllowed, mConnectableNetworks);
                if (selectedNetwork != null) {
                    localLog(registeredEvaluator.getName() + " selects "
                            + WifiNetworkSelector.toNetworkString(selectedNetwork) + " : "
                            + selectedNetwork.getNetworkSelectionStatus().getCandidate().BSSID);
                    break;
                }
            }
        }

        if (selectedNetwork != null) {
            selectedNetwork = overrideCandidateWithUserConnectChoice(selectedNetwork);
            mLastNetworkSelectionTimeStamp = mClock.getElapsedSinceBootMillis();
        }

        return selectedNetwork;
    }

    /**
     * Register a network evaluator
     *
     * @param evaluator the network evaluator to be registered
     * @param priority a value between 0 and (SCORER_MIN_PRIORITY-1)
     *
     * @return true if the evaluator is successfully registered with QNS;
     *         false if failed to register the evaluator
     */
    public boolean registerNetworkEvaluator(NetworkEvaluator evaluator, int priority) {
        if (priority < 0 || priority >= EVALUATOR_MIN_PRIORITY) {
            localLog("Invalid network evaluator priority: " + priority);
            return false;
        }

        if (mEvaluators[priority] != null) {
            localLog("Priority " + priority + " is already registered by "
                    + mEvaluators[priority].getName());
            return false;
        }

        mEvaluators[priority] = evaluator;
        return true;
    }

    WifiNetworkSelector(Context context, WifiConfigManager configManager, Clock clock,
            LocalLog localLog) {
        mWifiConfigManager = configManager;
        mClock = clock;
        mLocalLog = localLog;

        mThresholdQualifiedRssi24 = context.getResources().getInteger(
                            R.integer.config_wifi_framework_wifi_score_low_rssi_threshold_24GHz);
        mThresholdQualifiedRssi5 = context.getResources().getInteger(
                            R.integer.config_wifi_framework_wifi_score_low_rssi_threshold_5GHz);
        mThresholdMinimumRssi24 = context.getResources().getInteger(
                            R.integer.config_wifi_framework_wifi_score_bad_rssi_threshold_24GHz);
        mThresholdMinimumRssi5 = context.getResources().getInteger(
                            R.integer.config_wifi_framework_wifi_score_bad_rssi_threshold_5GHz);
        mEnableAutoJoinWhenAssociated = context.getResources().getBoolean(
                            R.bool.config_wifi_framework_enable_associated_network_selection);
    }
}
