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

package com.android.server.wifi;

import static com.android.server.wifi.util.InformationElementUtil.BssLoad.CHANNEL_UTILIZATION_SCALE;

import android.content.Context;
import android.net.wifi.WifiInfo;
import android.net.wifi.WifiManager.DeviceMobilityState;
import android.os.Handler;
import android.os.HandlerExecutor;
import android.telephony.PhoneStateListener;
import android.telephony.TelephonyManager;
import android.util.Log;

import com.android.server.wifi.proto.WifiStatsLog;
import com.android.server.wifi.proto.nano.WifiMetricsProto.WifiIsUnusableEvent;
import com.android.server.wifi.scanner.KnownBandsChannelHelper;
import com.android.server.wifi.util.InformationElementUtil.BssLoad;
import com.android.wifi.resources.R;

/**
 * Looks for Wifi data stalls
 */
public class WifiDataStall {
    private static final String TAG = "WifiDataStall";
    private boolean mVerboseLoggingEnabled = false;
    public static final int INVALID_THROUGHPUT = -1;
    // At low traffic, link speed values below the following threshold
    // are ignored because it could be due to low rate management frames
    public static final int LINK_SPEED_LOW_THRESHOLD_MBPS = 9;
    // Maximum time gap between two WifiLinkLayerStats to trigger a data stall
    public static final int MAX_MS_DELTA_FOR_DATA_STALL = 60 * 1000; // 1 minute
    // Maximum time that a data stall start time stays valid.
    public static final long VALIDITY_PERIOD_OF_DATA_STALL_START_MS = 30 * 1000; // 0.5 minutes
    // Default Tx packet error rate when there is no Tx attempt
    public static final int DEFAULT_TX_PACKET_ERROR_RATE = 5;
    // Default CCA level when CCA stats are not available
    public static final int DEFAULT_CCA_LEVEL_2G = CHANNEL_UTILIZATION_SCALE * 16 / 100;
    public static final int DEFAULT_CCA_LEVEL_ABOVE_2G = CHANNEL_UTILIZATION_SCALE * 6 / 100;
    // Minimum time interval in ms between two link layer stats cache updates
    private static final int LLSTATS_CACHE_UPDATE_INTERVAL_MIN_MS = 30_000;
    // Maximum time margin between two link layer stats for connection duration update
    public static final int MAX_TIME_MARGIN_LAST_TWO_POLLS_MS = 200;

    private final FrameworkFacade mFacade;
    private final DeviceConfigFacade mDeviceConfigFacade;
    private final WifiMetrics mWifiMetrics;
    private final Context mContext;
    private final WifiChannelUtilization mWifiChannelUtilization;
    private TelephonyManager mTelephonyManager;
    private final ThroughputPredictor mThroughputPredictor;
    private WifiNative.ConnectionCapabilities mConnectionCapabilities;

    private int mLastFrequency = -1;
    private String mLastBssid;
    private long mDataStallStartTimeMs = -1;
    private Clock mClock;
    private boolean mDataStallTx = false;
    private boolean mDataStallRx = false;
    private long mLastTxBytes;
    private long mLastRxBytes;
    private boolean mIsThroughputSufficient = true;
    private boolean mIsCellularDataAvailable = false;
    private final PhoneStateListener mPhoneStateListener;
    private boolean mPhoneStateListenerEnabled = false;
    private int mTxTputKbps = INVALID_THROUGHPUT;
    private int mRxTputKbps = INVALID_THROUGHPUT;

    public WifiDataStall(FrameworkFacade facade, WifiMetrics wifiMetrics, Context context,
            DeviceConfigFacade deviceConfigFacade, WifiChannelUtilization wifiChannelUtilization,
            Clock clock, Handler handler, ThroughputPredictor throughputPredictor) {
        mFacade = facade;
        mDeviceConfigFacade = deviceConfigFacade;
        mWifiMetrics = wifiMetrics;
        mContext = context;
        mClock = clock;
        mWifiChannelUtilization = wifiChannelUtilization;
        mWifiChannelUtilization.setCacheUpdateIntervalMs(LLSTATS_CACHE_UPDATE_INTERVAL_MIN_MS);
        mThroughputPredictor = throughputPredictor;
        mPhoneStateListener = new PhoneStateListener(new HandlerExecutor(handler)) {
            @Override
            public void onDataConnectionStateChanged(int state, int networkType) {
                if (state == TelephonyManager.DATA_CONNECTED) {
                    mIsCellularDataAvailable = true;
                } else if (state == TelephonyManager.DATA_DISCONNECTED) {
                    mIsCellularDataAvailable = false;
                } else {
                    Log.e(TAG, "onDataConnectionStateChanged unexpected State: " + state);
                    return;
                }
                logd("Cellular Data: " + mIsCellularDataAvailable);
            }
        };
    }

    /**
     * initialization after wifi is enabled
     */
    public void init() {
        mWifiChannelUtilization.init(null);
        reset();
    }

    /**
     * Reset internal variables
     */
    public void reset() {
        mLastTxBytes = 0;
        mLastRxBytes = 0;
        mLastFrequency = -1;
        mLastBssid = null;
        mDataStallStartTimeMs = -1;
        mDataStallTx = false;
        mDataStallRx = false;
        mIsThroughputSufficient = true;
        mTxTputKbps = INVALID_THROUGHPUT;
        mRxTputKbps = INVALID_THROUGHPUT;
    }

    /**
     * Set ConnectionCapabilities after each association and roaming
     */
    public void setConnectionCapabilities(WifiNative.ConnectionCapabilities capabilities) {
        mConnectionCapabilities = capabilities;
    }
    /**
     * Enable phone state listener
     */
    public void enablePhoneStateListener() {
        if (mTelephonyManager == null) {
            mTelephonyManager = (TelephonyManager) mContext
                    .getSystemService(Context.TELEPHONY_SERVICE);
        }
        if (mTelephonyManager != null && !mPhoneStateListenerEnabled) {
            mPhoneStateListenerEnabled = true;
            mTelephonyManager.listen(mPhoneStateListener,
                    PhoneStateListener.LISTEN_DATA_CONNECTION_STATE);
        }
    }

    /**
     * Disable phone state listener
     */
    public void disablePhoneStateListener() {
        if (mTelephonyManager != null && mPhoneStateListenerEnabled) {
            mPhoneStateListenerEnabled = false;
            mTelephonyManager.listen(mPhoneStateListener, PhoneStateListener.LISTEN_NONE);
        }
    }

    /**
     * Enable/Disable verbose logging.
     * @param verbose true to enable and false to disable.
     */
    public void enableVerboseLogging(boolean verbose) {
        mVerboseLoggingEnabled = verbose;
        mWifiChannelUtilization.enableVerboseLogging(verbose);
    }

    /**
     * Update device mobility state
     * @param newState the new device mobility state
     */
    public void setDeviceMobilityState(@DeviceMobilityState int newState) {
        mWifiChannelUtilization.setDeviceMobilityState(newState);
    }

    /**
     * Check if current link layer throughput is sufficient.
     * This should be called after checkDataStallAndThroughputSufficiency().
     * @return true if it is sufficient or false if it is insufficient
     */
    public boolean isThroughputSufficient() {
        return mIsThroughputSufficient;
    }

    /**
     * Check if cellular data is available
     * @return true if it is available and false otherwise
     */
    public boolean isCellularDataAvailable() {
        return mIsCellularDataAvailable;
    }

    /**
     * Get the latest Tx throughput based on Tx link speed, PER and channel utilization
     * @return the latest estimated Tx throughput in Kbps if it is available
     *  or INVALID_THROUGHPUT if it is not available
     */
    public int getTxThroughputKbps() {
        logd("tx tput in kbps: " + mTxTputKbps);
        return mTxTputKbps;
    }

    /**
     * Get the latest Rx throughput based on Rx link speed and channel utilization
     * @return the latest estimated Rx throughput in Kbps if it is available
     *  or INVALID_THROUGHPUT if it is not available
     */
    public int getRxThroughputKbps() {
        logd("rx tput in kbps: " + mRxTputKbps);
        return mRxTputKbps;
    }

    /**
     * Update data stall detection, check throughput sufficiency and report wifi health stat
     * with the latest link layer stats
     * @param oldStats second most recent WifiLinkLayerStats
     * @param newStats most recent WifiLinkLayerStats
     * @param wifiInfo WifiInfo for current connection
     * @return trigger type of WifiIsUnusableEvent
     */
    public int checkDataStallAndThroughputSufficiency(WifiLinkLayerStats oldStats,
            WifiLinkLayerStats newStats, WifiInfo wifiInfo) {
        int currFrequency = wifiInfo.getFrequency();
        mWifiChannelUtilization.refreshChannelStatsAndChannelUtilization(newStats, currFrequency);
        int ccaLevel = mWifiChannelUtilization.getUtilizationRatio(currFrequency);
        mWifiMetrics.incrementChannelUtilizationCount(ccaLevel, currFrequency);

        if (oldStats == null || newStats == null) {
            // First poll after new association
            // Update throughput with prediction
            if (wifiInfo.getRssi() != WifiInfo.INVALID_RSSI && mConnectionCapabilities != null) {
                mTxTputKbps = mThroughputPredictor.predictTxThroughput(mConnectionCapabilities,
                        wifiInfo.getRssi(), currFrequency, ccaLevel) * 1000;
                mRxTputKbps = mThroughputPredictor.predictRxThroughput(mConnectionCapabilities,
                        wifiInfo.getRssi(), currFrequency, ccaLevel) * 1000;
            }
            mIsThroughputSufficient = true;
            mWifiMetrics.resetWifiIsUnusableLinkLayerStats();
            mWifiMetrics.incrementThroughputKbpsCount(mTxTputKbps, mRxTputKbps, currFrequency);
            return WifiIsUnusableEvent.TYPE_UNKNOWN;
        }

        long txSuccessDelta = (newStats.txmpdu_be + newStats.txmpdu_bk
                + newStats.txmpdu_vi + newStats.txmpdu_vo)
                - (oldStats.txmpdu_be + oldStats.txmpdu_bk
                + oldStats.txmpdu_vi + oldStats.txmpdu_vo);
        long txRetriesDelta = (newStats.retries_be + newStats.retries_bk
                + newStats.retries_vi + newStats.retries_vo)
                - (oldStats.retries_be + oldStats.retries_bk
                + oldStats.retries_vi + oldStats.retries_vo);
        long txBadDelta = (newStats.lostmpdu_be + newStats.lostmpdu_bk
                + newStats.lostmpdu_vi + newStats.lostmpdu_vo)
                - (oldStats.lostmpdu_be + oldStats.lostmpdu_bk
                + oldStats.lostmpdu_vi + oldStats.lostmpdu_vo);
        long rxSuccessDelta = (newStats.rxmpdu_be + newStats.rxmpdu_bk
                + newStats.rxmpdu_vi + newStats.rxmpdu_vo)
                - (oldStats.rxmpdu_be + oldStats.rxmpdu_bk
                + oldStats.rxmpdu_vi + oldStats.rxmpdu_vo);
        int timeDeltaLastTwoPollsMs = (int) (newStats.timeStampInMs - oldStats.timeStampInMs);

        long totalTxDelta = txSuccessDelta + txRetriesDelta;
        boolean isTxTrafficHigh = (totalTxDelta * 1000)
                > (mDeviceConfigFacade.getTxPktPerSecondThr() * timeDeltaLastTwoPollsMs);
        boolean isRxTrafficHigh = (rxSuccessDelta * 1000)
                > (mDeviceConfigFacade.getRxPktPerSecondThr() * timeDeltaLastTwoPollsMs);
        if (timeDeltaLastTwoPollsMs < 0
                || txSuccessDelta < 0
                || txRetriesDelta < 0
                || txBadDelta < 0
                || rxSuccessDelta < 0) {
            mIsThroughputSufficient = true;
            // There was a reset in WifiLinkLayerStats
            mWifiMetrics.resetWifiIsUnusableLinkLayerStats();
            return WifiIsUnusableEvent.TYPE_UNKNOWN;
        }

        mWifiMetrics.updateWifiIsUnusableLinkLayerStats(txSuccessDelta, txRetriesDelta,
                txBadDelta, rxSuccessDelta, timeDeltaLastTwoPollsMs);

        int txLinkSpeedMbps = wifiInfo.getLinkSpeed();
        int rxLinkSpeedMbps = wifiInfo.getRxLinkSpeedMbps();
        boolean isSameBssidAndFreq = mLastBssid == null || mLastFrequency == -1
                || (mLastBssid.equals(wifiInfo.getBSSID())
                && mLastFrequency == currFrequency);
        mLastFrequency = currFrequency;
        mLastBssid = wifiInfo.getBSSID();

        if (ccaLevel == BssLoad.INVALID) {
            ccaLevel = wifiInfo.is24GHz() ? DEFAULT_CCA_LEVEL_2G : DEFAULT_CCA_LEVEL_ABOVE_2G;
            logd(" use default cca Level");
        }
        logd(" ccaLevel = " + ccaLevel);

        int txPer = updateTxPer(txSuccessDelta, txRetriesDelta, isSameBssidAndFreq);

        boolean isTxTputLow = false;
        boolean isRxTputLow = false;

        if (txLinkSpeedMbps > 0) {
            // Exclude update with low rate management frames
            if (isTxTrafficHigh || txLinkSpeedMbps > LINK_SPEED_LOW_THRESHOLD_MBPS) {
                mTxTputKbps = (int) ((long) txLinkSpeedMbps * 1000 * (100 - txPer) / 100
                        * (CHANNEL_UTILIZATION_SCALE  - ccaLevel) / CHANNEL_UTILIZATION_SCALE);
            }
            isTxTputLow =  mTxTputKbps < mDeviceConfigFacade.getDataStallTxTputThrKbps();
        } else {
            mTxTputKbps = INVALID_THROUGHPUT;
        }

        if (rxLinkSpeedMbps > 0) {
            // Exclude update with low rate management frames
            if (isRxTrafficHigh || rxLinkSpeedMbps > LINK_SPEED_LOW_THRESHOLD_MBPS) {
                mRxTputKbps = (int) ((long) rxLinkSpeedMbps * 1000
                        * (CHANNEL_UTILIZATION_SCALE  - ccaLevel) / CHANNEL_UTILIZATION_SCALE);
            }
            isRxTputLow = mRxTputKbps < mDeviceConfigFacade.getDataStallRxTputThrKbps();
        } else {
            mRxTputKbps = INVALID_THROUGHPUT;
        }
        mWifiMetrics.incrementThroughputKbpsCount(mTxTputKbps, mRxTputKbps, currFrequency);

        mIsThroughputSufficient = isThroughputSufficientInternal(mTxTputKbps, mRxTputKbps,
                isTxTrafficHigh, isRxTrafficHigh, timeDeltaLastTwoPollsMs);

        int maxTimeDeltaMs = mContext.getResources().getInteger(
                R.integer.config_wifiPollRssiIntervalMilliseconds)
                + MAX_TIME_MARGIN_LAST_TWO_POLLS_MS;
        if (timeDeltaLastTwoPollsMs > 0 && timeDeltaLastTwoPollsMs <= maxTimeDeltaMs) {
            mWifiMetrics.incrementConnectionDuration(timeDeltaLastTwoPollsMs,
                    mIsThroughputSufficient, mIsCellularDataAvailable);
            reportWifiHealthStat(currFrequency, timeDeltaLastTwoPollsMs, mIsThroughputSufficient,
                    mIsCellularDataAvailable);
        }

        boolean possibleDataStallTx = isTxTputLow
                || ccaLevel >= mDeviceConfigFacade.getDataStallCcaLevelThr()
                || txPer >= mDeviceConfigFacade.getDataStallTxPerThr();
        boolean possibleDataStallRx = isRxTputLow
                || ccaLevel >= mDeviceConfigFacade.getDataStallCcaLevelThr();

        boolean dataStallTx = isTxTrafficHigh ? possibleDataStallTx : mDataStallTx;
        boolean dataStallRx = isRxTrafficHigh ? possibleDataStallRx : mDataStallRx;

        return detectConsecutiveTwoDataStalls(timeDeltaLastTwoPollsMs, dataStallTx, dataStallRx);
    }

    // Data stall event is triggered if there are consecutive Tx and/or Rx data stalls
    // 1st data stall should be preceded by no data stall
    // Reset mDataStallStartTimeMs to -1 if currently there is no Tx or Rx data stall
    private int detectConsecutiveTwoDataStalls(int timeDeltaLastTwoPollsMs,
            boolean dataStallTx, boolean dataStallRx) {
        if (timeDeltaLastTwoPollsMs >= MAX_MS_DELTA_FOR_DATA_STALL) {
            return WifiIsUnusableEvent.TYPE_UNKNOWN;
        }

        if (dataStallTx || dataStallRx) {
            mDataStallTx = mDataStallTx || dataStallTx;
            mDataStallRx = mDataStallRx || dataStallRx;
            if (mDataStallStartTimeMs == -1) {
                mDataStallStartTimeMs = mClock.getElapsedSinceBootMillis();
                if (mDeviceConfigFacade.getDataStallDurationMs() == 0) {
                    mDataStallStartTimeMs = -1;
                    int result = calculateUsabilityEventType(mDataStallTx, mDataStallRx);
                    mDataStallRx = false;
                    mDataStallTx = false;
                    return result;
                }
            } else {
                long elapsedTime = mClock.getElapsedSinceBootMillis() - mDataStallStartTimeMs;
                if (elapsedTime >= mDeviceConfigFacade.getDataStallDurationMs()) {
                    mDataStallStartTimeMs = -1;
                    if (elapsedTime <= VALIDITY_PERIOD_OF_DATA_STALL_START_MS) {
                        int result = calculateUsabilityEventType(mDataStallTx, mDataStallRx);
                        mDataStallRx = false;
                        mDataStallTx = false;
                        return result;
                    } else {
                        mDataStallTx = false;
                        mDataStallRx = false;
                    }
                } else {
                    // No need to do anything.
                }
            }
        } else {
            mDataStallStartTimeMs = -1;
            mDataStallTx = false;
            mDataStallRx = false;
        }
        return WifiIsUnusableEvent.TYPE_UNKNOWN;
    }

    private int updateTxPer(long txSuccessDelta, long txRetriesDelta, boolean isSameBssidAndFreq) {
        if (!isSameBssidAndFreq) {
            return DEFAULT_TX_PACKET_ERROR_RATE;
        }
        long txAttempts = txSuccessDelta + txRetriesDelta;
        if (txAttempts <= 0) {
            return DEFAULT_TX_PACKET_ERROR_RATE;
        }
        return (int) (txRetriesDelta * 100 / txAttempts);
    }
    private int calculateUsabilityEventType(boolean dataStallTx, boolean dataStallRx) {
        int result = WifiIsUnusableEvent.TYPE_UNKNOWN;
        if (dataStallTx && dataStallRx) {
            result = WifiIsUnusableEvent.TYPE_DATA_STALL_BOTH;
        } else if (dataStallTx) {
            result = WifiIsUnusableEvent.TYPE_DATA_STALL_BAD_TX;
        } else if (dataStallRx) {
            result = WifiIsUnusableEvent.TYPE_DATA_STALL_TX_WITHOUT_RX;
        }
        mWifiMetrics.logWifiIsUnusableEvent(result);
        return result;
    }

    private boolean isThroughputSufficientInternal(int l2TxTputKbps, int l2RxTputKbps,
            boolean isTxTrafficHigh, boolean isRxTrafficHigh, int timeDeltaLastTwoPollsMs) {
        long txBytes = mFacade.getTotalTxBytes() - mFacade.getMobileTxBytes();
        long rxBytes = mFacade.getTotalRxBytes() - mFacade.getMobileRxBytes();
        if (timeDeltaLastTwoPollsMs > MAX_MS_DELTA_FOR_DATA_STALL
                || mLastTxBytes == 0 || mLastRxBytes == 0) {
            mLastTxBytes = txBytes;
            mLastRxBytes = rxBytes;
            return true;
        }

        int l3TxTputKbps = (int) ((txBytes - mLastTxBytes) * 8 / timeDeltaLastTwoPollsMs);
        int l3RxTputKbps = (int) ((rxBytes - mLastRxBytes) * 8 / timeDeltaLastTwoPollsMs);

        mLastTxBytes = txBytes;
        mLastRxBytes = rxBytes;

        boolean isTxTputSufficient = isL2ThroughputSufficient(l2TxTputKbps, l3TxTputKbps);
        boolean isRxTputSufficient = isL2ThroughputSufficient(l2RxTputKbps, l3RxTputKbps);
        isTxTputSufficient = detectAndOverrideFalseInSufficient(
                isTxTputSufficient, isTxTrafficHigh, mIsThroughputSufficient);
        isRxTputSufficient = detectAndOverrideFalseInSufficient(
                isRxTputSufficient, isRxTrafficHigh, mIsThroughputSufficient);

        boolean isThroughputSufficient = isTxTputSufficient && isRxTputSufficient;

        StringBuilder sb = new StringBuilder();
        logd(sb.append("L2 txTputKbps: ").append(l2TxTputKbps)
                .append(", rxTputKbps: ").append(l2RxTputKbps)
                .append(", L3 txTputKbps: ").append(l3TxTputKbps)
                .append(", rxTputKbps: ").append(l3RxTputKbps)
                .append(", TxTrafficHigh: ").append(isTxTrafficHigh)
                .append(", RxTrafficHigh: ").append(isRxTrafficHigh)
                .append(", Throughput Sufficient: ").append(isThroughputSufficient)
                .toString());
        return isThroughputSufficient;
    }

    /**
     * L2 tput is sufficient when one of the following conditions is met
     * 1) L3 tput is low and L2 tput is above its low threshold
     * 2) L3 tput is not low and L2 tput over L3 tput ratio is above sufficientRatioThr
     * 3) L3 tput is not low and L2 tput is above its high threshold
     * 4) L2 tput is invalid
     */
    private boolean isL2ThroughputSufficient(int l2TputKbps, int l3TputKbps) {
        if (l2TputKbps == INVALID_THROUGHPUT) return true;
        boolean isL3TputLow = (l3TputKbps * mDeviceConfigFacade.getTputSufficientRatioThrDen())
                < (mDeviceConfigFacade.getTputSufficientLowThrKbps()
                * mDeviceConfigFacade.getTputSufficientRatioThrNum());
        boolean isL2TputAboveLowThr =
                l2TputKbps >= mDeviceConfigFacade.getTputSufficientLowThrKbps();
        if (isL3TputLow) return isL2TputAboveLowThr;

        boolean isL2TputAboveHighThr =
                l2TputKbps >= mDeviceConfigFacade.getTputSufficientHighThrKbps();
        boolean isL2L3TputRatioAboveThr =
                (l2TputKbps * mDeviceConfigFacade.getTputSufficientRatioThrDen())
                >= (l3TputKbps * mDeviceConfigFacade.getTputSufficientRatioThrNum());
        return isL2TputAboveHighThr || isL2L3TputRatioAboveThr;
    }

    private boolean detectAndOverrideFalseInSufficient(boolean isTputSufficient,
            boolean isTrafficHigh, boolean lastIsTputSufficient) {
        boolean possibleFalseInsufficient = (!isTrafficHigh && !isTputSufficient);
        return  possibleFalseInsufficient ? lastIsTputSufficient : isTputSufficient;
    }

    /**
     * Report the latest Wifi connection health to WestWorld
     */
    private void reportWifiHealthStat(int frequency, int timeDeltaLastTwoPollsMs,
            boolean isThroughputSufficient,
            boolean isCellularDataAvailable) {
        int band = getBand(frequency);
        WifiStatsLog.write(WifiStatsLog.WIFI_HEALTH_STAT_REPORTED, timeDeltaLastTwoPollsMs,
                isThroughputSufficient,  isCellularDataAvailable, band);
    }

    private int getBand(int frequency) {
        int band;
        if (frequency >= KnownBandsChannelHelper.BAND_24_GHZ_START_FREQ
                && frequency <= KnownBandsChannelHelper.BAND_24_GHZ_END_FREQ) {
            band = WifiStatsLog.WIFI_HEALTH_STAT_REPORTED__BAND__BAND_2G;
        } else if (frequency >= KnownBandsChannelHelper.BAND_5_GHZ_START_FREQ
                && frequency <= KnownBandsChannelHelper.BAND_6_GHZ_END_FREQ) {
            if (frequency <= KnownBandsChannelHelper.BAND_5_GHZ_LOW_END_FREQ) {
                band = WifiStatsLog.WIFI_HEALTH_STAT_REPORTED__BAND__BAND_5G_LOW;
            } else if (frequency <= KnownBandsChannelHelper.BAND_5_GHZ_MID_END_FREQ) {
                band = WifiStatsLog.WIFI_HEALTH_STAT_REPORTED__BAND__BAND_5G_MIDDLE;
            } else if (frequency <= KnownBandsChannelHelper.BAND_5_GHZ_END_FREQ) {
                band = WifiStatsLog.WIFI_HEALTH_STAT_REPORTED__BAND__BAND_5G_HIGH;
            } else if (frequency <= KnownBandsChannelHelper.BAND_6_GHZ_LOW_END_FREQ) {
                band = WifiStatsLog.WIFI_HEALTH_STAT_REPORTED__BAND__BAND_6G_LOW;
            } else if (frequency <= KnownBandsChannelHelper.BAND_6_GHZ_MID_END_FREQ) {
                band = WifiStatsLog.WIFI_HEALTH_STAT_REPORTED__BAND__BAND_6G_MIDDLE;
            } else {
                band = WifiStatsLog.WIFI_HEALTH_STAT_REPORTED__BAND__BAND_6G_HIGH;
            }
        } else {
            band = WifiStatsLog.WIFI_HEALTH_STAT_REPORTED__BAND__UNKNOWN;
        }
        return band;
    }
    private void logd(String string) {
        if (mVerboseLoggingEnabled) {
            Log.d(TAG, string);
        }
    }
}
