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