xref: /aosp_15_r20/cts/tests/tests/bluetooth/src/android/bluetooth/cts/BluetoothQualityReportTest.java (revision b7c941bb3fa97aba169d73cee0bed2de8ac964bf)
1 /*
2  * Copyright 2023 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package android.bluetooth.cts;
18 
19 import android.bluetooth.BluetoothClass;
20 import android.bluetooth.BluetoothQualityReport;
21 import android.bluetooth.BluetoothQualityReport.BqrCommon;
22 import android.bluetooth.BluetoothQualityReport.BqrConnectFail;
23 import android.bluetooth.BluetoothQualityReport.BqrEnergyMonitor;
24 import android.bluetooth.BluetoothQualityReport.BqrRfStats;
25 import android.bluetooth.BluetoothQualityReport.BqrVsA2dpChoppy;
26 import android.bluetooth.BluetoothQualityReport.BqrVsLsto;
27 import android.bluetooth.BluetoothQualityReport.BqrVsScoChoppy;
28 import android.os.Parcel;
29 import android.platform.test.annotations.RequiresFlagsEnabled;
30 import android.platform.test.flag.junit.CheckFlagsRule;
31 import android.platform.test.flag.junit.DeviceFlagsValueProvider;
32 import android.util.Log;
33 
34 import androidx.test.ext.junit.runners.AndroidJUnit4;
35 
36 import com.android.bluetooth.flags.Flags;
37 
38 import com.google.common.truth.Expect;
39 
40 import org.junit.Assert;
41 import org.junit.Rule;
42 import org.junit.Test;
43 import org.junit.runner.RunWith;
44 
45 import java.nio.ByteBuffer;
46 import java.nio.ByteOrder;
47 
48 @RunWith(AndroidJUnit4.class)
49 public final class BluetoothQualityReportTest {
50 
51     @Rule public final Expect expect = Expect.create();
52 
53     @Rule
54     public final CheckFlagsRule mCheckFlagsRule = DeviceFlagsValueProvider.createCheckFlagsRule();
55 
56     private static final String TAG = "BluetoothQualityReportTest";
57 
58     private static String mRemoteAddress = "01:02:03:04:05:06";
59     private static String mDefaultAddress = "00:00:00:00:00:00";
60     private static String mRemoteName = "DeviceName";
61     private static String mDefaultName = "";
62     private static int mLmpVer = 0;
63     private static int mLmpSubVer = 1;
64     private static int mManufacturerId = 3;
65     private static int mRemoteCoD = 4;
66 
assertBqrCommon(BQRParameters bqrp, BluetoothQualityReport bqr)67     private void assertBqrCommon(BQRParameters bqrp, BluetoothQualityReport bqr) {
68         // BQR Common
69         BqrCommon bqrCommon = bqr.getBqrCommon();
70         Assert.assertNotNull(bqrCommon);
71         Assert.assertEquals(bqr.getQualityReportId(), bqrp.getQualityReportId());
72         if ((bqr.getQualityReportId() == BluetoothQualityReport.QUALITY_REPORT_ID_ENERGY_MONITOR)
73                 || (bqr.getQualityReportId()
74                         == BluetoothQualityReport.QUALITY_REPORT_ID_RF_STATS)) {
75             return;
76         }
77         Assert.assertEquals(bqrp.mPacketType, bqrCommon.getPacketType());
78         Assert.assertEquals("TYPE_NULL", BqrCommon.packetTypeToString(bqrCommon.getPacketType()));
79         Assert.assertEquals(bqrp.mConnectionHandle, bqrCommon.getConnectionHandle());
80         Assert.assertTrue(
81                 bqrp.mConnectionRoleCentral.equals(
82                         BqrCommon.connectionRoleToString(bqrCommon.getConnectionRole())));
83         Assert.assertEquals(bqrp.mConnectionRole, bqrCommon.getConnectionRole());
84         Assert.assertEquals(bqrp.mTxPowerLevel, bqrCommon.getTxPowerLevel());
85         Assert.assertEquals(bqrp.mRssi, bqrCommon.getRssi());
86         Assert.assertEquals(bqrp.mSnr, bqrCommon.getSnr());
87         Assert.assertEquals(bqrp.mUnusedAfhChannelCount, bqrCommon.getUnusedAfhChannelCount());
88         Assert.assertEquals(
89                 bqrp.mAfhSelectUnidealChannelCount, bqrCommon.getAfhSelectUnidealChannelCount());
90         Assert.assertEquals(bqrp.mLsto, bqrCommon.getLsto());
91         Assert.assertEquals(bqrp.mPiconetClock, bqrCommon.getPiconetClock());
92         Assert.assertEquals(bqrp.mRetransmissionCount, bqrCommon.getRetransmissionCount());
93         Assert.assertEquals(bqrp.mNoRxCount, bqrCommon.getNoRxCount());
94         Assert.assertEquals(bqrp.mNakCount, bqrCommon.getNakCount());
95         Assert.assertEquals(bqrp.mLastTxAckTimestamp, bqrCommon.getLastTxAckTimestamp());
96         Assert.assertEquals(bqrp.mFlowOffCount, bqrCommon.getFlowOffCount());
97         Assert.assertEquals(bqrp.mLastFlowOnTimestamp, bqrCommon.getLastFlowOnTimestamp());
98         Assert.assertEquals(bqrp.mOverflowCount, bqrCommon.getOverflowCount());
99         Assert.assertEquals(bqrp.mUnderflowCount, bqrCommon.getUnderflowCount());
100         Assert.assertEquals(bqrp.mCalFailedItemCount, bqrCommon.getCalFailedItemCount());
101     }
102 
assertBqrApproachLsto(BQRParameters bqrp, BluetoothQualityReport bqr)103     private void assertBqrApproachLsto(BQRParameters bqrp, BluetoothQualityReport bqr) {
104         // BQR VS LSTO
105         BqrVsLsto bqrVsLsto = (BqrVsLsto) bqr.getBqrEvent();
106         Assert.assertNotNull(bqrVsLsto);
107         Assert.assertEquals(
108                 "Approaching LSTO",
109                 BluetoothQualityReport.qualityReportIdToString(bqr.getQualityReportId()));
110         Assert.assertEquals(bqrp.mConnState & 0xFF, bqrVsLsto.getConnState());
111         Assert.assertEquals(
112                 "CONN_UNPARK_ACTIVE", BqrVsLsto.connStateToString(bqrVsLsto.getConnState()));
113         Assert.assertEquals(bqrp.mBasebandStats, bqrVsLsto.getBasebandStats());
114         Assert.assertEquals(bqrp.mSlotsUsed, bqrVsLsto.getSlotsUsed());
115         Assert.assertEquals(bqrp.mCxmDenials, bqrVsLsto.getCxmDenials());
116         Assert.assertEquals(bqrp.mTxSkipped, bqrVsLsto.getTxSkipped());
117         Assert.assertEquals(bqrp.mRfLoss, bqrVsLsto.getRfLoss());
118         Assert.assertEquals(bqrp.mNativeClock, bqrVsLsto.getNativeClock());
119         Assert.assertEquals(bqrp.mLastTxAckTimestampLsto, bqrVsLsto.getLastTxAckTimestamp());
120         Assert.assertEquals(0, bqrVsLsto.describeContents());
121     }
122 
assertBqrA2dpChoppy(BQRParameters bqrp, BluetoothQualityReport bqr)123     private void assertBqrA2dpChoppy(BQRParameters bqrp, BluetoothQualityReport bqr) {
124         // BQR VS A2DP Choppy
125         BqrVsA2dpChoppy bqrVsA2dpChoppy = (BqrVsA2dpChoppy) bqr.getBqrEvent();
126         Assert.assertNotNull(bqrVsA2dpChoppy);
127         Assert.assertEquals(
128                 "A2DP choppy",
129                 BluetoothQualityReport.qualityReportIdToString(bqr.getQualityReportId()));
130         Assert.assertEquals(bqrp.mArrivalTime, bqrVsA2dpChoppy.getArrivalTime());
131         Assert.assertEquals(bqrp.mScheduleTime, bqrVsA2dpChoppy.getScheduleTime());
132         Assert.assertEquals(bqrp.mGlitchCountA2dp, bqrVsA2dpChoppy.getGlitchCount());
133         Assert.assertEquals(bqrp.mTxCxmDenialsA2dp, bqrVsA2dpChoppy.getTxCxmDenials());
134         Assert.assertEquals(bqrp.mRxCxmDenialsA2dp, bqrVsA2dpChoppy.getRxCxmDenials());
135         Assert.assertEquals(bqrp.mAclTxQueueLength, bqrVsA2dpChoppy.getAclTxQueueLength());
136         Assert.assertEquals(bqrp.mLinkQuality, bqrVsA2dpChoppy.getLinkQuality());
137         Assert.assertEquals(
138                 "MEDIUM", BqrVsA2dpChoppy.linkQualityToString(bqrVsA2dpChoppy.getLinkQuality()));
139         Assert.assertEquals(0, bqrVsA2dpChoppy.describeContents());
140     }
141 
assertBqrScoChoppy(BQRParameters bqrp, BluetoothQualityReport bqr)142     private void assertBqrScoChoppy(BQRParameters bqrp, BluetoothQualityReport bqr) {
143         // BQR VS SCO Choppy
144         BqrVsScoChoppy bqrVsScoChoppy = (BqrVsScoChoppy) bqr.getBqrEvent();
145         Assert.assertNotNull(bqrVsScoChoppy);
146         Assert.assertEquals(
147                 "SCO choppy",
148                 BluetoothQualityReport.qualityReportIdToString(bqr.getQualityReportId()));
149         Assert.assertEquals(bqrp.mGlitchCountSco, bqrVsScoChoppy.getGlitchCount());
150         Assert.assertEquals(bqrp.mIntervalEsco, bqrVsScoChoppy.getIntervalEsco());
151         Assert.assertEquals(bqrp.mWindowEsco, bqrVsScoChoppy.getWindowEsco());
152         Assert.assertEquals(bqrp.mAirFormat, bqrVsScoChoppy.getAirFormat());
153         Assert.assertEquals(
154                 "CVSD", BqrVsScoChoppy.airFormatToString(bqrVsScoChoppy.getAirFormat()));
155         Assert.assertEquals(bqrp.mInstanceCount, bqrVsScoChoppy.getInstanceCount());
156         Assert.assertEquals(bqrp.mTxCxmDenialsSco, bqrVsScoChoppy.getTxCxmDenials());
157         Assert.assertEquals(bqrp.mRxCxmDenialsSco, bqrVsScoChoppy.getRxCxmDenials());
158         Assert.assertEquals(bqrp.mTxAbortCount, bqrVsScoChoppy.getTxAbortCount());
159         Assert.assertEquals(bqrp.mLateDispatch, bqrVsScoChoppy.getLateDispatch());
160         Assert.assertEquals(bqrp.mMicIntrMiss, bqrVsScoChoppy.getMicIntrMiss());
161         Assert.assertEquals(bqrp.mLpaIntrMiss, bqrVsScoChoppy.getLpaIntrMiss());
162         Assert.assertEquals(bqrp.mSprIntrMiss, bqrVsScoChoppy.getSprIntrMiss());
163         Assert.assertEquals(bqrp.mPlcFillCount, bqrVsScoChoppy.getPlcFillCount());
164         Assert.assertEquals(bqrp.mPlcDiscardCount, bqrVsScoChoppy.getPlcDiscardCount());
165         Assert.assertEquals(bqrp.mMissedInstanceCount, bqrVsScoChoppy.getMissedInstanceCount());
166         Assert.assertEquals(bqrp.mTxRetransmitSlotCount, bqrVsScoChoppy.getTxRetransmitSlotCount());
167         Assert.assertEquals(bqrp.mRxRetransmitSlotCount, bqrVsScoChoppy.getRxRetransmitSlotCount());
168         Assert.assertEquals(bqrp.mGoodRxFrameCount, bqrVsScoChoppy.getGoodRxFrameCount());
169         Assert.assertEquals(0, bqrVsScoChoppy.describeContents());
170     }
171 
assertBqrEnergyMonitor(BQRParameters bqrp, BluetoothQualityReport bqr)172     private void assertBqrEnergyMonitor(BQRParameters bqrp, BluetoothQualityReport bqr) {
173         BqrEnergyMonitor bqrEnergyMonitor = (BqrEnergyMonitor) bqr.getBqrEvent();
174         expect.that(bqrEnergyMonitor).isNotNull();
175         expect.that(BluetoothQualityReport.qualityReportIdToString(bqr.getQualityReportId()))
176                 .isEqualTo("Energy Monitor");
177         expect.that(bqrp.mAvgCurrentConsume)
178                 .isEqualTo(bqrEnergyMonitor.getAverageCurrentConsumptionMicroamps());
179         expect.that(bqrp.mIdleTotalTime).isEqualTo(bqrEnergyMonitor.getIdleStateTotalTimeMillis());
180         expect.that(bqrp.mIdleStateEnterCount).isEqualTo(bqrEnergyMonitor.getIdleStateEnterCount());
181         expect.that(bqrp.mActiveTotalTime)
182                 .isEqualTo(bqrEnergyMonitor.getActiveStateTotalTimeMillis());
183         expect.that(bqrp.mActiveStateEnterCount)
184                 .isEqualTo(bqrEnergyMonitor.getActiveStateEnterCount());
185         expect.that(bqrp.mBredrTxTotalTime).isEqualTo(bqrEnergyMonitor.getBredrTxTotalTimeMillis());
186         expect.that(bqrp.mBredrTxStateEnterCount)
187                 .isEqualTo(bqrEnergyMonitor.getBredrTxStateEnterCount());
188         expect.that(bqrp.mBredrTxAvgPowerLevel)
189                 .isEqualTo(bqrEnergyMonitor.getBredrAverageTxPowerLeveldBm());
190         expect.that(bqrp.mBredrRxTotalTime).isEqualTo(bqrEnergyMonitor.getBredrRxTotalTimeMillis());
191         expect.that(bqrp.mBredrRxStateEnterCount)
192                 .isEqualTo(bqrEnergyMonitor.getBredrRxStateEnterCount());
193         expect.that(bqrp.mLeTxTotalTime).isEqualTo(bqrEnergyMonitor.getLeTsTotalTimeMillis());
194         expect.that(bqrp.mLeTxStateEnterCount).isEqualTo(bqrEnergyMonitor.getLeTxStateEnterCount());
195         expect.that(bqrp.mLeTxAvgPowerLevel)
196                 .isEqualTo(bqrEnergyMonitor.getLeAverageTxPowerLeveldBm());
197         expect.that(bqrp.mLeRxTotalTime).isEqualTo(bqrEnergyMonitor.getLeRxTotalTimeMillis());
198         expect.that(bqrp.mLeRxStateEnterCount).isEqualTo(bqrEnergyMonitor.getLeRxStateEnterCount());
199         expect.that(bqrp.mReportTotalTime)
200                 .isEqualTo(bqrEnergyMonitor.getPowerDataTotalTimeMillis());
201         expect.that(bqrp.mRxActiveOneChainTime)
202                 .isEqualTo(bqrEnergyMonitor.getRxSingleChainActiveDurationMillis());
203         expect.that(bqrp.mRxActiveTwoChainTime)
204                 .isEqualTo(bqrEnergyMonitor.getRxDualChainActiveDurationMillis());
205         expect.that(bqrp.mTxiPaActiveOneChainTime)
206                 .isEqualTo(bqrEnergyMonitor.getTxInternalPaSingleChainActiveDurationMillis());
207         expect.that(bqrp.mTxiPaActiveTwoChainTime)
208                 .isEqualTo(bqrEnergyMonitor.getTxInternalPaDualChainActiveDurationMillis());
209         expect.that(bqrp.mTxePaActiveOneChainTime)
210                 .isEqualTo(bqrEnergyMonitor.getTxExternalPaSingleChainActiveDurationMillis());
211         expect.that(bqrp.mTxePaActiveTwoChainTime)
212                 .isEqualTo(bqrEnergyMonitor.getTxExternalPaDualChainActiveDurationMillis());
213         expect.that(bqrEnergyMonitor.describeContents()).isEqualTo(0);
214     }
215 
assertBqrConnectFail(BQRParameters bqrp, BluetoothQualityReport bqr)216     private void assertBqrConnectFail(BQRParameters bqrp, BluetoothQualityReport bqr) {
217         // BQR VS Connect Fail
218         BqrConnectFail bqrConnectFail = (BqrConnectFail) bqr.getBqrEvent();
219         Assert.assertNotNull(bqrConnectFail);
220         Assert.assertEquals(
221                 "Connect fail",
222                 BluetoothQualityReport.qualityReportIdToString(bqr.getQualityReportId()));
223         Assert.assertEquals(bqrp.mFailReason, bqrConnectFail.getFailReason());
224         Assert.assertEquals(0, bqrConnectFail.describeContents());
225     }
226 
assertBqrRfStats(BQRParameters bqrp, BluetoothQualityReport bqr)227     private void assertBqrRfStats(BQRParameters bqrp, BluetoothQualityReport bqr) {
228         BqrRfStats bqrRfStats = (BqrRfStats) bqr.getBqrEvent();
229         expect.that(bqrRfStats).isNotNull();
230         expect.that(BluetoothQualityReport.qualityReportIdToString(bqr.getQualityReportId()))
231                 .isEqualTo("RF Stats");
232         expect.that(bqrp.mExtensionInfo).isEqualTo(bqrRfStats.getExtensionInfo());
233         expect.that(bqrp.mReportTimePeriod).isEqualTo(bqrRfStats.getPerformanceDurationMillis());
234         expect.that(bqrp.mTxPoweriPaBf)
235                 .isEqualTo(bqrRfStats.getTxPowerInternalPaBeamformingCount());
236         expect.that(bqrp.mTxPowerePaBf)
237                 .isEqualTo(bqrRfStats.getTxPowerExternalPaBeamformingCount());
238         expect.that(bqrp.mTxPoweriPaDiv).isEqualTo(bqrRfStats.getTxPowerInternalPaDiversityCount());
239         expect.that(bqrp.mTxPowerePaDiv).isEqualTo(bqrRfStats.getTxPowerExternalPaDiversityCount());
240         expect.that(bqrp.mRssiChainOver50)
241                 .isEqualTo(bqrRfStats.getPacketsWithRssiAboveMinus50dBm());
242         expect.that(bqrp.mRssiChain50To55).isEqualTo(bqrRfStats.getPacketsWithRssi50To55dBm());
243         expect.that(bqrp.mRssiChain55To60).isEqualTo(bqrRfStats.getPacketsWithRssi55To60dBm());
244         expect.that(bqrp.mRssiChain60To65).isEqualTo(bqrRfStats.getPacketsWithRssi60To65dBm());
245         expect.that(bqrp.mRssiChain65To70).isEqualTo(bqrRfStats.getPacketsWithRssi65To70dBm());
246         expect.that(bqrp.mRssiChain70To75).isEqualTo(bqrRfStats.getPacketsWithRssi70To75dBm());
247         expect.that(bqrp.mRssiChain75To80).isEqualTo(bqrRfStats.getPacketsWithRssi75To80dBm());
248         expect.that(bqrp.mRssiChain80To85).isEqualTo(bqrRfStats.getPacketsWithRssi80To85dBm());
249         expect.that(bqrp.mRssiChain85To90).isEqualTo(bqrRfStats.getPacketsWithRssi85To90dBm());
250         expect.that(bqrp.mRssiChainUnder90)
251                 .isEqualTo(bqrRfStats.getPacketsWithRssiBelowMinus90dBm());
252         expect.that(bqrp.mRssiDeltaUnder2).isEqualTo(bqrRfStats.getPacketsWithRssiDeltaBelow2dBm());
253         expect.that(bqrp.mRssiDelta2To5).isEqualTo(bqrRfStats.getPacketsWithRssiDelta2To5dBm());
254         expect.that(bqrp.mRssiDelta5To8).isEqualTo(bqrRfStats.getPacketsWithRssiDelta5To8dBm());
255         expect.that(bqrp.mRssiDelta8To11).isEqualTo(bqrRfStats.getPacketsWithRssiDelta8To11dBm());
256         expect.that(bqrp.mRssiDeltaOver11)
257                 .isEqualTo(bqrRfStats.getPacketsWithRssiDeltaAbove11dBm());
258         expect.that(bqrRfStats.describeContents()).isEqualTo(0);
259     }
260 
getBluetoothClassHelper(int remoteCoD)261     private static BluetoothClass getBluetoothClassHelper(int remoteCoD) {
262         Parcel p = Parcel.obtain();
263         p.writeInt(remoteCoD);
264         p.setDataPosition(0);
265         BluetoothClass bluetoothClass = BluetoothClass.CREATOR.createFromParcel(p);
266         p.recycle();
267         return bluetoothClass;
268     }
269 
initBqrCommon( BQRParameters bqrp, String remoteAddr, int lmpVer, int lmpSubVer, int manufacturerId, String remoteName, int remoteCoD)270     private BluetoothQualityReport initBqrCommon(
271             BQRParameters bqrp,
272             String remoteAddr,
273             int lmpVer,
274             int lmpSubVer,
275             int manufacturerId,
276             String remoteName,
277             int remoteCoD) {
278 
279         BluetoothClass bluetoothClass = getBluetoothClassHelper(remoteCoD);
280 
281         BluetoothQualityReport bqr =
282                 new BluetoothQualityReport.Builder(bqrp.getByteArray())
283                         .setRemoteAddress(remoteAddr)
284                         .setLmpVersion(lmpVer)
285                         .setLmpSubVersion(lmpSubVer)
286                         .setManufacturerId(manufacturerId)
287                         .setRemoteName(remoteName)
288                         .setBluetoothClass(bluetoothClass)
289                         .build();
290 
291         Log.i(TAG, bqr.toString());
292 
293         Assert.assertTrue(remoteAddr.equals(bqr.getRemoteAddress()));
294         Assert.assertEquals(lmpVer, bqr.getLmpVersion());
295         Assert.assertEquals(lmpSubVer, bqr.getLmpSubVersion());
296         Assert.assertEquals(manufacturerId, bqr.getManufacturerId());
297         Assert.assertTrue(remoteName.equals(bqr.getRemoteName()));
298         Assert.assertEquals(bluetoothClass, bqr.getBluetoothClass());
299 
300         assertBqrCommon(bqrp, bqr);
301 
302         return bqr;
303     }
304 
305     @Test
bqrMonitor()306     public void bqrMonitor() {
307         BQRParameters bqrp = BQRParameters.getInstance();
308         Assert.assertNotNull(bqrp);
309 
310         bqrp.setQualityReportId((byte) BluetoothQualityReport.QUALITY_REPORT_ID_MONITOR);
311         Assert.assertEquals(
312                 bqrp.getQualityReportId(), BluetoothQualityReport.QUALITY_REPORT_ID_MONITOR);
313 
314         BluetoothQualityReport bqr =
315                 initBqrCommon(
316                         bqrp,
317                         mRemoteAddress,
318                         mLmpVer,
319                         mLmpSubVer,
320                         mManufacturerId,
321                         mRemoteName,
322                         mRemoteCoD);
323     }
324 
325     @Test
bqrApproachLsto()326     public void bqrApproachLsto() {
327         BQRParameters bqrp = BQRParameters.getInstance();
328         Assert.assertNotNull(bqrp);
329 
330         bqrp.setQualityReportId((byte) BluetoothQualityReport.QUALITY_REPORT_ID_APPROACH_LSTO);
331         Assert.assertEquals(
332                 bqrp.getQualityReportId(), BluetoothQualityReport.QUALITY_REPORT_ID_APPROACH_LSTO);
333 
334         BluetoothQualityReport bqr =
335                 initBqrCommon(
336                         bqrp,
337                         mRemoteAddress,
338                         mLmpVer,
339                         mLmpSubVer,
340                         mManufacturerId,
341                         mRemoteName,
342                         mRemoteCoD);
343 
344         assertBqrApproachLsto(bqrp, bqr);
345     }
346 
347     @Test
bqrA2dpChoppy()348     public void bqrA2dpChoppy() {
349         BQRParameters bqrp = BQRParameters.getInstance();
350         Assert.assertNotNull(bqrp);
351 
352         bqrp.setQualityReportId((byte) BluetoothQualityReport.QUALITY_REPORT_ID_A2DP_CHOPPY);
353         Assert.assertEquals(
354                 bqrp.getQualityReportId(), BluetoothQualityReport.QUALITY_REPORT_ID_A2DP_CHOPPY);
355 
356         BluetoothQualityReport bqr =
357                 initBqrCommon(
358                         bqrp,
359                         mRemoteAddress,
360                         mLmpVer,
361                         mLmpSubVer,
362                         mManufacturerId,
363                         mRemoteName,
364                         mRemoteCoD);
365 
366         assertBqrA2dpChoppy(bqrp, bqr);
367     }
368 
369     @Test
bqrScoChoppy()370     public void bqrScoChoppy() {
371         BQRParameters bqrp = BQRParameters.getInstance();
372         Assert.assertNotNull(bqrp);
373 
374         bqrp.setQualityReportId((byte) BluetoothQualityReport.QUALITY_REPORT_ID_SCO_CHOPPY);
375         Assert.assertEquals(
376                 bqrp.getQualityReportId(), BluetoothQualityReport.QUALITY_REPORT_ID_SCO_CHOPPY);
377 
378         BluetoothQualityReport bqr =
379                 initBqrCommon(
380                         bqrp,
381                         mRemoteAddress,
382                         mLmpVer,
383                         mLmpSubVer,
384                         mManufacturerId,
385                         mRemoteName,
386                         mRemoteCoD);
387 
388         assertBqrScoChoppy(bqrp, bqr);
389     }
390 
391     @Test
392     @RequiresFlagsEnabled(Flags.FLAG_SUPPORT_BLUETOOTH_QUALITY_REPORT_V6)
bqrEnergyMonitor()393     public void bqrEnergyMonitor() {
394         BQRParameters bqrp = BQRParameters.getInstance();
395         Assert.assertNotNull(bqrp);
396 
397         bqrp.setQualityReportId((byte) BluetoothQualityReport.QUALITY_REPORT_ID_ENERGY_MONITOR);
398         Assert.assertEquals(
399                 bqrp.getQualityReportId(), BluetoothQualityReport.QUALITY_REPORT_ID_ENERGY_MONITOR);
400 
401         BluetoothQualityReport bqr =
402                 initBqrCommon(
403                         bqrp,
404                         mRemoteAddress,
405                         mLmpVer,
406                         mLmpSubVer,
407                         mManufacturerId,
408                         mRemoteName,
409                         mRemoteCoD);
410 
411         assertBqrEnergyMonitor(bqrp, bqr);
412     }
413 
414     @Test
bqrConnectFail()415     public void bqrConnectFail() {
416         BQRParameters bqrp = BQRParameters.getInstance();
417         Assert.assertNotNull(bqrp);
418 
419         bqrp.setQualityReportId((byte) BluetoothQualityReport.QUALITY_REPORT_ID_CONN_FAIL);
420         Assert.assertEquals(
421                 bqrp.getQualityReportId(), BluetoothQualityReport.QUALITY_REPORT_ID_CONN_FAIL);
422 
423         BluetoothQualityReport bqr =
424                 initBqrCommon(
425                         bqrp,
426                         mRemoteAddress,
427                         mLmpVer,
428                         mLmpSubVer,
429                         mManufacturerId,
430                         mRemoteName,
431                         mRemoteCoD);
432 
433         assertBqrConnectFail(bqrp, bqr);
434 
435         BqrConnectFail bqrConnectFail = (BqrConnectFail) bqr.getBqrEvent();
436         Assert.assertNotNull(bqrConnectFail);
437 
438         Assert.assertEquals(
439                 "No error",
440                 BqrConnectFail.connectFailIdToString(BqrConnectFail.CONNECT_FAIL_ID_NO_ERROR));
441         Assert.assertEquals(
442                 "Page Timeout",
443                 BqrConnectFail.connectFailIdToString(BqrConnectFail.CONNECT_FAIL_ID_PAGE_TIMEOUT));
444         Assert.assertEquals(
445                 "Connection Timeout",
446                 BqrConnectFail.connectFailIdToString(
447                         BqrConnectFail.CONNECT_FAIL_ID_CONNECTION_TIMEOUT));
448         Assert.assertEquals(
449                 "ACL already exists",
450                 BqrConnectFail.connectFailIdToString(
451                         BqrConnectFail.CONNECT_FAIL_ID_ACL_ALREADY_EXIST));
452         Assert.assertEquals(
453                 "Controller busy",
454                 BqrConnectFail.connectFailIdToString(
455                         BqrConnectFail.CONNECT_FAIL_ID_CONTROLLER_BUSY));
456         Assert.assertEquals("INVALID", BqrConnectFail.connectFailIdToString(0xFF));
457     }
458 
459     @Test
460     @RequiresFlagsEnabled(Flags.FLAG_SUPPORT_BLUETOOTH_QUALITY_REPORT_V6)
bqrRfStats()461     public void bqrRfStats() {
462         BQRParameters bqrp = BQRParameters.getInstance();
463         Assert.assertNotNull(bqrp);
464 
465         bqrp.setQualityReportId((byte) BluetoothQualityReport.QUALITY_REPORT_ID_RF_STATS);
466         Assert.assertEquals(
467                 bqrp.getQualityReportId(), BluetoothQualityReport.QUALITY_REPORT_ID_RF_STATS);
468 
469         BluetoothQualityReport bqr =
470                 initBqrCommon(
471                         bqrp,
472                         mRemoteAddress,
473                         mLmpVer,
474                         mLmpSubVer,
475                         mManufacturerId,
476                         mRemoteName,
477                         mRemoteCoD);
478 
479         assertBqrRfStats(bqrp, bqr);
480     }
481 
482     @Test
defaultNameAddress()483     public void defaultNameAddress() {
484         BQRParameters bqrp = BQRParameters.getInstance();
485         Assert.assertNotNull(bqrp);
486 
487         bqrp.setQualityReportId((byte) BluetoothQualityReport.QUALITY_REPORT_ID_MONITOR);
488         Assert.assertEquals(
489                 bqrp.getQualityReportId(), BluetoothQualityReport.QUALITY_REPORT_ID_MONITOR);
490 
491         BluetoothClass bluetoothClass = getBluetoothClassHelper(mRemoteCoD);
492 
493         BluetoothQualityReport bqr =
494                 new BluetoothQualityReport.Builder(bqrp.getByteArray())
495                         .setRemoteAddress("123456123456")
496                         .setLmpVersion(mLmpVer)
497                         .setLmpSubVersion(mLmpSubVer)
498                         .setManufacturerId(mManufacturerId)
499                         .setBluetoothClass(bluetoothClass)
500                         .build();
501 
502         Assert.assertTrue(bqr.getRemoteAddress().equals(mDefaultAddress));
503         Assert.assertTrue(bqr.getRemoteName().equals(mDefaultName));
504     }
505 
506     @Test
invalidQualityReportId()507     public void invalidQualityReportId() {
508         BQRParameters bqrp = BQRParameters.getInstance();
509         Assert.assertNotNull(bqrp);
510 
511         bqrp.setQualityReportId((byte) 123);
512         Assert.assertEquals(bqrp.getQualityReportId(), 123);
513 
514         Assert.assertThrows(
515                 IllegalArgumentException.class,
516                 () ->
517                         initBqrCommon(
518                                 bqrp,
519                                 mRemoteAddress,
520                                 mLmpVer,
521                                 mLmpSubVer,
522                                 mManufacturerId,
523                                 mRemoteName,
524                                 mRemoteCoD));
525     }
526 
527     @Test
rawDataNull()528     public void rawDataNull() {
529         BluetoothClass bluetoothClass = getBluetoothClassHelper(mRemoteCoD);
530 
531         Assert.assertThrows(
532                 NullPointerException.class,
533                 () ->
534                         new BluetoothQualityReport.Builder(null)
535                                 .setRemoteAddress(mRemoteAddress)
536                                 .setLmpVersion(mLmpVer)
537                                 .setLmpSubVersion(mLmpSubVer)
538                                 .setManufacturerId(mManufacturerId)
539                                 .setRemoteName(mRemoteName)
540                                 .setBluetoothClass(bluetoothClass)
541                                 .build());
542     }
543 
544     @Test
invalidRawData()545     public void invalidRawData() {
546         BQRParameters bqrp = BQRParameters.getInstance();
547         Assert.assertNotNull(bqrp);
548 
549         BluetoothClass bluetoothClass = getBluetoothClassHelper(mRemoteCoD);
550 
551         for (int id : BQRParameters.QualityReportId) {
552             bqrp.setQualityReportId((byte) id);
553             Assert.assertEquals(bqrp.getQualityReportId(), id);
554 
555             byte[] rawData = {0};
556 
557             switch (id) {
558                 case BluetoothQualityReport.QUALITY_REPORT_ID_MONITOR:
559                     rawData = ByteBuffer.allocate(BQRParameters.mBqrCommonSize - 1).array();
560                     break;
561                 case BluetoothQualityReport.QUALITY_REPORT_ID_APPROACH_LSTO:
562                     rawData =
563                             ByteBuffer.allocate(
564                                             BQRParameters.mBqrCommonSize
565                                                     + BQRParameters.mBqrVsLstoSize
566                                                     - 1)
567                                     .array();
568                     break;
569                 case BluetoothQualityReport.QUALITY_REPORT_ID_A2DP_CHOPPY:
570                     rawData =
571                             ByteBuffer.allocate(
572                                             BQRParameters.mBqrCommonSize
573                                                     + BQRParameters.mBqrVsA2dpChoppySize
574                                                     - 1)
575                                     .array();
576                     break;
577                 case BluetoothQualityReport.QUALITY_REPORT_ID_SCO_CHOPPY:
578                     rawData =
579                             ByteBuffer.allocate(
580                                             BQRParameters.mBqrCommonSize
581                                                     + BQRParameters.mBqrVsScoChoppySize
582                                                     - 1)
583                                     .array();
584                     break;
585                 case BluetoothQualityReport.QUALITY_REPORT_ID_CONN_FAIL:
586                     rawData =
587                             ByteBuffer.allocate(
588                                             BQRParameters.mBqrCommonSize
589                                                     + BQRParameters.mBqrVsScoChoppySize
590                                                     - 1)
591                                     .array();
592                     break;
593             }
594 
595             final byte[] data = rawData;
596 
597             Assert.assertThrows(
598                     IllegalArgumentException.class,
599                     () ->
600                             new BluetoothQualityReport.Builder(data)
601                                     .setRemoteAddress(mRemoteAddress)
602                                     .setLmpVersion(mLmpVer)
603                                     .setLmpSubVersion(mLmpSubVer)
604                                     .setManufacturerId(mManufacturerId)
605                                     .setRemoteName(mRemoteName)
606                                     .setBluetoothClass(bluetoothClass)
607                                     .build());
608         }
609     }
610 
611     @Test
readWriteBqrParcel()612     public void readWriteBqrParcel() {
613         BQRParameters bqrp = BQRParameters.getInstance();
614         Assert.assertNotNull(bqrp);
615 
616         for (int id : BQRParameters.QualityReportId) {
617             if ((id == BluetoothQualityReport.QUALITY_REPORT_ID_ENERGY_MONITOR)
618                     || (id == BluetoothQualityReport.QUALITY_REPORT_ID_RF_STATS)) {
619                 continue;
620             }
621             bqrp.setQualityReportId((byte) id);
622             Assert.assertEquals(bqrp.getQualityReportId(), id);
623 
624             BluetoothQualityReport bqr =
625                     initBqrCommon(
626                             bqrp,
627                             mRemoteAddress,
628                             mLmpVer,
629                             mLmpSubVer,
630                             mManufacturerId,
631                             mRemoteName,
632                             mRemoteCoD);
633 
634             Parcel parcel = Parcel.obtain();
635             bqr.writeToParcel(parcel, 0);
636             parcel.setDataPosition(0);
637 
638             BluetoothQualityReport bqrFromParcel =
639                     BluetoothQualityReport.CREATOR.createFromParcel(parcel);
640 
641             assertBqrCommon(bqrp, bqrFromParcel);
642 
643             switch (id) {
644                 case BluetoothQualityReport.QUALITY_REPORT_ID_MONITOR:
645                     break;
646                 case BluetoothQualityReport.QUALITY_REPORT_ID_APPROACH_LSTO:
647                     assertBqrApproachLsto(bqrp, bqr);
648                     break;
649                 case BluetoothQualityReport.QUALITY_REPORT_ID_A2DP_CHOPPY:
650                     assertBqrA2dpChoppy(bqrp, bqr);
651                     break;
652                 case BluetoothQualityReport.QUALITY_REPORT_ID_SCO_CHOPPY:
653                     assertBqrScoChoppy(bqrp, bqr);
654                     break;
655                 case BluetoothQualityReport.QUALITY_REPORT_ID_CONN_FAIL:
656                     assertBqrConnectFail(bqrp, bqr);
657                     break;
658             }
659         }
660     }
661 
662     @Test
663     @RequiresFlagsEnabled(Flags.FLAG_SUPPORT_BLUETOOTH_QUALITY_REPORT_V6)
readWriteBqrParcelV6Flag()664     public void readWriteBqrParcelV6Flag() {
665         BQRParameters bqrp = BQRParameters.getInstance();
666         Assert.assertNotNull(bqrp);
667 
668         for (int id : BQRParameters.QualityReportId) {
669             bqrp.setQualityReportId((byte) id);
670             Assert.assertEquals(bqrp.getQualityReportId(), id);
671 
672             BluetoothQualityReport bqr =
673                     initBqrCommon(
674                             bqrp,
675                             mRemoteAddress,
676                             mLmpVer,
677                             mLmpSubVer,
678                             mManufacturerId,
679                             mRemoteName,
680                             mRemoteCoD);
681 
682             Parcel parcel = Parcel.obtain();
683             bqr.writeToParcel(parcel, 0);
684             parcel.setDataPosition(0);
685 
686             BluetoothQualityReport bqrFromParcel =
687                     BluetoothQualityReport.CREATOR.createFromParcel(parcel);
688 
689             assertBqrCommon(bqrp, bqrFromParcel);
690 
691             switch (id) {
692                 case BluetoothQualityReport.QUALITY_REPORT_ID_MONITOR:
693                     break;
694                 case BluetoothQualityReport.QUALITY_REPORT_ID_APPROACH_LSTO:
695                     assertBqrApproachLsto(bqrp, bqr);
696                     break;
697                 case BluetoothQualityReport.QUALITY_REPORT_ID_A2DP_CHOPPY:
698                     assertBqrA2dpChoppy(bqrp, bqr);
699                     break;
700                 case BluetoothQualityReport.QUALITY_REPORT_ID_SCO_CHOPPY:
701                     assertBqrScoChoppy(bqrp, bqr);
702                     break;
703                 case BluetoothQualityReport.QUALITY_REPORT_ID_CONN_FAIL:
704                     assertBqrConnectFail(bqrp, bqr);
705                     break;
706                 case BluetoothQualityReport.QUALITY_REPORT_ID_ENERGY_MONITOR:
707                     assertBqrEnergyMonitor(bqrp, bqr);
708                     break;
709                 case BluetoothQualityReport.QUALITY_REPORT_ID_RF_STATS:
710                     assertBqrRfStats(bqrp, bqr);
711                     break;
712             }
713         }
714     }
715 
716     @Test
readWriteBqrCommonParcel()717     public void readWriteBqrCommonParcel() {
718         BQRParameters bqrp = BQRParameters.getInstance();
719         Assert.assertNotNull(bqrp);
720 
721         bqrp.setQualityReportId((byte) BluetoothQualityReport.QUALITY_REPORT_ID_MONITOR);
722         Assert.assertEquals(
723                 bqrp.getQualityReportId(), BluetoothQualityReport.QUALITY_REPORT_ID_MONITOR);
724 
725         BluetoothQualityReport bqr =
726                 initBqrCommon(
727                         bqrp,
728                         mRemoteAddress,
729                         mLmpVer,
730                         mLmpSubVer,
731                         mManufacturerId,
732                         mRemoteName,
733                         mRemoteCoD);
734 
735         Assert.assertEquals(
736                 "Quality monitor",
737                 BluetoothQualityReport.qualityReportIdToString(bqr.getQualityReportId()));
738 
739         Parcel parcel = Parcel.obtain();
740         bqr.getBqrCommon().writeToParcel(parcel, 0);
741         parcel.setDataPosition(0);
742 
743         BqrCommon bqrCommonFromParcel = BqrCommon.CREATOR.createFromParcel(parcel);
744 
745         // BQR Common
746         Assert.assertNotNull(bqrCommonFromParcel);
747         Assert.assertEquals(bqrp.mPacketType, bqrCommonFromParcel.getPacketType());
748         Assert.assertEquals(
749                 "TYPE_NULL", BqrCommon.packetTypeToString(bqrCommonFromParcel.getPacketType()));
750         Assert.assertEquals(bqrp.mConnectionHandle, bqrCommonFromParcel.getConnectionHandle());
751         Assert.assertTrue(
752                 bqrp.mConnectionRoleCentral.equals(
753                         BqrCommon.connectionRoleToString(bqrCommonFromParcel.getConnectionRole())));
754         Assert.assertEquals(bqrp.mTxPowerLevel, bqrCommonFromParcel.getTxPowerLevel());
755         Assert.assertEquals(bqrp.mRssi, bqrCommonFromParcel.getRssi());
756         Assert.assertEquals(bqrp.mSnr, bqrCommonFromParcel.getSnr());
757         Assert.assertEquals(
758                 bqrp.mUnusedAfhChannelCount, bqrCommonFromParcel.getUnusedAfhChannelCount());
759         Assert.assertEquals(
760                 bqrp.mAfhSelectUnidealChannelCount,
761                 bqrCommonFromParcel.getAfhSelectUnidealChannelCount());
762         Assert.assertEquals(bqrp.mLsto, bqrCommonFromParcel.getLsto());
763         Assert.assertEquals(bqrp.mPiconetClock, bqrCommonFromParcel.getPiconetClock());
764         Assert.assertEquals(
765                 bqrp.mRetransmissionCount, bqrCommonFromParcel.getRetransmissionCount());
766         Assert.assertEquals(bqrp.mNoRxCount, bqrCommonFromParcel.getNoRxCount());
767         Assert.assertEquals(bqrp.mNakCount, bqrCommonFromParcel.getNakCount());
768         Assert.assertEquals(bqrp.mLastTxAckTimestamp, bqrCommonFromParcel.getLastTxAckTimestamp());
769         Assert.assertEquals(bqrp.mFlowOffCount, bqrCommonFromParcel.getFlowOffCount());
770         Assert.assertEquals(
771                 bqrp.mLastFlowOnTimestamp, bqrCommonFromParcel.getLastFlowOnTimestamp());
772         Assert.assertEquals(bqrp.mOverflowCount, bqrCommonFromParcel.getOverflowCount());
773         Assert.assertEquals(bqrp.mUnderflowCount, bqrCommonFromParcel.getUnderflowCount());
774     }
775 
776     @Test
readWriteBqrVsApproachLstoParcel()777     public void readWriteBqrVsApproachLstoParcel() {
778         BQRParameters bqrp = BQRParameters.getInstance();
779         Assert.assertNotNull(bqrp);
780 
781         bqrp.setQualityReportId((byte) BluetoothQualityReport.QUALITY_REPORT_ID_APPROACH_LSTO);
782         Assert.assertEquals(
783                 bqrp.getQualityReportId(), BluetoothQualityReport.QUALITY_REPORT_ID_APPROACH_LSTO);
784 
785         BluetoothQualityReport bqr =
786                 initBqrCommon(
787                         bqrp,
788                         mRemoteAddress,
789                         mLmpVer,
790                         mLmpSubVer,
791                         mManufacturerId,
792                         mRemoteName,
793                         mRemoteCoD);
794 
795         Assert.assertEquals(
796                 "Approaching LSTO",
797                 BluetoothQualityReport.qualityReportIdToString(bqr.getQualityReportId()));
798 
799         BqrVsLsto bqrVsLsto = (BqrVsLsto) bqr.getBqrEvent();
800         Assert.assertNotNull(bqrVsLsto);
801         Parcel parcel = Parcel.obtain();
802         bqrVsLsto.writeToParcel(parcel, 0);
803         parcel.setDataPosition(0);
804 
805         BqrVsLsto bqrVsLstoFromParcel = BqrVsLsto.CREATOR.createFromParcel(parcel);
806 
807         // BQR VS LSTO
808         Assert.assertNotNull(bqrVsLstoFromParcel);
809         Assert.assertEquals(bqrp.mConnState & 0xFF, bqrVsLstoFromParcel.getConnState());
810         Assert.assertEquals(
811                 "CONN_UNPARK_ACTIVE",
812                 BqrVsLsto.connStateToString(bqrVsLstoFromParcel.getConnState()));
813         Assert.assertEquals(bqrp.mBasebandStats, bqrVsLstoFromParcel.getBasebandStats());
814         Assert.assertEquals(bqrp.mSlotsUsed, bqrVsLstoFromParcel.getSlotsUsed());
815         Assert.assertEquals(bqrp.mCxmDenials, bqrVsLstoFromParcel.getCxmDenials());
816         Assert.assertEquals(bqrp.mTxSkipped, bqrVsLstoFromParcel.getTxSkipped());
817         Assert.assertEquals(bqrp.mRfLoss, bqrVsLstoFromParcel.getRfLoss());
818         Assert.assertEquals(bqrp.mNativeClock, bqrVsLstoFromParcel.getNativeClock());
819         Assert.assertEquals(
820                 bqrp.mLastTxAckTimestampLsto, bqrVsLstoFromParcel.getLastTxAckTimestamp());
821         Assert.assertEquals(0, bqrVsLstoFromParcel.describeContents());
822     }
823 
824     @Test
readWriteBqrVsA2dpChoppyParcel()825     public void readWriteBqrVsA2dpChoppyParcel() {
826         BQRParameters bqrp = BQRParameters.getInstance();
827         Assert.assertNotNull(bqrp);
828 
829         bqrp.setQualityReportId((byte) BluetoothQualityReport.QUALITY_REPORT_ID_A2DP_CHOPPY);
830         Assert.assertEquals(
831                 bqrp.getQualityReportId(), BluetoothQualityReport.QUALITY_REPORT_ID_A2DP_CHOPPY);
832 
833         BluetoothQualityReport bqr =
834                 initBqrCommon(
835                         bqrp,
836                         mRemoteAddress,
837                         mLmpVer,
838                         mLmpSubVer,
839                         mManufacturerId,
840                         mRemoteName,
841                         mRemoteCoD);
842 
843         Assert.assertEquals(
844                 "A2DP choppy",
845                 BluetoothQualityReport.qualityReportIdToString(bqr.getQualityReportId()));
846 
847         BqrVsA2dpChoppy bqrVsA2dpChoppy = (BqrVsA2dpChoppy) bqr.getBqrEvent();
848         Assert.assertNotNull(bqrVsA2dpChoppy);
849         Parcel parcel = Parcel.obtain();
850         bqrVsA2dpChoppy.writeToParcel(parcel, 0);
851         parcel.setDataPosition(0);
852 
853         BqrVsA2dpChoppy bqrVsA2dpChoppyFromParcel =
854                 BqrVsA2dpChoppy.CREATOR.createFromParcel(parcel);
855 
856         // BQR VS A2DP Choppy
857         Assert.assertNotNull(bqrVsA2dpChoppyFromParcel);
858         Assert.assertEquals(bqrp.mArrivalTime, bqrVsA2dpChoppyFromParcel.getArrivalTime());
859         Assert.assertEquals(bqrp.mScheduleTime, bqrVsA2dpChoppyFromParcel.getScheduleTime());
860         Assert.assertEquals(bqrp.mGlitchCountA2dp, bqrVsA2dpChoppyFromParcel.getGlitchCount());
861         Assert.assertEquals(bqrp.mTxCxmDenialsA2dp, bqrVsA2dpChoppyFromParcel.getTxCxmDenials());
862         Assert.assertEquals(bqrp.mRxCxmDenialsA2dp, bqrVsA2dpChoppyFromParcel.getRxCxmDenials());
863         Assert.assertEquals(
864                 bqrp.mAclTxQueueLength, bqrVsA2dpChoppyFromParcel.getAclTxQueueLength());
865         Assert.assertEquals(bqrp.mLinkQuality, bqrVsA2dpChoppyFromParcel.getLinkQuality());
866         Assert.assertEquals(
867                 "MEDIUM",
868                 BqrVsA2dpChoppy.linkQualityToString(bqrVsA2dpChoppyFromParcel.getLinkQuality()));
869         Assert.assertEquals(0, bqrVsA2dpChoppyFromParcel.describeContents());
870     }
871 
872     @Test
readWriteBqrVsScoChoppyParcel()873     public void readWriteBqrVsScoChoppyParcel() {
874         BQRParameters bqrp = BQRParameters.getInstance();
875         Assert.assertNotNull(bqrp);
876 
877         bqrp.setQualityReportId((byte) BluetoothQualityReport.QUALITY_REPORT_ID_SCO_CHOPPY);
878         Assert.assertEquals(
879                 bqrp.getQualityReportId(), BluetoothQualityReport.QUALITY_REPORT_ID_SCO_CHOPPY);
880 
881         BluetoothQualityReport bqr =
882                 initBqrCommon(
883                         bqrp,
884                         mRemoteAddress,
885                         mLmpVer,
886                         mLmpSubVer,
887                         mManufacturerId,
888                         mRemoteName,
889                         mRemoteCoD);
890 
891         Assert.assertEquals(
892                 "SCO choppy",
893                 BluetoothQualityReport.qualityReportIdToString(bqr.getQualityReportId()));
894 
895         BqrVsScoChoppy bqrVsScoChoppy = (BqrVsScoChoppy) bqr.getBqrEvent();
896         Assert.assertNotNull(bqrVsScoChoppy);
897         Parcel parcel = Parcel.obtain();
898         bqrVsScoChoppy.writeToParcel(parcel, 0);
899         parcel.setDataPosition(0);
900 
901         BqrVsScoChoppy bqrVsScoChoppyFromParcel = BqrVsScoChoppy.CREATOR.createFromParcel(parcel);
902 
903         // BQR VS SCO Choppy
904         Assert.assertNotNull(bqrVsScoChoppyFromParcel);
905         Assert.assertEquals(bqrp.mGlitchCountSco, bqrVsScoChoppyFromParcel.getGlitchCount());
906         Assert.assertEquals(bqrp.mIntervalEsco, bqrVsScoChoppyFromParcel.getIntervalEsco());
907         Assert.assertEquals(bqrp.mWindowEsco, bqrVsScoChoppyFromParcel.getWindowEsco());
908         Assert.assertEquals(bqrp.mAirFormat, bqrVsScoChoppyFromParcel.getAirFormat());
909         Assert.assertEquals(
910                 "CVSD", BqrVsScoChoppy.airFormatToString(bqrVsScoChoppyFromParcel.getAirFormat()));
911         Assert.assertEquals(bqrp.mInstanceCount, bqrVsScoChoppyFromParcel.getInstanceCount());
912         Assert.assertEquals(bqrp.mTxCxmDenialsSco, bqrVsScoChoppyFromParcel.getTxCxmDenials());
913         Assert.assertEquals(bqrp.mRxCxmDenialsSco, bqrVsScoChoppyFromParcel.getRxCxmDenials());
914         Assert.assertEquals(bqrp.mTxAbortCount, bqrVsScoChoppyFromParcel.getTxAbortCount());
915         Assert.assertEquals(bqrp.mLateDispatch, bqrVsScoChoppyFromParcel.getLateDispatch());
916         Assert.assertEquals(bqrp.mMicIntrMiss, bqrVsScoChoppyFromParcel.getMicIntrMiss());
917         Assert.assertEquals(bqrp.mLpaIntrMiss, bqrVsScoChoppyFromParcel.getLpaIntrMiss());
918         Assert.assertEquals(bqrp.mSprIntrMiss, bqrVsScoChoppyFromParcel.getSprIntrMiss());
919         Assert.assertEquals(bqrp.mPlcFillCount, bqrVsScoChoppyFromParcel.getPlcFillCount());
920         Assert.assertEquals(bqrp.mPlcDiscardCount, bqrVsScoChoppyFromParcel.getPlcDiscardCount());
921 
922         Assert.assertEquals(
923                 bqrp.mMissedInstanceCount, bqrVsScoChoppyFromParcel.getMissedInstanceCount());
924         Assert.assertEquals(
925                 bqrp.mTxRetransmitSlotCount, bqrVsScoChoppyFromParcel.getTxRetransmitSlotCount());
926         Assert.assertEquals(
927                 bqrp.mRxRetransmitSlotCount, bqrVsScoChoppyFromParcel.getRxRetransmitSlotCount());
928         Assert.assertEquals(bqrp.mGoodRxFrameCount, bqrVsScoChoppyFromParcel.getGoodRxFrameCount());
929         Assert.assertEquals(0, bqrVsScoChoppyFromParcel.describeContents());
930     }
931 
932     @Test
readWriteBqrConnectFailParcel()933     public void readWriteBqrConnectFailParcel() {
934         BQRParameters bqrp = BQRParameters.getInstance();
935         Assert.assertNotNull(bqrp);
936 
937         bqrp.setQualityReportId((byte) BluetoothQualityReport.QUALITY_REPORT_ID_CONN_FAIL);
938         Assert.assertEquals(
939                 bqrp.getQualityReportId(), BluetoothQualityReport.QUALITY_REPORT_ID_CONN_FAIL);
940 
941         BluetoothQualityReport bqr =
942                 initBqrCommon(
943                         bqrp,
944                         mRemoteAddress,
945                         mLmpVer,
946                         mLmpSubVer,
947                         mManufacturerId,
948                         mRemoteName,
949                         mRemoteCoD);
950 
951         Assert.assertEquals(
952                 "Connect fail",
953                 BluetoothQualityReport.qualityReportIdToString(bqr.getQualityReportId()));
954 
955         BqrConnectFail bqrConnectFail = (BqrConnectFail) bqr.getBqrEvent();
956         Assert.assertNotNull(bqrConnectFail);
957         Parcel parcel = Parcel.obtain();
958         bqrConnectFail.writeToParcel(parcel, 0);
959         parcel.setDataPosition(0);
960 
961         BqrConnectFail bqrConnFailFromParcel = BqrConnectFail.CREATOR.createFromParcel(parcel);
962 
963         // BQR VS Connect Fail
964         Assert.assertNotNull(bqrConnFailFromParcel);
965         Assert.assertEquals(bqrp.mFailReason, bqrConnFailFromParcel.getFailReason());
966         Assert.assertEquals(0, bqrConnFailFromParcel.describeContents());
967     }
968 
969     /**
970      * Get the test object of BluetoothQualityReport based on given Quality Report Id.
971      *
972      * @param qualityReportId Quality Report Id
973      * @return Bluetooth Quality Report object
974      */
getBqr(int qualityReportId)975     public static BluetoothQualityReport getBqr(int qualityReportId) {
976         BQRParameters bqrp = BQRParameters.getInstance();
977         Assert.assertNotNull(bqrp);
978 
979         bqrp.setQualityReportId((byte) qualityReportId);
980         Assert.assertEquals(bqrp.getQualityReportId(), qualityReportId);
981         BluetoothClass bluetoothClass = getBluetoothClassHelper(mRemoteCoD);
982 
983         BluetoothQualityReport bqr =
984                 new BluetoothQualityReport.Builder(bqrp.getByteArray())
985                         .setRemoteAddress(mRemoteAddress)
986                         .setLmpVersion(mLmpVer)
987                         .setLmpSubVersion(mLmpSubVer)
988                         .setManufacturerId(mManufacturerId)
989                         .setRemoteName(mRemoteName)
990                         .setBluetoothClass(bluetoothClass)
991                         .build();
992         return bqr;
993     }
994 
995     private static final class BQRParameters {
996         private static BQRParameters INSTANCE;
997         private static String TAG = "BQRParameters";
998 
999         public static int mBqrCommonSize = 85;
1000         public static int mBqrVsLstoSize = 23;
1001         public static int mBqrVsA2dpChoppySize = 16;
1002         public static int mBqrVsScoChoppySize = 33;
1003         public static int mBqrConnectFailSize = 1;
1004         public static int mBqrEnergyMonitorSize = 81;
1005         public static int mBqrRfStatsSize = 82;
1006 
1007         // BQR Common
1008         public byte mQualityReportId = 1;
1009         public byte mPacketType = 2;
1010         public short mConnectionHandle = 3;
1011         public byte mConnectionRole = 0; // Central
1012         public String mConnectionRoleCentral = "Central";
1013         public byte mTxPowerLevel = 5;
1014         public byte mRssi = 6;
1015         public byte mSnr = 7;
1016         public byte mUnusedAfhChannelCount = 8;
1017         public byte mAfhSelectUnidealChannelCount = 9;
1018         public short mLsto = 10;
1019         public int mPiconetClock = 11;
1020         public int mRetransmissionCount = 12;
1021         public int mNoRxCount = 13;
1022         public int mNakCount = 14;
1023         public int mLastTxAckTimestamp = 15;
1024         public int mFlowOffCount = 16;
1025         public int mLastFlowOnTimestamp = 17;
1026         public int mOverflowCount = 18;
1027         public int mUnderflowCount = 19;
1028         public String mAddressStr = "01:02:03:04:05:06";
1029         public byte[] mAddress = {6, 5, 4, 3, 2, 1};
1030         public byte mCalFailedItemCount = 50;
1031 
1032         public int mTxTotalPackets = 20;
1033         public int mTxUnackPackets = 21;
1034         public int mTxFlushPackets = 22;
1035         public int mTxLastSubeventPackets = 23;
1036         public int mCrcErrorPackets = 24;
1037         public int mRxDupPackets = 25;
1038         public int mRxUnRecvPackets = 26;
1039         public short mCoexInfoMask = 1;
1040 
1041         // BQR VS LSTO
1042         public byte mConnState = (byte) 0x89;
1043         public int mBasebandStats = 21;
1044         public int mSlotsUsed = 22;
1045         public short mCxmDenials = 23;
1046         public short mTxSkipped = 24;
1047         public short mRfLoss = 25;
1048         public int mNativeClock = 26;
1049         public int mLastTxAckTimestampLsto = 27;
1050 
1051         // BQR VS A2DP Choppy
1052         public int mArrivalTime = 28;
1053         public int mScheduleTime = 29;
1054         public short mGlitchCountA2dp = 30;
1055         public short mTxCxmDenialsA2dp = 31;
1056         public short mRxCxmDenialsA2dp = 32;
1057         public byte mAclTxQueueLength = 33;
1058         public byte mLinkQuality = 3;
1059 
1060         // BQR VS SCO Choppy
1061         public short mGlitchCountSco = 35;
1062         public byte mIntervalEsco = 36;
1063         public byte mWindowEsco = 37;
1064         public byte mAirFormat = 2;
1065         public short mInstanceCount = 39;
1066         public short mTxCxmDenialsSco = 40;
1067         public short mRxCxmDenialsSco = 41;
1068         public short mTxAbortCount = 42;
1069         public short mLateDispatch = 43;
1070         public short mMicIntrMiss = 44;
1071         public short mLpaIntrMiss = 45;
1072         public short mSprIntrMiss = 46;
1073         public short mPlcFillCount = 47;
1074         public short mPlcDiscardCount = 51;
1075         public short mMissedInstanceCount = 52;
1076         public short mTxRetransmitSlotCount = 53;
1077         public short mRxRetransmitSlotCount = 54;
1078         public short mGoodRxFrameCount = 55;
1079 
1080         // BQR VS Connect Fail
1081         public byte mFailReason = 0x3a;
1082 
1083         // BQR Energy Monitor
1084         public short mAvgCurrentConsume = 56;
1085         public int mIdleTotalTime = 57;
1086         public int mIdleStateEnterCount = 58;
1087         public int mActiveTotalTime = 59;
1088         public int mActiveStateEnterCount = 60;
1089         public int mBredrTxTotalTime = 61;
1090         public int mBredrTxStateEnterCount = 62;
1091         public byte mBredrTxAvgPowerLevel = 63;
1092         public int mBredrRxTotalTime = 64;
1093         public int mBredrRxStateEnterCount = 65;
1094         public int mLeTxTotalTime = 66;
1095         public int mLeTxStateEnterCount = 67;
1096         public byte mLeTxAvgPowerLevel = 68;
1097         public int mLeRxTotalTime = 69;
1098         public int mLeRxStateEnterCount = 70;
1099         public int mReportTotalTime = 71;
1100         public int mRxActiveOneChainTime = 72;
1101         public int mRxActiveTwoChainTime = 73;
1102         public int mTxiPaActiveOneChainTime = 74;
1103         public int mTxiPaActiveTwoChainTime = 75;
1104         public int mTxePaActiveOneChainTime = 76;
1105         public int mTxePaActiveTwoChainTime = 77;
1106 
1107         // BQR Rf Stats
1108         public byte mExtensionInfo = 78;
1109         public int mReportTimePeriod = 79;
1110         public int mTxPoweriPaBf = 80;
1111         public int mTxPowerePaBf = 81;
1112         public int mTxPoweriPaDiv = 82;
1113         public int mTxPowerePaDiv = 83;
1114         public int mRssiChainOver50 = 84;
1115         public int mRssiChain50To55 = 85;
1116         public int mRssiChain55To60 = 86;
1117         public int mRssiChain60To65 = 87;
1118         public int mRssiChain65To70 = 88;
1119         public int mRssiChain70To75 = 89;
1120         public int mRssiChain75To80 = 90;
1121         public int mRssiChain80To85 = 91;
1122         public int mRssiChain85To90 = 92;
1123         public int mRssiChainUnder90 = 93;
1124         public int mRssiDeltaUnder2 = 94;
1125         public int mRssiDelta2To5 = 95;
1126         public int mRssiDelta5To8 = 96;
1127         public int mRssiDelta8To11 = 97;
1128         public int mRssiDeltaOver11 = 98;
1129 
1130         public static int[] QualityReportId = {
1131             BluetoothQualityReport.QUALITY_REPORT_ID_MONITOR,
1132             BluetoothQualityReport.QUALITY_REPORT_ID_APPROACH_LSTO,
1133             BluetoothQualityReport.QUALITY_REPORT_ID_A2DP_CHOPPY,
1134             BluetoothQualityReport.QUALITY_REPORT_ID_SCO_CHOPPY,
1135             BluetoothQualityReport.QUALITY_REPORT_ID_CONN_FAIL,
1136             BluetoothQualityReport.QUALITY_REPORT_ID_ENERGY_MONITOR,
1137             BluetoothQualityReport.QUALITY_REPORT_ID_RF_STATS,
1138         };
1139 
BQRParameters()1140         private BQRParameters() {}
1141 
getInstance()1142         public static BQRParameters getInstance() {
1143             if (INSTANCE == null) {
1144                 INSTANCE = new BQRParameters();
1145             }
1146             return INSTANCE;
1147         }
1148 
setQualityReportId(byte id)1149         public void setQualityReportId(byte id) {
1150             mQualityReportId = id;
1151         }
1152 
getQualityReportId()1153         public int getQualityReportId() {
1154             return (int) mQualityReportId;
1155         }
1156 
getByteArray()1157         public byte[] getByteArray() {
1158             ByteBuffer ba;
1159             ByteBuffer addrBuff = ByteBuffer.wrap(mAddress, 0, mAddress.length);
1160 
1161             switch ((int) mQualityReportId) {
1162                 case BluetoothQualityReport.QUALITY_REPORT_ID_MONITOR:
1163                     ba = ByteBuffer.allocate(mBqrCommonSize);
1164                     break;
1165                 case BluetoothQualityReport.QUALITY_REPORT_ID_APPROACH_LSTO:
1166                     ba = ByteBuffer.allocate(mBqrCommonSize + mBqrVsLstoSize);
1167                     break;
1168                 case BluetoothQualityReport.QUALITY_REPORT_ID_A2DP_CHOPPY:
1169                     ba = ByteBuffer.allocate(mBqrCommonSize + mBqrVsA2dpChoppySize);
1170                     break;
1171                 case BluetoothQualityReport.QUALITY_REPORT_ID_SCO_CHOPPY:
1172                     ba = ByteBuffer.allocate(mBqrCommonSize + mBqrVsScoChoppySize);
1173                     break;
1174                 case BluetoothQualityReport.QUALITY_REPORT_ID_CONN_FAIL:
1175                     ba = ByteBuffer.allocate(mBqrCommonSize + mBqrConnectFailSize);
1176                     break;
1177                 case BluetoothQualityReport.QUALITY_REPORT_ID_ENERGY_MONITOR:
1178                     ba = ByteBuffer.allocate(1 + mBqrEnergyMonitorSize);
1179                     break;
1180                 case BluetoothQualityReport.QUALITY_REPORT_ID_RF_STATS:
1181                     ba = ByteBuffer.allocate(1 + mBqrRfStatsSize);
1182                     break;
1183                 default:
1184                     ba = ByteBuffer.allocate(mBqrCommonSize);
1185                     break;
1186             }
1187 
1188             ba.order(ByteOrder.LITTLE_ENDIAN);
1189 
1190             ba.put(mQualityReportId);
1191 
1192             if (mQualityReportId
1193                     == (byte) BluetoothQualityReport.QUALITY_REPORT_ID_ENERGY_MONITOR) {
1194                 ba.putShort(mAvgCurrentConsume);
1195                 ba.putInt(mIdleTotalTime);
1196                 ba.putInt(mIdleStateEnterCount);
1197                 ba.putInt(mActiveTotalTime);
1198                 ba.putInt(mActiveStateEnterCount);
1199                 ba.putInt(mBredrTxTotalTime);
1200                 ba.putInt(mBredrTxStateEnterCount);
1201                 ba.put(mBredrTxAvgPowerLevel);
1202                 ba.putInt(mBredrRxTotalTime);
1203                 ba.putInt(mBredrRxStateEnterCount);
1204                 ba.putInt(mLeTxTotalTime);
1205                 ba.putInt(mLeTxStateEnterCount);
1206                 ba.put(mLeTxAvgPowerLevel);
1207                 ba.putInt(mLeRxTotalTime);
1208                 ba.putInt(mLeRxStateEnterCount);
1209                 ba.putInt(mReportTotalTime);
1210                 ba.putInt(mRxActiveOneChainTime);
1211                 ba.putInt(mRxActiveTwoChainTime);
1212                 ba.putInt(mTxiPaActiveOneChainTime);
1213                 ba.putInt(mTxiPaActiveTwoChainTime);
1214                 ba.putInt(mTxePaActiveOneChainTime);
1215                 ba.putInt(mTxePaActiveTwoChainTime);
1216             } else if (mQualityReportId
1217                     == (byte) BluetoothQualityReport.QUALITY_REPORT_ID_RF_STATS) {
1218                 ba.put(mExtensionInfo);
1219                 ba.putInt(mReportTimePeriod);
1220                 ba.putInt(mTxPoweriPaBf);
1221                 ba.putInt(mTxPowerePaBf);
1222                 ba.putInt(mTxPoweriPaDiv);
1223                 ba.putInt(mTxPowerePaDiv);
1224                 ba.putInt(mRssiChainOver50);
1225                 ba.putInt(mRssiChain50To55);
1226                 ba.putInt(mRssiChain55To60);
1227                 ba.putInt(mRssiChain60To65);
1228                 ba.putInt(mRssiChain65To70);
1229                 ba.putInt(mRssiChain70To75);
1230                 ba.putInt(mRssiChain75To80);
1231                 ba.putInt(mRssiChain80To85);
1232                 ba.putInt(mRssiChain85To90);
1233                 ba.putInt(mRssiChainUnder90);
1234                 ba.putInt(mRssiDeltaUnder2);
1235                 ba.putInt(mRssiDelta2To5);
1236                 ba.putInt(mRssiDelta5To8);
1237                 ba.putInt(mRssiDelta8To11);
1238                 ba.putInt(mRssiDeltaOver11);
1239             } else {
1240                 ba.put(mPacketType);
1241                 ba.putShort(mConnectionHandle);
1242                 ba.put(mConnectionRole);
1243                 ba.put(mTxPowerLevel);
1244                 ba.put(mRssi);
1245                 ba.put(mSnr);
1246                 ba.put(mUnusedAfhChannelCount);
1247                 ba.put(mAfhSelectUnidealChannelCount);
1248                 ba.putShort(mLsto);
1249                 ba.putInt(mPiconetClock);
1250                 ba.putInt(mRetransmissionCount);
1251                 ba.putInt(mNoRxCount);
1252                 ba.putInt(mNakCount);
1253                 ba.putInt(mLastTxAckTimestamp);
1254                 ba.putInt(mFlowOffCount);
1255                 ba.putInt(mLastFlowOnTimestamp);
1256                 ba.putInt(mOverflowCount);
1257                 ba.putInt(mUnderflowCount);
1258                 ba.put(addrBuff);
1259                 ba.put(mCalFailedItemCount);
1260                 ba.putInt(mTxTotalPackets);
1261                 ba.putInt(mTxUnackPackets);
1262                 ba.putInt(mTxFlushPackets);
1263                 ba.putInt(mTxLastSubeventPackets);
1264                 ba.putInt(mCrcErrorPackets);
1265                 ba.putInt(mRxDupPackets);
1266                 ba.putInt(mRxUnRecvPackets);
1267                 ba.putShort(mCoexInfoMask);
1268 
1269                 if (mQualityReportId
1270                         == (byte) BluetoothQualityReport.QUALITY_REPORT_ID_APPROACH_LSTO) {
1271                     ba.put(mConnState);
1272                     ba.putInt(mBasebandStats);
1273                     ba.putInt(mSlotsUsed);
1274                     ba.putShort(mCxmDenials);
1275                     ba.putShort(mTxSkipped);
1276                     ba.putShort(mRfLoss);
1277                     ba.putInt(mNativeClock);
1278                     ba.putInt(mLastTxAckTimestampLsto);
1279                 } else if (mQualityReportId
1280                         == (byte) BluetoothQualityReport.QUALITY_REPORT_ID_A2DP_CHOPPY) {
1281                     ba.putInt(mArrivalTime);
1282                     ba.putInt(mScheduleTime);
1283                     ba.putShort(mGlitchCountA2dp);
1284                     ba.putShort(mTxCxmDenialsA2dp);
1285                     ba.putShort(mRxCxmDenialsA2dp);
1286                     ba.put(mAclTxQueueLength);
1287                     ba.put(mLinkQuality);
1288                 } else if (mQualityReportId
1289                         == (byte) BluetoothQualityReport.QUALITY_REPORT_ID_SCO_CHOPPY) {
1290                     ba.putShort(mGlitchCountSco);
1291                     ba.put(mIntervalEsco);
1292                     ba.put(mWindowEsco);
1293                     ba.put(mAirFormat);
1294                     ba.putShort(mInstanceCount);
1295                     ba.putShort(mTxCxmDenialsSco);
1296                     ba.putShort(mRxCxmDenialsSco);
1297                     ba.putShort(mTxAbortCount);
1298                     ba.putShort(mLateDispatch);
1299                     ba.putShort(mMicIntrMiss);
1300                     ba.putShort(mLpaIntrMiss);
1301                     ba.putShort(mSprIntrMiss);
1302                     ba.putShort(mPlcFillCount);
1303                     ba.putShort(mPlcDiscardCount);
1304                     ba.putShort(mMissedInstanceCount);
1305                     ba.putShort(mTxRetransmitSlotCount);
1306                     ba.putShort(mRxRetransmitSlotCount);
1307                     ba.putShort(mGoodRxFrameCount);
1308 
1309                 } else if (mQualityReportId
1310                         == (byte) BluetoothQualityReport.QUALITY_REPORT_ID_CONN_FAIL) {
1311                     ba.put(mFailReason);
1312                 }
1313             }
1314             return ba.array();
1315         }
1316     }
1317 }
1318