/* * Copyright 2017 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.annotation.NonNull; import android.net.wifi.WifiInfo; /** * Extends WifiInfo with the methods for computing the averaged packet rates */ public class ExtendedWifiInfo extends WifiInfo { private static final long RESET_TIME_STAMP = Long.MIN_VALUE; private static final double FILTER_TIME_CONSTANT = 3000.0; private static final int SOURCE_UNKNOWN = 0; private static final int SOURCE_TRAFFIC_COUNTERS = 1; private static final int SOURCE_LLSTATS = 2; private final WifiGlobals mWifiGlobals; private final String mIfaceName; private int mLastSource = SOURCE_UNKNOWN; private long mLastPacketCountUpdateTimeStamp = RESET_TIME_STAMP; ExtendedWifiInfo(WifiGlobals wifiGlobals, String ifaceName) { mWifiGlobals = wifiGlobals; mIfaceName = ifaceName; } @Override public void reset() { super.reset(); mLastSource = SOURCE_UNKNOWN; mLastPacketCountUpdateTimeStamp = RESET_TIME_STAMP; if (mWifiGlobals.isConnectedMacRandomizationEnabled()) { setMacAddress(DEFAULT_MAC_ADDRESS); } } /** * Updates the packet rates using link layer stats * * @param stats WifiLinkLayerStats * @param timeStamp time in milliseconds */ public void updatePacketRates(@NonNull WifiLinkLayerStats stats, long timeStamp) { long txgood = stats.txmpdu_be + stats.txmpdu_bk + stats.txmpdu_vi + stats.txmpdu_vo; long txretries = stats.retries_be + stats.retries_bk + stats.retries_vi + stats.retries_vo; long txbad = stats.lostmpdu_be + stats.lostmpdu_bk + stats.lostmpdu_vi + stats.lostmpdu_vo; long rxgood = stats.rxmpdu_be + stats.rxmpdu_bk + stats.rxmpdu_vi + stats.rxmpdu_vo; update(SOURCE_LLSTATS, txgood, txretries, txbad, rxgood, timeStamp); } /** * This function is less powerful and used if the WifiLinkLayerStats API is not implemented * at the Wifi HAL */ public void updatePacketRates(long txPackets, long rxPackets, long timeStamp) { update(SOURCE_TRAFFIC_COUNTERS, txPackets, 0, 0, rxPackets, timeStamp); } private void update(int source, long txgood, long txretries, long txbad, long rxgood, long timeStamp) { if (source == mLastSource && mLastPacketCountUpdateTimeStamp != RESET_TIME_STAMP && mLastPacketCountUpdateTimeStamp < timeStamp && txBad <= txbad && txSuccess <= txgood && rxSuccess <= rxgood && txRetries <= txretries) { long timeDelta = timeStamp - mLastPacketCountUpdateTimeStamp; double lastSampleWeight = Math.exp(-1.0 * timeDelta / FILTER_TIME_CONSTANT); double currentSampleWeight = 1.0 - lastSampleWeight; setLostTxPacketsPerSecond(getLostTxPacketsPerSecond() * lastSampleWeight + (txbad - txBad) * 1000.0 / timeDelta * currentSampleWeight); setSuccessfulTxPacketsPerSecond(getSuccessfulTxPacketsPerSecond() * lastSampleWeight + (txgood - txSuccess) * 1000.0 / timeDelta * currentSampleWeight); setSuccessfulRxPacketsPerSecond(getSuccessfulRxPacketsPerSecond() * lastSampleWeight + (rxgood - rxSuccess) * 1000.0 / timeDelta * currentSampleWeight); setRetriedTxPacketsRate(getRetriedTxPacketsPerSecond() * lastSampleWeight + (txretries - txRetries) * 1000.0 / timeDelta * currentSampleWeight); } else { setLostTxPacketsPerSecond(0); setSuccessfulTxPacketsPerSecond(0); setSuccessfulRxPacketsPerSecond(0); setRetriedTxPacketsRate(0); mLastSource = source; } txBad = txbad; txSuccess = txgood; rxSuccess = rxgood; txRetries = txretries; mLastPacketCountUpdateTimeStamp = timeStamp; } public String getIfaceName() { return mIfaceName; } }