• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2019 The Linux Foundation
3  * Copyright (C) 2023 The Android Open Source Project
4  *
5  * Licensed under the Apache License, Version 2.0 (the "License");
6  * you may not use this file except in compliance with the License.
7  * You may obtain a copy of the License at
8  *
9  *      http://www.apache.org/licenses/LICENSE-2.0
10  *
11  * Unless required by applicable law or agreed to in writing, software
12  * distributed under the License is distributed on an "AS IS" BASIS,
13  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  * See the License for the specific language governing permissions and
15  * limitations under the License.
16  */
17 
18 package android.bluetooth;
19 
20 import static java.util.Objects.requireNonNull;
21 
22 import android.annotation.DurationMillisLong;
23 import android.annotation.FlaggedApi;
24 import android.annotation.IntDef;
25 import android.annotation.NonNull;
26 import android.annotation.Nullable;
27 import android.annotation.SystemApi;
28 import android.os.Parcel;
29 import android.os.Parcelable;
30 import android.util.Log;
31 
32 import com.android.bluetooth.flags.Flags;
33 
34 import java.lang.annotation.Retention;
35 import java.lang.annotation.RetentionPolicy;
36 import java.nio.ByteBuffer;
37 import java.nio.ByteOrder;
38 
39 /**
40  * This class provides the System APIs to access the data of BQR event reported from firmware side.
41  * Currently it supports five event types: Quality monitor event, Approaching LSTO event, A2DP
42  * choppy event, SCO choppy event and Connect fail event. To know which kind of event is wrapped in
43  * this {@link BluetoothQualityReport} object, you need to call {@link #getQualityReportId}.
44  *
45  * <ul>
46  *   <li>For Quality monitor event, you can call {@link #getBqrCommon} to get a {@link
47  *       BluetoothQualityReport.BqrCommon} object.
48  *   <li>For Approaching LSTO event, you can call {@link #getBqrCommon} to get a {@link
49  *       BluetoothQualityReport.BqrCommon} object, and call {@link #getBqrEvent} to get a {@link
50  *       BluetoothQualityReport.BqrVsLsto} object.
51  *   <li>For A2DP choppy event, you can call {@link #getBqrCommon} to get a {@link
52  *       BluetoothQualityReport.BqrCommon} object, and call {@link #getBqrEvent} to get a {@link
53  *       BluetoothQualityReport.BqrVsA2dpChoppy} object.
54  *   <li>For SCO choppy event, you can call {@link #getBqrCommon} to get a {@link
55  *       BluetoothQualityReport.BqrCommon} object, and call {@link #getBqrEvent} to get a {@link
56  *       BluetoothQualityReport.BqrVsScoChoppy} object.
57  *   <li>For Connect fail event, you can call {@link #getBqrCommon} to get a {@link
58  *       BluetoothQualityReport.BqrCommon} object, and call {@link #getBqrEvent} to get a {@link
59  *       BluetoothQualityReport.BqrConnectFail} object.
60  *   <li>For Energy monitor event, you can call {@link #getBqrEvent} to get a {@link
61  *       BluetoothQualityReport.BqrEnergyMonitor} object.
62  *   <li>For RF stats event, you can call {@link #getBqrEvent} to get a {@link
63  *       BluetoothQualityReport.BqrRfStats} object.
64  * </ul>
65  *
66  * @hide
67  */
68 @SystemApi
69 public final class BluetoothQualityReport implements Parcelable {
70     private static final String TAG = BluetoothQualityReport.class.getSimpleName();
71 
72     /**
73      * Quality report ID: Monitor.
74      *
75      * @hide
76      */
77     @SystemApi public static final int QUALITY_REPORT_ID_MONITOR = 0x01;
78 
79     /**
80      * Quality report ID: Approaching LSTO.
81      *
82      * @hide
83      */
84     @SystemApi public static final int QUALITY_REPORT_ID_APPROACH_LSTO = 0x02;
85 
86     /**
87      * Quality report ID: A2DP choppy.
88      *
89      * @hide
90      */
91     @SystemApi public static final int QUALITY_REPORT_ID_A2DP_CHOPPY = 0x03;
92 
93     /**
94      * Quality report ID: SCO choppy.
95      *
96      * @hide
97      */
98     @SystemApi public static final int QUALITY_REPORT_ID_SCO_CHOPPY = 0x04;
99 
100     // Report ID 0x05 is reserved for Root inflammation event,
101     // which indicates a fatal error in the Bluetooth HAL or controller.
102     // This event requires a Bluetooth stack restart and is not passed
103     // to the framework. It is not explicitly defined as a System API
104     // because it is handled internally within the Bluetooth stack.
105 
106     /**
107      * Quality report ID: Energy Monitor.
108      *
109      * @hide
110      */
111     @FlaggedApi(Flags.FLAG_SUPPORT_BLUETOOTH_QUALITY_REPORT_V6)
112     @SystemApi
113     public static final int QUALITY_REPORT_ID_ENERGY_MONITOR = 0x06;
114 
115     // Report ID 0x07 is reserved for LE Audio Choppy events. This ID will be used
116     // in a future version to indicate instances of choppy audio playback
117     // experienced with LE Audio connections. It is currently not handled.
118     /**
119      * Quality report ID: Connect Fail.
120      *
121      * @hide
122      */
123     @SystemApi public static final int QUALITY_REPORT_ID_CONN_FAIL = 0x08;
124 
125     /**
126      * Quality report ID: RF Stats.
127      *
128      * @hide
129      */
130     @FlaggedApi(Flags.FLAG_SUPPORT_BLUETOOTH_QUALITY_REPORT_V6)
131     @SystemApi
132     public static final int QUALITY_REPORT_ID_RF_STATS = 0x09;
133 
134     /** @hide */
135     @Retention(RetentionPolicy.SOURCE)
136     @IntDef(
137             prefix = {"QUALITY_REPORT_ID"},
138             value = {
139                 QUALITY_REPORT_ID_MONITOR,
140                 QUALITY_REPORT_ID_APPROACH_LSTO,
141                 QUALITY_REPORT_ID_A2DP_CHOPPY,
142                 QUALITY_REPORT_ID_SCO_CHOPPY,
143                 QUALITY_REPORT_ID_ENERGY_MONITOR,
144                 QUALITY_REPORT_ID_CONN_FAIL,
145                 QUALITY_REPORT_ID_RF_STATS,
146             })
147     public @interface QualityReportId {}
148 
149     private final String mAddr;
150     private final int mLmpVer;
151     private final int mLmpSubVer;
152     private final int mManufacturerId;
153     private final String mName;
154     private final BluetoothClass mBluetoothClass;
155 
156     private final BqrCommon mBqrCommon;
157     private BqrVsLsto mBqrVsLsto;
158     private BqrVsA2dpChoppy mBqrVsA2dpChoppy;
159     private BqrVsScoChoppy mBqrVsScoChoppy;
160     private BqrConnectFail mBqrConnectFail;
161     private BqrEnergyMonitor mBqrEnergyMonitor;
162     private BqrRfStats mBqrRfStats;
163 
164     enum PacketType {
165         INVALID,
166         TYPE_ID,
167         TYPE_NULL,
168         TYPE_POLL,
169         TYPE_FHS,
170         TYPE_HV1,
171         TYPE_HV2,
172         TYPE_HV3,
173         TYPE_DV,
174         TYPE_EV3,
175         TYPE_EV4,
176         TYPE_EV5,
177         TYPE_2EV3,
178         TYPE_2EV5,
179         TYPE_3EV3,
180         TYPE_3EV5,
181         TYPE_DM1,
182         TYPE_DH1,
183         TYPE_DM3,
184         TYPE_DH3,
185         TYPE_DM5,
186         TYPE_DH5,
187         TYPE_AUX1,
188         TYPE_2DH1,
189         TYPE_2DH3,
190         TYPE_2DH5,
191         TYPE_3DH1,
192         TYPE_3DH3,
193         TYPE_3DH5;
194 
195         private static final PacketType[] sAllValues = values();
196 
fromOrdinal(int n)197         static PacketType fromOrdinal(int n) {
198             if (n < sAllValues.length) {
199                 return sAllValues[n];
200             }
201             return INVALID;
202         }
203     }
204 
205     enum ConnState {
206         CONN_IDLE(0x00),
207         CONN_ACTIVE(0x81),
208         CONN_HOLD(0x02),
209         CONN_SNIFF_IDLE(0x03),
210         CONN_SNIFF_ACTIVE(0x84),
211         CONN_SNIFF_MASTER_TRANSITION(0x85),
212         CONN_PARK(0x06),
213         CONN_PARK_PEND(0x47),
214         CONN_UNPARK_PEND(0x08),
215         CONN_UNPARK_ACTIVE(0x89),
216         CONN_DISCONNECT_PENDING(0x4A),
217         CONN_PAGING(0x0B),
218         CONN_PAGE_SCAN(0x0C),
219         CONN_LOCAL_LOOPBACK(0x0D),
220         CONN_LE_ACTIVE(0x0E),
221         CONN_ANT_ACTIVE(0x0F),
222         CONN_TRIGGER_SCAN(0x10),
223         CONN_RECONNECTING(0x11),
224         CONN_SEMI_CONN(0x12);
225 
226         private final int mValue;
227         private static final ConnState[] sAllStates = values();
228 
ConnState(int val)229         ConnState(int val) {
230             mValue = val;
231         }
232 
toString(int val)233         public static String toString(int val) {
234             for (ConnState state : sAllStates) {
235                 if (state.mValue == val) {
236                     return state.toString();
237                 }
238             }
239             return "INVALID";
240         }
241     }
242 
243     enum LinkQuality {
244         ULTRA_HIGH,
245         HIGH,
246         STANDARD,
247         MEDIUM,
248         LOW,
249         INVALID;
250 
251         private static final LinkQuality[] sAllValues = values();
252 
fromOrdinal(int n)253         static LinkQuality fromOrdinal(int n) {
254             if (n < sAllValues.length - 1) {
255                 return sAllValues[n];
256             }
257             return INVALID;
258         }
259     }
260 
261     enum AirMode {
262         uLaw,
263         aLaw,
264         CVSD,
265         transparent_msbc,
266         INVALID;
267 
268         private static final AirMode[] sAllValues = values();
269 
fromOrdinal(int n)270         static AirMode fromOrdinal(int n) {
271             if (n < sAllValues.length - 1) {
272                 return sAllValues[n];
273             }
274             return INVALID;
275         }
276     }
277 
278     /**
279      * Constructs a {@link BluetoothQualityReport} from raw byte data.
280      *
281      * <p>This constructor is intended for testing and internal use. It should not be used directly
282      * in application code.
283      */
BluetoothQualityReport( String remoteAddr, int lmpVer, int lmpSubVer, int manufacturerId, String remoteName, BluetoothClass bluetoothClass, byte[] rawData)284     private BluetoothQualityReport(
285             String remoteAddr,
286             int lmpVer,
287             int lmpSubVer,
288             int manufacturerId,
289             String remoteName,
290             BluetoothClass bluetoothClass,
291             byte[] rawData) {
292         mAddr = remoteAddr;
293         mLmpVer = lmpVer;
294         mLmpSubVer = lmpSubVer;
295         mManufacturerId = manufacturerId;
296         mName = remoteName;
297         mBluetoothClass = bluetoothClass;
298 
299         mBqrCommon = new BqrCommon(rawData, 0);
300         int id = mBqrCommon.getQualityReportId();
301         if (id == QUALITY_REPORT_ID_MONITOR) return;
302 
303         int vsPartOffset = BqrCommon.BQR_COMMON_LEN;
304         if (id == QUALITY_REPORT_ID_APPROACH_LSTO) {
305             mBqrVsLsto = new BqrVsLsto(rawData, vsPartOffset);
306         } else if (id == QUALITY_REPORT_ID_A2DP_CHOPPY) {
307             mBqrVsA2dpChoppy = new BqrVsA2dpChoppy(rawData, vsPartOffset);
308         } else if (id == QUALITY_REPORT_ID_SCO_CHOPPY) {
309             mBqrVsScoChoppy = new BqrVsScoChoppy(rawData, vsPartOffset);
310         } else if (id == QUALITY_REPORT_ID_CONN_FAIL) {
311             mBqrConnectFail = new BqrConnectFail(rawData, vsPartOffset);
312         } else {
313             if (Flags.supportBluetoothQualityReportV6()) {
314                 if (id == QUALITY_REPORT_ID_ENERGY_MONITOR) {
315                     mBqrEnergyMonitor = new BqrEnergyMonitor(rawData, 1);
316                     return;
317                 } else if (id == QUALITY_REPORT_ID_RF_STATS) {
318                     mBqrRfStats = new BqrRfStats(rawData, 1);
319                     return;
320                 }
321             }
322             throw new IllegalArgumentException(TAG + ": unknown quality report id:" + id);
323         }
324     }
325 
BluetoothQualityReport(Parcel in)326     private BluetoothQualityReport(Parcel in) {
327         mAddr = in.readString();
328         mLmpVer = in.readInt();
329         mLmpSubVer = in.readInt();
330         mManufacturerId = in.readInt();
331         mName = in.readString();
332         mBluetoothClass = new BluetoothClass(in.readInt());
333 
334         mBqrCommon = new BqrCommon(in);
335         int id = mBqrCommon.getQualityReportId();
336         if (id == QUALITY_REPORT_ID_APPROACH_LSTO) {
337             mBqrVsLsto = new BqrVsLsto(in);
338         } else if (id == QUALITY_REPORT_ID_A2DP_CHOPPY) {
339             mBqrVsA2dpChoppy = new BqrVsA2dpChoppy(in);
340         } else if (id == QUALITY_REPORT_ID_SCO_CHOPPY) {
341             mBqrVsScoChoppy = new BqrVsScoChoppy(in);
342         } else if (id == QUALITY_REPORT_ID_CONN_FAIL) {
343             mBqrConnectFail = new BqrConnectFail(in);
344         }
345 
346         if (Flags.supportBluetoothQualityReportV6()) {
347             if (id == QUALITY_REPORT_ID_ENERGY_MONITOR) {
348                 mBqrEnergyMonitor = new BqrEnergyMonitor(in);
349             } else if (id == QUALITY_REPORT_ID_RF_STATS) {
350                 mBqrRfStats = new BqrRfStats(in);
351             }
352         }
353     }
354 
355     /**
356      * Get the quality report id.
357      *
358      * @hide
359      */
360     @SystemApi
getQualityReportId()361     public @QualityReportId int getQualityReportId() {
362         return mBqrCommon.getQualityReportId();
363     }
364 
365     /**
366      * Get the string of the quality report id.
367      *
368      * @return the string of the id
369      * @hide
370      */
371     @SystemApi
qualityReportIdToString(@ualityReportId int id)372     public static @NonNull String qualityReportIdToString(@QualityReportId int id) {
373         return BqrCommon.qualityReportIdToString(id);
374     }
375 
376     /**
377      * Get bluetooth address of remote device in this report.
378      *
379      * @return bluetooth address of remote device
380      * @hide
381      */
382     @SystemApi
getRemoteAddress()383     public @Nullable String getRemoteAddress() {
384         return mAddr;
385     }
386 
387     /**
388      * Get LMP version of remote device in this report.
389      *
390      * @return LMP version of remote device
391      * @hide
392      */
393     @SystemApi
getLmpVersion()394     public int getLmpVersion() {
395         return mLmpVer;
396     }
397 
398     /**
399      * Get LMP subVersion of remote device in this report.
400      *
401      * @return LMP subVersion of remote device
402      * @hide
403      */
404     @SystemApi
getLmpSubVersion()405     public int getLmpSubVersion() {
406         return mLmpSubVer;
407     }
408 
409     /**
410      * Get manufacturer id of remote device in this report.
411      *
412      * @return manufacturer id of remote device
413      * @hide
414      */
415     @SystemApi
getManufacturerId()416     public int getManufacturerId() {
417         return mManufacturerId;
418     }
419 
420     /**
421      * Get the name of remote device in this report.
422      *
423      * @return the name of remote device
424      * @hide
425      */
426     @SystemApi
getRemoteName()427     public @Nullable String getRemoteName() {
428         return mName;
429     }
430 
431     /**
432      * Get the class of remote device in this report.
433      *
434      * @return the class of remote device
435      * @hide
436      */
437     @SystemApi
getBluetoothClass()438     public @Nullable BluetoothClass getBluetoothClass() {
439         return mBluetoothClass;
440     }
441 
442     /**
443      * Get the {@link BluetoothQualityReport.BqrCommon} object.
444      *
445      * @return the {@link BluetoothQualityReport.BqrCommon} object.
446      * @hide
447      */
448     @SystemApi
getBqrCommon()449     public @Nullable BqrCommon getBqrCommon() {
450         return mBqrCommon;
451     }
452 
453     /**
454      * Get the event data object based on current Quality Report Id. If the report id is {@link
455      * #QUALITY_REPORT_ID_MONITOR}, this returns a {@link BluetoothQualityReport.BqrCommon} object.
456      * If the report id is {@link #QUALITY_REPORT_ID_APPROACH_LSTO}, this returns a {@link
457      * BluetoothQualityReport.BqrVsLsto} object. If the report id is {@link
458      * #QUALITY_REPORT_ID_A2DP_CHOPPY}, this returns a {@link
459      * BluetoothQualityReport.BqrVsA2dpChoppy} object. If the report id is {@link
460      * #QUALITY_REPORT_ID_SCO_CHOPPY}, this returns a {@link BluetoothQualityReport.BqrVsScoChoppy}
461      * object. If the report id is {@link #QUALITY_REPORT_ID_CONN_FAIL}, this returns a {@link
462      * BluetoothQualityReport.BqrConnectFail} object. If the report id is none of the above, this
463      * returns {@code null}.
464      *
465      * @return the event data object based on the quality report id
466      * @hide
467      */
468     @SystemApi
getBqrEvent()469     public @Nullable Parcelable getBqrEvent() {
470         if (mBqrCommon == null) {
471             return null;
472         }
473         int id = mBqrCommon.getQualityReportId();
474 
475         if (Flags.supportBluetoothQualityReportV6()) {
476             if (id == QUALITY_REPORT_ID_ENERGY_MONITOR) {
477                 return mBqrEnergyMonitor;
478             } else if (id == QUALITY_REPORT_ID_RF_STATS) {
479                 return mBqrRfStats;
480             }
481         }
482 
483         switch (id) {
484             case QUALITY_REPORT_ID_MONITOR:
485                 return mBqrCommon;
486             case QUALITY_REPORT_ID_APPROACH_LSTO:
487                 return mBqrVsLsto;
488             case QUALITY_REPORT_ID_A2DP_CHOPPY:
489                 return mBqrVsA2dpChoppy;
490             case QUALITY_REPORT_ID_SCO_CHOPPY:
491                 return mBqrVsScoChoppy;
492             case QUALITY_REPORT_ID_CONN_FAIL:
493                 return mBqrConnectFail;
494             default:
495                 return null;
496         }
497     }
498 
499     /** @hide */
500     @SystemApi
501     public static final @NonNull Parcelable.Creator<BluetoothQualityReport> CREATOR =
502             new Parcelable.Creator<BluetoothQualityReport>() {
503                 public BluetoothQualityReport createFromParcel(Parcel in) {
504                     return new BluetoothQualityReport(in);
505                 }
506 
507                 public BluetoothQualityReport[] newArray(int size) {
508                     return new BluetoothQualityReport[size];
509                 }
510             };
511 
512     @Override
describeContents()513     public int describeContents() {
514         return 0;
515     }
516 
517     /**
518      * Write BluetoothQualityReport to parcel.
519      *
520      * @hide
521      */
522     @SystemApi
523     @Override
writeToParcel(@onNull Parcel out, int flags)524     public void writeToParcel(@NonNull Parcel out, int flags) {
525         BluetoothUtils.writeStringToParcel(out, mAddr);
526         out.writeInt(mLmpVer);
527         out.writeInt(mLmpSubVer);
528         out.writeInt(mManufacturerId);
529         BluetoothUtils.writeStringToParcel(out, mName);
530         out.writeInt(mBluetoothClass.getClassOfDevice());
531         mBqrCommon.writeToParcel(out, flags);
532         int id = mBqrCommon.getQualityReportId();
533         if (id == QUALITY_REPORT_ID_APPROACH_LSTO) {
534             mBqrVsLsto.writeToParcel(out, flags);
535         } else if (id == QUALITY_REPORT_ID_A2DP_CHOPPY) {
536             mBqrVsA2dpChoppy.writeToParcel(out, flags);
537         } else if (id == QUALITY_REPORT_ID_SCO_CHOPPY) {
538             mBqrVsScoChoppy.writeToParcel(out, flags);
539         } else if (id == QUALITY_REPORT_ID_CONN_FAIL) {
540             mBqrConnectFail.writeToParcel(out, flags);
541         }
542 
543         if (Flags.supportBluetoothQualityReportV6()) {
544             if (id == QUALITY_REPORT_ID_ENERGY_MONITOR) {
545                 mBqrEnergyMonitor.writeToParcel(out, flags);
546             } else if (id == QUALITY_REPORT_ID_RF_STATS) {
547                 mBqrRfStats.writeToParcel(out, flags);
548             }
549         }
550     }
551 
552     /** BluetoothQualityReport to String. */
553     @Override
554     @NonNull
toString()555     public String toString() {
556         String str;
557         str =
558                 "BQR: {\n"
559                         + ("  mAddr: " + mAddr)
560                         + (", mLmpVer: " + String.format("0x%02X", mLmpVer))
561                         + (", mLmpSubVer: " + String.format("0x%04X", mLmpSubVer))
562                         + (", mManufacturerId: " + String.format("0x%04X", mManufacturerId))
563                         + (", mName: " + mName)
564                         + (", mBluetoothClass: " + mBluetoothClass.toString())
565                         + ",\n"
566                         + mBqrCommon
567                         + "\n";
568 
569         int id = mBqrCommon.getQualityReportId();
570         if (id == QUALITY_REPORT_ID_APPROACH_LSTO) {
571             str = str + mBqrVsLsto + "\n}";
572         } else if (id == QUALITY_REPORT_ID_A2DP_CHOPPY) {
573             str = str + mBqrVsA2dpChoppy + "\n}";
574         } else if (id == QUALITY_REPORT_ID_SCO_CHOPPY) {
575             str = str + mBqrVsScoChoppy + "\n}";
576         } else if (id == QUALITY_REPORT_ID_CONN_FAIL) {
577             str = str + mBqrConnectFail + "\n}";
578         } else if (id == QUALITY_REPORT_ID_MONITOR) {
579             str = str + "}";
580         }
581 
582         if (Flags.supportBluetoothQualityReportV6()) {
583             if (id == QUALITY_REPORT_ID_ENERGY_MONITOR) {
584                 str = str + mBqrEnergyMonitor + "\n}";
585             } else if (id == QUALITY_REPORT_ID_RF_STATS) {
586                 str = str + mBqrRfStats + "\n}";
587             }
588         }
589 
590         return str;
591     }
592 
593     /**
594      * Builder for new instances of {@link BluetoothQualityReport}.
595      *
596      * @hide
597      */
598     @SystemApi
599     public static final class Builder {
600         private String remoteAddr = "00:00:00:00:00:00";
601         private int lmpVer;
602         private int lmpSubVer;
603         private int manufacturerId;
604         private String remoteName = "";
605         private BluetoothClass bluetoothClass = new BluetoothClass(0);
606         private final byte[] rawData;
607 
608         /**
609          * Creates a new instance of {@link Builder}.
610          *
611          * @return The new instance
612          * @throws NullPointerException if rawData is null
613          * @hide
614          */
615         @SystemApi
Builder(@onNull byte[] rawData)616         public Builder(@NonNull byte[] rawData) {
617             this.rawData = requireNonNull(rawData);
618         }
619 
620         /**
621          * Sets the Remote Device Address (big-endian) attribute for the new instance of {@link
622          * BluetoothQualityReport}.
623          *
624          * @param remoteAddr the Remote Device Address (big-endian) attribute
625          * @hide
626          */
627         @NonNull
628         @SystemApi
setRemoteAddress(@ullable String remoteAddr)629         public Builder setRemoteAddress(@Nullable String remoteAddr) {
630             if (!BluetoothAdapter.checkBluetoothAddress(remoteAddr)) {
631                 Log.d(TAG, "remote address is not a valid bluetooth address: " + remoteAddr);
632             } else {
633                 this.remoteAddr = remoteAddr;
634             }
635             return this;
636         }
637 
638         /**
639          * Sets the Link Manager Protocol Version attribute for the new instance of {@link
640          * BluetoothQualityReport}.
641          *
642          * @param lmpVer the Link Manager Protocol Version attribute
643          * @hide
644          */
645         @NonNull
646         @SystemApi
setLmpVersion(int lmpVer)647         public Builder setLmpVersion(int lmpVer) {
648             this.lmpVer = lmpVer;
649             return this;
650         }
651 
652         /**
653          * Sets the Link Manager Protocol SubVersion attribute for the new instance of {@link
654          * BluetoothQualityReport}.
655          *
656          * @param lmpSubVer the Link Manager Protocol SubVersion attribute
657          * @hide
658          */
659         @NonNull
660         @SystemApi
setLmpSubVersion(int lmpSubVer)661         public Builder setLmpSubVersion(int lmpSubVer) {
662             this.lmpSubVer = lmpSubVer;
663             return this;
664         }
665 
666         /**
667          * Sets the Manufacturer Id attribute for the new instance of {@link
668          * BluetoothQualityReport}.
669          *
670          * @param manufacturerId the Manufacturer Id attribute
671          * @hide
672          */
673         @NonNull
674         @SystemApi
setManufacturerId(int manufacturerId)675         public Builder setManufacturerId(int manufacturerId) {
676             this.manufacturerId = manufacturerId;
677             return this;
678         }
679 
680         /**
681          * Sets the Remote Device Name attribute for the new instance of {@link
682          * BluetoothQualityReport}.
683          *
684          * @param remoteName the Remote Device Name attribute
685          * @hide
686          */
687         @NonNull
688         @SystemApi
setRemoteName(@ullable String remoteName)689         public Builder setRemoteName(@Nullable String remoteName) {
690             if (remoteName == null) {
691                 Log.d(TAG, "remote name is null");
692             } else {
693                 this.remoteName = remoteName;
694             }
695             return this;
696         }
697 
698         /**
699          * Sets the Bluetooth Class of Remote Device attribute for the new instance of {@link
700          * BluetoothQualityReport}.
701          *
702          * @param bluetoothClass the Remote Class of Device attribute
703          * @hide
704          */
705         @NonNull
706         @SystemApi
setBluetoothClass(@ullable BluetoothClass bluetoothClass)707         public Builder setBluetoothClass(@Nullable BluetoothClass bluetoothClass) {
708             if (bluetoothClass == null) {
709                 Log.d(TAG, "remote bluetooth class is null");
710             } else {
711                 this.bluetoothClass = bluetoothClass;
712             }
713             return this;
714         }
715 
716         /**
717          * Creates a new instance of {@link BluetoothQualityReport}.
718          *
719          * @return The new instance
720          * @throws IllegalArgumentException Unsupported Quality Report Id or invalid raw data
721          * @hide
722          */
723         @NonNull
724         @SystemApi
build()725         public BluetoothQualityReport build() {
726             return new BluetoothQualityReport(
727                     remoteAddr,
728                     lmpVer,
729                     lmpSubVer,
730                     manufacturerId,
731                     remoteName,
732                     bluetoothClass,
733                     rawData);
734         }
735     }
736 
737     /**
738      * This class provides the System APIs to access the common part of BQR event.
739      *
740      * @hide
741      */
742     @SystemApi
743     public static final class BqrCommon implements Parcelable {
744         private static final String TAG =
745                 BluetoothQualityReport.TAG + "." + BqrCommon.class.getSimpleName();
746 
747         static final int BQR_COMMON_LEN = 85;
748 
749         private final @QualityReportId int mQualityReportId;
750         private int mPacketType;
751         private int mConnectionHandle;
752         private int mConnectionRole;
753         private int mTxPowerLevel;
754         private int mRssi;
755         private int mSnr;
756         private int mUnusedAfhChannelCount;
757         private int mAfhSelectUnidealChannelCount;
758         private int mLsto;
759         private long mPiconetClock;
760         private long mRetransmissionCount;
761         private long mNoRxCount;
762         private long mNakCount;
763         private long mLastTxAckTimestamp;
764         private long mFlowOffCount;
765         private long mLastFlowOnTimestamp;
766         private long mOverflowCount;
767         private long mUnderflowCount;
768         private String mAddr;
769         private int mCalFailedItemCount;
770         private long mTxTotalPackets;
771         private long mTxUnackPackets;
772         private long mTxFlushPackets;
773         private long mTxLastSubeventPackets;
774         private long mCrcErrorPackets;
775         private long mRxDupPackets;
776         private long mRxUnRecvPackets;
777         private int mCoexInfoMask;
778 
BqrCommon(byte[] rawData, int offset)779         private BqrCommon(byte[] rawData, int offset) {
780 
781             mQualityReportId = rawData[0] & 0xFF;
782             if (Flags.supportBluetoothQualityReportV6()) {
783                 if ((mQualityReportId == QUALITY_REPORT_ID_ENERGY_MONITOR)
784                         || (mQualityReportId == QUALITY_REPORT_ID_RF_STATS)) {
785                     return;
786                 }
787             }
788 
789             if (rawData == null || rawData.length < offset + BQR_COMMON_LEN) {
790                 throw new IllegalArgumentException(TAG + ": BQR raw data length is abnormal.");
791             }
792 
793             ByteBuffer bqrBuf =
794                     ByteBuffer.wrap(rawData, offset, rawData.length - offset).asReadOnlyBuffer();
795             bqrBuf.order(ByteOrder.LITTLE_ENDIAN);
796 
797             bqrBuf.get();
798             mPacketType = bqrBuf.get() & 0xFF;
799             mConnectionHandle = bqrBuf.getShort() & 0xFFFF;
800             mConnectionRole = bqrBuf.get() & 0xFF;
801             mTxPowerLevel = bqrBuf.get() & 0xFF;
802             mRssi = bqrBuf.get();
803             mSnr = bqrBuf.get();
804             mUnusedAfhChannelCount = bqrBuf.get() & 0xFF;
805             mAfhSelectUnidealChannelCount = bqrBuf.get() & 0xFF;
806             mLsto = bqrBuf.getShort() & 0xFFFF;
807             mPiconetClock = bqrBuf.getInt() & 0xFFFFFFFFL;
808             mRetransmissionCount = bqrBuf.getInt() & 0xFFFFFFFFL;
809             mNoRxCount = bqrBuf.getInt() & 0xFFFFFFFFL;
810             mNakCount = bqrBuf.getInt() & 0xFFFFFFFFL;
811             mLastTxAckTimestamp = bqrBuf.getInt() & 0xFFFFFFFFL;
812             mFlowOffCount = bqrBuf.getInt() & 0xFFFFFFFFL;
813             mLastFlowOnTimestamp = bqrBuf.getInt() & 0xFFFFFFFFL;
814             mOverflowCount = bqrBuf.getInt() & 0xFFFFFFFFL;
815             mUnderflowCount = bqrBuf.getInt() & 0xFFFFFFFFL;
816             int currentOffset = bqrBuf.position();
817             mAddr =
818                     String.format(
819                             "%02X:%02X:%02X:%02X:%02X:%02X",
820                             bqrBuf.get(currentOffset + 5),
821                             bqrBuf.get(currentOffset + 4),
822                             bqrBuf.get(currentOffset + 3),
823                             bqrBuf.get(currentOffset + 2),
824                             bqrBuf.get(currentOffset + 1),
825                             bqrBuf.get(currentOffset + 0));
826             bqrBuf.position(currentOffset + 6);
827             mCalFailedItemCount = bqrBuf.get() & 0xFF;
828             mTxTotalPackets = bqrBuf.getInt() & 0xFFFFFFFFL;
829             mTxUnackPackets = bqrBuf.getInt() & 0xFFFFFFFFL;
830             mTxFlushPackets = bqrBuf.getInt() & 0xFFFFFFFFL;
831             mTxLastSubeventPackets = bqrBuf.getInt() & 0xFFFFFFFFL;
832             mCrcErrorPackets = bqrBuf.getInt() & 0xFFFFFFFFL;
833             mRxDupPackets = bqrBuf.getInt() & 0xFFFFFFFFL;
834             mRxUnRecvPackets = bqrBuf.getInt() & 0xFFFFFFFFL;
835             mCoexInfoMask = bqrBuf.getShort() & 0xFFFF;
836         }
837 
BqrCommon(Parcel in)838         private BqrCommon(Parcel in) {
839             mQualityReportId = in.readInt();
840             mPacketType = in.readInt();
841             mConnectionHandle = in.readInt();
842             mConnectionRole = in.readInt();
843             mTxPowerLevel = in.readInt();
844             mRssi = in.readInt();
845             mSnr = in.readInt();
846             mUnusedAfhChannelCount = in.readInt();
847             mAfhSelectUnidealChannelCount = in.readInt();
848             mLsto = in.readInt();
849             mPiconetClock = in.readLong();
850             mRetransmissionCount = in.readLong();
851             mNoRxCount = in.readLong();
852             mNakCount = in.readLong();
853             mLastTxAckTimestamp = in.readLong();
854             mFlowOffCount = in.readLong();
855             mLastFlowOnTimestamp = in.readLong();
856             mOverflowCount = in.readLong();
857             mUnderflowCount = in.readLong();
858             mAddr = in.readString();
859             mCalFailedItemCount = in.readInt();
860             mTxTotalPackets = in.readLong();
861             mTxUnackPackets = in.readLong();
862             mTxFlushPackets = in.readLong();
863             mTxLastSubeventPackets = in.readLong();
864             mCrcErrorPackets = in.readLong();
865             mRxDupPackets = in.readLong();
866             mRxUnRecvPackets = in.readLong();
867             mCoexInfoMask = in.readInt();
868         }
869 
870         @QualityReportId
getQualityReportId()871         int getQualityReportId() {
872             return mQualityReportId;
873         }
874 
qualityReportIdToString(@ualityReportId int id)875         static String qualityReportIdToString(@QualityReportId int id) {
876 
877             if (Flags.supportBluetoothQualityReportV6()) {
878                 if (QUALITY_REPORT_ID_ENERGY_MONITOR == id) {
879                     return "Energy Monitor";
880                 } else if (QUALITY_REPORT_ID_RF_STATS == id) {
881                     return "RF Stats";
882                 }
883             }
884 
885             switch (id) {
886                 case QUALITY_REPORT_ID_MONITOR:
887                     return "Quality monitor";
888                 case QUALITY_REPORT_ID_APPROACH_LSTO:
889                     return "Approaching LSTO";
890                 case QUALITY_REPORT_ID_A2DP_CHOPPY:
891                     return "A2DP choppy";
892                 case QUALITY_REPORT_ID_SCO_CHOPPY:
893                     return "SCO choppy";
894                 case QUALITY_REPORT_ID_CONN_FAIL:
895                     return "Connect fail";
896                 default:
897                     return "INVALID";
898             }
899         }
900 
901         /**
902          * Get the packet type of the connection.
903          *
904          * @return the packet type
905          * @hide
906          */
907         @SystemApi
getPacketType()908         public int getPacketType() {
909             return mPacketType;
910         }
911 
912         /**
913          * Get the string of packet type.
914          *
915          * @param packetType packet type of the connection
916          * @return the string of packet type
917          * @hide
918          */
919         @SystemApi
packetTypeToString(int packetType)920         public static @Nullable String packetTypeToString(int packetType) {
921             PacketType type = PacketType.fromOrdinal(packetType);
922             return type.toString();
923         }
924 
925         /**
926          * Get the connection handle of the connection.
927          *
928          * @return the connection handle
929          * @hide
930          */
931         @SystemApi
getConnectionHandle()932         public int getConnectionHandle() {
933             return mConnectionHandle;
934         }
935 
936         /**
937          * Connection role: central.
938          *
939          * @hide
940          */
941         @SystemApi public static final int CONNECTION_ROLE_CENTRAL = 0;
942 
943         /**
944          * Connection role: peripheral.
945          *
946          * @hide
947          */
948         @SystemApi public static final int CONNECTION_ROLE_PERIPHERAL = 1;
949 
950         /** @hide */
951         @Retention(RetentionPolicy.SOURCE)
952         @IntDef(
953                 prefix = {"CONNECTION_ROLE"},
954                 value = {
955                     CONNECTION_ROLE_CENTRAL,
956                     CONNECTION_ROLE_PERIPHERAL,
957                 })
958         public @interface ConnectionRole {}
959 
960         /**
961          * Get the connection Role of the connection.
962          *
963          * @return the connection Role
964          * @hide
965          */
966         @SystemApi
967         @ConnectionRole
getConnectionRole()968         public int getConnectionRole() {
969             return mConnectionRole;
970         }
971 
972         /**
973          * Get the connection Role of the connection, "Central" or "Peripheral".
974          *
975          * @param connectionRole connection Role of the connection
976          * @return the connection Role String
977          * @hide
978          */
979         @SystemApi
connectionRoleToString(int connectionRole)980         public static @NonNull String connectionRoleToString(int connectionRole) {
981             if (connectionRole == CONNECTION_ROLE_CENTRAL) {
982                 return "Central";
983             } else if (connectionRole == CONNECTION_ROLE_PERIPHERAL) {
984                 return "Peripheral";
985             } else {
986                 return "INVALID:" + connectionRole;
987             }
988         }
989 
990         /**
991          * Get the current transmit power level for the connection.
992          *
993          * @return the TX power level
994          * @hide
995          */
996         @SystemApi
getTxPowerLevel()997         public int getTxPowerLevel() {
998             return mTxPowerLevel;
999         }
1000 
1001         /**
1002          * Get the Received Signal Strength Indication (RSSI) value for the connection.
1003          *
1004          * @return the RSSI
1005          * @hide
1006          */
1007         @SystemApi
getRssi()1008         public int getRssi() {
1009             return mRssi;
1010         }
1011 
1012         /**
1013          * Get the Signal-to-Noise Ratio (SNR) value for the connection.
1014          *
1015          * @return the SNR
1016          * @hide
1017          */
1018         @SystemApi
getSnr()1019         public int getSnr() {
1020             return mSnr;
1021         }
1022 
1023         /**
1024          * Get the number of unused channels in AFH_channel_map.
1025          *
1026          * @return the number of unused channels
1027          * @hide
1028          */
1029         @SystemApi
getUnusedAfhChannelCount()1030         public int getUnusedAfhChannelCount() {
1031             return mUnusedAfhChannelCount;
1032         }
1033 
1034         /**
1035          * Get the number of the channels which are interfered and quality is bad but are still
1036          * selected for AFH.
1037          *
1038          * @return the number of the selected unideal channels
1039          * @hide
1040          */
1041         @SystemApi
getAfhSelectUnidealChannelCount()1042         public int getAfhSelectUnidealChannelCount() {
1043             return mAfhSelectUnidealChannelCount;
1044         }
1045 
1046         /**
1047          * Get the current link supervision timeout setting. time_ms: N * 0.625 ms (1 slot).
1048          *
1049          * @return link supervision timeout value
1050          * @hide
1051          */
1052         @SystemApi
getLsto()1053         public int getLsto() {
1054             return mLsto;
1055         }
1056 
1057         /**
1058          * Get the piconet clock for the specified Connection_Handle. time_ms: N * 0.3125 ms (1
1059          * Bluetooth Clock).
1060          *
1061          * @return the piconet clock
1062          * @hide
1063          */
1064         @SystemApi
getPiconetClock()1065         public long getPiconetClock() {
1066             return mPiconetClock;
1067         }
1068 
1069         /**
1070          * Get the count of retransmission.
1071          *
1072          * @return the count of retransmission
1073          * @hide
1074          */
1075         @SystemApi
getRetransmissionCount()1076         public long getRetransmissionCount() {
1077             return mRetransmissionCount;
1078         }
1079 
1080         /**
1081          * Get the count of no RX.
1082          *
1083          * @return the count of no RX
1084          * @hide
1085          */
1086         @SystemApi
getNoRxCount()1087         public long getNoRxCount() {
1088             return mNoRxCount;
1089         }
1090 
1091         /**
1092          * Get the count of NAK(Negative Acknowledge).
1093          *
1094          * @return the count of NAK
1095          * @hide
1096          */
1097         @SystemApi
getNakCount()1098         public long getNakCount() {
1099             return mNakCount;
1100         }
1101 
1102         /**
1103          * Get the timestamp of last TX ACK. time_ms: N * 0.3125 ms (1 Bluetooth Clock).
1104          *
1105          * @return the timestamp of last TX ACK
1106          * @hide
1107          */
1108         @SystemApi
getLastTxAckTimestamp()1109         public long getLastTxAckTimestamp() {
1110             return mLastTxAckTimestamp;
1111         }
1112 
1113         /**
1114          * Get the count of flow-off.
1115          *
1116          * @return the count of flow-off
1117          * @hide
1118          */
1119         @SystemApi
getFlowOffCount()1120         public long getFlowOffCount() {
1121             return mFlowOffCount;
1122         }
1123 
1124         /**
1125          * Get the timestamp of last flow-on.
1126          *
1127          * @return the timestamp of last flow-on
1128          * @hide
1129          */
1130         @SystemApi
getLastFlowOnTimestamp()1131         public long getLastFlowOnTimestamp() {
1132             return mLastFlowOnTimestamp;
1133         }
1134 
1135         /**
1136          * Get the buffer overflow count (how many bytes of TX data are dropped) since the last
1137          * event.
1138          *
1139          * @return the buffer overflow count
1140          * @hide
1141          */
1142         @SystemApi
getOverflowCount()1143         public long getOverflowCount() {
1144             return mOverflowCount;
1145         }
1146 
1147         /**
1148          * Get the buffer underflow count (in byte).
1149          *
1150          * @return the buffer underflow count
1151          * @hide
1152          */
1153         @SystemApi
getUnderflowCount()1154         public long getUnderflowCount() {
1155             return mUnderflowCount;
1156         }
1157 
1158         /**
1159          * Get the count of calibration failed items.
1160          *
1161          * @return the count of calibration failure
1162          * @hide
1163          */
1164         @SystemApi
getCalFailedItemCount()1165         public int getCalFailedItemCount() {
1166             return mCalFailedItemCount;
1167         }
1168 
1169         /**
1170          * Gets the total number of packets transmitted.
1171          *
1172          * @return the total number of transmitted packets
1173          * @hide
1174          */
1175         @FlaggedApi(Flags.FLAG_SUPPORT_BLUETOOTH_QUALITY_REPORT_V6)
1176         @SystemApi
getTxTotalPackets()1177         public long getTxTotalPackets() {
1178             return mTxTotalPackets;
1179         }
1180 
1181         /**
1182          * Gets the number of transmitted packets that did not receive an acknowledgment.
1183          *
1184          * @return the number of unacknowledged packets
1185          * @hide
1186          */
1187         @FlaggedApi(Flags.FLAG_SUPPORT_BLUETOOTH_QUALITY_REPORT_V6)
1188         @SystemApi
getTxUnackPackets()1189         public long getTxUnackPackets() {
1190             return mTxUnackPackets;
1191         }
1192 
1193         /**
1194          * Gets the number of packets that were not sent out by their flush point.
1195          *
1196          * @return the number of packets not sent due to flush
1197          * @hide
1198          */
1199         @FlaggedApi(Flags.FLAG_SUPPORT_BLUETOOTH_QUALITY_REPORT_V6)
1200         @SystemApi
getTxFlushPackets()1201         public long getTxFlushPackets() {
1202             return mTxFlushPackets;
1203         }
1204 
1205         /**
1206          * Gets the number of CIS (Connected Isochronous Stream) Data PDUs transmitted by the Link
1207          * Layer in the last subevent of a CIS event.
1208          *
1209          * @return the number of CIS Data PDUs transmitted in the last subevent
1210          * @hide
1211          */
1212         @FlaggedApi(Flags.FLAG_SUPPORT_BLUETOOTH_QUALITY_REPORT_V6)
1213         @SystemApi
getTxLastSubeventPackets()1214         public long getTxLastSubeventPackets() {
1215             return mTxLastSubeventPackets;
1216         }
1217 
1218         /**
1219          * Gets the number of received packets with CRC (Cyclic Redundancy Check) errors since the
1220          * last event.
1221          *
1222          * @return the number of packets received with CRC errors
1223          * @hide
1224          */
1225         @FlaggedApi(Flags.FLAG_SUPPORT_BLUETOOTH_QUALITY_REPORT_V6)
1226         @SystemApi
getCrcErrorPackets()1227         public long getCrcErrorPackets() {
1228             return mCrcErrorPackets;
1229         }
1230 
1231         /**
1232          * Gets the number of duplicate (retransmitted) packets received since the last event.
1233          *
1234          * @return the number of duplicate packets received
1235          * @hide
1236          */
1237         @FlaggedApi(Flags.FLAG_SUPPORT_BLUETOOTH_QUALITY_REPORT_V6)
1238         @SystemApi
getRxDupPackets()1239         public long getRxDupPackets() {
1240             return mRxDupPackets;
1241         }
1242 
1243         /**
1244          * Gets the number of unreceived packets. This value corresponds to the parameter of the LE
1245          * Read ISO Link Quality command.
1246          *
1247          * @return the number of unreceived packets
1248          * @hide
1249          */
1250         @FlaggedApi(Flags.FLAG_SUPPORT_BLUETOOTH_QUALITY_REPORT_V6)
1251         @SystemApi
getRxUnRecvPackets()1252         public long getRxUnRecvPackets() {
1253             return mRxUnRecvPackets;
1254         }
1255 
1256         /**
1257          * Gets the coexistence information mask.
1258          *
1259          * @return the coexistence information mask value
1260          * @hide
1261          */
1262         @FlaggedApi(Flags.FLAG_SUPPORT_BLUETOOTH_QUALITY_REPORT_V6)
1263         @SystemApi
getCoexInfoMask()1264         public int getCoexInfoMask() {
1265             return mCoexInfoMask;
1266         }
1267 
1268         @Override
describeContents()1269         public int describeContents() {
1270             return 0;
1271         }
1272 
1273         /**
1274          * Write BqrCommon to parcel.
1275          *
1276          * @hide
1277          */
1278         @SystemApi
1279         @Override
writeToParcel(@onNull Parcel dest, int flags)1280         public void writeToParcel(@NonNull Parcel dest, int flags) {
1281             dest.writeInt(mQualityReportId);
1282             dest.writeInt(mPacketType);
1283             dest.writeInt(mConnectionHandle);
1284             dest.writeInt(mConnectionRole);
1285             dest.writeInt(mTxPowerLevel);
1286             dest.writeInt(mRssi);
1287             dest.writeInt(mSnr);
1288             dest.writeInt(mUnusedAfhChannelCount);
1289             dest.writeInt(mAfhSelectUnidealChannelCount);
1290             dest.writeInt(mLsto);
1291             dest.writeLong(mPiconetClock);
1292             dest.writeLong(mRetransmissionCount);
1293             dest.writeLong(mNoRxCount);
1294             dest.writeLong(mNakCount);
1295             dest.writeLong(mLastTxAckTimestamp);
1296             dest.writeLong(mFlowOffCount);
1297             dest.writeLong(mLastFlowOnTimestamp);
1298             dest.writeLong(mOverflowCount);
1299             dest.writeLong(mUnderflowCount);
1300             BluetoothUtils.writeStringToParcel(dest, mAddr);
1301             dest.writeInt(mCalFailedItemCount);
1302             dest.writeLong(mTxTotalPackets);
1303             dest.writeLong(mTxUnackPackets);
1304             dest.writeLong(mTxFlushPackets);
1305             dest.writeLong(mTxLastSubeventPackets);
1306             dest.writeLong(mCrcErrorPackets);
1307             dest.writeLong(mRxDupPackets);
1308             dest.writeLong(mRxUnRecvPackets);
1309             dest.writeInt(mCoexInfoMask);
1310         }
1311 
1312         /** @hide */
1313         @SystemApi
1314         public static final @NonNull Parcelable.Creator<BqrCommon> CREATOR =
1315                 new Parcelable.Creator<BqrCommon>() {
1316                     public BqrCommon createFromParcel(Parcel in) {
1317                         return new BqrCommon(in);
1318                     }
1319 
1320                     public BqrCommon[] newArray(int size) {
1321                         return new BqrCommon[size];
1322                     }
1323                 };
1324 
1325         /** BqrCommon to String. */
1326         @Override
1327         @NonNull
toString()1328         public String toString() {
1329             String str;
1330             str =
1331                     "  BqrCommon: {\n"
1332                             + "    mQualityReportId: "
1333                             + qualityReportIdToString(getQualityReportId())
1334                             + "("
1335                             + String.format("0x%02X", mQualityReportId)
1336                             + ")"
1337                             + ", mPacketType: "
1338                             + packetTypeToString(mPacketType)
1339                             + "("
1340                             + String.format("0x%02X", mPacketType)
1341                             + ")"
1342                             + ", mConnectionHandle: "
1343                             + String.format("0x%04X", mConnectionHandle)
1344                             + ", mConnectionRole: "
1345                             + getConnectionRole()
1346                             + "("
1347                             + mConnectionRole
1348                             + ")"
1349                             + ", mTxPowerLevel: "
1350                             + mTxPowerLevel
1351                             + ", mRssi: "
1352                             + mRssi
1353                             + ", mSnr: "
1354                             + mSnr
1355                             + ", mUnusedAfhChannelCount: "
1356                             + mUnusedAfhChannelCount
1357                             + ",\n"
1358                             + "    mAfhSelectUnidealChannelCount: "
1359                             + mAfhSelectUnidealChannelCount
1360                             + ", mLsto: "
1361                             + mLsto
1362                             + ", mPiconetClock: "
1363                             + String.format("0x%08X", mPiconetClock)
1364                             + ", mRetransmissionCount: "
1365                             + mRetransmissionCount
1366                             + ", mNoRxCount: "
1367                             + mNoRxCount
1368                             + ", mNakCount: "
1369                             + mNakCount
1370                             + ", mLastTxAckTimestamp: "
1371                             + String.format("0x%08X", mLastTxAckTimestamp)
1372                             + ", mFlowOffCount: "
1373                             + mFlowOffCount
1374                             + ",\n"
1375                             + "    mLastFlowOnTimestamp: "
1376                             + String.format("0x%08X", mLastFlowOnTimestamp)
1377                             + ", mOverflowCount: "
1378                             + mOverflowCount
1379                             + ", mUnderflowCount: "
1380                             + mUnderflowCount
1381                             + ", mAddr: "
1382                             + mAddr
1383                             + ", mCalFailedItemCount: "
1384                             + mCalFailedItemCount
1385                             + ",\n"
1386                             + "    mTxTotalPackets: "
1387                             + mTxTotalPackets
1388                             + ", mTxUnackPackets: "
1389                             + mTxUnackPackets
1390                             + ", mTxFlushPackets: "
1391                             + mTxFlushPackets
1392                             + ", mTxLastSubeventPackets: "
1393                             + mTxLastSubeventPackets
1394                             + ", mCrcErrorPackets: "
1395                             + mCrcErrorPackets
1396                             + ", mRxDupPackets: "
1397                             + mRxDupPackets
1398                             + ", mRxUnRecvPackets: "
1399                             + mRxUnRecvPackets
1400                             + ", mCoexInfoMask: "
1401                             + mCoexInfoMask
1402                             + "\n  }";
1403 
1404             return str;
1405         }
1406     }
1407 
1408     /**
1409      * This class provides the System APIs to access the vendor specific part of Approaching LSTO
1410      * event.
1411      *
1412      * @hide
1413      */
1414     @SystemApi
1415     public static final class BqrVsLsto implements Parcelable {
1416         private static final String TAG =
1417                 BluetoothQualityReport.TAG + "." + BqrVsLsto.class.getSimpleName();
1418 
1419         private final int mConnState;
1420         private final long mBasebandStats;
1421         private final long mSlotsUsed;
1422         private final int mCxmDenials;
1423         private final int mTxSkipped;
1424         private final int mRfLoss;
1425         private final long mNativeClock;
1426         private final long mLastTxAckTimestamp;
1427 
BqrVsLsto(byte[] rawData, int offset)1428         private BqrVsLsto(byte[] rawData, int offset) {
1429             if (rawData == null || rawData.length <= offset) {
1430                 throw new IllegalArgumentException(TAG + ": BQR raw data length is abnormal.");
1431             }
1432 
1433             ByteBuffer bqrBuf =
1434                     ByteBuffer.wrap(rawData, offset, rawData.length - offset).asReadOnlyBuffer();
1435             bqrBuf.order(ByteOrder.LITTLE_ENDIAN);
1436 
1437             mConnState = bqrBuf.get() & 0xFF;
1438             mBasebandStats = bqrBuf.getInt() & 0xFFFFFFFFL;
1439             mSlotsUsed = bqrBuf.getInt() & 0xFFFFFFFFL;
1440             mCxmDenials = bqrBuf.getShort() & 0xFFFF;
1441             mTxSkipped = bqrBuf.getShort() & 0xFFFF;
1442             mRfLoss = bqrBuf.getShort() & 0xFFFF;
1443             mNativeClock = bqrBuf.getInt() & 0xFFFFFFFFL;
1444             mLastTxAckTimestamp = bqrBuf.getInt() & 0xFFFFFFFFL;
1445         }
1446 
BqrVsLsto(Parcel in)1447         private BqrVsLsto(Parcel in) {
1448             mConnState = in.readInt();
1449             mBasebandStats = in.readLong();
1450             mSlotsUsed = in.readLong();
1451             mCxmDenials = in.readInt();
1452             mTxSkipped = in.readInt();
1453             mRfLoss = in.readInt();
1454             mNativeClock = in.readLong();
1455             mLastTxAckTimestamp = in.readLong();
1456         }
1457 
1458         /**
1459          * Get the conn state of sco.
1460          *
1461          * @return the conn state
1462          * @hide
1463          */
1464         @SystemApi
getConnState()1465         public int getConnState() {
1466             return mConnState;
1467         }
1468 
1469         /**
1470          * Get the string of conn state of sco.
1471          *
1472          * @param connectionState connection state of sco
1473          * @return the string of conn state
1474          * @hide
1475          */
1476         @SystemApi
connStateToString(int connectionState)1477         public static @Nullable String connStateToString(int connectionState) {
1478             return ConnState.toString(connectionState);
1479         }
1480 
1481         /**
1482          * Get the baseband statistics.
1483          *
1484          * @return the baseband statistics
1485          * @hide
1486          */
1487         @SystemApi
getBasebandStats()1488         public long getBasebandStats() {
1489             return mBasebandStats;
1490         }
1491 
1492         /**
1493          * Get the count of slots allocated for current connection.
1494          *
1495          * @return the count of slots allocated for current connection
1496          * @hide
1497          */
1498         @SystemApi
getSlotsUsed()1499         public long getSlotsUsed() {
1500             return mSlotsUsed;
1501         }
1502 
1503         /**
1504          * Get the count of Coex denials.
1505          *
1506          * @return the count of CXM denials
1507          * @hide
1508          */
1509         @SystemApi
getCxmDenials()1510         public int getCxmDenials() {
1511             return mCxmDenials;
1512         }
1513 
1514         /**
1515          * Get the count of TX skipped when no poll from remote device.
1516          *
1517          * @return the count of TX skipped
1518          * @hide
1519          */
1520         @SystemApi
getTxSkipped()1521         public int getTxSkipped() {
1522             return mTxSkipped;
1523         }
1524 
1525         /**
1526          * Get the count of RF loss.
1527          *
1528          * @return the count of RF loss
1529          * @hide
1530          */
1531         @SystemApi
getRfLoss()1532         public int getRfLoss() {
1533             return mRfLoss;
1534         }
1535 
1536         /**
1537          * Get the timestamp when issue happened. time_ms: N * 0.3125 ms (1 Bluetooth Clock).
1538          *
1539          * @return the timestamp when issue happened
1540          * @hide
1541          */
1542         @SystemApi
getNativeClock()1543         public long getNativeClock() {
1544             return mNativeClock;
1545         }
1546 
1547         /**
1548          * Get the timestamp of last TX ACK. time_ms: N * 0.3125 ms (1 Bluetooth Clock).
1549          *
1550          * @return the timestamp of last TX ACK
1551          * @hide
1552          */
1553         @SystemApi
getLastTxAckTimestamp()1554         public long getLastTxAckTimestamp() {
1555             return mLastTxAckTimestamp;
1556         }
1557 
1558         @Override
describeContents()1559         public int describeContents() {
1560             return 0;
1561         }
1562 
1563         /**
1564          * Write BqrVsLsto to parcel.
1565          *
1566          * @hide
1567          */
1568         @SystemApi
1569         @Override
writeToParcel(@onNull Parcel dest, int flags)1570         public void writeToParcel(@NonNull Parcel dest, int flags) {
1571             dest.writeInt(mConnState);
1572             dest.writeLong(mBasebandStats);
1573             dest.writeLong(mSlotsUsed);
1574             dest.writeInt(mCxmDenials);
1575             dest.writeInt(mTxSkipped);
1576             dest.writeInt(mRfLoss);
1577             dest.writeLong(mNativeClock);
1578             dest.writeLong(mLastTxAckTimestamp);
1579         }
1580 
1581         /** @hide */
1582         @SystemApi
1583         public static final @NonNull Parcelable.Creator<BqrVsLsto> CREATOR =
1584                 new Parcelable.Creator<BqrVsLsto>() {
1585                     public BqrVsLsto createFromParcel(Parcel in) {
1586                         return new BqrVsLsto(in);
1587                     }
1588 
1589                     public BqrVsLsto[] newArray(int size) {
1590                         return new BqrVsLsto[size];
1591                     }
1592                 };
1593 
1594         /** BqrVsLsto to String. */
1595         @Override
1596         @NonNull
toString()1597         public String toString() {
1598             String str;
1599             str =
1600                     "  BqrVsLsto: {\n"
1601                             + "    mConnState: "
1602                             + connStateToString(getConnState())
1603                             + "("
1604                             + String.format("0x%02X", mConnState)
1605                             + ")"
1606                             + ", mBasebandStats: "
1607                             + String.format("0x%08X", mBasebandStats)
1608                             + ", mSlotsUsed: "
1609                             + mSlotsUsed
1610                             + ", mCxmDenials: "
1611                             + mCxmDenials
1612                             + ", mTxSkipped: "
1613                             + mTxSkipped
1614                             + ", mRfLoss: "
1615                             + mRfLoss
1616                             + ", mNativeClock: "
1617                             + String.format("0x%08X", mNativeClock)
1618                             + ", mLastTxAckTimestamp: "
1619                             + String.format("0x%08X", mLastTxAckTimestamp)
1620                             + "\n  }";
1621 
1622             return str;
1623         }
1624     }
1625 
1626     /**
1627      * This class provides the System APIs to access the vendor specific part of A2dp choppy event.
1628      *
1629      * @hide
1630      */
1631     @SystemApi
1632     public static final class BqrVsA2dpChoppy implements Parcelable {
1633         private static final String TAG =
1634                 BluetoothQualityReport.TAG + "." + BqrVsA2dpChoppy.class.getSimpleName();
1635 
1636         private final long mArrivalTime;
1637         private final long mScheduleTime;
1638         private final int mGlitchCount;
1639         private final int mTxCxmDenials;
1640         private final int mRxCxmDenials;
1641         private final int mAclTxQueueLength;
1642         private final int mLinkQuality;
1643 
BqrVsA2dpChoppy(byte[] rawData, int offset)1644         private BqrVsA2dpChoppy(byte[] rawData, int offset) {
1645             if (rawData == null || rawData.length <= offset) {
1646                 throw new IllegalArgumentException(TAG + ": BQR raw data length is abnormal.");
1647             }
1648 
1649             ByteBuffer bqrBuf =
1650                     ByteBuffer.wrap(rawData, offset, rawData.length - offset).asReadOnlyBuffer();
1651             bqrBuf.order(ByteOrder.LITTLE_ENDIAN);
1652 
1653             mArrivalTime = bqrBuf.getInt() & 0xFFFFFFFFL;
1654             mScheduleTime = bqrBuf.getInt() & 0xFFFFFFFFL;
1655             mGlitchCount = bqrBuf.getShort() & 0xFFFF;
1656             mTxCxmDenials = bqrBuf.getShort() & 0xFFFF;
1657             mRxCxmDenials = bqrBuf.getShort() & 0xFFFF;
1658             mAclTxQueueLength = bqrBuf.get() & 0xFF;
1659             mLinkQuality = bqrBuf.get() & 0xFF;
1660         }
1661 
BqrVsA2dpChoppy(Parcel in)1662         private BqrVsA2dpChoppy(Parcel in) {
1663             mArrivalTime = in.readLong();
1664             mScheduleTime = in.readLong();
1665             mGlitchCount = in.readInt();
1666             mTxCxmDenials = in.readInt();
1667             mRxCxmDenials = in.readInt();
1668             mAclTxQueueLength = in.readInt();
1669             mLinkQuality = in.readInt();
1670         }
1671 
1672         /**
1673          * Get the timestamp of a2dp packet arrived. time_ms: N * 0.3125 ms (1 Bluetooth Clock).
1674          *
1675          * @return the timestamp of a2dp packet arrived
1676          * @hide
1677          */
1678         @SystemApi
getArrivalTime()1679         public long getArrivalTime() {
1680             return mArrivalTime;
1681         }
1682 
1683         /**
1684          * Get the timestamp of a2dp packet scheduled. time_ms: N * 0.3125 ms (1 Bluetooth Clock).
1685          *
1686          * @return the timestamp of a2dp packet scheduled
1687          * @hide
1688          */
1689         @SystemApi
getScheduleTime()1690         public long getScheduleTime() {
1691             return mScheduleTime;
1692         }
1693 
1694         /**
1695          * Get the a2dp glitch count since the last event.
1696          *
1697          * @return the a2dp glitch count
1698          * @hide
1699          */
1700         @SystemApi
getGlitchCount()1701         public int getGlitchCount() {
1702             return mGlitchCount;
1703         }
1704 
1705         /**
1706          * Get the count of Coex TX denials.
1707          *
1708          * @return the count of Coex TX denials
1709          * @hide
1710          */
1711         @SystemApi
getTxCxmDenials()1712         public int getTxCxmDenials() {
1713             return mTxCxmDenials;
1714         }
1715 
1716         /**
1717          * Get the count of Coex RX denials.
1718          *
1719          * @return the count of Coex RX denials
1720          * @hide
1721          */
1722         @SystemApi
getRxCxmDenials()1723         public int getRxCxmDenials() {
1724             return mRxCxmDenials;
1725         }
1726 
1727         /**
1728          * Get the ACL queue length which are pending TX in FW.
1729          *
1730          * @return the ACL queue length
1731          * @hide
1732          */
1733         @SystemApi
getAclTxQueueLength()1734         public int getAclTxQueueLength() {
1735             return mAclTxQueueLength;
1736         }
1737 
1738         /**
1739          * Get the link quality for the current connection.
1740          *
1741          * @return the link quality
1742          * @hide
1743          */
1744         @SystemApi
getLinkQuality()1745         public int getLinkQuality() {
1746             return mLinkQuality;
1747         }
1748 
1749         /**
1750          * Get the string of link quality for the current connection.
1751          *
1752          * @param linkQuality link quality for the current connection
1753          * @return the string of link quality
1754          * @hide
1755          */
1756         @SystemApi
linkQualityToString(int linkQuality)1757         public static @Nullable String linkQualityToString(int linkQuality) {
1758             LinkQuality q = LinkQuality.fromOrdinal(linkQuality);
1759             return q.toString();
1760         }
1761 
1762         @Override
describeContents()1763         public int describeContents() {
1764             return 0;
1765         }
1766 
1767         /**
1768          * Write BqrVsA2dpChoppy to parcel.
1769          *
1770          * @hide
1771          */
1772         @SystemApi
1773         @Override
writeToParcel(@onNull Parcel dest, int flags)1774         public void writeToParcel(@NonNull Parcel dest, int flags) {
1775             dest.writeLong(mArrivalTime);
1776             dest.writeLong(mScheduleTime);
1777             dest.writeInt(mGlitchCount);
1778             dest.writeInt(mTxCxmDenials);
1779             dest.writeInt(mRxCxmDenials);
1780             dest.writeInt(mAclTxQueueLength);
1781             dest.writeInt(mLinkQuality);
1782         }
1783 
1784         /** @hide */
1785         @SystemApi
1786         public static final @NonNull Parcelable.Creator<BqrVsA2dpChoppy> CREATOR =
1787                 new Parcelable.Creator<BqrVsA2dpChoppy>() {
1788                     public BqrVsA2dpChoppy createFromParcel(Parcel in) {
1789                         return new BqrVsA2dpChoppy(in);
1790                     }
1791 
1792                     public BqrVsA2dpChoppy[] newArray(int size) {
1793                         return new BqrVsA2dpChoppy[size];
1794                     }
1795                 };
1796 
1797         /** BqrVsA2dpChoppy to String. */
1798         @Override
1799         @NonNull
toString()1800         public String toString() {
1801             String str;
1802             str =
1803                     "  BqrVsA2dpChoppy: {\n"
1804                             + "    mArrivalTime: "
1805                             + String.format("0x%08X", mArrivalTime)
1806                             + ", mScheduleTime: "
1807                             + String.format("0x%08X", mScheduleTime)
1808                             + ", mGlitchCount: "
1809                             + mGlitchCount
1810                             + ", mTxCxmDenials: "
1811                             + mTxCxmDenials
1812                             + ", mRxCxmDenials: "
1813                             + mRxCxmDenials
1814                             + ", mAclTxQueueLength: "
1815                             + mAclTxQueueLength
1816                             + ", mLinkQuality: "
1817                             + linkQualityToString(mLinkQuality)
1818                             + "("
1819                             + String.format("0x%02X", mLinkQuality)
1820                             + ")"
1821                             + "\n  }";
1822 
1823             return str;
1824         }
1825     }
1826 
1827     /**
1828      * This class provides the System APIs to access the vendor specific part of SCO choppy event.
1829      *
1830      * @hide
1831      */
1832     @SystemApi
1833     public static final class BqrVsScoChoppy implements Parcelable {
1834         private static final String TAG =
1835                 BluetoothQualityReport.TAG + "." + BqrVsScoChoppy.class.getSimpleName();
1836 
1837         private final int mGlitchCount;
1838         private final int mIntervalEsco;
1839         private final int mWindowEsco;
1840         private final int mAirFormat;
1841         private final int mInstanceCount;
1842         private final int mTxCxmDenials;
1843         private final int mRxCxmDenials;
1844         private final int mTxAbortCount;
1845         private final int mLateDispatch;
1846         private final int mMicIntrMiss;
1847         private final int mLpaIntrMiss;
1848         private final int mSprIntrMiss;
1849         private final int mPlcFillCount;
1850         private final int mPlcDiscardCount;
1851         private final int mMissedInstanceCount;
1852         private final int mTxRetransmitSlotCount;
1853         private final int mRxRetransmitSlotCount;
1854         private final int mGoodRxFrameCount;
1855 
BqrVsScoChoppy(byte[] rawData, int offset)1856         private BqrVsScoChoppy(byte[] rawData, int offset) {
1857             if (rawData == null || rawData.length <= offset) {
1858                 throw new IllegalArgumentException(TAG + ": BQR raw data length is abnormal.");
1859             }
1860 
1861             ByteBuffer bqrBuf =
1862                     ByteBuffer.wrap(rawData, offset, rawData.length - offset).asReadOnlyBuffer();
1863             bqrBuf.order(ByteOrder.LITTLE_ENDIAN);
1864 
1865             mGlitchCount = bqrBuf.getShort() & 0xFFFF;
1866             mIntervalEsco = bqrBuf.get() & 0xFF;
1867             mWindowEsco = bqrBuf.get() & 0xFF;
1868             mAirFormat = bqrBuf.get() & 0xFF;
1869             mInstanceCount = bqrBuf.getShort() & 0xFFFF;
1870             mTxCxmDenials = bqrBuf.getShort() & 0xFFFF;
1871             mRxCxmDenials = bqrBuf.getShort() & 0xFFFF;
1872             mTxAbortCount = bqrBuf.getShort() & 0xFFFF;
1873             mLateDispatch = bqrBuf.getShort() & 0xFFFF;
1874             mMicIntrMiss = bqrBuf.getShort() & 0xFFFF;
1875             mLpaIntrMiss = bqrBuf.getShort() & 0xFFFF;
1876             mSprIntrMiss = bqrBuf.getShort() & 0xFFFF;
1877             mPlcFillCount = bqrBuf.getShort() & 0xFFFF;
1878             mPlcDiscardCount = bqrBuf.getShort() & 0xFFFF;
1879             mMissedInstanceCount = bqrBuf.getShort() & 0xFFFF;
1880             mTxRetransmitSlotCount = bqrBuf.getShort() & 0xFFFF;
1881             mRxRetransmitSlotCount = bqrBuf.getShort() & 0xFFFF;
1882             mGoodRxFrameCount = bqrBuf.getShort() & 0xFFFF;
1883         }
1884 
BqrVsScoChoppy(Parcel in)1885         private BqrVsScoChoppy(Parcel in) {
1886             mGlitchCount = in.readInt();
1887             mIntervalEsco = in.readInt();
1888             mWindowEsco = in.readInt();
1889             mAirFormat = in.readInt();
1890             mInstanceCount = in.readInt();
1891             mTxCxmDenials = in.readInt();
1892             mRxCxmDenials = in.readInt();
1893             mTxAbortCount = in.readInt();
1894             mLateDispatch = in.readInt();
1895             mMicIntrMiss = in.readInt();
1896             mLpaIntrMiss = in.readInt();
1897             mSprIntrMiss = in.readInt();
1898             mPlcFillCount = in.readInt();
1899             mPlcDiscardCount = in.readInt();
1900             mMissedInstanceCount = in.readInt();
1901             mTxRetransmitSlotCount = in.readInt();
1902             mRxRetransmitSlotCount = in.readInt();
1903             mGoodRxFrameCount = in.readInt();
1904         }
1905 
1906         /**
1907          * Get the sco glitch count since the last event.
1908          *
1909          * @return the sco glitch count
1910          * @hide
1911          */
1912         @SystemApi
getGlitchCount()1913         public int getGlitchCount() {
1914             return mGlitchCount;
1915         }
1916 
1917         /**
1918          * Get ESCO interval in slots. It is the value of Transmission_Interval parameter in
1919          * Synchronous Connection Complete event.
1920          *
1921          * @return ESCO interval in slots
1922          * @hide
1923          */
1924         @SystemApi
getIntervalEsco()1925         public int getIntervalEsco() {
1926             return mIntervalEsco;
1927         }
1928 
1929         /**
1930          * Get ESCO window in slots. It is the value of Retransmission Window parameter in
1931          * Synchronous Connection Complete event.
1932          *
1933          * @return ESCO window in slots
1934          * @hide
1935          */
1936         @SystemApi
getWindowEsco()1937         public int getWindowEsco() {
1938             return mWindowEsco;
1939         }
1940 
1941         /**
1942          * Get the air mode. It is the value of Air Mode parameter in Synchronous Connection
1943          * Complete event.
1944          *
1945          * @return the air mode
1946          * @hide
1947          */
1948         @SystemApi
getAirFormat()1949         public int getAirFormat() {
1950             return mAirFormat;
1951         }
1952 
1953         /**
1954          * Get the string of air mode.
1955          *
1956          * @param airFormat the value of Air Mode parameter in Synchronous Connection Complete event
1957          * @return the string of air mode
1958          * @hide
1959          */
1960         @SystemApi
airFormatToString(int airFormat)1961         public static @Nullable String airFormatToString(int airFormat) {
1962             AirMode m = AirMode.fromOrdinal(airFormat);
1963             return m.toString();
1964         }
1965 
1966         /**
1967          * Get the xSCO instance count.
1968          *
1969          * @return the xSCO instance count
1970          * @hide
1971          */
1972         @SystemApi
getInstanceCount()1973         public int getInstanceCount() {
1974             return mInstanceCount;
1975         }
1976 
1977         /**
1978          * Get the count of Coex TX denials.
1979          *
1980          * @return the count of Coex TX denials
1981          * @hide
1982          */
1983         @SystemApi
getTxCxmDenials()1984         public int getTxCxmDenials() {
1985             return mTxCxmDenials;
1986         }
1987 
1988         /**
1989          * Get the count of Coex RX denials.
1990          *
1991          * @return the count of Coex RX denials
1992          * @hide
1993          */
1994         @SystemApi
getRxCxmDenials()1995         public int getRxCxmDenials() {
1996             return mRxCxmDenials;
1997         }
1998 
1999         /**
2000          * Get the count of sco packets aborted.
2001          *
2002          * @return the count of sco packets aborted
2003          * @hide
2004          */
2005         @SystemApi
getTxAbortCount()2006         public int getTxAbortCount() {
2007             return mTxAbortCount;
2008         }
2009 
2010         /**
2011          * Get the count of sco packets dispatched late.
2012          *
2013          * @return the count of sco packets dispatched late
2014          * @hide
2015          */
2016         @SystemApi
getLateDispatch()2017         public int getLateDispatch() {
2018             return mLateDispatch;
2019         }
2020 
2021         /**
2022          * Get the count of missed Mic interrupts.
2023          *
2024          * @return the count of missed Mic interrupts
2025          * @hide
2026          */
2027         @SystemApi
getMicIntrMiss()2028         public int getMicIntrMiss() {
2029             return mMicIntrMiss;
2030         }
2031 
2032         /**
2033          * Get the count of missed LPA interrupts.
2034          *
2035          * @return the count of missed LPA interrupts
2036          * @hide
2037          */
2038         @SystemApi
getLpaIntrMiss()2039         public int getLpaIntrMiss() {
2040             return mLpaIntrMiss;
2041         }
2042 
2043         /**
2044          * Get the count of missed Speaker interrupts.
2045          *
2046          * @return the count of missed Speaker interrupts
2047          * @hide
2048          */
2049         @SystemApi
getSprIntrMiss()2050         public int getSprIntrMiss() {
2051             return mSprIntrMiss;
2052         }
2053 
2054         /**
2055          * Get the count of packet loss concealment filled.
2056          *
2057          * @return the count of packet loss concealment filled
2058          * @hide
2059          */
2060         @SystemApi
getPlcFillCount()2061         public int getPlcFillCount() {
2062             return mPlcFillCount;
2063         }
2064 
2065         /**
2066          * Get the count of packet loss concealment discarded.
2067          *
2068          * @return the count of packet loss concealment discarded
2069          * @hide
2070          */
2071         @SystemApi
getPlcDiscardCount()2072         public int getPlcDiscardCount() {
2073             return mPlcDiscardCount;
2074         }
2075 
2076         /**
2077          * Get the count of sco instances missed.
2078          *
2079          * @return the count of sco instances missed
2080          * @hide
2081          */
2082         @SystemApi
getMissedInstanceCount()2083         public int getMissedInstanceCount() {
2084             return mMissedInstanceCount;
2085         }
2086 
2087         /**
2088          * Get the count of slots for Tx retransmission.
2089          *
2090          * @return the count of slots for Tx retransmission
2091          * @hide
2092          */
2093         @SystemApi
getTxRetransmitSlotCount()2094         public int getTxRetransmitSlotCount() {
2095             return mTxRetransmitSlotCount;
2096         }
2097 
2098         /**
2099          * Get the count of slots for Rx retransmission.
2100          *
2101          * @return the count of slots for Rx retransmission
2102          * @hide
2103          */
2104         @SystemApi
getRxRetransmitSlotCount()2105         public int getRxRetransmitSlotCount() {
2106             return mRxRetransmitSlotCount;
2107         }
2108 
2109         /**
2110          * Get the count of Rx good packets
2111          *
2112          * @return the count of Rx good packets
2113          * @hide
2114          */
2115         @SystemApi
getGoodRxFrameCount()2116         public int getGoodRxFrameCount() {
2117             return mGoodRxFrameCount;
2118         }
2119 
2120         @Override
describeContents()2121         public int describeContents() {
2122             return 0;
2123         }
2124 
2125         /**
2126          * Write BqrVsScoChoppy to parcel.
2127          *
2128          * @hide
2129          */
2130         @SystemApi
2131         @Override
writeToParcel(@onNull Parcel dest, int flags)2132         public void writeToParcel(@NonNull Parcel dest, int flags) {
2133             dest.writeInt(mGlitchCount);
2134             dest.writeInt(mIntervalEsco);
2135             dest.writeInt(mWindowEsco);
2136             dest.writeInt(mAirFormat);
2137             dest.writeInt(mInstanceCount);
2138             dest.writeInt(mTxCxmDenials);
2139             dest.writeInt(mRxCxmDenials);
2140             dest.writeInt(mTxAbortCount);
2141             dest.writeInt(mLateDispatch);
2142             dest.writeInt(mMicIntrMiss);
2143             dest.writeInt(mLpaIntrMiss);
2144             dest.writeInt(mSprIntrMiss);
2145             dest.writeInt(mPlcFillCount);
2146             dest.writeInt(mPlcDiscardCount);
2147             dest.writeInt(mMissedInstanceCount);
2148             dest.writeInt(mTxRetransmitSlotCount);
2149             dest.writeInt(mRxRetransmitSlotCount);
2150             dest.writeInt(mGoodRxFrameCount);
2151         }
2152 
2153         /** @hide */
2154         @SystemApi
2155         public static final @NonNull Parcelable.Creator<BqrVsScoChoppy> CREATOR =
2156                 new Parcelable.Creator<BqrVsScoChoppy>() {
2157                     public BqrVsScoChoppy createFromParcel(Parcel in) {
2158                         return new BqrVsScoChoppy(in);
2159                     }
2160 
2161                     public BqrVsScoChoppy[] newArray(int size) {
2162                         return new BqrVsScoChoppy[size];
2163                     }
2164                 };
2165 
2166         /** BqrVsScoChoppy to String. */
2167         @Override
2168         @NonNull
toString()2169         public String toString() {
2170             String str;
2171             str =
2172                     "  BqrVsScoChoppy: {\n"
2173                             + "    mGlitchCount: "
2174                             + mGlitchCount
2175                             + ", mIntervalEsco: "
2176                             + mIntervalEsco
2177                             + ", mWindowEsco: "
2178                             + mWindowEsco
2179                             + ", mAirFormat: "
2180                             + airFormatToString(mAirFormat)
2181                             + "("
2182                             + String.format("0x%02X", mAirFormat)
2183                             + ")"
2184                             + ", mInstanceCount: "
2185                             + mInstanceCount
2186                             + ", mTxCxmDenials: "
2187                             + mTxCxmDenials
2188                             + ", mRxCxmDenials: "
2189                             + mRxCxmDenials
2190                             + ", mTxAbortCount: "
2191                             + mTxAbortCount
2192                             + ",\n"
2193                             + "    mLateDispatch: "
2194                             + mLateDispatch
2195                             + ", mMicIntrMiss: "
2196                             + mMicIntrMiss
2197                             + ", mLpaIntrMiss: "
2198                             + mLpaIntrMiss
2199                             + ", mSprIntrMiss: "
2200                             + mSprIntrMiss
2201                             + ", mPlcFillCount: "
2202                             + mPlcFillCount
2203                             + ", mPlcDiscardCount: "
2204                             + mPlcDiscardCount
2205                             + ", mMissedInstanceCount: "
2206                             + mMissedInstanceCount
2207                             + ", mTxRetransmitSlotCount: "
2208                             + mTxRetransmitSlotCount
2209                             + ",\n"
2210                             + "    mRxRetransmitSlotCount: "
2211                             + mRxRetransmitSlotCount
2212                             + ", mGoodRxFrameCount: "
2213                             + mGoodRxFrameCount
2214                             + "\n  }";
2215 
2216             return str;
2217         }
2218     }
2219 
2220     /**
2221      * This class provides the System APIs to access the Connect fail event.
2222      *
2223      * @hide
2224      */
2225     @SystemApi
2226     public static final class BqrConnectFail implements Parcelable {
2227         private static final String TAG =
2228                 BluetoothQualityReport.TAG + "." + BqrConnectFail.class.getSimpleName();
2229 
2230         /**
2231          * Connect Fail reason: No error.
2232          *
2233          * @hide
2234          */
2235         @SystemApi public static final int CONNECT_FAIL_ID_NO_ERROR = 0x00;
2236 
2237         /**
2238          * Connect Fail reason: Page timeout.
2239          *
2240          * @hide
2241          */
2242         @SystemApi public static final int CONNECT_FAIL_ID_PAGE_TIMEOUT = 0x04;
2243 
2244         /**
2245          * Connect Fail reason: Connection timeout.
2246          *
2247          * @hide
2248          */
2249         @SystemApi public static final int CONNECT_FAIL_ID_CONNECTION_TIMEOUT = 0x08;
2250 
2251         /**
2252          * Connect Fail reason: ACL already exists.
2253          *
2254          * @hide
2255          */
2256         @SystemApi public static final int CONNECT_FAIL_ID_ACL_ALREADY_EXIST = 0x0b;
2257 
2258         /**
2259          * Connect Fail reason: Controller busy.
2260          *
2261          * @hide
2262          */
2263         @SystemApi public static final int CONNECT_FAIL_ID_CONTROLLER_BUSY = 0x3a;
2264 
2265         /** @hide */
2266         @Retention(RetentionPolicy.SOURCE)
2267         @IntDef(
2268                 prefix = {"CONNECT_FAIL_ID"},
2269                 value = {
2270                     CONNECT_FAIL_ID_NO_ERROR,
2271                     CONNECT_FAIL_ID_PAGE_TIMEOUT,
2272                     CONNECT_FAIL_ID_CONNECTION_TIMEOUT,
2273                     CONNECT_FAIL_ID_ACL_ALREADY_EXIST,
2274                     CONNECT_FAIL_ID_CONTROLLER_BUSY,
2275                 })
2276         public @interface ConnectFailId {}
2277 
2278         private final int mFailReason;
2279 
BqrConnectFail(byte[] rawData, int offset)2280         private BqrConnectFail(byte[] rawData, int offset) {
2281             if (rawData == null || rawData.length <= offset) {
2282                 throw new IllegalArgumentException(TAG + ": BQR raw data length is abnormal.");
2283             }
2284 
2285             ByteBuffer bqrBuf =
2286                     ByteBuffer.wrap(rawData, offset, rawData.length - offset).asReadOnlyBuffer();
2287             bqrBuf.order(ByteOrder.LITTLE_ENDIAN);
2288 
2289             mFailReason = bqrBuf.get() & 0xFF;
2290         }
2291 
BqrConnectFail(Parcel in)2292         private BqrConnectFail(Parcel in) {
2293             mFailReason = in.readInt();
2294         }
2295 
2296         /**
2297          * Get the fail reason.
2298          *
2299          * @return the fail reason
2300          * @hide
2301          */
2302         @SystemApi
2303         @ConnectFailId
getFailReason()2304         public int getFailReason() {
2305             return mFailReason;
2306         }
2307 
2308         @Override
describeContents()2309         public int describeContents() {
2310             return 0;
2311         }
2312 
2313         /**
2314          * Write BqrConnectFail to parcel.
2315          *
2316          * @hide
2317          */
2318         @SystemApi
2319         @Override
writeToParcel(@onNull Parcel dest, int flags)2320         public void writeToParcel(@NonNull Parcel dest, int flags) {
2321             dest.writeInt(mFailReason);
2322         }
2323 
2324         /** @hide */
2325         @SystemApi
2326         public static final @NonNull Parcelable.Creator<BqrConnectFail> CREATOR =
2327                 new Parcelable.Creator<BqrConnectFail>() {
2328                     public BqrConnectFail createFromParcel(Parcel in) {
2329                         return new BqrConnectFail(in);
2330                     }
2331 
2332                     public BqrConnectFail[] newArray(int size) {
2333                         return new BqrConnectFail[size];
2334                     }
2335                 };
2336 
2337         /**
2338          * Get the string of the Connect Fail ID.
2339          *
2340          * @param id the connect fail reason
2341          * @return the string of the id
2342          * @hide
2343          */
2344         @SystemApi
connectFailIdToString(@onnectFailId int id)2345         public static @NonNull String connectFailIdToString(@ConnectFailId int id) {
2346             switch (id) {
2347                 case CONNECT_FAIL_ID_NO_ERROR:
2348                     return "No error";
2349                 case CONNECT_FAIL_ID_PAGE_TIMEOUT:
2350                     return "Page Timeout";
2351                 case CONNECT_FAIL_ID_CONNECTION_TIMEOUT:
2352                     return "Connection Timeout";
2353                 case CONNECT_FAIL_ID_ACL_ALREADY_EXIST:
2354                     return "ACL already exists";
2355                 case CONNECT_FAIL_ID_CONTROLLER_BUSY:
2356                     return "Controller busy";
2357                 default:
2358                     return "INVALID";
2359             }
2360         }
2361 
2362         /** BqrConnectFail to String. */
2363         @Override
2364         @NonNull
toString()2365         public String toString() {
2366             String str;
2367             str =
2368                     "  BqrConnectFail: {\n"
2369                             + "    mFailReason: "
2370                             + connectFailIdToString(mFailReason)
2371                             + " ("
2372                             + String.format("0x%02X", mFailReason)
2373                             + ")"
2374                             + "\n  }";
2375 
2376             return str;
2377         }
2378     }
2379 
2380     /**
2381      * This class provides APIs to access the Energy Monitoring events from the Bluetooth Quality
2382      * Report. It includes detailed information about the energy consumption of various Bluetooth
2383      * operations, such as transmit and receive times for both BR/EDR and LE connections, as well as
2384      * time spent in different power states.
2385      *
2386      * @hide
2387      */
2388     @FlaggedApi(Flags.FLAG_SUPPORT_BLUETOOTH_QUALITY_REPORT_V6)
2389     @SystemApi
2390     public static final class BqrEnergyMonitor implements Parcelable {
2391         private static final String TAG =
2392                 BluetoothQualityReport.TAG + "." + BqrEnergyMonitor.class.getSimpleName();
2393 
2394         private final int mAvgCurrentConsume;
2395         private final long mIdleTotalTime;
2396         private final long mIdleStateEnterCount;
2397         private final long mActiveTotalTime;
2398         private final long mActiveStateEnterCount;
2399         private final long mBredrTxTotalTime;
2400         private final long mBredrTxStateEnterCount;
2401         private final int mBredrTxAvgPowerLevel;
2402         private final long mBredrRxTotalTime;
2403         private final long mBredrRxStateEnterCount;
2404         private final long mLeTxTotalTime;
2405         private final long mLeTxStateEnterCount;
2406         private final int mLeTxAvgPowerLevel;
2407         private final long mLeRxTotalTime;
2408         private final long mLeRxStateEnterCount;
2409         private final long mReportTotalTime;
2410         private final long mRxActiveOneChainTime;
2411         private final long mRxActiveTwoChainTime;
2412         private final long mTxiPaActiveOneChainTime;
2413         private final long mTxiPaActiveTwoChainTime;
2414         private final long mTxePaActiveOneChainTime;
2415         private final long mTxePaActiveTwoChainTime;
2416 
BqrEnergyMonitor(byte[] rawData, int offset)2417         private BqrEnergyMonitor(byte[] rawData, int offset) {
2418             if (rawData == null || rawData.length <= offset) {
2419                 throw new IllegalArgumentException(
2420                         TAG + ": BQR EnergyMonitor raw data length is abnormal.");
2421             }
2422 
2423             ByteBuffer bqrBuf =
2424                     ByteBuffer.wrap(rawData, offset, rawData.length - offset).asReadOnlyBuffer();
2425             bqrBuf.order(ByteOrder.LITTLE_ENDIAN);
2426 
2427             mAvgCurrentConsume = bqrBuf.getShort() & 0xFFFF;
2428             mIdleTotalTime = bqrBuf.getInt() & 0xFFFFFFFFL;
2429             mIdleStateEnterCount = bqrBuf.getInt() & 0xFFFFFFFFL;
2430             mActiveTotalTime = bqrBuf.getInt() & 0xFFFFFFFFL;
2431             mActiveStateEnterCount = bqrBuf.getInt() & 0xFFFFFFFFL;
2432             mBredrTxTotalTime = bqrBuf.getInt() & 0xFFFFFFFFL;
2433             mBredrTxStateEnterCount = bqrBuf.getInt() & 0xFFFFFFFFL;
2434             mBredrTxAvgPowerLevel = bqrBuf.get() & 0xFF;
2435             mBredrRxTotalTime = bqrBuf.getInt() & 0xFFFFFFFFL;
2436             mBredrRxStateEnterCount = bqrBuf.getInt() & 0xFFFFFFFFL;
2437             mLeTxTotalTime = bqrBuf.getInt() & 0xFFFFFFFFL;
2438             mLeTxStateEnterCount = bqrBuf.getInt() & 0xFFFFFFFFL;
2439             mLeTxAvgPowerLevel = bqrBuf.get() & 0xFF;
2440             mLeRxTotalTime = bqrBuf.getInt() & 0xFFFFFFFFL;
2441             mLeRxStateEnterCount = bqrBuf.getInt() & 0xFFFFFFFFL;
2442             mReportTotalTime = bqrBuf.getInt() & 0xFFFFFFFFL;
2443             mRxActiveOneChainTime = bqrBuf.getInt() & 0xFFFFFFFFL;
2444             mRxActiveTwoChainTime = bqrBuf.getInt() & 0xFFFFFFFFL;
2445             mTxiPaActiveOneChainTime = bqrBuf.getInt() & 0xFFFFFFFFL;
2446             mTxiPaActiveTwoChainTime = bqrBuf.getInt() & 0xFFFFFFFFL;
2447             mTxePaActiveOneChainTime = bqrBuf.getInt() & 0xFFFFFFFFL;
2448             mTxePaActiveTwoChainTime = bqrBuf.getInt() & 0xFFFFFFFFL;
2449         }
2450 
BqrEnergyMonitor(Parcel in)2451         private BqrEnergyMonitor(Parcel in) {
2452             mAvgCurrentConsume = in.readInt();
2453             mIdleTotalTime = in.readLong();
2454             mIdleStateEnterCount = in.readLong();
2455             mActiveTotalTime = in.readLong();
2456             mActiveStateEnterCount = in.readLong();
2457             mBredrTxTotalTime = in.readLong();
2458             mBredrTxStateEnterCount = in.readLong();
2459             mBredrTxAvgPowerLevel = in.readInt();
2460             mBredrRxTotalTime = in.readLong();
2461             mBredrRxStateEnterCount = in.readLong();
2462             mLeTxTotalTime = in.readLong();
2463             mLeTxStateEnterCount = in.readLong();
2464             mLeTxAvgPowerLevel = in.readInt();
2465             mLeRxTotalTime = in.readLong();
2466             mLeRxStateEnterCount = in.readLong();
2467             mReportTotalTime = in.readLong();
2468             mRxActiveOneChainTime = in.readLong();
2469             mRxActiveTwoChainTime = in.readLong();
2470             mTxiPaActiveOneChainTime = in.readLong();
2471             mTxiPaActiveTwoChainTime = in.readLong();
2472             mTxePaActiveOneChainTime = in.readLong();
2473             mTxePaActiveTwoChainTime = in.readLong();
2474         }
2475 
2476         /**
2477          * Gets the average current consumption of all activities consumed by the controller in
2478          * microamps.
2479          *
2480          * @return the average current consumption in microamps
2481          * @hide
2482          */
2483         @SystemApi
getAverageCurrentConsumptionMicroamps()2484         public int getAverageCurrentConsumptionMicroamps() {
2485             return mAvgCurrentConsume;
2486         }
2487 
2488         /**
2489          * Gets the total time the controller has spent in the idle state (low power states, sleep)
2490          * in milliseconds.
2491          *
2492          * @return the total time in the idle state in milliseconds
2493          * @hide
2494          */
2495         @SystemApi
2496         @DurationMillisLong
getIdleStateTotalTimeMillis()2497         public long getIdleStateTotalTimeMillis() {
2498             return mIdleTotalTime;
2499         }
2500 
2501         /**
2502          * Gets the number of times the controller has entered the idle state.
2503          *
2504          * @return the number of times the controller has entered the idle state
2505          * @hide
2506          */
2507         @SystemApi
getIdleStateEnterCount()2508         public long getIdleStateEnterCount() {
2509             return mIdleStateEnterCount;
2510         }
2511 
2512         /**
2513          * Gets the total time the controller has spent in the active state (inquiring, paging,
2514          * ACL/SCO/eSCO/BIS/CIS traffic, processing any task) in milliseconds.
2515          *
2516          * @return the total time in the active state in milliseconds
2517          * @hide
2518          */
2519         @SystemApi
2520         @DurationMillisLong
getActiveStateTotalTimeMillis()2521         public long getActiveStateTotalTimeMillis() {
2522             return mActiveTotalTime;
2523         }
2524 
2525         /**
2526          * Gets the number of times the controller has entered the active state.
2527          *
2528          * @return the number of times the controller has entered the active state
2529          * @hide
2530          */
2531         @SystemApi
getActiveStateEnterCount()2532         public long getActiveStateEnterCount() {
2533             return mActiveStateEnterCount;
2534         }
2535 
2536         /**
2537          * Gets the total time the controller has spent transmitting BR/EDR data (ACL/SCO/eSCO
2538          * traffic) in milliseconds.
2539          *
2540          * @return the total time spent in the BR/EDR transmit state in milliseconds
2541          * @hide
2542          */
2543         @SystemApi
2544         @DurationMillisLong
getBredrTxTotalTimeMillis()2545         public long getBredrTxTotalTimeMillis() {
2546             return mBredrTxTotalTime;
2547         }
2548 
2549         /**
2550          * Gets the number of times the controller has entered the BR/EDR transmit state.
2551          *
2552          * @return the number of times the controller has entered the BR/EDR transmit state
2553          * @hide
2554          */
2555         @SystemApi
getBredrTxStateEnterCount()2556         public long getBredrTxStateEnterCount() {
2557             return mBredrTxStateEnterCount;
2558         }
2559 
2560         /**
2561          * Gets the average transmit power level of all BR/EDR links in dBm.
2562          *
2563          * @return the average transmit power level of all BR/EDR links in dBm
2564          * @hide
2565          */
2566         @SystemApi
getBredrAverageTxPowerLeveldBm()2567         public int getBredrAverageTxPowerLeveldBm() {
2568             return mBredrTxAvgPowerLevel;
2569         }
2570 
2571         /**
2572          * Gets the total time the controller has spent receiving BR/EDR data (ACL/SCO/eSCO traffic)
2573          * in milliseconds.
2574          *
2575          * @return the total time spent in the BR/EDR receive state in milliseconds
2576          * @hide
2577          */
2578         @SystemApi
2579         @DurationMillisLong
getBredrRxTotalTimeMillis()2580         public long getBredrRxTotalTimeMillis() {
2581             return mBredrRxTotalTime;
2582         }
2583 
2584         /**
2585          * Gets the number of times the controller has entered the BR/EDR receive state.
2586          *
2587          * @return the number of times the controller has entered the BR/EDR receive state
2588          * @hide
2589          */
2590         @SystemApi
getBredrRxStateEnterCount()2591         public long getBredrRxStateEnterCount() {
2592             return mBredrRxStateEnterCount;
2593         }
2594 
2595         /**
2596          * Gets the total time the controller has spent transmitting LE data (ACL/BIS/CIS or LE
2597          * advertising traffic) in milliseconds.
2598          *
2599          * @return the total time spent in the LE transmit state in milliseconds
2600          * @hide
2601          */
2602         @SystemApi
2603         @DurationMillisLong
getLeTsTotalTimeMillis()2604         public long getLeTsTotalTimeMillis() {
2605             return mLeTxTotalTime;
2606         }
2607 
2608         /**
2609          * Gets the number of times the controller has entered the LE transmit state.
2610          *
2611          * @return the number of times the controller has entered the LE transmit state
2612          * @hide
2613          */
2614         @SystemApi
getLeTxStateEnterCount()2615         public long getLeTxStateEnterCount() {
2616             return mLeTxStateEnterCount;
2617         }
2618 
2619         /**
2620          * Gets the average transmit power level of all LE links in dBm.
2621          *
2622          * @return the average transmit power level of all LE links in dBm
2623          * @hide
2624          */
2625         @SystemApi
getLeAverageTxPowerLeveldBm()2626         public int getLeAverageTxPowerLeveldBm() {
2627             return mLeTxAvgPowerLevel;
2628         }
2629 
2630         /**
2631          * Gets the total time the controller has spent receiving LE data (ACL/BIS/CIS or LE
2632          * scanning traffic) in milliseconds.
2633          *
2634          * @return the total time spent in the LE receive state in milliseconds
2635          * @hide
2636          */
2637         @SystemApi
2638         @DurationMillisLong
getLeRxTotalTimeMillis()2639         public long getLeRxTotalTimeMillis() {
2640             return mLeRxTotalTime;
2641         }
2642 
2643         /**
2644          * Gets the number of times the controller has entered the LE receive state.
2645          *
2646          * @return the number of times the controller has entered the LE receive state
2647          * @hide
2648          */
2649         @SystemApi
getLeRxStateEnterCount()2650         public long getLeRxStateEnterCount() {
2651             return mLeRxStateEnterCount;
2652         }
2653 
2654         /**
2655          * Gets the total time duration over which power-related information has been collected in
2656          * milliseconds.
2657          *
2658          * @return the total time duration for power data collection in milliseconds
2659          * @hide
2660          */
2661         @SystemApi
2662         @DurationMillisLong
getPowerDataTotalTimeMillis()2663         public long getPowerDataTotalTimeMillis() {
2664             return mReportTotalTime;
2665         }
2666 
2667         /**
2668          * Gets the time duration of the receiver being active with one antenna chain in
2669          * milliseconds.
2670          *
2671          * @return the time duration of single-chain receiver activity in milliseconds
2672          * @hide
2673          */
2674         @SystemApi
2675         @DurationMillisLong
getRxSingleChainActiveDurationMillis()2676         public long getRxSingleChainActiveDurationMillis() {
2677             return mRxActiveOneChainTime;
2678         }
2679 
2680         /**
2681          * Gets the time duration of the receiver being active with two antenna chains in
2682          * milliseconds.
2683          *
2684          * @return the time duration of dual-chain receiver activity in milliseconds
2685          * @hide
2686          */
2687         @SystemApi
2688         @DurationMillisLong
getRxDualChainActiveDurationMillis()2689         public long getRxDualChainActiveDurationMillis() {
2690             return mRxActiveTwoChainTime;
2691         }
2692 
2693         /**
2694          * Gets the time duration of the internal transmitter being active with one antenna chain in
2695          * milliseconds.
2696          *
2697          * @return the time duration of single-chain internal transmitter activity in milliseconds
2698          * @hide
2699          */
2700         @SystemApi
2701         @DurationMillisLong
getTxInternalPaSingleChainActiveDurationMillis()2702         public long getTxInternalPaSingleChainActiveDurationMillis() {
2703             return mTxiPaActiveOneChainTime;
2704         }
2705 
2706         /**
2707          * Gets the time duration of the internal transmitter being active with two antenna chains
2708          * in milliseconds.
2709          *
2710          * @return the time duration of dual-chain internal transmitter activity in milliseconds
2711          * @hide
2712          */
2713         @SystemApi
2714         @DurationMillisLong
getTxInternalPaDualChainActiveDurationMillis()2715         public long getTxInternalPaDualChainActiveDurationMillis() {
2716             return mTxiPaActiveTwoChainTime;
2717         }
2718 
2719         /**
2720          * Gets the time duration of the external transmitter being active with one antenna chain in
2721          * milliseconds.
2722          *
2723          * @return the time duration of single-chain external transmitter activity in milliseconds
2724          * @hide
2725          */
2726         @SystemApi
2727         @DurationMillisLong
getTxExternalPaSingleChainActiveDurationMillis()2728         public long getTxExternalPaSingleChainActiveDurationMillis() {
2729             return mTxePaActiveOneChainTime;
2730         }
2731 
2732         /**
2733          * Gets the time duration of the external transmitter being active with two antenna chains
2734          * in milliseconds.
2735          *
2736          * @return the time duration of dual-chain external transmitter activity in milliseconds
2737          * @hide
2738          */
2739         @SystemApi
2740         @DurationMillisLong
getTxExternalPaDualChainActiveDurationMillis()2741         public long getTxExternalPaDualChainActiveDurationMillis() {
2742             return mTxePaActiveTwoChainTime;
2743         }
2744 
2745         @Override
describeContents()2746         public int describeContents() {
2747             return 0;
2748         }
2749 
2750         /**
2751          * Write BqrEnergyMonitor to parcel.
2752          *
2753          * @hide
2754          */
2755         @SystemApi
2756         @Override
writeToParcel(@onNull Parcel dest, int flags)2757         public void writeToParcel(@NonNull Parcel dest, int flags) {
2758             dest.writeInt(mAvgCurrentConsume);
2759             dest.writeLong(mIdleTotalTime);
2760             dest.writeLong(mIdleStateEnterCount);
2761             dest.writeLong(mActiveTotalTime);
2762             dest.writeLong(mActiveStateEnterCount);
2763             dest.writeLong(mBredrTxTotalTime);
2764             dest.writeLong(mBredrTxStateEnterCount);
2765             dest.writeInt(mBredrTxAvgPowerLevel);
2766             dest.writeLong(mBredrRxTotalTime);
2767             dest.writeLong(mBredrRxStateEnterCount);
2768             dest.writeLong(mLeTxTotalTime);
2769             dest.writeLong(mLeTxStateEnterCount);
2770             dest.writeInt(mLeTxAvgPowerLevel);
2771             dest.writeLong(mLeRxTotalTime);
2772             dest.writeLong(mLeRxStateEnterCount);
2773             dest.writeLong(mReportTotalTime);
2774             dest.writeLong(mRxActiveOneChainTime);
2775             dest.writeLong(mRxActiveTwoChainTime);
2776             dest.writeLong(mTxiPaActiveOneChainTime);
2777             dest.writeLong(mTxiPaActiveTwoChainTime);
2778             dest.writeLong(mTxePaActiveOneChainTime);
2779             dest.writeLong(mTxePaActiveTwoChainTime);
2780         }
2781 
2782         /** @hide */
2783         @SystemApi
2784         public static final @NonNull Parcelable.Creator<BqrEnergyMonitor> CREATOR =
2785                 new Parcelable.Creator<BqrEnergyMonitor>() {
2786                     public BqrEnergyMonitor createFromParcel(Parcel in) {
2787                         return new BqrEnergyMonitor(in);
2788                     }
2789 
2790                     public BqrEnergyMonitor[] newArray(int size) {
2791                         return new BqrEnergyMonitor[size];
2792                     }
2793                 };
2794 
2795         /** BqrVsLsto to String. */
2796         @Override
2797         @NonNull
toString()2798         public String toString() {
2799             return "  BqrEnergyMonitor: {\n"
2800                     + "    AvgCurrentConsume: "
2801                     + mAvgCurrentConsume
2802                     + ", mIdleTotalTime: "
2803                     + mIdleTotalTime
2804                     + ", mIdleStateEnterCount: "
2805                     + mIdleStateEnterCount
2806                     + ", mActiveTotalTime: "
2807                     + mActiveTotalTime
2808                     + ", mActiveStateEnterCount: "
2809                     + mActiveStateEnterCount
2810                     + ",\n"
2811                     + "    mBredrTxTotalTime: "
2812                     + mBredrTxTotalTime
2813                     + ", mBredrTxStateEnterCount: "
2814                     + mBredrTxStateEnterCount
2815                     + ", mBredrTxAvgPowerLevel: "
2816                     + mBredrTxAvgPowerLevel
2817                     + ", mBredrRxTotalTime: "
2818                     + mBredrRxTotalTime
2819                     + ", mBredrRxStateEnterCount: "
2820                     + mBredrRxStateEnterCount
2821                     + ", mLeTxTotalTime: "
2822                     + mLeTxTotalTime
2823                     + ", mLeTxStateEnterCount: "
2824                     + mLeTxStateEnterCount
2825                     + ", mLeTxAvgPowerLevel: "
2826                     + mLeTxAvgPowerLevel
2827                     + ", mLeRxTotalTime: "
2828                     + mLeRxTotalTime
2829                     + ", mLeRxStateEnterCount: "
2830                     + mLeRxStateEnterCount
2831                     + ", mReportTotalTime: "
2832                     + mReportTotalTime
2833                     + ", mRxActiveOneChainTime: "
2834                     + mRxActiveOneChainTime
2835                     + ", mRxActiveTwoChainTime: "
2836                     + mRxActiveTwoChainTime
2837                     + ", mTxiPaActiveOneChainTime: "
2838                     + mTxiPaActiveOneChainTime
2839                     + ", mTxiPaActiveTwoChainTime: "
2840                     + mTxiPaActiveTwoChainTime
2841                     + ", mTxePaActiveOneChainTime: "
2842                     + mTxePaActiveOneChainTime
2843                     + ", mTxePaActiveTwoChainTime: "
2844                     + mTxePaActiveTwoChainTime
2845                     + "\n  }";
2846         }
2847     }
2848 
2849     /**
2850      * This class provides APIs to access RF statistics events from the Bluetooth Quality Report. It
2851      * includes detailed information about received signal strength (RSSI) across different antenna
2852      * chains, transmit power levels, and packet counts for various transmission and reception
2853      * scenarios. This data can be used to analyze RF performance and identify potential issues in
2854      * Bluetooth connections.
2855      *
2856      * @hide
2857      */
2858     @FlaggedApi(Flags.FLAG_SUPPORT_BLUETOOTH_QUALITY_REPORT_V6)
2859     @SystemApi
2860     public static final class BqrRfStats implements Parcelable {
2861         private static final String TAG =
2862                 BluetoothQualityReport.TAG + "." + BqrRfStats.class.getSimpleName();
2863 
2864         private final int mExtensionInfo;
2865         private final long mReportTimePeriod;
2866         private final long mTxPoweriPaBf;
2867         private final long mTxPowerePaBf;
2868         private final long mTxPoweriPaDiv;
2869         private final long mTxPowerePaDiv;
2870         private final long mRssiChainOver50;
2871         private final long mRssiChain50To55;
2872         private final long mRssiChain55To60;
2873         private final long mRssiChain60To65;
2874         private final long mRssiChain65To70;
2875         private final long mRssiChain70To75;
2876         private final long mRssiChain75To80;
2877         private final long mRssiChain80To85;
2878         private final long mRssiChain85To90;
2879         private final long mRssiChainUnder90;
2880         private final long mRssiDeltaUnder2;
2881         private final long mRssiDelta2To5;
2882         private final long mRssiDelta5To8;
2883         private final long mRssiDelta8To11;
2884         private final long mRssiDeltaOver11;
2885 
BqrRfStats(byte[] rawData, int offset)2886         private BqrRfStats(byte[] rawData, int offset) {
2887             if (rawData == null || rawData.length <= offset) {
2888                 throw new IllegalArgumentException(
2889                         TAG + ": BQR RF Stats raw data length is abnormal.");
2890             }
2891 
2892             ByteBuffer bqrBuf =
2893                     ByteBuffer.wrap(rawData, offset, rawData.length - offset).asReadOnlyBuffer();
2894             bqrBuf.order(ByteOrder.LITTLE_ENDIAN);
2895 
2896             mExtensionInfo = bqrBuf.get() & 0xFF;
2897             mReportTimePeriod = bqrBuf.getInt() & 0xFFFFFFFFL;
2898             mTxPoweriPaBf = bqrBuf.getInt() & 0xFFFFFFFFL;
2899             mTxPowerePaBf = bqrBuf.getInt() & 0xFFFFFFFFL;
2900             mTxPoweriPaDiv = bqrBuf.getInt() & 0xFFFFFFFFL;
2901             mTxPowerePaDiv = bqrBuf.getInt() & 0xFFFFFFFFL;
2902             mRssiChainOver50 = bqrBuf.getInt() & 0xFFFFFFFFL;
2903             mRssiChain50To55 = bqrBuf.getInt() & 0xFFFFFFFFL;
2904             mRssiChain55To60 = bqrBuf.getInt() & 0xFFFFFFFFL;
2905             mRssiChain60To65 = bqrBuf.getInt() & 0xFFFFFFFFL;
2906             mRssiChain65To70 = bqrBuf.getInt() & 0xFFFFFFFFL;
2907             mRssiChain70To75 = bqrBuf.getInt() & 0xFFFFFFFFL;
2908             mRssiChain75To80 = bqrBuf.getInt() & 0xFFFFFFFFL;
2909             mRssiChain80To85 = bqrBuf.getInt() & 0xFFFFFFFFL;
2910             mRssiChain85To90 = bqrBuf.getInt() & 0xFFFFFFFFL;
2911             mRssiChainUnder90 = bqrBuf.getInt() & 0xFFFFFFFFL;
2912             mRssiDeltaUnder2 = bqrBuf.getInt() & 0xFFFFFFFFL;
2913             mRssiDelta2To5 = bqrBuf.getInt() & 0xFFFFFFFFL;
2914             mRssiDelta5To8 = bqrBuf.getInt() & 0xFFFFFFFFL;
2915             mRssiDelta8To11 = bqrBuf.getInt() & 0xFFFFFFFFL;
2916             mRssiDeltaOver11 = bqrBuf.getInt() & 0xFFFFFFFFL;
2917         }
2918 
BqrRfStats(Parcel in)2919         private BqrRfStats(Parcel in) {
2920             mExtensionInfo = in.readInt();
2921             mReportTimePeriod = in.readLong();
2922             mTxPoweriPaBf = in.readLong();
2923             mTxPowerePaBf = in.readLong();
2924             mTxPoweriPaDiv = in.readLong();
2925             mTxPowerePaDiv = in.readLong();
2926             mRssiChainOver50 = in.readLong();
2927             mRssiChain50To55 = in.readLong();
2928             mRssiChain55To60 = in.readLong();
2929             mRssiChain60To65 = in.readLong();
2930             mRssiChain65To70 = in.readLong();
2931             mRssiChain70To75 = in.readLong();
2932             mRssiChain75To80 = in.readLong();
2933             mRssiChain80To85 = in.readLong();
2934             mRssiChain85To90 = in.readLong();
2935             mRssiChainUnder90 = in.readLong();
2936             mRssiDeltaUnder2 = in.readLong();
2937             mRssiDelta2To5 = in.readLong();
2938             mRssiDelta5To8 = in.readLong();
2939             mRssiDelta8To11 = in.readLong();
2940             mRssiDeltaOver11 = in.readLong();
2941         }
2942 
2943         /**
2944          * Gets the extension Info for the RF stats event.
2945          *
2946          * @return the extension information for the RF stats event
2947          * @hide
2948          */
2949         @SystemApi
getExtensionInfo()2950         public int getExtensionInfo() {
2951             return mExtensionInfo;
2952         }
2953 
2954         /**
2955          * Gets the time duration over which performance information has been collected in
2956          * milliseconds.
2957          *
2958          * @return the time duration for performance data collection in milliseconds
2959          * @hide
2960          */
2961         @SystemApi
2962         @DurationMillisLong
getPerformanceDurationMillis()2963         public long getPerformanceDurationMillis() {
2964             return mReportTimePeriod;
2965         }
2966 
2967         /**
2968          * Gets the packet count for transmissions using internal PA (iPA) beamforming.
2969          *
2970          * @return the packet count for iPA beamforming transmissions
2971          * @hide
2972          */
2973         @SystemApi
getTxPowerInternalPaBeamformingCount()2974         public long getTxPowerInternalPaBeamformingCount() {
2975             return mTxPoweriPaBf;
2976         }
2977 
2978         /**
2979          * Gets the packet count for transmissions using external PA (ePA) beamforming.
2980          *
2981          * @return the packet count for ePA beamforming transmissions
2982          * @hide
2983          */
2984         @SystemApi
getTxPowerExternalPaBeamformingCount()2985         public long getTxPowerExternalPaBeamformingCount() {
2986             return mTxPowerePaBf;
2987         }
2988 
2989         /**
2990          * Gets the packet count for transmissions using internal PA (iPA) diversity.
2991          *
2992          * @return the packet count for iPA diversity transmissions
2993          * @hide
2994          */
2995         @SystemApi
getTxPowerInternalPaDiversityCount()2996         public long getTxPowerInternalPaDiversityCount() {
2997             return mTxPoweriPaDiv;
2998         }
2999 
3000         /**
3001          * Gets the packet count for transmissions using external PA (ePA) diversity.
3002          *
3003          * @return the packet count for ePA diversity transmissions
3004          * @hide
3005          */
3006         @SystemApi
getTxPowerExternalPaDiversityCount()3007         public long getTxPowerExternalPaDiversityCount() {
3008             return mTxPowerePaDiv;
3009         }
3010 
3011         /**
3012          * Gets the packet count for received signals with an RSSI (Received Signal Strength
3013          * Indicator) greater than -50 dBm on any antenna chain.
3014          *
3015          * @return the packet count for RSSI stronger than -50 dBm
3016          * @hide
3017          */
3018         @SystemApi
getPacketsWithRssiAboveMinus50dBm()3019         public long getPacketsWithRssiAboveMinus50dBm() {
3020             return mRssiChainOver50;
3021         }
3022 
3023         /**
3024          * Gets the packet count for received signals with an RSSI between -50 dBm and -55 dBm on
3025          * any antenna chain.
3026          *
3027          * @return the packet count for RSSI between -50 dBm and -55 dBm
3028          * @hide
3029          */
3030         @SystemApi
getPacketsWithRssi50To55dBm()3031         public long getPacketsWithRssi50To55dBm() {
3032             return mRssiChain50To55;
3033         }
3034 
3035         /**
3036          * Gets the packet count for received signals with an RSSI between -55 dBm and -60 dBm on
3037          * any antenna chain.
3038          *
3039          * @return the packet count for RSSI between -55 dBm and -60 dBm
3040          * @hide
3041          */
3042         @SystemApi
getPacketsWithRssi55To60dBm()3043         public long getPacketsWithRssi55To60dBm() {
3044             return mRssiChain55To60;
3045         }
3046 
3047         /**
3048          * Gets the packet count for received signals with an RSSI between -60 dBm and -65 dBm on
3049          * any antenna chain.
3050          *
3051          * @return the packet count for RSSI between -60 dBm and -65 dBm
3052          * @hide
3053          */
3054         @SystemApi
getPacketsWithRssi60To65dBm()3055         public long getPacketsWithRssi60To65dBm() {
3056             return mRssiChain60To65;
3057         }
3058 
3059         /**
3060          * Gets the packet count for received signals with an RSSI between -65 dBm and -70 dBm on
3061          * any antenna chain.
3062          *
3063          * @return the packet count for RSSI between -65 dBm and -70 dBm
3064          * @hide
3065          */
3066         @SystemApi
getPacketsWithRssi65To70dBm()3067         public long getPacketsWithRssi65To70dBm() {
3068             return mRssiChain65To70;
3069         }
3070 
3071         /**
3072          * Gets the packet count for received signals with an RSSI between -70 dBm and -75 dBm on
3073          * any antenna chain.
3074          *
3075          * @return the packet count for RSSI between -70 dBm and -75 dBm
3076          * @hide
3077          */
3078         @SystemApi
getPacketsWithRssi70To75dBm()3079         public long getPacketsWithRssi70To75dBm() {
3080             return mRssiChain70To75;
3081         }
3082 
3083         /**
3084          * Gets the packet count for received signals with an RSSI between -75 dBm and -80 dBm on
3085          * any antenna chain.
3086          *
3087          * @return the packet count for RSSI between -75 dBm and -80 dBm
3088          * @hide
3089          */
3090         @SystemApi
getPacketsWithRssi75To80dBm()3091         public long getPacketsWithRssi75To80dBm() {
3092             return mRssiChain75To80;
3093         }
3094 
3095         /**
3096          * Gets the packet count for received signals with an RSSI between -80 dBm and -85 dBm on
3097          * any antenna chain.
3098          *
3099          * @return the packet count for RSSI between -80 dBm and -85 dBm
3100          * @hide
3101          */
3102         @SystemApi
getPacketsWithRssi80To85dBm()3103         public long getPacketsWithRssi80To85dBm() {
3104             return mRssiChain80To85;
3105         }
3106 
3107         /**
3108          * Gets the packet count for received signals with an RSSI between -85 dBm and -90 dBm on
3109          * any antenna chain.
3110          *
3111          * @return the packet count for RSSI between -85 dBm and -90 dBm
3112          * @hide
3113          */
3114         @SystemApi
getPacketsWithRssi85To90dBm()3115         public long getPacketsWithRssi85To90dBm() {
3116             return mRssiChain85To90;
3117         }
3118 
3119         /**
3120          * Gets the packet count for received signals with an RSSI (Received Signal Strength
3121          * Indicator) weaker than -90 dBm on any antenna chain.
3122          *
3123          * @return the packet count for RSSI weaker than -90 dBm
3124          * @hide
3125          */
3126         @SystemApi
getPacketsWithRssiBelowMinus90dBm()3127         public long getPacketsWithRssiBelowMinus90dBm() {
3128             return mRssiChainUnder90;
3129         }
3130 
3131         /**
3132          * Gets the packet count where the difference in RSSI between antenna chains is less than 2
3133          * dBm.
3134          *
3135          * @return the packet count for RSSI delta less than 2 dBm
3136          * @hide
3137          */
3138         @SystemApi
getPacketsWithRssiDeltaBelow2dBm()3139         public long getPacketsWithRssiDeltaBelow2dBm() {
3140             return mRssiDeltaUnder2;
3141         }
3142 
3143         /**
3144          * Gets the packet count where the difference in RSSI between antenna chains is between 2
3145          * dBm and 5 dBm.
3146          *
3147          * @return the packet count for RSSI delta between 2 dBm and 5 dBm
3148          * @hide
3149          */
3150         @SystemApi
getPacketsWithRssiDelta2To5dBm()3151         public long getPacketsWithRssiDelta2To5dBm() {
3152             return mRssiDelta2To5;
3153         }
3154 
3155         /**
3156          * Gets the packet count where the difference in RSSI between antenna chains is between 5
3157          * dBm and 8 dBm.
3158          *
3159          * @return the packet count for RSSI delta between 5 dBm and 8 dBm
3160          * @hide
3161          */
3162         @SystemApi
getPacketsWithRssiDelta5To8dBm()3163         public long getPacketsWithRssiDelta5To8dBm() {
3164             return mRssiDelta5To8;
3165         }
3166 
3167         /**
3168          * Gets the packet count where the difference in RSSI between antenna chains is greater than
3169          * 11 dBm.
3170          *
3171          * @return the packet count for RSSI delta greater than 11 dBm
3172          * @hide
3173          */
3174         @SystemApi
getPacketsWithRssiDelta8To11dBm()3175         public long getPacketsWithRssiDelta8To11dBm() {
3176             return mRssiDelta8To11;
3177         }
3178 
3179         /**
3180          * Get the Packet counter of RSSI delta are larger than 11 dBm
3181          *
3182          * @return the packet counter of RSSI delta are larger than 11 dBm
3183          * @hide
3184          */
3185         @SystemApi
getPacketsWithRssiDeltaAbove11dBm()3186         public long getPacketsWithRssiDeltaAbove11dBm() {
3187             return mRssiDeltaOver11;
3188         }
3189 
3190         @Override
describeContents()3191         public int describeContents() {
3192             return 0;
3193         }
3194 
3195         /**
3196          * Write BqrRfStats to parcel.
3197          *
3198          * @hide
3199          */
3200         @SystemApi
3201         @Override
writeToParcel(@onNull Parcel dest, int flags)3202         public void writeToParcel(@NonNull Parcel dest, int flags) {
3203             dest.writeInt(mExtensionInfo);
3204             dest.writeLong(mReportTimePeriod);
3205             dest.writeLong(mTxPoweriPaBf);
3206             dest.writeLong(mTxPowerePaBf);
3207             dest.writeLong(mTxPoweriPaDiv);
3208             dest.writeLong(mTxPowerePaDiv);
3209             dest.writeLong(mRssiChainOver50);
3210             dest.writeLong(mRssiChain50To55);
3211             dest.writeLong(mRssiChain55To60);
3212             dest.writeLong(mRssiChain60To65);
3213             dest.writeLong(mRssiChain65To70);
3214             dest.writeLong(mRssiChain70To75);
3215             dest.writeLong(mRssiChain75To80);
3216             dest.writeLong(mRssiChain80To85);
3217             dest.writeLong(mRssiChain85To90);
3218             dest.writeLong(mRssiChainUnder90);
3219             dest.writeLong(mRssiDeltaUnder2);
3220             dest.writeLong(mRssiDelta2To5);
3221             dest.writeLong(mRssiDelta5To8);
3222             dest.writeLong(mRssiDelta8To11);
3223             dest.writeLong(mRssiDeltaOver11);
3224         }
3225 
3226         /** @hide */
3227         @SystemApi
3228         public static final @NonNull Parcelable.Creator<BqrRfStats> CREATOR =
3229                 new Parcelable.Creator<BqrRfStats>() {
3230                     public BqrRfStats createFromParcel(Parcel in) {
3231                         return new BqrRfStats(in);
3232                     }
3233 
3234                     public BqrRfStats[] newArray(int size) {
3235                         return new BqrRfStats[size];
3236                     }
3237                 };
3238 
3239         /** BqrVsLsto to String. */
3240         @Override
3241         @NonNull
toString()3242         public String toString() {
3243             return "  BqrRfStats: {\n"
3244                     + "    mExtensionInfo: "
3245                     + mExtensionInfo
3246                     + ", mReportTimePeriod: "
3247                     + mReportTimePeriod
3248                     + ", mTxPoweriPaBf: "
3249                     + mTxPoweriPaBf
3250                     + ", mTxPowerePaBf: "
3251                     + mTxPowerePaBf
3252                     + ", mTxPoweriPaDiv: "
3253                     + mTxPoweriPaDiv
3254                     + ", mTxPowerePaDiv: "
3255                     + mTxPowerePaDiv
3256                     + ",\n"
3257                     + "    mRssiChainOver50: "
3258                     + mRssiChainOver50
3259                     + ", mRssiChain50To55: "
3260                     + mRssiChain50To55
3261                     + ", mRssiChain55To60: "
3262                     + mRssiChain55To60
3263                     + ", mRssiChain60To65: "
3264                     + mRssiChain60To65
3265                     + ", mRssiChain65To70: "
3266                     + mRssiChain65To70
3267                     + ", mRssiChain70To75: "
3268                     + mRssiChain70To75
3269                     + ", mRssiChain75To80: "
3270                     + mRssiChain75To80
3271                     + ", mRssiChain80To85: "
3272                     + mRssiChain80To85
3273                     + ", mRssiChain85To90: "
3274                     + mRssiChain85To90
3275                     + ", mRssiChainUnder90: "
3276                     + mRssiChainUnder90
3277                     + ",\n"
3278                     + "    mRssiDeltaUnder2: "
3279                     + mRssiDeltaUnder2
3280                     + ", mRssiDelta2To5: "
3281                     + mRssiDelta2To5
3282                     + ", mRssiDelta5To8: "
3283                     + mRssiDelta5To8
3284                     + ", mRssiDelta8To11: "
3285                     + mRssiDelta8To11
3286                     + ", mRssiDeltaOver11: "
3287                     + mRssiDeltaOver11
3288                     + "\n  }";
3289         }
3290     }
3291 }
3292