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