summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorVenkatesh Sharma <quic_venkshar@quicinc.com>2023-02-14 17:00:54 +0530
committerSrinu Jella <quic_sjella@quicinc.com>2023-03-20 10:46:28 +0000
commit21c71dc4b09f42e6af608f585be3bd28d6cc043c (patch)
treeab29293d45f41ed06b12b3e2c8051bf0d750eaf1
parent9c2cfd90483797fef5b2396b65c96948038568d9 (diff)
BQR Vendor specific extension
- Implemented the vendor version of BQR5. - Implemented parser for Quality monitor, LSTO, SCO choppy, A2DP choppy reports to parse the extended info. - Implemented Disc monitor and Misc monitor reports using vendor specific mechanism introduced as part of BQR5. CRs-Fixed: 3426980 Change-Id: I1b5f385fc4ad330a3dce88f92832c5c8ab344a93
-rw-r--r--core/java/android/bluetooth/BluetoothAdapter.java25
-rw-r--r--core/java/android/bluetooth/BluetoothQualityReport.java1055
2 files changed, 979 insertions, 101 deletions
diff --git a/core/java/android/bluetooth/BluetoothAdapter.java b/core/java/android/bluetooth/BluetoothAdapter.java
index ea6fddbfac73..63eff19d3600 100644
--- a/core/java/android/bluetooth/BluetoothAdapter.java
+++ b/core/java/android/bluetooth/BluetoothAdapter.java
@@ -15,6 +15,12 @@
* limitations under the License.
*/
+/*
+ * Changes from Qualcomm Innovation Center are provided under the following license:
+ * Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved.
+ * SPDX-License-Identifier: BSD-3-Clause-Clear
+ */
+
package android.bluetooth;
import static java.util.Objects.requireNonNull;
@@ -395,6 +401,25 @@ public final class BluetoothAdapter {
public static final String EXTRA_PREVIOUS_SCAN_MODE =
"android.bluetooth.adapter.extra.PREVIOUS_SCAN_MODE";
+ /**
+ * Broadcast Action: Broadcast details of IOT device when an IOT
+ * related issue is observed.
+ * <p>Always contains the extra fields {@link #EXTRA_NAME}.
+ * <p>Requires {@link android.Manifest.permission#BLUETOOTH} to receive.
+ * @hide
+ **/
+
+ @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
+ public static final String ACTION_REMOTE_ISSUE_OCCURRED =
+ "org.codeaurora.intent.bluetooth.action.REMOTE_ISSUE_OCCURRED";
+
+ /**
+ * Used as a Parcelable {@link BluetoothQualityReport} extra field in
+ * {@link #ACTION_REMOTE_ISSUE_OCCURRED} intent. It contains the {@link BluetoothQualityReport}.
+ * @hide
+ */
+ public static final String EXTRA_BQR = "android.bluetooth.qti.extra.EXTRA_BQR";
+
/** @hide */
@IntDef(prefix = { "SCAN_" }, value = {
SCAN_MODE_NONE,
diff --git a/core/java/android/bluetooth/BluetoothQualityReport.java b/core/java/android/bluetooth/BluetoothQualityReport.java
index e9ed008b6954..0e225371ad04 100644
--- a/core/java/android/bluetooth/BluetoothQualityReport.java
+++ b/core/java/android/bluetooth/BluetoothQualityReport.java
@@ -27,6 +27,12 @@
* IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
+/*
+ * Changes from Qualcomm Innovation Center are provided under the following license:
+ * Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved.
+ * SPDX-License-Identifier: BSD-3-Clause-Clear
+ */
+
package android.bluetooth;
import android.annotation.NonNull;
@@ -77,8 +83,12 @@ public final class BluetoothQualityReport implements Parcelable {
public static final int QUALITY_REPORT_ID_APPROACH_LSTO = 0x02;
public static final int QUALITY_REPORT_ID_A2DP_CHOPPY = 0x03;
public static final int QUALITY_REPORT_ID_SCO_CHOPPY = 0x04;
+ public static final int QUALITY_REPORT_ID_VENDOR_SPECIFIC = 0x10;
/* Vendor Specific Report IDs from 0x20 */
public static final int QUALITY_REPORT_ID_CONN_FAIL = 0x20;
+ public static final int QUALITY_REPORT_ID_CONN_FAIL_BQR5 = 0x08;
+ public static final int QUALITY_REPORT_ID_VS_DISC_MONITOR = 0x01;
+ public static final int QUALITY_REPORT_ID_VS_MISC_MONITOR = 0x02;
private String mAddr;
private int mLmpVer;
@@ -86,14 +96,18 @@ public final class BluetoothQualityReport implements Parcelable {
private int mManufacturerId;
private String mName;
private int mBluetoothClass;
+ private boolean mVendorBqr5;
private BqrCommon mBqrCommon;
private BqrVsCommon mBqrVsCommon;
+ private BqrVsQualityMonitor mBqrVsQualityMonitor;
private BqrVsLsto mBqrVsLsto;
private BqrVsA2dpChoppy mBqrVsA2dpChoppy;
private BqrVsScoChoppy mBqrVsScoChoppy;
private BqrVsConnectFail mBqrVsConnectFail;
+ private BqrVsDiscoveryMonitoring mBqrVsDiscMonitoring;
+ private BqrVsMiscMonitoring mBqrVsMiscMonitoring;
enum PacketType {
INVALID, TYPE_ID, TYPE_NULL, TYPE_POLL, TYPE_FHS, TYPE_HV1, TYPE_HV2, TYPE_HV3,
@@ -203,8 +217,81 @@ public final class BluetoothQualityReport implements Parcelable {
}
}
+
+ public BluetoothQualityReport(String remoteAddr, int lmpVer, int lmpSubVer,
+ int manufacturerId, String remoteName, int remoteCoD, byte[] rawData,
+ boolean vendorBqr5) {
+ mVendorBqr5 = vendorBqr5;
+ if (!BluetoothAdapter.checkBluetoothAddress(remoteAddr)) {
+ Log.d(TAG, "remote addr is invalid");
+ mAddr = "00:00:00:00:00:00";
+ } else {
+ mAddr = remoteAddr;
+ }
+
+ mLmpVer = lmpVer;
+ mLmpSubVer = lmpSubVer;
+ mManufacturerId = manufacturerId;
+ if (remoteName == null) {
+ Log.d(TAG, "remote name is null");
+ mName = "";
+ } else {
+ mName = remoteName;
+ }
+ mBluetoothClass = remoteCoD;
+
+ mBqrCommon = new BqrCommon(rawData, 0, vendorBqr5);
+ int id = mBqrCommon.getQualityReportId();
+ int vsPartOffset = 0;
+ if (id == QUALITY_REPORT_ID_MONITOR ||
+ id == QUALITY_REPORT_ID_APPROACH_LSTO ||
+ id == QUALITY_REPORT_ID_A2DP_CHOPPY ||
+ id == QUALITY_REPORT_ID_SCO_CHOPPY) {
+ mBqrVsCommon = new BqrVsCommon(rawData, BqrCommon.BQR_COMMON_LEN);
+ vsPartOffset = BqrCommon.BQR_COMMON_LEN + mBqrVsCommon.getLength();
+ }
+
+ if (mVendorBqr5 == true && id == QUALITY_REPORT_ID_CONN_FAIL_BQR5) {
+ mBqrVsCommon = new BqrVsCommon(rawData, BqrCommon.BQR_COMMON_LEN);
+ vsPartOffset = BqrCommon.BQR_COMMON_LEN + mBqrVsCommon.getLength();
+ }
+
+ if (mVendorBqr5 == false && id == QUALITY_REPORT_ID_CONN_FAIL) {
+ mBqrVsCommon = new BqrVsCommon(rawData, BqrCommon.BQR_COMMON_LEN);
+ vsPartOffset = BqrCommon.BQR_COMMON_LEN + mBqrVsCommon.getLength();
+ }
+
+ if (mVendorBqr5 == true && id == QUALITY_REPORT_ID_MONITOR) {
+ mBqrVsQualityMonitor = new BqrVsQualityMonitor(rawData, vsPartOffset);
+ } else if (mVendorBqr5 == false && id == QUALITY_REPORT_ID_MONITOR){
+ return;
+ } else if (id == QUALITY_REPORT_ID_APPROACH_LSTO) {
+ mBqrVsLsto = new BqrVsLsto(rawData, vsPartOffset);
+ } else if (id == QUALITY_REPORT_ID_A2DP_CHOPPY) {
+ mBqrVsA2dpChoppy = new BqrVsA2dpChoppy(rawData, vsPartOffset);
+ } else if (id == QUALITY_REPORT_ID_SCO_CHOPPY) {
+ mBqrVsScoChoppy = new BqrVsScoChoppy(rawData, vsPartOffset);
+ } else if(mVendorBqr5 == true &&
+ id == QUALITY_REPORT_ID_VENDOR_SPECIFIC) {
+ int vsId = mBqrCommon.getVendorQualityReportId();
+ if (vsId == QUALITY_REPORT_ID_VS_DISC_MONITOR) {
+ mBqrVsDiscMonitoring = new BqrVsDiscoveryMonitoring(rawData, 2);
+ } else if (vsId == QUALITY_REPORT_ID_VS_MISC_MONITOR) {
+ mBqrVsMiscMonitoring = new BqrVsMiscMonitoring(rawData, 2);
+ }
+ } else if ((mVendorBqr5 == true &&
+ id == QUALITY_REPORT_ID_CONN_FAIL_BQR5) ||
+ (mVendorBqr5 == false &&
+ id == QUALITY_REPORT_ID_CONN_FAIL)) {
+ mBqrVsConnectFail = new BqrVsConnectFail(rawData, vsPartOffset);
+ } else {
+ throw new IllegalArgumentException(TAG + ": unkown quality report id:" + id);
+ }
+ }
+
private BluetoothQualityReport(Parcel in) {
mBqrCommon = new BqrCommon(in);
+ mVendorBqr5 = in.readBoolean();
mAddr = in.readString();
mLmpVer = in.readInt();
mLmpSubVer = in.readInt();
@@ -212,15 +299,44 @@ public final class BluetoothQualityReport implements Parcelable {
mName = in.readString();
mBluetoothClass = in.readInt();
- mBqrVsCommon = new BqrVsCommon(in);
int id = mBqrCommon.getQualityReportId();
- if (id == QUALITY_REPORT_ID_APPROACH_LSTO) {
+ if (id == QUALITY_REPORT_ID_MONITOR ||
+ id == QUALITY_REPORT_ID_APPROACH_LSTO ||
+ id == QUALITY_REPORT_ID_A2DP_CHOPPY ||
+ id == QUALITY_REPORT_ID_SCO_CHOPPY) {
+ mBqrVsCommon = new BqrVsCommon(in);
+ }
+
+ if (mVendorBqr5 == true && id == QUALITY_REPORT_ID_CONN_FAIL_BQR5) {
+ mBqrVsCommon = new BqrVsCommon(in);
+ }
+
+ if (mVendorBqr5 == false && id == QUALITY_REPORT_ID_CONN_FAIL) {
+ mBqrVsCommon = new BqrVsCommon(in);
+ }
+
+ if (mVendorBqr5 == true && id == QUALITY_REPORT_ID_MONITOR) {
+ mBqrVsQualityMonitor = new BqrVsQualityMonitor(in);
+ } else if (mVendorBqr5 == false && id == QUALITY_REPORT_ID_MONITOR) {
+ return;
+ } else if (id == QUALITY_REPORT_ID_APPROACH_LSTO) {
mBqrVsLsto = new BqrVsLsto(in);
} else if (id == QUALITY_REPORT_ID_A2DP_CHOPPY) {
mBqrVsA2dpChoppy = new BqrVsA2dpChoppy(in);
} else if (id == QUALITY_REPORT_ID_SCO_CHOPPY) {
mBqrVsScoChoppy = new BqrVsScoChoppy(in);
- } else if (id == QUALITY_REPORT_ID_CONN_FAIL) {
+ } else if(mVendorBqr5 == true &&
+ id == QUALITY_REPORT_ID_VENDOR_SPECIFIC) {
+ int vsId = mBqrCommon.getVendorQualityReportId();
+ if (vsId == QUALITY_REPORT_ID_VS_DISC_MONITOR) {
+ mBqrVsDiscMonitoring = new BqrVsDiscoveryMonitoring(in);
+ } else if (vsId == QUALITY_REPORT_ID_VS_MISC_MONITOR) {
+ mBqrVsMiscMonitoring = new BqrVsMiscMonitoring(in);
+ }
+ } else if ((mVendorBqr5 == true &&
+ id == QUALITY_REPORT_ID_CONN_FAIL_BQR5) ||
+ (mVendorBqr5 == false &&
+ id == QUALITY_REPORT_ID_CONN_FAIL)) {
mBqrVsConnectFail = new BqrVsConnectFail(in);
}
}
@@ -236,25 +352,59 @@ public final class BluetoothQualityReport implements Parcelable {
}
/**
+ * Get the vendor quality report id.
+ * @return the id, is one of {@link #QUALITY_REPORT_ID_VS_DISC_MONITOR},
+ * {@link #QUALITY_REPORT_ID_VS_MISC_MONITOR}.
+ */
+ public int getVendorQualityReportId() {
+ return mBqrCommon.getVendorQualityReportId();
+ }
+
+ /**
* Get the string of the quality report id.
* @return the string of the id.
*/
public String getQualityReportIdStr() {
int id = mBqrCommon.getQualityReportId();
- switch (id) {
- case QUALITY_REPORT_ID_MONITOR:
- return "Quality monitor";
- case QUALITY_REPORT_ID_APPROACH_LSTO:
- return "Approaching LSTO";
- case QUALITY_REPORT_ID_A2DP_CHOPPY:
- return "A2DP choppy";
- case QUALITY_REPORT_ID_SCO_CHOPPY:
- return "SCO choppy";
- case QUALITY_REPORT_ID_CONN_FAIL:
- return "Connect fail";
- default:
- return "INVALID";
+ if (id == QUALITY_REPORT_ID_MONITOR) {
+ return "Quality monitor";
+ } else if (id == QUALITY_REPORT_ID_APPROACH_LSTO) {
+ return "Approaching LSTO";
+ } else if (id == QUALITY_REPORT_ID_A2DP_CHOPPY) {
+ return "A2DP choppy";
+ } else if (id == QUALITY_REPORT_ID_SCO_CHOPPY) {
+ return "SCO choppy";
+ } else if(mVendorBqr5 == true &&
+ id == QUALITY_REPORT_ID_VENDOR_SPECIFIC) {
+ return "Vendor specific";
+ } else if ((mVendorBqr5 == true &&
+ id == QUALITY_REPORT_ID_CONN_FAIL_BQR5) ||
+ (mVendorBqr5 == false &&
+ id == QUALITY_REPORT_ID_CONN_FAIL)) {
+ return "Connect failed";
+ } else {
+ return "Invalid";
+ }
+ }
+
+ /**
+ * Get the string of the vendor quality report id.
+ * @return the string of the id.
+ */
+ public String getVendorQualityReportIdStr() {
+ int id = mBqrCommon.getQualityReportId();
+ if(mVendorBqr5 == true &&
+ id == QUALITY_REPORT_ID_VENDOR_SPECIFIC) {
+ int vsId = mBqrCommon.getVendorQualityReportId();
+ if (vsId == QUALITY_REPORT_ID_VS_DISC_MONITOR) {
+ return "Discovery Monitoring";
+ } else if (vsId == QUALITY_REPORT_ID_VS_MISC_MONITOR) {
+ return "Misc Monitoring";
+ }
+ } else {
+ return "Invalid";
}
+ return "Invalid";
}
/**
@@ -266,6 +416,14 @@ public final class BluetoothQualityReport implements Parcelable {
}
/**
+ * Is Vendor BQR5 Enabled.
+ * @return true if Vendor BQR5 Enabled otherwise false.
+ */
+ public boolean isVendorBqr5() {
+ return mVendorBqr5;
+ }
+
+ /**
* Get LMP version of remote device in this report.
* @return LMP version of remote device.
*/
@@ -375,21 +533,51 @@ public final class BluetoothQualityReport implements Parcelable {
@Override
public void writeToParcel(Parcel out, int flags) {
mBqrCommon.writeToParcel(out, flags);
+ out.writeBoolean(mVendorBqr5);
out.writeString(mAddr);
out.writeInt(mLmpVer);
out.writeInt(mLmpSubVer);
out.writeInt(mManufacturerId);
out.writeString(mName);
out.writeInt(mBluetoothClass);
- mBqrVsCommon.writeToParcel(out, flags);
int id = mBqrCommon.getQualityReportId();
- if (id == QUALITY_REPORT_ID_APPROACH_LSTO) {
+ if (id == QUALITY_REPORT_ID_MONITOR ||
+ id == QUALITY_REPORT_ID_APPROACH_LSTO ||
+ id == QUALITY_REPORT_ID_A2DP_CHOPPY ||
+ id == QUALITY_REPORT_ID_SCO_CHOPPY) {
+ mBqrVsCommon.writeToParcel(out, flags);
+ }
+
+ if (mVendorBqr5 == true && id == QUALITY_REPORT_ID_CONN_FAIL_BQR5) {
+ mBqrVsCommon.writeToParcel(out, flags);
+ }
+
+ if (mVendorBqr5 == false && id == QUALITY_REPORT_ID_CONN_FAIL) {
+ mBqrVsCommon.writeToParcel(out, flags);
+ }
+
+ if (mVendorBqr5 == true && id == QUALITY_REPORT_ID_MONITOR) {
+ mBqrVsQualityMonitor.writeToParcel(out, flags);
+ } else if (mVendorBqr5 == false && id == QUALITY_REPORT_ID_MONITOR) {
+ return;
+ } else if (id == QUALITY_REPORT_ID_APPROACH_LSTO) {
mBqrVsLsto.writeToParcel(out, flags);
} else if (id == QUALITY_REPORT_ID_A2DP_CHOPPY) {
mBqrVsA2dpChoppy.writeToParcel(out, flags);
} else if (id == QUALITY_REPORT_ID_SCO_CHOPPY) {
mBqrVsScoChoppy.writeToParcel(out, flags);
- } else if (id == QUALITY_REPORT_ID_CONN_FAIL) {
+ } else if(mVendorBqr5 == true &&
+ id == QUALITY_REPORT_ID_VENDOR_SPECIFIC) {
+ int vsId = mBqrCommon.getVendorQualityReportId();
+ if (vsId == QUALITY_REPORT_ID_VS_DISC_MONITOR) {
+ mBqrVsDiscMonitoring.writeToParcel(out, flags);
+ } else if (vsId == QUALITY_REPORT_ID_VS_MISC_MONITOR) {
+ mBqrVsMiscMonitoring.writeToParcel(out, flags);
+ }
+ } else if ((mVendorBqr5 == true &&
+ id == QUALITY_REPORT_ID_CONN_FAIL_BQR5) ||
+ (mVendorBqr5 == false &&
+ id == QUALITY_REPORT_ID_CONN_FAIL)) {
mBqrVsConnectFail.writeToParcel(out, flags);
}
}
@@ -398,6 +586,7 @@ public final class BluetoothQualityReport implements Parcelable {
public String toString() {
String str;
str = "BQR: {\n"
+ + " mVendorBqr5: " + mVendorBqr5
+ " mAddr: " + mAddr
+ ", mLmpVer: " + String.format("0x%02X", mLmpVer)
+ ", mLmpSubVer: " + String.format("0x%04X", mLmpSubVer)
@@ -405,22 +594,35 @@ public final class BluetoothQualityReport implements Parcelable {
+ ", mName: " + mName
+ ", mBluetoothClass: " + String.format("0x%X", mBluetoothClass)
+ ",\n"
- + mBqrCommon + "\n"
- + mBqrVsCommon + "\n";
+ + mBqrCommon + "\n";
int id = mBqrCommon.getQualityReportId();
- if (id == QUALITY_REPORT_ID_APPROACH_LSTO) {
+ if(!(mVendorBqr5 == true &&
+ id == QUALITY_REPORT_ID_VENDOR_SPECIFIC)){
+ str += mBqrVsCommon + "\n";
+ }
+ if (mVendorBqr5 == true && id == QUALITY_REPORT_ID_MONITOR) {
+ str += mBqrVsQualityMonitor + "\n}";
+ } else if (id == QUALITY_REPORT_ID_APPROACH_LSTO) {
str += mBqrVsLsto + "\n}";
} else if (id == QUALITY_REPORT_ID_A2DP_CHOPPY) {
str += mBqrVsA2dpChoppy + "\n}";
} else if (id == QUALITY_REPORT_ID_SCO_CHOPPY) {
str += mBqrVsScoChoppy + "\n}";
- } else if (id == QUALITY_REPORT_ID_CONN_FAIL) {
+ } else if(mVendorBqr5 == true &&
+ id == QUALITY_REPORT_ID_VENDOR_SPECIFIC) {
+ int vsId = mBqrCommon.getVendorQualityReportId();
+ if (vsId == QUALITY_REPORT_ID_VS_DISC_MONITOR) {
+ str += mBqrVsDiscMonitoring + "\n}";
+ } else if (vsId == QUALITY_REPORT_ID_VS_MISC_MONITOR) {
+ str += mBqrVsMiscMonitoring + "\n}";
+ }
+ } else if ((mVendorBqr5 == true &&
+ id == QUALITY_REPORT_ID_CONN_FAIL_BQR5) ||
+ (mVendorBqr5 == false &&
+ id == QUALITY_REPORT_ID_CONN_FAIL)) {
str += mBqrVsConnectFail + "\n}";
- } else if (id == QUALITY_REPORT_ID_MONITOR) {
- str += "}";
}
-
return str;
}
@@ -432,6 +634,7 @@ public final class BluetoothQualityReport implements Parcelable {
static final int BQR_COMMON_LEN = 48;
private int mQualityReportId;
+ private int mVendorQualityReportId;
private int mPacketType;
private int mConnectionHandle;
private int mConnectionRole;
@@ -450,6 +653,7 @@ public final class BluetoothQualityReport implements Parcelable {
private long mLastFlowOnTimestamp;
private long mOverflowCount;
private long mUnderflowCount;
+ private boolean mVendorBqr5;
private BqrCommon(byte[] rawData, int offset) {
if (rawData == null || rawData.length < offset + BQR_COMMON_LEN) {
@@ -481,32 +685,76 @@ public final class BluetoothQualityReport implements Parcelable {
mUnderflowCount = bqrBuf.getInt() & 0xFFFFFFFFL;
}
+ private BqrCommon(byte[] rawData, int offset, boolean vendorBqr5) {
+ if (rawData == null || rawData.length < offset + 2) {
+ throw new IllegalArgumentException(TAG + ": BQR raw data length is abnormal.");
+ }
+
+ ByteBuffer bqrBuf = ByteBuffer.wrap(rawData, offset, rawData.length - offset)
+ .asReadOnlyBuffer();
+ bqrBuf.order(ByteOrder.LITTLE_ENDIAN);
+ mVendorBqr5 = vendorBqr5;
+ mQualityReportId = bqrBuf.get() & 0xFF;
+ if(mQualityReportId == QUALITY_REPORT_ID_VENDOR_SPECIFIC) {
+ mVendorQualityReportId = bqrBuf.get() & 0xFF;
+ } else {
+ mPacketType = bqrBuf.get() & 0xFF;
+ mConnectionHandle = bqrBuf.getShort() & 0xFFFF;
+ mConnectionRole = bqrBuf.get() & 0xFF;
+ mTxPowerLevel = bqrBuf.get() & 0xFF;
+ mRssi = bqrBuf.get();
+ mSnr = bqrBuf.get();
+ mUnusedAfhChannelCount = bqrBuf.get() & 0xFF;
+ mAfhSelectUnidealChannelCount = bqrBuf.get() & 0xFF;
+ mLsto = bqrBuf.getShort() & 0xFFFF;
+ mPiconetClock = bqrBuf.getInt() & 0xFFFFFFFFL;
+ mRetransmissionCount = bqrBuf.getInt() & 0xFFFFFFFFL;
+ mNoRxCount = bqrBuf.getInt() & 0xFFFFFFFFL;
+ mNakCount = bqrBuf.getInt() & 0xFFFFFFFFL;
+ mLastTxAckTimestamp = bqrBuf.getInt() & 0xFFFFFFFFL;
+ mFlowOffCount = bqrBuf.getInt() & 0xFFFFFFFFL;
+ mLastFlowOnTimestamp = bqrBuf.getInt() & 0xFFFFFFFFL;
+ mOverflowCount = bqrBuf.getInt() & 0xFFFFFFFFL;
+ mUnderflowCount = bqrBuf.getInt() & 0xFFFFFFFFL;
+ }
+ }
+
private BqrCommon(Parcel in) {
+ mVendorBqr5 = in.readBoolean();
mQualityReportId = in.readInt();
- mPacketType = in.readInt();
- mConnectionHandle = in.readInt();
- mConnectionRole = in.readInt();
- mTxPowerLevel = in.readInt();
- mRssi = in.readInt();
- mSnr = in.readInt();
- mUnusedAfhChannelCount = in.readInt();
- mAfhSelectUnidealChannelCount = in.readInt();
- mLsto = in.readInt();
- mPiconetClock = in.readLong();
- mRetransmissionCount = in.readLong();
- mNoRxCount = in.readLong();
- mNakCount = in.readLong();
- mLastTxAckTimestamp = in.readLong();
- mFlowOffCount = in.readLong();
- mLastFlowOnTimestamp = in.readLong();
- mOverflowCount = in.readLong();
- mUnderflowCount = in.readLong();
+ if(mVendorBqr5 == true &&
+ mQualityReportId == QUALITY_REPORT_ID_VENDOR_SPECIFIC) {
+ mVendorQualityReportId = in.readInt();
+ } else {
+ mPacketType = in.readInt();
+ mConnectionHandle = in.readInt();
+ mConnectionRole = in.readInt();
+ mTxPowerLevel = in.readInt();
+ mRssi = in.readInt();
+ mSnr = in.readInt();
+ mUnusedAfhChannelCount = in.readInt();
+ mAfhSelectUnidealChannelCount = in.readInt();
+ mLsto = in.readInt();
+ mPiconetClock = in.readLong();
+ mRetransmissionCount = in.readLong();
+ mNoRxCount = in.readLong();
+ mNakCount = in.readLong();
+ mLastTxAckTimestamp = in.readLong();
+ mFlowOffCount = in.readLong();
+ mLastFlowOnTimestamp = in.readLong();
+ mOverflowCount = in.readLong();
+ mUnderflowCount = in.readLong();
+ }
}
int getQualityReportId() {
return mQualityReportId;
}
+ int getVendorQualityReportId() {
+ return mVendorQualityReportId;
+ }
+
/**
* Get the packet type of the connection.
* @return the packet type.
@@ -677,31 +925,47 @@ public final class BluetoothQualityReport implements Parcelable {
@Override
public void writeToParcel(Parcel dest, int flags) {
+ dest.writeBoolean(mVendorBqr5);
dest.writeInt(mQualityReportId);
- dest.writeInt(mPacketType);
- dest.writeInt(mConnectionHandle);
- dest.writeInt(mConnectionRole);
- dest.writeInt(mTxPowerLevel);
- dest.writeInt(mRssi);
- dest.writeInt(mSnr);
- dest.writeInt(mUnusedAfhChannelCount);
- dest.writeInt(mAfhSelectUnidealChannelCount);
- dest.writeInt(mLsto);
- dest.writeLong(mPiconetClock);
- dest.writeLong(mRetransmissionCount);
- dest.writeLong(mNoRxCount);
- dest.writeLong(mNakCount);
- dest.writeLong(mLastTxAckTimestamp);
- dest.writeLong(mFlowOffCount);
- dest.writeLong(mLastFlowOnTimestamp);
- dest.writeLong(mOverflowCount);
- dest.writeLong(mUnderflowCount);
+ if(mVendorBqr5 == true &&
+ mQualityReportId == QUALITY_REPORT_ID_VENDOR_SPECIFIC) {
+ dest.writeInt(mVendorQualityReportId);
+ } else {
+ dest.writeInt(mPacketType);
+ dest.writeInt(mConnectionHandle);
+ dest.writeInt(mConnectionRole);
+ dest.writeInt(mTxPowerLevel);
+ dest.writeInt(mRssi);
+ dest.writeInt(mSnr);
+ dest.writeInt(mUnusedAfhChannelCount);
+ dest.writeInt(mAfhSelectUnidealChannelCount);
+ dest.writeInt(mLsto);
+ dest.writeLong(mPiconetClock);
+ dest.writeLong(mRetransmissionCount);
+ dest.writeLong(mNoRxCount);
+ dest.writeLong(mNakCount);
+ dest.writeLong(mLastTxAckTimestamp);
+ dest.writeLong(mFlowOffCount);
+ dest.writeLong(mLastFlowOnTimestamp);
+ dest.writeLong(mOverflowCount);
+ dest.writeLong(mUnderflowCount);
+ }
}
@Override
public String toString() {
String str;
- str = " BqrCommon: {\n"
+ if(mVendorBqr5 == true &&
+ mQualityReportId == QUALITY_REPORT_ID_VENDOR_SPECIFIC) {
+ str = " BqrCommon: {\n"
+ + " mQualityReportId: " + BluetoothQualityReport.this.getQualityReportIdStr()
+ + "(" + String.format("0x%02X", mQualityReportId) + ")"
+ + " mVendorQualityReportId: " + BluetoothQualityReport.this.getVendorQualityReportIdStr()
+ + "(" + String.format("0x%02X", mVendorQualityReportId) + ")"
+ + "\n }";
+ return str;
+ } else {
+ str = " BqrCommon: {\n"
+ " mQualityReportId: " + BluetoothQualityReport.this.getQualityReportIdStr()
+ "(" + String.format("0x%02X", mQualityReportId) + ")"
+ ", mPacketType: " + getPacketTypeStr()
@@ -726,10 +990,9 @@ public final class BluetoothQualityReport implements Parcelable {
+ ", mOverflowCount: " + mOverflowCount
+ ", mUnderflowCount: " + mUnderflowCount
+ "\n }";
-
- return str;
+ return str;
+ }
}
-
}
/**
@@ -798,12 +1061,93 @@ public final class BluetoothQualityReport implements Parcelable {
}
}
+ public class BqrVsQualityMonitor implements Parcelable {
+ private static final String TAG = BluetoothQualityReport.TAG + ".BqrVsQualityMonitor";
+ private int mPowerLevelInDbm;
+ private long mCrcErrorCount;
+ private long mDecryptErrorCount;
+ private long mLastSniffStartTimestamp;
+ private long mLastActiveStartTimestamp;
+
+ private BqrVsQualityMonitor(byte[] rawData, int offset) {
+ if (rawData == null || rawData.length <= offset) {
+ throw new IllegalArgumentException(TAG + ": BQR raw data length is abnormal.");
+ }
+
+ ByteBuffer bqrBuf = ByteBuffer.wrap(rawData, offset, rawData.length - offset)
+ .asReadOnlyBuffer();
+ bqrBuf.order(ByteOrder.LITTLE_ENDIAN);
+ mPowerLevelInDbm = bqrBuf.get() & 0xFF;
+ mCrcErrorCount = bqrBuf.getInt() & 0xFFFFFFFFL;
+ mDecryptErrorCount = bqrBuf.getInt() & 0xFFFFFFFFL;
+ mLastSniffStartTimestamp = bqrBuf.getInt() & 0xFFFFFFFFL;
+ mLastActiveStartTimestamp = bqrBuf.getInt() & 0xFFFFFFFFL;
+
+ }
+
+ private BqrVsQualityMonitor(Parcel in) {
+ mPowerLevelInDbm = in.readInt();
+ mCrcErrorCount = in.readLong();
+ mDecryptErrorCount = in.readLong();
+ mLastSniffStartTimestamp = in.readLong();
+ mLastActiveStartTimestamp = in.readLong();
+ }
+
+ public int getPowerLevelInDbm() {
+ return mPowerLevelInDbm;
+ }
+
+ public long getCrcErrorCount() {
+ return mCrcErrorCount;
+ }
+
+ public long getDecryptErrorCount() {
+ return mDecryptErrorCount;
+ }
+
+ public long getLastSniffStartTimestamp() {
+ return mLastSniffStartTimestamp;
+ }
+
+ public long getLastActiveStartTimestamp() {
+ return mLastActiveStartTimestamp;
+ }
+
+ public int describeContents(){
+ return 0;
+ }
+ @Override
+ public void writeToParcel(Parcel dest, int flags) {
+ dest.writeInt(mPowerLevelInDbm);
+ dest.writeLong(mCrcErrorCount);
+ dest.writeLong(mDecryptErrorCount);
+ dest.writeLong(mLastSniffStartTimestamp);
+ dest.writeLong(mLastActiveStartTimestamp);
+ }
+
+ @Override
+ public String toString() {
+ String str;
+ str = " BqrVsQualityMonitor: {\n"
+ + ", mPowerLevelInDbm: " + mPowerLevelInDbm
+ + ", mCrcErrorCount: " + mCrcErrorCount
+ + ", mDecryptErrorCount: " + mDecryptErrorCount
+ + ", mLastSniffStartTimestamp: " + mLastSniffStartTimestamp
+ + ", mLastActiveStartTimestamp: " + mLastActiveStartTimestamp
+ + "\n }";
+
+ return str;
+ }
+
+ }
+
/**
* This class provides the public APIs to access the vendor specific part of
* Approaching LSTO event.
*/
public class BqrVsLsto implements Parcelable {
private static final String TAG = BluetoothQualityReport.TAG + ".BqrVsLsto";
+ static final int BQR_VS_LSTO_LEN = 26;
private int mConnState;
private long mBasebandStats;
@@ -813,11 +1157,22 @@ public final class BluetoothQualityReport implements Parcelable {
private int mRfLoss;
private long mNativeClock;
private long mLastTxAckTimestamp;
+ private int mPowerLevelInDbm;
+ private long mCrcErrorCount;
+ private long mDecryptErrorCount;
+ private long mLastSniffStartTimestamp;
+ private long mLastActiveStartTimestamp;
+ private boolean isExtended;
private BqrVsLsto(byte[] rawData, int offset) {
if (rawData == null || rawData.length <= offset) {
throw new IllegalArgumentException(TAG + ": BQR raw data length is abnormal.");
}
+ if ((rawData.length - offset) > BQR_VS_LSTO_LEN) {
+ isExtended = true;
+ } else {
+ isExtended = false;
+ }
ByteBuffer bqrBuf = ByteBuffer.wrap(rawData, offset, rawData.length - offset)
.asReadOnlyBuffer();
@@ -831,9 +1186,18 @@ public final class BluetoothQualityReport implements Parcelable {
mRfLoss = bqrBuf.getShort() & 0xFFFF;
mNativeClock = bqrBuf.getInt() & 0xFFFFFFFFL;
mLastTxAckTimestamp = bqrBuf.getInt() & 0xFFFFFFFFL;
+ mPowerLevelInDbm = bqrBuf.get() & 0xFF;
+
+ if(isExtended) {
+ mCrcErrorCount = bqrBuf.getInt() & 0xFFFFFFFFL;
+ mDecryptErrorCount = bqrBuf.getInt() & 0xFFFFFFFFL;
+ mLastSniffStartTimestamp = bqrBuf.getInt() & 0xFFFFFFFFL;
+ mLastActiveStartTimestamp = bqrBuf.getInt() & 0xFFFFFFFFL;
+ }
}
private BqrVsLsto(Parcel in) {
+ isExtended = in.readBoolean();
mConnState = in.readInt();
mBasebandStats = in.readLong();
mSlotsUsed = in.readLong();
@@ -842,6 +1206,13 @@ public final class BluetoothQualityReport implements Parcelable {
mRfLoss = in.readInt();
mNativeClock = in.readLong();
mLastTxAckTimestamp = in.readLong();
+ mPowerLevelInDbm = in.readInt();
+ if(isExtended){
+ mCrcErrorCount = in.readLong();
+ mDecryptErrorCount = in.readLong();
+ mLastSniffStartTimestamp = in.readLong();
+ mLastActiveStartTimestamp = in.readLong();
+ }
}
/**
@@ -853,6 +1224,14 @@ public final class BluetoothQualityReport implements Parcelable {
}
/**
+ * Is extended to have few more params.
+ * @return true or false.
+ */
+ public boolean isExtended() {
+ return isExtended;
+ }
+
+ /**
* Get the string of conn state of sco.
* @return the string of conn state.
*/
@@ -909,6 +1288,26 @@ public final class BluetoothQualityReport implements Parcelable {
return mNativeClock;
}
+ public int getPowerLevelInDbm() {
+ return mPowerLevelInDbm;
+ }
+
+ public long getCrcErrorCount() {
+ return mCrcErrorCount;
+ }
+
+ public long getDecryptErrorCount() {
+ return mDecryptErrorCount;
+ }
+
+ public long getLastSniffStartTimestamp() {
+ return mLastSniffStartTimestamp;
+ }
+
+ public long getLastActiveStartTimestamp() {
+ return mLastActiveStartTimestamp;
+ }
+
/**
* Get the timestamp of last TX ACK.
* time_ms: N * 0.3125 ms (1 Bluetooth Clock).
@@ -924,6 +1323,7 @@ public final class BluetoothQualityReport implements Parcelable {
@Override
public void writeToParcel(Parcel dest, int flags) {
+ dest.writeBoolean(isExtended);
dest.writeInt(mConnState);
dest.writeLong(mBasebandStats);
dest.writeLong(mSlotsUsed);
@@ -932,12 +1332,21 @@ public final class BluetoothQualityReport implements Parcelable {
dest.writeInt(mRfLoss);
dest.writeLong(mNativeClock);
dest.writeLong(mLastTxAckTimestamp);
+ dest.writeInt(mPowerLevelInDbm);
+ if(isExtended){
+ dest.writeLong(mCrcErrorCount);
+ dest.writeLong(mDecryptErrorCount);
+ dest.writeLong(mLastSniffStartTimestamp);
+ dest.writeLong(mLastActiveStartTimestamp);
+ }
+
}
@Override
public String toString() {
String str;
- str = " BqrVsLsto: {\n"
+ str = " BqrVsLsto: {\n"
+ + ", isExtended: " + isExtended
+ " mConnState: " + getConnStateStr()
+ "(" + String.format("0x%02X", mConnState) + ")"
+ ", mBasebandStats: " + String.format("0x%08X", mBasebandStats)
@@ -947,10 +1356,19 @@ public final class BluetoothQualityReport implements Parcelable {
+ ", mRfLoss: " + mRfLoss
+ ", mNativeClock: " + String.format("0x%08X", mNativeClock)
+ ", mLastTxAckTimestamp: " + String.format("0x%08X", mLastTxAckTimestamp)
+ + ", mPowerLevelInDbm: " + mPowerLevelInDbm
+ "\n }";
+ if (isExtended) {
+ str += ", mCrcErrorCount: " + mCrcErrorCount
+ + ", mDecryptErrorCount: " + mDecryptErrorCount
+ + ", mLastSniffStartTimestamp: " + mLastSniffStartTimestamp
+ + ", mLastActiveStartTimestamp: " + mLastActiveStartTimestamp
+ + "\n }";
+ }
return str;
}
+
}
/**
@@ -959,6 +1377,7 @@ public final class BluetoothQualityReport implements Parcelable {
*/
public class BqrVsA2dpChoppy implements Parcelable {
private static final String TAG = BluetoothQualityReport.TAG + ".BqrVsA2dpChoppy";
+ private static final int BQR_VS_A2DPCHOPPY_LEN = 16;
private long mArrivalTime;
private long mScheduleTime;
@@ -967,33 +1386,100 @@ public final class BluetoothQualityReport implements Parcelable {
private int mRxCxmDenials;
private int mAclTxQueueLength;
private int mLinkQuality;
+ private int mPowerLevelInDbm;
+ private int mA2dpRole;
+ private long mCrcErrorCount;
+ private long mDecryptErrorCount;
+ private long mLastSniffStartTimestamp;
+ private long mLastActiveStartTimestamp;
+ private long mFlushedA2dpPacketCount;
+ private long mSinkJitterBufferOverrunCount;
+ private long mSinkJitterUnderrunCount;
+ private long mSinkRetransmissionAckCount;
+ private boolean isExtended;
+ private int role;
private BqrVsA2dpChoppy(byte[] rawData, int offset) {
if (rawData == null || rawData.length <= offset) {
throw new IllegalArgumentException(TAG + ": BQR raw data length is abnormal.");
}
-
+ if ((rawData.length - offset) > BQR_VS_A2DPCHOPPY_LEN) {
+ isExtended = true;
+ } else {
+ isExtended = false;
+ }
+ if(isExtended) {
+ int roleOffset = 16;
+ ByteBuffer bqrBufRole = ByteBuffer.wrap(rawData, offset, rawData.length - (offset + roleOffset))
+ .asReadOnlyBuffer();
+ role = bqrBufRole.get() & 0xFF;
+ } else {
+ role = 1; // TODO to macro
+ }
ByteBuffer bqrBuf = ByteBuffer.wrap(rawData, offset, rawData.length - offset)
.asReadOnlyBuffer();
bqrBuf.order(ByteOrder.LITTLE_ENDIAN);
- mArrivalTime = bqrBuf.getInt() & 0xFFFFFFFFL;
- mScheduleTime = bqrBuf.getInt() & 0xFFFFFFFFL;
- mGlitchCount = bqrBuf.getShort() & 0xFFFF;
- mTxCxmDenials = bqrBuf.getShort() & 0xFFFF;
- mRxCxmDenials = bqrBuf.getShort() & 0xFFFF;
- mAclTxQueueLength = bqrBuf.get() & 0xFF;
- mLinkQuality = bqrBuf.get() & 0xFF;
+ if (isExtended == true) {
+ mArrivalTime = bqrBuf.getInt() & 0xFFFFFFFFL;
+ mScheduleTime = bqrBuf.getInt() & 0xFFFFFFFFL;
+ mGlitchCount = bqrBuf.getShort() & 0xFFFF;
+ mTxCxmDenials = bqrBuf.getShort() & 0xFFFF;
+ mRxCxmDenials = bqrBuf.getShort() & 0xFFFF;
+ mAclTxQueueLength = bqrBuf.get() & 0xFF;
+ mLinkQuality = bqrBuf.get() & 0xFF;
+ mPowerLevelInDbm = bqrBuf.get() & 0xFF;
+ mA2dpRole = bqrBuf.get() & 0xFF;
+ mCrcErrorCount = bqrBuf.getInt() & 0xFFFFFFFFL;
+ mDecryptErrorCount = bqrBuf.getInt() & 0xFFFFFFFFL;
+ mLastSniffStartTimestamp = bqrBuf.getInt() & 0xFFFFFFFFL;
+ mLastActiveStartTimestamp = bqrBuf.getInt() & 0xFFFFFFFFL;
+ mFlushedA2dpPacketCount = bqrBuf.getInt() & 0xFFFFFFFFL;
+ mSinkJitterBufferOverrunCount = bqrBuf.getInt() & 0xFFFFFFFFL;
+ mSinkJitterUnderrunCount = bqrBuf.getInt() & 0xFFFFFFFFL;
+ mSinkRetransmissionAckCount = bqrBuf.getInt() & 0xFFFFFFFFL;
+ } else {
+ mArrivalTime = bqrBuf.getInt() & 0xFFFFFFFFL;
+ mScheduleTime = bqrBuf.getInt() & 0xFFFFFFFFL;
+ mGlitchCount = bqrBuf.getShort() & 0xFFFF;
+ mTxCxmDenials = bqrBuf.getShort() & 0xFFFF;
+ mRxCxmDenials = bqrBuf.getShort() & 0xFFFF;
+ mAclTxQueueLength = bqrBuf.get() & 0xFF;
+ mLinkQuality = bqrBuf.get() & 0xFF;
+ mPowerLevelInDbm = bqrBuf.get() & 0xFF;
+ }
}
private BqrVsA2dpChoppy(Parcel in) {
- mArrivalTime = in.readLong();
- mScheduleTime = in.readLong();
- mGlitchCount = in.readInt();
- mTxCxmDenials = in.readInt();
- mRxCxmDenials = in.readInt();
- mAclTxQueueLength = in.readInt();
- mLinkQuality = in.readInt();
+ isExtended = in.readBoolean();
+ if(isExtended==true) {
+ mArrivalTime = in.readLong();
+ mScheduleTime = in.readLong();
+ mGlitchCount = in.readInt();
+ mTxCxmDenials = in.readInt();
+ mRxCxmDenials = in.readInt();
+ mAclTxQueueLength = in.readInt();
+ mLinkQuality = in.readInt();
+ mPowerLevelInDbm = in.readInt();
+ mA2dpRole = in.readInt();
+ mCrcErrorCount = in.readLong();
+ mDecryptErrorCount = in.readLong();
+ mLastSniffStartTimestamp = in.readLong();
+ mLastActiveStartTimestamp = in.readLong();
+ mFlushedA2dpPacketCount = in.readLong();
+ mSinkJitterBufferOverrunCount = in.readLong();
+ mSinkJitterUnderrunCount = in.readLong();
+ mSinkRetransmissionAckCount = in.readLong();
+ } else {
+ mArrivalTime = in.readLong();
+ mScheduleTime = in.readLong();
+ mGlitchCount = in.readInt();
+ mTxCxmDenials = in.readInt();
+ mRxCxmDenials = in.readInt();
+ mAclTxQueueLength = in.readInt();
+ mLinkQuality = in.readInt();
+ mPowerLevelInDbm = in.readInt();
+ }
}
/**
@@ -1022,6 +1508,10 @@ public final class BluetoothQualityReport implements Parcelable {
return mGlitchCount;
}
+ public int getSinkGlitchCount() {
+ return mGlitchCount;
+ }
+
/**
* Get the count of Coex TX denials.
* @return the count of Coex TX denials.
@@ -1038,6 +1528,14 @@ public final class BluetoothQualityReport implements Parcelable {
return mRxCxmDenials;
}
+ public int getSinkTxCxmDenials() {
+ return mTxCxmDenials;
+ }
+
+ public int getSinkRxCxmDenials() {
+ return mRxCxmDenials;
+ }
+
/**
* Get the ACL queue length which are pending TX in FW.
* @return the ACL queue length.
@@ -1067,21 +1565,107 @@ public final class BluetoothQualityReport implements Parcelable {
return 0;
}
- @Override
- public void writeToParcel(Parcel dest, int flags) {
- dest.writeLong(mArrivalTime);
- dest.writeLong(mScheduleTime);
- dest.writeInt(mGlitchCount);
- dest.writeInt(mTxCxmDenials);
- dest.writeInt(mRxCxmDenials);
- dest.writeInt(mAclTxQueueLength);
- dest.writeInt(mLinkQuality);
+ public int getPowerLevelInDbm() {
+ return mPowerLevelInDbm;
}
- @Override
- public String toString() {
+ public int getA2dpRole() {
+ return mA2dpRole;
+ }
+
+ public long getCrcErrorCount() {
+ return mCrcErrorCount;
+ }
+
+ public long getSinkCrcErrorCount() {
+ return mCrcErrorCount;
+ }
+
+ public long getDecryptErrorCount() {
+ return mDecryptErrorCount;
+ }
+
+ public long getSinkDecryptErrorCount() {
+ return mDecryptErrorCount;
+ }
+
+ public long getLastSniffStartTimestamp() {
+ return mLastSniffStartTimestamp;
+ }
+ public long getSinkLastSniffStartTimestamp() {
+ return mLastSniffStartTimestamp;
+ }
+
+ public long getLastActiveStartTimestamp() {
+ return mLastActiveStartTimestamp;
+ }
+
+ public long getSinkLastActiveStartTimestamp() {
+ return mLastActiveStartTimestamp;
+ }
+
+ public long getFlushedA2dpPacketCount() {
+ return mFlushedA2dpPacketCount;
+ }
+
+ public long getSinkA2dpJitterBufferOverrunCount() {
+ return mSinkJitterBufferOverrunCount;
+ }
+
+ public long getSinkA2dpJitterUnderrunCount() {
+ return mSinkJitterUnderrunCount;
+ }
+
+ public long getSinkA2dpReTransmissionAckCounnt() {
+ return mSinkRetransmissionAckCount;
+ }
+
+ /**
+ * Is extended to have few more params.
+ * @return true or false.
+ */
+ public boolean isExtended() {
+ return isExtended;
+ }
+
+ @Override
+ public void writeToParcel(Parcel dest, int flags) {
+ dest.writeBoolean(isExtended);
+ if(isExtended==true){
+ dest.writeLong(mArrivalTime);
+ dest.writeLong(mScheduleTime);
+ dest.writeInt(mGlitchCount);
+ dest.writeInt(mTxCxmDenials);
+ dest.writeInt(mRxCxmDenials);
+ dest.writeInt(mAclTxQueueLength);
+ dest.writeInt(mLinkQuality);
+ dest.writeInt(mPowerLevelInDbm);
+ dest.writeInt(mA2dpRole);
+ dest.writeLong(mCrcErrorCount);
+ dest.writeLong(mDecryptErrorCount);
+ dest.writeLong(mLastSniffStartTimestamp);
+ dest.writeLong(mLastActiveStartTimestamp);
+ dest.writeLong(mFlushedA2dpPacketCount);
+ dest.writeLong(mSinkJitterBufferOverrunCount);
+ dest.writeLong(mSinkJitterUnderrunCount);
+ dest.writeLong(mSinkRetransmissionAckCount);
+ } else {
+ dest.writeLong(mArrivalTime);
+ dest.writeLong(mScheduleTime);
+ dest.writeInt(mGlitchCount);
+ dest.writeInt(mTxCxmDenials);
+ dest.writeInt(mRxCxmDenials);
+ dest.writeInt(mAclTxQueueLength);
+ dest.writeInt(mLinkQuality);
+ dest.writeInt(mPowerLevelInDbm);
+ }
+ }
+
+ @Override
+ public String toString() {
String str;
str = " BqrVsA2dpChoppy: {\n"
+ + ", isExtended: " + isExtended
+ " mArrivalTime: " + String.format("0x%08X", mArrivalTime)
+ ", mScheduleTime: " + String.format("0x%08X", mScheduleTime)
+ ", mGlitchCount: " + mGlitchCount
@@ -1090,19 +1674,32 @@ public final class BluetoothQualityReport implements Parcelable {
+ ", mAclTxQueueLength: " + mAclTxQueueLength
+ ", mLinkQuality: " + getLinkQualityStr()
+ "(" + String.format("0x%02X", mLinkQuality) + ")"
+ + ",mPowerLevelInDbm: " + mPowerLevelInDbm
+ "\n }";
-
+ if(isExtended) {
+ str += "mA2dpRole: " + mA2dpRole
+ + ", mCrcErrorCount: " + mCrcErrorCount
+ + ", mDecryptErrorCount: " + mDecryptErrorCount
+ + ", mLastSniffStartTimestamp: " + mLastSniffStartTimestamp
+ + ", mLastActiveStartTimestamp:" + mLastActiveStartTimestamp
+ + ", mFlushedA2dpPacketCount: " + mFlushedA2dpPacketCount
+ + ", mSinkJitterBufferOverrunCount: " + mSinkJitterBufferOverrunCount
+ + ", mSinkJitterUnderrunCount: " + mSinkJitterUnderrunCount
+ + ", mSinkRetransmissionAckCount: " + mSinkRetransmissionAckCount
+ + "\n }";
+ }
return str;
}
-
}
+
/**
* This class provides the public APIs to access the vendor specific part of
* SCO choppy event.
*/
public class BqrVsScoChoppy implements Parcelable {
private static final String TAG = BluetoothQualityReport.TAG + ".BqrVsScoChoppy";
+ private static final int BQR_VS_SCOCHOPPY_LEN = 34;
private int mGlitchCount;
private int mIntervalEsco;
@@ -1122,12 +1719,22 @@ public final class BluetoothQualityReport implements Parcelable {
private int mTxRetransmitSlotCount;
private int mRxRetransmitSlotCount;
private int mGoodRxFrameCount;
-
+ private int mPowerLevelInDbm;
+ private long mCrcErrorCount;
+ private long mDecryptErrorCount;
+ private long mLastSniffStartTimestamp;
+ private long mLastActiveStartTimestamp;
+ private boolean isExtended;
private BqrVsScoChoppy(byte[] rawData, int offset) {
if (rawData == null || rawData.length <= offset) {
throw new IllegalArgumentException(TAG + ": BQR raw data length is abnormal.");
}
-
+ if((rawData.length - offset) > BQR_VS_SCOCHOPPY_LEN){
+ isExtended = true;
+ }
+ else{
+ isExtended = false;
+ }
ByteBuffer bqrBuf = ByteBuffer.wrap(rawData, offset, rawData.length - offset)
.asReadOnlyBuffer();
bqrBuf.order(ByteOrder.LITTLE_ENDIAN);
@@ -1151,12 +1758,20 @@ public final class BluetoothQualityReport implements Parcelable {
mTxRetransmitSlotCount = bqrBuf.getShort() & 0xFFFF;
mRxRetransmitSlotCount = bqrBuf.getShort() & 0xFFFF;
mGoodRxFrameCount = bqrBuf.getShort() & 0xFFFF;
+ mPowerLevelInDbm = bqrBuf.get() & 0xFF;
} catch (BufferUnderflowException e) {
Log.v(TAG, "some fields are not contained");
}
+ if(isExtended) {
+ mCrcErrorCount = bqrBuf.getInt() & 0xFFFFFFFFL;
+ mDecryptErrorCount = bqrBuf.getInt() & 0xFFFFFFFFL;
+ mLastSniffStartTimestamp = bqrBuf.getInt() & 0xFFFFFFFFL;
+ mLastActiveStartTimestamp = bqrBuf.getInt() & 0xFFFFFFFFL;
+ }
}
private BqrVsScoChoppy(Parcel in) {
+ isExtended = in.readBoolean();
mGlitchCount = in.readInt();
mIntervalEsco = in.readInt();
mWindowEsco = in.readInt();
@@ -1175,6 +1790,13 @@ public final class BluetoothQualityReport implements Parcelable {
mTxRetransmitSlotCount = in.readInt();
mRxRetransmitSlotCount = in.readInt();
mGoodRxFrameCount = in.readInt();
+ mPowerLevelInDbm = in.readInt();
+ if (isExtended) {
+ mCrcErrorCount = in.readLong();
+ mDecryptErrorCount = in.readLong();
+ mLastSniffStartTimestamp = in.readLong();
+ mLastActiveStartTimestamp = in.readLong();
+ }
}
/**
@@ -1333,12 +1955,42 @@ public final class BluetoothQualityReport implements Parcelable {
return mGoodRxFrameCount;
}
+ public int getPowerLevelInDbm() {
+ return mPowerLevelInDbm;
+ }
+
+ public long getCrcErrorCount() {
+ return mCrcErrorCount;
+ }
+
+ public long getDecryptErrorCount() {
+ return mDecryptErrorCount;
+ }
+
+ public long getLastSniffStartTimestamp() {
+ return mLastSniffStartTimestamp;
+ }
+
+ public long getLastActiveStartTimestamp() {
+ return mLastActiveStartTimestamp;
+ }
+
+
public int describeContents() {
return 0;
}
+ /**
+ * Is extended to have few more params.
+ * @return true or false.
+ */
+ public boolean isExtended() {
+ return isExtended;
+ }
+
@Override
public void writeToParcel(Parcel dest, int flags) {
+ dest.writeBoolean(isExtended);
dest.writeInt(mGlitchCount);
dest.writeInt(mIntervalEsco);
dest.writeInt(mWindowEsco);
@@ -1357,12 +2009,20 @@ public final class BluetoothQualityReport implements Parcelable {
dest.writeInt(mTxRetransmitSlotCount);
dest.writeInt(mRxRetransmitSlotCount);
dest.writeInt(mGoodRxFrameCount);
+ dest.writeInt(mPowerLevelInDbm);
+ if(isExtended){
+ dest.writeLong(mCrcErrorCount);
+ dest.writeLong(mDecryptErrorCount);
+ dest.writeLong(mLastSniffStartTimestamp);
+ dest.writeLong(mLastActiveStartTimestamp);
+ }
}
@Override
public String toString() {
String str;
str = " BqrVsScoChoppy: {\n"
+ + ", isExtended: " + isExtended
+ " mGlitchCount: " + mGlitchCount
+ ", mIntervalEsco: " + mIntervalEsco
+ ", mWindowEsco: " + mWindowEsco
@@ -1384,8 +2044,202 @@ public final class BluetoothQualityReport implements Parcelable {
+ ",\n"
+ " mRxRetransmitSlotCount: " + mRxRetransmitSlotCount
+ ", mGoodRxFrameCount: " + mGoodRxFrameCount
+ + "mPowerLevelInDbm: " + mPowerLevelInDbm
+ + "\n }";
+ if(isExtended) {
+ str += ", mCrcErrorCount: " + mCrcErrorCount
+ + ", mDecryptErrorCount: " + mDecryptErrorCount
+ + ", mLastSniffStartTimestamp: " + mLastSniffStartTimestamp
+ + ", mLastActiveStartTimestamp: " + mLastActiveStartTimestamp
+ + "\n }";
+ }
+ return str;
+ }
+ }
+
+ public class BqrVsDiscoveryMonitoring implements Parcelable {
+ private static final String TAG = BluetoothQualityReport.TAG + ".BqrVsDiscoveryMonitoring";
+ private long mInquiryCount;
+ private long mInquiryScanWindowCount;
+ private long mInquiryScanWindowDuration;
+ private long mPageScanWindowCount;
+ private long mPageScanWindowDuration;
+ private long mBleAdvertisementCount;
+ private long mBleScanWindowCount;
+ private long mBleScanWindowDuration;
+ private long mBleScanRequestCount;
+ private long mBleScanResponseCount;
+
+ private BqrVsDiscoveryMonitoring(byte[] rawData, int offset) {
+ if (rawData == null || rawData.length <= offset) {
+ throw new IllegalArgumentException(TAG + ": BQR raw data length is abnormal.");
+ }
+
+ ByteBuffer bqrBuf = ByteBuffer.wrap(rawData, offset, rawData.length - offset)
+ .asReadOnlyBuffer();
+ bqrBuf.order(ByteOrder.LITTLE_ENDIAN);
+ mInquiryCount = bqrBuf.getInt() & 0xFFFFFFFFL;
+ mInquiryScanWindowCount = bqrBuf.getInt() & 0xFFFFFFFFL;
+ mInquiryScanWindowDuration = bqrBuf.getInt() & 0xFFFFFFFFL;
+ mPageScanWindowCount = bqrBuf.getInt() & 0xFFFFFFFFL;
+ mPageScanWindowDuration = bqrBuf.getInt() & 0xFFFFFFFFL;
+ mBleAdvertisementCount = bqrBuf.getInt() & 0xFFFFFFFFL;
+ mBleScanWindowCount = bqrBuf.getInt() & 0xFFFFFFFFL;
+ mBleScanWindowDuration = bqrBuf.getInt() & 0xFFFFFFFFL;
+ mBleScanRequestCount = bqrBuf.getInt() & 0xFFFFFFFFL;
+ mBleScanResponseCount = bqrBuf.getInt() & 0xFFFFFFFFL;
+
+ }
+
+ private BqrVsDiscoveryMonitoring(Parcel in) {
+ mInquiryCount = in.readLong();
+ mInquiryScanWindowCount = in.readLong();
+ mInquiryScanWindowDuration = in.readLong();
+ mPageScanWindowCount = in.readLong();
+ mPageScanWindowDuration = in.readLong();
+ mBleAdvertisementCount = in.readLong();
+ mBleScanRequestCount = in.readLong();
+ mBleScanWindowDuration = in.readLong();
+ mBleScanRequestCount = in.readLong();
+ mBleScanResponseCount = in.readLong();
+ }
+
+ public long getInquiryCount() {
+ return mInquiryCount;
+ }
+
+ public long getInquiryScanWindowCount() {
+ return mInquiryScanWindowCount;
+ }
+
+ public long getInquiryScanWindowDuration() {
+ return mInquiryScanWindowDuration;
+ }
+
+ public long getPageScanWindowCount() {
+ return mPageScanWindowCount;
+ }
+
+ public long getBleAdvertisementCount() {
+ return mBleAdvertisementCount;
+ }
+
+ public long getBleScanWindowCount() {
+ return mBleScanWindowCount;
+ }
+
+ public long getBleScanWindowDuration() {
+ return mBleScanWindowDuration;
+ }
+
+ public long getBleScanRequestCount() {
+ return mBleScanRequestCount;
+ }
+
+ public long getBleScanResponseCount() {
+ return mBleScanResponseCount;
+ }
+ public int describeContents(){
+ return 0;
+ }
+ @Override
+ public void writeToParcel(Parcel dest, int flags) {
+ dest.writeLong(mInquiryCount);
+ dest.writeLong(mInquiryScanWindowCount);
+ dest.writeLong(mInquiryScanWindowDuration);
+ dest.writeLong(mPageScanWindowCount);
+ dest.writeLong(mPageScanWindowDuration);
+ dest.writeLong(mBleAdvertisementCount);
+ dest.writeLong(mBleScanWindowCount);
+ dest.writeLong(mBleScanWindowDuration);
+ dest.writeLong(mBleScanRequestCount);
+ dest.writeLong(mBleScanResponseCount);
+ }
+
+ @Override
+ public String toString() {
+ String str = "";
+ str = " BqrVsDiscoveryMonitoring: {\n"
+ + ", mInquiryCount: " + mInquiryCount
+ + ", mInquiryScanWindowCount: " + mInquiryScanWindowCount
+ + ", mInquiryScanWindowDuration: " + mInquiryScanWindowDuration
+ + ", mPageScanWindowCount: " + mPageScanWindowCount
+ + ", mPageScanWindowDuration: " + mPageScanWindowDuration
+ + ", mBleAdvertisementCount: " + mBleAdvertisementCount
+ + ", mBleScanWindowCount: " + mBleScanWindowCount
+ + ", mBleScanWindowDuration: " + mBleScanWindowDuration
+ + ", mBleScanRequestCount: " + mBleScanRequestCount
+ + ", mBleScanResponseCount: " + mBleScanResponseCount
+ "\n }";
+ return str;
+ }
+
+ }
+
+ public class BqrVsMiscMonitoring implements Parcelable {
+ private static final String TAG = BluetoothQualityReport.TAG + ".BqrVsMiscMonitoring";
+ private long mRadioWakeupCount;
+ private long mHciWakeupCount;
+ private long mErrorWakeupCount;
+ private long mCoexRejectCount;
+
+ private BqrVsMiscMonitoring(byte[] rawData, int offset) {
+ if (rawData == null || rawData.length <= offset) {
+ throw new IllegalArgumentException(TAG + ": BQR raw data length is abnormal.");
+ }
+
+ ByteBuffer bqrBuf = ByteBuffer.wrap(rawData, offset, rawData.length - offset)
+ .asReadOnlyBuffer();
+ bqrBuf.order(ByteOrder.LITTLE_ENDIAN);
+ mRadioWakeupCount = bqrBuf.getInt() & 0xFFFFFFFFL;
+ mHciWakeupCount = bqrBuf.getInt() & 0xFFFFFFFFL;
+ mErrorWakeupCount = bqrBuf.getInt() & 0xFFFFFFFFL;
+ mCoexRejectCount = bqrBuf.getInt() & 0xFFFFFFFFL;
+ }
+
+ private BqrVsMiscMonitoring(Parcel in) {
+ mRadioWakeupCount = in.readLong();
+ mHciWakeupCount = in.readLong();
+ mErrorWakeupCount = in.readLong();
+ mCoexRejectCount = in.readLong();
+ }
+
+ public long getRadioWakeupCount() {
+ return mRadioWakeupCount;
+ }
+
+ public long getHciWakeupCount() {
+ return mHciWakeupCount;
+ }
+ public long getErrorWakeupCount() {
+ return mErrorWakeupCount;
+ }
+
+ public long getCoexRejectCount() {
+ return mCoexRejectCount;
+ }
+
+ public int describeContents(){
+ return 0;
+ }
+ @Override
+ public void writeToParcel(Parcel dest, int flags) {
+ dest.writeLong(mRadioWakeupCount);
+ dest.writeLong(mHciWakeupCount);
+ dest.writeLong(mErrorWakeupCount);
+ dest.writeLong(mCoexRejectCount);
+ }
+
+ @Override
+ public String toString() {
+ String str = "";
+ str = " BqrVsMiscMonitoring: {\n"
+ + ", mRadioWakeupCount: " + mRadioWakeupCount
+ + ", mHciWakeupCount: " + mHciWakeupCount
+ + ", mErrorWakeupCount: " + mErrorWakeupCount
+ + ", mCoexRejectCount: " + mCoexRejectCount
+ + "\n }";
return str;
}
@@ -1399,7 +2253,6 @@ public final class BluetoothQualityReport implements Parcelable {
private static final String TAG = BluetoothQualityReport.TAG + ".BqrVsConnectFail";
private int mFailReason;
-
private BqrVsConnectFail(byte[] rawData, int offset) {
if (rawData == null || rawData.length <= offset) {
throw new IllegalArgumentException(TAG + ": BQR raw data length is abnormal.");
@@ -1415,7 +2268,6 @@ public final class BluetoothQualityReport implements Parcelable {
private BqrVsConnectFail(Parcel in) {
mFailReason = in.readInt();
}
-
/**
* Get the fail reason.
* @return the fail reason.
@@ -1430,9 +2282,8 @@ public final class BluetoothQualityReport implements Parcelable {
@Override
public void writeToParcel(Parcel dest, int flags) {
- dest.writeInt(mFailReason);
+ dest.writeInt(mFailReason);
}
-
@Override
public String toString() {
String str;
@@ -1445,3 +2296,5 @@ public final class BluetoothQualityReport implements Parcelable {
}
}
+
+