1 /* 2 * Copyright 2017 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package com.android.server.wifi; 18 19 import android.annotation.NonNull; 20 import android.net.wifi.WifiInfo; 21 22 /** 23 * Extends WifiInfo with the methods for computing the averaged packet rates 24 */ 25 public class ExtendedWifiInfo extends WifiInfo { 26 private static final long RESET_TIME_STAMP = Long.MIN_VALUE; 27 private static final double FILTER_TIME_CONSTANT = 3000.0; 28 private static final int SOURCE_UNKNOWN = 0; 29 private static final int SOURCE_TRAFFIC_COUNTERS = 1; 30 private static final int SOURCE_LLSTATS = 2; 31 32 private final WifiGlobals mWifiGlobals; 33 private final String mIfaceName; 34 35 private int mLastSource = SOURCE_UNKNOWN; 36 private long mLastPacketCountUpdateTimeStamp = RESET_TIME_STAMP; 37 ExtendedWifiInfo(WifiGlobals wifiGlobals, String ifaceName)38 ExtendedWifiInfo(WifiGlobals wifiGlobals, String ifaceName) { 39 mWifiGlobals = wifiGlobals; 40 mIfaceName = ifaceName; 41 } 42 43 @Override reset()44 public void reset() { 45 super.reset(); 46 mLastSource = SOURCE_UNKNOWN; 47 mLastPacketCountUpdateTimeStamp = RESET_TIME_STAMP; 48 if (mWifiGlobals.isConnectedMacRandomizationEnabled()) { 49 setMacAddress(DEFAULT_MAC_ADDRESS); 50 } 51 } 52 53 /** 54 * Updates the packet rates using link layer stats 55 * 56 * @param stats WifiLinkLayerStats 57 * @param timeStamp time in milliseconds 58 */ updatePacketRates(@onNull WifiLinkLayerStats stats, long timeStamp)59 public void updatePacketRates(@NonNull WifiLinkLayerStats stats, long timeStamp) { 60 long txgood = stats.txmpdu_be + stats.txmpdu_bk + stats.txmpdu_vi + stats.txmpdu_vo; 61 long txretries = stats.retries_be + stats.retries_bk + stats.retries_vi + stats.retries_vo; 62 long txbad = stats.lostmpdu_be + stats.lostmpdu_bk + stats.lostmpdu_vi + stats.lostmpdu_vo; 63 long rxgood = stats.rxmpdu_be + stats.rxmpdu_bk + stats.rxmpdu_vi + stats.rxmpdu_vo; 64 update(SOURCE_LLSTATS, txgood, txretries, txbad, rxgood, timeStamp); 65 } 66 67 /** 68 * This function is less powerful and used if the WifiLinkLayerStats API is not implemented 69 * at the Wifi HAL 70 */ updatePacketRates(long txPackets, long rxPackets, long timeStamp)71 public void updatePacketRates(long txPackets, long rxPackets, long timeStamp) { 72 update(SOURCE_TRAFFIC_COUNTERS, txPackets, 0, 0, rxPackets, timeStamp); 73 } 74 update(int source, long txgood, long txretries, long txbad, long rxgood, long timeStamp)75 private void update(int source, long txgood, long txretries, long txbad, long rxgood, 76 long timeStamp) { 77 if (source == mLastSource 78 && mLastPacketCountUpdateTimeStamp != RESET_TIME_STAMP 79 && mLastPacketCountUpdateTimeStamp < timeStamp 80 && txBad <= txbad 81 && txSuccess <= txgood 82 && rxSuccess <= rxgood 83 && txRetries <= txretries) { 84 long timeDelta = timeStamp - mLastPacketCountUpdateTimeStamp; 85 double lastSampleWeight = Math.exp(-1.0 * timeDelta / FILTER_TIME_CONSTANT); 86 double currentSampleWeight = 1.0 - lastSampleWeight; 87 88 setLostTxPacketsPerSecond(getLostTxPacketsPerSecond() * lastSampleWeight 89 + (txbad - txBad) * 1000.0 / timeDelta 90 * currentSampleWeight); 91 setSuccessfulTxPacketsPerSecond(getSuccessfulTxPacketsPerSecond() * lastSampleWeight 92 + (txgood - txSuccess) * 1000.0 / timeDelta 93 * currentSampleWeight); 94 setSuccessfulRxPacketsPerSecond(getSuccessfulRxPacketsPerSecond() * lastSampleWeight 95 + (rxgood - rxSuccess) * 1000.0 / timeDelta 96 * currentSampleWeight); 97 setRetriedTxPacketsRate(getRetriedTxPacketsPerSecond() * lastSampleWeight 98 + (txretries - txRetries) * 1000.0 / timeDelta 99 * currentSampleWeight); 100 } else { 101 setLostTxPacketsPerSecond(0); 102 setSuccessfulTxPacketsPerSecond(0); 103 setSuccessfulRxPacketsPerSecond(0); 104 setRetriedTxPacketsRate(0); 105 mLastSource = source; 106 } 107 txBad = txbad; 108 txSuccess = txgood; 109 rxSuccess = rxgood; 110 txRetries = txretries; 111 mLastPacketCountUpdateTimeStamp = timeStamp; 112 } 113 getIfaceName()114 public String getIfaceName() { 115 return mIfaceName; 116 } 117 } 118