/*
 * 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.content.Context;
import android.database.ContentObserver;
import android.net.Network;
import android.net.NetworkAgent;
import android.net.Uri;
import android.net.wifi.IScoreUpdateObserver;
import android.net.wifi.IWifiConnectedNetworkScorer;
import android.net.wifi.WifiInfo;
import android.net.wifi.nl80211.WifiNl80211Manager;
import android.os.Handler;
import android.os.IBinder;
import android.os.Looper;
import android.os.RemoteException;
import android.provider.Settings;
import android.util.Log;

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

import java.io.FileDescriptor;
import java.io.PrintWriter;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.LinkedList;
import java.util.Locale;

/**
 * Class used to calculate scores for connected wifi networks and report it to the associated
 * network agent.
 */
public class WifiScoreReport {
    private static final String TAG = "WifiScoreReport";

    private static final int DUMPSYS_ENTRY_COUNT_LIMIT = 3600; // 3 hours on 3 second poll

    private boolean mVerboseLoggingEnabled = false;
    private static final long FIRST_REASONABLE_WALL_CLOCK = 1490000000000L; // mid-December 2016

    private static final long MIN_TIME_TO_KEEP_BELOW_TRANSITION_SCORE_MILLIS = 9000;
    private long mLastDownwardBreachTimeMillis = 0;

    private static final int WIFI_CONNECTED_NETWORK_SCORER_IDENTIFIER = 0;
    private static final int INVALID_SESSION_ID = -1;
    private static final long MIN_TIME_TO_WAIT_BEFORE_BLOCKLIST_BSSID_MILLIS = 29000;
    private static final long INVALID_WALL_CLOCK_MILLIS = -1;
    private static final int WIFI_SCORE_TO_TERMINATE_CONNECTION_BLOCKLIST_BSSID = -2;

    /**
     * Copy of the settings string. Can't directly use the constant because it is @hide.
     * See {@link android.provider.Settings.Secure.ADAPTIVE_CONNECTIVITY_ENABLED}.
     * TODO(b/167709538) remove this hardcoded string and create new API in Wifi mainline.
     */
    @VisibleForTesting
    public static final String SETTINGS_SECURE_ADAPTIVE_CONNECTIVITY_ENABLED =
            "adaptive_connectivity_enabled";

    // Cache of the last score
    private int mScore = ConnectedScore.WIFI_MAX_SCORE;

    private final ScoringParams mScoringParams;
    private final Clock mClock;
    private int mSessionNumber = 0; // not to be confused with sessionid, this just counts resets
    private String mInterfaceName;
    private final BssidBlocklistMonitor mBssidBlocklistMonitor;
    private final Context mContext;
    private long mLastScoreBreachLowTimeMillis = INVALID_WALL_CLOCK_MILLIS;
    private long mLastScoreBreachHighTimeMillis = INVALID_WALL_CLOCK_MILLIS;

    ConnectedScore mAggressiveConnectedScore;
    VelocityBasedConnectedScore mVelocityBasedConnectedScore;

    NetworkAgent mNetworkAgent;
    WifiMetrics mWifiMetrics;
    WifiInfo mWifiInfo;
    WifiNative mWifiNative;
    WifiThreadRunner mWifiThreadRunner;
    DeviceConfigFacade mDeviceConfigFacade;
    Handler mHandler;
    FrameworkFacade mFrameworkFacade;

    /**
     * Callback proxy. See {@link android.net.wifi.WifiManager.ScoreUpdateObserver}.
     */
    private class ScoreUpdateObserverProxy extends IScoreUpdateObserver.Stub {
        @Override
        public void notifyScoreUpdate(int sessionId, int score) {
            mWifiThreadRunner.post(() -> {
                if (mWifiConnectedNetworkScorerHolder == null
                        || sessionId == INVALID_SESSION_ID
                        || sessionId != getCurrentSessionId()) {
                    Log.w(TAG, "Ignoring stale/invalid external score"
                             + " sessionId=" + sessionId
                             + " currentSessionId=" + getCurrentSessionId()
                             + " score=" + score);
                    return;
                }
                // Disconnect WiFi and blocklist current BSSID. This is an intermediate solution
                // and will be removed when the extension API is extended to include more inputs
                // tracked by b/171571687.
                if (score == WIFI_SCORE_TO_TERMINATE_CONNECTION_BLOCKLIST_BSSID) {
                    mBssidBlocklistMonitor.handleBssidConnectionFailure(mWifiInfo.getBSSID(),
                            mWifiInfo.getSSID(),
                            BssidBlocklistMonitor.REASON_FRAMEWORK_DISCONNECT_CONNECTED_SCORE,
                            mWifiInfo.getRssi());
                    return;
                }
                if (score > ConnectedScore.WIFI_MAX_SCORE
                        || score < ConnectedScore.WIFI_MIN_SCORE) {
                    Log.e(TAG, "Invalid score value from external scorer: " + score);
                    return;
                }
                long millis = mClock.getWallClockMillis();
                if (score < ConnectedScore.WIFI_TRANSITION_SCORE) {
                    if (mScore >= ConnectedScore.WIFI_TRANSITION_SCORE) {
                        mLastScoreBreachLowTimeMillis = millis;
                    }
                } else {
                    mLastScoreBreachLowTimeMillis = INVALID_WALL_CLOCK_MILLIS;
                }
                if (score > ConnectedScore.WIFI_TRANSITION_SCORE) {
                    if (mScore <= ConnectedScore.WIFI_TRANSITION_SCORE) {
                        mLastScoreBreachHighTimeMillis = millis;
                    }
                } else {
                    mLastScoreBreachHighTimeMillis = INVALID_WALL_CLOCK_MILLIS;
                }
                reportNetworkScoreToConnectivityServiceIfNecessary(score);
                mScore = score;
                updateWifiMetrics(millis, -1, mScore);
            });
        }

        @Override
        public void triggerUpdateOfWifiUsabilityStats(int sessionId) {
            mWifiThreadRunner.post(() -> {
                if (mWifiConnectedNetworkScorerHolder == null
                        || sessionId == INVALID_SESSION_ID
                        || sessionId != getCurrentSessionId()
                        || mInterfaceName == null) {
                    Log.w(TAG, "Ignoring triggerUpdateOfWifiUsabilityStats"
                             + " sessionId=" + sessionId
                             + " currentSessionId=" + getCurrentSessionId()
                             + " interfaceName=" + mInterfaceName);
                    return;
                }
                WifiLinkLayerStats stats = mWifiNative.getWifiLinkLayerStats(mInterfaceName);

                // update mWifiInfo
                // TODO(b/153075963): Better coordinate this class and ClientModeImpl to remove
                // redundant codes below and in ClientModeImpl#fetchRssiLinkSpeedAndFrequencyNative.
                WifiNl80211Manager.SignalPollResult pollResult =
                        mWifiNative.signalPoll(mInterfaceName);
                if (pollResult != null) {
                    int newRssi = pollResult.currentRssiDbm;
                    int newTxLinkSpeed = pollResult.txBitrateMbps;
                    int newFrequency = pollResult.associationFrequencyMHz;
                    int newRxLinkSpeed = pollResult.rxBitrateMbps;

                    if (newRssi > WifiInfo.INVALID_RSSI && newRssi < WifiInfo.MAX_RSSI) {
                        if (newRssi > (WifiInfo.INVALID_RSSI + 256)) {
                            Log.wtf(TAG, "Error! +ve value RSSI: " + newRssi);
                            newRssi -= 256;
                        }
                        mWifiInfo.setRssi(newRssi);
                    } else {
                        mWifiInfo.setRssi(WifiInfo.INVALID_RSSI);
                    }
                    /*
                     * set Tx link speed only if it is valid
                     */
                    if (newTxLinkSpeed > 0) {
                        mWifiInfo.setLinkSpeed(newTxLinkSpeed);
                        mWifiInfo.setTxLinkSpeedMbps(newTxLinkSpeed);
                    }
                    /*
                     * set Rx link speed only if it is valid
                     */
                    if (newRxLinkSpeed > 0) {
                        mWifiInfo.setRxLinkSpeedMbps(newRxLinkSpeed);
                    }
                    if (newFrequency > 0) {
                        mWifiInfo.setFrequency(newFrequency);
                    }
                }

                // TODO(b/153075963): This should not be plumbed through WifiMetrics
                mWifiMetrics.updateWifiUsabilityStatsEntries(mWifiInfo, stats);
            });
        }
    }

    /**
     * Report network score to connectivity service.
     */
    private void reportNetworkScoreToConnectivityServiceIfNecessary(int score) {
        if (mNetworkAgent == null) {
            return;
        }
        if (mWifiConnectedNetworkScorerHolder == null && score == mWifiInfo.getScore()) {
            return;
        }
        if (mWifiConnectedNetworkScorerHolder != null
                && mContext.getResources().getBoolean(
                        R.bool.config_wifiMinConfirmationDurationSendNetworkScoreEnabled)) {
            long millis = mClock.getWallClockMillis();
            if (mLastScoreBreachLowTimeMillis != INVALID_WALL_CLOCK_MILLIS) {
                if (mWifiInfo.getRssi()
                        >= mDeviceConfigFacade.getRssiThresholdNotSendLowScoreToCsDbm()) {
                    Log.d(TAG, "Not reporting low score because RSSI is high "
                            + mWifiInfo.getRssi());
                    return;
                }
                if ((millis - mLastScoreBreachLowTimeMillis)
                        < mDeviceConfigFacade.getMinConfirmationDurationSendLowScoreMs()) {
                    Log.d(TAG, "Not reporting low score because elapsed time is shorter than "
                            + "the minimum confirmation duration");
                    return;
                }
            }
            if (mLastScoreBreachHighTimeMillis != INVALID_WALL_CLOCK_MILLIS
                    && (millis - mLastScoreBreachHighTimeMillis)
                            < mDeviceConfigFacade.getMinConfirmationDurationSendHighScoreMs()) {
                Log.d(TAG, "Not reporting high score because elapsed time is shorter than "
                        + "the minimum confirmation duration");
                return;
            }
        }
        // Stay a notch above the transition score if adaptive connectivity is disabled.
        if (!mAdaptiveConnectivityEnabled) {
            score = ConnectedScore.WIFI_TRANSITION_SCORE + 1;
            if (mVerboseLoggingEnabled) {
                Log.d(TAG,
                        "Adaptive connectivity disabled - Stay a notch above the transition score");
            }
        }
        mNetworkAgent.sendNetworkScore(score);
    }

    /**
     * Container for storing info about external scorer and tracking its death.
     */
    private final class WifiConnectedNetworkScorerHolder implements IBinder.DeathRecipient {
        private final IBinder mBinder;
        private final IWifiConnectedNetworkScorer mScorer;
        private int mSessionId = INVALID_SESSION_ID;

        WifiConnectedNetworkScorerHolder(IBinder binder, IWifiConnectedNetworkScorer scorer) {
            mBinder = binder;
            mScorer = scorer;
        }

        /**
         * Link WiFi connected scorer to death listener.
         */
        public boolean linkScorerToDeath() {
            try {
                mBinder.linkToDeath(this, 0);
            } catch (RemoteException e) {
                Log.e(TAG, "Unable to linkToDeath Wifi connected network scorer " + mScorer, e);
                return false;
            }
            return true;
        }

        /**
         * App hosting the binder has died.
         */
        @Override
        public void binderDied() {
            mWifiThreadRunner.post(() -> revertToDefaultConnectedScorer());
        }

        /**
         * Unlink this object from binder death.
         */
        public void reset() {
            mBinder.unlinkToDeath(this, 0);
        }

        /**
         * Starts a new scoring session.
         */
        public void startSession(int sessionId) {
            if (sessionId == INVALID_SESSION_ID) {
                throw new IllegalArgumentException();
            }
            if (mSessionId != INVALID_SESSION_ID) {
                // This is not expected to happen, log if it does
                Log.e(TAG, "Stopping session " + mSessionId + " before starting " + sessionId);
                stopSession();
            }
            // Bail now if the scorer has gone away
            if (this != mWifiConnectedNetworkScorerHolder) {
                return;
            }
            mSessionId = sessionId;
            try {
                mScorer.onStart(sessionId);
            } catch (RemoteException e) {
                Log.e(TAG, "Unable to start Wifi connected network scorer " + this, e);
                revertToDefaultConnectedScorer();
            }
        }
        public void stopSession() {
            final int sessionId = mSessionId;
            if (sessionId == INVALID_SESSION_ID) return;
            mSessionId = INVALID_SESSION_ID;
            try {
                mScorer.onStop(sessionId);
            } catch (RemoteException e) {
                Log.e(TAG, "Unable to stop Wifi connected network scorer " + this, e);
                revertToDefaultConnectedScorer();
            }
        }
    }

    private final ScoreUpdateObserverProxy mScoreUpdateObserver =
            new ScoreUpdateObserverProxy();

    private WifiConnectedNetworkScorerHolder mWifiConnectedNetworkScorerHolder;

    /**
     * Observer for adaptive connectivity enable settings changes.
     * This is enabled by default. Will be toggled off via adb command or a settings
     * toggle by the user to disable adaptive connectivity.
     */
    private class AdaptiveConnectivityEnabledSettingObserver extends ContentObserver {
        AdaptiveConnectivityEnabledSettingObserver(Handler handler) {
            super(handler);
        }

        @Override
        public void onChange(boolean selfChange) {
            super.onChange(selfChange);
            mAdaptiveConnectivityEnabled = getValue();
            Log.d(TAG, "Adaptive connectivity status changed: " + mAdaptiveConnectivityEnabled);
            mWifiMetrics.setAdaptiveConnectivityState(mAdaptiveConnectivityEnabled);
            mWifiMetrics.logUserActionEvent(
                    mWifiMetrics.convertAdaptiveConnectivityStateToUserActionEventType(
                            mAdaptiveConnectivityEnabled));
        }

        /**
         * Register settings change observer.
         */
        public void initialize() {
            Uri uri = Settings.Secure.getUriFor(SETTINGS_SECURE_ADAPTIVE_CONNECTIVITY_ENABLED);
            if (uri == null) {
                Log.e(TAG, "Adaptive connectivity user toggle does not exist in Settings");
                return;
            }
            mFrameworkFacade.registerContentObserver(mContext, uri, true, this);
            mAdaptiveConnectivityEnabled = mAdaptiveConnectivityEnabledSettingObserver.getValue();
            mWifiMetrics.setAdaptiveConnectivityState(mAdaptiveConnectivityEnabled);
        }

        public boolean getValue() {
            return mFrameworkFacade.getSecureIntegerSetting(
                    mContext, SETTINGS_SECURE_ADAPTIVE_CONNECTIVITY_ENABLED, 1) == 1;
        }
    }

    private final AdaptiveConnectivityEnabledSettingObserver
            mAdaptiveConnectivityEnabledSettingObserver;
    private boolean mAdaptiveConnectivityEnabled = true;

    WifiScoreReport(ScoringParams scoringParams, Clock clock, WifiMetrics wifiMetrics,
            WifiInfo wifiInfo, WifiNative wifiNative, BssidBlocklistMonitor bssidBlocklistMonitor,
            WifiThreadRunner wifiThreadRunner, DeviceConfigFacade deviceConfigFacade,
            Context context, Looper looper, FrameworkFacade frameworkFacade) {
        mScoringParams = scoringParams;
        mClock = clock;
        mAggressiveConnectedScore = new AggressiveConnectedScore(scoringParams, clock);
        mVelocityBasedConnectedScore = new VelocityBasedConnectedScore(scoringParams, clock);
        mWifiMetrics = wifiMetrics;
        mWifiInfo = wifiInfo;
        mWifiNative = wifiNative;
        mBssidBlocklistMonitor = bssidBlocklistMonitor;
        mWifiThreadRunner = wifiThreadRunner;
        mDeviceConfigFacade = deviceConfigFacade;
        mContext = context;
        mFrameworkFacade = frameworkFacade;
        mHandler = new Handler(looper);
        mAdaptiveConnectivityEnabledSettingObserver =
                new AdaptiveConnectivityEnabledSettingObserver(mHandler);
    }

    /**
     * Reset the last calculated score.
     */
    public void reset() {
        mSessionNumber++;
        mScore = ConnectedScore.WIFI_MAX_SCORE;
        mLastKnownNudCheckScore = ConnectedScore.WIFI_TRANSITION_SCORE;
        mAggressiveConnectedScore.reset();
        if (mVelocityBasedConnectedScore != null) {
            mVelocityBasedConnectedScore.reset();
        }
        mLastDownwardBreachTimeMillis = 0;
        mLastScoreBreachLowTimeMillis = INVALID_WALL_CLOCK_MILLIS;
        mLastScoreBreachHighTimeMillis = INVALID_WALL_CLOCK_MILLIS;
        if (mVerboseLoggingEnabled) Log.d(TAG, "reset");
    }

    /**
     * Enable/Disable verbose logging in score report generation.
     */
    public void enableVerboseLogging(boolean enable) {
        mVerboseLoggingEnabled = enable;
    }

    /**
     * Calculate wifi network score based on updated link layer stats and send the score to
     * the WifiNetworkAgent.
     *
     * If the score has changed from the previous value, update the WifiNetworkAgent.
     *
     * Called periodically (POLL_RSSI_INTERVAL_MSECS) about every 3 seconds.
     */
    public void calculateAndReportScore() {
        // Bypass AOSP scorer if Wifi connected network scorer is set
        if (mWifiConnectedNetworkScorerHolder != null) {
            return;
        }

        if (mWifiInfo.getRssi() == mWifiInfo.INVALID_RSSI) {
            Log.d(TAG, "Not reporting score because RSSI is invalid");
            return;
        }
        int score;

        long millis = mClock.getWallClockMillis();
        mVelocityBasedConnectedScore.updateUsingWifiInfo(mWifiInfo, millis);

        int s2 = mVelocityBasedConnectedScore.generateScore();
        score = s2;

        if (mWifiInfo.getScore() > ConnectedScore.WIFI_TRANSITION_SCORE
                && score <= ConnectedScore.WIFI_TRANSITION_SCORE
                && mWifiInfo.getSuccessfulTxPacketsPerSecond()
                        >= mScoringParams.getYippeeSkippyPacketsPerSecond()
                && mWifiInfo.getSuccessfulRxPacketsPerSecond()
                        >= mScoringParams.getYippeeSkippyPacketsPerSecond()
        ) {
            score = ConnectedScore.WIFI_TRANSITION_SCORE + 1;
        }

        if (mWifiInfo.getScore() > ConnectedScore.WIFI_TRANSITION_SCORE
                && score <= ConnectedScore.WIFI_TRANSITION_SCORE) {
            // We don't want to trigger a downward breach unless the rssi is
            // below the entry threshold.  There is noise in the measured rssi, and
            // the kalman-filtered rssi is affected by the trend, so check them both.
            // TODO(b/74613347) skip this if there are other indications to support the low score
            int entry = mScoringParams.getEntryRssi(mWifiInfo.getFrequency());
            if (mVelocityBasedConnectedScore.getFilteredRssi() >= entry
                    || mWifiInfo.getRssi() >= entry) {
                // Stay a notch above the transition score to reduce ambiguity.
                score = ConnectedScore.WIFI_TRANSITION_SCORE + 1;
            }
        }

        if (mWifiInfo.getScore() >= ConnectedScore.WIFI_TRANSITION_SCORE
                && score < ConnectedScore.WIFI_TRANSITION_SCORE) {
            mLastDownwardBreachTimeMillis = millis;
        } else if (mWifiInfo.getScore() < ConnectedScore.WIFI_TRANSITION_SCORE
                && score >= ConnectedScore.WIFI_TRANSITION_SCORE) {
            // Staying at below transition score for a certain period of time
            // to prevent going back to wifi network again in a short time.
            long elapsedMillis = millis - mLastDownwardBreachTimeMillis;
            if (elapsedMillis < MIN_TIME_TO_KEEP_BELOW_TRANSITION_SCORE_MILLIS) {
                score = mWifiInfo.getScore();
            }
        }
        //sanitize boundaries
        if (score > ConnectedScore.WIFI_MAX_SCORE) {
            score = ConnectedScore.WIFI_MAX_SCORE;
        }
        if (score < 0) {
            score = 0;
        }

        //report score
        reportNetworkScoreToConnectivityServiceIfNecessary(score);
        updateWifiMetrics(millis, s2, score);
        mScore = score;
    }

    private int getCurrentNetId() {
        int netId = 0;
        if (mNetworkAgent != null) {
            final Network network = mNetworkAgent.getNetwork();
            if (network != null) {
                netId = network.getNetId();
            }
        }
        return netId;
    }

    private int getCurrentSessionId() {
        return sessionIdFromNetId(getCurrentNetId());
    }

    /**
     * Encodes a network id into a scoring session id.
     *
     * We use a different numeric value for session id and the network id
     * to make it clear that these are not the same thing. However, for
     * easier debugging, the network id can be recovered by dropping the
     * last decimal digit (at least until they get very, very, large).
     */
    public static int sessionIdFromNetId(final int netId) {
        if (netId <= 0) return INVALID_SESSION_ID;
        return (int) (((long) netId * 10 + (8 - (netId % 9))) % Integer.MAX_VALUE + 1);
    }

    private void updateWifiMetrics(long now, int s2, int score) {
        int netId = getCurrentNetId();

        mAggressiveConnectedScore.updateUsingWifiInfo(mWifiInfo, now);
        int s1 = mAggressiveConnectedScore.generateScore();
        logLinkMetrics(now, netId, s1, s2, score);

        if (score != mWifiInfo.getScore()) {
            if (mVerboseLoggingEnabled) {
                Log.d(TAG, "report new wifi score " + score);
            }
            mWifiInfo.setScore(score);
        }
        mWifiMetrics.incrementWifiScoreCount(score);
    }

    private static final double TIME_CONSTANT_MILLIS = 30.0e+3;
    private static final long NUD_THROTTLE_MILLIS = 5000;
    private long mLastKnownNudCheckTimeMillis = 0;
    private int mLastKnownNudCheckScore = ConnectedScore.WIFI_TRANSITION_SCORE;
    private int mNudYes = 0;    // Counts when we voted for a NUD
    private int mNudCount = 0;  // Counts when we were told a NUD was sent

    /**
     * Recommends that a layer 3 check be done
     *
     * The caller can use this to (help) decide that an IP reachability check
     * is desirable. The check is not done here; that is the caller's responsibility.
     *
     * @return true to indicate that an IP reachability check is recommended
     */
    public boolean shouldCheckIpLayer() {
        // Don't recommend if adaptive connectivity is disabled.
        if (!mAdaptiveConnectivityEnabled) {
            if (mVerboseLoggingEnabled) {
                Log.d(TAG, "Adaptive connectivity disabled - Don't check IP layer");
            }
            return false;
        }
        int nud = mScoringParams.getNudKnob();
        if (nud == 0) {
            return false;
        }
        long millis = mClock.getWallClockMillis();
        long deltaMillis = millis - mLastKnownNudCheckTimeMillis;
        // Don't ever ask back-to-back - allow at least 5 seconds
        // for the previous one to finish.
        if (deltaMillis < NUD_THROTTLE_MILLIS) {
            return false;
        }
        // nextNudBreach is the bar the score needs to cross before we ask for NUD
        double nextNudBreach = ConnectedScore.WIFI_TRANSITION_SCORE;
        if (mWifiConnectedNetworkScorerHolder == null) {
            // nud is between 1 and 10 at this point
            double deltaLevel = 11 - nud;
            // If we were below threshold the last time we checked, then compute a new bar
            // that starts down from there and decays exponentially back up to the steady-state
            // bar. If 5 time constants have passed, we are 99% of the way there, so skip the math.
            if (mLastKnownNudCheckScore < ConnectedScore.WIFI_TRANSITION_SCORE
                    && deltaMillis < 5.0 * TIME_CONSTANT_MILLIS) {
                double a = Math.exp(-deltaMillis / TIME_CONSTANT_MILLIS);
                nextNudBreach =
                        a * (mLastKnownNudCheckScore - deltaLevel) + (1.0 - a) * nextNudBreach;
            }
        }
        if (mScore >= nextNudBreach) {
            return false;
        }
        mNudYes++;
        return true;
    }

    /**
     * Should be called when a reachability check has been issued
     *
     * When the caller has requested an IP reachability check, calling this will
     * help to rate-limit requests via shouldCheckIpLayer()
     */
    public void noteIpCheck() {
        long millis = mClock.getWallClockMillis();
        mLastKnownNudCheckTimeMillis = millis;
        mLastKnownNudCheckScore = mScore;
        mNudCount++;
    }

    /**
     * Data for dumpsys
     *
     * These are stored as csv formatted lines
     */
    private LinkedList<String> mLinkMetricsHistory = new LinkedList<String>();

    /**
     * Data logging for dumpsys
     */
    private void logLinkMetrics(long now, int netId, int s1, int s2, int score) {
        if (now < FIRST_REASONABLE_WALL_CLOCK) return;
        double rssi = mWifiInfo.getRssi();
        double filteredRssi = -1;
        double rssiThreshold = -1;
        if (mWifiConnectedNetworkScorerHolder == null) {
            filteredRssi = mVelocityBasedConnectedScore.getFilteredRssi();
            rssiThreshold = mVelocityBasedConnectedScore.getAdjustedRssiThreshold();
        }
        int freq = mWifiInfo.getFrequency();
        int txLinkSpeed = mWifiInfo.getLinkSpeed();
        int rxLinkSpeed = mWifiInfo.getRxLinkSpeedMbps();
        double txSuccessRate = mWifiInfo.getSuccessfulTxPacketsPerSecond();
        double txRetriesRate = mWifiInfo.getRetriedTxPacketsPerSecond();
        double txBadRate = mWifiInfo.getLostTxPacketsPerSecond();
        double rxSuccessRate = mWifiInfo.getSuccessfulRxPacketsPerSecond();
        String s;
        try {
            String timestamp = new SimpleDateFormat("MM-dd HH:mm:ss.SSS").format(new Date(now));
            s = String.format(Locale.US, // Use US to avoid comma/decimal confusion
                    "%s,%d,%d,%.1f,%.1f,%.1f,%d,%d,%d,%.2f,%.2f,%.2f,%.2f,%d,%d,%d,%d,%d",
                    timestamp, mSessionNumber, netId,
                    rssi, filteredRssi, rssiThreshold, freq, txLinkSpeed, rxLinkSpeed,
                    txSuccessRate, txRetriesRate, txBadRate, rxSuccessRate,
                    mNudYes, mNudCount,
                    s1, s2, score);
        } catch (Exception e) {
            Log.e(TAG, "format problem", e);
            return;
        }
        synchronized (mLinkMetricsHistory) {
            mLinkMetricsHistory.add(s);
            while (mLinkMetricsHistory.size() > DUMPSYS_ENTRY_COUNT_LIMIT) {
                mLinkMetricsHistory.removeFirst();
            }
        }
    }

    /**
     * Tag to be used in dumpsys request
     */
    public static final String DUMP_ARG = "WifiScoreReport";

    /**
     * Dump logged signal strength and traffic measurements.
     * @param fd unused
     * @param pw PrintWriter for writing dump to
     * @param args unused
     */
    public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
        LinkedList<String> history;
        synchronized (mLinkMetricsHistory) {
            history = new LinkedList<>(mLinkMetricsHistory);
        }
        pw.println("time,session,netid,rssi,filtered_rssi,rssi_threshold,freq,txLinkSpeed,"
                + "rxLinkSpeed,tx_good,tx_retry,tx_bad,rx_pps,nudrq,nuds,s1,s2,score");
        for (String line : history) {
            pw.println(line);
        }
        history.clear();
    }

    /**
     * Set a scorer for Wi-Fi connected network score handling.
     * @param binder
     * @param scorer
     */
    public boolean setWifiConnectedNetworkScorer(IBinder binder,
            IWifiConnectedNetworkScorer scorer) {
        if (binder == null || scorer == null) return false;
        // Enforce that only a single scorer can be set successfully.
        if (mWifiConnectedNetworkScorerHolder != null) {
            Log.e(TAG, "Failed to set current scorer because one scorer is already set");
            return false;
        }
        WifiConnectedNetworkScorerHolder scorerHolder =
                new WifiConnectedNetworkScorerHolder(binder, scorer);
        if (!scorerHolder.linkScorerToDeath()) {
            return false;
        }
        mWifiConnectedNetworkScorerHolder = scorerHolder;

        try {
            scorer.onSetScoreUpdateObserver(mScoreUpdateObserver);
        } catch (RemoteException e) {
            Log.e(TAG, "Unable to set score update observer " + scorer, e);
            revertToDefaultConnectedScorer();
            return false;
        }
        // Disable AOSP scorer
        mVelocityBasedConnectedScore = null;
        mWifiMetrics.setIsExternalWifiScorerOn(true);
        // If there is already a connection, start a new session
        final int netId = getCurrentNetId();
        if (netId > 0) {
            startConnectedNetworkScorer(netId);
        }
        return true;
    }

    /**
     * Clear an existing scorer for Wi-Fi connected network score handling.
     */
    public void clearWifiConnectedNetworkScorer() {
        if (mWifiConnectedNetworkScorerHolder == null) {
            return;
        }
        mWifiConnectedNetworkScorerHolder.reset();
        revertToDefaultConnectedScorer();
    }

    /**
     * Start the registered Wi-Fi connected network scorer.
     * @param netId identifies the current android.net.Network
     */
    public void startConnectedNetworkScorer(int netId) {
        final int sessionId = getCurrentSessionId();
        if (mWifiConnectedNetworkScorerHolder == null
                || netId != getCurrentNetId()
                || sessionId == INVALID_SESSION_ID) {
            Log.w(TAG, "Cannot start external scoring"
                    + " netId=" + netId
                    + " currentNetId=" + getCurrentNetId()
                    + " sessionId=" + sessionId);
            return;
        }
        mWifiInfo.setScore(ConnectedScore.WIFI_MAX_SCORE);
        mWifiConnectedNetworkScorerHolder.startSession(sessionId);
        mLastScoreBreachLowTimeMillis = INVALID_WALL_CLOCK_MILLIS;
        mLastScoreBreachHighTimeMillis = INVALID_WALL_CLOCK_MILLIS;
    }

    /**
     * Stop the registered Wi-Fi connected network scorer.
     */
    public void stopConnectedNetworkScorer() {
        mNetworkAgent = null;
        if (mWifiConnectedNetworkScorerHolder == null) {
            return;
        }
        mWifiConnectedNetworkScorerHolder.stopSession();

        long millis = mClock.getWallClockMillis();
        // Blocklist the current BSS
        if ((mLastScoreBreachLowTimeMillis != INVALID_WALL_CLOCK_MILLIS)
                && ((millis - mLastScoreBreachLowTimeMillis)
                        >= MIN_TIME_TO_WAIT_BEFORE_BLOCKLIST_BSSID_MILLIS)) {
            mBssidBlocklistMonitor.handleBssidConnectionFailure(mWifiInfo.getBSSID(),
                    mWifiInfo.getSSID(),
                    BssidBlocklistMonitor.REASON_FRAMEWORK_DISCONNECT_CONNECTED_SCORE,
                    mWifiInfo.getRssi());
            mLastScoreBreachLowTimeMillis = INVALID_WALL_CLOCK_MILLIS;
        }
    }

    /**
     * Set NetworkAgent
     */
    public void setNetworkAgent(NetworkAgent agent) {
        mNetworkAgent = agent;
    }

    /**
     * Get cached score
     */
    public int getScore() {
        return mScore;
    }

    /**
     * Set interface name
     * @param ifaceName
     */
    public void setInterfaceName(String ifaceName) {
        mInterfaceName = ifaceName;
    }

    private void revertToDefaultConnectedScorer() {
        Log.d(TAG, "Using VelocityBasedConnectedScore");
        mVelocityBasedConnectedScore = new VelocityBasedConnectedScore(mScoringParams, mClock);
        mWifiConnectedNetworkScorerHolder = null;
        mWifiMetrics.setIsExternalWifiScorerOn(false);
    }

    /**
     * Initialize WifiScoreReport
     */
    public void initialize() {
        mAdaptiveConnectivityEnabledSettingObserver.initialize();
    }
}
