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