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