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 int mLastSource = SOURCE_UNKNOWN;
33     private long mLastPacketCountUpdateTimeStamp = RESET_TIME_STAMP;
34     private boolean mEnableConnectedMacRandomization = false;
35 
36     @Override
reset()37     public void reset() {
38         super.reset();
39         mLastSource = SOURCE_UNKNOWN;
40         mLastPacketCountUpdateTimeStamp = RESET_TIME_STAMP;
41         if (mEnableConnectedMacRandomization) {
42             setMacAddress(DEFAULT_MAC_ADDRESS);
43         }
44     }
45 
46     /**
47      * Updates the packet rates using link layer stats
48      *
49      * @param stats WifiLinkLayerStats
50      * @param timeStamp time in milliseconds
51      */
updatePacketRates(@onNull WifiLinkLayerStats stats, long timeStamp)52     public void updatePacketRates(@NonNull WifiLinkLayerStats stats, long timeStamp) {
53         long txgood = stats.txmpdu_be + stats.txmpdu_bk + stats.txmpdu_vi + stats.txmpdu_vo;
54         long txretries = stats.retries_be + stats.retries_bk + stats.retries_vi + stats.retries_vo;
55         long txbad = stats.lostmpdu_be + stats.lostmpdu_bk + stats.lostmpdu_vi + stats.lostmpdu_vo;
56         long rxgood = stats.rxmpdu_be + stats.rxmpdu_bk + stats.rxmpdu_vi + stats.rxmpdu_vo;
57         update(SOURCE_LLSTATS, txgood, txretries, txbad, rxgood, timeStamp);
58     }
59 
60     /**
61      * This function is less powerful and used if the WifiLinkLayerStats API is not implemented
62      * at the Wifi HAL
63      */
updatePacketRates(long txPackets, long rxPackets, long timeStamp)64     public void updatePacketRates(long txPackets, long rxPackets, long timeStamp) {
65         update(SOURCE_TRAFFIC_COUNTERS, txPackets, 0, 0, rxPackets, timeStamp);
66     }
67 
update(int source, long txgood, long txretries, long txbad, long rxgood, long timeStamp)68     private void update(int source, long txgood, long txretries, long txbad, long rxgood,
69             long timeStamp) {
70         if (source == mLastSource
71                 && mLastPacketCountUpdateTimeStamp != RESET_TIME_STAMP
72                 && mLastPacketCountUpdateTimeStamp < timeStamp
73                 && txBad <= txbad
74                 && txSuccess <= txgood
75                 && rxSuccess <= rxgood
76                 && txRetries <= txretries) {
77             long timeDelta = timeStamp - mLastPacketCountUpdateTimeStamp;
78             double lastSampleWeight = Math.exp(-1.0 * timeDelta / FILTER_TIME_CONSTANT);
79             double currentSampleWeight = 1.0 - lastSampleWeight;
80 
81             txBadRate = txBadRate * lastSampleWeight
82                     + (txbad - txBad) * 1000.0 / timeDelta
83                     * currentSampleWeight;
84             txSuccessRate = txSuccessRate * lastSampleWeight
85                     + (txgood - txSuccess) * 1000.0 / timeDelta
86                     * currentSampleWeight;
87             rxSuccessRate = rxSuccessRate * lastSampleWeight
88                     + (rxgood - rxSuccess) * 1000.0 / timeDelta
89                     * currentSampleWeight;
90             txRetriesRate = txRetriesRate * lastSampleWeight
91                     + (txretries - txRetries) * 1000.0 / timeDelta
92                     * currentSampleWeight;
93         } else {
94             txBadRate = 0;
95             txSuccessRate = 0;
96             rxSuccessRate = 0;
97             txRetriesRate = 0;
98             mLastSource = source;
99         }
100         txBad = txbad;
101         txSuccess = txgood;
102         rxSuccess = rxgood;
103         txRetries = txretries;
104         mLastPacketCountUpdateTimeStamp = timeStamp;
105     }
106 
107     /**
108      * Updates whether Connected MAC Randomization is enabled.
109      *
110      * @hide
111      */
setEnableConnectedMacRandomization(boolean enableConnectedMacRandomization)112     public void setEnableConnectedMacRandomization(boolean enableConnectedMacRandomization) {
113         mEnableConnectedMacRandomization = enableConnectedMacRandomization;
114     }
115 
116 }
117