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