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.net.wifi.WifiManager; 20 import android.net.wifi.WifiUsabilityStatsEntry.LinkState; 21 import android.net.wifi.WifiUsabilityStatsEntry.WifiChannelBandwidth; 22 import android.util.SparseArray; 23 24 import java.util.Arrays; 25 import java.util.List; 26 27 /** 28 * A class representing link layer statistics collected over a Wifi Interface. 29 */ 30 31 /** 32 * {@hide} 33 */ 34 public class WifiLinkLayerStats { 35 public static final String V1_0 = "V1_0"; 36 public static final String V1_3 = "V1_3"; 37 public static final String V1_5 = "V1_5"; 38 39 /** The version of hal StaLinkLayerStats **/ 40 public String version; 41 42 /** 43 * Link specific statistics. 44 */ 45 public static class LinkSpecificStats { 46 47 /** Link identifier of the link */ 48 public int link_id; 49 50 /** Link state as {@link LinkState} */ 51 public @LinkState int state; 52 53 /** Identifier of the radio on which link is currently operating */ 54 public int radio_id; 55 56 /** Frequency of the link in MHz */ 57 public int frequencyMhz; 58 59 /** Number of beacons received from our own AP */ 60 public int beacon_rx; 61 62 /** RSSI of management frames */ 63 public int rssi_mgmt; 64 65 /* Packet counters and contention time stats */ 66 67 /** WME Best Effort Access Category received mpdu */ 68 public long rxmpdu_be; 69 /** WME Best Effort Access Category transmitted mpdu */ 70 public long txmpdu_be; 71 /** WME Best Effort Access Category lost mpdu */ 72 public long lostmpdu_be; 73 /** WME Best Effort Access Category number of transmission retries */ 74 public long retries_be; 75 /** WME Best Effort Access Category data packet min contention time in microseconds */ 76 public long contentionTimeMinBeInUsec; 77 /** WME Best Effort Access Category data packet max contention time in microseconds */ 78 public long contentionTimeMaxBeInUsec; 79 /** WME Best Effort Access Category data packet average contention time in microseconds */ 80 public long contentionTimeAvgBeInUsec; 81 /** 82 * WME Best Effort Access Category number of data packets used for deriving the min, the 83 * max, 84 * and the average contention time 85 */ 86 public long contentionNumSamplesBe; 87 88 /** WME Background Access Category received mpdu */ 89 public long rxmpdu_bk; 90 /** WME Background Access Category transmitted mpdu */ 91 public long txmpdu_bk; 92 /** WME Background Access Category lost mpdu */ 93 public long lostmpdu_bk; 94 /** WME Background Access Category number of transmission retries */ 95 public long retries_bk; 96 /** WME Background Access Category data packet min contention time in microseconds */ 97 public long contentionTimeMinBkInUsec; 98 /** WME Background Access Category data packet max contention time in microseconds */ 99 public long contentionTimeMaxBkInUsec; 100 /** WME Background Access Category data packet average contention time in microseconds */ 101 public long contentionTimeAvgBkInUsec; 102 /** 103 * WME Background Access Category number of data packets used for deriving the min, the max, 104 * and the average contention time 105 */ 106 public long contentionNumSamplesBk; 107 108 /** WME Video Access Category received mpdu */ 109 public long rxmpdu_vi; 110 /** WME Video Access Category transmitted mpdu */ 111 public long txmpdu_vi; 112 /** WME Video Access Category lost mpdu */ 113 public long lostmpdu_vi; 114 /** WME Video Access Category number of transmission retries */ 115 public long retries_vi; 116 /** WME Video Access Category data packet min contention time in microseconds */ 117 public long contentionTimeMinViInUsec; 118 /** WME Video Access Category data packet max contention time in microseconds */ 119 public long contentionTimeMaxViInUsec; 120 /** WME Video Access Category data packet average contention time in microseconds */ 121 public long contentionTimeAvgViInUsec; 122 /** 123 * WME Video Access Category number of data packets used for deriving the min, the max, and 124 * the average contention time 125 */ 126 public long contentionNumSamplesVi; 127 128 /** WME Voice Access Category received mpdu */ 129 public long rxmpdu_vo; 130 /** WME Voice Access Category transmitted mpdu */ 131 public long txmpdu_vo; 132 /** WME Voice Access Category lost mpdu */ 133 public long lostmpdu_vo; 134 /** WME Voice Access Category number of transmission retries */ 135 public long retries_vo; 136 /** WME Voice Access Category data packet min contention time in microseconds */ 137 public long contentionTimeMinVoInUsec; 138 /** WME Voice Access Category data packet max contention time in microseconds */ 139 public long contentionTimeMaxVoInUsec; 140 /** WME Voice Access Category data packet average contention time in microseconds */ 141 public long contentionTimeAvgVoInUsec; 142 /** 143 * WME Voice Access Category number of data packets used for deriving the min, the max, and 144 * the average contention time 145 */ 146 public long contentionNumSamplesVo; 147 148 /** 149 * Duty cycle of the link. 150 * if this link is being served using time slicing on a radio with one or more ifaces 151 * (i.e MCC), then the duty cycle assigned to this iface in %. 152 * If not using time slicing (i.e SCC or DBS), set to 100. 153 */ 154 public short timeSliceDutyCycleInPercent = -1; 155 156 /** 157 * Peer statistics. 158 */ 159 public PeerInfo[] peerInfo; 160 161 public List<ScanResultWithSameFreq> scan_results_same_freq; 162 } 163 164 public LinkSpecificStats[] links; 165 166 /** 167 * Scan result who has the same frequency with WiFi Link 168 */ 169 public static class ScanResultWithSameFreq { 170 /** 171 * timestamp in microseconds (since boot) when 172 * this result was last seen. 173 */ 174 public long scan_result_timestamp_micros; 175 /** The detected signal level in dBm, also known as the RSSI */ 176 public int rssi; 177 /** The center frequency of the primary 20 MHz frequency (in MHz) of the channel */ 178 public int frequencyMhz; 179 /** BSSID of access point */ 180 public String bssid; 181 } 182 183 /** 184 * The stats below which is already captured in WifiLinkLayerStats#LinkSpecificStats will be 185 * having an aggregated value. The aggregation logic is defined at 186 * wifiNative#setAggregatedLinkLayerStats(). 187 */ 188 189 /** Number of beacons received from our own AP */ 190 public int beacon_rx; 191 192 /** RSSI of management frames */ 193 public int rssi_mgmt; 194 195 /* Packet counters and contention time stats */ 196 197 /** WME Best Effort Access Category received mpdu */ 198 public long rxmpdu_be; 199 /** WME Best Effort Access Category transmitted mpdu */ 200 public long txmpdu_be; 201 /** WME Best Effort Access Category lost mpdu */ 202 public long lostmpdu_be; 203 /** WME Best Effort Access Category number of transmission retries */ 204 public long retries_be; 205 /** WME Best Effort Access Category data packet min contention time in microseconds */ 206 public long contentionTimeMinBeInUsec; 207 /** WME Best Effort Access Category data packet max contention time in microseconds */ 208 public long contentionTimeMaxBeInUsec; 209 /** WME Best Effort Access Category data packet average contention time in microseconds */ 210 public long contentionTimeAvgBeInUsec; 211 /** 212 * WME Best Effort Access Category number of data packets used for deriving the min, the max, 213 * and the average contention time 214 */ 215 public long contentionNumSamplesBe; 216 217 /** WME Background Access Category received mpdu */ 218 public long rxmpdu_bk; 219 /** WME Background Access Category transmitted mpdu */ 220 public long txmpdu_bk; 221 /** WME Background Access Category lost mpdu */ 222 public long lostmpdu_bk; 223 /** WME Background Access Category number of transmission retries */ 224 public long retries_bk; 225 /** WME Background Access Category data packet min contention time in microseconds */ 226 public long contentionTimeMinBkInUsec; 227 /** WME Background Access Category data packet max contention time in microseconds */ 228 public long contentionTimeMaxBkInUsec; 229 /** WME Background Access Category data packet average contention time in microseconds */ 230 public long contentionTimeAvgBkInUsec; 231 /** 232 * WME Background Access Category number of data packets used for deriving the min, the max, 233 * and the average contention time 234 */ 235 public long contentionNumSamplesBk; 236 237 /** WME Video Access Category received mpdu */ 238 public long rxmpdu_vi; 239 /** WME Video Access Category transmitted mpdu */ 240 public long txmpdu_vi; 241 /** WME Video Access Category lost mpdu */ 242 public long lostmpdu_vi; 243 /** WME Video Access Category number of transmission retries */ 244 public long retries_vi; 245 /** WME Video Access Category data packet min contention time in microseconds */ 246 public long contentionTimeMinViInUsec; 247 /** WME Video Access Category data packet max contention time in microseconds */ 248 public long contentionTimeMaxViInUsec; 249 /** WME Video Access Category data packet average contention time in microseconds */ 250 public long contentionTimeAvgViInUsec; 251 /** 252 * WME Video Access Category number of data packets used for deriving the min, the max, and 253 * the average contention time 254 */ 255 public long contentionNumSamplesVi; 256 257 /** WME Voice Access Category received mpdu */ 258 public long rxmpdu_vo; 259 /** WME Voice Access Category transmitted mpdu */ 260 public long txmpdu_vo; 261 /** WME Voice Access Category lost mpdu */ 262 public long lostmpdu_vo; 263 /** WME Voice Access Category number of transmission retries */ 264 public long retries_vo; 265 /** WME Voice Access Category data packet min contention time in microseconds */ 266 public long contentionTimeMinVoInUsec; 267 /** WME Voice Access Category data packet max contention time in microseconds */ 268 public long contentionTimeMaxVoInUsec; 269 /** WME Voice Access Category data packet average contention time in microseconds */ 270 public long contentionTimeAvgVoInUsec; 271 /** 272 * WME Voice Access Category number of data packets used for deriving the min, the max, and 273 * the average contention time 274 */ 275 public long contentionNumSamplesVo; 276 277 /** 278 * Cumulative milliseconds when radio is awake 279 */ 280 public int on_time; 281 /** 282 * Cumulative milliseconds of active transmission 283 */ 284 public int tx_time; 285 /** 286 * Cumulative milliseconds per radio transmit power level of active transmission 287 */ 288 public int[] tx_time_per_level; 289 /** 290 * Cumulative milliseconds of active receive 291 */ 292 public int rx_time; 293 /** 294 * Cumulative milliseconds when radio is awake due to scan 295 */ 296 public int on_time_scan; 297 /** 298 * Cumulative milliseconds when radio is awake due to nan scan 299 */ 300 public int on_time_nan_scan; 301 /** 302 * Cumulative milliseconds when radio is awake due to background scan 303 */ 304 public int on_time_background_scan; 305 /** 306 * Cumulative milliseconds when radio is awake due to roam scan 307 */ 308 public int on_time_roam_scan; 309 /** 310 * Cumulative milliseconds when radio is awake due to pno scan 311 */ 312 public int on_time_pno_scan; 313 /** 314 * Cumulative milliseconds when radio is awake due to hotspot 2.0 scan amd GAS exchange 315 */ 316 public int on_time_hs20_scan; 317 318 /** 319 * channel stats 320 */ 321 public static class ChannelStats { 322 /** 323 * Channel frequency in MHz; 324 */ 325 public int frequency; 326 /** 327 * Center frequency in MHz for first segment 328 */ 329 public int frequencyFirstSegment; 330 /** 331 * Center frequency in MHz for second segment 332 */ 333 public int frequencySecondSegment; 334 /** 335 * Channel Width as {@link WifiChannelBandwidth} 336 */ 337 public @WifiChannelBandwidth int channelWidth; 338 /** 339 * Cumulative milliseconds radio is awake on this channel 340 */ 341 public int radioOnTimeMs; 342 /** 343 * Cumulative milliseconds CCA is held busy on this channel 344 */ 345 public int ccaBusyTimeMs; 346 } 347 348 /** 349 * Channel stats list 350 */ 351 public final SparseArray<ChannelStats> channelStatsMap = new SparseArray<>(); 352 353 /** 354 * numRadios - Number of radios used for coalescing above radio stats. 355 */ 356 public int numRadios; 357 358 /** 359 * TimeStamp - absolute milliseconds from boot when these stats were sampled. 360 */ 361 public long timeStampInMs; 362 363 /** 364 * Duty cycle of the iface. 365 * if this iface is being served using time slicing on a radio with one or more ifaces 366 * (i.e MCC), then the duty cycle assigned to this iface in %. 367 * If not using time slicing (i.e SCC or DBS), set to 100. 368 */ 369 public short timeSliceDutyCycleInPercent = -1; 370 371 /** 372 * Per rate information and statistics. 373 */ 374 public static class RateStat { 375 /** 376 * Preamble information. 0: OFDM, 1:CCK, 2:HT 3:VHT 4:HE 5..7 reserved. 377 */ 378 public int preamble; 379 /** 380 * Number of spatial streams. 0:1x1, 1:2x2, 3:3x3, 4:4x4. 381 */ 382 public int nss; 383 /** 384 * Bandwidth information. 0:20MHz, 1:40Mhz, 2:80Mhz, 3:160Mhz. 385 */ 386 public int bw; 387 /** 388 * MCS index. OFDM/CCK rate code would be as per IEEE std in the units of 0.5Mbps. 389 * HT/VHT/HE: it would be MCS index. 390 */ 391 public int rateMcsIdx; 392 /** 393 * Bitrate in units of 100 Kbps. 394 */ 395 public int bitRateInKbps; 396 /** 397 * Number of successfully transmitted data packets (ACK received). 398 */ 399 public int txMpdu; 400 /** 401 * Number of received data packets. 402 */ 403 public int rxMpdu; 404 /** 405 * Number of data packet losses (no ACK). 406 */ 407 public int mpduLost; 408 /** 409 * Number of data packet retries. 410 */ 411 public int retries; 412 } 413 414 /** 415 * Per peer statistics. 416 */ 417 public static class PeerInfo { 418 /** 419 * Station count. 420 */ 421 public short staCount; 422 /** 423 * Channel utilization. 424 */ 425 public short chanUtil; 426 /** 427 * Per rate statistics. 428 */ 429 public RateStat[] rateStats; 430 } 431 432 /** 433 * Peer statistics. 434 */ 435 public PeerInfo[] peerInfo; 436 437 /** 438 * Radio stats 439 */ 440 public static class RadioStat { 441 /** 442 * Radio identifier 443 */ 444 public int radio_id; 445 /** 446 * Cumulative milliseconds when radio is awake from the last radio chip reset 447 */ 448 public int on_time; 449 /** 450 * Cumulative milliseconds of active transmission from the last radio chip reset 451 */ 452 public int tx_time; 453 /** 454 * Cumulative milliseconds of active receive from the last radio chip reset 455 */ 456 public int rx_time; 457 /** 458 * Cumulative milliseconds when radio is awake due to scan from the last radio chip reset 459 */ 460 public int on_time_scan; 461 /** 462 * Cumulative milliseconds when radio is awake due to nan scan from the last radio chip 463 * reset 464 */ 465 public int on_time_nan_scan; 466 /** 467 * Cumulative milliseconds when radio is awake due to background scan from the last radio 468 * chip reset 469 */ 470 public int on_time_background_scan; 471 /** 472 * Cumulative milliseconds when radio is awake due to roam scan from the last radio chip 473 * reset 474 */ 475 public int on_time_roam_scan; 476 /** 477 * Cumulative milliseconds when radio is awake due to pno scan from the last radio chip 478 * reset 479 */ 480 public int on_time_pno_scan; 481 /** 482 * Cumulative milliseconds when radio is awake due to hotspot 2.0 scan amd GAS exchange 483 * from the last radio chip reset 484 */ 485 public int on_time_hs20_scan; 486 /** 487 * Channel stats list 488 */ 489 public final SparseArray<ChannelStats> channelStatsMap = new SparseArray<>(); 490 /** 491 * Time for which the radio is in active tranmission per tx level 492 */ 493 public int[] tx_time_in_ms_per_level; 494 } 495 496 /** 497 * Radio stats of all the radios. 498 */ 499 public RadioStat[] radioStats; 500 501 public @WifiManager.MloMode int wifiMloMode; 502 503 @Override toString()504 public String toString() { 505 StringBuilder sbuf = new StringBuilder(); 506 sbuf.append(" WifiLinkLayerStats: ").append('\n'); 507 508 sbuf.append(" version of StaLinkLayerStats: ").append(version).append('\n'); 509 sbuf.append(" my bss beacon rx: ").append(Integer.toString(this.beacon_rx)).append('\n'); 510 sbuf.append(" RSSI mgmt: ").append(Integer.toString(this.rssi_mgmt)).append('\n'); 511 sbuf.append(" BE : ").append(" rx=").append(Long.toString(this.rxmpdu_be)) 512 .append(" tx=").append(Long.toString(this.txmpdu_be)) 513 .append(" lost=").append(Long.toString(this.lostmpdu_be)) 514 .append(" retries=").append(Long.toString(this.retries_be)).append('\n') 515 .append(" contention_time_min") 516 .append(Long.toString(this.contentionTimeMinBeInUsec)) 517 .append(" contention_time_max") 518 .append(Long.toString(this.contentionTimeMaxBeInUsec)).append('\n') 519 .append(" contention_time_avg") 520 .append(Long.toString(this.contentionTimeAvgBeInUsec)) 521 .append(" contention_num_samples") 522 .append(Long.toString(this.contentionNumSamplesBe)).append('\n'); 523 sbuf.append(" BK : ").append(" rx=").append(Long.toString(this.rxmpdu_bk)) 524 .append(" tx=").append(Long.toString(this.txmpdu_bk)) 525 .append(" lost=").append(Long.toString(this.lostmpdu_bk)) 526 .append(" retries=").append(Long.toString(this.retries_bk)).append('\n') 527 .append(" contention_time_min") 528 .append(Long.toString(this.contentionTimeMinBkInUsec)) 529 .append(" contention_time_max") 530 .append(Long.toString(this.contentionTimeMaxBkInUsec)).append('\n') 531 .append(" contention_time_avg") 532 .append(Long.toString(this.contentionTimeAvgBkInUsec)) 533 .append(" contention_num_samples") 534 .append(Long.toString(this.contentionNumSamplesBk)).append('\n'); 535 sbuf.append(" VI : ").append(" rx=").append(Long.toString(this.rxmpdu_vi)) 536 .append(" tx=").append(Long.toString(this.txmpdu_vi)) 537 .append(" lost=").append(Long.toString(this.lostmpdu_vi)) 538 .append(" retries=").append(Long.toString(this.retries_vi)).append('\n') 539 .append(" contention_time_min") 540 .append(Long.toString(this.contentionTimeMinViInUsec)) 541 .append(" contention_time_max") 542 .append(Long.toString(this.contentionTimeMaxViInUsec)).append('\n') 543 .append(" contention_time_avg") 544 .append(Long.toString(this.contentionTimeAvgViInUsec)) 545 .append(" contention_num_samples") 546 .append(Long.toString(this.contentionNumSamplesVi)).append('\n'); 547 sbuf.append(" VO : ").append(" rx=").append(Long.toString(this.rxmpdu_vo)) 548 .append(" tx=").append(Long.toString(this.txmpdu_vo)) 549 .append(" lost=").append(Long.toString(this.lostmpdu_vo)) 550 .append(" retries=").append(Long.toString(this.retries_vo)).append('\n') 551 .append(" contention_time_min") 552 .append(Long.toString(this.contentionTimeMinVoInUsec)) 553 .append(" contention_time_max") 554 .append(Long.toString(this.contentionTimeMaxVoInUsec)).append('\n') 555 .append(" contention_time_avg") 556 .append(Long.toString(this.contentionTimeAvgVoInUsec)) 557 .append(" contention_num_samples") 558 .append(Long.toString(this.contentionNumSamplesVo)).append('\n'); 559 if (this.links != null) { 560 sbuf.append("Per link stats: Number of links = ").append(this.links.length).append( 561 "\n"); 562 for (WifiLinkLayerStats.LinkSpecificStats link : this.links) { 563 sbuf.append(" link id: ").append(link.link_id).append("\n"); 564 sbuf.append(" bss beacon rx: ").append(Integer.toString(link.beacon_rx)).append( 565 '\n'); 566 sbuf.append(" RSSI mgmt: ").append(Integer.toString(link.rssi_mgmt)).append('\n'); 567 sbuf.append(" BE : ").append(" rx=").append(Long.toString(link.rxmpdu_be)) 568 .append(" tx=").append(Long.toString(link.txmpdu_be)) 569 .append(" lost=").append(Long.toString(link.lostmpdu_be)) 570 .append(" retries=").append(Long.toString(link.retries_be)).append('\n') 571 .append(" contention_time_min") 572 .append(Long.toString(link.contentionTimeMinBeInUsec)) 573 .append(" contention_time_max") 574 .append(Long.toString(link.contentionTimeMaxBeInUsec)).append('\n') 575 .append(" contention_time_avg") 576 .append(Long.toString(link.contentionTimeAvgBeInUsec)) 577 .append(" contention_num_samples") 578 .append(Long.toString(link.contentionNumSamplesBe)).append('\n'); 579 sbuf.append(" BK : ").append(" rx=").append(Long.toString(link.rxmpdu_bk)) 580 .append(" tx=").append(Long.toString(link.txmpdu_bk)) 581 .append(" lost=").append(Long.toString(link.lostmpdu_bk)) 582 .append(" retries=").append(Long.toString(link.retries_bk)).append('\n') 583 .append(" contention_time_min") 584 .append(Long.toString(link.contentionTimeMinBkInUsec)) 585 .append(" contention_time_max") 586 .append(Long.toString(link.contentionTimeMaxBkInUsec)).append('\n') 587 .append(" contention_time_avg") 588 .append(Long.toString(link.contentionTimeAvgBkInUsec)) 589 .append(" contention_num_samples") 590 .append(Long.toString(link.contentionNumSamplesBk)).append('\n'); 591 sbuf.append(" VI : ").append(" rx=").append(Long.toString(link.rxmpdu_vi)) 592 .append(" tx=").append(Long.toString(link.txmpdu_vi)) 593 .append(" lost=").append(Long.toString(link.lostmpdu_vi)) 594 .append(" retries=").append(Long.toString(link.retries_vi)).append('\n') 595 .append(" contention_time_min") 596 .append(Long.toString(link.contentionTimeMinViInUsec)) 597 .append(" contention_time_max") 598 .append(Long.toString(link.contentionTimeMaxViInUsec)).append('\n') 599 .append(" contention_time_avg") 600 .append(Long.toString(link.contentionTimeAvgViInUsec)) 601 .append(" contention_num_samples") 602 .append(Long.toString(link.contentionNumSamplesVi)).append('\n'); 603 sbuf.append(" VO : ").append(" rx=").append(Long.toString(link.rxmpdu_vo)) 604 .append(" tx=").append(Long.toString(link.txmpdu_vo)) 605 .append(" lost=").append(Long.toString(link.lostmpdu_vo)) 606 .append(" retries=").append(Long.toString(link.retries_vo)).append('\n') 607 .append(" contention_time_min") 608 .append(Long.toString(link.contentionTimeMinVoInUsec)) 609 .append(" contention_time_max") 610 .append(Long.toString(link.contentionTimeMaxVoInUsec)).append('\n') 611 .append(" contention_time_avg") 612 .append(Long.toString(link.contentionTimeAvgVoInUsec)) 613 .append(" contention_num_samples") 614 .append(Long.toString(link.contentionNumSamplesVo)).append('\n'); 615 sbuf.append(" Duty cycle of the link=").append( 616 Short.toString(timeSliceDutyCycleInPercent)).append("\n"); 617 if (link.peerInfo != null) { 618 sbuf.append(" Number of peers=").append(link.peerInfo.length).append('\n'); 619 for (PeerInfo peer : link.peerInfo) { 620 sbuf.append(" staCount=").append(peer.staCount) 621 .append(" chanUtil=").append(peer.chanUtil).append('\n'); 622 if (peer.rateStats != null) { 623 for (RateStat rateStat : peer.rateStats) { 624 sbuf.append(" preamble=").append(rateStat.preamble) 625 .append(" nss=").append(rateStat.nss) 626 .append(" bw=").append(rateStat.bw) 627 .append(" rateMcsIdx=").append(rateStat.rateMcsIdx) 628 .append(" bitRateInKbps=").append( 629 rateStat.bitRateInKbps).append( 630 '\n') 631 .append(" txMpdu=").append(rateStat.txMpdu) 632 .append(" rxMpdu=").append(rateStat.rxMpdu) 633 .append(" mpduLost=").append(rateStat.mpduLost) 634 .append(" retries=").append(rateStat.retries).append('\n'); 635 } 636 } 637 } 638 } 639 } 640 } 641 642 sbuf.append(" numRadios=" + numRadios) 643 .append(" on_time= ").append(Integer.toString(this.on_time)) 644 .append(" tx_time=").append(Integer.toString(this.tx_time)) 645 .append(" rx_time=").append(Integer.toString(this.rx_time)) 646 .append(" scan_time=").append(Integer.toString(this.on_time_scan)).append('\n') 647 .append(" nan_scan_time=") 648 .append(Integer.toString(this.on_time_nan_scan)).append('\n') 649 .append(" g_scan_time=") 650 .append(Integer.toString(this.on_time_background_scan)).append('\n') 651 .append(" roam_scan_time=") 652 .append(Integer.toString(this.on_time_roam_scan)).append('\n') 653 .append(" pno_scan_time=") 654 .append(Integer.toString(this.on_time_pno_scan)).append('\n') 655 .append(" hs2.0_scan_time=") 656 .append(Integer.toString(this.on_time_hs20_scan)).append('\n') 657 .append(" tx_time_per_level=" + Arrays.toString(tx_time_per_level)).append('\n'); 658 int numChanStats = this.channelStatsMap.size(); 659 sbuf.append(" Number of channel stats=").append(numChanStats).append('\n'); 660 for (int i = 0; i < numChanStats; ++i) { 661 ChannelStats channelStatsEntry = this.channelStatsMap.valueAt(i); 662 sbuf.append(" Frequency=").append(channelStatsEntry.frequency) 663 .append(" radioOnTimeMs=").append(channelStatsEntry.radioOnTimeMs) 664 .append(" ccaBusyTimeMs=").append(channelStatsEntry.ccaBusyTimeMs).append('\n'); 665 } 666 int numRadios = this.radioStats == null ? 0 : this.radioStats.length; 667 sbuf.append(" Individual radio stats: numRadios=").append(numRadios).append('\n'); 668 for (int i = 0; i < numRadios; i++) { 669 RadioStat radio = this.radioStats[i]; 670 sbuf.append(" radio_id=" + radio.radio_id) 671 .append(" on_time=").append(Integer.toString(radio.on_time)) 672 .append(" tx_time=").append(Integer.toString(radio.tx_time)) 673 .append(" rx_time=").append(Integer.toString(radio.rx_time)) 674 .append(" scan_time=").append(Integer.toString(radio.on_time_scan)).append('\n') 675 .append(" nan_scan_time=") 676 .append(Integer.toString(radio.on_time_nan_scan)).append('\n') 677 .append(" g_scan_time=") 678 .append(Integer.toString(radio.on_time_background_scan)).append('\n') 679 .append(" roam_scan_time=") 680 .append(Integer.toString(radio.on_time_roam_scan)).append('\n') 681 .append(" pno_scan_time=") 682 .append(Integer.toString(radio.on_time_pno_scan)).append('\n') 683 .append(" hs2.0_scan_time=") 684 .append(Integer.toString(radio.on_time_hs20_scan)).append('\n'); 685 int numRadioChanStats = radio.channelStatsMap.size(); 686 sbuf.append(" Number of channel stats=").append(numRadioChanStats).append('\n'); 687 for (int j = 0; j < numRadioChanStats; ++j) { 688 ChannelStats channelStatsEntry = radio.channelStatsMap.valueAt(j); 689 sbuf.append(" Frequency=").append(channelStatsEntry.frequency) 690 .append(" radioOnTimeMs=").append(channelStatsEntry.radioOnTimeMs) 691 .append(" ccaBusyTimeMs=").append(channelStatsEntry.ccaBusyTimeMs) 692 .append('\n'); 693 } 694 } 695 sbuf.append(" ts=" + timeStampInMs); 696 int numPeers = this.peerInfo == null ? 0 : this.peerInfo.length; 697 sbuf.append(" Number of peers=").append(numPeers).append('\n'); 698 for (int i = 0; i < numPeers; i++) { 699 PeerInfo peer = this.peerInfo[i]; 700 sbuf.append(" staCount=").append(peer.staCount) 701 .append(" chanUtil=").append(peer.chanUtil).append('\n'); 702 int numRateStats = peer.rateStats == null ? 0 : peer.rateStats.length; 703 for (int j = 0; j < numRateStats; j++) { 704 RateStat rateStat = peer.rateStats[j]; 705 sbuf.append(" preamble=").append(rateStat.preamble) 706 .append(" nss=").append(rateStat.nss) 707 .append(" bw=").append(rateStat.bw) 708 .append(" rateMcsIdx=").append(rateStat.rateMcsIdx) 709 .append(" bitRateInKbps=").append(rateStat.bitRateInKbps).append('\n') 710 .append(" txMpdu=").append(rateStat.txMpdu) 711 .append(" rxMpdu=").append(rateStat.rxMpdu) 712 .append(" mpduLost=").append(rateStat.mpduLost) 713 .append(" retries=").append(rateStat.retries).append('\n'); 714 } 715 } 716 return sbuf.toString(); 717 } 718 719 /** 720 * Returns the link which has the best (=max) RSSI. 721 * 722 * @return link index. 723 */ getBestLinkIndex()724 private int getBestLinkIndex() { 725 int best = 0; 726 for (int i = 1; i < links.length; ++i) { 727 if (links[i].rssi_mgmt > links[best].rssi_mgmt) { 728 best = i; 729 } 730 } 731 return best; 732 } 733 clearAggregatedPacketStats()734 private void clearAggregatedPacketStats() { 735 rxmpdu_be = 0; 736 txmpdu_be = 0; 737 lostmpdu_be = 0; 738 retries_be = 0; 739 740 rxmpdu_bk = 0; 741 txmpdu_bk = 0; 742 lostmpdu_bk = 0; 743 retries_bk = 0; 744 745 rxmpdu_vi = 0; 746 txmpdu_vi = 0; 747 lostmpdu_vi = 0; 748 retries_vi = 0; 749 750 rxmpdu_vo = 0; 751 txmpdu_vo = 0; 752 lostmpdu_vo = 0; 753 retries_vo = 0; 754 } 755 756 /** 757 * Add packet stats for all links. 758 */ aggregatePacketStats()759 private void aggregatePacketStats() { 760 clearAggregatedPacketStats(); 761 for (LinkSpecificStats link : links) { 762 rxmpdu_be += link.rxmpdu_be; 763 txmpdu_be += link.txmpdu_be; 764 lostmpdu_be += link.lostmpdu_be; 765 retries_be += link.retries_be; 766 767 rxmpdu_bk += link.rxmpdu_bk; 768 txmpdu_bk += link.txmpdu_bk; 769 lostmpdu_bk += link.lostmpdu_bk; 770 retries_bk += link.retries_bk; 771 772 rxmpdu_vi += link.rxmpdu_vi; 773 txmpdu_vi += link.txmpdu_vi; 774 lostmpdu_vi += link.lostmpdu_vi; 775 retries_vi += link.retries_vi; 776 777 rxmpdu_vo += link.rxmpdu_vo; 778 txmpdu_vo += link.txmpdu_vo; 779 lostmpdu_vo += link.lostmpdu_vo; 780 retries_vo += link.retries_vo; 781 } 782 } 783 784 /** 785 * Squash all link peer stats to a single list. 786 */ aggregatePeerStats()787 private void aggregatePeerStats() { 788 if (links == null) { 789 return; 790 } 791 int numOfPeers = 0; 792 for (LinkSpecificStats link : links) { 793 if (link.peerInfo != null) { 794 numOfPeers += link.peerInfo.length; 795 } 796 } 797 if (numOfPeers == 0) { 798 return; 799 } 800 peerInfo = new PeerInfo[numOfPeers]; 801 for (LinkSpecificStats link : links) { 802 if (link.peerInfo == null) continue; 803 int i = 0; 804 for (PeerInfo peer : link.peerInfo) { 805 peerInfo[i] = new PeerInfo(); 806 peerInfo[i].staCount = peer.staCount; 807 peerInfo[i].chanUtil = peer.chanUtil; 808 if (peer.rateStats == null) continue; 809 peerInfo[i].rateStats = new RateStat[peer.rateStats.length]; 810 int j = 0; 811 for (RateStat rateStat : peer.rateStats) { 812 peerInfo[i].rateStats[j] = new RateStat(); 813 peerInfo[i].rateStats[j].preamble = rateStat.preamble; 814 peerInfo[i].rateStats[j].nss = rateStat.nss; 815 peerInfo[i].rateStats[j].bw = rateStat.bw; 816 peerInfo[i].rateStats[j].rateMcsIdx = rateStat.rateMcsIdx; 817 peerInfo[i].rateStats[j].bitRateInKbps = rateStat.bitRateInKbps; 818 peerInfo[i].rateStats[j].txMpdu = rateStat.txMpdu; 819 peerInfo[i].rateStats[j].rxMpdu = rateStat.rxMpdu; 820 peerInfo[i].rateStats[j].mpduLost = rateStat.mpduLost; 821 peerInfo[i].rateStats[j].retries = rateStat.retries; 822 j++; 823 } 824 i++; 825 } 826 } 827 } 828 829 /** 830 * Aggregate link layer stats per link. The logic for aggregation is different for each of the 831 * stats. 832 * - Best link is selected based on rssi. 833 * - Use best link for rssi, beacon_rx and dutyCycle and Contention stats. 834 * - Packet related stats are added. 835 * - Squash all peer stat lists to a single list of peers. 836 */ aggregateLinkLayerStats()837 public void aggregateLinkLayerStats() { 838 if (links == null) return; 839 int i = getBestLinkIndex(); 840 rssi_mgmt = links[i].rssi_mgmt; 841 beacon_rx = links[i].beacon_rx; 842 timeSliceDutyCycleInPercent = links[i].timeSliceDutyCycleInPercent; 843 contentionTimeMinBeInUsec = links[i].contentionTimeMinBeInUsec; 844 contentionTimeMaxBeInUsec = links[i].contentionTimeMaxBeInUsec; 845 contentionTimeAvgBeInUsec = links[i].contentionTimeAvgBeInUsec; 846 contentionNumSamplesBe = links[i].contentionNumSamplesBe; 847 contentionTimeMinBkInUsec = links[i].contentionTimeMinBkInUsec; 848 contentionTimeMaxBkInUsec = links[i].contentionTimeMaxBkInUsec; 849 contentionTimeAvgBkInUsec = links[i].contentionTimeAvgBkInUsec; 850 contentionNumSamplesBk = links[i].contentionNumSamplesBk; 851 contentionTimeMinViInUsec = links[i].contentionTimeMinViInUsec; 852 contentionTimeMaxViInUsec = links[i].contentionTimeMaxViInUsec; 853 contentionTimeAvgViInUsec = links[i].contentionTimeAvgViInUsec; 854 contentionNumSamplesVi = links[i].contentionNumSamplesVi; 855 contentionTimeMinVoInUsec = links[i].contentionTimeMinVoInUsec; 856 contentionTimeMaxVoInUsec = links[i].contentionTimeMaxVoInUsec; 857 contentionTimeAvgVoInUsec = links[i].contentionTimeAvgVoInUsec; 858 contentionNumSamplesVo = links[i].contentionNumSamplesVo; 859 aggregatePacketStats(); 860 aggregatePeerStats(); 861 } 862 } 863