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

package com.android.server.wifi;

import android.app.ActivityManager;
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.net.IpConfiguration;
import android.net.ProxyInfo;
import android.net.StaticIpConfiguration;
import android.net.wifi.ScanResult;
import android.net.wifi.WifiConfiguration;
import android.net.wifi.WifiConfiguration.NetworkSelectionStatus;
import android.net.wifi.WifiEnterpriseConfig;
import android.net.wifi.WifiInfo;
import android.net.wifi.WifiManager;
import android.net.wifi.WifiScanner;
import android.os.Process;
import android.os.UserHandle;
import android.os.UserManager;
import android.provider.Settings;
import android.telephony.TelephonyManager;
import android.text.TextUtils;
import android.util.ArraySet;
import android.util.LocalLog;
import android.util.Log;

import com.android.internal.R;
import com.android.internal.annotations.VisibleForTesting;
import com.android.server.LocalServices;
import com.android.server.wifi.WifiConfigStoreLegacy.WifiConfigStoreDataLegacy;
import com.android.server.wifi.hotspot2.PasspointManager;
import com.android.server.wifi.util.ScanResultUtil;
import com.android.server.wifi.util.TelephonyUtil;
import com.android.server.wifi.util.WifiPermissionsUtil;
import com.android.server.wifi.util.WifiPermissionsWrapper;

import org.xmlpull.v1.XmlPullParserException;

import java.io.FileDescriptor;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.BitSet;
import java.util.Calendar;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;

/**
 * This class provides the APIs to manage configured Wi-Fi networks.
 * It deals with the following:
 * - Maintaining a list of configured networks for quick access.
 * - Persisting the configurations to store when required.
 * - Supporting WifiManager Public API calls:
 *   > addOrUpdateNetwork()
 *   > removeNetwork()
 *   > enableNetwork()
 *   > disableNetwork()
 * - Handle user switching on multi-user devices.
 *
 * All network configurations retrieved from this class are copies of the original configuration
 * stored in the internal database. So, any updates to the retrieved configuration object are
 * meaningless and will not be reflected in the original database.
 * This is done on purpose to ensure that only WifiConfigManager can modify configurations stored
 * in the internal database. Any configuration updates should be triggered with appropriate helper
 * methods of this class using the configuration's unique networkId.
 *
 * NOTE: These API's are not thread safe and should only be used from WifiStateMachine thread.
 */
public class WifiConfigManager {
    /**
     * String used to mask passwords to public interface.
     */
    @VisibleForTesting
    public static final String PASSWORD_MASK = "*";
    /**
     * Package name for SysUI. This is used to lookup the UID of SysUI which is used to allow
     * Quick settings to modify network configurations.
     */
    @VisibleForTesting
    public static final String SYSUI_PACKAGE_NAME = "com.android.systemui";
    /**
     * Network Selection disable reason thresholds. These numbers are used to debounce network
     * failures before we disable them.
     * These are indexed using the disable reason constants defined in
     * {@link android.net.wifi.WifiConfiguration.NetworkSelectionStatus}.
     */
    @VisibleForTesting
    public 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
            1,  //  threshold for DISABLED_WPS_START
            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
            1   //  threshold for DISABLED_BY_USER_SWITCH
    };
    /**
     * Network Selection disable timeout for each kind of error. After the timeout milliseconds,
     * enable the network again.
     * These are indexed using the disable reason constants defined in
     * {@link android.net.wifi.WifiConfiguration.NetworkSelectionStatus}.
     */
    @VisibleForTesting
    public static final int[] NETWORK_SELECTION_DISABLE_TIMEOUT_MS = {
            Integer.MAX_VALUE,  // threshold for NETWORK_SELECTION_ENABLE
            15 * 60 * 1000,     // threshold for DISABLED_BAD_LINK
            5 * 60 * 1000,      // threshold for DISABLED_ASSOCIATION_REJECTION
            5 * 60 * 1000,      // threshold for DISABLED_AUTHENTICATION_FAILURE
            5 * 60 * 1000,      // threshold for DISABLED_DHCP_FAILURE
            5 * 60 * 1000,      // threshold for DISABLED_DNS_FAILURE
            0 * 60 * 1000,      // threshold for DISABLED_WPS_START
            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
            Integer.MAX_VALUE   // threshold for DISABLED_BY_USER_SWITCH
    };
    /**
     * Interface for other modules to listen to the saved network updated
     * events.
     */
    public interface OnSavedNetworkUpdateListener {
        /**
         * Invoked on saved network being added.
         */
        void onSavedNetworkAdded(int networkId);
        /**
         * Invoked on saved network being enabled.
         */
        void onSavedNetworkEnabled(int networkId);
        /**
         * Invoked on saved network being permanently disabled.
         */
        void onSavedNetworkPermanentlyDisabled(int networkId);
        /**
         * Invoked on saved network being removed.
         */
        void onSavedNetworkRemoved(int networkId);
        /**
         * Invoked on saved network being temporarily disabled.
         */
        void onSavedNetworkTemporarilyDisabled(int networkId);
        /**
         * Invoked on saved network being updated.
         */
        void onSavedNetworkUpdated(int networkId);
    }
    /**
     * Max size of scan details to cache in {@link #mScanDetailCaches}.
     */
    @VisibleForTesting
    public static final int SCAN_CACHE_ENTRIES_MAX_SIZE = 192;
    /**
     * Once the size of the scan details in the cache {@link #mScanDetailCaches} exceeds
     * {@link #SCAN_CACHE_ENTRIES_MAX_SIZE}, trim it down to this value so that we have some
     * buffer time before the next eviction.
     */
    @VisibleForTesting
    public static final int SCAN_CACHE_ENTRIES_TRIM_SIZE = 128;
    /**
     * Link networks only if they have less than this number of scan cache entries.
     */
    @VisibleForTesting
    public static final int LINK_CONFIGURATION_MAX_SCAN_CACHE_ENTRIES = 6;
    /**
     * Link networks only if the bssid in scan results for the networks match in the first
     * 16 ASCII chars in the bssid string. For example = "af:de:56;34:15:7"
     */
    @VisibleForTesting
    public static final int LINK_CONFIGURATION_BSSID_MATCH_LENGTH = 16;
    /**
     * Flags to be passed in for |canModifyNetwork| to decide if the change is minor and can
     * bypass the lockdown checks.
     */
    private static final boolean ALLOW_LOCKDOWN_CHECK_BYPASS = true;
    private static final boolean DISALLOW_LOCKDOWN_CHECK_BYPASS = false;
    /**
     * Log tag for this class.
     */
    private static final String TAG = "WifiConfigManager";
    /**
     * Maximum age of scan results that can be used for averaging out RSSI value.
     */
    private static final int SCAN_RESULT_MAXIMUM_AGE_MS = 40000;
    /**
     * General sorting algorithm of all networks for scanning purposes:
     * Place the configurations in descending order of their |numAssociation| values. If networks
     * have the same |numAssociation|, place the configurations with
     * |lastSeenInQualifiedNetworkSelection| set first.
     */
    private static final WifiConfigurationUtil.WifiConfigurationComparator sScanListComparator =
            new WifiConfigurationUtil.WifiConfigurationComparator() {
                @Override
                public int compareNetworksWithSameStatus(WifiConfiguration a, WifiConfiguration b) {
                    if (a.numAssociation != b.numAssociation) {
                        return Long.compare(b.numAssociation, a.numAssociation);
                    } else {
                        boolean isConfigALastSeen =
                                a.getNetworkSelectionStatus()
                                        .getSeenInLastQualifiedNetworkSelection();
                        boolean isConfigBLastSeen =
                                b.getNetworkSelectionStatus()
                                        .getSeenInLastQualifiedNetworkSelection();
                        return Boolean.compare(isConfigBLastSeen, isConfigALastSeen);
                    }
                }
            };

    /**
     * List of external dependencies for WifiConfigManager.
     */
    private final Context mContext;
    private final Clock mClock;
    private final UserManager mUserManager;
    private final BackupManagerProxy mBackupManagerProxy;
    private final TelephonyManager mTelephonyManager;
    private final WifiKeyStore mWifiKeyStore;
    private final WifiConfigStore mWifiConfigStore;
    private final WifiConfigStoreLegacy mWifiConfigStoreLegacy;
    private final WifiPermissionsUtil mWifiPermissionsUtil;
    private final WifiPermissionsWrapper mWifiPermissionsWrapper;
    /**
     * Local log used for debugging any WifiConfigManager issues.
     */
    private final LocalLog mLocalLog =
            new LocalLog(ActivityManager.isLowRamDeviceStatic() ? 128 : 256);
    /**
     * Map of configured networks with network id as the key.
     */
    private final ConfigurationMap mConfiguredNetworks;
    /**
     * Stores a map of NetworkId to ScanDetailCache.
     */
    private final Map<Integer, ScanDetailCache> mScanDetailCaches;
    /**
     * Framework keeps a list of ephemeral SSIDs that where deleted by user,
     * so as, framework knows not to autoconnect 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.
     */
    private final Set<String> mDeletedEphemeralSSIDs;
    /**
     * Flag to indicate if only networks with the same psk should be linked.
     * TODO(b/30706406): Remove this flag if unused.
     */
    private final boolean mOnlyLinkSameCredentialConfigurations;
    /**
     * Number of channels to scan for during partial scans initiated while connected.
     */
    private final int mMaxNumActiveChannelsForPartialScans;
    /**
     * Verbose logging flag. Toggled by developer options.
     */
    private boolean mVerboseLoggingEnabled = false;
    /**
     * Current logged in user ID.
     */
    private int mCurrentUserId = UserHandle.USER_SYSTEM;
    /**
     * Flag to indicate that the new user's store has not yet been read since user switch.
     * Initialize this flag to |true| to trigger a read on the first user unlock after
     * bootup.
     */
    private boolean mPendingUnlockStoreRead = true;
    /**
     * Flag to indicate if we have performed a read from store at all. This is used to gate
     * any user unlock/switch operations until we read the store (Will happen if wifi is disabled
     * when user updates from N to O).
     */
    private boolean mPendingStoreRead = true;
    /**
     * Flag to indicate if the user unlock was deferred until the store load occurs.
     */
    private boolean mDeferredUserUnlockRead = false;
    /**
     * This is keeping track of the next network ID to be assigned. Any new networks will be
     * assigned |mNextNetworkId| as network ID.
     */
    private int mNextNetworkId = 0;
    /**
     * UID of system UI. This uid is allowed to modify network configurations regardless of which
     * user is logged in.
     */
    private int mSystemUiUid = -1;
    /**
     * This is used to remember which network was selected successfully last by an app. This is set
     * when an app invokes {@link #enableNetwork(int, boolean, int)} with |disableOthers| flag set.
     * This is the only way for an app to request connection to a specific network using the
     * {@link WifiManager} API's.
     */
    private int mLastSelectedNetworkId = WifiConfiguration.INVALID_NETWORK_ID;
    private long mLastSelectedTimeStamp =
            WifiConfiguration.NetworkSelectionStatus.INVALID_NETWORK_SELECTION_DISABLE_TIMESTAMP;

    // Store data for network list and deleted ephemeral SSID list.  Used for serializing
    // parsing data to/from the config store.
    private final NetworkListStoreData mNetworkListStoreData;
    private final DeletedEphemeralSsidsStoreData mDeletedEphemeralSsidsStoreData;

    // Store the saved network update listener.
    private OnSavedNetworkUpdateListener mListener = null;

    /**
     * Create new instance of WifiConfigManager.
     */
    WifiConfigManager(
            Context context, Clock clock, UserManager userManager,
            TelephonyManager telephonyManager, WifiKeyStore wifiKeyStore,
            WifiConfigStore wifiConfigStore, WifiConfigStoreLegacy wifiConfigStoreLegacy,
            WifiPermissionsUtil wifiPermissionsUtil,
            WifiPermissionsWrapper wifiPermissionsWrapper,
            NetworkListStoreData networkListStoreData,
            DeletedEphemeralSsidsStoreData deletedEphemeralSsidsStoreData) {
        mContext = context;
        mClock = clock;
        mUserManager = userManager;
        mBackupManagerProxy = new BackupManagerProxy();
        mTelephonyManager = telephonyManager;
        mWifiKeyStore = wifiKeyStore;
        mWifiConfigStore = wifiConfigStore;
        mWifiConfigStoreLegacy = wifiConfigStoreLegacy;
        mWifiPermissionsUtil = wifiPermissionsUtil;
        mWifiPermissionsWrapper = wifiPermissionsWrapper;

        mConfiguredNetworks = new ConfigurationMap(userManager);
        mScanDetailCaches = new HashMap<>(16, 0.75f);
        mDeletedEphemeralSSIDs = new HashSet<>();

        // Register store data for network list and deleted ephemeral SSIDs.
        mNetworkListStoreData = networkListStoreData;
        mDeletedEphemeralSsidsStoreData = deletedEphemeralSsidsStoreData;
        mWifiConfigStore.registerStoreData(mNetworkListStoreData);
        mWifiConfigStore.registerStoreData(mDeletedEphemeralSsidsStoreData);

        mOnlyLinkSameCredentialConfigurations = mContext.getResources().getBoolean(
                R.bool.config_wifi_only_link_same_credential_configurations);
        mMaxNumActiveChannelsForPartialScans = mContext.getResources().getInteger(
                R.integer.config_wifi_framework_associated_partial_scan_max_num_active_channels);

        try {
            mSystemUiUid = mContext.getPackageManager().getPackageUidAsUser(SYSUI_PACKAGE_NAME,
                    PackageManager.MATCH_SYSTEM_ONLY, UserHandle.USER_SYSTEM);
        } catch (PackageManager.NameNotFoundException e) {
            Log.e(TAG, "Unable to resolve SystemUI's UID.");
        }
    }

    /**
     * Construct the string to be put in the |creationTime| & |updateTime| elements of
     * WifiConfiguration from the provided wall clock millis.
     *
     * @param wallClockMillis Time in milliseconds to be converted to string.
     */
    @VisibleForTesting
    public static String createDebugTimeStampString(long wallClockMillis) {
        StringBuilder sb = new StringBuilder();
        sb.append("time=");
        Calendar c = Calendar.getInstance();
        c.setTimeInMillis(wallClockMillis);
        sb.append(String.format("%tm-%td %tH:%tM:%tS.%tL", c, c, c, c, c, c));
        return sb.toString();
    }

    /**
     * Enable/disable verbose logging in WifiConfigManager & its helper classes.
     */
    public void enableVerboseLogging(int verbose) {
        if (verbose > 0) {
            mVerboseLoggingEnabled = true;
        } else {
            mVerboseLoggingEnabled = false;
        }
        mWifiConfigStore.enableVerboseLogging(mVerboseLoggingEnabled);
        mWifiKeyStore.enableVerboseLogging(mVerboseLoggingEnabled);
    }

    /**
     * Helper method to mask all passwords/keys from the provided WifiConfiguration object. This
     * is needed when the network configurations are being requested via the public WifiManager
     * API's.
     * This currently masks the following elements: psk, wepKeys & enterprise config password.
     */
    private void maskPasswordsInWifiConfiguration(WifiConfiguration configuration) {
        if (!TextUtils.isEmpty(configuration.preSharedKey)) {
            configuration.preSharedKey = PASSWORD_MASK;
        }
        if (configuration.wepKeys != null) {
            for (int i = 0; i < configuration.wepKeys.length; i++) {
                if (!TextUtils.isEmpty(configuration.wepKeys[i])) {
                    configuration.wepKeys[i] = PASSWORD_MASK;
                }
            }
        }
        if (!TextUtils.isEmpty(configuration.enterpriseConfig.getPassword())) {
            configuration.enterpriseConfig.setPassword(PASSWORD_MASK);
        }
    }

    /**
     * Helper method to create a copy of the provided internal WifiConfiguration object to be
     * passed to external modules.
     *
     * @param configuration provided WifiConfiguration object.
     * @param maskPasswords Mask passwords or not.
     * @return Copy of the WifiConfiguration object.
     */
    private WifiConfiguration createExternalWifiConfiguration(
            WifiConfiguration configuration, boolean maskPasswords) {
        WifiConfiguration network = new WifiConfiguration(configuration);
        if (maskPasswords) {
            maskPasswordsInWifiConfiguration(network);
        }
        return network;
    }

    /**
     * Fetch the list of currently configured networks maintained in WifiConfigManager.
     *
     * This retrieves a copy of the internal configurations maintained by WifiConfigManager and
     * should be used for any public interfaces.
     *
     * @param savedOnly     Retrieve only saved networks.
     * @param maskPasswords Mask passwords or not.
     * @return List of WifiConfiguration objects representing the networks.
     */
    private List<WifiConfiguration> getConfiguredNetworks(
            boolean savedOnly, boolean maskPasswords) {
        List<WifiConfiguration> networks = new ArrayList<>();
        for (WifiConfiguration config : getInternalConfiguredNetworks()) {
            if (savedOnly && config.ephemeral) {
                continue;
            }
            networks.add(createExternalWifiConfiguration(config, maskPasswords));
        }
        return networks;
    }

    /**
     * Retrieves the list of all configured networks with passwords masked.
     *
     * @return List of WifiConfiguration objects representing the networks.
     */
    public List<WifiConfiguration> getConfiguredNetworks() {
        return getConfiguredNetworks(false, true);
    }

    /**
     * Retrieves the list of all configured networks with the passwords in plaintext.
     *
     * WARNING: Don't use this to pass network configurations to external apps. Should only be
     * sent to system apps/wifi stack, when there is a need for passwords in plaintext.
     * TODO: Need to understand the current use case of this API.
     *
     * @return List of WifiConfiguration objects representing the networks.
     */
    public List<WifiConfiguration> getConfiguredNetworksWithPasswords() {
        return getConfiguredNetworks(false, false);
    }

    /**
     * Retrieves the list of all configured networks with the passwords masked.
     *
     * @return List of WifiConfiguration objects representing the networks.
     */
    public List<WifiConfiguration> getSavedNetworks() {
        return getConfiguredNetworks(true, true);
    }

    /**
     * Retrieves the configured network corresponding to the provided networkId with password
     * masked.
     *
     * @param networkId networkId of the requested network.
     * @return WifiConfiguration object if found, null otherwise.
     */
    public WifiConfiguration getConfiguredNetwork(int networkId) {
        WifiConfiguration config = getInternalConfiguredNetwork(networkId);
        if (config == null) {
            return null;
        }
        // Create a new configuration object with the passwords masked to send out to the external
        // world.
        return createExternalWifiConfiguration(config, true);
    }

    /**
     * Retrieves the configured network corresponding to the provided config key with password
     * masked.
     *
     * @param configKey configKey of the requested network.
     * @return WifiConfiguration object if found, null otherwise.
     */
    public WifiConfiguration getConfiguredNetwork(String configKey) {
        WifiConfiguration config = getInternalConfiguredNetwork(configKey);
        if (config == null) {
            return null;
        }
        // Create a new configuration object with the passwords masked to send out to the external
        // world.
        return createExternalWifiConfiguration(config, true);
    }

    /**
     * Retrieves the configured network corresponding to the provided networkId with password
     * in plaintext.
     *
     * WARNING: Don't use this to pass network configurations to external apps. Should only be
     * sent to system apps/wifi stack, when there is a need for passwords in plaintext.
     *
     * @param networkId networkId of the requested network.
     * @return WifiConfiguration object if found, null otherwise.
     */
    public WifiConfiguration getConfiguredNetworkWithPassword(int networkId) {
        WifiConfiguration config = getInternalConfiguredNetwork(networkId);
        if (config == null) {
            return null;
        }
        // Create a new configuration object without the passwords masked to send out to the
        // external world.
        return createExternalWifiConfiguration(config, false);
    }

    /**
     * Helper method to retrieve all the internal WifiConfiguration objects corresponding to all
     * the networks in our database.
     */
    private Collection<WifiConfiguration> getInternalConfiguredNetworks() {
        return mConfiguredNetworks.valuesForCurrentUser();
    }

    /**
     * Helper method to retrieve the internal WifiConfiguration object corresponding to the
     * provided configuration in our database.
     * This first attempts to find the network using the provided network ID in configuration,
     * else it attempts to find a matching configuration using the configKey.
     */
    private WifiConfiguration getInternalConfiguredNetwork(WifiConfiguration config) {
        WifiConfiguration internalConfig = mConfiguredNetworks.getForCurrentUser(config.networkId);
        if (internalConfig != null) {
            return internalConfig;
        }
        internalConfig = mConfiguredNetworks.getByConfigKeyForCurrentUser(config.configKey());
        if (internalConfig == null) {
            Log.e(TAG, "Cannot find network with networkId " + config.networkId
                    + " or configKey " + config.configKey());
        }
        return internalConfig;
    }

    /**
     * Helper method to retrieve the internal WifiConfiguration object corresponding to the
     * provided network ID in our database.
     */
    private WifiConfiguration getInternalConfiguredNetwork(int networkId) {
        if (networkId == WifiConfiguration.INVALID_NETWORK_ID) {
            Log.w(TAG, "Looking up network with invalid networkId -1");
            return null;
        }
        WifiConfiguration internalConfig = mConfiguredNetworks.getForCurrentUser(networkId);
        if (internalConfig == null) {
            Log.e(TAG, "Cannot find network with networkId " + networkId);
        }
        return internalConfig;
    }

    /**
     * Helper method to retrieve the internal WifiConfiguration object corresponding to the
     * provided configKey in our database.
     */
    private WifiConfiguration getInternalConfiguredNetwork(String configKey) {
        WifiConfiguration internalConfig =
                mConfiguredNetworks.getByConfigKeyForCurrentUser(configKey);
        if (internalConfig == null) {
            Log.e(TAG, "Cannot find network with configKey " + configKey);
        }
        return internalConfig;
    }

    /**
     * Method to send out the configured networks change broadcast when a single network
     * configuration is changed.
     *
     * @param network WifiConfiguration corresponding to the network that was 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 sendConfiguredNetworkChangedBroadcast(
            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);
        // Create a new WifiConfiguration with passwords masked before we send it out.
        WifiConfiguration broadcastNetwork = new WifiConfiguration(network);
        maskPasswordsInWifiConfiguration(broadcastNetwork);
        intent.putExtra(WifiManager.EXTRA_WIFI_CONFIGURATION, broadcastNetwork);
        intent.putExtra(WifiManager.EXTRA_CHANGE_REASON, reason);
        mContext.sendBroadcastAsUserMultiplePermissions(
                intent,
                UserHandle.ALL,
                new String[]{
                        android.Manifest.permission.ACCESS_WIFI_STATE,
                        android.Manifest.permission.ACCESS_FINE_LOCATION,
                });
    }

    /**
     * Method to send out the configured networks change broadcast when multiple network
     * configurations are changed.
     */
    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);
    }

    /**
     * Checks if |uid| has permission to modify the provided configuration.
     *
     * @param config         WifiConfiguration object corresponding to the network to be modified.
     * @param uid            UID of the app requesting the modification.
     * @param ignoreLockdown Ignore the configuration lockdown checks for connection attempts.
     */
    private boolean canModifyNetwork(WifiConfiguration config, int uid, boolean ignoreLockdown) {
        // Passpoint configurations are generated and managed by PasspointManager. They can be
        // added by either PasspointNetworkEvaluator (for auto connection) or Settings app
        // (for manual connection), and need to be removed once the connection is completed.
        // Since it is "owned" by us, so always allow us to modify them.
        if (config.isPasspoint() && uid == Process.WIFI_UID) {
            return true;
        }

        // EAP-SIM/AKA/AKA' network needs framework to update the anonymous identity provided
        // by authenticator back to the WifiConfiguration object.
        // Since it is "owned" by us, so always allow us to modify them.
        if (config.enterpriseConfig != null
                && uid == Process.WIFI_UID
                && TelephonyUtil.isSimEapMethod(config.enterpriseConfig.getEapMethod())) {
            return true;
        }

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

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

        // If |uid| corresponds to the device owner, allow all modifications.
        if (isUidDeviceOwner) {
            return true;
        }

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

        // Check if the |uid| holds the |OVERRIDE_CONFIG_WIFI| permission if the caller asks us to
        // bypass the lockdown checks.
        if (ignoreLockdown) {
            return mWifiPermissionsUtil.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) {
            Log.w(TAG, "Error retrieving DPMI service.");
            return false;
        }

        // WiFi config lockdown related logic. At this point we know uid is NOT a Device Owner.
        final boolean isConfigEligibleForLockdown = dpmi != null && dpmi.isActiveAdminWithPolicy(
                config.creatorUid, DeviceAdminInfo.USES_POLICY_DEVICE_OWNER);
        if (!isConfigEligibleForLockdown) {
            return isCreator || mWifiPermissionsUtil.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 && mWifiPermissionsUtil.checkConfigOverridePermission(uid);
    }

    /**
     * Method to check if the provided UID belongs to the current foreground user or some other
     * app (only SysUI today) running on behalf of the user.
     * This is used to prevent any background user apps from modifying network configurations.
     *
     * @param uid uid of the app.
     * @return true if the UID belongs to the current foreground app or SystemUI, false otherwise.
     */
    private boolean doesUidBelongToCurrentUser(int uid) {
        return (WifiConfigurationUtil.doesUidBelongToAnyProfile(
                uid, mUserManager.getProfiles(mCurrentUserId)) || (uid == mSystemUiUid));
    }

    /**
     * Copy over public elements from an external WifiConfiguration object to the internal
     * configuration object if element has been set in the provided external WifiConfiguration.
     * The only exception is the hidden |IpConfiguration| parameters, these need to be copied over
     * for every update.
     *
     * This method updates all elements that are common to both network addition & update.
     * The following fields of {@link WifiConfiguration} are not copied from external configs:
     *  > networkId - These are allocated by Wi-Fi stack internally for any new configurations.
     *  > status - The status needs to be explicitly updated using
     *             {@link WifiManager#enableNetwork(int, boolean)} or
     *             {@link WifiManager#disableNetwork(int)}.
     *
     * @param internalConfig WifiConfiguration object in our internal map.
     * @param externalConfig WifiConfiguration object provided from the external API.
     */
    private void mergeWithInternalWifiConfiguration(
            WifiConfiguration internalConfig, WifiConfiguration externalConfig) {
        if (externalConfig.SSID != null) {
            internalConfig.SSID = externalConfig.SSID;
        }
        if (externalConfig.BSSID != null) {
            internalConfig.BSSID = externalConfig.BSSID.toLowerCase();
        }
        internalConfig.hiddenSSID = externalConfig.hiddenSSID;
        if (externalConfig.preSharedKey != null
                && !externalConfig.preSharedKey.equals(PASSWORD_MASK)) {
            internalConfig.preSharedKey = externalConfig.preSharedKey;
        }
        // Modify only wep keys are present in the provided configuration. This is a little tricky
        // because there is no easy way to tell if the app is actually trying to null out the
        // existing keys or not.
        if (externalConfig.wepKeys != null) {
            boolean hasWepKey = false;
            for (int i = 0; i < internalConfig.wepKeys.length; i++) {
                if (externalConfig.wepKeys[i] != null
                        && !externalConfig.wepKeys[i].equals(PASSWORD_MASK)) {
                    internalConfig.wepKeys[i] = externalConfig.wepKeys[i];
                    hasWepKey = true;
                }
            }
            if (hasWepKey) {
                internalConfig.wepTxKeyIndex = externalConfig.wepTxKeyIndex;
            }
        }
        if (externalConfig.FQDN != null) {
            internalConfig.FQDN = externalConfig.FQDN;
        }
        if (externalConfig.providerFriendlyName != null) {
            internalConfig.providerFriendlyName = externalConfig.providerFriendlyName;
        }
        if (externalConfig.roamingConsortiumIds != null) {
            internalConfig.roamingConsortiumIds = externalConfig.roamingConsortiumIds.clone();
        }

        // Copy over all the auth/protocol/key mgmt parameters if set.
        if (externalConfig.allowedAuthAlgorithms != null
                && !externalConfig.allowedAuthAlgorithms.isEmpty()) {
            internalConfig.allowedAuthAlgorithms =
                    (BitSet) externalConfig.allowedAuthAlgorithms.clone();
        }
        if (externalConfig.allowedProtocols != null
                && !externalConfig.allowedProtocols.isEmpty()) {
            internalConfig.allowedProtocols = (BitSet) externalConfig.allowedProtocols.clone();
        }
        if (externalConfig.allowedKeyManagement != null
                && !externalConfig.allowedKeyManagement.isEmpty()) {
            internalConfig.allowedKeyManagement =
                    (BitSet) externalConfig.allowedKeyManagement.clone();
        }
        if (externalConfig.allowedPairwiseCiphers != null
                && !externalConfig.allowedPairwiseCiphers.isEmpty()) {
            internalConfig.allowedPairwiseCiphers =
                    (BitSet) externalConfig.allowedPairwiseCiphers.clone();
        }
        if (externalConfig.allowedGroupCiphers != null
                && !externalConfig.allowedGroupCiphers.isEmpty()) {
            internalConfig.allowedGroupCiphers =
                    (BitSet) externalConfig.allowedGroupCiphers.clone();
        }

        // Copy over the |IpConfiguration| parameters if set.
        if (externalConfig.getIpConfiguration() != null) {
            IpConfiguration.IpAssignment ipAssignment = externalConfig.getIpAssignment();
            if (ipAssignment != IpConfiguration.IpAssignment.UNASSIGNED) {
                internalConfig.setIpAssignment(ipAssignment);
                if (ipAssignment == IpConfiguration.IpAssignment.STATIC) {
                    internalConfig.setStaticIpConfiguration(
                            new StaticIpConfiguration(externalConfig.getStaticIpConfiguration()));
                }
            }
            IpConfiguration.ProxySettings proxySettings = externalConfig.getProxySettings();
            if (proxySettings != IpConfiguration.ProxySettings.UNASSIGNED) {
                internalConfig.setProxySettings(proxySettings);
                if (proxySettings == IpConfiguration.ProxySettings.PAC
                        || proxySettings == IpConfiguration.ProxySettings.STATIC) {
                    internalConfig.setHttpProxy(new ProxyInfo(externalConfig.getHttpProxy()));
                }
            }
        }

        // Copy over the |WifiEnterpriseConfig| parameters if set.
        if (externalConfig.enterpriseConfig != null) {
            internalConfig.enterpriseConfig.copyFromExternal(
                    externalConfig.enterpriseConfig, PASSWORD_MASK);
        }
    }

    /**
     * Set all the exposed defaults in the newly created WifiConfiguration object.
     * These fields have a default value advertised in our public documentation. The only exception
     * is the hidden |IpConfiguration| parameters, these have a default value even though they're
     * hidden.
     *
     * @param configuration provided WifiConfiguration object.
     */
    private void setDefaultsInWifiConfiguration(WifiConfiguration configuration) {
        configuration.allowedAuthAlgorithms.set(WifiConfiguration.AuthAlgorithm.OPEN);

        configuration.allowedProtocols.set(WifiConfiguration.Protocol.RSN);
        configuration.allowedProtocols.set(WifiConfiguration.Protocol.WPA);

        configuration.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.WPA_PSK);
        configuration.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.WPA_EAP);

        configuration.allowedPairwiseCiphers.set(WifiConfiguration.PairwiseCipher.CCMP);
        configuration.allowedPairwiseCiphers.set(WifiConfiguration.PairwiseCipher.TKIP);

        configuration.allowedGroupCiphers.set(WifiConfiguration.GroupCipher.CCMP);
        configuration.allowedGroupCiphers.set(WifiConfiguration.GroupCipher.TKIP);
        configuration.allowedGroupCiphers.set(WifiConfiguration.GroupCipher.WEP40);
        configuration.allowedGroupCiphers.set(WifiConfiguration.GroupCipher.WEP104);

        configuration.setIpAssignment(IpConfiguration.IpAssignment.DHCP);
        configuration.setProxySettings(IpConfiguration.ProxySettings.NONE);

        configuration.status = WifiConfiguration.Status.DISABLED;
        configuration.getNetworkSelectionStatus().setNetworkSelectionStatus(
                NetworkSelectionStatus.NETWORK_SELECTION_PERMANENTLY_DISABLED);
    }

    /**
     * Create a new internal WifiConfiguration object by copying over parameters from the provided
     * external configuration and set defaults for the appropriate parameters.
     *
     * @param externalConfig WifiConfiguration object provided from the external API.
     * @return New WifiConfiguration object with parameters merged from the provided external
     * configuration.
     */
    private WifiConfiguration createNewInternalWifiConfigurationFromExternal(
            WifiConfiguration externalConfig, int uid) {
        WifiConfiguration newInternalConfig = new WifiConfiguration();

        // First allocate a new network ID for the configuration.
        newInternalConfig.networkId = mNextNetworkId++;

        // First set defaults in the new configuration created.
        setDefaultsInWifiConfiguration(newInternalConfig);

        // Copy over all the public elements from the provided configuration.
        mergeWithInternalWifiConfiguration(newInternalConfig, externalConfig);

        // Copy over the hidden configuration parameters. These are the only parameters used by
        // system apps to indicate some property about the network being added.
        // These are only copied over for network additions and ignored for network updates.
        newInternalConfig.requirePMF = externalConfig.requirePMF;
        newInternalConfig.noInternetAccessExpected = externalConfig.noInternetAccessExpected;
        newInternalConfig.ephemeral = externalConfig.ephemeral;
        newInternalConfig.meteredHint = externalConfig.meteredHint;
        newInternalConfig.useExternalScores = externalConfig.useExternalScores;
        newInternalConfig.shared = externalConfig.shared;

        // Add debug information for network addition.
        newInternalConfig.creatorUid = newInternalConfig.lastUpdateUid = uid;
        newInternalConfig.creatorName = newInternalConfig.lastUpdateName =
                mContext.getPackageManager().getNameForUid(uid);
        newInternalConfig.creationTime = newInternalConfig.updateTime =
                createDebugTimeStampString(mClock.getWallClockMillis());

        return newInternalConfig;
    }

    /**
     * Create a new internal WifiConfiguration object by copying over parameters from the provided
     * external configuration to a copy of the existing internal WifiConfiguration object.
     *
     * @param internalConfig WifiConfiguration object in our internal map.
     * @param externalConfig WifiConfiguration object provided from the external API.
     * @return Copy of existing WifiConfiguration object with parameters merged from the provided
     * configuration.
     */
    private WifiConfiguration updateExistingInternalWifiConfigurationFromExternal(
            WifiConfiguration internalConfig, WifiConfiguration externalConfig, int uid) {
        WifiConfiguration newInternalConfig = new WifiConfiguration(internalConfig);

        // Copy over all the public elements from the provided configuration.
        mergeWithInternalWifiConfiguration(newInternalConfig, externalConfig);

        // Add debug information for network update.
        newInternalConfig.lastUpdateUid = uid;
        newInternalConfig.lastUpdateName = mContext.getPackageManager().getNameForUid(uid);
        newInternalConfig.updateTime = createDebugTimeStampString(mClock.getWallClockMillis());

        return newInternalConfig;
    }

    /**
     * Add a network or update a network configuration to our database.
     * If the supplied networkId is INVALID_NETWORK_ID, we create a new empty
     * network configuration. Otherwise, the networkId should refer to an existing configuration.
     *
     * @param config provided WifiConfiguration object.
     * @param uid    UID of the app requesting the network addition/deletion.
     * @return NetworkUpdateResult object representing status of the update.
     */
    private NetworkUpdateResult addOrUpdateNetworkInternal(WifiConfiguration config, int uid) {
        if (mVerboseLoggingEnabled) {
            Log.v(TAG, "Adding/Updating network " + config.getPrintableSsid());
        }
        WifiConfiguration newInternalConfig = null;

        // First check if we already have a network with the provided network id or configKey.
        WifiConfiguration existingInternalConfig = getInternalConfiguredNetwork(config);
        // No existing network found. So, potentially a network add.
        if (existingInternalConfig == null) {
            newInternalConfig = createNewInternalWifiConfigurationFromExternal(config, uid);
            // Since the original config provided may have had an empty
            // {@link WifiConfiguration#allowedKeyMgmt} field, check again if we already have a
            // network with the the same configkey.
            existingInternalConfig = getInternalConfiguredNetwork(newInternalConfig.configKey());
        }
        // Existing network found. So, a network update.
        if (existingInternalConfig != null) {
            // Check for the app's permission before we let it update this network.
            if (!canModifyNetwork(existingInternalConfig, uid, DISALLOW_LOCKDOWN_CHECK_BYPASS)) {
                Log.e(TAG, "UID " + uid + " does not have permission to update configuration "
                        + config.configKey());
                return new NetworkUpdateResult(WifiConfiguration.INVALID_NETWORK_ID);
            }
            newInternalConfig =
                    updateExistingInternalWifiConfigurationFromExternal(
                            existingInternalConfig, config, uid);
        }

        // Only add networks with proxy settings if the user has permission to
        if (WifiConfigurationUtil.hasProxyChanged(existingInternalConfig, newInternalConfig)
                && !canModifyProxySettings(uid)) {
            Log.e(TAG, "UID " + uid + " does not have permission to modify proxy Settings "
                    + config.configKey() + ". Must have OVERRIDE_WIFI_CONFIG,"
                    + " or be device or profile owner.");
            return new NetworkUpdateResult(WifiConfiguration.INVALID_NETWORK_ID);
        }

        // Update the keys for non-Passpoint enterprise networks.  For Passpoint, the certificates
        // and keys are installed at the time the provider is installed.
        if (config.enterpriseConfig != null
                && config.enterpriseConfig.getEapMethod() != WifiEnterpriseConfig.Eap.NONE
                && !config.isPasspoint()) {
            if (!(mWifiKeyStore.updateNetworkKeys(newInternalConfig, existingInternalConfig))) {
                return new NetworkUpdateResult(WifiConfiguration.INVALID_NETWORK_ID);
            }
        }

        boolean newNetwork = (existingInternalConfig == null);
        // This is needed to inform IpManager about any IP configuration changes.
        boolean hasIpChanged =
                newNetwork || WifiConfigurationUtil.hasIpChanged(
                        existingInternalConfig, newInternalConfig);
        boolean hasProxyChanged =
                newNetwork || WifiConfigurationUtil.hasProxyChanged(
                        existingInternalConfig, newInternalConfig);
        // Reset the |hasEverConnected| flag if the credential parameters changed in this update.
        boolean hasCredentialChanged =
                newNetwork || WifiConfigurationUtil.hasCredentialChanged(
                        existingInternalConfig, newInternalConfig);
        if (hasCredentialChanged) {
            newInternalConfig.getNetworkSelectionStatus().setHasEverConnected(false);
        }

        // Add it to our internal map. This will replace any existing network configuration for
        // updates.
        mConfiguredNetworks.put(newInternalConfig);

        if (mDeletedEphemeralSSIDs.remove(config.SSID)) {
            if (mVerboseLoggingEnabled) {
                Log.v(TAG, "Removed from ephemeral blacklist: " + config.SSID);
            }
        }

        // Stage the backup of the SettingsProvider package which backs this up.
        mBackupManagerProxy.notifyDataChanged();

        NetworkUpdateResult result =
                new NetworkUpdateResult(hasIpChanged, hasProxyChanged, hasCredentialChanged);
        result.setIsNewNetwork(newNetwork);
        result.setNetworkId(newInternalConfig.networkId);

        localLog("addOrUpdateNetworkInternal: added/updated config."
                + " netId=" + newInternalConfig.networkId
                + " configKey=" + newInternalConfig.configKey()
                + " uid=" + Integer.toString(newInternalConfig.creatorUid)
                + " name=" + newInternalConfig.creatorName);
        return result;
    }

    /**
     * Add a network or update a network configuration to our database.
     * If the supplied networkId is INVALID_NETWORK_ID, we create a new empty
     * network configuration. Otherwise, the networkId should refer to an existing configuration.
     *
     * @param config provided WifiConfiguration object.
     * @param uid    UID of the app requesting the network addition/modification.
     * @return NetworkUpdateResult object representing status of the update.
     */
    public NetworkUpdateResult addOrUpdateNetwork(WifiConfiguration config, int uid) {
        if (!doesUidBelongToCurrentUser(uid)) {
            Log.e(TAG, "UID " + uid + " not visible to the current user");
            return new NetworkUpdateResult(WifiConfiguration.INVALID_NETWORK_ID);
        }
        if (config == null) {
            Log.e(TAG, "Cannot add/update network with null config");
            return new NetworkUpdateResult(WifiConfiguration.INVALID_NETWORK_ID);
        }
        if (mPendingStoreRead) {
            Log.e(TAG, "Cannot add/update network before store is read!");
            return new NetworkUpdateResult(WifiConfiguration.INVALID_NETWORK_ID);
        }
        NetworkUpdateResult result = addOrUpdateNetworkInternal(config, uid);
        if (!result.isSuccess()) {
            Log.e(TAG, "Failed to add/update network " + config.getPrintableSsid());
            return result;
        }
        WifiConfiguration newConfig = getInternalConfiguredNetwork(result.getNetworkId());
        sendConfiguredNetworkChangedBroadcast(
                newConfig,
                result.isNewNetwork()
                        ? WifiManager.CHANGE_REASON_ADDED
                        : WifiManager.CHANGE_REASON_CONFIG_CHANGE);
        // Unless the added network is ephemeral or Passpoint, persist the network update/addition.
        if (!config.ephemeral && !config.isPasspoint()) {
            saveToStore(true);
            if (mListener != null) {
                if (result.isNewNetwork()) {
                    mListener.onSavedNetworkAdded(newConfig.networkId);
                } else {
                    mListener.onSavedNetworkUpdated(newConfig.networkId);
                }
            }
        }
        return result;
    }

    /**
     * Removes the specified network configuration from our database.
     *
     * @param config provided WifiConfiguration object.
     * @return true if successful, false otherwise.
     */
    private boolean removeNetworkInternal(WifiConfiguration config) {
        if (mVerboseLoggingEnabled) {
            Log.v(TAG, "Removing network " + config.getPrintableSsid());
        }
        // Remove any associated enterprise keys for non-Passpoint networks.
        if (!config.isPasspoint() && config.enterpriseConfig != null
                && config.enterpriseConfig.getEapMethod() != WifiEnterpriseConfig.Eap.NONE) {
            mWifiKeyStore.removeKeys(config.enterpriseConfig);
        }

        removeConnectChoiceFromAllNetworks(config.configKey());
        mConfiguredNetworks.remove(config.networkId);
        mScanDetailCaches.remove(config.networkId);
        // Stage the backup of the SettingsProvider package which backs this up.
        mBackupManagerProxy.notifyDataChanged();

        localLog("removeNetworkInternal: removed config."
                + " netId=" + config.networkId
                + " configKey=" + config.configKey());
        return true;
    }

    /**
     * Removes the specified network configuration from our database.
     *
     * @param networkId network ID of the provided network.
     * @param uid       UID of the app requesting the network deletion.
     * @return true if successful, false otherwise.
     */
    public boolean removeNetwork(int networkId, int uid) {
        if (!doesUidBelongToCurrentUser(uid)) {
            Log.e(TAG, "UID " + uid + " not visible to the current user");
            return false;
        }
        WifiConfiguration config = getInternalConfiguredNetwork(networkId);
        if (config == null) {
            return false;
        }
        if (!canModifyNetwork(config, uid, DISALLOW_LOCKDOWN_CHECK_BYPASS)) {
            Log.e(TAG, "UID " + uid + " does not have permission to delete configuration "
                    + config.configKey());
            return false;
        }
        if (!removeNetworkInternal(config)) {
            Log.e(TAG, "Failed to remove network " + config.getPrintableSsid());
            return false;
        }
        if (networkId == mLastSelectedNetworkId) {
            clearLastSelectedNetwork();
        }
        sendConfiguredNetworkChangedBroadcast(config, WifiManager.CHANGE_REASON_REMOVED);
        // Unless the removed network is ephemeral or Passpoint, persist the network removal.
        if (!config.ephemeral && !config.isPasspoint()) {
            saveToStore(true);
            if (mListener != null) mListener.onSavedNetworkRemoved(networkId);
        }
        return true;
    }

    /**
     * Remove all networks associated with an application.
     *
     * @param app Application info of the package of networks to remove.
     * @return the {@link Set} of networks that were removed by this call. Networks which matched
     *         but failed to remove are omitted from this set.
     */
    public Set<Integer> removeNetworksForApp(ApplicationInfo app) {
        if (app == null || app.packageName == null) {
            return Collections.<Integer>emptySet();
        }
        Log.d(TAG, "Remove all networks for app " + app);
        Set<Integer> removedNetworks = new ArraySet<>();
        WifiConfiguration[] copiedConfigs =
                mConfiguredNetworks.valuesForAllUsers().toArray(new WifiConfiguration[0]);
        for (WifiConfiguration config : copiedConfigs) {
            if (app.uid != config.creatorUid || !app.packageName.equals(config.creatorName)) {
                continue;
            }
            localLog("Removing network " + config.SSID
                    + ", application \"" + app.packageName + "\" uninstalled"
                    + " from user " + UserHandle.getUserId(app.uid));
            if (removeNetwork(config.networkId, mSystemUiUid)) {
                removedNetworks.add(config.networkId);
            }
        }
        return removedNetworks;
    }

    /**
     * Remove all networks associated with a user.
     *
     * @param userId The identifier of the user which is being removed.
     * @return the {@link Set} of networks that were removed by this call. Networks which matched
     *         but failed to remove are omitted from this set.
     */
    Set<Integer> removeNetworksForUser(int userId) {
        Log.d(TAG, "Remove all networks for user " + userId);
        Set<Integer> removedNetworks = new ArraySet<>();
        WifiConfiguration[] copiedConfigs =
                mConfiguredNetworks.valuesForAllUsers().toArray(new WifiConfiguration[0]);
        for (WifiConfiguration config : copiedConfigs) {
            if (userId != UserHandle.getUserId(config.creatorUid)) {
                continue;
            }
            localLog("Removing network " + config.SSID + ", user " + userId + " removed");
            if (removeNetwork(config.networkId, mSystemUiUid)) {
                removedNetworks.add(config.networkId);
            }
        }
        return removedNetworks;
    }

    /**
     * Helper method to mark a network enabled for network selection.
     */
    private void setNetworkSelectionEnabled(WifiConfiguration config) {
        NetworkSelectionStatus status = config.getNetworkSelectionStatus();
        status.setNetworkSelectionStatus(
                NetworkSelectionStatus.NETWORK_SELECTION_ENABLED);
        status.setDisableTime(
                NetworkSelectionStatus.INVALID_NETWORK_SELECTION_DISABLE_TIMESTAMP);
        status.setNetworkSelectionDisableReason(NetworkSelectionStatus.NETWORK_SELECTION_ENABLE);

        // Clear out all the disable reason counters.
        status.clearDisableReasonCounter();
        if (mListener != null) mListener.onSavedNetworkEnabled(config.networkId);
    }

    /**
     * Helper method to mark a network temporarily disabled for network selection.
     */
    private void setNetworkSelectionTemporarilyDisabled(
            WifiConfiguration config, int disableReason) {
        NetworkSelectionStatus status = config.getNetworkSelectionStatus();
        status.setNetworkSelectionStatus(
                NetworkSelectionStatus.NETWORK_SELECTION_TEMPORARY_DISABLED);
        // Only need a valid time filled in for temporarily disabled networks.
        status.setDisableTime(mClock.getElapsedSinceBootMillis());
        status.setNetworkSelectionDisableReason(disableReason);
        if (mListener != null) mListener.onSavedNetworkTemporarilyDisabled(config.networkId);
    }

    /**
     * Helper method to mark a network permanently disabled for network selection.
     */
    private void setNetworkSelectionPermanentlyDisabled(
            WifiConfiguration config, int disableReason) {
        NetworkSelectionStatus status = config.getNetworkSelectionStatus();
        status.setNetworkSelectionStatus(
                NetworkSelectionStatus.NETWORK_SELECTION_PERMANENTLY_DISABLED);
        status.setDisableTime(
                NetworkSelectionStatus.INVALID_NETWORK_SELECTION_DISABLE_TIMESTAMP);
        status.setNetworkSelectionDisableReason(disableReason);
        if (mListener != null) mListener.onSavedNetworkPermanentlyDisabled(config.networkId);
    }

    /**
     * Helper method to set the publicly exposed status for the network and send out the network
     * status change broadcast.
     */
    private void setNetworkStatus(WifiConfiguration config, int status) {
        config.status = status;
        sendConfiguredNetworkChangedBroadcast(config, WifiManager.CHANGE_REASON_CONFIG_CHANGE);
    }

    /**
     * Sets a network's status (both internal and public) according to the update reason and
     * its current state.
     *
     * This updates the network's {@link WifiConfiguration#mNetworkSelectionStatus} field and the
     * public {@link WifiConfiguration#status} field if the network is either enabled or
     * permanently disabled.
     *
     * @param config network to be updated.
     * @param reason reason code for update.
     * @return true if the input configuration has been updated, false otherwise.
     */
    private boolean setNetworkSelectionStatus(WifiConfiguration config, int reason) {
        NetworkSelectionStatus networkStatus = config.getNetworkSelectionStatus();
        if (reason < 0 || reason >= NetworkSelectionStatus.NETWORK_SELECTION_DISABLED_MAX) {
            Log.e(TAG, "Invalid Network disable reason " + reason);
            return false;
        }
        if (reason == NetworkSelectionStatus.NETWORK_SELECTION_ENABLE) {
            setNetworkSelectionEnabled(config);
            setNetworkStatus(config, WifiConfiguration.Status.ENABLED);
        } else if (reason < NetworkSelectionStatus.DISABLED_TLS_VERSION_MISMATCH) {
            setNetworkSelectionTemporarilyDisabled(config, reason);
        } else {
            setNetworkSelectionPermanentlyDisabled(config, reason);
            setNetworkStatus(config, WifiConfiguration.Status.DISABLED);
        }
        localLog("setNetworkSelectionStatus: configKey=" + config.configKey()
                + " networkStatus=" + networkStatus.getNetworkStatusString() + " disableReason="
                + networkStatus.getNetworkDisableReasonString() + " at="
                + createDebugTimeStampString(mClock.getWallClockMillis()));
        saveToStore(false);
        return true;
    }

    /**
     * Update a network's status (both internal and public) according to the update reason and
     * its current state.
     *
     * @param config network to be updated.
     * @param reason reason code for update.
     * @return true if the input configuration has been updated, false otherwise.
     */
    private boolean updateNetworkSelectionStatus(WifiConfiguration config, int reason) {
        NetworkSelectionStatus networkStatus = config.getNetworkSelectionStatus();
        if (reason != NetworkSelectionStatus.NETWORK_SELECTION_ENABLE) {
            networkStatus.incrementDisableReasonCounter(reason);
            // For network disable reasons, we should only update the status if we cross the
            // threshold.
            int disableReasonCounter = networkStatus.getDisableReasonCounter(reason);
            int disableReasonThreshold = NETWORK_SELECTION_DISABLE_THRESHOLD[reason];
            if (disableReasonCounter < disableReasonThreshold) {
                if (mVerboseLoggingEnabled) {
                    Log.v(TAG, "Disable counter for network " + config.getPrintableSsid()
                            + " for reason "
                            + NetworkSelectionStatus.getNetworkDisableReasonString(reason) + " is "
                            + networkStatus.getDisableReasonCounter(reason) + " and threshold is "
                            + disableReasonThreshold);
                }
                return true;
            }
        }
        return setNetworkSelectionStatus(config, reason);
    }

    /**
     * Update a network's status (both internal and public) according to the update reason and
     * its current state.
     *
     * Each network has 2 status:
     * 1. NetworkSelectionStatus: This is internal selection status of the network. This is used
     * for temporarily disabling a network for Network Selector.
     * 2. Status: This is the exposed status for a network. This is mostly set by
     * the public API's {@link WifiManager#enableNetwork(int, boolean)} &
     * {@link WifiManager#disableNetwork(int)}.
     *
     * @param networkId network ID of the network that needs the update.
     * @param reason    reason to update the network.
     * @return true if the input configuration has been updated, false otherwise.
     */
    public boolean updateNetworkSelectionStatus(int networkId, int reason) {
        WifiConfiguration config = getInternalConfiguredNetwork(networkId);
        if (config == null) {
            return false;
        }
        return updateNetworkSelectionStatus(config, reason);
    }

    /**
     * Update whether a network is currently not recommended by {@link RecommendedNetworkEvaluator}.
     *
     * @param networkId network ID of the network to be updated
     * @param notRecommended whether this network is not recommended
     * @return true if the network is updated, false otherwise
     */
    public boolean updateNetworkNotRecommended(int networkId, boolean notRecommended) {
        WifiConfiguration config = getInternalConfiguredNetwork(networkId);
        if (config == null) {
            return false;
        }

        config.getNetworkSelectionStatus().setNotRecommended(notRecommended);
        if (mVerboseLoggingEnabled) {
            localLog("updateNetworkRecommendation: configKey=" + config.configKey()
                    + " notRecommended=" + notRecommended);
        }
        saveToStore(false);
        return true;
    }

    /**
     * Attempt to re-enable a network for network selection, if this network was either:
     * a) Previously temporarily disabled, but its disable timeout has expired, or
     * b) Previously disabled because of a user switch, but is now visible to the current
     * user.
     *
     * @param config configuration for the network to be re-enabled for network selection. The
     *               network corresponding to the config must be visible to the current user.
     * @return true if the network identified by {@param config} was re-enabled for qualified
     * network selection, false otherwise.
     */
    private boolean tryEnableNetwork(WifiConfiguration config) {
        NetworkSelectionStatus networkStatus = config.getNetworkSelectionStatus();
        if (networkStatus.isNetworkTemporaryDisabled()) {
            long timeDifferenceMs =
                    mClock.getElapsedSinceBootMillis() - networkStatus.getDisableTime();
            int disableReason = networkStatus.getNetworkSelectionDisableReason();
            long disableTimeoutMs = NETWORK_SELECTION_DISABLE_TIMEOUT_MS[disableReason];
            if (timeDifferenceMs >= disableTimeoutMs) {
                return updateNetworkSelectionStatus(
                        config, NetworkSelectionStatus.NETWORK_SELECTION_ENABLE);
            }
        } else if (networkStatus.isDisabledByReason(
                NetworkSelectionStatus.DISABLED_DUE_TO_USER_SWITCH)) {
            return updateNetworkSelectionStatus(
                    config, NetworkSelectionStatus.NETWORK_SELECTION_ENABLE);
        }
        return false;
    }

    /**
     * Attempt to re-enable a network for network selection, if this network was either:
     * a) Previously temporarily disabled, but its disable timeout has expired, or
     * b) Previously disabled because of a user switch, but is now visible to the current
     * user.
     *
     * @param networkId the id of the network to be checked for possible unblock (due to timeout)
     * @return true if the network identified by {@param networkId} was re-enabled for qualified
     * network selection, false otherwise.
     */
    public boolean tryEnableNetwork(int networkId) {
        WifiConfiguration config = getInternalConfiguredNetwork(networkId);
        if (config == null) {
            return false;
        }
        return tryEnableNetwork(config);
    }

    /**
     * Enable a network using the public {@link WifiManager#enableNetwork(int, boolean)} API.
     *
     * @param networkId     network ID of the network that needs the update.
     * @param disableOthers Whether to disable all other networks or not. This is used to indicate
     *                      that the app requested connection to a specific network.
     * @param uid           uid of the app requesting the update.
     * @return true if it succeeds, false otherwise
     */
    public boolean enableNetwork(int networkId, boolean disableOthers, int uid) {
        if (mVerboseLoggingEnabled) {
            Log.v(TAG, "Enabling network " + networkId + " (disableOthers " + disableOthers + ")");
        }
        if (!doesUidBelongToCurrentUser(uid)) {
            Log.e(TAG, "UID " + uid + " not visible to the current user");
            return false;
        }
        WifiConfiguration config = getInternalConfiguredNetwork(networkId);
        if (config == null) {
            return false;
        }
        if (!canModifyNetwork(config, uid, DISALLOW_LOCKDOWN_CHECK_BYPASS)) {
            Log.e(TAG, "UID " + uid + " does not have permission to update configuration "
                    + config.configKey());
            return false;
        }
        if (!updateNetworkSelectionStatus(
                networkId, WifiConfiguration.NetworkSelectionStatus.NETWORK_SELECTION_ENABLE)) {
            return false;
        }
        if (disableOthers) {
            setLastSelectedNetwork(networkId);
        }
        saveToStore(true);
        return true;
    }

    /**
     * Disable a network using the public {@link WifiManager#disableNetwork(int)} API.
     *
     * @param networkId network ID of the network that needs the update.
     * @param uid       uid of the app requesting the update.
     * @return true if it succeeds, false otherwise
     */
    public boolean disableNetwork(int networkId, int uid) {
        if (mVerboseLoggingEnabled) {
            Log.v(TAG, "Disabling network " + networkId);
        }
        if (!doesUidBelongToCurrentUser(uid)) {
            Log.e(TAG, "UID " + uid + " not visible to the current user");
            return false;
        }
        WifiConfiguration config = getInternalConfiguredNetwork(networkId);
        if (config == null) {
            return false;
        }
        if (!canModifyNetwork(config, uid, DISALLOW_LOCKDOWN_CHECK_BYPASS)) {
            Log.e(TAG, "UID " + uid + " does not have permission to update configuration "
                    + config.configKey());
            return false;
        }
        if (!updateNetworkSelectionStatus(
                networkId, NetworkSelectionStatus.DISABLED_BY_WIFI_MANAGER)) {
            return false;
        }
        if (networkId == mLastSelectedNetworkId) {
            clearLastSelectedNetwork();
        }
        saveToStore(true);
        return true;
    }

    /**
     * Checks if the |uid| has the necessary permission to force a connection to a network
     * and updates the last connected UID for the provided configuration.
     *
     * @param networkId network ID corresponding to the network.
     * @param uid       uid of the app requesting the connection.
     * @return true if |uid| has the necessary permission to trigger explicit connection to the
     * network, false otherwise.
     * Note: This returns true only for the system settings/sysui app which holds the
     * {@link android.Manifest.permission#OVERRIDE_WIFI_CONFIG} permission. We don't want to let
     * any other app force connection to a network.
     */
    public boolean checkAndUpdateLastConnectUid(int networkId, int uid) {
        if (mVerboseLoggingEnabled) {
            Log.v(TAG, "Update network last connect UID for " + networkId);
        }
        if (!doesUidBelongToCurrentUser(uid)) {
            Log.e(TAG, "UID " + uid + " not visible to the current user");
            return false;
        }
        WifiConfiguration config = getInternalConfiguredNetwork(networkId);
        if (config == null) {
            return false;
        }
        if (!canModifyNetwork(config, uid, ALLOW_LOCKDOWN_CHECK_BYPASS)) {
            Log.e(TAG, "UID " + uid + " does not have permission to update configuration "
                    + config.configKey());
            return false;
        }
        config.lastConnectUid = uid;
        return true;
    }

    /**
     * Updates a network configuration after a successful connection to it.
     *
     * This method updates the following WifiConfiguration elements:
     * 1. Set the |lastConnected| timestamp.
     * 2. Increment |numAssociation| counter.
     * 3. Clear the disable reason counters in the associated |NetworkSelectionStatus|.
     * 4. Set the hasEverConnected| flag in the associated |NetworkSelectionStatus|.
     * 5. Sets the status of network as |CURRENT|.
     *
     * @param networkId network ID corresponding to the network.
     * @return true if the network was found, false otherwise.
     */
    public boolean updateNetworkAfterConnect(int networkId) {
        if (mVerboseLoggingEnabled) {
            Log.v(TAG, "Update network after connect for " + networkId);
        }
        WifiConfiguration config = getInternalConfiguredNetwork(networkId);
        if (config == null) {
            return false;
        }
        config.lastConnected = mClock.getWallClockMillis();
        config.numAssociation++;
        config.getNetworkSelectionStatus().clearDisableReasonCounter();
        config.getNetworkSelectionStatus().setHasEverConnected(true);
        setNetworkStatus(config, WifiConfiguration.Status.CURRENT);
        saveToStore(false);
        return true;
    }

    /**
     * Updates a network configuration after disconnection from it.
     *
     * This method updates the following WifiConfiguration elements:
     * 1. Set the |lastDisConnected| timestamp.
     * 2. Sets the status of network back to |ENABLED|.
     *
     * @param networkId network ID corresponding to the network.
     * @return true if the network was found, false otherwise.
     */
    public boolean updateNetworkAfterDisconnect(int networkId) {
        if (mVerboseLoggingEnabled) {
            Log.v(TAG, "Update network after disconnect for " + networkId);
        }
        WifiConfiguration config = getInternalConfiguredNetwork(networkId);
        if (config == null) {
            return false;
        }
        config.lastDisconnected = mClock.getWallClockMillis();
        // If the network hasn't been disabled, mark it back as
        // enabled after disconnection.
        if (config.status == WifiConfiguration.Status.CURRENT) {
            setNetworkStatus(config, WifiConfiguration.Status.ENABLED);
        }
        saveToStore(false);
        return true;
    }

    /**
     * Set default GW MAC address for the provided network.
     *
     * @param networkId  network ID corresponding to the network.
     * @param macAddress MAC address of the gateway to be set.
     * @return true if the network was found, false otherwise.
     */
    public boolean setNetworkDefaultGwMacAddress(int networkId, String macAddress) {
        WifiConfiguration config = getInternalConfiguredNetwork(networkId);
        if (config == null) {
            return false;
        }
        config.defaultGwMacAddress = macAddress;
        return true;
    }

    /**
     * Clear the {@link NetworkSelectionStatus#mCandidate},
     * {@link NetworkSelectionStatus#mCandidateScore} &
     * {@link NetworkSelectionStatus#mSeenInLastQualifiedNetworkSelection} for the provided network.
     *
     * This is invoked by Network Selector at the start of every selection procedure to clear all
     * configured networks' scan-result-candidates.
     *
     * @param networkId network ID corresponding to the network.
     * @return true if the network was found, false otherwise.
     */
    public boolean clearNetworkCandidateScanResult(int networkId) {
        if (mVerboseLoggingEnabled) {
            Log.v(TAG, "Clear network candidate scan result for " + networkId);
        }
        WifiConfiguration config = getInternalConfiguredNetwork(networkId);
        if (config == null) {
            return false;
        }
        config.getNetworkSelectionStatus().setCandidate(null);
        config.getNetworkSelectionStatus().setCandidateScore(Integer.MIN_VALUE);
        config.getNetworkSelectionStatus().setSeenInLastQualifiedNetworkSelection(false);
        return true;
    }

    /**
     * Set the {@link NetworkSelectionStatus#mCandidate},
     * {@link NetworkSelectionStatus#mCandidateScore} &
     * {@link NetworkSelectionStatus#mSeenInLastQualifiedNetworkSelection} for the provided network.
     *
     * This is invoked by Network Selector when it sees a network during network selection procedure
     * to set the scan result candidate.
     *
     * @param networkId  network ID corresponding to the network.
     * @param scanResult Candidate ScanResult associated with this network.
     * @param score      Score assigned to the candidate.
     * @return true if the network was found, false otherwise.
     */
    public boolean setNetworkCandidateScanResult(int networkId, ScanResult scanResult, int score) {
        if (mVerboseLoggingEnabled) {
            Log.v(TAG, "Set network candidate scan result " + scanResult + " for " + networkId);
        }
        WifiConfiguration config = getInternalConfiguredNetwork(networkId);
        if (config == null) {
            return false;
        }
        config.getNetworkSelectionStatus().setCandidate(scanResult);
        config.getNetworkSelectionStatus().setCandidateScore(score);
        config.getNetworkSelectionStatus().setSeenInLastQualifiedNetworkSelection(true);
        return true;
    }

    /**
     * Iterate through all the saved networks and remove the provided configuration from the
     * {@link NetworkSelectionStatus#mConnectChoice} from them.
     *
     * This is invoked when a network is removed from our records.
     *
     * @param connectChoiceConfigKey ConfigKey corresponding to the network that is being removed.
     */
    private void removeConnectChoiceFromAllNetworks(String connectChoiceConfigKey) {
        if (mVerboseLoggingEnabled) {
            Log.v(TAG, "Removing connect choice from all networks " + connectChoiceConfigKey);
        }
        if (connectChoiceConfigKey == null) {
            return;
        }
        for (WifiConfiguration config : mConfiguredNetworks.valuesForCurrentUser()) {
            WifiConfiguration.NetworkSelectionStatus status = config.getNetworkSelectionStatus();
            String connectChoice = status.getConnectChoice();
            if (TextUtils.equals(connectChoice, connectChoiceConfigKey)) {
                Log.d(TAG, "remove connect choice:" + connectChoice + " from " + config.SSID
                        + " : " + config.networkId);
                clearNetworkConnectChoice(config.networkId);
            }
        }
    }

    /**
     * Clear the {@link NetworkSelectionStatus#mConnectChoice} &
     * {@link NetworkSelectionStatus#mConnectChoiceTimestamp} for the provided network.
     *
     * @param networkId network ID corresponding to the network.
     * @return true if the network was found, false otherwise.
     */
    public boolean clearNetworkConnectChoice(int networkId) {
        if (mVerboseLoggingEnabled) {
            Log.v(TAG, "Clear network connect choice for " + networkId);
        }
        WifiConfiguration config = getInternalConfiguredNetwork(networkId);
        if (config == null) {
            return false;
        }
        config.getNetworkSelectionStatus().setConnectChoice(null);
        config.getNetworkSelectionStatus().setConnectChoiceTimestamp(
                NetworkSelectionStatus.INVALID_NETWORK_SELECTION_DISABLE_TIMESTAMP);
        saveToStore(false);
        return true;
    }

    /**
     * Set the {@link NetworkSelectionStatus#mConnectChoice} &
     * {@link NetworkSelectionStatus#mConnectChoiceTimestamp} for the provided network.
     *
     * This is invoked by Network Selector when the user overrides the currently connected network
     * choice.
     *
     * @param networkId              network ID corresponding to the network.
     * @param connectChoiceConfigKey ConfigKey corresponding to the network which was chosen over
     *                               this network.
     * @param timestamp              timestamp at which the choice was made.
     * @return true if the network was found, false otherwise.
     */
    public boolean setNetworkConnectChoice(
            int networkId, String connectChoiceConfigKey, long timestamp) {
        if (mVerboseLoggingEnabled) {
            Log.v(TAG, "Set network connect choice " + connectChoiceConfigKey + " for " + networkId);
        }
        WifiConfiguration config = getInternalConfiguredNetwork(networkId);
        if (config == null) {
            return false;
        }
        config.getNetworkSelectionStatus().setConnectChoice(connectChoiceConfigKey);
        config.getNetworkSelectionStatus().setConnectChoiceTimestamp(timestamp);
        saveToStore(false);
        return true;
    }

    /**
     * Increments the number of no internet access reports in the provided network.
     *
     * @param networkId network ID corresponding to the network.
     * @return true if the network was found, false otherwise.
     */
    public boolean incrementNetworkNoInternetAccessReports(int networkId) {
        WifiConfiguration config = getInternalConfiguredNetwork(networkId);
        if (config == null) {
            return false;
        }
        config.numNoInternetAccessReports++;
        return true;
    }

    /**
     * Sets the internet access is validated or not in the provided network.
     *
     * @param networkId network ID corresponding to the network.
     * @param validated Whether access is validated or not.
     * @return true if the network was found, false otherwise.
     */
    public boolean setNetworkValidatedInternetAccess(int networkId, boolean validated) {
        WifiConfiguration config = getInternalConfiguredNetwork(networkId);
        if (config == null) {
            return false;
        }
        config.validatedInternetAccess = validated;
        config.numNoInternetAccessReports = 0;
        saveToStore(false);
        return true;
    }

    /**
     * Sets whether the internet access is expected or not in the provided network.
     *
     * @param networkId network ID corresponding to the network.
     * @param expected  Whether access is expected or not.
     * @return true if the network was found, false otherwise.
     */
    public boolean setNetworkNoInternetAccessExpected(int networkId, boolean expected) {
        WifiConfiguration config = getInternalConfiguredNetwork(networkId);
        if (config == null) {
            return false;
        }
        config.noInternetAccessExpected = expected;
        return true;
    }

    /**
     * Helper method to clear out the {@link #mNextNetworkId} user/app network selection. This
     * is done when either the corresponding network is either removed or disabled.
     */
    private void clearLastSelectedNetwork() {
        if (mVerboseLoggingEnabled) {
            Log.v(TAG, "Clearing last selected network");
        }
        mLastSelectedNetworkId = WifiConfiguration.INVALID_NETWORK_ID;
        mLastSelectedTimeStamp = NetworkSelectionStatus.INVALID_NETWORK_SELECTION_DISABLE_TIMESTAMP;
    }

    /**
     * Helper method to mark a network as the last selected one by an app/user. This is set
     * when an app invokes {@link #enableNetwork(int, boolean, int)} with |disableOthers| flag set.
     * This is used by network selector to assign a special bonus during network selection.
     */
    private void setLastSelectedNetwork(int networkId) {
        if (mVerboseLoggingEnabled) {
            Log.v(TAG, "Setting last selected network to " + networkId);
        }
        mLastSelectedNetworkId = networkId;
        mLastSelectedTimeStamp = mClock.getElapsedSinceBootMillis();
    }

    /**
     * Retrieve the network Id corresponding to the last network that was explicitly selected by
     * an app/user.
     *
     * @return network Id corresponding to the last selected network.
     */
    public int getLastSelectedNetwork() {
        return mLastSelectedNetworkId;
    }

    /**
     * Retrieve the configKey corresponding to the last network that was explicitly selected by
     * an app/user.
     *
     * @return network Id corresponding to the last selected network.
     */
    public String getLastSelectedNetworkConfigKey() {
        if (mLastSelectedNetworkId == WifiConfiguration.INVALID_NETWORK_ID) {
            return "";
        }
        WifiConfiguration config = getInternalConfiguredNetwork(mLastSelectedNetworkId);
        if (config == null) {
            return "";
        }
        return config.configKey();
    }

    /**
     * Retrieve the time stamp at which a network was explicitly selected by an app/user.
     *
     * @return timestamp in milliseconds from boot when this was set.
     */
    public long getLastSelectedTimeStamp() {
        return mLastSelectedTimeStamp;
    }

    /**
     * Helper method to get the scan detail cache entry {@link #mScanDetailCaches} for the provided
     * network.
     *
     * @param networkId network ID corresponding to the network.
     * @return existing {@link ScanDetailCache} entry if one exists or null.
     */
    public ScanDetailCache getScanDetailCacheForNetwork(int networkId) {
        return mScanDetailCaches.get(networkId);
    }

    /**
     * Helper method to get or create a scan detail cache entry {@link #mScanDetailCaches} for
     * the provided network.
     *
     * @param config configuration corresponding to the the network.
     * @return existing {@link ScanDetailCache} entry if one exists or a new instance created for
     * this network.
     */
    private ScanDetailCache getOrCreateScanDetailCacheForNetwork(WifiConfiguration config) {
        if (config == null) return null;
        ScanDetailCache cache = getScanDetailCacheForNetwork(config.networkId);
        if (cache == null && config.networkId != WifiConfiguration.INVALID_NETWORK_ID) {
            cache = new ScanDetailCache(
                    config, SCAN_CACHE_ENTRIES_MAX_SIZE, SCAN_CACHE_ENTRIES_TRIM_SIZE);
            mScanDetailCaches.put(config.networkId, cache);
        }
        return cache;
    }

    /**
     * Saves the provided ScanDetail into the corresponding scan detail cache entry
     * {@link #mScanDetailCaches} for the provided network.
     *
     * @param config     configuration corresponding to the the network.
     * @param scanDetail new scan detail instance to be saved into the cache.
     */
    private void saveToScanDetailCacheForNetwork(
            WifiConfiguration config, ScanDetail scanDetail) {
        ScanResult scanResult = scanDetail.getScanResult();

        ScanDetailCache scanDetailCache = getOrCreateScanDetailCacheForNetwork(config);
        if (scanDetailCache == null) {
            Log.e(TAG, "Could not allocate scan cache for " + config.getPrintableSsid());
            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;
        }
        if (config.ephemeral) {
            // For an ephemeral Wi-Fi config, the ScanResult should be considered
            // untrusted.
            scanResult.untrusted = true;
        }

        // Add the scan detail to this network's scan detail cache.
        scanDetailCache.put(scanDetail);

        // Since we added a scan result to this configuration, re-attempt linking.
        // TODO: Do we really need to do this after every scan result?
        attemptNetworkLinking(config);
    }

    /**
     * Retrieves a saved network corresponding to the provided scan detail if one exists.
     *
     * @param scanDetail ScanDetail instance  to use for looking up the network.
     * @return WifiConfiguration object representing the network corresponding to the scanDetail,
     * null if none exists.
     */
    private WifiConfiguration getSavedNetworkForScanDetail(ScanDetail scanDetail) {
        ScanResult scanResult = scanDetail.getScanResult();
        if (scanResult == null) {
            Log.e(TAG, "No scan result found in scan detail");
            return null;
        }
        for (WifiConfiguration config : getInternalConfiguredNetworks()) {
            if (ScanResultUtil.doesScanResultMatchWithNetwork(scanResult, config)) {
                if (mVerboseLoggingEnabled) {
                    Log.v(TAG, "getSavedNetworkFromScanDetail Found " + config.configKey()
                            + " for " + scanResult.SSID + "[" + scanResult.capabilities + "]");
                }
                return config;
            }
        }
        return null;
    }

    /**
     * Retrieves a saved network corresponding to the provided scan detail if one exists and caches
     * the provided |scanDetail| into the corresponding scan detail cache entry
     * {@link #mScanDetailCaches} for the retrieved network.
     *
     * @param scanDetail input a scanDetail from the scan result
     * @return WifiConfiguration object representing the network corresponding to the scanDetail,
     * null if none exists.
     */
    public WifiConfiguration getSavedNetworkForScanDetailAndCache(ScanDetail scanDetail) {
        WifiConfiguration network = getSavedNetworkForScanDetail(scanDetail);
        if (network == null) {
            return null;
        }
        saveToScanDetailCacheForNetwork(network, scanDetail);
        // Cache DTIM values parsed from the beacon frame Traffic Indication Map (TIM)
        // Information Element (IE), into the associated WifiConfigurations. Most of the
        // time there is no TIM IE in the scan result (Probe Response instead of Beacon
        // Frame), these scanResult DTIM's are negative and ignored.
        // Used for metrics collection.
        if (scanDetail.getNetworkDetail() != null
                && scanDetail.getNetworkDetail().getDtimInterval() > 0) {
            network.dtimInterval = scanDetail.getNetworkDetail().getDtimInterval();
        }
        return createExternalWifiConfiguration(network, true);
    }

    /**
     * Update the scan detail cache associated with current connected network with latest
     * RSSI value in the provided WifiInfo.
     * This is invoked when we get an RSSI poll update after connection.
     *
     * @param info WifiInfo instance pointing to the current connected network.
     */
    public void updateScanDetailCacheFromWifiInfo(WifiInfo info) {
        WifiConfiguration config = getInternalConfiguredNetwork(info.getNetworkId());
        ScanDetailCache scanDetailCache = getScanDetailCacheForNetwork(info.getNetworkId());
        if (config != null && scanDetailCache != null) {
            ScanDetail scanDetail = scanDetailCache.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, SCAN_RESULT_MAXIMUM_AGE_MS);
                if (mVerboseLoggingEnabled) {
                    Log.v(TAG, "Updating scan detail cache freq=" + result.frequency
                            + " BSSID=" + result.BSSID
                            + " RSSI=" + result.level
                            + " for " + config.configKey());
                }
            }
        }
    }

    /**
     * Save the ScanDetail to the ScanDetailCache of the given network.  This is used
     * by {@link com.android.server.wifi.hotspot2.PasspointNetworkEvaluator} for caching
     * ScanDetail for newly created {@link WifiConfiguration} for Passpoint network.
     *
     * @param networkId The ID of the network to save ScanDetail to
     * @param scanDetail The ScanDetail to cache
     */
    public void updateScanDetailForNetwork(int networkId, ScanDetail scanDetail) {
        WifiConfiguration network = getInternalConfiguredNetwork(networkId);
        if (network == null) {
            return;
        }
        saveToScanDetailCacheForNetwork(network, scanDetail);
    }

    /**
     * Helper method to check if the 2 provided networks can be linked or not.
     * Networks are considered for linking if:
     * 1. Share the same GW MAC address.
     * 2. Scan results for the networks have AP's with MAC address which differ only in the last
     * nibble.
     *
     * @param network1         WifiConfiguration corresponding to network 1.
     * @param network2         WifiConfiguration corresponding to network 2.
     * @param scanDetailCache1 ScanDetailCache entry for network 1.
     * @param scanDetailCache1 ScanDetailCache entry for network 2.
     * @return true if the networks should be linked, false if the networks should be unlinked.
     */
    private boolean shouldNetworksBeLinked(
            WifiConfiguration network1, WifiConfiguration network2,
            ScanDetailCache scanDetailCache1, ScanDetailCache scanDetailCache2) {
        // TODO (b/30706406): Link networks only with same passwords if the
        // |mOnlyLinkSameCredentialConfigurations| flag is set.
        if (mOnlyLinkSameCredentialConfigurations) {
            if (!TextUtils.equals(network1.preSharedKey, network2.preSharedKey)) {
                if (mVerboseLoggingEnabled) {
                    Log.v(TAG, "shouldNetworksBeLinked unlink due to password mismatch");
                }
                return false;
            }
        }
        if (network1.defaultGwMacAddress != null && network2.defaultGwMacAddress != null) {
            // If both default GW are known, link only if they are equal
            if (network1.defaultGwMacAddress.equals(network2.defaultGwMacAddress)) {
                if (mVerboseLoggingEnabled) {
                    Log.v(TAG, "shouldNetworksBeLinked link due to same gw " + network2.SSID
                            + " and " + network1.SSID + " GW " + network1.defaultGwMacAddress);
                }
                return 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 default gateways
            // are known we will revisit the choice of linking them.
            if (scanDetailCache1 != null && scanDetailCache2 != null) {
                for (String abssid : scanDetailCache1.keySet()) {
                    for (String bbssid : scanDetailCache2.keySet()) {
                        if (abssid.regionMatches(
                                true, 0, bbssid, 0, LINK_CONFIGURATION_BSSID_MATCH_LENGTH)) {
                            // If first 16 ASCII characters of BSSID matches,
                            // we assume this is a DBDC.
                            if (mVerboseLoggingEnabled) {
                                Log.v(TAG, "shouldNetworksBeLinked link due to DBDC BSSID match "
                                        + network2.SSID + " and " + network1.SSID
                                        + " bssida " + abssid + " bssidb " + bbssid);
                            }
                            return true;
                        }
                    }
                }
            }
        }
        return false;
    }

    /**
     * Helper methods to link 2 networks together.
     *
     * @param network1 WifiConfiguration corresponding to network 1.
     * @param network2 WifiConfiguration corresponding to network 2.
     */
    private void linkNetworks(WifiConfiguration network1, WifiConfiguration network2) {
        if (mVerboseLoggingEnabled) {
            Log.v(TAG, "linkNetworks will link " + network2.configKey()
                    + " and " + network1.configKey());
        }
        if (network2.linkedConfigurations == null) {
            network2.linkedConfigurations = new HashMap<>();
        }
        if (network1.linkedConfigurations == null) {
            network1.linkedConfigurations = new HashMap<>();
        }
        // TODO (b/30638473): This needs to become a set instead of map, but it will need
        // public interface changes and need some migration of existing store data.
        network2.linkedConfigurations.put(network1.configKey(), 1);
        network1.linkedConfigurations.put(network2.configKey(), 1);
    }

    /**
     * Helper methods to unlink 2 networks from each other.
     *
     * @param network1 WifiConfiguration corresponding to network 1.
     * @param network2 WifiConfiguration corresponding to network 2.
     */
    private void unlinkNetworks(WifiConfiguration network1, WifiConfiguration network2) {
        if (network2.linkedConfigurations != null
                && (network2.linkedConfigurations.get(network1.configKey()) != null)) {
            if (mVerboseLoggingEnabled) {
                Log.v(TAG, "unlinkNetworks un-link " + network1.configKey()
                        + " from " + network2.configKey());
            }
            network2.linkedConfigurations.remove(network1.configKey());
        }
        if (network1.linkedConfigurations != null
                && (network1.linkedConfigurations.get(network2.configKey()) != null)) {
            if (mVerboseLoggingEnabled) {
                Log.v(TAG, "unlinkNetworks un-link " + network2.configKey()
                        + " from " + network1.configKey());
            }
            network1.linkedConfigurations.remove(network2.configKey());
        }
    }

    /**
     * This method runs through all the saved networks and checks if the provided network can be
     * linked with any of them.
     *
     * @param config WifiConfiguration object corresponding to the network that needs to be
     *               checked for potential links.
     */
    private void attemptNetworkLinking(WifiConfiguration config) {
        // Only link WPA_PSK config.
        if (!config.allowedKeyManagement.get(WifiConfiguration.KeyMgmt.WPA_PSK)) {
            return;
        }
        ScanDetailCache scanDetailCache = getScanDetailCacheForNetwork(config.networkId);
        // Ignore configurations with large number of BSSIDs.
        if (scanDetailCache != null
                && scanDetailCache.size() > LINK_CONFIGURATION_MAX_SCAN_CACHE_ENTRIES) {
            return;
        }
        for (WifiConfiguration linkConfig : getInternalConfiguredNetworks()) {
            if (linkConfig.configKey().equals(config.configKey())) {
                continue;
            }
            if (linkConfig.ephemeral) {
                continue;
            }
            // Network Selector will be allowed to dynamically jump from a linked configuration
            // to another, hence only link configurations that have WPA_PSK security type.
            if (!linkConfig.allowedKeyManagement.get(WifiConfiguration.KeyMgmt.WPA_PSK)) {
                continue;
            }
            ScanDetailCache linkScanDetailCache =
                    getScanDetailCacheForNetwork(linkConfig.networkId);
            // Ignore configurations with large number of BSSIDs.
            if (linkScanDetailCache != null
                    && linkScanDetailCache.size() > LINK_CONFIGURATION_MAX_SCAN_CACHE_ENTRIES) {
                continue;
            }
            // Check if the networks should be linked/unlinked.
            if (shouldNetworksBeLinked(
                    config, linkConfig, scanDetailCache, linkScanDetailCache)) {
                linkNetworks(config, linkConfig);
            } else {
                unlinkNetworks(config, linkConfig);
            }
        }
    }

    /**
     * Helper method to fetch list of channels for a network from the associated ScanResult's cache
     * and add it to the provided channel as long as the size of the set is less than
     * |maxChannelSetSize|.
     *
     * @param channelSet        Channel set holding all the channels for the network.
     * @param scanDetailCache   ScanDetailCache entry associated with the network.
     * @param nowInMillis       current timestamp to be used for age comparison.
     * @param ageInMillis       only consider scan details whose timestamps are earlier than this
     *                          value.
     * @param maxChannelSetSize Maximum number of channels to be added to the set.
     * @return false if the list is full, true otherwise.
     */
    private boolean addToChannelSetForNetworkFromScanDetailCache(
            Set<Integer> channelSet, ScanDetailCache scanDetailCache,
            long nowInMillis, long ageInMillis, int maxChannelSetSize) {
        if (scanDetailCache != null && scanDetailCache.size() > 0) {
            for (ScanDetail scanDetail : scanDetailCache.values()) {
                ScanResult result = scanDetail.getScanResult();
                boolean valid = (nowInMillis - result.seen) < ageInMillis;
                if (mVerboseLoggingEnabled) {
                    Log.v(TAG, "fetchChannelSetForNetwork has " + result.BSSID + " freq "
                            + result.frequency + " age " + (nowInMillis - result.seen)
                            + " ?=" + valid);
                }
                if (valid) {
                    channelSet.add(result.frequency);
                }
                if (channelSet.size() >= maxChannelSetSize) {
                    return false;
                }
            }
        }
        return true;
    }

    /**
     * Retrieve a set of channels on which AP's for the provided network was seen using the
     * internal ScanResult's cache {@link #mScanDetailCaches}. This is used for initiating partial
     * scans for the currently connected network.
     *
     * @param networkId       network ID corresponding to the network.
     * @param ageInMillis     only consider scan details whose timestamps are earlier than this value.
     * @param homeChannelFreq frequency of the currently connected network.
     * @return Set containing the frequencies on which this network was found, null if the network
     * was not found or there are no associated scan details in the cache.
     */
    public Set<Integer> fetchChannelSetForNetworkForPartialScan(int networkId, long ageInMillis,
                                                                int homeChannelFreq) {
        WifiConfiguration config = getInternalConfiguredNetwork(networkId);
        if (config == null) {
            return null;
        }
        ScanDetailCache scanDetailCache = getScanDetailCacheForNetwork(networkId);
        if (scanDetailCache == null && config.linkedConfigurations == null) {
            Log.i(TAG, "No scan detail and linked configs associated with networkId " + networkId);
            return null;
        }
        if (mVerboseLoggingEnabled) {
            StringBuilder dbg = new StringBuilder();
            dbg.append("fetchChannelSetForNetworkForPartialScan ageInMillis ")
                    .append(ageInMillis)
                    .append(" for ")
                    .append(config.configKey())
                    .append(" max ")
                    .append(mMaxNumActiveChannelsForPartialScans);
            if (scanDetailCache != null) {
                dbg.append(" bssids " + scanDetailCache.size());
            }
            if (config.linkedConfigurations != null) {
                dbg.append(" linked " + config.linkedConfigurations.size());
            }
            Log.v(TAG, dbg.toString());
        }
        Set<Integer> channelSet = new HashSet<>();

        // First add the currently connected network channel.
        if (homeChannelFreq > 0) {
            channelSet.add(homeChannelFreq);
            if (channelSet.size() >= mMaxNumActiveChannelsForPartialScans) {
                return channelSet;
            }
        }

        long nowInMillis = mClock.getWallClockMillis();

        // Then get channels for the network.
        if (!addToChannelSetForNetworkFromScanDetailCache(
                channelSet, scanDetailCache, nowInMillis, ageInMillis,
                mMaxNumActiveChannelsForPartialScans)) {
            return channelSet;
        }

        // Lastly get channels for linked networks.
        if (config.linkedConfigurations != null) {
            for (String configKey : config.linkedConfigurations.keySet()) {
                WifiConfiguration linkedConfig = getInternalConfiguredNetwork(configKey);
                if (linkedConfig == null) {
                    continue;
                }
                ScanDetailCache linkedScanDetailCache =
                        getScanDetailCacheForNetwork(linkedConfig.networkId);
                if (!addToChannelSetForNetworkFromScanDetailCache(
                        channelSet, linkedScanDetailCache, nowInMillis, ageInMillis,
                        mMaxNumActiveChannelsForPartialScans)) {
                    break;
                }
            }
        }
        return channelSet;
    }

    /**
     * Retrieves a list of all the saved networks before enabling disconnected/connected PNO.
     *
     * PNO network list sent to the firmware has limited size. If there are a lot of saved
     * networks, this list will be truncated and we might end up not sending the networks
     * with the highest chance of connecting to the firmware.
     * So, re-sort the network list based on the frequency of connection to those networks
     * and whether it was last seen in the scan results.
     *
     * TODO (b/30399964): Recalculate the list whenever network status changes.
     * @return list of networks with updated priorities.
     */
    public List<WifiScanner.PnoSettings.PnoNetwork> retrievePnoNetworkList() {
        List<WifiScanner.PnoSettings.PnoNetwork> pnoList = new ArrayList<>();
        List<WifiConfiguration> networks = new ArrayList<>(getInternalConfiguredNetworks());
        // Remove any permanently disabled networks.
        Iterator<WifiConfiguration> iter = networks.iterator();
        while (iter.hasNext()) {
            WifiConfiguration config = iter.next();
            if (config.getNetworkSelectionStatus().isNetworkPermanentlyDisabled()) {
                iter.remove();
            }
        }
        Collections.sort(networks, sScanListComparator);
        // Let's use the network list size - 1 as the highest priority and then go down from there.
        // So, the most frequently connected network has the highest priority now.
        int priority = networks.size() - 1;
        for (WifiConfiguration config : networks) {
            pnoList.add(WifiConfigurationUtil.createPnoNetwork(config, priority));
            priority--;
        }
        return pnoList;
    }

    /**
     * Retrieves a list of all the saved hidden networks for scans.
     *
     * Hidden network list sent to the firmware has limited size. If there are a lot of saved
     * networks, this list will be truncated and we might end up not sending the networks
     * with the highest chance of connecting to the firmware.
     * So, re-sort the network list based on the frequency of connection to those networks
     * and whether it was last seen in the scan results.
     *
     * @return list of networks with updated priorities.
     */
    public List<WifiScanner.ScanSettings.HiddenNetwork> retrieveHiddenNetworkList() {
        List<WifiScanner.ScanSettings.HiddenNetwork> hiddenList = new ArrayList<>();
        List<WifiConfiguration> networks = new ArrayList<>(getInternalConfiguredNetworks());
        // Remove any permanently disabled networks or non hidden networks.
        Iterator<WifiConfiguration> iter = networks.iterator();
        while (iter.hasNext()) {
            WifiConfiguration config = iter.next();
            if (!config.hiddenSSID ||
                    config.getNetworkSelectionStatus().isNetworkPermanentlyDisabled()) {
                iter.remove();
            }
        }
        Collections.sort(networks, sScanListComparator);
        // Let's use the network list size - 1 as the highest priority and then go down from there.
        // So, the most frequently connected network has the highest priority now.
        int priority = networks.size() - 1;
        for (WifiConfiguration config : networks) {
            hiddenList.add(
                    new WifiScanner.ScanSettings.HiddenNetwork(config.SSID));
            priority--;
        }
        return hiddenList;
    }

    /**
     * Check if the provided ephemeral network was deleted by the user or not.
     *
     * @param ssid caller must ensure that the SSID passed thru this API match
     *             the WifiConfiguration.SSID rules, and thus be surrounded by quotes.
     * @return true if network was deleted, false otherwise.
     */
    public boolean wasEphemeralNetworkDeleted(String ssid) {
        return mDeletedEphemeralSSIDs.contains(ssid);
    }

    /**
     * Disable an ephemeral SSID for the purpose of network selection.
     *
     * 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.
     */
    public WifiConfiguration disableEphemeralNetwork(String ssid) {
        if (ssid == null) {
            return null;
        }
        WifiConfiguration foundConfig = null;
        for (WifiConfiguration config : getInternalConfiguredNetworks()) {
            if (config.ephemeral && TextUtils.equals(config.SSID, ssid)) {
                foundConfig = config;
                break;
            }
        }
        mDeletedEphemeralSSIDs.add(ssid);
        Log.d(TAG, "Forget ephemeral SSID " + ssid + " num=" + mDeletedEphemeralSSIDs.size());
        if (foundConfig != null) {
            Log.d(TAG, "Found ephemeral config in disableEphemeralNetwork: "
                    + foundConfig.networkId);
        }
        return foundConfig;
    }

    /**
     * Resets all sim networks state.
     */
    public void resetSimNetworks() {
        if (mVerboseLoggingEnabled) localLog("resetSimNetworks");
        for (WifiConfiguration config : getInternalConfiguredNetworks()) {
            if (TelephonyUtil.isSimConfig(config)) {
                String currentIdentity = TelephonyUtil.getSimIdentity(mTelephonyManager, config);
                // Update the loaded config
                config.enterpriseConfig.setIdentity(currentIdentity);
                if (config.enterpriseConfig.getEapMethod() != WifiEnterpriseConfig.Eap.PEAP) {
                    config.enterpriseConfig.setAnonymousIdentity("");
                }
            }
        }
    }

    /**
     * Any network using certificates to authenticate access requires unlocked key store; unless
     * the certificates can be stored with hardware encryption
     *
     * @return true if we need an unlocked keystore, false otherwise.
     */
    public boolean needsUnlockedKeyStore() {
        for (WifiConfiguration config : getInternalConfiguredNetworks()) {
            if (WifiConfigurationUtil.isConfigForEapNetwork(config)) {
                if (mWifiKeyStore.needsSoftwareBackedKeyStore(config.enterpriseConfig)) {
                    return true;
                }
            }
        }
        return false;
    }

    /**
     * Helper method to perform the following operations during user switch/unlock:
     * - Remove private networks of the old user.
     * - Load from the new user store file.
     * - Save the store files again to migrate any user specific networks from the shared store
     *   to user store.
     * This method assumes the user store is visible (i.e CE storage is unlocked). So, the caller
     * should ensure that the stores are accessible before invocation.
     *
     * @param userId The identifier of the new foreground user, after the unlock or switch.
     */
    private void handleUserUnlockOrSwitch(int userId) {
        if (mVerboseLoggingEnabled) {
            Log.v(TAG, "Loading from store after user switch/unlock for " + userId);
        }
        // Switch out the user store file.
        if (loadFromUserStoreAfterUnlockOrSwitch(userId)) {
            saveToStore(true);
            mPendingUnlockStoreRead = false;
        }
    }

    /**
     * Handles the switch to a different foreground user:
     * - Flush the current state to the old user's store file.
     * - Switch the user specific store file.
     * - Reload the networks from the store files (shared & user).
     * - Write the store files to move any user specific private networks from shared store to user
     *   store.
     *
     * Need to be called when {@link com.android.server.SystemService#onSwitchUser(int)} is invoked.
     *
     * @param userId The identifier of the new foreground user, after the switch.
     * @return List of network ID's of all the private networks of the old user which will be
     * removed from memory.
     */
    public Set<Integer> handleUserSwitch(int userId) {
        if (mVerboseLoggingEnabled) {
            Log.v(TAG, "Handling user switch for " + userId);
        }
        if (userId == mCurrentUserId) {
            Log.w(TAG, "User already in foreground " + userId);
            return new HashSet<>();
        }
        if (mPendingStoreRead) {
            Log.wtf(TAG, "Unexpected user switch before store is read!");
            return new HashSet<>();
        }
        if (mUserManager.isUserUnlockingOrUnlocked(mCurrentUserId)) {
            saveToStore(true);
        }
        // Remove any private networks of the old user before switching the userId.
        Set<Integer> removedNetworkIds = clearInternalUserData(mCurrentUserId);
        mConfiguredNetworks.setNewUser(userId);
        mCurrentUserId = userId;

        if (mUserManager.isUserUnlockingOrUnlocked(mCurrentUserId)) {
            handleUserUnlockOrSwitch(mCurrentUserId);
        } else {
            // Cannot read data from new user's CE store file before they log-in.
            mPendingUnlockStoreRead = true;
            Log.i(TAG, "Waiting for user unlock to load from store");
        }
        return removedNetworkIds;
    }

    /**
     * Handles the unlock of foreground user. This maybe needed to read the store file if the user's
     * CE storage is not visible when {@link #handleUserSwitch(int)} is invoked.
     *
     * Need to be called when {@link com.android.server.SystemService#onUnlockUser(int)} is invoked.
     *
     * @param userId The identifier of the user that unlocked.
     */
    public void handleUserUnlock(int userId) {
        if (mVerboseLoggingEnabled) {
            Log.v(TAG, "Handling user unlock for " + userId);
        }
        if (mPendingStoreRead) {
            Log.w(TAG, "Ignore user unlock until store is read!");
            mDeferredUserUnlockRead = true;
            return;
        }
        if (userId == mCurrentUserId && mPendingUnlockStoreRead) {
            handleUserUnlockOrSwitch(mCurrentUserId);
        }
    }

    /**
     * Handles the stop of foreground user. This is needed to write the store file to flush
     * out any pending data before the user's CE store storage is unavailable.
     *
     * Need to be called when {@link com.android.server.SystemService#onStopUser(int)} is invoked.
     *
     * @param userId The identifier of the user that stopped.
     */
    public void handleUserStop(int userId) {
        if (userId == mCurrentUserId && mUserManager.isUserUnlockingOrUnlocked(mCurrentUserId)) {
            saveToStore(true);
            clearInternalData();
            mCurrentUserId = UserHandle.USER_SYSTEM;
        }
    }

    /**
     * Helper method to clear internal databases.
     * This method clears the:
     *  - List of configured networks.
     *  - Map of scan detail caches.
     *  - List of deleted ephemeral networks.
     */
    private void clearInternalData() {
        mConfiguredNetworks.clear();
        mDeletedEphemeralSSIDs.clear();
        mScanDetailCaches.clear();
        clearLastSelectedNetwork();
    }

    /**
     * Helper method to clear internal databases of the specified user.
     * This method clears the:
     *  - Private configured configured networks of the specified user.
     *  - Map of scan detail caches.
     *  - List of deleted ephemeral networks.
     *
     * @param userId The identifier of the current foreground user, before the switch.
     * @return List of network ID's of all the private networks of the old user which will be
     * removed from memory.
     */
    private Set<Integer> clearInternalUserData(int userId) {
        Set<Integer> removedNetworkIds = new HashSet<>();
        // Remove any private networks of the old user before switching the userId.
        for (WifiConfiguration config : getInternalConfiguredNetworks()) {
            if (!config.shared && WifiConfigurationUtil.doesUidBelongToAnyProfile(
                    config.creatorUid, mUserManager.getProfiles(userId))) {
                removedNetworkIds.add(config.networkId);
                mConfiguredNetworks.remove(config.networkId);
            }
        }
        mDeletedEphemeralSSIDs.clear();
        mScanDetailCaches.clear();
        clearLastSelectedNetwork();
        return removedNetworkIds;
    }

    /**
     * Helper function to populate the internal (in-memory) data from the retrieved shared store
     * (file) data.
     *
     * @param configurations list of configurations retrieved from store.
     */
    private void loadInternalDataFromSharedStore(
            List<WifiConfiguration> configurations) {
        for (WifiConfiguration configuration : configurations) {
            configuration.networkId = mNextNetworkId++;
            if (mVerboseLoggingEnabled) {
                Log.v(TAG, "Adding network from shared store " + configuration.configKey());
            }
            mConfiguredNetworks.put(configuration);
        }
    }

    /**
     * Helper function to populate the internal (in-memory) data from the retrieved user store
     * (file) data.
     *
     * @param configurations        list of configurations retrieved from store.
     * @param deletedEphemeralSSIDs list of ssid's representing the ephemeral networks deleted by
     *                              the user.
     */
    private void loadInternalDataFromUserStore(
            List<WifiConfiguration> configurations, Set<String> deletedEphemeralSSIDs) {
        for (WifiConfiguration configuration : configurations) {
            configuration.networkId = mNextNetworkId++;
            if (mVerboseLoggingEnabled) {
                Log.v(TAG, "Adding network from user store " + configuration.configKey());
            }
            mConfiguredNetworks.put(configuration);
        }
        for (String ssid : deletedEphemeralSSIDs) {
            mDeletedEphemeralSSIDs.add(ssid);
        }
    }

    /**
     * Helper function to populate the internal (in-memory) data from the retrieved stores (file)
     * data.
     * This method:
     * 1. Clears all existing internal data.
     * 2. Sends out the networks changed broadcast after loading all the data.
     *
     * @param sharedConfigurations  list of  network configurations retrieved from shared store.
     * @param userConfigurations    list of  network configurations retrieved from user store.
     * @param deletedEphemeralSSIDs list of ssid's representing the ephemeral networks deleted by
     *                              the user.
     */
    private void loadInternalData(
            List<WifiConfiguration> sharedConfigurations,
            List<WifiConfiguration> userConfigurations, Set<String> deletedEphemeralSSIDs) {
        // Clear out all the existing in-memory lists and load the lists from what was retrieved
        // from the config store.
        clearInternalData();
        loadInternalDataFromSharedStore(sharedConfigurations);
        loadInternalDataFromUserStore(userConfigurations, deletedEphemeralSSIDs);
        if (mConfiguredNetworks.sizeForAllUsers() == 0) {
            Log.w(TAG, "No stored networks found.");
        }
        sendConfiguredNetworksChangedBroadcast();
        mPendingStoreRead = false;
    }

    /**
     * Migrate data from legacy store files. The function performs the following operations:
     * 1. Check if the legacy store files are present.
     * 2. If yes, read all the data from the store files.
     * 3. Save it to the new store files.
     * 4. Delete the legacy store file.
     *
     * @return true if migration was successful or not needed (fresh install), false if it failed.
     */
    public boolean migrateFromLegacyStore() {
        if (!mWifiConfigStoreLegacy.areStoresPresent()) {
            Log.d(TAG, "Legacy store files not found. No migration needed!");
            return true;
        }
        WifiConfigStoreDataLegacy storeData = mWifiConfigStoreLegacy.read();
        Log.d(TAG, "Reading from legacy store completed");
        loadInternalData(storeData.getConfigurations(), new ArrayList<WifiConfiguration>(),
                storeData.getDeletedEphemeralSSIDs());

        // Setup user store for the current user in case it have not setup yet, so that data
        // owned by the current user will be backed to the user store.
        if (mDeferredUserUnlockRead) {
            mWifiConfigStore.setUserStore(WifiConfigStore.createUserFile(mCurrentUserId));
            mDeferredUserUnlockRead = false;
        }

        if (!saveToStore(true)) {
            return false;
        }
        mWifiConfigStoreLegacy.removeStores();
        Log.d(TAG, "Migration from legacy store completed");
        return true;
    }

    /**
     * Read the config store and load the in-memory lists from the store data retrieved and sends
     * out the networks changed broadcast.
     *
     * This reads all the network configurations from:
     * 1. Shared WifiConfigStore.xml
     * 2. User WifiConfigStore.xml
     *
     * @return true on success or not needed (fresh install/pending legacy store migration),
     * false otherwise.
     */
    public boolean loadFromStore() {
        if (!mWifiConfigStore.areStoresPresent()) {
            Log.d(TAG, "New store files not found. No saved networks loaded!");
            if (!mWifiConfigStoreLegacy.areStoresPresent()) {
                // No legacy store files either, so reset the pending store read flag.
                mPendingStoreRead = false;
            }
            return true;
        }
        // If the user unlock comes in before we load from store, which means the user store have
        // not been setup yet for the current user.  Setup the user store before the read so that
        // configurations for the current user will also being loaded.
        if (mDeferredUserUnlockRead) {
            Log.i(TAG, "Handling user unlock before loading from store.");
            mWifiConfigStore.setUserStore(WifiConfigStore.createUserFile(mCurrentUserId));
            mDeferredUserUnlockRead = false;
        }
        try {
            mWifiConfigStore.read();
        } catch (IOException e) {
            Log.wtf(TAG, "Reading from new store failed. All saved networks are lost!", e);
            return false;
        } catch (XmlPullParserException e) {
            Log.wtf(TAG, "XML deserialization of store failed. All saved networks are lost!", e);
            return false;
        }
        loadInternalData(mNetworkListStoreData.getSharedConfigurations(),
                mNetworkListStoreData.getUserConfigurations(),
                mDeletedEphemeralSsidsStoreData.getSsidList());
        return true;
    }

    /**
     * Read the user config store and load the in-memory lists from the store data retrieved and
     * sends out the networks changed broadcast.
     * This should be used for all user switches/unlocks to only load networks from the user
     * specific store and avoid reloading the shared networks.
     *
     * This reads all the network configurations from:
     * 1. User WifiConfigStore.xml
     *
     * @param userId The identifier of the foreground user.
     * @return true on success, false otherwise.
     */
    public boolean loadFromUserStoreAfterUnlockOrSwitch(int userId) {
        try {
            mWifiConfigStore.switchUserStoreAndRead(WifiConfigStore.createUserFile(userId));
        } catch (IOException e) {
            Log.wtf(TAG, "Reading from new store failed. All saved private networks are lost!", e);
            return false;
        } catch (XmlPullParserException e) {
            Log.wtf(TAG, "XML deserialization of store failed. All saved private networks are" +
                    "lost!", e);
            return false;
        }
        loadInternalDataFromUserStore(mNetworkListStoreData.getUserConfigurations(),
                mDeletedEphemeralSsidsStoreData.getSsidList());
        return true;
    }

    /**
     * Save the current snapshot of the in-memory lists to the config store.
     *
     * @param forceWrite Whether the write needs to be forced or not.
     * @return Whether the write was successful or not, this is applicable only for force writes.
     */
    public boolean saveToStore(boolean forceWrite) {
        ArrayList<WifiConfiguration> sharedConfigurations = new ArrayList<>();
        ArrayList<WifiConfiguration> userConfigurations = new ArrayList<>();
        // List of network IDs for legacy Passpoint configuration to be removed.
        List<Integer> legacyPasspointNetId = new ArrayList<>();
        for (WifiConfiguration config : mConfiguredNetworks.valuesForAllUsers()) {
            // Ignore ephemeral networks and non-legacy Passpoint configurations.
            if (config.ephemeral || (config.isPasspoint() && !config.isLegacyPasspointConfig)) {
                continue;
            }

            // Migrate the legacy Passpoint configurations owned by the current user to
            // {@link PasspointManager}.
            if (config.isLegacyPasspointConfig && WifiConfigurationUtil.doesUidBelongToAnyProfile(
                        config.creatorUid, mUserManager.getProfiles(mCurrentUserId))) {
                legacyPasspointNetId.add(config.networkId);
                // Migrate the legacy Passpoint configuration and add it to PasspointManager.
                if (!PasspointManager.addLegacyPasspointConfig(config)) {
                    Log.e(TAG, "Failed to migrate legacy Passpoint config: " + config.FQDN);
                }
                // This will prevent adding |config| to the |sharedConfigurations|.
                continue;
            }

            // We push all shared networks & private networks not belonging to the current
            // user to the shared store. Ideally, private networks for other users should
            // not even be in memory,
            // But, this logic is in place to deal with store migration from N to O
            // because all networks were previously stored in a central file. We cannot
            // write these private networks to the user specific store until the corresponding
            // user logs in.
            if (config.shared || !WifiConfigurationUtil.doesUidBelongToAnyProfile(
                    config.creatorUid, mUserManager.getProfiles(mCurrentUserId))) {
                sharedConfigurations.add(config);
            } else {
                userConfigurations.add(config);
            }
        }

        // Remove the configurations for migrated Passpoint configurations.
        for (int networkId : legacyPasspointNetId) {
            mConfiguredNetworks.remove(networkId);
        }

        // Setup store data for write.
        mNetworkListStoreData.setSharedConfigurations(sharedConfigurations);
        mNetworkListStoreData.setUserConfigurations(userConfigurations);
        mDeletedEphemeralSsidsStoreData.setSsidList(mDeletedEphemeralSSIDs);

        try {
            mWifiConfigStore.write(forceWrite);
        } catch (IOException e) {
            Log.wtf(TAG, "Writing to store failed. Saved networks maybe lost!", e);
            return false;
        } catch (XmlPullParserException e) {
            Log.wtf(TAG, "XML serialization for store failed. Saved networks maybe lost!", e);
            return false;
        }
        return true;
    }

    /**
     * Helper method for logging into local log buffer.
     */
    private void localLog(String s) {
        if (mLocalLog != null) {
            mLocalLog.log(s);
        }
    }

    /**
     * Dump the local log buffer and other internal state of WifiConfigManager.
     */
    public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
        pw.println("Dump of WifiConfigManager");
        pw.println("WifiConfigManager - Log Begin ----");
        mLocalLog.dump(fd, pw, args);
        pw.println("WifiConfigManager - Log End ----");
        pw.println("WifiConfigManager - Configured networks Begin ----");
        for (WifiConfiguration network : getInternalConfiguredNetworks()) {
            pw.println(network);
        }
        pw.println("WifiConfigManager - Configured networks End ----");
        pw.println("WifiConfigManager - Next network ID to be allocated " + mNextNetworkId);
        pw.println("WifiConfigManager - Last selected network ID " + mLastSelectedNetworkId);
    }

    /**
     * Returns true if the given uid has permission to add, update or remove proxy settings
     */
    private boolean canModifyProxySettings(int uid) {
        final DevicePolicyManagerInternal dpmi =
                mWifiPermissionsWrapper.getDevicePolicyManagerInternal();
        final boolean isUidProfileOwner = dpmi != null && dpmi.isActiveAdminWithPolicy(uid,
                DeviceAdminInfo.USES_POLICY_PROFILE_OWNER);
        final boolean isUidDeviceOwner = dpmi != null && dpmi.isActiveAdminWithPolicy(uid,
                DeviceAdminInfo.USES_POLICY_DEVICE_OWNER);
        final boolean hasConfigOverridePermission =
                mWifiPermissionsUtil.checkConfigOverridePermission(uid);
        // If |uid| corresponds to the device owner, allow all modifications.
        if (isUidDeviceOwner || isUidProfileOwner || hasConfigOverridePermission) {
            return true;
        }
        if (mVerboseLoggingEnabled) {
            Log.v(TAG, "UID: " + uid + " cannot modify WifiConfiguration proxy settings."
                    + " ConfigOverride=" + hasConfigOverridePermission
                    + " DeviceOwner=" + isUidDeviceOwner
                    + " ProfileOwner=" + isUidProfileOwner);
        }
        return false;
    }

    /**
     * Set the saved network update event listener
     */
    public void setOnSavedNetworkUpdateListener(OnSavedNetworkUpdateListener listener) {
        mListener = listener;
    }
}
