/*
 * Copyright (C) 2015 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.settingslib.wifi;

import android.annotation.IntDef;
import android.annotation.MainThread;
import android.annotation.Nullable;
import android.app.AppGlobals;
import android.content.Context;
import android.content.pm.ApplicationInfo;
import android.content.pm.IPackageManager;
import android.content.pm.PackageManager;
import android.net.ConnectivityManager;
import android.net.NetworkCapabilities;
import android.net.NetworkInfo;
import android.net.NetworkInfo.DetailedState;
import android.net.NetworkInfo.State;
import android.net.NetworkKey;
import android.net.NetworkScoreManager;
import android.net.NetworkScorerAppData;
import android.net.ScoredNetwork;
import android.net.wifi.IWifiManager;
import android.net.wifi.ScanResult;
import android.net.wifi.WifiConfiguration;
import android.net.wifi.WifiConfiguration.KeyMgmt;
import android.net.wifi.WifiEnterpriseConfig;
import android.net.wifi.WifiInfo;
import android.net.wifi.WifiManager;
import android.net.wifi.WifiNetworkScoreCache;
import android.net.wifi.hotspot2.OsuProvider;
import android.net.wifi.hotspot2.PasspointConfiguration;
import android.net.wifi.hotspot2.ProvisioningCallback;
import android.os.Bundle;
import android.os.Parcelable;
import android.os.RemoteException;
import android.os.ServiceManager;
import android.os.SystemClock;
import android.os.UserHandle;
import android.provider.Settings;
import android.text.TextUtils;
import android.util.ArraySet;
import android.util.Log;
import android.util.Pair;

import androidx.annotation.GuardedBy;
import androidx.annotation.NonNull;

import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.util.CollectionUtils;
import com.android.settingslib.R;
import com.android.settingslib.utils.ThreadUtils;

import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.atomic.AtomicInteger;

/**
 * Represents a selectable Wifi Network for use in various wifi selection menus backed by
 * {@link WifiTracker}.
 *
 * <p>An AccessPoint, which would be more fittingly named "WifiNetwork", is an aggregation of
 * {@link ScanResult ScanResults} along with pertinent metadata (e.g. current connection info,
 * network scores) required to successfully render the network to the user.
 */
public class AccessPoint implements Comparable<AccessPoint> {
    static final String TAG = "SettingsLib.AccessPoint";

    /**
     * Lower bound on the 2.4 GHz (802.11b/g/n) WLAN channels
     */
    public static final int LOWER_FREQ_24GHZ = 2400;

    /**
     * Upper bound on the 2.4 GHz (802.11b/g/n) WLAN channels
     */
    public static final int HIGHER_FREQ_24GHZ = 2500;

    /**
     * Lower bound on the 5.0 GHz (802.11a/h/j/n/ac) WLAN channels
     */
    public static final int LOWER_FREQ_5GHZ = 4900;

    /**
     * Upper bound on the 5.0 GHz (802.11a/h/j/n/ac) WLAN channels
     */
    public static final int HIGHER_FREQ_5GHZ = 5900;

    /** The key which identifies this AccessPoint grouping. */
    private String mKey;

    /**
     * Synchronization lock for managing concurrency between main and worker threads.
     *
     * <p>This lock should be held for all modifications to {@link #mScanResults} and
     * {@link #mExtraScanResults}.
     */
    private final Object mLock = new Object();

    @IntDef({Speed.NONE, Speed.SLOW, Speed.MODERATE, Speed.FAST, Speed.VERY_FAST})
    @Retention(RetentionPolicy.SOURCE)
    public @interface Speed {
        /**
         * Constant value representing an unlabeled / unscored network.
         */
        int NONE = 0;
        /**
         * Constant value representing a slow speed network connection.
         */
        int SLOW = 5;
        /**
         * Constant value representing a medium speed network connection.
         */
        int MODERATE = 10;
        /**
         * Constant value representing a fast speed network connection.
         */
        int FAST = 20;
        /**
         * Constant value representing a very fast speed network connection.
         */
        int VERY_FAST = 30;
    }

    @IntDef({PasspointConfigurationVersion.INVALID,
            PasspointConfigurationVersion.NO_OSU_PROVISIONED,
            PasspointConfigurationVersion.OSU_PROVISIONED})
    @Retention(RetentionPolicy.SOURCE)
    public @interface PasspointConfigurationVersion {
        int INVALID = 0;
        int NO_OSU_PROVISIONED = 1; // R1.
        int OSU_PROVISIONED = 2;    // R2 or R3.
    }

    /** The underlying set of scan results comprising this AccessPoint. */
    @GuardedBy("mLock")
    private final ArraySet<ScanResult> mScanResults = new ArraySet<>();

    /**
     * Extra set of unused scan results corresponding to this AccessPoint for verbose logging
     * purposes, such as a set of Passpoint roaming scan results when home scans are available.
     */
    @GuardedBy("mLock")
    private final ArraySet<ScanResult> mExtraScanResults = new ArraySet<>();

    /**
     * Map of BSSIDs to scored networks for individual bssids.
     *
     * <p>This cache should not be evicted with scan results, as the values here are used to
     * generate a fallback in the absence of scores for the visible APs.
     */
    private final Map<String, TimestampedScoredNetwork> mScoredNetworkCache = new HashMap<>();

    static final String KEY_NETWORKINFO = "key_networkinfo";
    static final String KEY_WIFIINFO = "key_wifiinfo";
    static final String KEY_SSID = "key_ssid";
    static final String KEY_SECURITY = "key_security";
    static final String KEY_SPEED = "key_speed";
    static final String KEY_PSKTYPE = "key_psktype";
    static final String KEY_SCANRESULTS = "key_scanresults";
    static final String KEY_SCOREDNETWORKCACHE = "key_scorednetworkcache";
    static final String KEY_CONFIG = "key_config";
    static final String KEY_FQDN = "key_fqdn";
    static final String KEY_PROVIDER_FRIENDLY_NAME = "key_provider_friendly_name";
    static final String KEY_IS_CARRIER_AP = "key_is_carrier_ap";
    static final String KEY_CARRIER_AP_EAP_TYPE = "key_carrier_ap_eap_type";
    static final String KEY_CARRIER_NAME = "key_carrier_name";
    static final String KEY_EAPTYPE = "eap_psktype";
    static final String KEY_SUBSCRIPTION_EXPIRATION_TIME_IN_MILLIS  =
            "key_subscription_expiration_time_in_millis";
    static final String KEY_PASSPOINT_CONFIGURATION_VERSION = "key_passpoint_configuration_version";
    static final AtomicInteger sLastId = new AtomicInteger(0);

    /*
     * NOTE: These constants for security and PSK types are saved to the bundle in saveWifiState,
     * and sent across IPC. The numeric values should remain stable, otherwise the changes will need
     * to be synced with other unbundled users of this library.
     */
    public static final int SECURITY_NONE = 0;
    public static final int SECURITY_WEP = 1;
    public static final int SECURITY_PSK = 2;
    public static final int SECURITY_EAP = 3;
    public static final int SECURITY_OWE = 4;
    public static final int SECURITY_SAE = 5;
    public static final int SECURITY_EAP_SUITE_B = 6;
    public static final int SECURITY_PSK_SAE_TRANSITION = 7;
    public static final int SECURITY_OWE_TRANSITION = 8;
    public static final int SECURITY_MAX_VAL = 9; // Has to be the last

    private static final int PSK_UNKNOWN = 0;
    private static final int PSK_WPA = 1;
    private static final int PSK_WPA2 = 2;
    private static final int PSK_WPA_WPA2 = 3;
    private static final int PSK_SAE = 4;

    private static final int EAP_UNKNOWN = 0;
    private static final int EAP_WPA = 1; // WPA-EAP
    private static final int EAP_WPA2_WPA3 = 2; // RSN-EAP

    /**
     * The number of distinct wifi levels.
     *
     * <p>Must keep in sync with {@link R.array.wifi_signal} and {@link WifiManager#RSSI_LEVELS}.
     */
    public static final int SIGNAL_LEVELS = 5;

    public static final int UNREACHABLE_RSSI = Integer.MIN_VALUE;

    public static final String KEY_PREFIX_AP = "AP:";
    public static final String KEY_PREFIX_FQDN = "FQDN:";
    public static final String KEY_PREFIX_OSU = "OSU:";

    private final Context mContext;

    private WifiManager mWifiManager;
    private WifiManager.ActionListener mConnectListener;

    private String ssid;
    private String bssid;
    private int security;
    private int networkId = WifiConfiguration.INVALID_NETWORK_ID;

    private int pskType = PSK_UNKNOWN;
    private int mEapType = EAP_UNKNOWN;

    private WifiConfiguration mConfig;

    private int mRssi = UNREACHABLE_RSSI;

    private WifiInfo mInfo;
    private NetworkInfo mNetworkInfo;
    AccessPointListener mAccessPointListener;

    private Object mTag;

    @Speed private int mSpeed = Speed.NONE;
    private boolean mIsScoredNetworkMetered = false;

    /**
     * Information associated with the {@link PasspointConfiguration}.  Only maintaining
     * the relevant info to preserve spaces.
     */
    private String mFqdn;
    private String mProviderFriendlyName;
    private boolean mIsRoaming = false;
    private long mSubscriptionExpirationTimeInMillis;
    @PasspointConfigurationVersion private int mPasspointConfigurationVersion =
            PasspointConfigurationVersion.INVALID;

    private boolean mIsCarrierAp = false;

    private OsuProvider mOsuProvider;

    private String mOsuStatus;
    private String mOsuFailure;
    private boolean mOsuProvisioningComplete = false;

    /**
     * The EAP type {@link WifiEnterpriseConfig.Eap} associated with this AP if it is a carrier AP.
     */
    private int mCarrierApEapType = WifiEnterpriseConfig.Eap.NONE;
    private String mCarrierName = null;

    public AccessPoint(Context context, Bundle savedState) {
        mContext = context;

        if (savedState.containsKey(KEY_CONFIG)) {
            mConfig = savedState.getParcelable(KEY_CONFIG);
        }
        if (mConfig != null) {
            loadConfig(mConfig);
        }
        if (savedState.containsKey(KEY_SSID)) {
            ssid = savedState.getString(KEY_SSID);
        }
        if (savedState.containsKey(KEY_SECURITY)) {
            security = savedState.getInt(KEY_SECURITY);
        }
        if (savedState.containsKey(KEY_SPEED)) {
            mSpeed = savedState.getInt(KEY_SPEED);
        }
        if (savedState.containsKey(KEY_PSKTYPE)) {
            pskType = savedState.getInt(KEY_PSKTYPE);
        }
        if (savedState.containsKey(KEY_EAPTYPE)) {
            mEapType = savedState.getInt(KEY_EAPTYPE);
        }
        mInfo = savedState.getParcelable(KEY_WIFIINFO);
        if (savedState.containsKey(KEY_NETWORKINFO)) {
            mNetworkInfo = savedState.getParcelable(KEY_NETWORKINFO);
        }
        if (savedState.containsKey(KEY_SCANRESULTS)) {
            Parcelable[] scanResults = savedState.getParcelableArray(KEY_SCANRESULTS);
            mScanResults.clear();
            for (Parcelable result : scanResults) {
                mScanResults.add((ScanResult) result);
            }
        }
        if (savedState.containsKey(KEY_SCOREDNETWORKCACHE)) {
            ArrayList<TimestampedScoredNetwork> scoredNetworkArrayList =
                    savedState.getParcelableArrayList(KEY_SCOREDNETWORKCACHE);
            for (TimestampedScoredNetwork timedScore : scoredNetworkArrayList) {
                mScoredNetworkCache.put(timedScore.getScore().networkKey.wifiKey.bssid, timedScore);
            }
        }
        if (savedState.containsKey(KEY_FQDN)) {
            mFqdn = savedState.getString(KEY_FQDN);
        }
        if (savedState.containsKey(KEY_PROVIDER_FRIENDLY_NAME)) {
            mProviderFriendlyName = savedState.getString(KEY_PROVIDER_FRIENDLY_NAME);
        }
        if (savedState.containsKey(KEY_IS_CARRIER_AP)) {
            mIsCarrierAp = savedState.getBoolean(KEY_IS_CARRIER_AP);
        }
        if (savedState.containsKey(KEY_CARRIER_AP_EAP_TYPE)) {
            mCarrierApEapType = savedState.getInt(KEY_CARRIER_AP_EAP_TYPE);
        }
        if (savedState.containsKey(KEY_CARRIER_NAME)) {
            mCarrierName = savedState.getString(KEY_CARRIER_NAME);
        }
        if (savedState.containsKey(KEY_SUBSCRIPTION_EXPIRATION_TIME_IN_MILLIS)) {
            mSubscriptionExpirationTimeInMillis =
                    savedState.getLong(KEY_SUBSCRIPTION_EXPIRATION_TIME_IN_MILLIS);
        }
        if (savedState.containsKey(KEY_PASSPOINT_CONFIGURATION_VERSION)) {
            mPasspointConfigurationVersion = savedState.getInt(KEY_PASSPOINT_CONFIGURATION_VERSION);
        }
        update(mConfig, mInfo, mNetworkInfo);

        // Calculate required fields
        updateKey();
        updateBestRssiInfo();
    }

    /**
     * Creates an AccessPoint with only a WifiConfiguration. This is used for the saved networks
     * page.
     */
    public AccessPoint(Context context, WifiConfiguration config) {
        mContext = context;
        loadConfig(config);
        updateKey();
    }

    /**
     * Initialize an AccessPoint object for a {@link PasspointConfiguration}.  This is mainly
     * used by "Saved Networks" page for managing the saved {@link PasspointConfiguration}.
     */
    public AccessPoint(Context context, PasspointConfiguration config) {
        mContext = context;
        mFqdn = config.getHomeSp().getFqdn();
        mProviderFriendlyName = config.getHomeSp().getFriendlyName();
        mSubscriptionExpirationTimeInMillis = config.getSubscriptionExpirationTimeInMillis();
        if (config.isOsuProvisioned()) {
            mPasspointConfigurationVersion = PasspointConfigurationVersion.OSU_PROVISIONED;
        } else {
            mPasspointConfigurationVersion = PasspointConfigurationVersion.NO_OSU_PROVISIONED;
        }
        updateKey();
    }

    /**
     * Initialize an AccessPoint object for a Passpoint network.
     */
    public AccessPoint(@NonNull Context context, @NonNull WifiConfiguration config,
            @Nullable Collection<ScanResult> homeScans,
            @Nullable Collection<ScanResult> roamingScans) {
        mContext = context;
        networkId = config.networkId;
        mConfig = config;
        mFqdn = config.FQDN;
        setScanResultsPasspoint(homeScans, roamingScans);
        updateKey();
    }

    /**
     * Initialize an AccessPoint object for a Passpoint OSU Provider.
     */
    public AccessPoint(@NonNull Context context, @NonNull OsuProvider provider,
            @NonNull Collection<ScanResult> results) {
        mContext = context;
        mOsuProvider = provider;
        setScanResults(results);
        updateKey();
    }

    AccessPoint(Context context, Collection<ScanResult> results) {
        mContext = context;
        setScanResults(results);
        updateKey();
    }

    @VisibleForTesting void loadConfig(WifiConfiguration config) {
        ssid = (config.SSID == null ? "" : removeDoubleQuotes(config.SSID));
        bssid = config.BSSID;
        security = getSecurity(config);
        networkId = config.networkId;
        mConfig = config;
    }

    /** Updates {@link #mKey} and should only called upon object creation/initialization. */
    private void updateKey() {
        // TODO(sghuman): Consolidate Key logic on ScanResultMatchInfo
        if (isPasspoint()) {
            mKey = getKey(mConfig);
        } else if (isPasspointConfig()) {
            mKey = getKey(mFqdn);
        } else if (isOsuProvider()) {
            mKey = getKey(mOsuProvider);
        } else { // Non-Passpoint AP
            mKey = getKey(getSsidStr(), getBssid(), getSecurity());
        }
    }

    /**
    * Returns a negative integer, zero, or a positive integer if this AccessPoint is less than,
    * equal to, or greater than the other AccessPoint.
    *
    * Sort order rules for AccessPoints:
    *   1. Active before inactive
    *   2. Reachable before unreachable
    *   3. Saved before unsaved
    *   4. Network speed value
    *   5. Stronger signal before weaker signal
    *   6. SSID alphabetically
    *
    * Note that AccessPoints with a signal are usually also Reachable,
    * and will thus appear before unreachable saved AccessPoints.
    */
    @Override
    public int compareTo(@NonNull AccessPoint other) {
        // Active one goes first.
        if (isActive() && !other.isActive()) return -1;
        if (!isActive() && other.isActive()) return 1;

        // Reachable one goes before unreachable one.
        if (isReachable() && !other.isReachable()) return -1;
        if (!isReachable() && other.isReachable()) return 1;

        // Configured (saved) one goes before unconfigured one.
        if (isSaved() && !other.isSaved()) return -1;
        if (!isSaved() && other.isSaved()) return 1;

        // Faster speeds go before slower speeds - but only if visible change in speed label
        if (getSpeed() != other.getSpeed()) {
            return other.getSpeed() - getSpeed();
        }

        // Sort by signal strength, bucketed by level
        int difference = WifiManager.calculateSignalLevel(other.mRssi, SIGNAL_LEVELS)
                - WifiManager.calculateSignalLevel(mRssi, SIGNAL_LEVELS);
        if (difference != 0) {
            return difference;
        }

        // Sort by title.
        difference = getTitle().compareToIgnoreCase(other.getTitle());
        if (difference != 0) {
            return difference;
        }

        // Do a case sensitive comparison to distinguish SSIDs that differ in case only
        return getSsidStr().compareTo(other.getSsidStr());
    }

    @Override
    public boolean equals(Object other) {
        if (!(other instanceof AccessPoint)) return false;
        return (this.compareTo((AccessPoint) other) == 0);
    }

    @Override
    public int hashCode() {
        int result = 0;
        if (mInfo != null) result += 13 * mInfo.hashCode();
        result += 19 * mRssi;
        result += 23 * networkId;
        result += 29 * ssid.hashCode();
        return result;
    }

    @Override
    public String toString() {
        StringBuilder builder = new StringBuilder().append("AccessPoint(")
                .append(ssid);
        if (bssid != null) {
            builder.append(":").append(bssid);
        }
        if (isSaved()) {
            builder.append(',').append("saved");
        }
        if (isActive()) {
            builder.append(',').append("active");
        }
        if (isEphemeral()) {
            builder.append(',').append("ephemeral");
        }
        if (isConnectable()) {
            builder.append(',').append("connectable");
        }
        if ((security != SECURITY_NONE) && (security != SECURITY_OWE)) {
            builder.append(',').append(securityToString(security, pskType));
        }
        builder.append(",level=").append(getLevel());
        if (mSpeed != Speed.NONE) {
            builder.append(",speed=").append(mSpeed);
        }
        builder.append(",metered=").append(isMetered());

        if (isVerboseLoggingEnabled()) {
            builder.append(",rssi=").append(mRssi);
            synchronized (mLock) {
                builder.append(",scan cache size=").append(mScanResults.size()
                        + mExtraScanResults.size());
            }
        }

        return builder.append(')').toString();
    }

    /**
     * Updates the AccessPoint rankingScore, metering, and speed, returning true if the data has
     * changed.
     *
     * @param scoreCache The score cache to use to retrieve scores
     * @param scoringUiEnabled Whether to show scoring and badging UI
     * @param maxScoreCacheAgeMillis the maximum age in milliseconds of scores to consider when
     *         generating speed labels
     */
    boolean update(
            WifiNetworkScoreCache scoreCache,
            boolean scoringUiEnabled,
            long maxScoreCacheAgeMillis) {
        boolean scoreChanged = false;
        if (scoringUiEnabled) {
            scoreChanged = updateScores(scoreCache, maxScoreCacheAgeMillis);
        }
        return updateMetered(scoreCache) || scoreChanged;
    }

    /**
     * Updates the AccessPoint rankingScore and speed, returning true if the data has changed.
     *
     * <p>Any cached {@link TimestampedScoredNetwork} objects older than the given max age in millis
     * will be removed when this method is invoked.
     *
     * <p>Precondition: {@link #mRssi} is up to date before invoking this method.
     *
     * @param scoreCache The score cache to use to retrieve scores
     * @param maxScoreCacheAgeMillis the maximum age in milliseconds of scores to consider when
     *         generating speed labels
     *
     * @return true if the set speed has changed
     */
    private boolean updateScores(WifiNetworkScoreCache scoreCache, long maxScoreCacheAgeMillis) {
        long nowMillis = SystemClock.elapsedRealtime();
        synchronized (mLock) {
            for (ScanResult result : mScanResults) {
                ScoredNetwork score = scoreCache.getScoredNetwork(result);
                if (score == null) {
                    continue;
                }
                TimestampedScoredNetwork timedScore = mScoredNetworkCache.get(result.BSSID);
                if (timedScore == null) {
                    mScoredNetworkCache.put(
                            result.BSSID, new TimestampedScoredNetwork(score, nowMillis));
                } else {
                    // Update data since the has been seen in the score cache
                    timedScore.update(score, nowMillis);
                }
            }
        }

        // Remove old cached networks
        long evictionCutoff = nowMillis - maxScoreCacheAgeMillis;
        Iterator<TimestampedScoredNetwork> iterator = mScoredNetworkCache.values().iterator();
        iterator.forEachRemaining(timestampedScoredNetwork -> {
            if (timestampedScoredNetwork.getUpdatedTimestampMillis() < evictionCutoff) {
                iterator.remove();
            }
        });

        return updateSpeed();
    }

    /**
     * Updates the internal speed, returning true if the update resulted in a speed label change.
     */
    private boolean updateSpeed() {
        int oldSpeed = mSpeed;
        mSpeed = generateAverageSpeedForSsid();

        boolean changed = oldSpeed != mSpeed;
        if(isVerboseLoggingEnabled() && changed) {
            Log.i(TAG, String.format("%s: Set speed to %d", ssid, mSpeed));
        }
        return changed;
    }

    /** Creates a speed value for the current {@link #mRssi} by averaging all non zero badges. */
    @Speed private int generateAverageSpeedForSsid() {
        if (mScoredNetworkCache.isEmpty()) {
            return Speed.NONE;
        }

        if (Log.isLoggable(TAG, Log.DEBUG)) {
            Log.d(TAG, String.format("Generating fallbackspeed for %s using cache: %s",
                    getSsidStr(), mScoredNetworkCache));
        }

        // TODO(b/63073866): If flickering issues persist, consider mapping using getLevel rather
        // than specific rssi value so score doesn't change without a visible wifi bar change. This
        // issue is likely to be more evident for the active AP whose RSSI value is not half-lifed.

        int count = 0;
        int totalSpeed = 0;
        for (TimestampedScoredNetwork timedScore : mScoredNetworkCache.values()) {
            int speed = timedScore.getScore().calculateBadge(mRssi);
            if (speed != Speed.NONE) {
                count++;
                totalSpeed += speed;
            }
        }
        int speed = count == 0 ? Speed.NONE : totalSpeed / count;
        if (isVerboseLoggingEnabled()) {
            Log.i(TAG, String.format("%s generated fallback speed is: %d", getSsidStr(), speed));
        }
        return roundToClosestSpeedEnum(speed);
    }

    /**
     * Updates the AccessPoint's metering based on {@link ScoredNetwork#meteredHint}, returning
     * true if the metering changed.
     */
    private boolean updateMetered(WifiNetworkScoreCache scoreCache) {
        boolean oldMetering = mIsScoredNetworkMetered;
        mIsScoredNetworkMetered = false;

        if (isActive() && mInfo != null) {
            NetworkKey key = NetworkKey.createFromWifiInfo(mInfo);
            ScoredNetwork score = scoreCache.getScoredNetwork(key);
            if (score != null) {
                mIsScoredNetworkMetered |= score.meteredHint;
            }
        } else {
            synchronized (mLock) {
                for (ScanResult result : mScanResults) {
                    ScoredNetwork score = scoreCache.getScoredNetwork(result);
                    if (score == null) {
                        continue;
                    }
                    mIsScoredNetworkMetered |= score.meteredHint;
                }
            }
        }
        return oldMetering == mIsScoredNetworkMetered;
    }

    public static String getKey(ScanResult result) {
        return getKey(result.SSID, result.BSSID, getSecurity(result));
    }

    /**
     * Returns the AccessPoint key for a WifiConfiguration.
     * This will return a special Passpoint key if the config is for Passpoint.
     */
    public static String getKey(WifiConfiguration config) {
        if (config.isPasspoint()) {
            return getKey(config.FQDN);
        } else {
            return getKey(removeDoubleQuotes(config.SSID), config.BSSID, getSecurity(config));
        }
    }

    /**
     * Returns the AccessPoint key corresponding to a Passpoint network by its FQDN.
     */
    public static String getKey(String fqdn) {
        return new StringBuilder()
                .append(KEY_PREFIX_FQDN)
                .append(fqdn).toString();
    }

    /**
     * Returns the AccessPoint key corresponding to the OsuProvider.
     */
    public static String getKey(OsuProvider provider) {
        return new StringBuilder()
                .append(KEY_PREFIX_OSU)
                .append(provider.getFriendlyName())
                .append(',')
                .append(provider.getServerUri()).toString();
    }

    /**
     * Returns the AccessPoint key for a normal non-Passpoint network by ssid/bssid and security.
     */
    private static String getKey(String ssid, String bssid, int security) {
        StringBuilder builder = new StringBuilder();
        builder.append(KEY_PREFIX_AP);
        if (TextUtils.isEmpty(ssid)) {
            builder.append(bssid);
        } else {
            builder.append(ssid);
        }
        builder.append(',').append(security);
        return builder.toString();
    }

    public String getKey() {
        return mKey;
    }

    /**
     * Determines if the other AccessPoint represents the same network as this AccessPoint
     */
    public boolean matches(AccessPoint other) {
        return getKey().equals(other.getKey());
    }

    public boolean matches(WifiConfiguration config) {
        if (config.isPasspoint()) {
            return (isPasspoint() && config.FQDN.equals(mConfig.FQDN));
        }

        if (!ssid.equals(removeDoubleQuotes(config.SSID))
                || (mConfig != null && mConfig.shared != config.shared)) {
            return false;
        }
        return security == getSecurity(config);
    }

    public WifiConfiguration getConfig() {
        return mConfig;
    }

    public String getPasspointFqdn() {
        return mFqdn;
    }

    public void clearConfig() {
        mConfig = null;
        networkId = WifiConfiguration.INVALID_NETWORK_ID;
    }

    public WifiInfo getInfo() {
        return mInfo;
    }

    /**
     * Returns the number of levels to show for a Wifi icon, from 0 to {@link #SIGNAL_LEVELS}-1.
     *
     * <p>Use {@#isReachable()} to determine if an AccessPoint is in range, as this method will
     * always return at least 0.
     */
    public int getLevel() {
        return WifiManager.calculateSignalLevel(mRssi, SIGNAL_LEVELS);
    }

    public int getRssi() {
        return mRssi;
    }

    /**
     * Returns the underlying scan result set.
     *
     * <p>Callers should not modify this set.
     */
    public Set<ScanResult> getScanResults() {
        Set<ScanResult> allScans = new ArraySet<>();
        synchronized (mLock) {
            allScans.addAll(mScanResults);
            allScans.addAll(mExtraScanResults);
        }
        return allScans;
    }

    public Map<String, TimestampedScoredNetwork> getScoredNetworkCache() {
        return mScoredNetworkCache;
    }

    /**
     * Updates {@link #mRssi} and sets scan result information to that of the best RSSI scan result.
     *
     * <p>If the given connection is active, the existing value of {@link #mRssi} will be returned.
     * If the given AccessPoint is not active, a value will be calculated from previous scan
     * results, returning the best RSSI for all matching AccessPoints averaged with the previous
     * value. If the access point is not connected and there are no scan results, the rssi will be
     * set to {@link #UNREACHABLE_RSSI}.
     */
    private void updateBestRssiInfo() {
        if (this.isActive()) {
            return;
        }

        ScanResult bestResult = null;
        int bestRssi = UNREACHABLE_RSSI;
        synchronized (mLock) {
            for (ScanResult result : mScanResults) {
                if (result.level > bestRssi) {
                    bestRssi = result.level;
                    bestResult = result;
                }
            }
        }

        // Set the rssi to the average of the current rssi and the previous rssi.
        if (bestRssi != UNREACHABLE_RSSI && mRssi != UNREACHABLE_RSSI) {
            mRssi = (mRssi + bestRssi) / 2;
        } else {
            mRssi = bestRssi;
        }

        if (bestResult != null) {
            ssid = bestResult.SSID;
            bssid = bestResult.BSSID;
            security = getSecurity(bestResult);
            if (security == SECURITY_PSK || security == SECURITY_SAE
                    || security == SECURITY_PSK_SAE_TRANSITION) {
                pskType = getPskType(bestResult);
            }
            if (security == SECURITY_EAP) {
                mEapType = getEapType(bestResult);
            }
            mIsCarrierAp = bestResult.isCarrierAp;
            mCarrierApEapType = bestResult.carrierApEapType;
            mCarrierName = bestResult.carrierName;
        }
        // Update the config SSID of a Passpoint network to that of the best RSSI
        if (isPasspoint()) {
            mConfig.SSID = convertToQuotedString(ssid);
        }
    }

    /**
     * Returns if the network should be considered metered.
     */
    public boolean isMetered() {
        return mIsScoredNetworkMetered
                || WifiConfiguration.isMetered(mConfig, mInfo);
    }

    public NetworkInfo getNetworkInfo() {
        return mNetworkInfo;
    }

    public int getSecurity() {
        return security;
    }

    public String getSecurityString(boolean concise) {
        Context context = mContext;
        if (isPasspoint() || isPasspointConfig()) {
            return concise ? context.getString(R.string.wifi_security_short_eap) :
                context.getString(R.string.wifi_security_eap);
        }
        switch(security) {
            case SECURITY_EAP:
                switch (mEapType) {
                    case EAP_WPA:
                        return concise ? context.getString(R.string.wifi_security_short_eap_wpa) :
                                context.getString(R.string.wifi_security_eap_wpa);
                    case EAP_WPA2_WPA3:
                        return concise
                                ? context.getString(R.string.wifi_security_short_eap_wpa2_wpa3) :
                                context.getString(R.string.wifi_security_eap_wpa2_wpa3);
                    case EAP_UNKNOWN:
                    default:
                        return concise
                                ? context.getString(R.string.wifi_security_short_eap) :
                                context.getString(R.string.wifi_security_eap);
                }
            case SECURITY_EAP_SUITE_B:
                return concise ? context.getString(R.string.wifi_security_short_eap_suiteb) :
                        context.getString(R.string.wifi_security_eap_suiteb);
            case SECURITY_PSK:
                switch (pskType) {
                    case PSK_WPA:
                        return concise ? context.getString(R.string.wifi_security_short_wpa) :
                            context.getString(R.string.wifi_security_wpa);
                    case PSK_WPA2:
                        return concise ? context.getString(R.string.wifi_security_short_wpa2) :
                            context.getString(R.string.wifi_security_wpa2);
                    case PSK_WPA_WPA2:
                        return concise ? context.getString(R.string.wifi_security_short_wpa_wpa2) :
                            context.getString(R.string.wifi_security_wpa_wpa2);
                    case PSK_UNKNOWN:
                    default:
                        return concise ? context.getString(R.string.wifi_security_short_psk_generic)
                                : context.getString(R.string.wifi_security_psk_generic);
                }
            case SECURITY_WEP:
                return concise ? context.getString(R.string.wifi_security_short_wep) :
                    context.getString(R.string.wifi_security_wep);
            case SECURITY_SAE:
            case SECURITY_PSK_SAE_TRANSITION:
                if (pskType == PSK_SAE) {
                    return concise ? context.getString(R.string.wifi_security_short_psk_sae) :
                            context.getString(R.string.wifi_security_psk_sae);
                } else {
                    return concise ? context.getString(R.string.wifi_security_short_sae) :
                            context.getString(R.string.wifi_security_sae);
                }
            case SECURITY_OWE_TRANSITION:
                if (mConfig != null && getSecurity(mConfig) == SECURITY_OWE) {
                    return concise ? context.getString(R.string.wifi_security_short_owe) :
                            context.getString(R.string.wifi_security_owe);
                }
                return concise ? "" : context.getString(R.string.wifi_security_none);
            case SECURITY_OWE:
                return concise ? context.getString(R.string.wifi_security_short_owe) :
                    context.getString(R.string.wifi_security_owe);
            case SECURITY_NONE:
            default:
                return concise ? "" : context.getString(R.string.wifi_security_none);
        }
    }

    public String getSsidStr() {
        return ssid;
    }

    public String getBssid() {
        return bssid;
    }

    public CharSequence getSsid() {
        return ssid;
    }

    /**
     * Returns the name associated with the stored config.
     * @deprecated Please use {@link #getTitle()} instead to get the display name of an AccessPoint.
     */
    @Deprecated
    public String getConfigName() {
        if (mConfig != null && mConfig.isPasspoint()) {
            return mConfig.providerFriendlyName;
        } else if (mFqdn != null) {
            return mProviderFriendlyName;
        } else {
            return ssid;
        }
    }

    public DetailedState getDetailedState() {
        if (mNetworkInfo != null) {
            return mNetworkInfo.getDetailedState();
        }
        Log.w(TAG, "NetworkInfo is null, cannot return detailed state");
        return null;
    }

    public boolean isCarrierAp() {
        return mIsCarrierAp;
    }

    public int getCarrierApEapType() {
        return mCarrierApEapType;
    }

    public String getCarrierName() {
        return mCarrierName;
    }

    public String getSavedNetworkSummary() {
        WifiConfiguration config = mConfig;
        if (config != null) {
            PackageManager pm = mContext.getPackageManager();
            String systemName = pm.getNameForUid(android.os.Process.SYSTEM_UID);
            int userId = UserHandle.getUserId(config.creatorUid);
            ApplicationInfo appInfo = null;
            if (config.creatorName != null && config.creatorName.equals(systemName)) {
                appInfo = mContext.getApplicationInfo();
            } else {
                try {
                    IPackageManager ipm = AppGlobals.getPackageManager();
                    appInfo = ipm.getApplicationInfo(config.creatorName, 0 /* flags */, userId);
                } catch (RemoteException rex) {
                }
            }
            if (appInfo != null &&
                    !appInfo.packageName.equals(mContext.getString(R.string.settings_package)) &&
                    !appInfo.packageName.equals(
                    mContext.getString(R.string.certinstaller_package))) {
                return mContext.getString(R.string.saved_network, appInfo.loadLabel(pm));
            }
        }

        if (isPasspointConfigurationR1() && isExpired()) {
            return mContext.getString(R.string.wifi_passpoint_expired);
        }
        return "";
    }

    /**
     * Returns the display title for the AccessPoint, such as for an AccessPointPreference's title.
     */
    public String getTitle() {
        if (isPasspoint()) {
            return mConfig.providerFriendlyName;
        } else if (isPasspointConfig()) {
            return mProviderFriendlyName;
        } else if (isOsuProvider()) {
            return mOsuProvider.getFriendlyName();
        } else {
            return getSsidStr();
        }
    }

    public String getSummary() {
        return getSettingsSummary();
    }

    public String getSettingsSummary() {
        return getSettingsSummary(false /*convertSavedAsDisconnected*/);
    }

    /**
     * Returns the summary for the AccessPoint.
     */
    public String getSettingsSummary(boolean convertSavedAsDisconnected) {
        if (isPasspointConfigurationR1() && isExpired()) {
            return mContext.getString(R.string.wifi_passpoint_expired);
        }

        // Update to new summary
        StringBuilder summary = new StringBuilder();

        if (isOsuProvider()) {
            if (mOsuProvisioningComplete) {
                summary.append(mContext.getString(R.string.osu_sign_up_complete));
            } else if (mOsuFailure != null) {
                summary.append(mOsuFailure);
            } else if (mOsuStatus != null) {
                summary.append(mOsuStatus);
            } else {
                summary.append(mContext.getString(R.string.tap_to_sign_up));
            }
        } else if (isActive()) {
            if (getDetailedState() == DetailedState.CONNECTED && mIsCarrierAp) {
                // This is the active connection on a carrier AP
                summary.append(String.format(mContext.getString(R.string.connected_via_carrier),
                        mCarrierName));
            } else {
                summary.append(getSummary(mContext, /* ssid */ null, getDetailedState(),
                        mInfo != null && mInfo.isEphemeral(),
                        mInfo != null ? mInfo.getNetworkSuggestionOrSpecifierPackageName() : null));
            }
        } else { // not active
            if (mConfig != null && mConfig.hasNoInternetAccess()) {
                int messageID = mConfig.getNetworkSelectionStatus().isNetworkPermanentlyDisabled()
                        ? R.string.wifi_no_internet_no_reconnect
                        : R.string.wifi_no_internet;
                summary.append(mContext.getString(messageID));
            } else if (mConfig != null && !mConfig.getNetworkSelectionStatus().isNetworkEnabled()) {
                WifiConfiguration.NetworkSelectionStatus networkStatus =
                        mConfig.getNetworkSelectionStatus();
                switch (networkStatus.getNetworkSelectionDisableReason()) {
                    case WifiConfiguration.NetworkSelectionStatus.DISABLED_AUTHENTICATION_FAILURE:
                        summary.append(mContext.getString(R.string.wifi_disabled_password_failure));
                        break;
                    case WifiConfiguration.NetworkSelectionStatus.DISABLED_BY_WRONG_PASSWORD:
                        summary.append(mContext.getString(R.string.wifi_check_password_try_again));
                        break;
                    case WifiConfiguration.NetworkSelectionStatus.DISABLED_DHCP_FAILURE:
                    case WifiConfiguration.NetworkSelectionStatus.DISABLED_DNS_FAILURE:
                        summary.append(mContext.getString(R.string.wifi_disabled_network_failure));
                        break;
                    case WifiConfiguration.NetworkSelectionStatus.DISABLED_ASSOCIATION_REJECTION:
                        summary.append(mContext.getString(R.string.wifi_disabled_generic));
                        break;
                }
            } else if (mConfig != null && mConfig.getNetworkSelectionStatus().isNotRecommended()) {
                summary.append(mContext.getString(
                        R.string.wifi_disabled_by_recommendation_provider));
            } else if (mIsCarrierAp) {
                summary.append(String.format(mContext.getString(
                        R.string.available_via_carrier), mCarrierName));
            } else if (!isReachable()) { // Wifi out of range
                summary.append(mContext.getString(R.string.wifi_not_in_range));
            } else { // In range, not disabled.
                if (mConfig != null) { // Is saved network
                    // Last attempt to connect to this failed. Show reason why
                    switch (mConfig.recentFailure.getAssociationStatus()) {
                        case WifiConfiguration.RecentFailure.STATUS_AP_UNABLE_TO_HANDLE_NEW_STA:
                            summary.append(mContext.getString(
                                    R.string.wifi_ap_unable_to_handle_new_sta));
                            break;
                        default:
                            if (convertSavedAsDisconnected) {
                                // Disconnected
                                summary.append(mContext.getString(R.string.wifi_disconnected));
                            } else {
                                // "Saved"
                                summary.append(mContext.getString(R.string.wifi_remembered));
                            }
                            break;
                    }
                }
            }
        }



        if (isVerboseLoggingEnabled()) {
            summary.append(WifiUtils.buildLoggingSummary(this, mConfig));
        }

        if (mConfig != null && (WifiUtils.isMeteredOverridden(mConfig) || mConfig.meteredHint)) {
            return mContext.getResources().getString(
                    R.string.preference_summary_default_combination,
                    WifiUtils.getMeteredLabel(mContext, mConfig),
                    summary.toString());
        }

        // If Speed label and summary are both present, use the preference combination to combine
        // the two, else return the non-null one.
        if (getSpeedLabel() != null && summary.length() != 0) {
            return mContext.getResources().getString(
                    R.string.preference_summary_default_combination,
                    getSpeedLabel(),
                    summary.toString());
        } else if (getSpeedLabel() != null) {
            return getSpeedLabel();
        } else {
            return summary.toString();
        }
    }

    /**
     * Return whether this is the active connection.
     * For ephemeral connections (networkId is invalid), this returns false if the network is
     * disconnected.
     */
    public boolean isActive() {
        return mNetworkInfo != null &&
                (networkId != WifiConfiguration.INVALID_NETWORK_ID ||
                 mNetworkInfo.getState() != State.DISCONNECTED);
    }

    public boolean isConnectable() {
        return getLevel() != -1 && getDetailedState() == null;
    }

    public boolean isEphemeral() {
        return mInfo != null && mInfo.isEphemeral() &&
                mNetworkInfo != null && mNetworkInfo.getState() != State.DISCONNECTED;
    }

    /**
     * Return true if this AccessPoint represents a Passpoint AP.
     */
    public boolean isPasspoint() {
        return mConfig != null && mConfig.isPasspoint();
    }

    /**
     * Return true if this AccessPoint represents a Passpoint provider configuration.
     */
    public boolean isPasspointConfig() {
        return mFqdn != null && mConfig == null;
    }

    /**
     * Return true if this AccessPoint represents an OSU Provider.
     */
    public boolean isOsuProvider() {
        return mOsuProvider != null;
    }

    /**
     * Return true if this AccessPoint is expired.
     */
    public boolean isExpired() {
        if (mSubscriptionExpirationTimeInMillis <= 0) {
            // Expiration time not specified.
            return false;
        } else {
            return System.currentTimeMillis() >= mSubscriptionExpirationTimeInMillis;
        }
    }

    public boolean isPasspointConfigurationR1() {
        return mPasspointConfigurationVersion == PasspointConfigurationVersion.NO_OSU_PROVISIONED;
    }

    /**
     * Return true if {@link PasspointConfiguration#isOsuProvisioned} is true, this may refer to R2
     * or R3.
     */
    public boolean isPasspointConfigurationOsuProvisioned() {
        return mPasspointConfigurationVersion == PasspointConfigurationVersion.OSU_PROVISIONED;
    }

    /**
     * Starts the OSU Provisioning flow.
     */
    public void startOsuProvisioning(@Nullable WifiManager.ActionListener connectListener) {
        mConnectListener = connectListener;

        getWifiManager().startSubscriptionProvisioning(
                mOsuProvider,
                mContext.getMainExecutor(),
                new AccessPointProvisioningCallback()
        );
    }

    /**
     * Return whether the given {@link WifiInfo} is for this access point.
     * If the current AP does not have a network Id then the config is used to
     * match based on SSID and security.
     */
    private boolean isInfoForThisAccessPoint(WifiConfiguration config, WifiInfo info) {
        if (info.isOsuAp() || mOsuStatus != null) {
            return (info.isOsuAp() && mOsuStatus != null);
        } else if (info.isPasspointAp() || isPasspoint()) {
            return (info.isPasspointAp() && isPasspoint()
                    && TextUtils.equals(info.getPasspointFqdn(), mConfig.FQDN));
        }

        if (networkId != WifiConfiguration.INVALID_NETWORK_ID) {
            return networkId == info.getNetworkId();
        } else if (config != null) {
            return isKeyEqual(getKey(config));
        } else {
            // Might be an ephemeral connection with no WifiConfiguration. Try matching on SSID.
            // (Note that we only do this if the WifiConfiguration explicitly equals INVALID).
            // TODO: Handle hex string SSIDs.
            return TextUtils.equals(removeDoubleQuotes(info.getSSID()), ssid);
        }
    }

    public boolean isSaved() {
        return mConfig != null;
    }

    public Object getTag() {
        return mTag;
    }

    public void setTag(Object tag) {
        mTag = tag;
    }

    /**
     * Generate and save a default wifiConfiguration with common values.
     * Can only be called for unsecured networks.
     */
    public void generateOpenNetworkConfig() {
        if (!isOpenNetwork()) {
            throw new IllegalStateException();
        }
        if (mConfig != null)
            return;
        mConfig = new WifiConfiguration();
        mConfig.SSID = AccessPoint.convertToQuotedString(ssid);

        if (security == SECURITY_NONE || !getWifiManager().isEasyConnectSupported()) {
            mConfig.allowedKeyManagement.set(KeyMgmt.NONE);
        } else {
            mConfig.allowedKeyManagement.set(KeyMgmt.OWE);
            mConfig.requirePMF = true;
        }
    }

    public void saveWifiState(Bundle savedState) {
        if (ssid != null) savedState.putString(KEY_SSID, getSsidStr());
        savedState.putInt(KEY_SECURITY, security);
        savedState.putInt(KEY_SPEED, mSpeed);
        savedState.putInt(KEY_PSKTYPE, pskType);
        savedState.putInt(KEY_EAPTYPE, mEapType);
        if (mConfig != null) savedState.putParcelable(KEY_CONFIG, mConfig);
        savedState.putParcelable(KEY_WIFIINFO, mInfo);
        synchronized (mLock) {
            savedState.putParcelableArray(KEY_SCANRESULTS,
                    mScanResults.toArray(new Parcelable[mScanResults.size()
                            + mExtraScanResults.size()]));
        }
        savedState.putParcelableArrayList(KEY_SCOREDNETWORKCACHE,
                new ArrayList<>(mScoredNetworkCache.values()));
        if (mNetworkInfo != null) {
            savedState.putParcelable(KEY_NETWORKINFO, mNetworkInfo);
        }
        if (mFqdn != null) {
            savedState.putString(KEY_FQDN, mFqdn);
        }
        if (mProviderFriendlyName != null) {
            savedState.putString(KEY_PROVIDER_FRIENDLY_NAME, mProviderFriendlyName);
        }
        savedState.putBoolean(KEY_IS_CARRIER_AP, mIsCarrierAp);
        savedState.putInt(KEY_CARRIER_AP_EAP_TYPE, mCarrierApEapType);
        savedState.putString(KEY_CARRIER_NAME, mCarrierName);
        savedState.putLong(KEY_SUBSCRIPTION_EXPIRATION_TIME_IN_MILLIS,
                mSubscriptionExpirationTimeInMillis);
        savedState.putInt(KEY_PASSPOINT_CONFIGURATION_VERSION, mPasspointConfigurationVersion);
    }

    public void setListener(AccessPointListener listener) {
        mAccessPointListener = listener;
    }

    private boolean isKeyEqual(String compareTo) {
        if (mKey == null) {
            return false;
        }
        return mKey.equals(compareTo);
    }

    /**
     * Sets {@link #mScanResults} to the given collection and updates info based on the best RSSI
     * scan result.
     *
     * @param scanResults a collection of scan results to add to the internal set
     */
    void setScanResults(Collection<ScanResult> scanResults) {
        if (CollectionUtils.isEmpty(scanResults)) {
            Log.d(TAG, "Cannot set scan results to empty list");
            return;
        }

        // Validate scan results are for current AP only by matching SSID/BSSID
        // Passpoint networks are not bound to a specific SSID/BSSID, so skip this for passpoint.
        if (mKey != null && !isPasspoint() && !isOsuProvider()) {
            for (ScanResult result : scanResults) {
                String scanResultKey = AccessPoint.getKey(result);
                if (!isKeyEqual(scanResultKey)) {
                    Log.d(TAG, String.format(
                                    "ScanResult %s\nkey of %s did not match current AP key %s",
                                    result, scanResultKey, mKey));
                    return;
                }
            }
        }

        int oldLevel = getLevel();
        synchronized (mLock) {
            mScanResults.clear();
            mScanResults.addAll(scanResults);
        }
        updateBestRssiInfo();
        int newLevel = getLevel();

        // If newLevel is 0, there will be no displayed Preference since the AP is unreachable
        if (newLevel > 0 && newLevel != oldLevel) {
            // Only update labels on visible rssi changes
            updateSpeed();
            ThreadUtils.postOnMainThread(() -> {
                if (mAccessPointListener != null) {
                    mAccessPointListener.onLevelChanged(this);
                }
            });

        }

        ThreadUtils.postOnMainThread(() -> {
            if (mAccessPointListener != null) {
                mAccessPointListener.onAccessPointChanged(this);
            }
        });
    }

    /**
     * Sets the internal scan result cache to the list of home scans.
     * If there are no home scans, then the roaming scan list is used, and the AccessPoint is
     * marked as roaming.
     */
    void setScanResultsPasspoint(
            @Nullable Collection<ScanResult> homeScans,
            @Nullable Collection<ScanResult> roamingScans) {
        synchronized (mLock) {
            mExtraScanResults.clear();
            if (!CollectionUtils.isEmpty(homeScans)) {
                mIsRoaming = false;
                if (!CollectionUtils.isEmpty(roamingScans)) {
                    mExtraScanResults.addAll(roamingScans);
                }
                setScanResults(homeScans);
            } else if (!CollectionUtils.isEmpty(roamingScans)) {
                mIsRoaming = true;
                setScanResults(roamingScans);
            }
        }
    }

    /**
     * Attempt to update the AccessPoint with the current connection info.
     * This is used to set an AccessPoint to the active one if the connection info matches, or
     * conversely to set an AccessPoint to inactive if the connection info does not match. The RSSI
     * is also updated upon a match. Listeners will be notified if an update occurred.
     *
     * This is called in {@link WifiTracker#updateAccessPoints} as well as in callbacks for handling
     * NETWORK_STATE_CHANGED_ACTION, RSSI_CHANGED_ACTION, and onCapabilitiesChanged in WifiTracker.
     *
     * Returns true if an update occurred.
     */
    public boolean update(
            @Nullable WifiConfiguration config, WifiInfo info, NetworkInfo networkInfo) {
        boolean updated = false;
        final int oldLevel = getLevel();
        if (info != null && isInfoForThisAccessPoint(config, info)) {
            updated = (mInfo == null);
            if (!isPasspoint() && mConfig != config) {
                // We do not set updated = true as we do not want to increase the amount of sorting
                // and copying performed in WifiTracker at this time. If issues involving refresh
                // are still seen, we will investigate further.
                update(config); // Notifies the AccessPointListener of the change
            }
            if (mRssi != info.getRssi() && info.getRssi() != WifiInfo.INVALID_RSSI) {
                mRssi = info.getRssi();
                updated = true;
            } else if (mNetworkInfo != null && networkInfo != null
                    && mNetworkInfo.getDetailedState() != networkInfo.getDetailedState()) {
                updated = true;
            }
            mInfo = info;
            mNetworkInfo = networkInfo;
        } else if (mInfo != null) {
            updated = true;
            mInfo = null;
            mNetworkInfo = null;
        }
        if (updated && mAccessPointListener != null) {
            ThreadUtils.postOnMainThread(() -> {
                if (mAccessPointListener != null) {
                    mAccessPointListener.onAccessPointChanged(this);
                }
            });

            if (oldLevel != getLevel() /* current level */) {
                ThreadUtils.postOnMainThread(() -> {
                    if (mAccessPointListener != null) {
                        mAccessPointListener.onLevelChanged(this);
                    }
                });
            }
        }

        return updated;
    }

    void update(@Nullable WifiConfiguration config) {
        mConfig = config;
        if (mConfig != null && !isPasspoint()) {
            ssid = removeDoubleQuotes(mConfig.SSID);
        }
        networkId = config != null ? config.networkId : WifiConfiguration.INVALID_NETWORK_ID;
        ThreadUtils.postOnMainThread(() -> {
            if (mAccessPointListener != null) {
                mAccessPointListener.onAccessPointChanged(this);
            }
        });
    }

    @VisibleForTesting
    void setRssi(int rssi) {
        mRssi = rssi;
    }

    /** Sets the rssi to {@link #UNREACHABLE_RSSI}. */
    void setUnreachable() {
        setRssi(AccessPoint.UNREACHABLE_RSSI);
    }

    int getSpeed() { return mSpeed;}

    @Nullable
    String getSpeedLabel() {
        return getSpeedLabel(mSpeed);
    }

    @Nullable
    @Speed
    private static int roundToClosestSpeedEnum(int speed) {
        if (speed < Speed.SLOW) {
            return Speed.NONE;
        } else if (speed < (Speed.SLOW + Speed.MODERATE) / 2) {
            return Speed.SLOW;
        } else if (speed < (Speed.MODERATE + Speed.FAST) / 2) {
            return Speed.MODERATE;
        } else if (speed < (Speed.FAST + Speed.VERY_FAST) / 2) {
            return Speed.FAST;
        } else {
            return Speed.VERY_FAST;
        }
    }

    @Nullable
    String getSpeedLabel(@Speed int speed) {
        return getSpeedLabel(mContext, speed);
    }

    private static String getSpeedLabel(Context context, int speed) {
        switch (speed) {
            case Speed.VERY_FAST:
                return context.getString(R.string.speed_label_very_fast);
            case Speed.FAST:
                return context.getString(R.string.speed_label_fast);
            case Speed.MODERATE:
                return context.getString(R.string.speed_label_okay);
            case Speed.SLOW:
                return context.getString(R.string.speed_label_slow);
            case Speed.NONE:
            default:
                return null;
        }
    }

    /** Return the speed label for a {@link ScoredNetwork} at the specified {@code rssi} level. */
    @Nullable
    public static String getSpeedLabel(Context context, ScoredNetwork scoredNetwork, int rssi) {
        return getSpeedLabel(context, roundToClosestSpeedEnum(scoredNetwork.calculateBadge(rssi)));
    }

    /** Return true if the current RSSI is reachable, and false otherwise. */
    public boolean isReachable() {
        return mRssi != UNREACHABLE_RSSI;
    }

    private static CharSequence getAppLabel(String packageName, PackageManager packageManager) {
        CharSequence appLabel = "";
        ApplicationInfo appInfo = null;
        try {
            int userId = UserHandle.getUserId(UserHandle.USER_CURRENT);
            appInfo = packageManager.getApplicationInfoAsUser(packageName, 0 /* flags */, userId);
        } catch (PackageManager.NameNotFoundException e) {
            Log.e(TAG, "Failed to get app info", e);
            return appLabel;
        }
        if (appInfo != null) {
            appLabel = appInfo.loadLabel(packageManager);
        }
        return appLabel;
    }

    public static String getSummary(Context context, String ssid, DetailedState state,
            boolean isEphemeral, String suggestionOrSpecifierPackageName) {
        if (state == DetailedState.CONNECTED) {
            if (isEphemeral && !TextUtils.isEmpty(suggestionOrSpecifierPackageName)) {
                CharSequence appLabel =
                        getAppLabel(suggestionOrSpecifierPackageName, context.getPackageManager());
                return context.getString(R.string.connected_via_app, appLabel);
            } else if (isEphemeral) {
                // Special case for connected + ephemeral networks.
                final NetworkScoreManager networkScoreManager = context.getSystemService(
                        NetworkScoreManager.class);
                NetworkScorerAppData scorer = networkScoreManager.getActiveScorer();
                if (scorer != null && scorer.getRecommendationServiceLabel() != null) {
                    String format = context.getString(R.string.connected_via_network_scorer);
                    return String.format(format, scorer.getRecommendationServiceLabel());
                } else {
                    return context.getString(R.string.connected_via_network_scorer_default);
                }
            }
        }

        // Case when there is wifi connected without internet connectivity.
        final ConnectivityManager cm = (ConnectivityManager)
                context.getSystemService(Context.CONNECTIVITY_SERVICE);
        if (state == DetailedState.CONNECTED) {
            IWifiManager wifiManager = IWifiManager.Stub.asInterface(
                    ServiceManager.getService(Context.WIFI_SERVICE));
            NetworkCapabilities nc = null;

            try {
                nc = cm.getNetworkCapabilities(wifiManager.getCurrentNetwork());
            } catch (RemoteException e) {}

            if (nc != null) {
                if (nc.hasCapability(nc.NET_CAPABILITY_CAPTIVE_PORTAL)) {
                    int id = context.getResources()
                            .getIdentifier("network_available_sign_in", "string", "android");
                    return context.getString(id);
                } else if (nc.hasCapability(
                        NetworkCapabilities.NET_CAPABILITY_PARTIAL_CONNECTIVITY)) {
                    return context.getString(R.string.wifi_limited_connection);
                } else if (!nc.hasCapability(NetworkCapabilities.NET_CAPABILITY_VALIDATED)) {
                    final String mode = Settings.Global.getString(context.getContentResolver(),
                            Settings.Global.PRIVATE_DNS_MODE);
                    if (nc.isPrivateDnsBroken()) {
                        return context.getString(R.string.private_dns_broken);
                    } else {
                        return context.getString(R.string.wifi_connected_no_internet);
                    }
                }
            }
        }
        if (state == null) {
            Log.w(TAG, "state is null, returning empty summary");
            return "";
        }
        String[] formats = context.getResources().getStringArray((ssid == null)
                ? R.array.wifi_status : R.array.wifi_status_with_ssid);
        int index = state.ordinal();

        if (index >= formats.length || formats[index].length() == 0) {
            return "";
        }
        return String.format(formats[index], ssid);
    }

    public static String convertToQuotedString(String string) {
        return "\"" + string + "\"";
    }

    private static int getPskType(ScanResult result) {
        boolean wpa = result.capabilities.contains("WPA-PSK");
        boolean wpa2 = result.capabilities.contains("RSN-PSK");
        boolean wpa3TransitionMode = result.capabilities.contains("PSK+SAE");
        boolean wpa3 = result.capabilities.contains("RSN-SAE");
        if (wpa3TransitionMode) {
            return PSK_SAE;
        } else if (wpa2 && wpa) {
            return PSK_WPA_WPA2;
        } else if (wpa2) {
            return PSK_WPA2;
        } else if (wpa) {
            return PSK_WPA;
        } else {
            if (!wpa3) {
                // Suppress warning for WPA3 only networks
                Log.w(TAG, "Received abnormal flag string: " + result.capabilities);
            }
            return PSK_UNKNOWN;
        }
    }

    private static int getEapType(ScanResult result) {
        // WPA2-Enterprise and WPA3-Enterprise (non 192-bit) advertise RSN-EAP-CCMP
        if (result.capabilities.contains("RSN-EAP")) {
            return EAP_WPA2_WPA3;
        }
        // WPA-Enterprise advertises WPA-EAP-TKIP
        if (result.capabilities.contains("WPA-EAP")) {
            return EAP_WPA;
        }
        return EAP_UNKNOWN;
    }

    private static int getSecurity(ScanResult result) {
        if (result.capabilities.contains("WEP")) {
            return SECURITY_WEP;
        } else if (result.capabilities.contains("SAE")) {
            return SECURITY_SAE;
        } else if (result.capabilities.contains("PSK")) {
            return SECURITY_PSK;
        } else if (result.capabilities.contains("EAP_SUITE_B_192")) {
            return SECURITY_EAP_SUITE_B;
        } else if (result.capabilities.contains("EAP")) {
            return SECURITY_EAP;
        } else if (result.capabilities.contains("OWE")) {
            return SECURITY_OWE;
        }
        return SECURITY_NONE;
    }

    static int getSecurity(WifiConfiguration config) {
        if (config.allowedKeyManagement.get(KeyMgmt.SAE)) {
            return SECURITY_SAE;
        }
        if (config.allowedKeyManagement.get(KeyMgmt.WPA_PSK)) {
            return SECURITY_PSK;
        }
        if (config.allowedKeyManagement.get(KeyMgmt.SUITE_B_192)) {
            return SECURITY_EAP_SUITE_B;
        }
        if (config.allowedKeyManagement.get(KeyMgmt.WPA_EAP) ||
                config.allowedKeyManagement.get(KeyMgmt.IEEE8021X)) {
            return SECURITY_EAP;
        }
        if (config.allowedKeyManagement.get(KeyMgmt.OWE)) {
            return SECURITY_OWE;
        }
        return (config.wepKeys[0] != null) ? SECURITY_WEP : SECURITY_NONE;
    }

    public static String securityToString(int security, int pskType) {
        if (security == SECURITY_WEP) {
            return "WEP";
        } else if (security == SECURITY_PSK) {
            if (pskType == PSK_WPA) {
                return "WPA";
            } else if (pskType == PSK_WPA2) {
                return "WPA2";
            } else if (pskType == PSK_WPA_WPA2) {
                return "WPA_WPA2";
            }
            return "PSK";
        } else if (security == SECURITY_EAP) {
            return "EAP";
        } else if (security == SECURITY_SAE) {
            return "SAE";
        } else if (security == SECURITY_EAP_SUITE_B) {
            return "SUITE_B";
        } else if (security == SECURITY_OWE) {
            return "OWE";
        }
        return "NONE";
    }

    static String removeDoubleQuotes(String string) {
        if (TextUtils.isEmpty(string)) {
            return "";
        }
        int length = string.length();
        if ((length > 1) && (string.charAt(0) == '"')
                && (string.charAt(length - 1) == '"')) {
            return string.substring(1, length - 1);
        }
        return string;
    }

    private WifiManager getWifiManager() {
        if (mWifiManager == null) {
            mWifiManager = (WifiManager) mContext.getSystemService(Context.WIFI_SERVICE);
        }
        return mWifiManager;
    }

    /**
     * Return true if this is an open network AccessPoint.
     */
    public boolean isOpenNetwork() {
        return security == SECURITY_NONE || security == SECURITY_OWE
                || security == SECURITY_OWE_TRANSITION;
    }

    /**
     * Callbacks relaying changes to the AccessPoint representation.
     *
     * <p>All methods are invoked on the Main Thread.
     */
    public interface AccessPointListener {

        /**
         * Indicates a change to the externally visible state of the AccessPoint trigger by an
         * update of ScanResults, saved configuration state, connection state, or score
         * (labels/metered) state.
         *
         * <p>Clients should refresh their view of the AccessPoint to match the updated state when
         * this is invoked. Overall this method is extraneous if clients are listening to
         * {@link WifiTracker.WifiListener#onAccessPointsChanged()} callbacks.
         *
         * <p>Examples of changes include signal strength, connection state, speed label, and
         * generally anything that would impact the summary string.
         *
         * @param accessPoint The accessPoint object the listener was registered on which has
         *                    changed
         */
        @MainThread void onAccessPointChanged(AccessPoint accessPoint);
        /**
         * Indicates the "wifi pie signal level" has changed, retrieved via calls to
         * {@link AccessPoint#getLevel()}.
         *
         * <p>This call is a subset of {@link #onAccessPointChanged(AccessPoint)} , hence is also
         * extraneous if the client is already reacting to that or the
         * {@link WifiTracker.WifiListener#onAccessPointsChanged()} callbacks.
         *
         * @param accessPoint The accessPoint object the listener was registered on whose level has
         *                    changed
         */
        @MainThread void onLevelChanged(AccessPoint accessPoint);
    }

    private static boolean isVerboseLoggingEnabled() {
        return WifiTracker.sVerboseLogging || Log.isLoggable(TAG, Log.VERBOSE);
    }

    /**
     * Callbacks relaying changes to the OSU provisioning status started in startOsuProvisioning().
     *
     * All methods are invoked on the Main Thread
     */
    @VisibleForTesting
    class AccessPointProvisioningCallback extends ProvisioningCallback {
        @Override
        @MainThread public void onProvisioningFailure(int status) {
            if (TextUtils.equals(mOsuStatus, mContext.getString(R.string.osu_completing_sign_up))) {
                mOsuFailure = mContext.getString(R.string.osu_sign_up_failed);
            } else {
                mOsuFailure = mContext.getString(R.string.osu_connect_failed);
            }
            mOsuStatus = null;
            mOsuProvisioningComplete = false;
            ThreadUtils.postOnMainThread(() -> {
                if (mAccessPointListener != null) {
                    mAccessPointListener.onAccessPointChanged(AccessPoint.this);
                }
            });
        }

        @Override
        @MainThread public void onProvisioningStatus(int status) {
            String newStatus = null;
            switch (status) {
                case OSU_STATUS_AP_CONNECTING:
                case OSU_STATUS_AP_CONNECTED:
                case OSU_STATUS_SERVER_CONNECTING:
                case OSU_STATUS_SERVER_VALIDATED:
                case OSU_STATUS_SERVER_CONNECTED:
                case OSU_STATUS_INIT_SOAP_EXCHANGE:
                case OSU_STATUS_WAITING_FOR_REDIRECT_RESPONSE:
                    newStatus = String.format(mContext.getString(R.string.osu_opening_provider),
                            mOsuProvider.getFriendlyName());
                    break;
                case OSU_STATUS_REDIRECT_RESPONSE_RECEIVED:
                case OSU_STATUS_SECOND_SOAP_EXCHANGE:
                case OSU_STATUS_THIRD_SOAP_EXCHANGE:
                case OSU_STATUS_RETRIEVING_TRUST_ROOT_CERTS:
                    newStatus = mContext.getString(
                            R.string.osu_completing_sign_up);
                    break;
            }
            boolean updated = !TextUtils.equals(mOsuStatus, newStatus);
            mOsuStatus = newStatus;
            mOsuFailure = null;
            mOsuProvisioningComplete = false;
            if (updated) {
                ThreadUtils.postOnMainThread(() -> {
                    if (mAccessPointListener != null) {
                        mAccessPointListener.onAccessPointChanged(AccessPoint.this);
                    }
                });
            }
        }

        @Override
        @MainThread public void onProvisioningComplete() {
            mOsuProvisioningComplete = true;
            mOsuFailure = null;
            mOsuStatus = null;

            ThreadUtils.postOnMainThread(() -> {
                if (mAccessPointListener != null) {
                    mAccessPointListener.onAccessPointChanged(AccessPoint.this);
                }
            });

            // Connect to the freshly provisioned network.
            WifiManager wifiManager = getWifiManager();

            PasspointConfiguration passpointConfig = wifiManager
                    .getMatchingPasspointConfigsForOsuProviders(Collections.singleton(mOsuProvider))
                    .get(mOsuProvider);
            if (passpointConfig == null) {
                Log.e(TAG, "Missing PasspointConfiguration for newly provisioned network!");
                if (mConnectListener != null) {
                    mConnectListener.onFailure(0);
                }
                return;
            }

            String fqdn = passpointConfig.getHomeSp().getFqdn();
            for (Pair<WifiConfiguration, Map<Integer, List<ScanResult>>> pairing :
                    wifiManager.getAllMatchingWifiConfigs(wifiManager.getScanResults())) {
                WifiConfiguration config = pairing.first;
                if (TextUtils.equals(config.FQDN, fqdn)) {
                    List<ScanResult> homeScans =
                            pairing.second.get(WifiManager.PASSPOINT_HOME_NETWORK);
                    List<ScanResult> roamingScans =
                            pairing.second.get(WifiManager.PASSPOINT_ROAMING_NETWORK);

                    AccessPoint connectionAp =
                            new AccessPoint(mContext, config, homeScans, roamingScans);
                    wifiManager.connect(connectionAp.getConfig(), mConnectListener);
                    return;
                }
            }
            if (mConnectListener != null) {
                mConnectListener.onFailure(0);
            }
        }
    }

    /**
     * Lets the caller know if the network was cloned from another network
     *
     * @return true if the network is cloned
     */
    public boolean isCloned() {
        if (mConfig == null) {
            return false;
        }
        return mConfig.clonedNetworkConfigKey != null;
    }
}
