1 /* 2 * Copyright 2014 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.util.SparseArray; 20 21 import java.util.Arrays; 22 23 /** 24 * A class representing link layer statistics collected over a Wifi Interface. 25 */ 26 27 /** 28 * {@hide} 29 */ 30 public class WifiLinkLayerStats { 31 public static final String V1_0 = "V1_0"; 32 public static final String V1_3 = "V1_3"; 33 public static final String V1_5 = "V1_5"; 34 35 /** The version of hal StaLinkLayerStats **/ 36 public String version; 37 38 /** Number of beacons received from our own AP */ 39 public int beacon_rx; 40 41 /** RSSI of management frames */ 42 public int rssi_mgmt; 43 44 /* Packet counters and contention time stats */ 45 46 /** WME Best Effort Access Category received mpdu */ 47 public long rxmpdu_be; 48 /** WME Best Effort Access Category transmitted mpdu */ 49 public long txmpdu_be; 50 /** WME Best Effort Access Category lost mpdu */ 51 public long lostmpdu_be; 52 /** WME Best Effort Access Category number of transmission retries */ 53 public long retries_be; 54 /** WME Best Effort Access Category data packet min contention time in microseconds */ 55 public long contentionTimeMinBeInUsec; 56 /** WME Best Effort Access Category data packet max contention time in microseconds */ 57 public long contentionTimeMaxBeInUsec; 58 /** WME Best Effort Access Category data packet average contention time in microseconds */ 59 public long contentionTimeAvgBeInUsec; 60 /** 61 * WME Best Effort Access Category number of data packets used for deriving the min, the max, 62 * and the average contention time 63 */ 64 public long contentionNumSamplesBe; 65 66 /** WME Background Access Category received mpdu */ 67 public long rxmpdu_bk; 68 /** WME Background Access Category transmitted mpdu */ 69 public long txmpdu_bk; 70 /** WME Background Access Category lost mpdu */ 71 public long lostmpdu_bk; 72 /** WME Background Access Category number of transmission retries */ 73 public long retries_bk; 74 /** WME Background Access Category data packet min contention time in microseconds */ 75 public long contentionTimeMinBkInUsec; 76 /** WME Background Access Category data packet max contention time in microseconds */ 77 public long contentionTimeMaxBkInUsec; 78 /** WME Background Access Category data packet average contention time in microseconds */ 79 public long contentionTimeAvgBkInUsec; 80 /** 81 * WME Background Access Category number of data packets used for deriving the min, the max, 82 * and the average contention time 83 */ 84 public long contentionNumSamplesBk; 85 86 /** WME Video Access Category received mpdu */ 87 public long rxmpdu_vi; 88 /** WME Video Access Category transmitted mpdu */ 89 public long txmpdu_vi; 90 /** WME Video Access Category lost mpdu */ 91 public long lostmpdu_vi; 92 /** WME Video Access Category number of transmission retries */ 93 public long retries_vi; 94 /** WME Video Access Category data packet min contention time in microseconds */ 95 public long contentionTimeMinViInUsec; 96 /** WME Video Access Category data packet max contention time in microseconds */ 97 public long contentionTimeMaxViInUsec; 98 /** WME Video Access Category data packet average contention time in microseconds */ 99 public long contentionTimeAvgViInUsec; 100 /** 101 * WME Video Access Category number of data packets used for deriving the min, the max, and 102 * the average contention time 103 */ 104 public long contentionNumSamplesVi; 105 106 /** WME Voice Access Category received mpdu */ 107 public long rxmpdu_vo; 108 /** WME Voice Access Category transmitted mpdu */ 109 public long txmpdu_vo; 110 /** WME Voice Access Category lost mpdu */ 111 public long lostmpdu_vo; 112 /** WME Voice Access Category number of transmission retries */ 113 public long retries_vo; 114 /** WME Voice Access Category data packet min contention time in microseconds */ 115 public long contentionTimeMinVoInUsec; 116 /** WME Voice Access Category data packet max contention time in microseconds */ 117 public long contentionTimeMaxVoInUsec; 118 /** WME Voice Access Category data packet average contention time in microseconds */ 119 public long contentionTimeAvgVoInUsec; 120 /** 121 * WME Voice Access Category number of data packets used for deriving the min, the max, and 122 * the average contention time 123 */ 124 public long contentionNumSamplesVo; 125 126 /** 127 * Cumulative milliseconds when radio is awake 128 */ 129 public int on_time; 130 /** 131 * Cumulative milliseconds of active transmission 132 */ 133 public int tx_time; 134 /** 135 * Cumulative milliseconds per radio transmit power level of active transmission 136 */ 137 public int[] tx_time_per_level; 138 /** 139 * Cumulative milliseconds of active receive 140 */ 141 public int rx_time; 142 /** 143 * Cumulative milliseconds when radio is awake due to scan 144 */ 145 public int on_time_scan; 146 /** 147 * Cumulative milliseconds when radio is awake due to nan scan 148 */ 149 public int on_time_nan_scan; 150 /** 151 * Cumulative milliseconds when radio is awake due to background scan 152 */ 153 public int on_time_background_scan; 154 /** 155 * Cumulative milliseconds when radio is awake due to roam scan 156 */ 157 public int on_time_roam_scan; 158 /** 159 * Cumulative milliseconds when radio is awake due to pno scan 160 */ 161 public int on_time_pno_scan; 162 /** 163 * Cumulative milliseconds when radio is awake due to hotspot 2.0 scan amd GAS exchange 164 */ 165 public int on_time_hs20_scan; 166 /** 167 * channel stats 168 */ 169 public static class ChannelStats { 170 /** 171 * Channel frequency in MHz; 172 */ 173 public int frequency; 174 /** 175 * Cumulative milliseconds radio is awake on this channel 176 */ 177 public int radioOnTimeMs; 178 /** 179 * Cumulative milliseconds CCA is held busy on this channel 180 */ 181 public int ccaBusyTimeMs; 182 } 183 /** 184 * Channel stats list 185 */ 186 public final SparseArray<ChannelStats> channelStatsMap = new SparseArray<>(); 187 188 /** 189 * numRadios - Number of radios used for coalescing above radio stats. 190 */ 191 public int numRadios; 192 193 /** 194 * TimeStamp - absolute milliseconds from boot when these stats were sampled. 195 */ 196 public long timeStampInMs; 197 198 /** 199 * Duty cycle of the iface. 200 * if this iface is being served using time slicing on a radio with one or more ifaces 201 * (i.e MCC), then the duty cycle assigned to this iface in %. 202 * If not using time slicing (i.e SCC or DBS), set to 100. 203 */ 204 public short timeSliceDutyCycleInPercent = -1; 205 206 /** 207 * Per rate information and statistics. 208 */ 209 public static class RateStat { 210 /** 211 * Preamble information. 0: OFDM, 1:CCK, 2:HT 3:VHT 4:HE 5..7 reserved. 212 */ 213 public int preamble; 214 /** 215 * Number of spatial streams. 0:1x1, 1:2x2, 3:3x3, 4:4x4. 216 */ 217 public int nss; 218 /** 219 * Bandwidth information. 0:20MHz, 1:40Mhz, 2:80Mhz, 3:160Mhz. 220 */ 221 public int bw; 222 /** 223 * MCS index. OFDM/CCK rate code would be as per IEEE std in the units of 0.5Mbps. 224 * HT/VHT/HE: it would be MCS index. 225 */ 226 public int rateMcsIdx; 227 /** 228 * Bitrate in units of 100 Kbps. 229 */ 230 public int bitRateInKbps; 231 /** 232 * Number of successfully transmitted data packets (ACK received). 233 */ 234 public int txMpdu; 235 /** 236 * Number of received data packets. 237 */ 238 public int rxMpdu; 239 /** 240 * Number of data packet losses (no ACK). 241 */ 242 public int mpduLost; 243 /** 244 * Number of data packet retries. 245 */ 246 public int retries; 247 } 248 249 /** 250 * Per peer statistics. 251 */ 252 public static class PeerInfo { 253 /** 254 * Station count. 255 */ 256 public short staCount; 257 /** 258 * Channel utilization. 259 */ 260 public short chanUtil; 261 /** 262 * Per rate statistics. 263 */ 264 public RateStat[] rateStats; 265 } 266 267 /** 268 * Peer statistics. 269 */ 270 public PeerInfo[] peerInfo; 271 272 /** 273 * Radio stats 274 */ 275 public static class RadioStat { 276 /** 277 * Radio identifier 278 */ 279 public int radio_id; 280 /** 281 * Cumulative milliseconds when radio is awake from the last radio chip reset 282 */ 283 public int on_time; 284 /** 285 * Cumulative milliseconds of active transmission from the last radio chip reset 286 */ 287 public int tx_time; 288 /** 289 * Cumulative milliseconds of active receive from the last radio chip reset 290 */ 291 public int rx_time; 292 /** 293 * Cumulative milliseconds when radio is awake due to scan from the last radio chip reset 294 */ 295 public int on_time_scan; 296 /** 297 * Cumulative milliseconds when radio is awake due to nan scan from the last radio chip 298 * reset 299 */ 300 public int on_time_nan_scan; 301 /** 302 * Cumulative milliseconds when radio is awake due to background scan from the last radio 303 * chip reset 304 */ 305 public int on_time_background_scan; 306 /** 307 * Cumulative milliseconds when radio is awake due to roam scan from the last radio chip 308 * reset 309 */ 310 public int on_time_roam_scan; 311 /** 312 * Cumulative milliseconds when radio is awake due to pno scan from the last radio chip 313 * reset 314 */ 315 public int on_time_pno_scan; 316 /** 317 * Cumulative milliseconds when radio is awake due to hotspot 2.0 scan amd GAS exchange 318 * from the last radio chip reset 319 */ 320 public int on_time_hs20_scan; 321 /** 322 * Channel stats list 323 */ 324 public final SparseArray<ChannelStats> channelStatsMap = new SparseArray<>(); 325 } 326 327 /** 328 * Radio stats of all the radios. 329 */ 330 public RadioStat[] radioStats; 331 332 @Override toString()333 public String toString() { 334 StringBuilder sbuf = new StringBuilder(); 335 sbuf.append(" WifiLinkLayerStats: ").append('\n'); 336 337 sbuf.append(" version of StaLinkLayerStats: ").append(version).append('\n'); 338 sbuf.append(" my bss beacon rx: ").append(Integer.toString(this.beacon_rx)).append('\n'); 339 sbuf.append(" RSSI mgmt: ").append(Integer.toString(this.rssi_mgmt)).append('\n'); 340 sbuf.append(" BE : ").append(" rx=").append(Long.toString(this.rxmpdu_be)) 341 .append(" tx=").append(Long.toString(this.txmpdu_be)) 342 .append(" lost=").append(Long.toString(this.lostmpdu_be)) 343 .append(" retries=").append(Long.toString(this.retries_be)).append('\n') 344 .append(" contention_time_min") 345 .append(Long.toString(this.contentionTimeMinBeInUsec)) 346 .append(" contention_time_max") 347 .append(Long.toString(this.contentionTimeMaxBeInUsec)).append('\n') 348 .append(" contention_time_avg") 349 .append(Long.toString(this.contentionTimeAvgBeInUsec)) 350 .append(" contention_num_samples") 351 .append(Long.toString(this.contentionNumSamplesBe)).append('\n'); 352 sbuf.append(" BK : ").append(" rx=").append(Long.toString(this.rxmpdu_bk)) 353 .append(" tx=").append(Long.toString(this.txmpdu_bk)) 354 .append(" lost=").append(Long.toString(this.lostmpdu_bk)) 355 .append(" retries=").append(Long.toString(this.retries_bk)).append('\n') 356 .append(" contention_time_min") 357 .append(Long.toString(this.contentionTimeMinBkInUsec)) 358 .append(" contention_time_max") 359 .append(Long.toString(this.contentionTimeMaxBkInUsec)).append('\n') 360 .append(" contention_time_avg") 361 .append(Long.toString(this.contentionTimeAvgBkInUsec)) 362 .append(" contention_num_samples") 363 .append(Long.toString(this.contentionNumSamplesBk)).append('\n'); 364 sbuf.append(" VI : ").append(" rx=").append(Long.toString(this.rxmpdu_vi)) 365 .append(" tx=").append(Long.toString(this.txmpdu_vi)) 366 .append(" lost=").append(Long.toString(this.lostmpdu_vi)) 367 .append(" retries=").append(Long.toString(this.retries_vi)).append('\n') 368 .append(" contention_time_min") 369 .append(Long.toString(this.contentionTimeMinViInUsec)) 370 .append(" contention_time_max") 371 .append(Long.toString(this.contentionTimeMaxViInUsec)).append('\n') 372 .append(" contention_time_avg") 373 .append(Long.toString(this.contentionTimeAvgViInUsec)) 374 .append(" contention_num_samples") 375 .append(Long.toString(this.contentionNumSamplesVi)).append('\n'); 376 sbuf.append(" VO : ").append(" rx=").append(Long.toString(this.rxmpdu_vo)) 377 .append(" tx=").append(Long.toString(this.txmpdu_vo)) 378 .append(" lost=").append(Long.toString(this.lostmpdu_vo)) 379 .append(" retries=").append(Long.toString(this.retries_vo)).append('\n') 380 .append(" contention_time_min") 381 .append(Long.toString(this.contentionTimeMinVoInUsec)) 382 .append(" contention_time_max") 383 .append(Long.toString(this.contentionTimeMaxVoInUsec)).append('\n') 384 .append(" contention_time_avg") 385 .append(Long.toString(this.contentionTimeAvgVoInUsec)) 386 .append(" contention_num_samples") 387 .append(Long.toString(this.contentionNumSamplesVo)).append('\n'); 388 sbuf.append(" numRadios=" + numRadios) 389 .append(" on_time= ").append(Integer.toString(this.on_time)) 390 .append(" tx_time=").append(Integer.toString(this.tx_time)) 391 .append(" rx_time=").append(Integer.toString(this.rx_time)) 392 .append(" scan_time=").append(Integer.toString(this.on_time_scan)).append('\n') 393 .append(" nan_scan_time=") 394 .append(Integer.toString(this.on_time_nan_scan)).append('\n') 395 .append(" g_scan_time=") 396 .append(Integer.toString(this.on_time_background_scan)).append('\n') 397 .append(" roam_scan_time=") 398 .append(Integer.toString(this.on_time_roam_scan)).append('\n') 399 .append(" pno_scan_time=") 400 .append(Integer.toString(this.on_time_pno_scan)).append('\n') 401 .append(" hs2.0_scan_time=") 402 .append(Integer.toString(this.on_time_hs20_scan)).append('\n') 403 .append(" tx_time_per_level=" + Arrays.toString(tx_time_per_level)).append('\n'); 404 int numChanStats = this.channelStatsMap.size(); 405 sbuf.append(" Number of channel stats=").append(numChanStats).append('\n'); 406 for (int i = 0; i < numChanStats; ++i) { 407 ChannelStats channelStatsEntry = this.channelStatsMap.valueAt(i); 408 sbuf.append(" Frequency=").append(channelStatsEntry.frequency) 409 .append(" radioOnTimeMs=").append(channelStatsEntry.radioOnTimeMs) 410 .append(" ccaBusyTimeMs=").append(channelStatsEntry.ccaBusyTimeMs).append('\n'); 411 } 412 int numRadios = this.radioStats == null ? 0 : this.radioStats.length; 413 sbuf.append(" Individual radio stats: numRadios=").append(numRadios).append('\n'); 414 for (int i = 0; i < numRadios; i++) { 415 RadioStat radio = this.radioStats[i]; 416 sbuf.append(" radio_id=" + radio.radio_id) 417 .append(" on_time=").append(Integer.toString(radio.on_time)) 418 .append(" tx_time=").append(Integer.toString(radio.tx_time)) 419 .append(" rx_time=").append(Integer.toString(radio.rx_time)) 420 .append(" scan_time=").append(Integer.toString(radio.on_time_scan)).append('\n') 421 .append(" nan_scan_time=") 422 .append(Integer.toString(radio.on_time_nan_scan)).append('\n') 423 .append(" g_scan_time=") 424 .append(Integer.toString(radio.on_time_background_scan)).append('\n') 425 .append(" roam_scan_time=") 426 .append(Integer.toString(radio.on_time_roam_scan)).append('\n') 427 .append(" pno_scan_time=") 428 .append(Integer.toString(radio.on_time_pno_scan)).append('\n') 429 .append(" hs2.0_scan_time=") 430 .append(Integer.toString(radio.on_time_hs20_scan)).append('\n'); 431 int numRadioChanStats = radio.channelStatsMap.size(); 432 sbuf.append(" Number of channel stats=").append(numRadioChanStats).append('\n'); 433 for (int j = 0; j < numRadioChanStats; ++j) { 434 ChannelStats channelStatsEntry = radio.channelStatsMap.valueAt(j); 435 sbuf.append(" Frequency=").append(channelStatsEntry.frequency) 436 .append(" radioOnTimeMs=").append(channelStatsEntry.radioOnTimeMs) 437 .append(" ccaBusyTimeMs=").append(channelStatsEntry.ccaBusyTimeMs) 438 .append('\n'); 439 } 440 } 441 sbuf.append(" ts=" + timeStampInMs); 442 int numPeers = this.peerInfo == null ? 0 : this.peerInfo.length; 443 sbuf.append(" Number of peers=").append(numPeers).append('\n'); 444 for (int i = 0; i < numPeers; i++) { 445 PeerInfo peer = this.peerInfo[i]; 446 sbuf.append(" staCount=").append(peer.staCount) 447 .append(" chanUtil=").append(peer.chanUtil).append('\n'); 448 int numRateStats = peer.rateStats == null ? 0 : peer.rateStats.length; 449 for (int j = 0; j < numRateStats; j++) { 450 RateStat rateStat = peer.rateStats[j]; 451 sbuf.append(" preamble=").append(rateStat.preamble) 452 .append(" nss=").append(rateStat.nss) 453 .append(" bw=").append(rateStat.bw) 454 .append(" rateMcsIdx=").append(rateStat.rateMcsIdx) 455 .append(" bitRateInKbps=").append(rateStat.bitRateInKbps).append('\n') 456 .append(" txMpdu=").append(rateStat.txMpdu) 457 .append(" rxMpdu=").append(rateStat.rxMpdu) 458 .append(" mpduLost=").append(rateStat.mpduLost) 459 .append(" retries=").append(rateStat.retries).append('\n'); 460 } 461 } 462 return sbuf.toString(); 463 } 464 465 } 466