/*
 * Copyright (C) 2010 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 static android.net.wifi.WifiConfiguration.INVALID_NETWORK_ID;

import android.app.admin.DeviceAdminInfo;
import android.app.admin.DevicePolicyManagerInternal;
import android.content.ContentResolver;
import android.content.Context;
import android.content.Intent;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageManager;
import android.content.pm.UserInfo;
import android.net.IpConfiguration;
import android.net.IpConfiguration.IpAssignment;
import android.net.IpConfiguration.ProxySettings;
import android.net.NetworkInfo.DetailedState;
import android.net.ProxyInfo;
import android.net.StaticIpConfiguration;
import android.net.wifi.PasspointManagementObjectDefinition;
import android.net.wifi.ScanResult;
import android.net.wifi.WifiConfiguration;
import android.net.wifi.WifiConfiguration.KeyMgmt;
import android.net.wifi.WifiConfiguration.Status;
import android.net.wifi.WifiEnterpriseConfig;
import android.net.wifi.WifiInfo;
import android.net.wifi.WifiManager;
import android.net.wifi.WifiScanner;
import android.net.wifi.WpsInfo;
import android.net.wifi.WpsResult;
import android.os.Environment;
import android.os.RemoteException;
import android.os.SystemClock;
import android.os.UserHandle;
import android.os.UserManager;
import android.provider.Settings;
import android.security.KeyStore;
import android.text.TextUtils;
import android.util.LocalLog;
import android.util.Log;
import android.util.SparseArray;

import com.android.internal.R;
import com.android.server.LocalServices;
import com.android.server.net.DelayedDiskWrite;
import com.android.server.net.IpConfigStore;
import com.android.server.wifi.anqp.ANQPElement;
import com.android.server.wifi.anqp.ANQPFactory;
import com.android.server.wifi.anqp.Constants;
import com.android.server.wifi.hotspot2.ANQPData;
import com.android.server.wifi.hotspot2.AnqpCache;
import com.android.server.wifi.hotspot2.IconEvent;
import com.android.server.wifi.hotspot2.NetworkDetail;
import com.android.server.wifi.hotspot2.PasspointMatch;
import com.android.server.wifi.hotspot2.SupplicantBridge;
import com.android.server.wifi.hotspot2.Utils;
import com.android.server.wifi.hotspot2.omadm.PasspointManagementObjectManager;
import com.android.server.wifi.hotspot2.pps.Credential;
import com.android.server.wifi.hotspot2.pps.HomeSP;

import org.xml.sax.SAXException;

import java.io.BufferedReader;
import java.io.DataOutputStream;
import java.io.File;
import java.io.FileDescriptor;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
import java.io.PrintWriter;
import java.security.cert.X509Certificate;
import java.text.DateFormat;
import java.util.ArrayList;
import java.util.BitSet;
import java.util.Calendar;
import java.util.Collection;
import java.util.Collections;
import java.util.Comparator;
import java.util.Date;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.zip.CRC32;
import java.util.zip.Checksum;


/**
 * This class provides the API to manage configured
 * wifi networks. The API is not thread safe is being
 * used only from WifiStateMachine.
 *
 * It deals with the following
 * - Add/update/remove a WifiConfiguration
 *   The configuration contains two types of information.
 *     = IP and proxy configuration that is handled by WifiConfigManager and
 *       is saved to disk on any change.
 *
 *       The format of configuration file is as follows:
 *       <version>
 *       <netA_key1><netA_value1><netA_key2><netA_value2>...<EOS>
 *       <netB_key1><netB_value1><netB_key2><netB_value2>...<EOS>
 *       ..
 *
 *       (key, value) pairs for a given network are grouped together and can
 *       be in any order. A EOS at the end of a set of (key, value) pairs
 *       indicates that the next set of (key, value) pairs are for a new
 *       network. A network is identified by a unique ID_KEY. If there is no
 *       ID_KEY in the (key, value) pairs, the data is discarded.
 *
 *       An invalid version on read would result in discarding the contents of
 *       the file. On the next write, the latest version is written to file.
 *
 *       Any failures during read or write to the configuration file are ignored
 *       without reporting to the user since the likelihood of these errors are
 *       low and the impact on connectivity is low.
 *
 *     = SSID & security details that is pushed to the supplicant.
 *       supplicant saves these details to the disk on calling
 *       saveConfigCommand().
 *
 *       We have two kinds of APIs exposed:
 *        > public API calls that provide fine grained control
 *          - enableNetwork, disableNetwork, addOrUpdateNetwork(),
 *          removeNetwork(). For these calls, the config is not persisted
 *          to the disk. (TODO: deprecate these calls in WifiManager)
 *        > The new API calls - selectNetwork(), saveNetwork() & forgetNetwork().
 *          These calls persist the supplicant config to disk.
 *
 * - Maintain a list of configured networks for quick access
 *
 */
public class WifiConfigManager {
    private static boolean sVDBG = false;
    private static boolean sVVDBG = false;
    public static final String TAG = "WifiConfigManager";
    public static final int MAX_TX_PACKET_FOR_FULL_SCANS = 8;
    public static final int MAX_RX_PACKET_FOR_FULL_SCANS = 16;
    public static final int MAX_TX_PACKET_FOR_PARTIAL_SCANS = 40;
    public static final int MAX_RX_PACKET_FOR_PARTIAL_SCANS = 80;
    public static final boolean ROAM_ON_ANY = false;
    public static final int MAX_NUM_SCAN_CACHE_ENTRIES = 128;
    private static final boolean DBG = true;
    private static final String PPS_FILE = "/data/misc/wifi/PerProviderSubscription.conf";
    private static final String IP_CONFIG_FILE =
            Environment.getDataDirectory() + "/misc/wifi/ipconfig.txt";

    // The Wifi verbose log is provided as a way to persist the verbose logging settings
    // for testing purpose.
    // It is not intended for normal use.
    private static final String WIFI_VERBOSE_LOGS_KEY = "WIFI_VERBOSE_LOGS";

    // As we keep deleted PSK WifiConfiguration for a while, the PSK of
    // those deleted WifiConfiguration is set to this random unused PSK
    private static final String DELETED_CONFIG_PSK = "Mjkd86jEMGn79KhKll298Uu7-deleted";

    /**
     * The maximum number of times we will retry a connection to an access point
     * for which we have failed in acquiring an IP address from DHCP. A value of
     * N means that we will make N+1 connection attempts in all.
     * <p>
     * See {@link Settings.Secure#WIFI_MAX_DHCP_RETRY_COUNT}. This is the default
     * value if a Settings value is not present.
     */
    private static final int DEFAULT_MAX_DHCP_RETRIES = 9;

    /**
     * The threshold for each kind of error. If a network continuously encounter the same error more
     * than the threshold times, this network will be disabled. -1 means unavailable.
     */
    private static final int[] NETWORK_SELECTION_DISABLE_THRESHOLD = {
            -1, //  threshold for NETWORK_SELECTION_ENABLE
            1,  //  threshold for DISABLED_BAD_LINK
            5,  //  threshold for DISABLED_ASSOCIATION_REJECTION
            5,  //  threshold for DISABLED_AUTHENTICATION_FAILURE
            5,  //  threshold for DISABLED_DHCP_FAILURE
            5,  //  threshold for DISABLED_DNS_FAILURE
            6,  //  threshold for DISABLED_TLS_VERSION_MISMATCH
            1,  //  threshold for DISABLED_AUTHENTICATION_NO_CREDENTIALS
            1,  //  threshold for DISABLED_NO_INTERNET
            1   //  threshold for DISABLED_BY_WIFI_MANAGER
    };

    /**
     * Timeout for each kind of error. After the timeout minutes, unblock the network again.
     */
    private static final int[] NETWORK_SELECTION_DISABLE_TIMEOUT = {
            Integer.MAX_VALUE,  // threshold for NETWORK_SELECTION_ENABLE
            15,                 // threshold for DISABLED_BAD_LINK
            5,                  // threshold for DISABLED_ASSOCIATION_REJECTION
            5,                  // threshold for DISABLED_AUTHENTICATION_FAILURE
            5,                  // threshold for DISABLED_DHCP_FAILURE
            5,                  // threshold for DISABLED_DNS_FAILURE
            Integer.MAX_VALUE,  // threshold for DISABLED_TLS_VERSION
            Integer.MAX_VALUE,  // threshold for DISABLED_AUTHENTICATION_NO_CREDENTIALS
            Integer.MAX_VALUE,  // threshold for DISABLED_NO_INTERNET
            Integer.MAX_VALUE   // threshold for DISABLED_BY_WIFI_MANAGER
    };

    public final AtomicBoolean mEnableAutoJoinWhenAssociated = new AtomicBoolean();
    public final AtomicBoolean mEnableChipWakeUpWhenAssociated = new AtomicBoolean(true);
    public final AtomicBoolean mEnableRssiPollWhenAssociated = new AtomicBoolean(true);
    public final AtomicInteger mThresholdSaturatedRssi5 = new AtomicInteger();
    public final AtomicInteger mThresholdQualifiedRssi24 = new AtomicInteger();
    public final AtomicInteger mEnableVerboseLogging = new AtomicInteger(0);
    public final AtomicInteger mAlwaysEnableScansWhileAssociated = new AtomicInteger(0);
    public final AtomicInteger mMaxNumActiveChannelsForPartialScans = new AtomicInteger();

    public boolean mEnableLinkDebouncing;
    public boolean mEnableWifiCellularHandoverUserTriggeredAdjustment;
    public int mNetworkSwitchingBlackListPeriodMs;
    public int mBadLinkSpeed24;
    public int mBadLinkSpeed5;
    public int mGoodLinkSpeed24;
    public int mGoodLinkSpeed5;

    // These fields are non-final for testing.
    public AtomicInteger mThresholdQualifiedRssi5 = new AtomicInteger();
    public AtomicInteger mThresholdMinimumRssi5 = new AtomicInteger();
    public AtomicInteger mThresholdSaturatedRssi24 = new AtomicInteger();
    public AtomicInteger mThresholdMinimumRssi24 = new AtomicInteger();
    public AtomicInteger mCurrentNetworkBoost = new AtomicInteger();
    public AtomicInteger mBandAward5Ghz = new AtomicInteger();

    /**
     * If Connectivity Service has triggered an unwanted network disconnect
     */
    public long mLastUnwantedNetworkDisconnectTimestamp = 0;

    /**
     * Framework keeps a list of ephemeral SSIDs that where deleted by user,
     * so as, framework knows not to autojoin again those SSIDs based on scorer input.
     * The list is never cleared up.
     *
     * The SSIDs are encoded in a String as per definition of WifiConfiguration.SSID field.
     */
    public Set<String> mDeletedEphemeralSSIDs = new HashSet<String>();

    /* configured networks with network id as the key */
    private final ConfigurationMap mConfiguredNetworks;

    private final LocalLog mLocalLog;
    private final KeyStore mKeyStore;
    private final WifiNetworkHistory mWifiNetworkHistory;
    private final WifiConfigStore mWifiConfigStore;
    private final AnqpCache mAnqpCache;
    private final SupplicantBridge mSupplicantBridge;
    private final SupplicantBridgeCallbacks mSupplicantBridgeCallbacks;
    private final PasspointManagementObjectManager mMOManager;
    private final boolean mEnableOsuQueries;
    private final SIMAccessor mSIMAccessor;
    private final UserManager mUserManager;
    private final Object mActiveScanDetailLock = new Object();

    private Context mContext;
    private FrameworkFacade mFacade;
    private Clock mClock;
    private IpConfigStore mIpconfigStore;
    private DelayedDiskWrite mWriter;
    private boolean mOnlyLinkSameCredentialConfigurations;
    private boolean mShowNetworks = false;
    private int mCurrentUserId = UserHandle.USER_SYSTEM;

    /* Stores a map of NetworkId to ScanCache */
    private ConcurrentHashMap<Integer, ScanDetailCache> mScanDetailCaches;

    /* Tracks the highest priority of configured networks */
    private int mLastPriority = -1;

    /**
     * The mLastSelectedConfiguration is used to remember which network
     * was selected last by the user.
     * The connection to this network may not be successful, as well
     * the selection (i.e. network priority) might not be persisted.
     * WiFi state machine is the only object that sets this variable.
     */
    private String mLastSelectedConfiguration = null;
    private long mLastSelectedTimeStamp =
            WifiConfiguration.NetworkSelectionStatus.INVALID_NETWORK_SELECTION_DISABLE_TIMESTAMP;

    /*
     * Lost config list, whenever we read a config from networkHistory.txt that was not in
     * wpa_supplicant.conf
     */
    private HashSet<String> mLostConfigsDbg = new HashSet<String>();

    private ScanDetail mActiveScanDetail;   // ScanDetail associated with active network

    private class SupplicantBridgeCallbacks implements SupplicantBridge.SupplicantBridgeCallbacks {
        @Override
        public void notifyANQPResponse(ScanDetail scanDetail,
                                       Map<Constants.ANQPElementType, ANQPElement> anqpElements) {
            updateAnqpCache(scanDetail, anqpElements);
            if (anqpElements == null || anqpElements.isEmpty()) {
                return;
            }
            scanDetail.propagateANQPInfo(anqpElements);

            Map<HomeSP, PasspointMatch> matches = matchNetwork(scanDetail, false);
            Log.d(Utils.hs2LogTag(getClass()), scanDetail.getSSID() + " pass 2 matches: "
                    + toMatchString(matches));

            cacheScanResultForPasspointConfigs(scanDetail, matches, null);
        }
        @Override
        public void notifyIconFailed(long bssid) {
            Intent intent = new Intent(WifiManager.PASSPOINT_ICON_RECEIVED_ACTION);
            intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT);
            intent.putExtra(WifiManager.EXTRA_PASSPOINT_ICON_BSSID, bssid);
            mContext.sendBroadcastAsUser(intent, UserHandle.ALL);
        }

    }

    WifiConfigManager(Context context, WifiNative wifiNative, FrameworkFacade facade, Clock clock,
            UserManager userManager, KeyStore keyStore) {
        mContext = context;
        mFacade = facade;
        mClock = clock;
        mKeyStore = keyStore;
        mUserManager = userManager;

        if (mShowNetworks) {
            mLocalLog = wifiNative.getLocalLog();
        } else {
            mLocalLog = null;
        }

        mOnlyLinkSameCredentialConfigurations = mContext.getResources().getBoolean(
                R.bool.config_wifi_only_link_same_credential_configurations);
        mMaxNumActiveChannelsForPartialScans.set(mContext.getResources().getInteger(
                R.integer.config_wifi_framework_associated_partial_scan_max_num_active_channels));
        mEnableLinkDebouncing = mContext.getResources().getBoolean(
                R.bool.config_wifi_enable_disconnection_debounce);
        mBandAward5Ghz.set(mContext.getResources().getInteger(
                R.integer.config_wifi_framework_5GHz_preference_boost_factor));
        mThresholdMinimumRssi5.set(mContext.getResources().getInteger(
                R.integer.config_wifi_framework_wifi_score_bad_rssi_threshold_5GHz));
        mThresholdQualifiedRssi5.set(mContext.getResources().getInteger(
                R.integer.config_wifi_framework_wifi_score_low_rssi_threshold_5GHz));
        mThresholdSaturatedRssi5.set(mContext.getResources().getInteger(
                R.integer.config_wifi_framework_wifi_score_good_rssi_threshold_5GHz));
        mThresholdMinimumRssi24.set(mContext.getResources().getInteger(
                R.integer.config_wifi_framework_wifi_score_bad_rssi_threshold_24GHz));
        mThresholdQualifiedRssi24.set(mContext.getResources().getInteger(
                R.integer.config_wifi_framework_wifi_score_low_rssi_threshold_24GHz));
        mThresholdSaturatedRssi24.set(mContext.getResources().getInteger(
                R.integer.config_wifi_framework_wifi_score_good_rssi_threshold_24GHz));
        mEnableWifiCellularHandoverUserTriggeredAdjustment = mContext.getResources().getBoolean(
                R.bool.config_wifi_framework_cellular_handover_enable_user_triggered_adjustment);
        mBadLinkSpeed24 = mContext.getResources().getInteger(
                R.integer.config_wifi_framework_wifi_score_bad_link_speed_24);
        mBadLinkSpeed5 = mContext.getResources().getInteger(
                R.integer.config_wifi_framework_wifi_score_bad_link_speed_5);
        mGoodLinkSpeed24 = mContext.getResources().getInteger(
                R.integer.config_wifi_framework_wifi_score_good_link_speed_24);
        mGoodLinkSpeed5 = mContext.getResources().getInteger(
                R.integer.config_wifi_framework_wifi_score_good_link_speed_5);
        mEnableAutoJoinWhenAssociated.set(mContext.getResources().getBoolean(
                R.bool.config_wifi_framework_enable_associated_network_selection));
        mCurrentNetworkBoost.set(mContext.getResources().getInteger(
                R.integer.config_wifi_framework_current_network_boost));
        mNetworkSwitchingBlackListPeriodMs = mContext.getResources().getInteger(
                R.integer.config_wifi_network_switching_blacklist_time);

        boolean hs2on = mContext.getResources().getBoolean(R.bool.config_wifi_hotspot2_enabled);
        Log.d(Utils.hs2LogTag(getClass()), "Passpoint is " + (hs2on ? "enabled" : "disabled"));

        mConfiguredNetworks = new ConfigurationMap(userManager);
        mMOManager = new PasspointManagementObjectManager(new File(PPS_FILE), hs2on);
        mEnableOsuQueries = true;
        mAnqpCache = new AnqpCache(mClock);
        mSupplicantBridgeCallbacks = new SupplicantBridgeCallbacks();
        mSupplicantBridge = new SupplicantBridge(wifiNative, mSupplicantBridgeCallbacks);
        mScanDetailCaches = new ConcurrentHashMap<>(16, 0.75f, 2);
        mSIMAccessor = new SIMAccessor(mContext);
        mWriter = new DelayedDiskWrite();
        mIpconfigStore = new IpConfigStore(mWriter);
        mWifiNetworkHistory = new WifiNetworkHistory(context, mLocalLog, mWriter);
        mWifiConfigStore =
                new WifiConfigStore(context, wifiNative, mKeyStore, mLocalLog, mShowNetworks, true);
    }

    public void trimANQPCache(boolean all) {
        mAnqpCache.clear(all, DBG);
    }

    void enableVerboseLogging(int verbose) {
        mEnableVerboseLogging.set(verbose);
        if (verbose > 0) {
            sVDBG = true;
            mShowNetworks = true;
        } else {
            sVDBG = false;
        }
        if (verbose > 1) {
            sVVDBG = true;
        } else {
            sVVDBG = false;
        }
    }

    /**
     * Fetch the list of configured networks
     * and enable all stored networks in supplicant.
     */
    void loadAndEnableAllNetworks() {
        if (DBG) log("Loading config and enabling all networks ");
        loadConfiguredNetworks();
        enableAllNetworks();
    }

    int getConfiguredNetworksSize() {
        return mConfiguredNetworks.sizeForCurrentUser();
    }

    /**
     * Fetch the list of currently saved networks (i.e. all configured networks, excluding
     * ephemeral networks).
     * @param pskMap Map of preSharedKeys, keyed by the configKey of the configuration the
     * preSharedKeys belong to
     * @return List of networks
     */
    private List<WifiConfiguration> getSavedNetworks(Map<String, String> pskMap) {
        List<WifiConfiguration> networks = new ArrayList<>();
        for (WifiConfiguration config : mConfiguredNetworks.valuesForCurrentUser()) {
            WifiConfiguration newConfig = new WifiConfiguration(config);
            // When updating this condition, update WifiStateMachine's CONNECT_NETWORK handler to
            // correctly handle updating existing configs that are filtered out here.
            if (config.ephemeral) {
                // Do not enumerate and return this configuration to anyone (e.g. WiFi Picker);
                // treat it as unknown instead. This configuration can still be retrieved
                // directly by its key or networkId.
                continue;
            }

            if (pskMap != null && config.allowedKeyManagement != null
                    && config.allowedKeyManagement.get(WifiConfiguration.KeyMgmt.WPA_PSK)
                    && pskMap.containsKey(config.configKey(true))) {
                newConfig.preSharedKey = pskMap.get(config.configKey(true));
            }
            networks.add(newConfig);
        }
        return networks;
    }

    /**
     * This function returns all configuration, and is used for debug and creating bug reports.
     */
    private List<WifiConfiguration> getAllConfiguredNetworks() {
        List<WifiConfiguration> networks = new ArrayList<>();
        for (WifiConfiguration config : mConfiguredNetworks.valuesForCurrentUser()) {
            WifiConfiguration newConfig = new WifiConfiguration(config);
            networks.add(newConfig);
        }
        return networks;
    }

    /**
     * Fetch the list of currently saved networks (i.e. all configured networks, excluding
     * ephemeral networks).
     * @return List of networks
     */
    public List<WifiConfiguration> getSavedNetworks() {
        return getSavedNetworks(null);
    }

    /**
     * Fetch the list of currently saved networks (i.e. all configured networks, excluding
     * ephemeral networks), filled with real preSharedKeys.
     * @return List of networks
     */
    List<WifiConfiguration> getPrivilegedSavedNetworks() {
        Map<String, String> pskMap = getCredentialsByConfigKeyMap();
        List<WifiConfiguration> configurations = getSavedNetworks(pskMap);
        for (WifiConfiguration configuration : configurations) {
            try {
                configuration
                        .setPasspointManagementObjectTree(mMOManager.getMOTree(configuration.FQDN));
            } catch (IOException ioe) {
                Log.w(TAG, "Failed to parse MO from " + configuration.FQDN + ": " + ioe);
            }
        }
        return configurations;
    }

    /**
     * Fetch the list of networkId's which are hidden in current user's configuration.
     * @return List of networkIds
     */
    public Set<Integer> getHiddenConfiguredNetworkIds() {
        return mConfiguredNetworks.getHiddenNetworkIdsForCurrentUser();
    }

    /**
     * Find matching network for this scanResult
     */
    WifiConfiguration getMatchingConfig(ScanResult scanResult) {
        if (scanResult == null) {
            return null;
        }
        for (Map.Entry entry : mScanDetailCaches.entrySet()) {
            Integer netId = (Integer) entry.getKey();
            ScanDetailCache cache = (ScanDetailCache) entry.getValue();
            WifiConfiguration config = getWifiConfiguration(netId);
            if (config == null) {
                continue;
            }
            if (cache.get(scanResult.BSSID) != null) {
                return config;
            }
        }

        return null;
    }

    /**
     * Fetch the preSharedKeys for all networks.
     * @return a map from configKey to preSharedKey.
     */
    private Map<String, String> getCredentialsByConfigKeyMap() {
        return readNetworkVariablesFromSupplicantFile("psk");
    }

    /**
     * Fetch the list of currently saved networks (i.e. all configured networks, excluding
     * ephemeral networks) that were recently seen.
     *
     * @param scanResultAgeMs The maximum age (in ms) of scan results for which we calculate the
     * RSSI values
     * @param copy If true, the returned list will contain copies of the configurations for the
     * saved networks. Otherwise, the returned list will contain references to these
     * configurations.
     * @return List of networks
     */
    List<WifiConfiguration> getRecentSavedNetworks(int scanResultAgeMs, boolean copy) {
        List<WifiConfiguration> networks = new ArrayList<WifiConfiguration>();

        for (WifiConfiguration config : mConfiguredNetworks.valuesForCurrentUser()) {
            if (config.ephemeral) {
                // Do not enumerate and return this configuration to anyone (e.g. WiFi Picker);
                // treat it as unknown instead. This configuration can still be retrieved
                // directly by its key or networkId.
                continue;
            }

            // Calculate the RSSI for scan results that are more recent than scanResultAgeMs.
            ScanDetailCache cache = getScanDetailCache(config);
            if (cache == null) {
                continue;
            }
            config.setVisibility(cache.getVisibility(scanResultAgeMs));
            if (config.visibility == null) {
                continue;
            }
            if (config.visibility.rssi5 == WifiConfiguration.INVALID_RSSI
                    && config.visibility.rssi24 == WifiConfiguration.INVALID_RSSI) {
                continue;
            }
            if (copy) {
                networks.add(new WifiConfiguration(config));
            } else {
                networks.add(config);
            }
        }
        return networks;
    }

    /**
     *  Update the configuration and BSSID with latest RSSI value.
     */
    void updateConfiguration(WifiInfo info) {
        WifiConfiguration config = getWifiConfiguration(info.getNetworkId());
        if (config != null && getScanDetailCache(config) != null) {
            ScanDetail scanDetail = getScanDetailCache(config).getScanDetail(info.getBSSID());
            if (scanDetail != null) {
                ScanResult result = scanDetail.getScanResult();
                long previousSeen = result.seen;
                int previousRssi = result.level;

                // Update the scan result
                scanDetail.setSeen();
                result.level = info.getRssi();

                // Average the RSSI value
                result.averageRssi(previousRssi, previousSeen,
                        WifiQualifiedNetworkSelector.SCAN_RESULT_MAXIMUNM_AGE);
                if (sVDBG) {
                    logd("updateConfiguration freq=" + result.frequency
                            + " BSSID=" + result.BSSID
                            + " RSSI=" + result.level
                            + " " + config.configKey());
                }
            }
        }
    }

    /**
     * get the Wificonfiguration for this netId
     *
     * @return Wificonfiguration
     */
    public WifiConfiguration getWifiConfiguration(int netId) {
        return mConfiguredNetworks.getForCurrentUser(netId);
    }

    /**
     * Get the Wificonfiguration for this key
     * @return Wificonfiguration
     */
    public WifiConfiguration getWifiConfiguration(String key) {
        return mConfiguredNetworks.getByConfigKeyForCurrentUser(key);
    }

    /**
     * Enable all networks (if disabled time expire) and save config. This will be a no-op if the
     * list of configured networks indicates all networks as being enabled
     */
    void enableAllNetworks() {
        boolean networkEnabledStateChanged = false;

        for (WifiConfiguration config : mConfiguredNetworks.valuesForCurrentUser()) {
            if (config != null && !config.ephemeral
                    && !config.getNetworkSelectionStatus().isNetworkEnabled()) {
                if (tryEnableQualifiedNetwork(config)) {
                    networkEnabledStateChanged = true;
                }
            }
        }

        if (networkEnabledStateChanged) {
            saveConfig();
            sendConfiguredNetworksChangedBroadcast();
        }
    }

    private boolean setNetworkPriorityNative(WifiConfiguration config, int priority) {
        return mWifiConfigStore.setNetworkPriority(config, priority);
    }

    private boolean setSSIDNative(WifiConfiguration config, String ssid) {
        return mWifiConfigStore.setNetworkSSID(config, ssid);
    }

    public boolean updateLastConnectUid(WifiConfiguration config, int uid) {
        if (config != null) {
            if (config.lastConnectUid != uid) {
                config.lastConnectUid = uid;
                return true;
            }
        }
        return false;
    }

    /**
     * Selects the specified network for connection. This involves
     * updating the priority of all the networks and enabling the given
     * network while disabling others.
     *
     * Selecting a network will leave the other networks disabled and
     * a call to enableAllNetworks() needs to be issued upon a connection
     * or a failure event from supplicant
     *
     * @param config network to select for connection
     * @param updatePriorities makes config highest priority network
     * @return false if the network id is invalid
     */
    boolean selectNetwork(WifiConfiguration config, boolean updatePriorities, int uid) {
        if (sVDBG) localLogNetwork("selectNetwork", config.networkId);
        if (config.networkId == INVALID_NETWORK_ID) return false;
        if (!WifiConfigurationUtil.isVisibleToAnyProfile(config,
                mUserManager.getProfiles(mCurrentUserId))) {
            loge("selectNetwork " + Integer.toString(config.networkId) + ": Network config is not "
                    + "visible to current user.");
            return false;
        }

        // Reset the priority of each network at start or if it goes too high.
        if (mLastPriority == -1 || mLastPriority > 1000000) {
            if (updatePriorities) {
                for (WifiConfiguration config2 : mConfiguredNetworks.valuesForCurrentUser()) {
                    if (config2.networkId != INVALID_NETWORK_ID) {
                        setNetworkPriorityNative(config2, 0);
                    }
                }
            }
            mLastPriority = 0;
        }

        // Set to the highest priority and save the configuration.
        if (updatePriorities) {
            setNetworkPriorityNative(config, ++mLastPriority);
        }

        if (config.isPasspoint()) {
            // Set the SSID for the underlying WPA supplicant network entry corresponding to this
            // Passpoint profile to the SSID of the BSS selected by QNS. |config.SSID| is set by
            // selectQualifiedNetwork.selectQualifiedNetwork(), when the qualified network selected
            // is a Passpoint network.
            logd("Setting SSID for WPA supplicant network " + config.networkId + " to "
                    + config.SSID);
            setSSIDNative(config, config.SSID);
        }

        mWifiConfigStore.enableHS20(config.isPasspoint());

        if (updatePriorities) {
            saveConfig();
        }

        updateLastConnectUid(config, uid);

        writeKnownNetworkHistory();

        /* Enable the given network while disabling all other networks */
        selectNetworkWithoutBroadcast(config.networkId);

       /* Avoid saving the config & sending a broadcast to prevent settings
        * from displaying a disabled list of networks */
        return true;
    }

    /**
     * Add/update the specified configuration and save config
     *
     * @param config WifiConfiguration to be saved
     * @return network update result
     */
    NetworkUpdateResult saveNetwork(WifiConfiguration config, int uid) {
        WifiConfiguration conf;

        // A new network cannot have null SSID
        if (config == null || (config.networkId == INVALID_NETWORK_ID && config.SSID == null)) {
            return new NetworkUpdateResult(INVALID_NETWORK_ID);
        }

        if (!WifiConfigurationUtil.isVisibleToAnyProfile(config,
                mUserManager.getProfiles(mCurrentUserId))) {
            return new NetworkUpdateResult(INVALID_NETWORK_ID);
        }

        if (sVDBG) localLogNetwork("WifiConfigManager: saveNetwork netId", config.networkId);
        if (sVDBG) {
            logd("WifiConfigManager saveNetwork,"
                    + " size=" + Integer.toString(mConfiguredNetworks.sizeForAllUsers())
                    + " (for all users)"
                    + " SSID=" + config.SSID
                    + " Uid=" + Integer.toString(config.creatorUid)
                    + "/" + Integer.toString(config.lastUpdateUid));
        }

        if (mDeletedEphemeralSSIDs.remove(config.SSID)) {
            if (sVDBG) {
                logd("WifiConfigManager: removed from ephemeral blacklist: " + config.SSID);
            }
            // NOTE: This will be flushed to disk as part of the addOrUpdateNetworkNative call
            // below, since we're creating/modifying a config.
        }

        boolean newNetwork = (config.networkId == INVALID_NETWORK_ID);
        NetworkUpdateResult result = addOrUpdateNetworkNative(config, uid);
        int netId = result.getNetworkId();

        if (sVDBG) localLogNetwork("WifiConfigManager: saveNetwork got it back netId=", netId);

        conf = mConfiguredNetworks.getForCurrentUser(netId);
        if (conf != null) {
            if (!conf.getNetworkSelectionStatus().isNetworkEnabled()) {
                if (sVDBG) localLog("WifiConfigManager: re-enabling: " + conf.SSID);

                // reenable autojoin, since new information has been provided
                updateNetworkSelectionStatus(netId,
                        WifiConfiguration.NetworkSelectionStatus.NETWORK_SELECTION_ENABLE);
            }
            if (sVDBG) {
                logd("WifiConfigManager: saveNetwork got config back netId="
                        + Integer.toString(netId)
                        + " uid=" + Integer.toString(config.creatorUid));
            }
        }

        saveConfig();
        sendConfiguredNetworksChangedBroadcast(
                conf,
                result.isNewNetwork()
                        ? WifiManager.CHANGE_REASON_ADDED
                        : WifiManager.CHANGE_REASON_CONFIG_CHANGE);
        return result;
    }

    void noteRoamingFailure(WifiConfiguration config, int reason) {
        if (config == null) return;
        config.lastRoamingFailure = mClock.currentTimeMillis();
        config.roamingFailureBlackListTimeMilli =
                2 * (config.roamingFailureBlackListTimeMilli + 1000);
        if (config.roamingFailureBlackListTimeMilli > mNetworkSwitchingBlackListPeriodMs) {
            config.roamingFailureBlackListTimeMilli = mNetworkSwitchingBlackListPeriodMs;
        }
        config.lastRoamingFailureReason = reason;
    }

    void saveWifiConfigBSSID(WifiConfiguration config, String bssid) {
        mWifiConfigStore.setNetworkBSSID(config, bssid);
    }


    void updateStatus(int netId, DetailedState state) {
        if (netId != INVALID_NETWORK_ID) {
            WifiConfiguration config = mConfiguredNetworks.getForAllUsers(netId);
            if (config == null) return;
            switch (state) {
                case CONNECTED:
                    config.status = Status.CURRENT;
                    //we successfully connected, hence remove the blacklist
                    updateNetworkSelectionStatus(netId,
                            WifiConfiguration.NetworkSelectionStatus.NETWORK_SELECTION_ENABLE);
                    break;
                case DISCONNECTED:
                    //If network is already disabled, keep the status
                    if (config.status == Status.CURRENT) {
                        config.status = Status.ENABLED;
                    }
                    break;
                default:
                    //do nothing, retain the existing state
                    break;
            }
        }
    }


    /**
     * Disable an ephemeral SSID for the purpose of auto-joining thru scored.
     * This SSID will never be scored anymore.
     * The only way to "un-disable it" is if the user create a network for that SSID and then
     * forget it.
     *
     * @param ssid caller must ensure that the SSID passed thru this API match
     *            the WifiConfiguration.SSID rules, and thus be surrounded by quotes.
     * @return the {@link WifiConfiguration} corresponding to this SSID, if any, so that we can
     *         disconnect if this is the current network.
     */
    WifiConfiguration disableEphemeralNetwork(String ssid) {
        if (ssid == null) {
            return null;
        }

        WifiConfiguration foundConfig = mConfiguredNetworks.getEphemeralForCurrentUser(ssid);

        mDeletedEphemeralSSIDs.add(ssid);
        logd("Forget ephemeral SSID " + ssid + " num=" + mDeletedEphemeralSSIDs.size());

        if (foundConfig != null) {
            logd("Found ephemeral config in disableEphemeralNetwork: " + foundConfig.networkId);
        }

        writeKnownNetworkHistory();
        return foundConfig;
    }

    /**
     * Forget the specified network and save config
     *
     * @param netId network to forget
     * @return {@code true} if it succeeds, {@code false} otherwise
     */
    boolean forgetNetwork(int netId) {
        if (mShowNetworks) localLogNetwork("forgetNetwork", netId);
        if (!removeNetwork(netId)) {
            loge("Failed to forget network " + netId);
            return false;
        }
        saveConfig();
        writeKnownNetworkHistory();
        return true;
    }

    /**
     * Add/update a network. Note that there is no saveConfig operation.
     * This function is retained for compatibility with the public
     * API. The more powerful saveNetwork() is used by the
     * state machine
     *
     * @param config wifi configuration to add/update
     * @return network Id
     */
    int addOrUpdateNetwork(WifiConfiguration config, int uid) {
        if (config == null || !WifiConfigurationUtil.isVisibleToAnyProfile(config,
                mUserManager.getProfiles(mCurrentUserId))) {
            return WifiConfiguration.INVALID_NETWORK_ID;
        }

        if (mShowNetworks) localLogNetwork("addOrUpdateNetwork id=", config.networkId);
        if (config.isPasspoint()) {
            /* create a temporary SSID with providerFriendlyName */
            Long csum = getChecksum(config.FQDN);
            config.SSID = csum.toString();
            config.enterpriseConfig.setDomainSuffixMatch(config.FQDN);
        }

        NetworkUpdateResult result = addOrUpdateNetworkNative(config, uid);
        if (result.getNetworkId() != WifiConfiguration.INVALID_NETWORK_ID) {
            WifiConfiguration conf = mConfiguredNetworks.getForCurrentUser(result.getNetworkId());
            if (conf != null) {
                sendConfiguredNetworksChangedBroadcast(
                        conf,
                        result.isNewNetwork
                                ? WifiManager.CHANGE_REASON_ADDED
                                : WifiManager.CHANGE_REASON_CONFIG_CHANGE);
            }
        }

        return result.getNetworkId();
    }

    public int addPasspointManagementObject(String managementObject) {
        try {
            mMOManager.addSP(managementObject);
            return 0;
        } catch (IOException | SAXException e) {
            return -1;
        }
    }

    public int modifyPasspointMo(String fqdn, List<PasspointManagementObjectDefinition> mos) {
        try {
            return mMOManager.modifySP(fqdn, mos);
        } catch (IOException | SAXException e) {
            return -1;
        }
    }

    public boolean queryPasspointIcon(long bssid, String fileName) {
        return mSupplicantBridge.doIconQuery(bssid, fileName);
    }

    public int matchProviderWithCurrentNetwork(String fqdn) {
        ScanDetail scanDetail = null;
        synchronized (mActiveScanDetailLock) {
            scanDetail = mActiveScanDetail;
        }
        if (scanDetail == null) {
            return PasspointMatch.None.ordinal();
        }
        HomeSP homeSP = mMOManager.getHomeSP(fqdn);
        if (homeSP == null) {
            return PasspointMatch.None.ordinal();
        }

        ANQPData anqpData = mAnqpCache.getEntry(scanDetail.getNetworkDetail());

        Map<Constants.ANQPElementType, ANQPElement> anqpElements =
                anqpData != null ? anqpData.getANQPElements() : null;

        return homeSP.match(scanDetail.getNetworkDetail(), anqpElements, mSIMAccessor).ordinal();
    }

    /**
     * General PnoNetwork list sorting algorithm:
     * 1, Place the fully enabled networks first. Among the fully enabled networks,
     * sort them in the oder determined by the return of |compareConfigurations| method
     * implementation.
     * 2. Next place all the temporarily disabled networks. Among the temporarily disabled
     * networks, sort them in the order determined by the return of |compareConfigurations| method
     * implementation.
     * 3. Place the permanently disabled networks last. The order among permanently disabled
     * networks doesn't matter.
     */
    private static class PnoListComparator implements Comparator<WifiConfiguration> {

        public final int ENABLED_NETWORK_SCORE = 3;
        public final int TEMPORARY_DISABLED_NETWORK_SCORE = 2;
        public final int PERMANENTLY_DISABLED_NETWORK_SCORE = 1;

        @Override
        public int compare(WifiConfiguration a, WifiConfiguration b) {
            int configAScore = getPnoNetworkSortScore(a);
            int configBScore = getPnoNetworkSortScore(b);
            if (configAScore == configBScore) {
                return compareConfigurations(a, b);
            } else {
                return Integer.compare(configBScore, configAScore);
            }
        }

        // This needs to be implemented by the connected/disconnected PNO list comparator.
        public int compareConfigurations(WifiConfiguration a, WifiConfiguration b) {
            return 0;
        }

        /**
         * Returns an integer representing a score for each configuration. The scores are assigned
         * based on the status of the configuration. The scores are assigned according to the order:
         * Fully enabled network > Temporarily disabled network > Permanently disabled network.
         */
        private int getPnoNetworkSortScore(WifiConfiguration config) {
            if (config.getNetworkSelectionStatus().isNetworkEnabled()) {
                return ENABLED_NETWORK_SCORE;
            } else if (config.getNetworkSelectionStatus().isNetworkTemporaryDisabled()) {
                return TEMPORARY_DISABLED_NETWORK_SCORE;
            } else {
                return PERMANENTLY_DISABLED_NETWORK_SCORE;
            }
        }
    }

    /**
     * Disconnected PnoNetwork list sorting algorithm:
     * Place the configurations in descending order of their |numAssociation| values. If networks
     * have the same |numAssociation|, then sort them in descending order of their |priority|
     * values.
     */
    private static final PnoListComparator sDisconnectedPnoListComparator =
            new PnoListComparator() {
                @Override
                public int compareConfigurations(WifiConfiguration a, WifiConfiguration b) {
                    if (a.numAssociation != b.numAssociation) {
                        return Long.compare(b.numAssociation, a.numAssociation);
                    } else {
                        return Integer.compare(b.priority, a.priority);
                    }
                }
            };

    /**
     * Retrieves an updated list of priorities for all the saved networks before
     * enabling disconnected PNO (wpa_supplicant based PNO).
     *
     * wpa_supplicant uses the priority of networks to build the list of SSID's to monitor
     * during PNO. If there are a lot of saved networks, this list will be truncated and we
     * might end up not connecting to the networks we use most frequently. So, We want the networks
     * to be re-sorted based on the relative |numAssociation| values.
     *
     * @return list of networks with updated priorities.
     */
    public ArrayList<WifiScanner.PnoSettings.PnoNetwork> retrieveDisconnectedPnoNetworkList() {
        return retrievePnoNetworkList(sDisconnectedPnoListComparator);
    }

    /**
     * Connected PnoNetwork list sorting algorithm:
     * Place the configurations with |lastSeenInQualifiedNetworkSelection| set first. If networks
     * have the same value, then sort them in descending order of their |numAssociation|
     * values.
     */
    private static final PnoListComparator sConnectedPnoListComparator =
            new PnoListComparator() {
                @Override
                public int compareConfigurations(WifiConfiguration a, WifiConfiguration b) {
                    boolean isConfigALastSeen =
                            a.getNetworkSelectionStatus().getSeenInLastQualifiedNetworkSelection();
                    boolean isConfigBLastSeen =
                            b.getNetworkSelectionStatus().getSeenInLastQualifiedNetworkSelection();
                    if (isConfigALastSeen != isConfigBLastSeen) {
                        return Boolean.compare(isConfigBLastSeen, isConfigALastSeen);
                    } else {
                        return Long.compare(b.numAssociation, a.numAssociation);
                    }
                }
            };

    /**
     * Retrieves an updated list of priorities for all the saved networks before
     * enabling connected PNO (HAL based ePno).
     *
     * @return list of networks with updated priorities.
     */
    public ArrayList<WifiScanner.PnoSettings.PnoNetwork> retrieveConnectedPnoNetworkList() {
        return retrievePnoNetworkList(sConnectedPnoListComparator);
    }

    /**
     * Create a PnoNetwork object from the provided WifiConfiguration.
     * @param config Configuration corresponding to the network.
     * @param newPriority New priority to be assigned to the network.
     */
    private static WifiScanner.PnoSettings.PnoNetwork createPnoNetworkFromWifiConfiguration(
            WifiConfiguration config, int newPriority) {
        WifiScanner.PnoSettings.PnoNetwork pnoNetwork =
                new WifiScanner.PnoSettings.PnoNetwork(config.SSID);
        pnoNetwork.networkId = config.networkId;
        pnoNetwork.priority = newPriority;
        if (config.hiddenSSID) {
            pnoNetwork.flags |= WifiScanner.PnoSettings.PnoNetwork.FLAG_DIRECTED_SCAN;
        }
        pnoNetwork.flags |= WifiScanner.PnoSettings.PnoNetwork.FLAG_A_BAND;
        pnoNetwork.flags |= WifiScanner.PnoSettings.PnoNetwork.FLAG_G_BAND;
        if (config.allowedKeyManagement.get(WifiConfiguration.KeyMgmt.WPA_PSK)) {
            pnoNetwork.authBitField |= WifiScanner.PnoSettings.PnoNetwork.AUTH_CODE_PSK;
        } else if (config.allowedKeyManagement.get(WifiConfiguration.KeyMgmt.WPA_EAP)
                || config.allowedKeyManagement.get(WifiConfiguration.KeyMgmt.IEEE8021X)) {
            pnoNetwork.authBitField |= WifiScanner.PnoSettings.PnoNetwork.AUTH_CODE_EAPOL;
        } else {
            pnoNetwork.authBitField |= WifiScanner.PnoSettings.PnoNetwork.AUTH_CODE_OPEN;
        }
        return pnoNetwork;
    }

    /**
     * Retrieves an updated list of priorities for all the saved networks before
     * enabling/disabling PNO.
     *
     * @param pnoListComparator The comparator to use for sorting networks
     * @return list of networks with updated priorities.
     */
    private ArrayList<WifiScanner.PnoSettings.PnoNetwork> retrievePnoNetworkList(
            PnoListComparator pnoListComparator) {
        ArrayList<WifiScanner.PnoSettings.PnoNetwork> pnoList = new ArrayList<>();
        ArrayList<WifiConfiguration> wifiConfigurations =
                new ArrayList<>(mConfiguredNetworks.valuesForCurrentUser());
        Collections.sort(wifiConfigurations, pnoListComparator);
        // Let's use the network list size as the highest priority and then go down from there.
        // So, the most frequently connected network has the highest priority now.
        int priority = wifiConfigurations.size();
        for (WifiConfiguration config : wifiConfigurations) {
            pnoList.add(createPnoNetworkFromWifiConfiguration(config, priority));
            priority--;
        }
        return pnoList;
    }

    /**
     * Remove a network. Note that there is no saveConfig operation.
     * This function is retained for compatibility with the public
     * API. The more powerful forgetNetwork() is used by the
     * state machine for network removal
     *
     * @param netId network to be removed
     * @return {@code true} if it succeeds, {@code false} otherwise
     */
    boolean removeNetwork(int netId) {
        if (mShowNetworks) localLogNetwork("removeNetwork", netId);
        WifiConfiguration config = mConfiguredNetworks.getForCurrentUser(netId);
        if (!removeConfigAndSendBroadcastIfNeeded(config)) {
            return false;
        }
        if (config.isPasspoint()) {
            writePasspointConfigs(config.FQDN, null);
        }
        return true;
    }

    private static Long getChecksum(String source) {
        Checksum csum = new CRC32();
        csum.update(source.getBytes(), 0, source.getBytes().length);
        return csum.getValue();
    }

    private boolean removeConfigWithoutBroadcast(WifiConfiguration config) {
        if (config == null) {
            return false;
        }
        if (!mWifiConfigStore.removeNetwork(config)) {
            loge("Failed to remove network " + config.networkId);
            return false;
        }
        if (config.configKey().equals(mLastSelectedConfiguration)) {
            mLastSelectedConfiguration = null;
        }
        mConfiguredNetworks.remove(config.networkId);
        mScanDetailCaches.remove(config.networkId);
        return true;
    }

    private boolean removeConfigAndSendBroadcastIfNeeded(WifiConfiguration config) {
        if (!removeConfigWithoutBroadcast(config)) {
            return false;
        }
        String key = config.configKey();
        if (sVDBG) {
            logd("removeNetwork " + " key=" + key + " config.id=" + config.networkId);
        }
        writeIpAndProxyConfigurations();
        sendConfiguredNetworksChangedBroadcast(config, WifiManager.CHANGE_REASON_REMOVED);
        if (!config.ephemeral) {
            removeUserSelectionPreference(key);
        }
        writeKnownNetworkHistory();
        return true;
    }

    private void removeUserSelectionPreference(String configKey) {
        if (DBG) {
            Log.d(TAG, "removeUserSelectionPreference: key is " + configKey);
        }
        if (configKey == null) {
            return;
        }
        for (WifiConfiguration config : mConfiguredNetworks.valuesForCurrentUser()) {
            WifiConfiguration.NetworkSelectionStatus status = config.getNetworkSelectionStatus();
            String connectChoice = status.getConnectChoice();
            if (connectChoice != null && connectChoice.equals(configKey)) {
                Log.d(TAG, "remove connect choice:" + connectChoice + " from " + config.SSID
                        + " : " + config.networkId);
                status.setConnectChoice(null);
                status.setConnectChoiceTimestamp(WifiConfiguration.NetworkSelectionStatus
                            .INVALID_NETWORK_SELECTION_DISABLE_TIMESTAMP);
            }
        }
    }

    /*
     * Remove all networks associated with an application
     *
     * @param packageName name of the package of networks to remove
     * @return {@code true} if all networks removed successfully, {@code false} otherwise
     */
    boolean removeNetworksForApp(ApplicationInfo app) {
        if (app == null || app.packageName == null) {
            return false;
        }

        boolean success = true;

        WifiConfiguration [] copiedConfigs =
                mConfiguredNetworks.valuesForCurrentUser().toArray(new WifiConfiguration[0]);
        for (WifiConfiguration config : copiedConfigs) {
            if (app.uid != config.creatorUid || !app.packageName.equals(config.creatorName)) {
                continue;
            }
            if (mShowNetworks) {
                localLog("Removing network " + config.SSID
                         + ", application \"" + app.packageName + "\" uninstalled"
                         + " from user " + UserHandle.getUserId(app.uid));
            }
            success &= removeNetwork(config.networkId);
        }

        saveConfig();

        return success;
    }

    boolean removeNetworksForUser(int userId) {
        boolean success = true;

        WifiConfiguration[] copiedConfigs =
                mConfiguredNetworks.valuesForAllUsers().toArray(new WifiConfiguration[0]);
        for (WifiConfiguration config : copiedConfigs) {
            if (userId != UserHandle.getUserId(config.creatorUid)) {
                continue;
            }
            success &= removeNetwork(config.networkId);
            if (mShowNetworks) {
                localLog("Removing network " + config.SSID
                        + ", user " + userId + " removed");
            }
        }

        return success;
    }

    /**
     * Enable a network. Note that there is no saveConfig operation.
     * This function is retained for compatibility with the public
     * API. The more powerful selectNetwork()/saveNetwork() is used by the
     * state machine for connecting to a network
     *
     * @param config network to be enabled
     * @return {@code true} if it succeeds, {@code false} otherwise
     */
    boolean enableNetwork(WifiConfiguration config, boolean disableOthers, int uid) {
        if (config == null) {
            return false;
        }

        updateNetworkSelectionStatus(
                config, WifiConfiguration.NetworkSelectionStatus.NETWORK_SELECTION_ENABLE);
        setLatestUserSelectedConfiguration(config);
        boolean ret = true;
        if (disableOthers) {
            ret = selectNetworkWithoutBroadcast(config.networkId);
            if (sVDBG) {
                localLogNetwork("enableNetwork(disableOthers=true, uid=" + uid + ") ",
                        config.networkId);
            }
            updateLastConnectUid(config, uid);
            writeKnownNetworkHistory();
            sendConfiguredNetworksChangedBroadcast();
        } else {
            if (sVDBG) localLogNetwork("enableNetwork(disableOthers=false) ", config.networkId);
            sendConfiguredNetworksChangedBroadcast(config, WifiManager.CHANGE_REASON_CONFIG_CHANGE);
        }
        return ret;
    }

    boolean selectNetworkWithoutBroadcast(int netId) {
        return mWifiConfigStore.selectNetwork(
                mConfiguredNetworks.getForCurrentUser(netId),
                mConfiguredNetworks.valuesForCurrentUser());
    }

    /**
     * Disable a network in wpa_supplicant.
     */
    boolean disableNetworkNative(WifiConfiguration config) {
        return mWifiConfigStore.disableNetwork(config);
    }

    /**
     * Disable all networks in wpa_supplicant.
     */
    void disableAllNetworksNative() {
        mWifiConfigStore.disableAllNetworks(mConfiguredNetworks.valuesForCurrentUser());
    }

    /**
     * Disable a network. Note that there is no saveConfig operation.
     * @param netId network to be disabled
     * @return {@code true} if it succeeds, {@code false} otherwise
     */
    boolean disableNetwork(int netId) {
        return mWifiConfigStore.disableNetwork(mConfiguredNetworks.getForCurrentUser(netId));
    }

    /**
     * Update a network according to the update reason and its current state
     * @param netId The network ID of the network need update
     * @param reason The reason to update the network
     * @return false if no change made to the input configure file, can due to error or need not
     *         true the input config file has been changed
     */
    boolean updateNetworkSelectionStatus(int netId, int reason) {
        WifiConfiguration config = getWifiConfiguration(netId);
        return updateNetworkSelectionStatus(config, reason);
    }

    /**
     * Update a network according to the update reason and its current state
     * @param config the network need update
     * @param reason The reason to update the network
     * @return false if no change made to the input configure file, can due to error or need not
     *         true the input config file has been changed
     */
    boolean updateNetworkSelectionStatus(WifiConfiguration config, int reason) {
        if (config == null) {
            return false;
        }

        WifiConfiguration.NetworkSelectionStatus networkStatus = config.getNetworkSelectionStatus();
        if (reason == WifiConfiguration.NetworkSelectionStatus.NETWORK_SELECTION_ENABLE) {
            updateNetworkStatus(config, WifiConfiguration.NetworkSelectionStatus
                    .NETWORK_SELECTION_ENABLE);
            localLog("Enable network:" + config.configKey());
            return true;
        }

        networkStatus.incrementDisableReasonCounter(reason);
        if (DBG) {
            localLog("Network:" + config.SSID + "disable counter of "
                    + WifiConfiguration.NetworkSelectionStatus.getNetworkDisableReasonString(reason)
                    + " is: " + networkStatus.getDisableReasonCounter(reason) + "and threshold is: "
                    + NETWORK_SELECTION_DISABLE_THRESHOLD[reason]);
        }

        if (networkStatus.getDisableReasonCounter(reason)
                >= NETWORK_SELECTION_DISABLE_THRESHOLD[reason]) {
            return updateNetworkStatus(config, reason);
        }
        return true;
    }

    /**
     * Check the config. If it is temporarily disabled, check the disable time is expired or not, If
     * expired, enabled it again for qualified network selection.
     * @param networkId the id of the network to be checked for possible unblock (due to timeout)
     * @return true if network status has been changed
     *         false network status is not changed
     */
    public boolean tryEnableQualifiedNetwork(int networkId) {
        WifiConfiguration config = getWifiConfiguration(networkId);
        if (config == null) {
            localLog("updateQualifiedNetworkstatus invalid network.");
            return false;
        }
        return tryEnableQualifiedNetwork(config);
    }

    /**
     * Check the config. If it is temporarily disabled, check the disable is expired or not, If
     * expired, enabled it again for qualified network selection.
     * @param config network to be checked for possible unblock (due to timeout)
     * @return true if network status has been changed
     *         false network status is not changed
     */
    private boolean tryEnableQualifiedNetwork(WifiConfiguration config) {
        WifiConfiguration.NetworkSelectionStatus networkStatus = config.getNetworkSelectionStatus();
        if (networkStatus.isNetworkTemporaryDisabled()) {
            //time difference in minutes
            long timeDifference =
                    (mClock.elapsedRealtime() - networkStatus.getDisableTime()) / 1000 / 60;
            if (timeDifference < 0 || timeDifference
                    >= NETWORK_SELECTION_DISABLE_TIMEOUT[
                    networkStatus.getNetworkSelectionDisableReason()]) {
                updateNetworkSelectionStatus(config.networkId,
                        networkStatus.NETWORK_SELECTION_ENABLE);
                return true;
            }
        }
        return false;
    }

    /**
     * Update a network's status. Note that there is no saveConfig operation.
     * @param config network to be updated
     * @param reason reason code for updated
     * @return false if no change made to the input configure file, can due to error or need not
     *         true the input config file has been changed
     */
    boolean updateNetworkStatus(WifiConfiguration config, int reason) {
        localLog("updateNetworkStatus:" + (config == null ? null : config.SSID));
        if (config == null) {
            return false;
        }

        WifiConfiguration.NetworkSelectionStatus networkStatus = config.getNetworkSelectionStatus();
        if (reason < 0 || reason >= WifiConfiguration.NetworkSelectionStatus
                .NETWORK_SELECTION_DISABLED_MAX) {
            localLog("Invalid Network disable reason:" + reason);
            return false;
        }

        if (reason == WifiConfiguration.NetworkSelectionStatus.NETWORK_SELECTION_ENABLE) {
            if (networkStatus.isNetworkEnabled()) {
                if (DBG) {
                    localLog("Need not change Qualified network Selection status since"
                            + " already enabled");
                }
                return false;
            }
            networkStatus.setNetworkSelectionStatus(WifiConfiguration.NetworkSelectionStatus
                    .NETWORK_SELECTION_ENABLED);
            networkStatus.setNetworkSelectionDisableReason(reason);
            networkStatus.setDisableTime(
                    WifiConfiguration.NetworkSelectionStatus
                    .INVALID_NETWORK_SELECTION_DISABLE_TIMESTAMP);
            networkStatus.clearDisableReasonCounter();
            String disableTime = DateFormat.getDateTimeInstance().format(new Date());
            if (DBG) {
                localLog("Re-enable network: " + config.SSID + " at " + disableTime);
            }
            sendConfiguredNetworksChangedBroadcast(config, WifiManager.CHANGE_REASON_CONFIG_CHANGE);
        } else {
            //disable the network
            if (networkStatus.isNetworkPermanentlyDisabled()) {
                //alreay permanent disable
                if (DBG) {
                    localLog("Do nothing. Alreay permanent disabled! "
                            + WifiConfiguration.NetworkSelectionStatus
                            .getNetworkDisableReasonString(reason));
                }
                return false;
            } else if (networkStatus.isNetworkTemporaryDisabled()
                    && reason < WifiConfiguration.NetworkSelectionStatus
                    .DISABLED_TLS_VERSION_MISMATCH) {
                //alreay temporarily disable
                if (DBG) {
                    localLog("Do nothing. Already temporarily disabled! "
                            + WifiConfiguration.NetworkSelectionStatus
                            .getNetworkDisableReasonString(reason));
                }
                return false;
            }

            if (networkStatus.isNetworkEnabled()) {
                disableNetworkNative(config);
                sendConfiguredNetworksChangedBroadcast(config,
                        WifiManager.CHANGE_REASON_CONFIG_CHANGE);
                localLog("Disable network " + config.SSID + " reason:"
                        + WifiConfiguration.NetworkSelectionStatus
                        .getNetworkDisableReasonString(reason));
            }
            if (reason < WifiConfiguration.NetworkSelectionStatus.DISABLED_TLS_VERSION_MISMATCH) {
                networkStatus.setNetworkSelectionStatus(WifiConfiguration.NetworkSelectionStatus
                        .NETWORK_SELECTION_TEMPORARY_DISABLED);
                networkStatus.setDisableTime(mClock.elapsedRealtime());
            } else {
                networkStatus.setNetworkSelectionStatus(WifiConfiguration.NetworkSelectionStatus
                        .NETWORK_SELECTION_PERMANENTLY_DISABLED);
            }
            networkStatus.setNetworkSelectionDisableReason(reason);
            if (DBG) {
                String disableTime = DateFormat.getDateTimeInstance().format(new Date());
                localLog("Network:" + config.SSID + "Configure new status:"
                        + networkStatus.getNetworkStatusString() + " with reason:"
                        + networkStatus.getNetworkDisableReasonString() + " at: " + disableTime);
            }
        }
        return true;
    }

    /**
     * Save the configured networks in supplicant to disk
     * @return {@code true} if it succeeds, {@code false} otherwise
     */
    boolean saveConfig() {
        return mWifiConfigStore.saveConfig();
    }

    /**
     * Start WPS pin method configuration with pin obtained
     * from the access point
     * @param config WPS configuration
     * @return Wps result containing status and pin
     */
    WpsResult startWpsWithPinFromAccessPoint(WpsInfo config) {
        return mWifiConfigStore.startWpsWithPinFromAccessPoint(
                config, mConfiguredNetworks.valuesForCurrentUser());
    }

    /**
     * Start WPS pin method configuration with obtained
     * from the device
     * @return WpsResult indicating status and pin
     */
    WpsResult startWpsWithPinFromDevice(WpsInfo config) {
        return mWifiConfigStore.startWpsWithPinFromDevice(
            config, mConfiguredNetworks.valuesForCurrentUser());
    }

    /**
     * Start WPS push button configuration
     * @param config WPS configuration
     * @return WpsResult indicating status and pin
     */
    WpsResult startWpsPbc(WpsInfo config) {
        return mWifiConfigStore.startWpsPbc(
            config, mConfiguredNetworks.valuesForCurrentUser());
    }

    /**
     * Fetch the static IP configuration for a given network id
     */
    StaticIpConfiguration getStaticIpConfiguration(int netId) {
        WifiConfiguration config = mConfiguredNetworks.getForCurrentUser(netId);
        if (config != null) {
            return config.getStaticIpConfiguration();
        }
        return null;
    }

    /**
     * Set the static IP configuration for a given network id
     */
    void setStaticIpConfiguration(int netId, StaticIpConfiguration staticIpConfiguration) {
        WifiConfiguration config = mConfiguredNetworks.getForCurrentUser(netId);
        if (config != null) {
            config.setStaticIpConfiguration(staticIpConfiguration);
        }
    }

    /**
     * set default GW MAC address
     */
    void setDefaultGwMacAddress(int netId, String macAddress) {
        WifiConfiguration config = mConfiguredNetworks.getForCurrentUser(netId);
        if (config != null) {
            //update defaultGwMacAddress
            config.defaultGwMacAddress = macAddress;
        }
    }


    /**
     * Fetch the proxy properties for a given network id
     * @param netId id
     * @return ProxyInfo for the network id
     */
    ProxyInfo getProxyProperties(int netId) {
        WifiConfiguration config = mConfiguredNetworks.getForCurrentUser(netId);
        if (config != null) {
            return config.getHttpProxy();
        }
        return null;
    }

    /**
     * Return if the specified network is using static IP
     * @param netId id
     * @return {@code true} if using static ip for netId
     */
    boolean isUsingStaticIp(int netId) {
        WifiConfiguration config = mConfiguredNetworks.getForCurrentUser(netId);
        if (config != null && config.getIpAssignment() == IpAssignment.STATIC) {
            return true;
        }
        return false;
    }

    boolean isEphemeral(int netId) {
        WifiConfiguration config = mConfiguredNetworks.getForCurrentUser(netId);
        return config != null && config.ephemeral;
    }

    boolean getMeteredHint(int netId) {
        WifiConfiguration config = mConfiguredNetworks.getForCurrentUser(netId);
        return config != null && config.meteredHint;
    }

    /**
     * Should be called when a single network configuration is made.
     * @param network The network configuration that changed.
     * @param reason The reason for the change, should be one of WifiManager.CHANGE_REASON_ADDED,
     * WifiManager.CHANGE_REASON_REMOVED, or WifiManager.CHANGE_REASON_CHANGE.
     */
    private void sendConfiguredNetworksChangedBroadcast(WifiConfiguration network,
            int reason) {
        Intent intent = new Intent(WifiManager.CONFIGURED_NETWORKS_CHANGED_ACTION);
        intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT);
        intent.putExtra(WifiManager.EXTRA_MULTIPLE_NETWORKS_CHANGED, false);
        intent.putExtra(WifiManager.EXTRA_WIFI_CONFIGURATION, network);
        intent.putExtra(WifiManager.EXTRA_CHANGE_REASON, reason);
        mContext.sendBroadcastAsUser(intent, UserHandle.ALL);
    }

    /**
     * Should be called when multiple network configuration changes are made.
     */
    private void sendConfiguredNetworksChangedBroadcast() {
        Intent intent = new Intent(WifiManager.CONFIGURED_NETWORKS_CHANGED_ACTION);
        intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT);
        intent.putExtra(WifiManager.EXTRA_MULTIPLE_NETWORKS_CHANGED, true);
        mContext.sendBroadcastAsUser(intent, UserHandle.ALL);
    }

    void loadConfiguredNetworks() {

        final Map<String, WifiConfiguration> configs = new HashMap<>();
        final SparseArray<Map<String, String>> networkExtras = new SparseArray<>();
        mLastPriority = mWifiConfigStore.loadNetworks(configs, networkExtras);

        readNetworkHistory(configs);
        readPasspointConfig(configs, networkExtras);

        // We are only now updating mConfiguredNetworks for two reasons:
        // 1) The information required to compute configKeys is spread across wpa_supplicant.conf
        //    and networkHistory.txt. Thus, we had to load both files first.
        // 2) mConfiguredNetworks caches a Passpoint network's FQDN the moment the network is added.
        //    Thus, we had to load the FQDNs first.
        mConfiguredNetworks.clear();
        for (Map.Entry<String, WifiConfiguration> entry : configs.entrySet()) {
            final String configKey = entry.getKey();
            final WifiConfiguration config = entry.getValue();
            if (!configKey.equals(config.configKey())) {
                if (mShowNetworks) {
                    log("Ignoring network " + config.networkId + " because the configKey loaded "
                            + "from wpa_supplicant.conf is not valid.");
                }
                mWifiConfigStore.removeNetwork(config);
                continue;
            }
            mConfiguredNetworks.put(config);
        }

        readIpAndProxyConfigurations();

        sendConfiguredNetworksChangedBroadcast();

        if (mShowNetworks) {
            localLog("loadConfiguredNetworks loaded " + mConfiguredNetworks.sizeForAllUsers()
                    + " networks (for all users)");
        }

        if (mConfiguredNetworks.sizeForAllUsers() == 0) {
            // no networks? Lets log if the file contents
            logKernelTime();
            logContents(WifiConfigStore.SUPPLICANT_CONFIG_FILE);
            logContents(WifiConfigStore.SUPPLICANT_CONFIG_FILE_BACKUP);
            logContents(WifiNetworkHistory.NETWORK_HISTORY_CONFIG_FILE);
        }
    }

    private void logContents(String file) {
        localLogAndLogcat("--- Begin " + file + " ---");
        BufferedReader reader = null;
        try {
            reader = new BufferedReader(new FileReader(file));
            for (String line = reader.readLine(); line != null; line = reader.readLine()) {
                localLogAndLogcat(line);
            }
        } catch (FileNotFoundException e) {
            localLog("Could not open " + file + ", " + e);
            Log.w(TAG, "Could not open " + file + ", " + e);
        } catch (IOException e) {
            localLog("Could not read " + file + ", " + e);
            Log.w(TAG, "Could not read " + file + ", " + e);
        } finally {
            try {
                if (reader != null) {
                    reader.close();
                }
            } catch (IOException e) {
                // Just ignore the fact that we couldn't close
            }
        }
        localLogAndLogcat("--- End " + file + " Contents ---");
    }

    private Map<String, String> readNetworkVariablesFromSupplicantFile(String key) {
        return mWifiConfigStore.readNetworkVariablesFromSupplicantFile(key);
    }

    private String readNetworkVariableFromSupplicantFile(String configKey, String key) {
        long start = SystemClock.elapsedRealtimeNanos();
        Map<String, String> data = mWifiConfigStore.readNetworkVariablesFromSupplicantFile(key);
        long end = SystemClock.elapsedRealtimeNanos();

        if (sVDBG) {
            localLog("readNetworkVariableFromSupplicantFile configKey=[" + configKey + "] key="
                    + key + " duration=" + (long) (end - start));
        }
        return data.get(configKey);
    }

    boolean needsUnlockedKeyStore() {

        // Any network using certificates to authenticate access requires
        // unlocked key store; unless the certificates can be stored with
        // hardware encryption

        for (WifiConfiguration config : mConfiguredNetworks.valuesForCurrentUser()) {

            if (config.allowedKeyManagement.get(KeyMgmt.WPA_EAP)
                    && config.allowedKeyManagement.get(KeyMgmt.IEEE8021X)) {

                if (needsSoftwareBackedKeyStore(config.enterpriseConfig)) {
                    return true;
                }
            }
        }

        return false;
    }

    void readPasspointConfig(Map<String, WifiConfiguration> configs,
            SparseArray<Map<String, String>> networkExtras) {
        List<HomeSP> homeSPs;
        try {
            homeSPs = mMOManager.loadAllSPs();
        } catch (IOException e) {
            loge("Could not read " + PPS_FILE + " : " + e);
            return;
        }

        int matchedConfigs = 0;
        for (HomeSP homeSp : homeSPs) {
            String fqdn = homeSp.getFQDN();
            Log.d(TAG, "Looking for " + fqdn);
            for (WifiConfiguration config : configs.values()) {
                Log.d(TAG, "Testing " + config.SSID);

                if (config.enterpriseConfig == null) {
                    continue;
                }
                final String configFqdn =
                        networkExtras.get(config.networkId).get(WifiConfigStore.ID_STRING_KEY_FQDN);
                if (configFqdn != null && configFqdn.equals(fqdn)) {
                    Log.d(TAG, "Matched " + configFqdn + " with " + config.networkId);
                    ++matchedConfigs;
                    config.FQDN = fqdn;
                    config.providerFriendlyName = homeSp.getFriendlyName();

                    HashSet<Long> roamingConsortiumIds = homeSp.getRoamingConsortiums();
                    config.roamingConsortiumIds = new long[roamingConsortiumIds.size()];
                    int i = 0;
                    for (long id : roamingConsortiumIds) {
                        config.roamingConsortiumIds[i] = id;
                        i++;
                    }
                    IMSIParameter imsiParameter = homeSp.getCredential().getImsi();
                    config.enterpriseConfig.setPlmn(
                            imsiParameter != null ? imsiParameter.toString() : null);
                    config.enterpriseConfig.setRealm(homeSp.getCredential().getRealm());
                }
            }
        }

        Log.d(TAG, "loaded " + matchedConfigs + " passpoint configs");
    }

    public void writePasspointConfigs(final String fqdn, final HomeSP homeSP) {
        mWriter.write(PPS_FILE, new DelayedDiskWrite.Writer() {
            @Override
            public void onWriteCalled(DataOutputStream out) throws IOException {
                try {
                    if (homeSP != null) {
                        mMOManager.addSP(homeSP);
                    } else {
                        mMOManager.removeSP(fqdn);
                    }
                } catch (IOException e) {
                    loge("Could not write " + PPS_FILE + " : " + e);
                }
            }
        }, false);
    }

    /**
     *  Write network history, WifiConfigurations and mScanDetailCaches to file.
     */
    private void readNetworkHistory(Map<String, WifiConfiguration> configs) {
        mWifiNetworkHistory.readNetworkHistory(configs,
                mScanDetailCaches,
                mDeletedEphemeralSSIDs);
    }

    /**
     *  Read Network history from file, merge it into mConfiguredNetowrks and mScanDetailCaches
     */
    public void writeKnownNetworkHistory() {
        final List<WifiConfiguration> networks = new ArrayList<WifiConfiguration>();
        for (WifiConfiguration config : mConfiguredNetworks.valuesForAllUsers()) {
            networks.add(new WifiConfiguration(config));
        }
        mWifiNetworkHistory.writeKnownNetworkHistory(networks,
                mScanDetailCaches,
                mDeletedEphemeralSSIDs);
    }

    public void setAndEnableLastSelectedConfiguration(int netId) {
        if (sVDBG) {
            logd("setLastSelectedConfiguration " + Integer.toString(netId));
        }
        if (netId == WifiConfiguration.INVALID_NETWORK_ID) {
            mLastSelectedConfiguration = null;
            mLastSelectedTimeStamp = -1;
        } else {
            WifiConfiguration selected = getWifiConfiguration(netId);
            if (selected == null) {
                mLastSelectedConfiguration = null;
                mLastSelectedTimeStamp = -1;
            } else {
                mLastSelectedConfiguration = selected.configKey();
                mLastSelectedTimeStamp = mClock.elapsedRealtime();
                updateNetworkSelectionStatus(netId,
                        WifiConfiguration.NetworkSelectionStatus.NETWORK_SELECTION_ENABLE);
                if (sVDBG) {
                    logd("setLastSelectedConfiguration now: " + mLastSelectedConfiguration);
                }
            }
        }
    }

    public void setLatestUserSelectedConfiguration(WifiConfiguration network) {
        if (network != null) {
            mLastSelectedConfiguration = network.configKey();
            mLastSelectedTimeStamp = mClock.elapsedRealtime();
        }
    }

    public String getLastSelectedConfiguration() {
        return mLastSelectedConfiguration;
    }

    public long getLastSelectedTimeStamp() {
        return mLastSelectedTimeStamp;
    }

    public boolean isLastSelectedConfiguration(WifiConfiguration config) {
        return (mLastSelectedConfiguration != null
                && config != null
                && mLastSelectedConfiguration.equals(config.configKey()));
    }

    private void writeIpAndProxyConfigurations() {
        final SparseArray<IpConfiguration> networks = new SparseArray<IpConfiguration>();
        for (WifiConfiguration config : mConfiguredNetworks.valuesForAllUsers()) {
            if (!config.ephemeral) {
                networks.put(configKey(config), config.getIpConfiguration());
            }
        }

        mIpconfigStore.writeIpAndProxyConfigurations(IP_CONFIG_FILE, networks);
    }

    private void readIpAndProxyConfigurations() {
        SparseArray<IpConfiguration> networks =
                mIpconfigStore.readIpAndProxyConfigurations(IP_CONFIG_FILE);

        if (networks == null || networks.size() == 0) {
            // IpConfigStore.readIpAndProxyConfigurations has already logged an error.
            return;
        }

        for (int i = 0; i < networks.size(); i++) {
            int id = networks.keyAt(i);
            WifiConfiguration config = mConfiguredNetworks.getByConfigKeyIDForAllUsers(id);
            // This is the only place the map is looked up through a (dangerous) hash-value!

            if (config == null || config.ephemeral) {
                logd("configuration found for missing network, nid=" + id
                        + ", ignored, networks.size=" + Integer.toString(networks.size()));
            } else {
                config.setIpConfiguration(networks.valueAt(i));
            }
        }
    }

    private NetworkUpdateResult addOrUpdateNetworkNative(WifiConfiguration config, int uid) {
        /*
         * If the supplied networkId is INVALID_NETWORK_ID, we create a new empty
         * network configuration. Otherwise, the networkId should
         * refer to an existing configuration.
         */

        if (sVDBG) localLog("addOrUpdateNetworkNative " + config.getPrintableSsid());
        if (config.isPasspoint() && !mMOManager.isEnabled()) {
            Log.e(TAG, "Passpoint is not enabled");
            return new NetworkUpdateResult(INVALID_NETWORK_ID);
        }

        boolean newNetwork = false;
        boolean existingMO = false;
        WifiConfiguration currentConfig;
        // networkId of INVALID_NETWORK_ID means we want to create a new network
        if (config.networkId == INVALID_NETWORK_ID) {
            // Try to fetch the existing config using configKey
            currentConfig = mConfiguredNetworks.getByConfigKeyForCurrentUser(config.configKey());
            if (currentConfig != null) {
                config.networkId = currentConfig.networkId;
            } else {
                if (mMOManager.getHomeSP(config.FQDN) != null) {
                    logd("addOrUpdateNetworkNative passpoint " + config.FQDN
                            + " was found, but no network Id");
                    existingMO = true;
                }
                newNetwork = true;
            }
        } else {
            // Fetch the existing config using networkID
            currentConfig = mConfiguredNetworks.getForCurrentUser(config.networkId);
        }

        // originalConfig is used to check for credential and config changes that would cause
        // HasEverConnected to be set to false.
        WifiConfiguration originalConfig = new WifiConfiguration(currentConfig);

        if (!mWifiConfigStore.addOrUpdateNetwork(config, currentConfig)) {
            return new NetworkUpdateResult(INVALID_NETWORK_ID);
        }
        int netId = config.networkId;
        String savedConfigKey = config.configKey();

        /* An update of the network variables requires reading them
         * back from the supplicant to update mConfiguredNetworks.
         * This is because some of the variables (SSID, wep keys &
         * passphrases) reflect different values when read back than
         * when written. For example, wep key is stored as * irrespective
         * of the value sent to the supplicant.
         */
        if (currentConfig == null) {
            currentConfig = new WifiConfiguration();
            currentConfig.setIpAssignment(IpAssignment.DHCP);
            currentConfig.setProxySettings(ProxySettings.NONE);
            currentConfig.networkId = netId;
            if (config != null) {
                // Carry over the creation parameters
                currentConfig.selfAdded = config.selfAdded;
                currentConfig.didSelfAdd = config.didSelfAdd;
                currentConfig.ephemeral = config.ephemeral;
                currentConfig.meteredHint = config.meteredHint;
                currentConfig.useExternalScores = config.useExternalScores;
                currentConfig.lastConnectUid = config.lastConnectUid;
                currentConfig.lastUpdateUid = config.lastUpdateUid;
                currentConfig.creatorUid = config.creatorUid;
                currentConfig.creatorName = config.creatorName;
                currentConfig.lastUpdateName = config.lastUpdateName;
                currentConfig.peerWifiConfiguration = config.peerWifiConfiguration;
                currentConfig.FQDN = config.FQDN;
                currentConfig.providerFriendlyName = config.providerFriendlyName;
                currentConfig.roamingConsortiumIds = config.roamingConsortiumIds;
                currentConfig.validatedInternetAccess = config.validatedInternetAccess;
                currentConfig.numNoInternetAccessReports = config.numNoInternetAccessReports;
                currentConfig.updateTime = config.updateTime;
                currentConfig.creationTime = config.creationTime;
                currentConfig.shared = config.shared;
            }
            if (DBG) {
                log("created new config netId=" + Integer.toString(netId)
                        + " uid=" + Integer.toString(currentConfig.creatorUid)
                        + " name=" + currentConfig.creatorName);
            }
        }

        /* save HomeSP object for passpoint networks */
        HomeSP homeSP = null;

        if (!existingMO && config.isPasspoint()) {
            try {
                if (config.updateIdentifier == null) {   // Only create an MO for r1 networks
                    Credential credential =
                            new Credential(config.enterpriseConfig, mKeyStore, !newNetwork);
                    HashSet<Long> roamingConsortiumIds = new HashSet<Long>();
                    for (Long roamingConsortiumId : config.roamingConsortiumIds) {
                        roamingConsortiumIds.add(roamingConsortiumId);
                    }

                    homeSP = new HomeSP(Collections.<String, Long>emptyMap(), config.FQDN,
                            roamingConsortiumIds, Collections.<String>emptySet(),
                            Collections.<Long>emptySet(), Collections.<Long>emptyList(),
                            config.providerFriendlyName, null, credential);

                    log("created a homeSP object for " + config.networkId + ":" + config.SSID);
                }

                /* fix enterprise config properties for passpoint */
                currentConfig.enterpriseConfig.setRealm(config.enterpriseConfig.getRealm());
                currentConfig.enterpriseConfig.setPlmn(config.enterpriseConfig.getPlmn());
            } catch (IOException ioe) {
                Log.e(TAG, "Failed to create Passpoint config: " + ioe);
                return new NetworkUpdateResult(INVALID_NETWORK_ID);
            }
        }

        if (uid != WifiConfiguration.UNKNOWN_UID) {
            if (newNetwork) {
                currentConfig.creatorUid = uid;
            } else {
                currentConfig.lastUpdateUid = uid;
            }
        }

        // For debug, record the time the configuration was modified
        StringBuilder sb = new StringBuilder();
        sb.append("time=");
        Calendar c = Calendar.getInstance();
        c.setTimeInMillis(mClock.currentTimeMillis());
        sb.append(String.format("%tm-%td %tH:%tM:%tS.%tL", c, c, c, c, c, c));

        if (newNetwork) {
            currentConfig.creationTime = sb.toString();
        } else {
            currentConfig.updateTime = sb.toString();
        }

        if (currentConfig.status == WifiConfiguration.Status.ENABLED) {
            // Make sure autojoin remain in sync with user modifying the configuration
            updateNetworkSelectionStatus(currentConfig.networkId,
                    WifiConfiguration.NetworkSelectionStatus.NETWORK_SELECTION_ENABLE);
        }

        if (currentConfig.configKey().equals(getLastSelectedConfiguration())
                && currentConfig.ephemeral) {
            // Make the config non-ephemeral since the user just explicitly clicked it.
            currentConfig.ephemeral = false;
            if (DBG) {
                log("remove ephemeral status netId=" + Integer.toString(netId)
                        + " " + currentConfig.configKey());
            }
        }

        if (sVDBG) log("will read network variables netId=" + Integer.toString(netId));

        readNetworkVariables(currentConfig);
        // When we read back the config from wpa_supplicant, some of the default values are set
        // which could change the configKey.
        if (!savedConfigKey.equals(currentConfig.configKey())) {
            if (!mWifiConfigStore.saveNetworkMetadata(currentConfig)) {
                loge("Failed to set network metadata. Removing config " + config.networkId);
                mWifiConfigStore.removeNetwork(config);
                return new NetworkUpdateResult(INVALID_NETWORK_ID);
            }
        }

        boolean passwordChanged = false;
        // check passed in config to see if it has more than a password set.
        if (!newNetwork && config.preSharedKey != null && !config.preSharedKey.equals("*")) {
            passwordChanged = true;
        }

        if (newNetwork || passwordChanged || wasCredentialChange(originalConfig, currentConfig)) {
            currentConfig.getNetworkSelectionStatus().setHasEverConnected(false);
        }

        // Persist configuration paramaters that are not saved by supplicant.
        if (config.lastUpdateName != null) {
            currentConfig.lastUpdateName = config.lastUpdateName;
        }
        if (config.lastUpdateUid != WifiConfiguration.UNKNOWN_UID) {
            currentConfig.lastUpdateUid = config.lastUpdateUid;
        }

        mConfiguredNetworks.put(currentConfig);

        NetworkUpdateResult result =
                writeIpAndProxyConfigurationsOnChange(currentConfig, config, newNetwork);
        result.setIsNewNetwork(newNetwork);
        result.setNetworkId(netId);

        if (homeSP != null) {
            writePasspointConfigs(null, homeSP);
        }

        saveConfig();
        writeKnownNetworkHistory();

        return result;
    }

    private boolean wasBitSetUpdated(BitSet originalBitSet, BitSet currentBitSet) {
        if (originalBitSet != null && currentBitSet != null) {
            // both configs have values set, check if they are different
            if (!originalBitSet.equals(currentBitSet)) {
                // the BitSets are different
                return true;
            }
        } else if (originalBitSet != null || currentBitSet != null) {
            return true;
        }
        return false;
    }

    private boolean wasCredentialChange(WifiConfiguration originalConfig,
            WifiConfiguration currentConfig) {
        // Check if any core WifiConfiguration parameters changed that would impact new connections
        if (originalConfig == null) {
            return true;
        }

        if (wasBitSetUpdated(originalConfig.allowedKeyManagement,
                currentConfig.allowedKeyManagement)) {
            return true;
        }

        if (wasBitSetUpdated(originalConfig.allowedProtocols, currentConfig.allowedProtocols)) {
            return true;
        }

        if (wasBitSetUpdated(originalConfig.allowedAuthAlgorithms,
                currentConfig.allowedAuthAlgorithms)) {
            return true;
        }

        if (wasBitSetUpdated(originalConfig.allowedPairwiseCiphers,
                currentConfig.allowedPairwiseCiphers)) {
            return true;
        }

        if (wasBitSetUpdated(originalConfig.allowedGroupCiphers,
                currentConfig.allowedGroupCiphers)) {
            return true;
        }

        if (originalConfig.wepKeys != null && currentConfig.wepKeys != null) {
            if (originalConfig.wepKeys.length == currentConfig.wepKeys.length) {
                for (int i = 0; i < originalConfig.wepKeys.length; i++) {
                    if (!Objects.equals(originalConfig.wepKeys[i], currentConfig.wepKeys[i])) {
                        return true;
                    }
                }
            } else {
                return true;
            }
        }

        if (originalConfig.hiddenSSID != currentConfig.hiddenSSID) {
            return true;
        }

        if (originalConfig.requirePMF != currentConfig.requirePMF) {
            return true;
        }

        if (wasEnterpriseConfigChange(originalConfig.enterpriseConfig,
                currentConfig.enterpriseConfig)) {
            return true;
        }
        return false;
    }


    protected boolean wasEnterpriseConfigChange(WifiEnterpriseConfig originalEnterpriseConfig,
            WifiEnterpriseConfig currentEnterpriseConfig) {
        if (originalEnterpriseConfig != null && currentEnterpriseConfig != null) {
            if (originalEnterpriseConfig.getEapMethod() != currentEnterpriseConfig.getEapMethod()) {
                return true;
            }

            if (originalEnterpriseConfig.getPhase2Method()
                    != currentEnterpriseConfig.getPhase2Method()) {
                return true;
            }

            X509Certificate[] originalCaCerts = originalEnterpriseConfig.getCaCertificates();
            X509Certificate[] currentCaCerts = currentEnterpriseConfig.getCaCertificates();

            if (originalCaCerts != null && currentCaCerts != null) {
                if (originalCaCerts.length == currentCaCerts.length) {
                    for (int i = 0; i < originalCaCerts.length; i++) {
                        if (!originalCaCerts[i].equals(currentCaCerts[i])) {
                            return true;
                        }
                    }
                } else {
                    // number of aliases is different, so the configs are different
                    return true;
                }
            } else {
                // one of the enterprise configs may have aliases
                if (originalCaCerts != null || currentCaCerts != null) {
                    return true;
                }
            }
        } else {
            // One of the configs may have an enterpriseConfig
            if (originalEnterpriseConfig != null || currentEnterpriseConfig != null) {
                return true;
            }
        }
        return false;
    }

    public WifiConfiguration getWifiConfigForHomeSP(HomeSP homeSP) {
        WifiConfiguration config = mConfiguredNetworks.getByFQDNForCurrentUser(homeSP.getFQDN());
        if (config == null) {
            Log.e(TAG, "Could not find network for homeSP " + homeSP.getFQDN());
        }
        return config;
    }

    public HomeSP getHomeSPForConfig(WifiConfiguration config) {
        WifiConfiguration storedConfig = mConfiguredNetworks.getForCurrentUser(config.networkId);
        return storedConfig != null && storedConfig.isPasspoint()
                ? mMOManager.getHomeSP(storedConfig.FQDN)
                : null;
    }

    public ScanDetailCache getScanDetailCache(WifiConfiguration config) {
        if (config == null) return null;
        ScanDetailCache cache = mScanDetailCaches.get(config.networkId);
        if (cache == null && config.networkId != WifiConfiguration.INVALID_NETWORK_ID) {
            cache = new ScanDetailCache(config);
            mScanDetailCaches.put(config.networkId, cache);
        }
        return cache;
    }

    /**
     * This function run thru the Saved WifiConfigurations and check if some should be linked.
     * @param config
     */
    public void linkConfiguration(WifiConfiguration config) {
        if (!WifiConfigurationUtil.isVisibleToAnyProfile(config,
                mUserManager.getProfiles(mCurrentUserId))) {
            logd("linkConfiguration: Attempting to link config " + config.configKey()
                    + " that is not visible to the current user.");
            return;
        }

        if (getScanDetailCache(config) != null && getScanDetailCache(config).size() > 6) {
            // Ignore configurations with large number of BSSIDs
            return;
        }
        if (!config.allowedKeyManagement.get(KeyMgmt.WPA_PSK)) {
            // Only link WPA_PSK config
            return;
        }
        for (WifiConfiguration link : mConfiguredNetworks.valuesForCurrentUser()) {
            boolean doLink = false;

            if (link.configKey().equals(config.configKey())) {
                continue;
            }

            if (link.ephemeral) {
                continue;
            }

            // Autojoin will be allowed to dynamically jump from a linked configuration
            // to another, hence only link configurations that have equivalent level of security
            if (!link.allowedKeyManagement.equals(config.allowedKeyManagement)) {
                continue;
            }

            ScanDetailCache linkedScanDetailCache = getScanDetailCache(link);
            if (linkedScanDetailCache != null && linkedScanDetailCache.size() > 6) {
                // Ignore configurations with large number of BSSIDs
                continue;
            }

            if (config.defaultGwMacAddress != null && link.defaultGwMacAddress != null) {
                // If both default GW are known, link only if they are equal
                if (config.defaultGwMacAddress.equals(link.defaultGwMacAddress)) {
                    if (sVDBG) {
                        logd("linkConfiguration link due to same gw " + link.SSID
                                + " and " + config.SSID + " GW " + config.defaultGwMacAddress);
                    }
                    doLink = true;
                }
            } else {
                // We do not know BOTH default gateways hence we will try to link
                // hoping that WifiConfigurations are indeed behind the same gateway.
                // once both WifiConfiguration have been tried and thus once both efault gateways
                // are known we will revisit the choice of linking them
                if ((getScanDetailCache(config) != null)
                        && (getScanDetailCache(config).size() <= 6)) {

                    for (String abssid : getScanDetailCache(config).keySet()) {
                        for (String bbssid : linkedScanDetailCache.keySet()) {
                            if (sVVDBG) {
                                logd("linkConfiguration try to link due to DBDC BSSID match "
                                        + link.SSID + " and " + config.SSID + " bssida " + abssid
                                        + " bssidb " + bbssid);
                            }
                            if (abssid.regionMatches(true, 0, bbssid, 0, 16)) {
                                // If first 16 ascii characters of BSSID matches,
                                // we assume this is a DBDC
                                doLink = true;
                            }
                        }
                    }
                }
            }

            if (doLink && mOnlyLinkSameCredentialConfigurations) {
                String apsk =
                        readNetworkVariableFromSupplicantFile(link.configKey(), "psk");
                String bpsk =
                        readNetworkVariableFromSupplicantFile(config.configKey(), "psk");
                if (apsk == null || bpsk == null
                        || TextUtils.isEmpty(apsk) || TextUtils.isEmpty(apsk)
                        || apsk.equals("*") || apsk.equals(DELETED_CONFIG_PSK)
                        || !apsk.equals(bpsk)) {
                    doLink = false;
                }
            }

            if (doLink) {
                if (sVDBG) {
                    logd("linkConfiguration: will link " + link.configKey()
                            + " and " + config.configKey());
                }
                if (link.linkedConfigurations == null) {
                    link.linkedConfigurations = new HashMap<String, Integer>();
                }
                if (config.linkedConfigurations == null) {
                    config.linkedConfigurations = new HashMap<String, Integer>();
                }
                if (link.linkedConfigurations.get(config.configKey()) == null) {
                    link.linkedConfigurations.put(config.configKey(), Integer.valueOf(1));
                }
                if (config.linkedConfigurations.get(link.configKey()) == null) {
                    config.linkedConfigurations.put(link.configKey(), Integer.valueOf(1));
                }
            } else {
                if (link.linkedConfigurations != null
                        && (link.linkedConfigurations.get(config.configKey()) != null)) {
                    if (sVDBG) {
                        logd("linkConfiguration: un-link " + config.configKey()
                                + " from " + link.configKey());
                    }
                    link.linkedConfigurations.remove(config.configKey());
                }
                if (config.linkedConfigurations != null
                        && (config.linkedConfigurations.get(link.configKey()) != null)) {
                    if (sVDBG) {
                        logd("linkConfiguration: un-link " + link.configKey()
                                + " from " + config.configKey());
                    }
                    config.linkedConfigurations.remove(link.configKey());
                }
            }
        }
    }

    public HashSet<Integer> makeChannelList(WifiConfiguration config, int age) {
        if (config == null) {
            return null;
        }
        long now_ms = mClock.currentTimeMillis();

        HashSet<Integer> channels = new HashSet<Integer>();

        //get channels for this configuration, if there are at least 2 BSSIDs
        if (getScanDetailCache(config) == null && config.linkedConfigurations == null) {
            return null;
        }

        if (sVDBG) {
            StringBuilder dbg = new StringBuilder();
            dbg.append("makeChannelList age=" + Integer.toString(age)
                    + " for " + config.configKey()
                    + " max=" + mMaxNumActiveChannelsForPartialScans);
            if (getScanDetailCache(config) != null) {
                dbg.append(" bssids=" + getScanDetailCache(config).size());
            }
            if (config.linkedConfigurations != null) {
                dbg.append(" linked=" + config.linkedConfigurations.size());
            }
            logd(dbg.toString());
        }

        int numChannels = 0;
        if (getScanDetailCache(config) != null && getScanDetailCache(config).size() > 0) {
            for (ScanDetail scanDetail : getScanDetailCache(config).values()) {
                ScanResult result = scanDetail.getScanResult();
                //TODO : cout active and passive channels separately
                if (numChannels > mMaxNumActiveChannelsForPartialScans.get()) {
                    break;
                }
                if (sVDBG) {
                    boolean test = (now_ms - result.seen) < age;
                    logd("has " + result.BSSID + " freq=" + Integer.toString(result.frequency)
                            + " age=" + Long.toString(now_ms - result.seen) + " ?=" + test);
                }
                if (((now_ms - result.seen) < age)) {
                    channels.add(result.frequency);
                    numChannels++;
                }
            }
        }

        //get channels for linked configurations
        if (config.linkedConfigurations != null) {
            for (String key : config.linkedConfigurations.keySet()) {
                WifiConfiguration linked = getWifiConfiguration(key);
                if (linked == null) {
                    continue;
                }
                if (getScanDetailCache(linked) == null) {
                    continue;
                }
                for (ScanDetail scanDetail : getScanDetailCache(linked).values()) {
                    ScanResult result = scanDetail.getScanResult();
                    if (sVDBG) {
                        logd("has link: " + result.BSSID
                                + " freq=" + Integer.toString(result.frequency)
                                + " age=" + Long.toString(now_ms - result.seen));
                    }
                    if (numChannels > mMaxNumActiveChannelsForPartialScans.get()) {
                        break;
                    }
                    if (((now_ms - result.seen) < age)) {
                        channels.add(result.frequency);
                        numChannels++;
                    }
                }
            }
        }
        return channels;
    }

    private Map<HomeSP, PasspointMatch> matchPasspointNetworks(ScanDetail scanDetail) {
        if (!mMOManager.isConfigured()) {
            if (mEnableOsuQueries) {
                NetworkDetail networkDetail = scanDetail.getNetworkDetail();
                List<Constants.ANQPElementType> querySet =
                        ANQPFactory.buildQueryList(networkDetail, false, true);

                if (networkDetail.queriable(querySet)) {
                    querySet = mAnqpCache.initiate(networkDetail, querySet);
                    if (querySet != null) {
                        mSupplicantBridge.startANQP(scanDetail, querySet);
                    }
                    updateAnqpCache(scanDetail, networkDetail.getANQPElements());
                }
            }
            return null;
        }
        NetworkDetail networkDetail = scanDetail.getNetworkDetail();
        if (!networkDetail.hasInterworking()) {
            return null;
        }
        updateAnqpCache(scanDetail, networkDetail.getANQPElements());

        Map<HomeSP, PasspointMatch> matches = matchNetwork(scanDetail, true);
        Log.d(Utils.hs2LogTag(getClass()), scanDetail.getSSID()
                + " pass 1 matches: " + toMatchString(matches));
        return matches;
    }

    private Map<HomeSP, PasspointMatch> matchNetwork(ScanDetail scanDetail, boolean query) {
        NetworkDetail networkDetail = scanDetail.getNetworkDetail();

        ANQPData anqpData = mAnqpCache.getEntry(networkDetail);

        Map<Constants.ANQPElementType, ANQPElement> anqpElements =
                anqpData != null ? anqpData.getANQPElements() : null;

        boolean queried = !query;
        Collection<HomeSP> homeSPs = mMOManager.getLoadedSPs().values();
        Map<HomeSP, PasspointMatch> matches = new HashMap<>(homeSPs.size());
        Log.d(Utils.hs2LogTag(getClass()), "match nwk " + scanDetail.toKeyString()
                + ", anqp " + (anqpData != null ? "present" : "missing")
                + ", query " + query + ", home sps: " + homeSPs.size());

        for (HomeSP homeSP : homeSPs) {
            PasspointMatch match = homeSP.match(networkDetail, anqpElements, mSIMAccessor);

            Log.d(Utils.hs2LogTag(getClass()), " -- "
                    + homeSP.getFQDN() + ": match " + match + ", queried " + queried);

            if ((match == PasspointMatch.Incomplete || mEnableOsuQueries) && !queried) {
                boolean matchSet = match == PasspointMatch.Incomplete;
                boolean osu = mEnableOsuQueries;
                List<Constants.ANQPElementType> querySet =
                        ANQPFactory.buildQueryList(networkDetail, matchSet, osu);
                if (networkDetail.queriable(querySet)) {
                    querySet = mAnqpCache.initiate(networkDetail, querySet);
                    if (querySet != null) {
                        mSupplicantBridge.startANQP(scanDetail, querySet);
                    }
                }
                queried = true;
            }
            matches.put(homeSP, match);
        }
        return matches;
    }

    public Map<Constants.ANQPElementType, ANQPElement> getANQPData(NetworkDetail network) {
        ANQPData data = mAnqpCache.getEntry(network);
        return data != null ? data.getANQPElements() : null;
    }

    public SIMAccessor getSIMAccessor() {
        return mSIMAccessor;
    }

    public void notifyANQPDone(Long bssid, boolean success) {
        mSupplicantBridge.notifyANQPDone(bssid, success);
    }

    public void notifyIconReceived(IconEvent iconEvent) {
        Intent intent = new Intent(WifiManager.PASSPOINT_ICON_RECEIVED_ACTION);
        intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT);
        intent.putExtra(WifiManager.EXTRA_PASSPOINT_ICON_BSSID, iconEvent.getBSSID());
        intent.putExtra(WifiManager.EXTRA_PASSPOINT_ICON_FILE, iconEvent.getFileName());
        try {
            intent.putExtra(WifiManager.EXTRA_PASSPOINT_ICON_DATA,
                    mSupplicantBridge.retrieveIcon(iconEvent));
        } catch (IOException ioe) {
            /* Simply omit the icon data as a failure indication */
        }
        mContext.sendBroadcastAsUser(intent, UserHandle.ALL);

    }

    private void updateAnqpCache(ScanDetail scanDetail,
                                 Map<Constants.ANQPElementType, ANQPElement> anqpElements) {
        NetworkDetail networkDetail = scanDetail.getNetworkDetail();

        if (anqpElements == null) {
            // Try to pull cached data if query failed.
            ANQPData data = mAnqpCache.getEntry(networkDetail);
            if (data != null) {
                scanDetail.propagateANQPInfo(data.getANQPElements());
            }
            return;
        }

        mAnqpCache.update(networkDetail, anqpElements);
    }

    private static String toMatchString(Map<HomeSP, PasspointMatch> matches) {
        StringBuilder sb = new StringBuilder();
        for (Map.Entry<HomeSP, PasspointMatch> entry : matches.entrySet()) {
            sb.append(' ').append(entry.getKey().getFQDN()).append("->").append(entry.getValue());
        }
        return sb.toString();
    }

    private void cacheScanResultForPasspointConfigs(ScanDetail scanDetail,
            Map<HomeSP, PasspointMatch> matches,
            List<WifiConfiguration> associatedWifiConfigurations) {

        for (Map.Entry<HomeSP, PasspointMatch> entry : matches.entrySet()) {
            PasspointMatch match = entry.getValue();
            if (match == PasspointMatch.HomeProvider || match == PasspointMatch.RoamingProvider) {
                WifiConfiguration config = getWifiConfigForHomeSP(entry.getKey());
                if (config != null) {
                    cacheScanResultForConfig(config, scanDetail, entry.getValue());
                    if (associatedWifiConfigurations != null) {
                        associatedWifiConfigurations.add(config);
                    }
                } else {
                    Log.w(Utils.hs2LogTag(getClass()), "Failed to find config for '"
                            + entry.getKey().getFQDN() + "'");
                    /* perhaps the configuration was deleted?? */
                }
            }
        }
    }

    private void cacheScanResultForConfig(
            WifiConfiguration config, ScanDetail scanDetail, PasspointMatch passpointMatch) {

        ScanResult scanResult = scanDetail.getScanResult();

        ScanDetailCache scanDetailCache = getScanDetailCache(config);
        if (scanDetailCache == null) {
            Log.w(TAG, "Could not allocate scan cache for " + config.SSID);
            return;
        }

        // Adding a new BSSID
        ScanResult result = scanDetailCache.get(scanResult.BSSID);
        if (result != null) {
            // transfer the black list status
            scanResult.blackListTimestamp = result.blackListTimestamp;
            scanResult.numIpConfigFailures = result.numIpConfigFailures;
            scanResult.numConnection = result.numConnection;
            scanResult.isAutoJoinCandidate = result.isAutoJoinCandidate;
        }

        if (config.ephemeral) {
            // For an ephemeral Wi-Fi config, the ScanResult should be considered
            // untrusted.
            scanResult.untrusted = true;
        }

        if (scanDetailCache.size() > (MAX_NUM_SCAN_CACHE_ENTRIES + 64)) {
            long now_dbg = 0;
            if (sVVDBG) {
                logd(" Will trim config " + config.configKey()
                        + " size " + scanDetailCache.size());

                for (ScanDetail sd : scanDetailCache.values()) {
                    logd("     " + sd.getBSSIDString() + " " + sd.getSeen());
                }
                now_dbg = SystemClock.elapsedRealtimeNanos();
            }
            // Trim the scan result cache to MAX_NUM_SCAN_CACHE_ENTRIES entries max
            // Since this operation is expensive, make sure it is not performed
            // until the cache has grown significantly above the trim treshold
            scanDetailCache.trim(MAX_NUM_SCAN_CACHE_ENTRIES);
            if (sVVDBG) {
                long diff = SystemClock.elapsedRealtimeNanos() - now_dbg;
                logd(" Finished trimming config, time(ns) " + diff);
                for (ScanDetail sd : scanDetailCache.values()) {
                    logd("     " + sd.getBSSIDString() + " " + sd.getSeen());
                }
            }
        }

        // Add the scan result to this WifiConfiguration
        if (passpointMatch != null) {
            scanDetailCache.put(scanDetail, passpointMatch, getHomeSPForConfig(config));
        } else {
            scanDetailCache.put(scanDetail);
        }

        // Since we added a scan result to this configuration, re-attempt linking
        linkConfiguration(config);
    }

    private boolean isEncryptionWep(String encryption) {
        return encryption.contains("WEP");
    }

    private boolean isEncryptionPsk(String encryption) {
        return encryption.contains("PSK");
    }

    private boolean isEncryptionEap(String encryption) {
        return encryption.contains("EAP");
    }

    public boolean isOpenNetwork(String encryption) {
        if (!isEncryptionWep(encryption) && !isEncryptionPsk(encryption)
                && !isEncryptionEap(encryption)) {
            return true;
        }
        return false;
    }

    public boolean isOpenNetwork(ScanResult scan) {
        String scanResultEncrypt = scan.capabilities;
        return isOpenNetwork(scanResultEncrypt);
    }

    public boolean isOpenNetwork(WifiConfiguration config) {
        String configEncrypt = config.configKey();
        return isOpenNetwork(configEncrypt);
    }

    /**
     * Get saved WifiConfiguration associated with a scan detail.
     * @param scanDetail input a scanDetail from the scan result
     * @return WifiConfiguration WifiConfiguration associated with this scanDetail, null if none
     */
    public List<WifiConfiguration> getSavedNetworkFromScanDetail(ScanDetail scanDetail) {
        ScanResult scanResult = scanDetail.getScanResult();
        if (scanResult == null) {
            return null;
        }
        List<WifiConfiguration> savedWifiConfigurations = new ArrayList<>();
        String ssid = "\"" + scanResult.SSID + "\"";
        for (WifiConfiguration config : mConfiguredNetworks.valuesForCurrentUser()) {
            if (config.SSID == null || !config.SSID.equals(ssid)) {
                continue;
            }
            if (DBG) {
                localLog("getSavedNetworkFromScanDetail(): try " + config.configKey()
                        + " SSID=" + config.SSID + " " + scanResult.SSID + " "
                        + scanResult.capabilities);
            }
            String scanResultEncrypt = scanResult.capabilities;
            String configEncrypt = config.configKey();
            if (isEncryptionWep(scanResultEncrypt) && isEncryptionWep(configEncrypt)
                    || (isEncryptionPsk(scanResultEncrypt) && isEncryptionPsk(configEncrypt))
                    || (isEncryptionEap(scanResultEncrypt) && isEncryptionEap(configEncrypt))
                    || (isOpenNetwork(scanResultEncrypt) && isOpenNetwork(configEncrypt))) {
                savedWifiConfigurations.add(config);
            }
        }
        return savedWifiConfigurations;
    }

    /**
     * Create a mapping between the scandetail and the Wificonfiguration it associated with
     * because Passpoint, one BSSID can associated with multiple SSIDs
     * @param scanDetail input a scanDetail from the scan result
     * @param isConnectingOrConnected input a boolean to indicate if WiFi is connecting or conncted
     * This is used for avoiding ANQP request
     * @return List<WifiConfiguration> a list of WifiConfigurations associated to this scanDetail
     */
    public List<WifiConfiguration> updateSavedNetworkWithNewScanDetail(ScanDetail scanDetail,
            boolean isConnectingOrConnected) {
        ScanResult scanResult = scanDetail.getScanResult();
        if (scanResult == null) {
            return null;
        }
        NetworkDetail networkDetail = scanDetail.getNetworkDetail();
        List<WifiConfiguration> associatedWifiConfigurations = new ArrayList<>();
        if (networkDetail.hasInterworking() && !isConnectingOrConnected) {
            Map<HomeSP, PasspointMatch> matches = matchPasspointNetworks(scanDetail);
            if (matches != null) {
                cacheScanResultForPasspointConfigs(scanDetail, matches,
                        associatedWifiConfigurations);
                //Do not return here. A BSSID can belong to both passpoint network and non-passpoint
                //Network
            }
        }
        List<WifiConfiguration> savedConfigurations = getSavedNetworkFromScanDetail(scanDetail);
        if (savedConfigurations != null) {
            for (WifiConfiguration config : savedConfigurations) {
                cacheScanResultForConfig(config, scanDetail, null);
                associatedWifiConfigurations.add(config);
            }
        }
        if (associatedWifiConfigurations.size() == 0) {
            return null;
        } else {
            return associatedWifiConfigurations;
        }
    }

    /**
     * Handles the switch to a different foreground user:
     * - Removes all ephemeral networks
     * - Disables private network configurations belonging to the previous foreground user
     * - Enables private network configurations belonging to the new foreground user
     *
     * @param userId The identifier of the new foreground user, after the switch.
     *
     * TODO(b/26785736): Terminate background users if the new foreground user has one or more
     * private network configurations.
     */
    public void handleUserSwitch(int userId) {
        mCurrentUserId = userId;
        Set<WifiConfiguration> ephemeralConfigs = new HashSet<>();
        for (WifiConfiguration config : mConfiguredNetworks.valuesForCurrentUser()) {
            if (config.ephemeral) {
                ephemeralConfigs.add(config);
            }
        }
        if (!ephemeralConfigs.isEmpty()) {
            for (WifiConfiguration config : ephemeralConfigs) {
                removeConfigWithoutBroadcast(config);
            }
            saveConfig();
            writeKnownNetworkHistory();
        }

        final List<WifiConfiguration> hiddenConfigurations =
                mConfiguredNetworks.handleUserSwitch(mCurrentUserId);
        for (WifiConfiguration network : hiddenConfigurations) {
            disableNetworkNative(network);
        }
        enableAllNetworks();

        // TODO(b/26785746): This broadcast is unnecessary if either of the following is true:
        // * The user switch did not change the list of visible networks
        // * The user switch revealed additional networks that were temporarily disabled and got
        //   re-enabled now (because enableAllNetworks() sent the same broadcast already).
        sendConfiguredNetworksChangedBroadcast();
    }

    public int getCurrentUserId() {
        return mCurrentUserId;
    }

    public boolean isCurrentUserProfile(int userId) {
        if (userId == mCurrentUserId) {
            return true;
        }
        final UserInfo parent = mUserManager.getProfileParent(userId);
        return parent != null && parent.id == mCurrentUserId;
    }

    /* Compare current and new configuration and write to file on change */
    private NetworkUpdateResult writeIpAndProxyConfigurationsOnChange(
            WifiConfiguration currentConfig,
            WifiConfiguration newConfig,
            boolean isNewNetwork) {
        boolean ipChanged = false;
        boolean proxyChanged = false;

        switch (newConfig.getIpAssignment()) {
            case STATIC:
                if (currentConfig.getIpAssignment() != newConfig.getIpAssignment()) {
                    ipChanged = true;
                } else {
                    ipChanged = !Objects.equals(
                            currentConfig.getStaticIpConfiguration(),
                            newConfig.getStaticIpConfiguration());
                }
                break;
            case DHCP:
                if (currentConfig.getIpAssignment() != newConfig.getIpAssignment()) {
                    ipChanged = true;
                }
                break;
            case UNASSIGNED:
                /* Ignore */
                break;
            default:
                loge("Ignore invalid ip assignment during write");
                break;
        }

        switch (newConfig.getProxySettings()) {
            case STATIC:
            case PAC:
                ProxyInfo newHttpProxy = newConfig.getHttpProxy();
                ProxyInfo currentHttpProxy = currentConfig.getHttpProxy();

                if (newHttpProxy != null) {
                    proxyChanged = !newHttpProxy.equals(currentHttpProxy);
                } else {
                    proxyChanged = (currentHttpProxy != null);
                }
                break;
            case NONE:
                if (currentConfig.getProxySettings() != newConfig.getProxySettings()) {
                    proxyChanged = true;
                }
                break;
            case UNASSIGNED:
                /* Ignore */
                break;
            default:
                loge("Ignore invalid proxy configuration during write");
                break;
        }

        if (ipChanged) {
            currentConfig.setIpAssignment(newConfig.getIpAssignment());
            currentConfig.setStaticIpConfiguration(newConfig.getStaticIpConfiguration());
            log("IP config changed SSID = " + currentConfig.SSID);
            if (currentConfig.getStaticIpConfiguration() != null) {
                log(" static configuration: "
                        + currentConfig.getStaticIpConfiguration().toString());
            }
        }

        if (proxyChanged) {
            currentConfig.setProxySettings(newConfig.getProxySettings());
            currentConfig.setHttpProxy(newConfig.getHttpProxy());
            log("proxy changed SSID = " + currentConfig.SSID);
            if (currentConfig.getHttpProxy() != null) {
                log(" proxyProperties: " + currentConfig.getHttpProxy().toString());
            }
        }

        if (ipChanged || proxyChanged || isNewNetwork) {
            if (sVDBG) {
                logd("writeIpAndProxyConfigurationsOnChange: " + currentConfig.SSID + " -> "
                        + newConfig.SSID + " path: " + IP_CONFIG_FILE);
            }
            writeIpAndProxyConfigurations();
        }
        return new NetworkUpdateResult(ipChanged, proxyChanged);
    }

    /**
     * Read the variables from the supplicant daemon that are needed to
     * fill in the WifiConfiguration object.
     *
     * @param config the {@link WifiConfiguration} object to be filled in.
     */
    private void readNetworkVariables(WifiConfiguration config) {
        mWifiConfigStore.readNetworkVariables(config);
    }

    /* return the allowed key management based on a scan result */

    public WifiConfiguration wifiConfigurationFromScanResult(ScanResult result) {

        WifiConfiguration config = new WifiConfiguration();

        config.SSID = "\"" + result.SSID + "\"";

        if (sVDBG) {
            logd("WifiConfiguration from scan results "
                    + config.SSID + " cap " + result.capabilities);
        }

        if (result.capabilities.contains("PSK") || result.capabilities.contains("EAP")
                || result.capabilities.contains("WEP")) {
            if (result.capabilities.contains("PSK")) {
                config.allowedKeyManagement.set(KeyMgmt.WPA_PSK);
            }

            if (result.capabilities.contains("EAP")) {
                config.allowedKeyManagement.set(KeyMgmt.WPA_EAP);
                config.allowedKeyManagement.set(KeyMgmt.IEEE8021X);
            }

            if (result.capabilities.contains("WEP")) {
                config.allowedKeyManagement.set(KeyMgmt.NONE);
                config.allowedAuthAlgorithms.set(WifiConfiguration.AuthAlgorithm.OPEN);
                config.allowedAuthAlgorithms.set(WifiConfiguration.AuthAlgorithm.SHARED);
            }
        } else {
            config.allowedKeyManagement.set(KeyMgmt.NONE);
        }

        return config;
    }

    public WifiConfiguration wifiConfigurationFromScanResult(ScanDetail scanDetail) {
        ScanResult result = scanDetail.getScanResult();
        return wifiConfigurationFromScanResult(result);
    }

    /* Returns a unique for a given configuration */
    private static int configKey(WifiConfiguration config) {
        String key = config.configKey();
        return key.hashCode();
    }

    void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
        pw.println("Dump of WifiConfigManager");
        pw.println("mLastPriority " + mLastPriority);
        pw.println("Configured networks");
        for (WifiConfiguration conf : getAllConfiguredNetworks()) {
            pw.println(conf);
        }
        pw.println();
        if (mLostConfigsDbg != null && mLostConfigsDbg.size() > 0) {
            pw.println("LostConfigs: ");
            for (String s : mLostConfigsDbg) {
                pw.println(s);
            }
        }

        if (mMOManager.isConfigured()) {
            pw.println("Begin dump of ANQP Cache");
            mAnqpCache.dump(pw);
            pw.println("End dump of ANQP Cache");
        }
    }

    public String getConfigFile() {
        return IP_CONFIG_FILE;
    }

    protected void logd(String s) {
        Log.d(TAG, s);
    }

    protected void loge(String s) {
        loge(s, false);
    }

    protected void loge(String s, boolean stack) {
        if (stack) {
            Log.e(TAG, s + " stack:" + Thread.currentThread().getStackTrace()[2].getMethodName()
                    + " - " + Thread.currentThread().getStackTrace()[3].getMethodName()
                    + " - " + Thread.currentThread().getStackTrace()[4].getMethodName()
                    + " - " + Thread.currentThread().getStackTrace()[5].getMethodName());
        } else {
            Log.e(TAG, s);
        }
    }

    private void logKernelTime() {
        long kernelTimeMs = System.nanoTime() / (1000 * 1000);
        StringBuilder builder = new StringBuilder();
        builder.append("kernel time = ")
                .append(kernelTimeMs / 1000)
                .append(".")
                .append(kernelTimeMs % 1000)
                .append("\n");
        localLog(builder.toString());
    }

    protected void log(String s) {
        Log.d(TAG, s);
    }

    private void localLog(String s) {
        if (mLocalLog != null) {
            mLocalLog.log(s);
        }
    }

    private void localLogAndLogcat(String s) {
        localLog(s);
        Log.d(TAG, s);
    }

    private void localLogNetwork(String s, int netId) {
        if (mLocalLog == null) {
            return;
        }

        WifiConfiguration config;
        synchronized (mConfiguredNetworks) {             // !!! Useless synchronization
            config = mConfiguredNetworks.getForAllUsers(netId);
        }

        if (config != null) {
            mLocalLog.log(s + " " + config.getPrintableSsid() + " " + netId
                    + " status=" + config.status
                    + " key=" + config.configKey());
        } else {
            mLocalLog.log(s + " " + netId);
        }
    }

    static boolean needsSoftwareBackedKeyStore(WifiEnterpriseConfig config) {
        String client = config.getClientCertificateAlias();
        if (!TextUtils.isEmpty(client)) {
            // a valid client certificate is configured

            // BUGBUG: keyStore.get() never returns certBytes; because it is not
            // taking WIFI_UID as a parameter. It always looks for certificate
            // with SYSTEM_UID, and never finds any Wifi certificates. Assuming that
            // all certificates need software keystore until we get the get() API
            // fixed.

            return true;
        }

        /*
        try {

            if (DBG) Slog.d(TAG, "Loading client certificate " + Credentials
                    .USER_CERTIFICATE + client);

            CertificateFactory factory = CertificateFactory.getInstance("X.509");
            if (factory == null) {
                Slog.e(TAG, "Error getting certificate factory");
                return;
            }

            byte[] certBytes = keyStore.get(Credentials.USER_CERTIFICATE + client);
            if (certBytes != null) {
                Certificate cert = (X509Certificate) factory.generateCertificate(
                        new ByteArrayInputStream(certBytes));

                if (cert != null) {
                    mNeedsSoftwareKeystore = hasHardwareBackedKey(cert);

                    if (DBG) Slog.d(TAG, "Loaded client certificate " + Credentials
                            .USER_CERTIFICATE + client);
                    if (DBG) Slog.d(TAG, "It " + (mNeedsSoftwareKeystore ? "needs" :
                            "does not need" ) + " software key store");
                } else {
                    Slog.d(TAG, "could not generate certificate");
                }
            } else {
                Slog.e(TAG, "Could not load client certificate " + Credentials
                        .USER_CERTIFICATE + client);
                mNeedsSoftwareKeystore = true;
            }

        } catch(CertificateException e) {
            Slog.e(TAG, "Could not read certificates");
            mCaCert = null;
            mClientCertificate = null;
        }
        */

        return false;
    }

    /**
     * Resets all sim networks from the network list.
     */
    public void resetSimNetworks() {
        mWifiConfigStore.resetSimNetworks(mConfiguredNetworks.valuesForCurrentUser());
    }

    boolean isNetworkConfigured(WifiConfiguration config) {
        // Check if either we have a network Id or a WifiConfiguration
        // matching the one we are trying to add.

        if (config.networkId != INVALID_NETWORK_ID) {
            return (mConfiguredNetworks.getForCurrentUser(config.networkId) != null);
        }

        return (mConfiguredNetworks.getByConfigKeyForCurrentUser(config.configKey()) != null);
    }

    /**
     * Checks if uid has access to modify the configuration corresponding to networkId.
     *
     * The conditions checked are, in descending priority order:
     * - Disallow modification if the the configuration is not visible to the uid.
     * - Allow modification if the uid represents the Device Owner app.
     * - Allow modification if both of the following are true:
     *   - The uid represents the configuration's creator or an app holding OVERRIDE_CONFIG_WIFI.
     *   - The modification is only for administrative annotation (e.g. when connecting) or the
     *     configuration is not lockdown eligible (which currently means that it was not last
     *     updated by the DO).
     * - Allow modification if configuration lockdown is explicitly disabled and the uid represents
     *   an app holding OVERRIDE_CONFIG_WIFI.
     * - In all other cases, disallow modification.
     */
    boolean canModifyNetwork(int uid, int networkId, boolean onlyAnnotate) {
        WifiConfiguration config = mConfiguredNetworks.getForCurrentUser(networkId);

        if (config == null) {
            loge("canModifyNetwork: cannot find config networkId " + networkId);
            return false;
        }

        final DevicePolicyManagerInternal dpmi = LocalServices.getService(
                DevicePolicyManagerInternal.class);

        final boolean isUidDeviceOwner = dpmi != null && dpmi.isActiveAdminWithPolicy(uid,
                DeviceAdminInfo.USES_POLICY_DEVICE_OWNER);

        if (isUidDeviceOwner) {
            return true;
        }

        final boolean isCreator = (config.creatorUid == uid);

        if (onlyAnnotate) {
            return isCreator || checkConfigOverridePermission(uid);
        }

        // Check if device has DPM capability. If it has and dpmi is still null, then we
        // treat this case with suspicion and bail out.
        if (mContext.getPackageManager().hasSystemFeature(PackageManager.FEATURE_DEVICE_ADMIN)
                && dpmi == null) {
            return false;
        }

        // WiFi config lockdown related logic. At this point we know uid NOT to be a Device Owner.

        final boolean isConfigEligibleForLockdown = dpmi != null && dpmi.isActiveAdminWithPolicy(
                config.creatorUid, DeviceAdminInfo.USES_POLICY_DEVICE_OWNER);
        if (!isConfigEligibleForLockdown) {
            return isCreator || checkConfigOverridePermission(uid);
        }

        final ContentResolver resolver = mContext.getContentResolver();
        final boolean isLockdownFeatureEnabled = Settings.Global.getInt(resolver,
                Settings.Global.WIFI_DEVICE_OWNER_CONFIGS_LOCKDOWN, 0) != 0;
        return !isLockdownFeatureEnabled && checkConfigOverridePermission(uid);
    }

    /**
     * Checks if uid has access to modify config.
     */
    boolean canModifyNetwork(int uid, WifiConfiguration config, boolean onlyAnnotate) {
        if (config == null) {
            loge("canModifyNetowrk recieved null configuration");
            return false;
        }

        // Resolve the correct network id.
        int netid;
        if (config.networkId != INVALID_NETWORK_ID) {
            netid = config.networkId;
        } else {
            WifiConfiguration test =
                    mConfiguredNetworks.getByConfigKeyForCurrentUser(config.configKey());
            if (test == null) {
                return false;
            } else {
                netid = test.networkId;
            }
        }

        return canModifyNetwork(uid, netid, onlyAnnotate);
    }

    boolean checkConfigOverridePermission(int uid) {
        try {
            return (mFacade.checkUidPermission(
                    android.Manifest.permission.OVERRIDE_WIFI_CONFIG, uid)
                    == PackageManager.PERMISSION_GRANTED);
        } catch (RemoteException e) {
            return false;
        }
    }

    /** called when CS ask WiFistateMachine to disconnect the current network
     * because the score is bad.
     */
    void handleBadNetworkDisconnectReport(int netId, WifiInfo info) {
        /* TODO verify the bad network is current */
        WifiConfiguration config = mConfiguredNetworks.getForCurrentUser(netId);
        if (config != null) {
            if ((info.is24GHz() && info.getRssi()
                    <= WifiQualifiedNetworkSelector.QUALIFIED_RSSI_24G_BAND)
                    || (info.is5GHz() && info.getRssi()
                    <= WifiQualifiedNetworkSelector.QUALIFIED_RSSI_5G_BAND)) {
                // We do not block due to bad RSSI since network selection should not select bad
                // RSSI candidate
            } else {
                // We got disabled but RSSI is good, so disable hard
                updateNetworkSelectionStatus(config,
                        WifiConfiguration.NetworkSelectionStatus.DISABLED_BAD_LINK);
            }
        }
        // Record last time Connectivity Service switched us away from WiFi and onto Cell
        mLastUnwantedNetworkDisconnectTimestamp = mClock.currentTimeMillis();
    }

    int getMaxDhcpRetries() {
        return mFacade.getIntegerSetting(mContext,
                Settings.Global.WIFI_MAX_DHCP_RETRY_COUNT,
                DEFAULT_MAX_DHCP_RETRIES);
    }

    void clearBssidBlacklist() {
        mWifiConfigStore.clearBssidBlacklist();
    }

    void blackListBssid(String bssid) {
        mWifiConfigStore.blackListBssid(bssid);
    }

    public boolean isBssidBlacklisted(String bssid) {
        return mWifiConfigStore.isBssidBlacklisted(bssid);
    }

    public boolean getEnableAutoJoinWhenAssociated() {
        return mEnableAutoJoinWhenAssociated.get();
    }

    public void setEnableAutoJoinWhenAssociated(boolean enabled) {
        mEnableAutoJoinWhenAssociated.set(enabled);
    }

    public void setActiveScanDetail(ScanDetail activeScanDetail) {
        synchronized (mActiveScanDetailLock) {
            mActiveScanDetail = activeScanDetail;
        }
    }

    /**
     * Check if the provided ephemeral network was deleted by the user or not.
     * @param ssid ssid of the network
     * @return true if network was deleted, false otherwise.
     */
    public boolean wasEphemeralNetworkDeleted(String ssid) {
        return mDeletedEphemeralSSIDs.contains(ssid);
    }
}
