1 /* 2 * Copyright (C) 2019 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 android.net.wifi; 18 19 import android.annotation.IntDef; 20 import android.annotation.IntRange; 21 import android.annotation.NonNull; 22 import android.annotation.SystemApi; 23 import android.os.Parcel; 24 import android.os.Parcelable; 25 import android.telephony.Annotation.NetworkType; 26 import android.util.Log; 27 import android.util.SparseArray; 28 29 import androidx.annotation.Nullable; 30 31 import java.lang.annotation.Retention; 32 import java.lang.annotation.RetentionPolicy; 33 import java.util.Arrays; 34 import java.util.Collections; 35 import java.util.List; 36 import java.util.NoSuchElementException; 37 38 /** 39 * This class makes a subset of 40 * com.android.server.wifi.nano.WifiMetricsProto.WifiUsabilityStatsEntry parcelable. 41 * 42 * @hide 43 */ 44 @SystemApi 45 public final class WifiUsabilityStatsEntry implements Parcelable { 46 private static final String TAG = "WifiUsabilityStatsEntry"; 47 48 /** @hide */ 49 @Retention(RetentionPolicy.SOURCE) 50 @IntDef(prefix = {"LINK_STATE_"}, value = { 51 LINK_STATE_UNKNOWN, 52 LINK_STATE_NOT_IN_USE, 53 LINK_STATE_IN_USE}) 54 public @interface LinkState {} 55 56 /** Chip does not support reporting the state of the link. */ 57 public static final int LINK_STATE_UNKNOWN = 0; 58 /** 59 * Link has not been in use since last report. It is placed in power save. All management, 60 * control and data frames for the MLO connection are carried over other links. In this state 61 * the link will not listen to beacons even in DTIM period and does not perform any 62 * GTK/IGTK/BIGTK updates but remains associated. 63 */ 64 public static final int LINK_STATE_NOT_IN_USE = 1; 65 /** 66 * Link is in use. In presence of traffic, it is set to be power active. When the traffic 67 * stops, the link will go into power save mode and will listen for beacons every DTIM period. 68 */ 69 public static final int LINK_STATE_IN_USE = 2; 70 71 /** @hide */ 72 @Retention(RetentionPolicy.SOURCE) 73 @IntDef(prefix = {"PROBE_STATUS_"}, value = { 74 PROBE_STATUS_UNKNOWN, 75 PROBE_STATUS_NO_PROBE, 76 PROBE_STATUS_SUCCESS, 77 PROBE_STATUS_FAILURE}) 78 public @interface ProbeStatus {} 79 80 /** Link probe status is unknown */ 81 public static final int PROBE_STATUS_UNKNOWN = 0; 82 /** Link probe is not triggered */ 83 public static final int PROBE_STATUS_NO_PROBE = 1; 84 /** Link probe is triggered and the result is success */ 85 public static final int PROBE_STATUS_SUCCESS = 2; 86 /** Link probe is triggered and the result is failure */ 87 public static final int PROBE_STATUS_FAILURE = 3; 88 89 /** Absolute milliseconds from device boot when these stats were sampled */ 90 private final long mTimeStampMillis; 91 /** The RSSI (in dBm) at the sample time */ 92 private final int mRssi; 93 /** Link speed at the sample time in Mbps */ 94 private final int mLinkSpeedMbps; 95 /** The total number of tx success counted from the last radio chip reset */ 96 private final long mTotalTxSuccess; 97 /** The total number of MPDU data packet retries counted from the last radio chip reset */ 98 private final long mTotalTxRetries; 99 /** The total number of tx bad counted from the last radio chip reset */ 100 private final long mTotalTxBad; 101 /** The total number of rx success counted from the last radio chip reset */ 102 private final long mTotalRxSuccess; 103 /** The total time the wifi radio is on in ms counted from the last radio chip reset */ 104 private final long mTotalRadioOnTimeMillis; 105 /** The total time the wifi radio is doing tx in ms counted from the last radio chip reset */ 106 private final long mTotalRadioTxTimeMillis; 107 /** The total time the wifi radio is doing rx in ms counted from the last radio chip reset */ 108 private final long mTotalRadioRxTimeMillis; 109 /** The total time spent on all types of scans in ms counted from the last radio chip reset */ 110 private final long mTotalScanTimeMillis; 111 /** The total time spent on nan scans in ms counted from the last radio chip reset */ 112 private final long mTotalNanScanTimeMillis; 113 /** The total time spent on background scans in ms counted from the last radio chip reset */ 114 private final long mTotalBackgroundScanTimeMillis; 115 /** The total time spent on roam scans in ms counted from the last radio chip reset */ 116 private final long mTotalRoamScanTimeMillis; 117 /** The total time spent on pno scans in ms counted from the last radio chip reset */ 118 private final long mTotalPnoScanTimeMillis; 119 /** The total time spent on hotspot2.0 scans and GAS exchange in ms counted from the last radio 120 * chip reset */ 121 private final long mTotalHotspot2ScanTimeMillis; 122 /** The total time CCA is on busy status on the current frequency in ms counted from the last 123 * radio chip reset */ 124 private final long mTotalCcaBusyFreqTimeMillis; 125 /** The total radio on time on the current frequency from the last radio chip reset */ 126 private final long mTotalRadioOnFreqTimeMillis; 127 /** The total number of beacons received from the last radio chip reset */ 128 private final long mTotalBeaconRx; 129 /** The status of link probe since last stats update */ 130 @ProbeStatus private final int mProbeStatusSinceLastUpdate; 131 /** The elapsed time of the most recent link probe since last stats update */ 132 private final int mProbeElapsedTimeSinceLastUpdateMillis; 133 /** The MCS rate of the most recent link probe since last stats update */ 134 private final int mProbeMcsRateSinceLastUpdate; 135 /** Rx link speed at the sample time in Mbps */ 136 private final int mRxLinkSpeedMbps; 137 /** @see #getTimeSliceDutyCycleInPercent() */ 138 private final int mTimeSliceDutyCycleInPercent; 139 140 /** {@hide} */ 141 @Retention(RetentionPolicy.SOURCE) 142 @IntDef(prefix = {"WME_ACCESS_CATEGORY_"}, value = { 143 WME_ACCESS_CATEGORY_BE, 144 WME_ACCESS_CATEGORY_BK, 145 WME_ACCESS_CATEGORY_VI, 146 WME_ACCESS_CATEGORY_VO}) 147 public @interface WmeAccessCategory {} 148 149 /** 150 * Wireless Multimedia Extensions (WME) Best Effort Access Category, IEEE Std 802.11-2020, 151 * Section 9.4.2.28, Table 9-155 152 */ 153 public static final int WME_ACCESS_CATEGORY_BE = 0; 154 /** 155 * Wireless Multimedia Extensions (WME) Background Access Category, IEEE Std 802.11-2020, 156 * Section 9.4.2.28, Table 9-155 157 */ 158 public static final int WME_ACCESS_CATEGORY_BK = 1; 159 /** 160 * Wireless Multimedia Extensions (WME) Video Access Category, IEEE Std 802.11-2020, 161 * Section 9.4.2.28, Table 9-155 162 */ 163 public static final int WME_ACCESS_CATEGORY_VI = 2; 164 /** 165 * Wireless Multimedia Extensions (WME) Voice Access Category, IEEE Std 802.11-2020, 166 * Section 9.4.2.28, Table 9-155 167 */ 168 public static final int WME_ACCESS_CATEGORY_VO = 3; 169 /** Number of WME Access Categories */ 170 public static final int NUM_WME_ACCESS_CATEGORIES = 4; 171 172 /** 173 * Data packet contention time statistics. 174 */ 175 public static final class ContentionTimeStats implements Parcelable { 176 private long mContentionTimeMinMicros; 177 private long mContentionTimeMaxMicros; 178 private long mContentionTimeAvgMicros; 179 private long mContentionNumSamples; 180 181 /** @hide */ ContentionTimeStats()182 public ContentionTimeStats() { 183 } 184 185 /** 186 * Constructor function 187 * @param timeMin The minimum data packet contention time 188 * @param timeMax The maximum data packet contention time 189 * @param timeAvg The average data packet contention time 190 * @param numSamples The number of samples used to get the reported contention time 191 */ ContentionTimeStats(long timeMin, long timeMax, long timeAvg, long numSamples)192 public ContentionTimeStats(long timeMin, long timeMax, long timeAvg, long numSamples) { 193 this.mContentionTimeMinMicros = timeMin; 194 this.mContentionTimeMaxMicros = timeMax; 195 this.mContentionTimeAvgMicros = timeAvg; 196 this.mContentionNumSamples = numSamples; 197 } 198 199 @Override describeContents()200 public int describeContents() { 201 return 0; 202 } 203 204 @Override writeToParcel(@onNull Parcel dest, int flags)205 public void writeToParcel(@NonNull Parcel dest, int flags) { 206 dest.writeLong(mContentionTimeMinMicros); 207 dest.writeLong(mContentionTimeMaxMicros); 208 dest.writeLong(mContentionTimeAvgMicros); 209 dest.writeLong(mContentionNumSamples); 210 } 211 212 /** Implement the Parcelable interface */ 213 public static final @NonNull Creator<ContentionTimeStats> CREATOR = 214 new Creator<ContentionTimeStats>() { 215 public ContentionTimeStats createFromParcel(Parcel in) { 216 ContentionTimeStats stats = new ContentionTimeStats(); 217 stats.mContentionTimeMinMicros = in.readLong(); 218 stats.mContentionTimeMaxMicros = in.readLong(); 219 stats.mContentionTimeAvgMicros = in.readLong(); 220 stats.mContentionNumSamples = in.readLong(); 221 return stats; 222 } 223 public ContentionTimeStats[] newArray(int size) { 224 return new ContentionTimeStats[size]; 225 } 226 }; 227 228 /** Data packet min contention time in microseconds */ getContentionTimeMinMicros()229 public long getContentionTimeMinMicros() { 230 return mContentionTimeMinMicros; 231 } 232 233 /** Data packet max contention time in microseconds */ getContentionTimeMaxMicros()234 public long getContentionTimeMaxMicros() { 235 return mContentionTimeMaxMicros; 236 } 237 238 /** Data packet average contention time in microseconds */ getContentionTimeAvgMicros()239 public long getContentionTimeAvgMicros() { 240 return mContentionTimeAvgMicros; 241 } 242 243 /** 244 * Number of data packets used for deriving the min, the max, and the average 245 * contention time 246 */ getContentionNumSamples()247 public long getContentionNumSamples() { 248 return mContentionNumSamples; 249 } 250 } 251 private final ContentionTimeStats[] mContentionTimeStats; 252 253 /** {@hide} */ 254 @Retention(RetentionPolicy.SOURCE) 255 @IntDef(prefix = {"WIFI_PREAMBLE_"}, value = { 256 WIFI_PREAMBLE_OFDM, 257 WIFI_PREAMBLE_CCK, 258 WIFI_PREAMBLE_HT, 259 WIFI_PREAMBLE_VHT, 260 WIFI_PREAMBLE_HE, 261 WIFI_PREAMBLE_EHT, 262 WIFI_PREAMBLE_INVALID}) 263 public @interface WifiPreambleType {} 264 265 /** Preamble type for 802.11a/g, IEEE Std 802.11-2020, Section 17 */ 266 public static final int WIFI_PREAMBLE_OFDM = 0; 267 /** Preamble type for 802.11b, IEEE Std 802.11-2020, Section 16 */ 268 public static final int WIFI_PREAMBLE_CCK = 1; 269 /** Preamble type for 802.11n, IEEE Std 802.11-2020, Section 19 */ 270 public static final int WIFI_PREAMBLE_HT = 2; 271 /** Preamble type for 802.11ac, IEEE Std 802.11-2020, Section 21 */ 272 public static final int WIFI_PREAMBLE_VHT = 3; 273 /** Preamble type for 802.11ax, IEEE Std 802.11ax-2021, Section 27 */ 274 public static final int WIFI_PREAMBLE_HE = 5; 275 /** Preamble type for 802.11be, IEEE Std 802.11be-2021, Section 36 */ 276 public static final int WIFI_PREAMBLE_EHT = 6; 277 /** Invalid */ 278 public static final int WIFI_PREAMBLE_INVALID = -1; 279 280 /** {@hide} */ 281 @Retention(RetentionPolicy.SOURCE) 282 @IntDef(prefix = {"WIFI_SPATIAL_STREAMS_"}, value = { 283 WIFI_SPATIAL_STREAMS_ONE, 284 WIFI_SPATIAL_STREAMS_TWO, 285 WIFI_SPATIAL_STREAMS_THREE, 286 WIFI_SPATIAL_STREAMS_FOUR, 287 WIFI_SPATIAL_STREAMS_INVALID}) 288 public @interface WifiSpatialStreams {} 289 290 /** Single stream, 1x1 */ 291 public static final int WIFI_SPATIAL_STREAMS_ONE = 1; 292 /** Dual streams, 2x2 */ 293 public static final int WIFI_SPATIAL_STREAMS_TWO = 2; 294 /** Three streams, 3x3 */ 295 public static final int WIFI_SPATIAL_STREAMS_THREE = 3; 296 /** Four streams, 4x4 */ 297 public static final int WIFI_SPATIAL_STREAMS_FOUR = 4; 298 /** Invalid */ 299 public static final int WIFI_SPATIAL_STREAMS_INVALID = -1; 300 301 /** {@hide} */ 302 @Retention(RetentionPolicy.SOURCE) 303 @IntDef(prefix = {"WIFI_BANDWIDTH_"}, value = { 304 WIFI_BANDWIDTH_20_MHZ, 305 WIFI_BANDWIDTH_40_MHZ, 306 WIFI_BANDWIDTH_80_MHZ, 307 WIFI_BANDWIDTH_160_MHZ, 308 WIFI_BANDWIDTH_320_MHZ, 309 WIFI_BANDWIDTH_80P80_MHZ, 310 WIFI_BANDWIDTH_5_MHZ, 311 WIFI_BANDWIDTH_10_MHZ, 312 WIFI_BANDWIDTH_INVALID}) 313 public @interface WifiChannelBandwidth {} 314 315 /** Channel bandwidth: 20MHz */ 316 public static final int WIFI_BANDWIDTH_20_MHZ = 0; 317 /** Channel bandwidth: 40MHz */ 318 public static final int WIFI_BANDWIDTH_40_MHZ = 1; 319 /** Channel bandwidth: 80MHz */ 320 public static final int WIFI_BANDWIDTH_80_MHZ = 2; 321 /** Channel bandwidth: 160MHz */ 322 public static final int WIFI_BANDWIDTH_160_MHZ = 3; 323 /** Channel bandwidth: 80MHz + 80MHz */ 324 public static final int WIFI_BANDWIDTH_80P80_MHZ = 4; 325 /** Channel bandwidth: 5MHz */ 326 public static final int WIFI_BANDWIDTH_5_MHZ = 5; 327 /** Channel bandwidth: 10MHz */ 328 public static final int WIFI_BANDWIDTH_10_MHZ = 6; 329 /** Channel bandwidth: 320MHz */ 330 public static final int WIFI_BANDWIDTH_320_MHZ = 7; 331 /** Invalid */ 332 public static final int WIFI_BANDWIDTH_INVALID = -1; 333 334 /** 335 * Rate information and statistics: packet counters (tx/rx successful packets, retries, lost) 336 * indexed by preamble, bandwidth, number of spatial streams, MCS, and bit rate. 337 */ 338 public static final class RateStats implements Parcelable { 339 @WifiPreambleType private int mPreamble; 340 @WifiSpatialStreams private int mNss; 341 @WifiChannelBandwidth private int mBw; 342 private int mRateMcsIdx; 343 private int mBitRateInKbps; 344 private int mTxMpdu; 345 private int mRxMpdu; 346 private int mMpduLost; 347 private int mRetries; 348 349 /** @hide */ RateStats()350 public RateStats() { 351 } 352 353 /** 354 * Constructor function. 355 * @param preamble Preamble information. 356 * @param nss Number of spatial streams. 357 * @param bw Bandwidth information. 358 * @param rateMcsIdx MCS index. OFDM/CCK rate code would be as per IEEE std in the units of 359 * 0.5Mbps. HT/VHT/HE/EHT: it would be MCS index. 360 * @param bitRateInKbps Bitrate in units of 100 Kbps. 361 * @param txMpdu Number of successfully transmitted data packets (ACK received). 362 * @param rxMpdu Number of received data packets. 363 * @param mpduLost Number of data packet losses (no ACK). 364 * @param retries Number of data packet retries. 365 */ RateStats(@ifiPreambleType int preamble, @WifiSpatialStreams int nss, @WifiChannelBandwidth int bw, int rateMcsIdx, int bitRateInKbps, int txMpdu, int rxMpdu, int mpduLost, int retries)366 public RateStats(@WifiPreambleType int preamble, @WifiSpatialStreams int nss, 367 @WifiChannelBandwidth int bw, int rateMcsIdx, int bitRateInKbps, int txMpdu, 368 int rxMpdu, int mpduLost, int retries) { 369 this.mPreamble = preamble; 370 this.mNss = nss; 371 this.mBw = bw; 372 this.mRateMcsIdx = rateMcsIdx; 373 this.mBitRateInKbps = bitRateInKbps; 374 this.mTxMpdu = txMpdu; 375 this.mRxMpdu = rxMpdu; 376 this.mMpduLost = mpduLost; 377 this.mRetries = retries; 378 } 379 380 @Override describeContents()381 public int describeContents() { 382 return 0; 383 } 384 385 @Override writeToParcel(@onNull Parcel dest, int flags)386 public void writeToParcel(@NonNull Parcel dest, int flags) { 387 dest.writeInt(mPreamble); 388 dest.writeInt(mNss); 389 dest.writeInt(mBw); 390 dest.writeInt(mRateMcsIdx); 391 dest.writeInt(mBitRateInKbps); 392 dest.writeInt(mTxMpdu); 393 dest.writeInt(mRxMpdu); 394 dest.writeInt(mMpduLost); 395 dest.writeInt(mRetries); 396 } 397 398 /** Implement the Parcelable interface */ 399 public static final @NonNull Creator<RateStats> CREATOR = new Creator<RateStats>() { 400 public RateStats createFromParcel(Parcel in) { 401 RateStats stats = new RateStats(); 402 stats.mPreamble = in.readInt(); 403 stats.mNss = in.readInt(); 404 stats.mBw = in.readInt(); 405 stats.mRateMcsIdx = in.readInt(); 406 stats.mBitRateInKbps = in.readInt(); 407 stats.mTxMpdu = in.readInt(); 408 stats.mRxMpdu = in.readInt(); 409 stats.mMpduLost = in.readInt(); 410 stats.mRetries = in.readInt(); 411 return stats; 412 } 413 public RateStats[] newArray(int size) { 414 return new RateStats[size]; 415 } 416 }; 417 418 /** Preamble information, see {@link WifiPreambleType} */ getPreamble()419 @WifiPreambleType public int getPreamble() { 420 return mPreamble; 421 } 422 423 /** Number of spatial streams, see {@link WifiSpatialStreams} */ getNumberOfSpatialStreams()424 @WifiSpatialStreams public int getNumberOfSpatialStreams() { 425 return mNss; 426 } 427 428 /** Bandwidth information, see {@link WifiChannelBandwidth} */ getBandwidthInMhz()429 @WifiChannelBandwidth public int getBandwidthInMhz() { 430 return mBw; 431 } 432 433 /** 434 * MCS index. OFDM/CCK rate code would be as per IEEE std in the units of 0.5Mbps. 435 * HT/VHT/HE/EHT: it would be MCS index 436 */ getRateMcsIdx()437 public int getRateMcsIdx() { 438 return mRateMcsIdx; 439 } 440 441 /** Bitrate in units of a hundred Kbps */ getBitRateInKbps()442 public int getBitRateInKbps() { 443 return mBitRateInKbps; 444 } 445 446 /** Number of successfully transmitted data packets (ACK received) */ getTxMpdu()447 public int getTxMpdu() { 448 return mTxMpdu; 449 } 450 451 /** Number of received data packets */ getRxMpdu()452 public int getRxMpdu() { 453 return mRxMpdu; 454 } 455 456 /** Number of data packet losses (no ACK) */ getMpduLost()457 public int getMpduLost() { 458 return mMpduLost; 459 } 460 461 /** Number of data packet retries */ getRetries()462 public int getRetries() { 463 return mRetries; 464 } 465 } 466 private final RateStats[] mRateStats; 467 468 /** 469 * Wifi link layer radio stats. 470 */ 471 public static final class RadioStats implements Parcelable { 472 /** 473 * Invalid radio id. 474 * @hide 475 */ 476 public static final int INVALID_RADIO_ID = -1; 477 private int mRadioId; 478 private long mTotalRadioOnTimeMillis; 479 private long mTotalRadioTxTimeMillis; 480 private long mTotalRadioRxTimeMillis; 481 private long mTotalScanTimeMillis; 482 private long mTotalNanScanTimeMillis; 483 private long mTotalBackgroundScanTimeMillis; 484 private long mTotalRoamScanTimeMillis; 485 private long mTotalPnoScanTimeMillis; 486 private long mTotalHotspot2ScanTimeMillis; 487 488 /** @hide */ RadioStats()489 public RadioStats() { 490 } 491 492 /** 493 * Constructor function 494 * @param radioId Firmware/Hardware implementation specific persistent value for this 495 * device, identifying the radio interface for which the stats are produced. 496 * @param onTime The total time the wifi radio is on in ms counted from the last radio 497 * chip reset 498 * @param txTime The total time the wifi radio is transmitting in ms counted from the last 499 * radio chip reset 500 * @param rxTime The total time the wifi radio is receiving in ms counted from the last 501 * radio chip reset 502 * @param onTimeScan The total time spent on all types of scans in ms counted from the 503 * last radio chip reset 504 * @param onTimeNanScan The total time spent on nan scans in ms counted from the last radio 505 * chip reset 506 * @param onTimeBackgroundScan The total time spent on background scans in ms counted from 507 * the last radio chip reset 508 * @param onTimeRoamScan The total time spent on roam scans in ms counted from the last 509 * radio chip reset 510 * @param onTimePnoScan The total time spent on pno scans in ms counted from the last radio 511 * chip reset 512 * @param onTimeHs20Scan The total time spent on hotspot2.0 scans and GAS exchange in ms 513 * counted from the last radio chip reset 514 */ RadioStats(int radioId, long onTime, long txTime, long rxTime, long onTimeScan, long onTimeNanScan, long onTimeBackgroundScan, long onTimeRoamScan, long onTimePnoScan, long onTimeHs20Scan)515 public RadioStats(int radioId, long onTime, long txTime, long rxTime, long onTimeScan, 516 long onTimeNanScan, long onTimeBackgroundScan, long onTimeRoamScan, 517 long onTimePnoScan, long onTimeHs20Scan) { 518 this.mRadioId = radioId; 519 this.mTotalRadioOnTimeMillis = onTime; 520 this.mTotalRadioTxTimeMillis = txTime; 521 this.mTotalRadioRxTimeMillis = rxTime; 522 this.mTotalScanTimeMillis = onTimeScan; 523 this.mTotalNanScanTimeMillis = onTimeNanScan; 524 this.mTotalBackgroundScanTimeMillis = onTimeBackgroundScan; 525 this.mTotalRoamScanTimeMillis = onTimeRoamScan; 526 this.mTotalPnoScanTimeMillis = onTimePnoScan; 527 this.mTotalHotspot2ScanTimeMillis = onTimeHs20Scan; 528 } 529 530 @Override describeContents()531 public int describeContents() { 532 return 0; 533 } 534 535 @Override writeToParcel(@onNull Parcel dest, int flags)536 public void writeToParcel(@NonNull Parcel dest, int flags) { 537 dest.writeInt(mRadioId); 538 dest.writeLong(mTotalRadioOnTimeMillis); 539 dest.writeLong(mTotalRadioTxTimeMillis); 540 dest.writeLong(mTotalRadioRxTimeMillis); 541 dest.writeLong(mTotalScanTimeMillis); 542 dest.writeLong(mTotalNanScanTimeMillis); 543 dest.writeLong(mTotalBackgroundScanTimeMillis); 544 dest.writeLong(mTotalRoamScanTimeMillis); 545 dest.writeLong(mTotalPnoScanTimeMillis); 546 dest.writeLong(mTotalHotspot2ScanTimeMillis); 547 } 548 549 /** Implement the Parcelable interface */ 550 public static final @NonNull Creator<RadioStats> CREATOR = 551 new Creator<RadioStats>() { 552 public RadioStats createFromParcel(Parcel in) { 553 RadioStats stats = new RadioStats(); 554 stats.mRadioId = in.readInt(); 555 stats.mTotalRadioOnTimeMillis = in.readLong(); 556 stats.mTotalRadioTxTimeMillis = in.readLong(); 557 stats.mTotalRadioRxTimeMillis = in.readLong(); 558 stats.mTotalScanTimeMillis = in.readLong(); 559 stats.mTotalNanScanTimeMillis = in.readLong(); 560 stats.mTotalBackgroundScanTimeMillis = in.readLong(); 561 stats.mTotalRoamScanTimeMillis = in.readLong(); 562 stats.mTotalPnoScanTimeMillis = in.readLong(); 563 stats.mTotalHotspot2ScanTimeMillis = in.readLong(); 564 return stats; 565 } 566 public RadioStats[] newArray(int size) { 567 return new RadioStats[size]; 568 } 569 }; 570 571 /** 572 * Firmware/Hardware implementation specific persistent value for this 573 * device, identifying the radio interface for which the stats are produced. 574 */ getRadioId()575 public long getRadioId() { 576 return mRadioId; 577 } 578 579 /** The total time the wifi radio is on in ms counted from the last radio chip reset */ getTotalRadioOnTimeMillis()580 public long getTotalRadioOnTimeMillis() { 581 return mTotalRadioOnTimeMillis; 582 } 583 584 /** 585 * The total time the wifi radio is transmitting in ms counted from the last radio chip 586 * reset 587 */ getTotalRadioTxTimeMillis()588 public long getTotalRadioTxTimeMillis() { 589 return mTotalRadioTxTimeMillis; 590 } 591 592 /** 593 * The total time the wifi radio is receiving in ms counted from the last radio chip reset 594 */ getTotalRadioRxTimeMillis()595 public long getTotalRadioRxTimeMillis() { 596 return mTotalRadioRxTimeMillis; 597 } 598 599 /** 600 * The total time spent on all types of scans in ms counted from the last radio chip reset 601 */ getTotalScanTimeMillis()602 public long getTotalScanTimeMillis() { 603 return mTotalScanTimeMillis; 604 } 605 606 /** The total time spent on nan scans in ms counted from the last radio chip reset */ getTotalNanScanTimeMillis()607 public long getTotalNanScanTimeMillis() { 608 return mTotalNanScanTimeMillis; 609 } 610 611 /** The total time spent on background scans in ms counted from the last radio chip reset */ getTotalBackgroundScanTimeMillis()612 public long getTotalBackgroundScanTimeMillis() { 613 return mTotalBackgroundScanTimeMillis; 614 } 615 616 /** The total time spent on roam scans in ms counted from the last radio chip reset */ getTotalRoamScanTimeMillis()617 public long getTotalRoamScanTimeMillis() { 618 return mTotalRoamScanTimeMillis; 619 } 620 621 /** The total time spent on pno scans in ms counted from the last radio chip reset */ getTotalPnoScanTimeMillis()622 public long getTotalPnoScanTimeMillis() { 623 return mTotalPnoScanTimeMillis; 624 } 625 626 /** 627 * The total time spent on hotspot2.0 scans and GAS exchange in ms counted from the 628 * last radio chip reset 629 */ getTotalHotspot2ScanTimeMillis()630 public long getTotalHotspot2ScanTimeMillis() { 631 return mTotalHotspot2ScanTimeMillis; 632 } 633 } 634 private final RadioStats[] mRadioStats; 635 private final int mChannelUtilizationRatio; 636 private final boolean mIsThroughputSufficient; 637 private final boolean mIsWifiScoringEnabled; 638 private final boolean mIsCellularDataAvailable; 639 private final @NetworkType int mCellularDataNetworkType; 640 private final int mCellularSignalStrengthDbm; 641 private final int mCellularSignalStrengthDb; 642 private final boolean mIsSameRegisteredCell; 643 644 /** 645 * Link specific statistics. 646 * 647 * @hide 648 */ 649 public static final class LinkStats implements Parcelable { 650 /** Link identifier (0 to 14) */ 651 private final int mLinkId; 652 /** Link state as listed {@link LinkState} */ 653 private final @LinkState int mState; 654 /** Radio identifier */ 655 private final int mRadioId; 656 /** The RSSI (in dBm) at the sample time */ 657 private final int mRssi; 658 /** Tx Link speed at the sample time in Mbps */ 659 private final int mTxLinkSpeedMbps; 660 /** Rx link speed at the sample time in Mbps */ 661 private final int mRxLinkSpeedMbps; 662 /** The total number of tx success counted from the last radio chip reset */ 663 private final long mTotalTxSuccess; 664 /** The total number of MPDU data packet retries counted from the last radio chip reset */ 665 private final long mTotalTxRetries; 666 /** The total number of tx bad counted from the last radio chip reset */ 667 private final long mTotalTxBad; 668 /** The total number of rx success counted from the last radio chip reset */ 669 private final long mTotalRxSuccess; 670 /** The total number of beacons received from the last radio chip reset */ 671 private final long mTotalBeaconRx; 672 /** @see #WifiUsabilityStatsEntry#getTimeSliceDutyCycleInPercent() */ 673 private final int mTimeSliceDutyCycleInPercent; 674 /** 675 * The total time CCA is on busy status on the link frequency in ms counted from the last 676 * radio chip reset 677 */ 678 private final long mTotalCcaBusyFreqTimeMillis; 679 /** The total radio on time on the link frequency in ms from the last radio chip reset */ 680 private final long mTotalRadioOnFreqTimeMillis; 681 /** Data packet contention time statistics */ 682 private final ContentionTimeStats[] mContentionTimeStats; 683 /** Rate information and statistics */ 684 private final RateStats[] mRateStats; 685 686 /** @hide */ LinkStats()687 public LinkStats() { 688 mLinkId = MloLink.INVALID_MLO_LINK_ID; 689 mState = LINK_STATE_UNKNOWN; 690 mRssi = WifiInfo.INVALID_RSSI; 691 mRadioId = RadioStats.INVALID_RADIO_ID; 692 mTxLinkSpeedMbps = WifiInfo.LINK_SPEED_UNKNOWN; 693 mRxLinkSpeedMbps = WifiInfo.LINK_SPEED_UNKNOWN; 694 mTotalTxSuccess = 0; 695 mTotalTxRetries = 0; 696 mTotalTxBad = 0; 697 mTotalRxSuccess = 0; 698 mTotalBeaconRx = 0; 699 mTimeSliceDutyCycleInPercent = 0; 700 mTotalCcaBusyFreqTimeMillis = 0; 701 mTotalRadioOnFreqTimeMillis = 0; 702 mContentionTimeStats = null; 703 mRateStats = null; 704 } 705 706 /** @hide 707 * Constructor function 708 * 709 * @param linkId Identifier of the link. 710 * @param radioId Identifier of the radio on which the link is operating 711 * currently. 712 * @param rssi Link Rssi (in dBm) at sample time. 713 * @param txLinkSpeedMpbs Transmit link speed in Mpbs at sample time. 714 * @param rxLinkSpeedMpbs Receive link speed in Mbps at sample time. 715 * @param totalTxSuccess Total number of Tx success. 716 * @param totalTxRetries Total packet retries. 717 * @param totalTxBad Total number of bad packets. 718 * @param totalRxSuccess Total number of good receive packets. 719 * @param totalBeaconRx Total number of beacon received. 720 * @param timeSliceDutyCycleInPercent Duty cycle of the connection. 721 * @param totalCcaBusyFreqTimeMillis Total CCA is on busy status on the link frequency from 722 * the last radio chip reset. 723 * @param totalRadioOnFreqTimeMillis Total Radio on time on the link frequency from the 724 * last radio chip reset. 725 * @param contentionTimeStats Data packet contention time statistics. 726 * @param rateStats Rate information. 727 */ LinkStats(int linkId, int state, int radioId, int rssi, int txLinkSpeedMpbs, int rxLinkSpeedMpbs, long totalTxSuccess, long totalTxRetries, long totalTxBad, long totalRxSuccess, long totalBeaconRx, int timeSliceDutyCycleInPercent, long totalCcaBusyFreqTimeMillis, long totalRadioOnFreqTimeMillis, ContentionTimeStats[] contentionTimeStats, RateStats[] rateStats)728 public LinkStats(int linkId, int state, int radioId, int rssi, int txLinkSpeedMpbs, 729 int rxLinkSpeedMpbs, long totalTxSuccess, long totalTxRetries, long totalTxBad, 730 long totalRxSuccess, long totalBeaconRx, int timeSliceDutyCycleInPercent, 731 long totalCcaBusyFreqTimeMillis, long totalRadioOnFreqTimeMillis, 732 ContentionTimeStats[] contentionTimeStats, RateStats[] rateStats) { 733 this.mLinkId = linkId; 734 this.mState = state; 735 this.mRadioId = radioId; 736 this.mRssi = rssi; 737 this.mTxLinkSpeedMbps = txLinkSpeedMpbs; 738 this.mRxLinkSpeedMbps = rxLinkSpeedMpbs; 739 this.mTotalTxSuccess = totalTxSuccess; 740 this.mTotalTxRetries = totalTxRetries; 741 this.mTotalTxBad = totalTxBad; 742 this.mTotalRxSuccess = totalRxSuccess; 743 this.mTotalBeaconRx = totalBeaconRx; 744 this.mTimeSliceDutyCycleInPercent = timeSliceDutyCycleInPercent; 745 this.mTotalCcaBusyFreqTimeMillis = totalCcaBusyFreqTimeMillis; 746 this.mTotalRadioOnFreqTimeMillis = totalRadioOnFreqTimeMillis; 747 this.mContentionTimeStats = contentionTimeStats; 748 this.mRateStats = rateStats; 749 } 750 751 @Override describeContents()752 public int describeContents() { 753 return 0; 754 } 755 756 @Override writeToParcel(@onNull Parcel dest, int flags)757 public void writeToParcel(@NonNull Parcel dest, int flags) { 758 dest.writeInt(mLinkId); 759 dest.writeInt(mState); 760 dest.writeInt(mRadioId); 761 dest.writeInt(mRssi); 762 dest.writeInt(mTxLinkSpeedMbps); 763 dest.writeInt(mRxLinkSpeedMbps); 764 dest.writeLong(mTotalTxSuccess); 765 dest.writeLong(mTotalTxRetries); 766 dest.writeLong(mTotalTxBad); 767 dest.writeLong(mTotalRxSuccess); 768 dest.writeLong(mTotalBeaconRx); 769 dest.writeInt(mTimeSliceDutyCycleInPercent); 770 dest.writeLong(mTotalCcaBusyFreqTimeMillis); 771 dest.writeLong(mTotalRadioOnFreqTimeMillis); 772 dest.writeTypedArray(mContentionTimeStats, flags); 773 dest.writeTypedArray(mRateStats, flags); 774 } 775 776 /** Implement the Parcelable interface */ 777 @NonNull 778 public static final Creator<LinkStats> CREATOR = 779 new Creator<>() { 780 public LinkStats createFromParcel(Parcel in) { 781 return new LinkStats(in.readInt(), in.readInt(), in.readInt(), in.readInt(), 782 in.readInt(), in.readInt(), in.readLong(), in.readLong(), 783 in.readLong(), in.readLong(), in.readLong(), in.readInt(), 784 in.readLong(), in.readLong(), 785 in.createTypedArray(ContentionTimeStats.CREATOR), 786 in.createTypedArray(RateStats.CREATOR)); 787 } 788 789 public LinkStats[] newArray(int size) { 790 return new LinkStats[size]; 791 } 792 }; 793 } 794 795 /** Link stats per link */ 796 private final SparseArray<LinkStats> mLinkStats; 797 798 /** Constructor function {@hide} */ WifiUsabilityStatsEntry(long timeStampMillis, int rssi, int linkSpeedMbps, long totalTxSuccess, long totalTxRetries, long totalTxBad, long totalRxSuccess, long totalRadioOnTimeMillis, long totalRadioTxTimeMillis, long totalRadioRxTimeMillis, long totalScanTimeMillis, long totalNanScanTimeMillis, long totalBackgroundScanTimeMillis, long totalRoamScanTimeMillis, long totalPnoScanTimeMillis, long totalHotspot2ScanTimeMillis, long totalCcaBusyFreqTimeMillis, long totalRadioOnFreqTimeMillis, long totalBeaconRx, @ProbeStatus int probeStatusSinceLastUpdate, int probeElapsedTimeSinceLastUpdateMillis, int probeMcsRateSinceLastUpdate, int rxLinkSpeedMbps, int timeSliceDutyCycleInPercent, ContentionTimeStats[] contentionTimeStats, RateStats[] rateStats, RadioStats[] radiostats, int channelUtilizationRatio, boolean isThroughputSufficient, boolean isWifiScoringEnabled, boolean isCellularDataAvailable, @NetworkType int cellularDataNetworkType, int cellularSignalStrengthDbm, int cellularSignalStrengthDb, boolean isSameRegisteredCell, SparseArray<LinkStats> linkStats)799 public WifiUsabilityStatsEntry(long timeStampMillis, int rssi, int linkSpeedMbps, 800 long totalTxSuccess, long totalTxRetries, long totalTxBad, long totalRxSuccess, 801 long totalRadioOnTimeMillis, long totalRadioTxTimeMillis, long totalRadioRxTimeMillis, 802 long totalScanTimeMillis, long totalNanScanTimeMillis, 803 long totalBackgroundScanTimeMillis, 804 long totalRoamScanTimeMillis, long totalPnoScanTimeMillis, 805 long totalHotspot2ScanTimeMillis, 806 long totalCcaBusyFreqTimeMillis, long totalRadioOnFreqTimeMillis, long totalBeaconRx, 807 @ProbeStatus int probeStatusSinceLastUpdate, int probeElapsedTimeSinceLastUpdateMillis, 808 int probeMcsRateSinceLastUpdate, int rxLinkSpeedMbps, 809 int timeSliceDutyCycleInPercent, ContentionTimeStats[] contentionTimeStats, 810 RateStats[] rateStats, RadioStats[] radiostats, int channelUtilizationRatio, 811 boolean isThroughputSufficient, boolean isWifiScoringEnabled, 812 boolean isCellularDataAvailable, @NetworkType int cellularDataNetworkType, 813 int cellularSignalStrengthDbm, int cellularSignalStrengthDb, 814 boolean isSameRegisteredCell, SparseArray<LinkStats> linkStats) { 815 mTimeStampMillis = timeStampMillis; 816 mRssi = rssi; 817 mLinkSpeedMbps = linkSpeedMbps; 818 mTotalTxSuccess = totalTxSuccess; 819 mTotalTxRetries = totalTxRetries; 820 mTotalTxBad = totalTxBad; 821 mTotalRxSuccess = totalRxSuccess; 822 mTotalRadioOnTimeMillis = totalRadioOnTimeMillis; 823 mTotalRadioTxTimeMillis = totalRadioTxTimeMillis; 824 mTotalRadioRxTimeMillis = totalRadioRxTimeMillis; 825 mTotalScanTimeMillis = totalScanTimeMillis; 826 mTotalNanScanTimeMillis = totalNanScanTimeMillis; 827 mTotalBackgroundScanTimeMillis = totalBackgroundScanTimeMillis; 828 mTotalRoamScanTimeMillis = totalRoamScanTimeMillis; 829 mTotalPnoScanTimeMillis = totalPnoScanTimeMillis; 830 mTotalHotspot2ScanTimeMillis = totalHotspot2ScanTimeMillis; 831 mTotalCcaBusyFreqTimeMillis = totalCcaBusyFreqTimeMillis; 832 mTotalRadioOnFreqTimeMillis = totalRadioOnFreqTimeMillis; 833 mTotalBeaconRx = totalBeaconRx; 834 mProbeStatusSinceLastUpdate = probeStatusSinceLastUpdate; 835 mProbeElapsedTimeSinceLastUpdateMillis = probeElapsedTimeSinceLastUpdateMillis; 836 mProbeMcsRateSinceLastUpdate = probeMcsRateSinceLastUpdate; 837 mRxLinkSpeedMbps = rxLinkSpeedMbps; 838 mTimeSliceDutyCycleInPercent = timeSliceDutyCycleInPercent; 839 mContentionTimeStats = contentionTimeStats; 840 mRateStats = rateStats; 841 mRadioStats = radiostats; 842 mChannelUtilizationRatio = channelUtilizationRatio; 843 mIsThroughputSufficient = isThroughputSufficient; 844 mIsWifiScoringEnabled = isWifiScoringEnabled; 845 mIsCellularDataAvailable = isCellularDataAvailable; 846 mCellularDataNetworkType = cellularDataNetworkType; 847 mCellularSignalStrengthDbm = cellularSignalStrengthDbm; 848 mCellularSignalStrengthDb = cellularSignalStrengthDb; 849 mIsSameRegisteredCell = isSameRegisteredCell; 850 mLinkStats = linkStats; 851 } 852 853 /** Implement the Parcelable interface */ describeContents()854 public int describeContents() { 855 return 0; 856 } 857 858 /** Implement the Parcelable interface */ writeToParcel(Parcel dest, int flags)859 public void writeToParcel(Parcel dest, int flags) { 860 dest.writeLong(mTimeStampMillis); 861 dest.writeInt(mRssi); 862 dest.writeInt(mLinkSpeedMbps); 863 dest.writeLong(mTotalTxSuccess); 864 dest.writeLong(mTotalTxRetries); 865 dest.writeLong(mTotalTxBad); 866 dest.writeLong(mTotalRxSuccess); 867 dest.writeLong(mTotalRadioOnTimeMillis); 868 dest.writeLong(mTotalRadioTxTimeMillis); 869 dest.writeLong(mTotalRadioRxTimeMillis); 870 dest.writeLong(mTotalScanTimeMillis); 871 dest.writeLong(mTotalNanScanTimeMillis); 872 dest.writeLong(mTotalBackgroundScanTimeMillis); 873 dest.writeLong(mTotalRoamScanTimeMillis); 874 dest.writeLong(mTotalPnoScanTimeMillis); 875 dest.writeLong(mTotalHotspot2ScanTimeMillis); 876 dest.writeLong(mTotalCcaBusyFreqTimeMillis); 877 dest.writeLong(mTotalRadioOnFreqTimeMillis); 878 dest.writeLong(mTotalBeaconRx); 879 dest.writeInt(mProbeStatusSinceLastUpdate); 880 dest.writeInt(mProbeElapsedTimeSinceLastUpdateMillis); 881 dest.writeInt(mProbeMcsRateSinceLastUpdate); 882 dest.writeInt(mRxLinkSpeedMbps); 883 dest.writeInt(mTimeSliceDutyCycleInPercent); 884 dest.writeTypedArray(mContentionTimeStats, flags); 885 dest.writeTypedArray(mRateStats, flags); 886 dest.writeTypedArray(mRadioStats, flags); 887 dest.writeInt(mChannelUtilizationRatio); 888 dest.writeBoolean(mIsThroughputSufficient); 889 dest.writeBoolean(mIsWifiScoringEnabled); 890 dest.writeBoolean(mIsCellularDataAvailable); 891 dest.writeInt(mCellularDataNetworkType); 892 dest.writeInt(mCellularSignalStrengthDbm); 893 dest.writeInt(mCellularSignalStrengthDb); 894 dest.writeBoolean(mIsSameRegisteredCell); 895 dest.writeSparseArray(mLinkStats); 896 } 897 898 /** Implement the Parcelable interface */ 899 public static final @android.annotation.NonNull Creator<WifiUsabilityStatsEntry> CREATOR = 900 new Creator<WifiUsabilityStatsEntry>() { 901 public WifiUsabilityStatsEntry createFromParcel(Parcel in) { 902 return new WifiUsabilityStatsEntry( 903 in.readLong(), in.readInt(), 904 in.readInt(), in.readLong(), in.readLong(), 905 in.readLong(), in.readLong(), in.readLong(), 906 in.readLong(), in.readLong(), in.readLong(), 907 in.readLong(), in.readLong(), in.readLong(), 908 in.readLong(), in.readLong(), in.readLong(), 909 in.readLong(), in.readLong(), in.readInt(), 910 in.readInt(), in.readInt(), in.readInt(), 911 in.readInt(), in.createTypedArray(ContentionTimeStats.CREATOR), 912 in.createTypedArray(RateStats.CREATOR), 913 in.createTypedArray(RadioStats.CREATOR), 914 in.readInt(), in.readBoolean(), in.readBoolean(), 915 in.readBoolean(), in.readInt(), in.readInt(), 916 in.readInt(), in.readBoolean(), 917 in.readSparseArray(LinkStats.class.getClassLoader()) 918 ); 919 } 920 921 public WifiUsabilityStatsEntry[] newArray(int size) { 922 return new WifiUsabilityStatsEntry[size]; 923 } 924 }; 925 926 /** Get identifiers of the links if multi link configuration exists. 927 * 928 * @return An array of link identifiers if exists, otherwise null. 929 */ 930 @Nullable getLinkIds()931 public int[] getLinkIds() { 932 if (mLinkStats == null) return null; 933 int[] result = new int[mLinkStats.size()]; 934 for (int i = 0; i < mLinkStats.size(); i++) { 935 result[i] = mLinkStats.keyAt(i); 936 } 937 return result; 938 } 939 940 /** 941 * Get link state. Refer {@link LinkState}. 942 * 943 * @param linkId Identifier of the link. 944 * @return Link state. 945 * @throws NoSuchElementException if linkId is invalid. 946 */ getLinkState(int linkId)947 public @LinkState int getLinkState(int linkId) { 948 if (mLinkStats.contains(linkId)) return mLinkStats.get(linkId).mState; 949 throw new NoSuchElementException("linkId is invalid - " + linkId); 950 } 951 952 /** Absolute milliseconds from device boot when these stats were sampled */ getTimeStampMillis()953 public long getTimeStampMillis() { 954 return mTimeStampMillis; 955 } 956 957 /** 958 * The RSSI (in dBm) at the sample time. In case of Multi Link Operation (MLO), returned RSSI is 959 * the highest of all associated links. 960 * 961 * @return the RSSI. 962 */ getRssi()963 public int getRssi() { 964 return mRssi; 965 } 966 967 /** The RSSI (in dBm) of the link at the sample time. 968 * 969 * @param linkId Identifier of the link. 970 * @return RSSI in dBm. 971 * @throws NoSuchElementException if linkId is invalid. 972 */ getRssi(int linkId)973 public int getRssi(int linkId) { 974 if (mLinkStats.contains(linkId)) return mLinkStats.get(linkId).mRssi; 975 throw new NoSuchElementException("linkId is invalid - " + linkId); 976 } 977 978 /** 979 * Get firmware/hardware implementation specific persistent value for this 980 * device, identifying the radio interface for which the stats are produced. 981 * 982 * @param linkId Identifier of the link. 983 * @return Radio identifier. 984 * @throws NoSuchElementException if linkId is invalid. 985 */ getRadioId(int linkId)986 public long getRadioId(int linkId) { 987 if (mLinkStats.contains(linkId)) return mLinkStats.get(linkId).mRadioId; 988 throw new NoSuchElementException("linkId is invalid - " + linkId); 989 } 990 991 /** Link speed at the sample time in Mbps. In case of Multi Link Operation (MLO), returned value 992 * is the current link speed of the associated link with the highest RSSI. 993 * 994 * @return Link speed in Mpbs or {@link WifiInfo#LINK_SPEED_UNKNOWN} if link speed is unknown. 995 */ getLinkSpeedMbps()996 public int getLinkSpeedMbps() { 997 return mLinkSpeedMbps; 998 } 999 1000 /** 1001 * Tx Link speed of the link at the sample time in Mbps. 1002 * 1003 * @param linkId Identifier of the link. 1004 * @return Transmit link speed in Mpbs or {@link WifiInfo#LINK_SPEED_UNKNOWN} if link speed 1005 * is unknown. 1006 * @throws NoSuchElementException if linkId is invalid. 1007 */ getTxLinkSpeedMbps(int linkId)1008 public int getTxLinkSpeedMbps(int linkId) { 1009 if (mLinkStats.contains(linkId)) return mLinkStats.get(linkId).mTxLinkSpeedMbps; 1010 throw new NoSuchElementException("linkId is invalid - " + linkId); 1011 } 1012 1013 /** 1014 * The total number of tx success counted from the last radio chip reset. In case of Multi 1015 * Link Operation (MLO), the returned value is the sum of total number of tx success on all 1016 * associated links. 1017 * 1018 * @return total tx success count. 1019 */ getTotalTxSuccess()1020 public long getTotalTxSuccess() { 1021 return mTotalTxSuccess; 1022 } 1023 1024 /** 1025 * The total number of tx success on a link counted from the last radio chip reset. 1026 * 1027 * @param linkId Identifier of the link. 1028 * @return total tx success count. 1029 * @throws NoSuchElementException if linkId is invalid. 1030 */ getTotalTxSuccess(int linkId)1031 public long getTotalTxSuccess(int linkId) { 1032 if (mLinkStats.contains(linkId)) return mLinkStats.get(linkId).mTotalTxSuccess; 1033 throw new NoSuchElementException("linkId is invalid - " + linkId); 1034 } 1035 1036 /** 1037 * The total number of MPDU data packet retries counted from the last radio chip reset. In 1038 * case of Multi Link Operation (MLO), the returned value is the sum of total number of MPDU 1039 * data packet retries on all associated links. 1040 * 1041 * @return total tx retries count. 1042 */ getTotalTxRetries()1043 public long getTotalTxRetries() { 1044 return mTotalTxRetries; 1045 } 1046 1047 /** 1048 * The total number of MPDU data packet retries on a link counted from the last radio chip 1049 * reset. 1050 * 1051 * @param linkId Identifier of the link. 1052 * @return total tx retries count. 1053 * @throws NoSuchElementException if linkId is invalid. 1054 */ getTotalTxRetries(int linkId)1055 public long getTotalTxRetries(int linkId) { 1056 if (mLinkStats.contains(linkId)) return mLinkStats.get(linkId).mTotalTxRetries; 1057 throw new NoSuchElementException("linkId is invalid - " + linkId); 1058 } 1059 1060 /** 1061 * The total number of tx bad counted from the last radio chip reset. In case of Multi Link 1062 * Operation (MLO), the returned value is the sum of total number of tx bad on all associated 1063 * links. 1064 * 1065 * @return total tx bad count. 1066 */ getTotalTxBad()1067 public long getTotalTxBad() { 1068 return mTotalTxBad; 1069 } 1070 1071 /** 1072 * The total number of tx bad on a link counted from the last radio chip reset. 1073 * 1074 * @param linkId Identifier of the link. 1075 * @return total tx bad count. 1076 * @throws NoSuchElementException if linkId is invalid. 1077 */ getTotalTxBad(int linkId)1078 public long getTotalTxBad(int linkId) { 1079 if (mLinkStats.contains(linkId)) return mLinkStats.get(linkId).mTotalTxBad; 1080 throw new NoSuchElementException("linkId is invalid - " + linkId); 1081 } 1082 1083 /** 1084 * The total number of rx success counted from the last radio chip reset. In case of Multi 1085 * Link Operation (MLO), the returned value is the sum of total number of rx success on all 1086 * associated links. 1087 * 1088 * @return total rx success count. 1089 */ getTotalRxSuccess()1090 public long getTotalRxSuccess() { 1091 return mTotalRxSuccess; 1092 } 1093 1094 /** 1095 * The total number of rx success on a link counted from the last radio chip reset. 1096 * 1097 * @param linkId Identifier of the link. 1098 * @return total rx success count. 1099 * @throws NoSuchElementException if linkId is invalid. 1100 */ getTotalRxSuccess(int linkId)1101 public long getTotalRxSuccess(int linkId) { 1102 if (mLinkStats.contains(linkId)) return mLinkStats.get(linkId).mTotalRxSuccess; 1103 throw new NoSuchElementException("linkId is invalid - " + linkId); 1104 } 1105 1106 /** The total time the wifi radio is on in ms counted from the last radio chip reset */ getTotalRadioOnTimeMillis()1107 public long getTotalRadioOnTimeMillis() { 1108 return mTotalRadioOnTimeMillis; 1109 } 1110 1111 /** The total time the wifi radio is doing tx in ms counted from the last radio chip reset */ getTotalRadioTxTimeMillis()1112 public long getTotalRadioTxTimeMillis() { 1113 return mTotalRadioTxTimeMillis; 1114 } 1115 1116 /** The total time the wifi radio is doing rx in ms counted from the last radio chip reset */ getTotalRadioRxTimeMillis()1117 public long getTotalRadioRxTimeMillis() { 1118 return mTotalRadioRxTimeMillis; 1119 } 1120 1121 /** The total time spent on all types of scans in ms counted from the last radio chip reset */ getTotalScanTimeMillis()1122 public long getTotalScanTimeMillis() { 1123 return mTotalScanTimeMillis; 1124 } 1125 1126 /** The total time spent on nan scans in ms counted from the last radio chip reset */ getTotalNanScanTimeMillis()1127 public long getTotalNanScanTimeMillis() { 1128 return mTotalNanScanTimeMillis; 1129 } 1130 1131 /** The total time spent on background scans in ms counted from the last radio chip reset */ getTotalBackgroundScanTimeMillis()1132 public long getTotalBackgroundScanTimeMillis() { 1133 return mTotalBackgroundScanTimeMillis; 1134 } 1135 1136 /** The total time spent on roam scans in ms counted from the last radio chip reset */ getTotalRoamScanTimeMillis()1137 public long getTotalRoamScanTimeMillis() { 1138 return mTotalRoamScanTimeMillis; 1139 } 1140 1141 /** The total time spent on pno scans in ms counted from the last radio chip reset */ getTotalPnoScanTimeMillis()1142 public long getTotalPnoScanTimeMillis() { 1143 return mTotalPnoScanTimeMillis; 1144 } 1145 1146 /** The total time spent on hotspot2.0 scans and GAS exchange in ms counted from the last radio 1147 * chip reset */ getTotalHotspot2ScanTimeMillis()1148 public long getTotalHotspot2ScanTimeMillis() { 1149 return mTotalHotspot2ScanTimeMillis; 1150 } 1151 1152 /** 1153 * The total time CCA is on busy status on the current frequency in ms counted from the last 1154 * radio chip reset.In case of Multi Link Operation (MLO), returned value is the total time 1155 * CCA is on busy status on the current frequency of the associated link with the highest 1156 * RSSI. 1157 */ getTotalCcaBusyFreqTimeMillis()1158 public long getTotalCcaBusyFreqTimeMillis() { 1159 return mTotalCcaBusyFreqTimeMillis; 1160 } 1161 1162 /** 1163 * The total time CCA is on busy status on the link frequency in ms counted from the last 1164 * radio chip reset. 1165 * 1166 * @param linkId Identifier of the link. 1167 * @return total time CCA is on busy status for the link in ms. 1168 * @throws NoSuchElementException if linkId is invalid. 1169 * @hide 1170 */ getTotalCcaBusyFreqTimeMillis(int linkId)1171 public long getTotalCcaBusyFreqTimeMillis(int linkId) { 1172 if (mLinkStats.contains(linkId)) return mLinkStats.get(linkId).mTotalCcaBusyFreqTimeMillis; 1173 throw new NoSuchElementException("linkId is invalid - " + linkId); 1174 } 1175 1176 /** 1177 * The total radio on time on the current frequency from the last radio chip reset. In case of 1178 * Multi Link Operation (MLO), returned value is the total time radio on time on the current 1179 * frequency of the associated link with the highest RSSI. 1180 */ getTotalRadioOnFreqTimeMillis()1181 public long getTotalRadioOnFreqTimeMillis() { 1182 return mTotalRadioOnFreqTimeMillis; 1183 } 1184 1185 /** 1186 * The total radio on time on the link frequency from the last radio chip reset 1187 * 1188 * @param linkId Identifier of the link. 1189 * @return The total radio on time for the link in ms. 1190 * @throws NoSuchElementException if linkId is invalid. 1191 * @hide 1192 */ getTotalRadioOnFreqTimeMillis(int linkId)1193 public long getTotalRadioOnFreqTimeMillis(int linkId) { 1194 if (mLinkStats.contains(linkId)) return mLinkStats.get(linkId).mTotalRadioOnFreqTimeMillis; 1195 throw new NoSuchElementException("linkId is invalid - " + linkId); 1196 } 1197 1198 /** 1199 * The total number of beacons received from the last radio chip reset. In case of Multi Link 1200 * Operation (MLO), the returned value is the beacons received on the associated link with 1201 * the highest RSSI. 1202 * 1203 * @return total beacons received. 1204 */ getTotalBeaconRx()1205 public long getTotalBeaconRx() { 1206 return mTotalBeaconRx; 1207 } 1208 1209 /** 1210 * The total number of beacons received from the last radio chip reset. 1211 * 1212 * @param linkId Identifier of the link. 1213 * @return total beacons received. 1214 * @throws NoSuchElementException if linkId is invalid. 1215 */ getTotalBeaconRx(int linkId)1216 public long getTotalBeaconRx(int linkId) { 1217 if (mLinkStats.contains(linkId)) return mLinkStats.get(linkId).mTotalBeaconRx; 1218 throw new NoSuchElementException("linkId is invalid - " + linkId); 1219 } 1220 1221 /** The status of link probe since last stats update */ getProbeStatusSinceLastUpdate()1222 @ProbeStatus public int getProbeStatusSinceLastUpdate() { 1223 return mProbeStatusSinceLastUpdate; 1224 } 1225 1226 /** The elapsed time of the most recent link probe since last stats update */ getProbeElapsedTimeSinceLastUpdateMillis()1227 public int getProbeElapsedTimeSinceLastUpdateMillis() { 1228 return mProbeElapsedTimeSinceLastUpdateMillis; 1229 } 1230 1231 /** The MCS rate of the most recent link probe since last stats update */ getProbeMcsRateSinceLastUpdate()1232 public int getProbeMcsRateSinceLastUpdate() { 1233 return mProbeMcsRateSinceLastUpdate; 1234 } 1235 1236 /** 1237 * Rx link speed at the sample time in Mbps. In case of Multi Link Operation (MLO), returned 1238 * value is the receive link speed of the associated link with the highest RSSI. 1239 * 1240 * @return Receive link speed in Mbps or {@link WifiInfo#LINK_SPEED_UNKNOWN} if link speed 1241 * is unknown. 1242 */ getRxLinkSpeedMbps()1243 public int getRxLinkSpeedMbps() { 1244 return mRxLinkSpeedMbps; 1245 } 1246 1247 /** 1248 * Rx Link speed of the link at the sample time in Mbps. 1249 * 1250 * @param linkId Identifier of the link. 1251 * @return Receive link speed in Mbps or {@link WifiInfo#LINK_SPEED_UNKNOWN} if link speed 1252 * is unknown. 1253 * @throws NoSuchElementException if linkId is invalid. 1254 */ getRxLinkSpeedMbps(int linkId)1255 public int getRxLinkSpeedMbps(int linkId) { 1256 if (mLinkStats.contains(linkId)) return mLinkStats.get(linkId).mRxLinkSpeedMbps; 1257 throw new NoSuchElementException("linkId is invalid - " + linkId); 1258 } 1259 1260 /** 1261 * Duty cycle of the connection. 1262 * If this connection is being served using time slicing on a radio with one or more interfaces 1263 * (i.e MCC), then this method returns the duty cycle assigned to this interface in percent. 1264 * If no concurrency or not using time slicing during concurrency (i.e SCC or DBS), set to 100. 1265 * In case of Multi Link Operation (MLO), returned value is the duty cycle of the associated 1266 * link with the highest RSSI. 1267 * 1268 * @return duty cycle in percent if known. 1269 * @throws NoSuchElementException if the duty cycle is unknown (not provided by the HAL). 1270 */ getTimeSliceDutyCycleInPercent()1271 public @IntRange(from = 0, to = 100) int getTimeSliceDutyCycleInPercent() { 1272 if (mTimeSliceDutyCycleInPercent == -1) { 1273 throw new NoSuchElementException("Unknown value"); 1274 } 1275 return mTimeSliceDutyCycleInPercent; 1276 } 1277 1278 /** 1279 * Duty cycle of the connection for a link. 1280 * If this connection is being served using time slicing on a radio with one or more interfaces 1281 * (i.e MCC) and links, then this method returns the duty cycle assigned to this interface in 1282 * percent for the link. If no concurrency or not using time slicing during concurrency (i.e SCC 1283 * or DBS), set to 100. 1284 * 1285 * @param linkId Identifier of the link. 1286 * @return duty cycle in percent if known. 1287 * @throws NoSuchElementException if the duty cycle is unknown (not provided by the HAL) or 1288 * linkId is invalid. 1289 */ getTimeSliceDutyCycleInPercent(int linkId)1290 public @IntRange(from = 0, to = 100) int getTimeSliceDutyCycleInPercent(int linkId) { 1291 if (!mLinkStats.contains(linkId)) { 1292 throw new NoSuchElementException("linkId is invalid - " + linkId); 1293 } 1294 if (mLinkStats.get(linkId).mTimeSliceDutyCycleInPercent == -1) { 1295 throw new NoSuchElementException("Unknown value"); 1296 } 1297 return mLinkStats.get(linkId).mTimeSliceDutyCycleInPercent; 1298 } 1299 1300 /** 1301 * Data packet contention time statistics for Access Category. In case of Multi Link 1302 * Operation (MLO), the returned value is the contention stats of the associated link with the 1303 * highest RSSI. 1304 * 1305 * @param ac The access category, see {@link WmeAccessCategory}. 1306 * @return The contention time statistics, see {@link ContentionTimeStats} 1307 */ 1308 @NonNull getContentionTimeStats(@meAccessCategory int ac)1309 public ContentionTimeStats getContentionTimeStats(@WmeAccessCategory int ac) { 1310 if (mContentionTimeStats != null 1311 && mContentionTimeStats.length == NUM_WME_ACCESS_CATEGORIES) { 1312 return mContentionTimeStats[ac]; 1313 } 1314 Log.e(TAG, "The ContentionTimeStats is not filled out correctly: " 1315 + Arrays.toString(mContentionTimeStats)); 1316 return new ContentionTimeStats(); 1317 } 1318 1319 /** 1320 * Data packet contention time statistics of a link for Access Category. 1321 * 1322 * @param linkId Identifier of the link. 1323 * @param ac The access category, see {@link WmeAccessCategory}. 1324 * @return The contention time statistics, see {@link ContentionTimeStats}. 1325 * @throws NoSuchElementException if linkId is invalid. 1326 */ 1327 @NonNull getContentionTimeStats(int linkId, @WmeAccessCategory int ac)1328 public ContentionTimeStats getContentionTimeStats(int linkId, @WmeAccessCategory int ac) { 1329 if (!mLinkStats.contains(linkId)) { 1330 throw new NoSuchElementException("linkId is invalid - " + linkId); 1331 } 1332 ContentionTimeStats[] linkContentionTimeStats = mLinkStats.get( 1333 linkId).mContentionTimeStats; 1334 if (linkContentionTimeStats != null 1335 && linkContentionTimeStats.length == NUM_WME_ACCESS_CATEGORIES) { 1336 return linkContentionTimeStats[ac]; 1337 } 1338 Log.e(TAG, "The ContentionTimeStats is not filled out correctly: " 1339 + Arrays.toString(mContentionTimeStats)); 1340 return new ContentionTimeStats(); 1341 } 1342 1343 /** 1344 * Rate information and statistics, which are ordered by preamble, modulation and coding scheme 1345 * (MCS), and number of spatial streams (NSS). In case of Multi Link Operation (MLO), the 1346 * returned rate information is that of the associated link with the highest RSSI. 1347 * 1348 * @return A list of rate statistics in the form of a list of {@link RateStats} objects. 1349 * Depending on the link type, the list is created following the order of: 1350 * - HT (IEEE Std 802.11-2020, Section 19): LEGACY rates (1Mbps, ..., 54Mbps), 1351 * HT MCS0, ..., MCS15; 1352 * - VHT (IEEE Std 802.11-2020, Section 21): LEGACY rates (1Mbps, ..., 54Mbps), 1353 * VHT MCS0/NSS1, ..., VHT MCS11/NSS1, VHT MCSO/NSS2, ..., VHT MCS11/NSS2; 1354 * - HE (IEEE Std 802.11ax-2020, Section 27): LEGACY rates (1Mbps, ..., 54Mbps), 1355 * HE MCS0/NSS1, ..., HE MCS11/NSS1, HE MCSO/NSS2, ..., HE MCS11/NSS2. 1356 * - EHT (IEEE std 802.11be-2021, Section 36): Legacy rates (1Mbps, ..., 54Mbps), 1357 * EHT MSC0/NSS1, ..., EHT MCS14/NSS1, EHT MCS0/NSS2, ..., EHT MCS14/NSS2. 1358 */ 1359 @NonNull getRateStats()1360 public List<RateStats> getRateStats() { 1361 if (mRateStats != null) { 1362 return Arrays.asList(mRateStats); 1363 } 1364 return Collections.emptyList(); 1365 } 1366 1367 /** 1368 * Rate information and statistics, which are ordered by preamble, modulation and coding scheme 1369 * (MCS), and number of spatial streams (NSS) for link. 1370 * 1371 * @param linkId Identifier of the link. 1372 * @return A list of rate statistics in the form of a list of {@link RateStats} objects. 1373 * Depending on the link type, the list is created following the order of: 1374 * - HT (IEEE Std 802.11-2020, Section 19): LEGACY rates (1Mbps, ..., 54Mbps), 1375 * HT MCS0, ..., MCS15; 1376 * - VHT (IEEE Std 802.11-2020, Section 21): LEGACY rates (1Mbps, ..., 54Mbps), 1377 * VHT MCS0/NSS1, ..., VHT MCS11/NSS1, VHT MCSO/NSS2, ..., VHT MCS11/NSS2; 1378 * - HE (IEEE Std 802.11ax-2020, Section 27): LEGACY rates (1Mbps, ..., 54Mbps), 1379 * HE MCS0/NSS1, ..., HE MCS11/NSS1, HE MCSO/NSS2, ..., HE MCS11/NSS2. 1380 * - EHT (IEEE std 802.11be-2021, Section 36): Legacy rates (1Mbps, ..., 54Mbps), 1381 * EHT MSC0/NSS1, ..., EHT MCS14/NSS1, EHT MCS0/NSS2, ..., EHT MCS14/NSS2. 1382 * @throws NoSuchElementException if linkId is invalid. 1383 */ 1384 @NonNull getRateStats(int linkId)1385 public List<RateStats> getRateStats(int linkId) { 1386 if (mLinkStats.contains(linkId)) { 1387 RateStats[] rateStats = mLinkStats.get(linkId).mRateStats; 1388 if (rateStats != null) return Arrays.asList(rateStats); 1389 return Collections.emptyList(); 1390 } 1391 throw new NoSuchElementException("linkId is invalid - " + linkId); 1392 } 1393 1394 /** 1395 * Radio stats from all the radios, see {@link RadioStats#getRadioId()} 1396 * @return A list of Wifi link layer radio stats, see {@link RadioStats} 1397 */ 1398 @NonNull getWifiLinkLayerRadioStats()1399 public List<RadioStats> getWifiLinkLayerRadioStats() { 1400 if (mRadioStats != null) { 1401 return Arrays.asList(mRadioStats); 1402 } 1403 return Collections.emptyList(); 1404 } 1405 1406 /** 1407 * Channel utilization ratio on the current channel. 1408 * 1409 * @return The channel utilization ratio (value) in the range of [0, 255], where x corresponds 1410 * to (x * 100 / 255)%, or -1 indicating that there is no valid value to return. 1411 */ getChannelUtilizationRatio()1412 public @IntRange(from = -1, to = 255) int getChannelUtilizationRatio() { 1413 return mChannelUtilizationRatio; 1414 } 1415 1416 /** 1417 * Indicate whether current link layer (L2) throughput is sufficient. L2 throughput is 1418 * sufficient when one of the following conditions is met: 1) L3 throughput is low and L2 1419 * throughput is above its low threshold; 2) L3 throughput is not low and L2 throughput over L3 1420 * throughput ratio is above a threshold; 3) L3 throughput is not low and L2 throughput is 1421 * above its high threshold. 1422 * 1423 * @return true if it is sufficient or false if it is insufficient. 1424 */ isThroughputSufficient()1425 public boolean isThroughputSufficient() { 1426 return mIsThroughputSufficient; 1427 } 1428 1429 /** 1430 * Indicate whether Wi-Fi scoring is enabled by the user, 1431 * see {@link WifiManager#setWifiScoringEnabled(boolean)}. 1432 * 1433 * @return true if it is enabled. 1434 */ isWifiScoringEnabled()1435 public boolean isWifiScoringEnabled() { 1436 return mIsWifiScoringEnabled; 1437 } 1438 1439 /** 1440 * Indicate whether Cellular data is available. 1441 * 1442 * @return true if it is available and false otherwise. 1443 */ isCellularDataAvailable()1444 public boolean isCellularDataAvailable() { 1445 return mIsCellularDataAvailable; 1446 } 1447 1448 /** Cellular data network type currently in use on the device for data transmission */ getCellularDataNetworkType()1449 @NetworkType public int getCellularDataNetworkType() { 1450 return mCellularDataNetworkType; 1451 } 1452 1453 /** 1454 * Cellular signal strength in dBm, NR: CsiRsrp, LTE: Rsrp, WCDMA/TDSCDMA: Rscp, 1455 * CDMA: Rssi, EVDO: Rssi, GSM: Rssi 1456 */ getCellularSignalStrengthDbm()1457 public int getCellularSignalStrengthDbm() { 1458 return mCellularSignalStrengthDbm; 1459 } 1460 1461 /** 1462 * Cellular signal strength in dB, NR: CsiSinr, LTE: Rsrq, WCDMA: EcNo, TDSCDMA: invalid, 1463 * CDMA: Ecio, EVDO: SNR, GSM: invalid 1464 */ getCellularSignalStrengthDb()1465 public int getCellularSignalStrengthDb() { 1466 return mCellularSignalStrengthDb; 1467 } 1468 1469 /** Whether the primary registered cell of current entry is same as that of previous entry */ isSameRegisteredCell()1470 public boolean isSameRegisteredCell() { 1471 return mIsSameRegisteredCell; 1472 } 1473 } 1474