1 /*
2  * Copyright (C) 2021 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package com.android.server.uwb;
18 
19 import static com.android.dx.mockito.inline.extended.ExtendedMockito.verify;
20 import static com.android.server.uwb.DeviceConfigFacade.DEFAULT_RANGING_RESULT_LOG_INTERVAL_MS;
21 
22 import static org.mockito.ArgumentMatchers.anyString;
23 import static org.mockito.Mockito.times;
24 import static org.mockito.Mockito.validateMockitoUsage;
25 import static org.mockito.Mockito.when;
26 
27 import android.content.AttributionSource;
28 import android.platform.test.annotations.Presubmit;
29 import android.uwb.AngleMeasurement;
30 import android.uwb.AngleOfArrivalMeasurement;
31 import android.uwb.DistanceMeasurement;
32 import android.uwb.RangingMeasurement;
33 
34 import androidx.test.filters.SmallTest;
35 import androidx.test.runner.AndroidJUnit4;
36 
37 import com.android.dx.mockito.inline.extended.ExtendedMockito;
38 import com.android.server.uwb.UwbSessionManager.UwbSession;
39 import com.android.server.uwb.data.UwbDlTDoAMeasurement;
40 import com.android.server.uwb.data.UwbOwrAoaMeasurement;
41 import com.android.server.uwb.data.UwbRangingData;
42 import com.android.server.uwb.data.UwbTwoWayMeasurement;
43 import com.android.server.uwb.data.UwbUciConstants;
44 import com.android.server.uwb.proto.UwbStatsLog;
45 
46 import com.google.uwb.support.fira.FiraOpenSessionParams;
47 import com.google.uwb.support.fira.FiraParams;
48 
49 import org.junit.After;
50 import org.junit.Before;
51 import org.junit.Test;
52 import org.junit.runner.RunWith;
53 import org.mockito.Mock;
54 import org.mockito.MockitoAnnotations;
55 import org.mockito.MockitoSession;
56 import org.mockito.quality.Strictness;
57 
58 import java.io.ByteArrayOutputStream;
59 import java.io.PrintWriter;
60 
61 /**
62  * Unit tests for {@link com.android.server.uwb.UwbMetrics}.
63  */
64 @RunWith(AndroidJUnit4.class)
65 @SmallTest
66 @Presubmit
67 public class UwbMetricsTest {
68     private static final int CHANNEL_DEFAULT = 5;
69     private static final int DISTANCE_DEFAULT_CM = 100;
70     private static final int ELEVATION_DEFAULT_DEGREE = 50;
71     private static final int AZIMUTH_DEFAULT_DEGREE = 56;
72     private static final int ELEVATION_FOM_DEFAULT = 90;
73     private static final int AZIMUTH_FOM_DEFAULT = 60;
74     private static final int DISTANCE_FILTERED_CM = 105;
75     private static final int ELEVATION_FILTERED_DEGREE = 45;
76     private static final int AZIMUTH_FILTERED_DEGREE = 156;
77     private static final int ELEVATION_FOM_FILTERED = 60;
78     private static final int AZIMUTH_FOM_FILTERED = 95;
79     private static final int NLOS_DEFAULT = 1;
80     private static final int VALID_RANGING_COUNT = 5;
81     private static final int RSSI_DEFAULT_DBM = -75;
82     private static final boolean IS_STATUS_CODE_OK_DEFAULT = true;
83     private static final int UID = 67;
84     private static final String PACKAGE_NAME = "com.android.uwb.test";
85     private static final AttributionSource ATTRIBUTION_SOURCE =
86             new AttributionSource.Builder(UID).setPackageName(PACKAGE_NAME).build();
87     private static final int RANGING_INTERVAL_MS = 200;
88     private static final int PARALLEL_SESSION_COUNT = 0;
89     private static final int RX_PACKET_COUNT = 10;
90     private static final int TX_PACKET_COUNT = 20;
91     private static final int RX_TO_UPPER_LEVEL_COUNT = 5;
92     private static final int FILTER_CONFIG_VALUE = 63;
93     @Mock
94     private UwbInjector mUwbInjector;
95     @Mock
96     private DeviceConfigFacade mDeviceConfigFacade;
97     @Mock
98     private UwbDiagnostics mUwbDiagnostics;
99     private UwbTwoWayMeasurement[] mTwoWayMeasurements = new UwbTwoWayMeasurement[1];
100     @Mock
101     private UwbTwoWayMeasurement mTwoWayMeasurement;
102     private UwbDlTDoAMeasurement[] mDlTDoAMeasurements = new UwbDlTDoAMeasurement[1];
103     @Mock
104     private UwbDlTDoAMeasurement mDlTDoAMeasurement;
105     @Mock
106     private UwbOwrAoaMeasurement mOwrAoaMeasurement;
107     @Mock
108     private UwbRangingData mRangingData;
109     @Mock
110     private RangingMeasurement mFilteredRangingMeasurement;
111     @Mock
112     private DistanceMeasurement mFilteredDistanceMeasurement;
113     @Mock
114     private AngleOfArrivalMeasurement mFilteredAngleOfArrivalMeasurement;
115     @Mock
116     private AngleMeasurement mFilteredAzimuthMeasurement;
117     @Mock
118     private AngleMeasurement mFilteredElevationMeasurement;
119     @Mock
120     private UwbSession mUwbSession;
121     @Mock
122     private FiraOpenSessionParams mFiraParams;
123 
124     private UwbMetrics mUwbMetrics;
125     private MockitoSession mMockSession;
126     private long mElapsedTimeMs;
127 
128     @Before
setUp()129     public void setUp() throws Exception {
130         MockitoAnnotations.initMocks(this);
131         setElapsedTimeMs(1000L);
132         mTwoWayMeasurements[0] = mTwoWayMeasurement;
133         mDlTDoAMeasurements[0] = mDlTDoAMeasurement;
134         when(mRangingData.getSessionId()).thenReturn(1L);
135         when(mRangingData.getNoOfRangingMeasures()).thenReturn(1);
136         when(mRangingData.getRangingMeasuresType()).thenReturn(
137                 (int) UwbUciConstants.RANGING_MEASUREMENT_TYPE_TWO_WAY);
138         when(mTwoWayMeasurement.isStatusCodeOk()).thenReturn(IS_STATUS_CODE_OK_DEFAULT);
139         when(mDlTDoAMeasurement.getStatus()).thenReturn(FiraParams.STATUS_CODE_OK);
140         when(mOwrAoaMeasurement.getRangingStatus()).thenReturn(FiraParams.STATUS_CODE_OK);
141         when(mRangingData.getRangingTwoWayMeasures()).thenReturn(mTwoWayMeasurements);
142         when(mRangingData.getUwbDlTDoAMeasurements()).thenReturn(mDlTDoAMeasurements);
143         when(mRangingData.getRangingOwrAoaMeasure()).thenReturn(mOwrAoaMeasurement);
144 
145         when(mFilteredRangingMeasurement.getDistanceMeasurement())
146                 .thenReturn(mFilteredDistanceMeasurement);
147         when(mFilteredRangingMeasurement.getAngleOfArrivalMeasurement())
148                 .thenReturn(mFilteredAngleOfArrivalMeasurement);
149         when(mFilteredAngleOfArrivalMeasurement.getAzimuth())
150                 .thenReturn(mFilteredAzimuthMeasurement);
151         when(mFilteredAngleOfArrivalMeasurement.getAltitude())
152                 .thenReturn(mFilteredElevationMeasurement);
153         when(mFilteredDistanceMeasurement.getMeters())
154                 .thenReturn((double) DISTANCE_FILTERED_CM / 100);
155         when(mFilteredAzimuthMeasurement.getRadians())
156                 .thenReturn(Math.toRadians(AZIMUTH_FILTERED_DEGREE));
157         when(mFilteredAzimuthMeasurement.getConfidenceLevel())
158                 .thenReturn((double) AZIMUTH_FOM_FILTERED / 100);
159         when(mFilteredElevationMeasurement.getRadians())
160                 .thenReturn(Math.toRadians(ELEVATION_FILTERED_DEGREE));
161         when(mFilteredElevationMeasurement.getConfidenceLevel())
162                 .thenReturn((double) ELEVATION_FOM_FILTERED / 100);
163 
164         when(mUwbSession.getSessionId()).thenReturn(1);
165         when(mUwbSession.getProtocolName()).thenReturn(FiraParams.PROTOCOL_NAME);
166         when(mUwbSession.getProfileType()).thenReturn(
167                 UwbStatsLog.UWB_SESSION_INITIATED__PROFILE__FIRA);
168         when(mUwbSession.getParams()).thenReturn(mFiraParams);
169         when(mUwbSession.getAttributionSource()).thenReturn(ATTRIBUTION_SOURCE);
170         when(mUwbSession.getParallelSessionCount()).thenReturn(PARALLEL_SESSION_COUNT);
171         when(mFiraParams.getStsConfig()).thenReturn(FiraParams.STS_CONFIG_STATIC);
172         when(mFiraParams.getDeviceRole()).thenReturn(FiraParams.RANGING_DEVICE_ROLE_INITIATOR);
173         when(mFiraParams.getDeviceType()).thenReturn(FiraParams.RANGING_DEVICE_TYPE_CONTROLLER);
174         when(mFiraParams.getChannelNumber()).thenReturn(CHANNEL_DEFAULT);
175         when(mFiraParams.getRangingIntervalMs()).thenReturn(RANGING_INTERVAL_MS);
176 
177         when(mTwoWayMeasurement.getDistance()).thenReturn(DISTANCE_DEFAULT_CM);
178         when(mTwoWayMeasurement.getAoaAzimuth()).thenReturn((float) AZIMUTH_DEFAULT_DEGREE);
179         when(mDlTDoAMeasurement.getAoaAzimuth()).thenReturn((float) AZIMUTH_DEFAULT_DEGREE);
180         when(mOwrAoaMeasurement.getAoaAzimuth()).thenReturn((float) AZIMUTH_DEFAULT_DEGREE);
181         when(mTwoWayMeasurement.getAoaAzimuthFom()).thenReturn(AZIMUTH_FOM_DEFAULT);
182         when(mDlTDoAMeasurement.getAoaAzimuthFom()).thenReturn(AZIMUTH_FOM_DEFAULT);
183         when(mOwrAoaMeasurement.getAoaAzimuthFom()).thenReturn(AZIMUTH_FOM_DEFAULT);
184         when(mTwoWayMeasurement.getAoaElevation()).thenReturn((float) ELEVATION_DEFAULT_DEGREE);
185         when(mDlTDoAMeasurement.getAoaElevation()).thenReturn((float) ELEVATION_DEFAULT_DEGREE);
186         when(mOwrAoaMeasurement.getAoaElevation()).thenReturn((float) ELEVATION_DEFAULT_DEGREE);
187         when(mTwoWayMeasurement.getAoaElevationFom()).thenReturn(ELEVATION_FOM_DEFAULT);
188         when(mDlTDoAMeasurement.getAoaElevationFom()).thenReturn(ELEVATION_FOM_DEFAULT);
189         when(mOwrAoaMeasurement.getAoaElevationFom()).thenReturn(ELEVATION_FOM_DEFAULT);
190         when(mTwoWayMeasurement.getNLoS()).thenReturn(NLOS_DEFAULT);
191         when(mDlTDoAMeasurement.getNLoS()).thenReturn(NLOS_DEFAULT);
192         when(mOwrAoaMeasurement.getNLoS()).thenReturn(NLOS_DEFAULT);
193         when(mTwoWayMeasurement.getRssi()).thenReturn(RSSI_DEFAULT_DBM);
194         when(mDlTDoAMeasurement.getRssi()).thenReturn(RSSI_DEFAULT_DBM);
195         when(mDeviceConfigFacade.getRangingResultLogIntervalMs())
196                 .thenReturn(DEFAULT_RANGING_RESULT_LOG_INTERVAL_MS);
197         when(mDeviceConfigFacade.isSessionInitErrorBugreportEnabled()).thenReturn(true);
198         when(mDeviceConfigFacade.isEnableFilters()).thenReturn(true);
199         when(mDeviceConfigFacade.isEnableBackAzimuth()).thenReturn(true);
200         when(mDeviceConfigFacade.isEnablePrimerAoA()).thenReturn(true);
201         when(mDeviceConfigFacade.isEnablePrimerEstElevation()).thenReturn(true);
202         when(mDeviceConfigFacade.isEnablePrimerFov()).thenReturn(true);
203         when(mDeviceConfigFacade.isEnableBackAzimuthMasking()).thenReturn(true);
204         when(mUwbInjector.getDeviceConfigFacade()).thenReturn(mDeviceConfigFacade);
205         when(mUwbInjector.getUwbDiagnostics()).thenReturn(mUwbDiagnostics);
206 
207         mUwbMetrics = new UwbMetrics(mUwbInjector);
208         mMockSession = ExtendedMockito.mockitoSession()
209                 .strictness(Strictness.LENIENT)
210                 .mockStatic(UwbStatsLog.class)
211                 .startMocking();
212     }
213 
214     /**
215      * Called after each test
216      */
217     @After
cleanup()218     public void cleanup() {
219         validateMockitoUsage();
220         mMockSession.finishMocking();
221     }
222 
setElapsedTimeMs(long elapsedTimeMs)223     private void setElapsedTimeMs(long elapsedTimeMs) {
224         mElapsedTimeMs = elapsedTimeMs;
225         when(mUwbInjector.getElapsedSinceBootMillis()).thenReturn(mElapsedTimeMs);
226     }
227 
addElapsedTimeMs(long durationMs)228     private void addElapsedTimeMs(long durationMs) {
229         mElapsedTimeMs += durationMs;
230         when(mUwbInjector.getElapsedSinceBootMillis()).thenReturn(mElapsedTimeMs);
231     }
232 
233     @Test
testLogRangingSessionAllEvents()234     public void testLogRangingSessionAllEvents() throws Exception {
235         mUwbMetrics.logRangingInitEvent(mUwbSession, UwbUciConstants.STATUS_CODE_OK);
236         ExtendedMockito.verify(() -> UwbStatsLog.write(
237                 UwbStatsLog.UWB_SESSION_INITED,
238                 UwbStatsLog.UWB_SESSION_INITIATED__PROFILE__FIRA,
239                 UwbStatsLog.UWB_SESSION_INITIATED__STS__STATIC, true,
240                 true, false, true,
241                 CHANNEL_DEFAULT, UwbStatsLog.UWB_SESSION_INITIATED__STATUS__SUCCESS,
242                 0, 0, UID, RANGING_INTERVAL_MS, PARALLEL_SESSION_COUNT , FILTER_CONFIG_VALUE
243         ));
244 
245         mUwbMetrics.longRangingStartEvent(mUwbSession,
246                 UwbUciConstants.STATUS_CODE_RANGING_TX_FAILED);
247         addElapsedTimeMs(DEFAULT_RANGING_RESULT_LOG_INTERVAL_MS);
248         mUwbMetrics.longRangingStartEvent(mUwbSession, UwbUciConstants.STATUS_CODE_OK);
249         addElapsedTimeMs(DEFAULT_RANGING_RESULT_LOG_INTERVAL_MS);
250 
251         for (int i = 0; i < VALID_RANGING_COUNT; i++) {
252             addElapsedTimeMs(DEFAULT_RANGING_RESULT_LOG_INTERVAL_MS);
253             mUwbMetrics.logRangingResult(UwbStatsLog.UWB_SESSION_INITIATED__PROFILE__FIRA,
254                     mRangingData, mFilteredRangingMeasurement);
255         }
256         when(mTwoWayMeasurement.isStatusCodeOk()).thenReturn(!IS_STATUS_CODE_OK_DEFAULT);
257         mUwbMetrics.logRangingResult(UwbStatsLog.UWB_SESSION_INITIATED__PROFILE__FIRA,
258                 mRangingData, mFilteredRangingMeasurement);
259 
260         for (int i = 0; i < RX_PACKET_COUNT; i++) {
261             mUwbMetrics.logDataRx(mUwbSession, UwbUciConstants.STATUS_CODE_OK);
262         }
263         mUwbMetrics.logDataRx(mUwbSession, UwbUciConstants.STATUS_CODE_FAILED);
264 
265         for (int i = 0; i < TX_PACKET_COUNT; i++) {
266             mUwbMetrics.logDataTx(mUwbSession, UwbUciConstants.STATUS_CODE_OK);
267         }
268         mUwbMetrics.logDataTx(mUwbSession, UwbUciConstants.STATUS_CODE_FAILED);
269 
270         mUwbMetrics.logDataToUpperLayer(mUwbSession, RX_TO_UPPER_LEVEL_COUNT);
271 
272         mUwbMetrics.logRangingCloseEvent(mUwbSession, UwbUciConstants.STATUS_CODE_FAILED);
273         addElapsedTimeMs(DEFAULT_RANGING_RESULT_LOG_INTERVAL_MS);
274         mUwbMetrics.logRangingCloseEvent(mUwbSession, UwbUciConstants.STATUS_CODE_OK);
275 
276         ExtendedMockito.verify(() -> UwbStatsLog.write(UwbStatsLog.UWB_RANGING_START,
277                 UwbStatsLog.UWB_SESSION_INITIATED__PROFILE__FIRA,
278                 UwbStatsLog.UWB_SESSION_INITIATED__STS__STATIC, true, true, false, true,
279                 UwbStatsLog.UWB_START_RANGING__STATUS__TX_FAILED));
280 
281         ExtendedMockito.verify(() -> UwbStatsLog.write(UwbStatsLog.UWB_RANGING_START,
282                 UwbStatsLog.UWB_SESSION_INITIATED__PROFILE__FIRA,
283                 UwbStatsLog.UWB_SESSION_INITIATED__STS__STATIC, true, true, false, true,
284                 UwbStatsLog.UWB_START_RANGING__STATUS__RANGING_SUCCESS));
285 
286         ExtendedMockito.verify(() -> UwbStatsLog.write(UwbStatsLog.UWB_FIRST_RANGING_RECEIVED,
287                 UwbStatsLog.UWB_SESSION_INITIATED__PROFILE__FIRA,
288                 DEFAULT_RANGING_RESULT_LOG_INTERVAL_MS * 2,
289                 DEFAULT_RANGING_RESULT_LOG_INTERVAL_MS * 2 / 200));
290 
291         ExtendedMockito.verify(() -> UwbStatsLog.write(UwbStatsLog.UWB_SESSION_CLOSED,
292                 UwbStatsLog.UWB_SESSION_INITIATED__PROFILE__FIRA,
293                 UwbStatsLog.UWB_SESSION_INITIATED__STS__STATIC, true,
294                 true, false, true,
295                 DEFAULT_RANGING_RESULT_LOG_INTERVAL_MS * (VALID_RANGING_COUNT + 2),
296                 UwbStatsLog.UWB_SESSION_CLOSED__DURATION_BUCKET__TEN_SEC_TO_ONE_MIN,
297                 VALID_RANGING_COUNT + 1, VALID_RANGING_COUNT,
298                 UwbStatsLog.UWB_SESSION_CLOSED__RANGING_COUNT_BUCKET__FIVE_TO_TWENTY,
299                 UwbStatsLog.UWB_SESSION_CLOSED__RANGING_COUNT_BUCKET__ONE_TO_FIVE,
300                 2, 1, 0,
301                 RX_PACKET_COUNT, TX_PACKET_COUNT, 1, 1, RX_TO_UPPER_LEVEL_COUNT,
302                 UwbStatsLog.UWB_SESSION_CLOSED__RANGING_TYPE__TWO_WAY));
303     }
304 
305     @Test
testLogRangingSessionInitFiraInvalidParams()306     public void testLogRangingSessionInitFiraInvalidParams() throws Exception {
307         when(mFiraParams.getStsConfig()).thenReturn(FiraParams.STS_CONFIG_DYNAMIC);
308         when(mFiraParams.getDeviceRole()).thenReturn(FiraParams.RANGING_DEVICE_ROLE_RESPONDER);
309         when(mFiraParams.getDeviceType()).thenReturn(FiraParams.RANGING_DEVICE_TYPE_CONTROLEE);
310 
311         mUwbMetrics.logRangingInitEvent(mUwbSession,
312                 UwbUciConstants.STATUS_CODE_INVALID_PARAM);
313         ExtendedMockito.verify(() -> UwbStatsLog.write(
314                 UwbStatsLog.UWB_SESSION_INITED,
315                 UwbStatsLog.UWB_SESSION_INITIATED__PROFILE__FIRA,
316                 UwbStatsLog.UWB_SESSION_INITIATED__STS__DYNAMIC, false,
317                 false, false, true,
318                 CHANNEL_DEFAULT, UwbStatsLog.UWB_SESSION_INITIATED__STATUS__BAD_PARAMS,
319                 0, 0, UID, RANGING_INTERVAL_MS, PARALLEL_SESSION_COUNT, FILTER_CONFIG_VALUE
320         ));
321         verify(mUwbDiagnostics).takeBugReport(anyString());
322     }
323 
324     @Test
testLoggingRangingResultValidDistanceAngle()325     public void testLoggingRangingResultValidDistanceAngle() throws Exception {
326         mUwbMetrics.logRangingInitEvent(mUwbSession, UwbUciConstants.STATUS_CODE_OK);
327         addElapsedTimeMs(DEFAULT_RANGING_RESULT_LOG_INTERVAL_MS);
328         mUwbMetrics.logRangingResult(UwbStatsLog.UWB_SESSION_INITIATED__PROFILE__FIRA,
329                 mRangingData, mFilteredRangingMeasurement);
330 
331         ExtendedMockito.verify(() -> UwbStatsLog.write(
332                 UwbStatsLog.UWB_RANGING_MEASUREMENT_RECEIVED,
333                 UwbStatsLog.UWB_SESSION_INITIATED__PROFILE__FIRA,
334                 UwbStatsLog.UWB_RANGING_MEASUREMENT_RECEIVED__NLOS__NLOS,
335                 true, DISTANCE_DEFAULT_CM, DISTANCE_DEFAULT_CM / 50,
336                 RSSI_DEFAULT_DBM,
337                 true, AZIMUTH_DEFAULT_DEGREE,
338                 AZIMUTH_DEFAULT_DEGREE / 10, AZIMUTH_FOM_DEFAULT,
339                 true, ELEVATION_DEFAULT_DEGREE,
340                 ELEVATION_DEFAULT_DEGREE / 10, ELEVATION_FOM_DEFAULT,
341                 UwbStatsLog.UWB_RANGING_MEASUREMENT_RECEIVED__RANGING_TYPE__TWO_WAY,
342                 DISTANCE_FILTERED_CM, AZIMUTH_FILTERED_DEGREE, AZIMUTH_FOM_FILTERED,
343                 ELEVATION_FILTERED_DEGREE, ELEVATION_FOM_FILTERED
344         ));
345     }
346 
347     @Test
testLoggingRangingResultSmallLoggingInterval()348     public void testLoggingRangingResultSmallLoggingInterval() throws Exception {
349         mUwbMetrics.logRangingInitEvent(mUwbSession, UwbUciConstants.STATUS_CODE_OK);
350         mUwbMetrics.logRangingResult(UwbStatsLog.UWB_SESSION_INITIATED__PROFILE__FIRA,
351                 mRangingData, mFilteredRangingMeasurement);
352 
353         ExtendedMockito.verify(() -> UwbStatsLog.write(
354                 UwbStatsLog.UWB_RANGING_MEASUREMENT_RECEIVED,
355                 UwbStatsLog.UWB_SESSION_INITIATED__PROFILE__FIRA,
356                 UwbStatsLog.UWB_RANGING_MEASUREMENT_RECEIVED__NLOS__NLOS,
357                 true, DISTANCE_DEFAULT_CM, DISTANCE_DEFAULT_CM / 50,
358                 RSSI_DEFAULT_DBM,
359                 true, AZIMUTH_DEFAULT_DEGREE,
360                 AZIMUTH_DEFAULT_DEGREE / 10, AZIMUTH_FOM_DEFAULT,
361                 true, ELEVATION_DEFAULT_DEGREE,
362                 ELEVATION_DEFAULT_DEGREE / 10, ELEVATION_FOM_DEFAULT,
363                 UwbStatsLog.UWB_RANGING_MEASUREMENT_RECEIVED__RANGING_TYPE__TWO_WAY,
364                 DISTANCE_FILTERED_CM, AZIMUTH_FILTERED_DEGREE, AZIMUTH_FOM_FILTERED,
365                 ELEVATION_FILTERED_DEGREE, ELEVATION_FOM_FILTERED
366         ), times(0));
367     }
368 
369     @Test
testLoggingRangingResultInvalidDistance()370     public void testLoggingRangingResultInvalidDistance() throws Exception {
371         mUwbMetrics.logRangingInitEvent(mUwbSession, UwbUciConstants.STATUS_CODE_OK);
372         addElapsedTimeMs(DEFAULT_RANGING_RESULT_LOG_INTERVAL_MS);
373         when(mTwoWayMeasurement.getDistance()).thenReturn(UwbMetrics.INVALID_DISTANCE);
374         when(mTwoWayMeasurement.getAoaAzimuth()).thenReturn((float) -10.0);
375         when(mTwoWayMeasurement.getAoaAzimuthFom()).thenReturn(0);
376         when(mTwoWayMeasurement.getAoaElevation()).thenReturn((float) -20.0);
377         when(mTwoWayMeasurement.getAoaElevationFom()).thenReturn(0);
378         when(mTwoWayMeasurement.getNLoS()).thenReturn(0);
379         when(mFilteredRangingMeasurement.getDistanceMeasurement()).thenReturn(null);
380 
381         mUwbMetrics.logRangingResult(UwbStatsLog.UWB_SESSION_INITIATED__PROFILE__CCC,
382                 mRangingData, mFilteredRangingMeasurement);
383 
384         ExtendedMockito.verify(() -> UwbStatsLog.write(
385                 UwbStatsLog.UWB_RANGING_MEASUREMENT_RECEIVED,
386                 UwbStatsLog.UWB_SESSION_INITIATED__PROFILE__CCC,
387                 UwbStatsLog.UWB_RANGING_MEASUREMENT_RECEIVED__NLOS__LOS,
388                 false, UwbMetrics.INVALID_DISTANCE, 0,
389                 RSSI_DEFAULT_DBM,
390                 false, -10, 0, 0,
391                 false, -20, 0, 0,
392                 UwbStatsLog.UWB_RANGING_MEASUREMENT_RECEIVED__RANGING_TYPE__TWO_WAY,
393                 UwbMetrics.INVALID_DISTANCE, AZIMUTH_FILTERED_DEGREE, AZIMUTH_FOM_FILTERED,
394                 ELEVATION_FILTERED_DEGREE, ELEVATION_FOM_FILTERED
395         ));
396     }
397 
398     @Test
testLoggingRangingResultDlTDoAMeasurement()399     public void testLoggingRangingResultDlTDoAMeasurement() throws Exception {
400         when(mRangingData.getRangingMeasuresType()).thenReturn(
401                 (int) UwbUciConstants.RANGING_MEASUREMENT_TYPE_DL_TDOA);
402         when(mFilteredRangingMeasurement.getDistanceMeasurement()).thenReturn(null);
403 
404         mUwbMetrics.logRangingInitEvent(mUwbSession, UwbUciConstants.STATUS_CODE_OK);
405         addElapsedTimeMs(DEFAULT_RANGING_RESULT_LOG_INTERVAL_MS);
406         mUwbMetrics.logRangingResult(UwbStatsLog.UWB_SESSION_INITIATED__PROFILE__FIRA,
407                 mRangingData, mFilteredRangingMeasurement);
408 
409         ExtendedMockito.verify(() -> UwbStatsLog.write(
410                 UwbStatsLog.UWB_RANGING_MEASUREMENT_RECEIVED,
411                 UwbStatsLog.UWB_SESSION_INITIATED__PROFILE__FIRA,
412                 UwbStatsLog.UWB_RANGING_MEASUREMENT_RECEIVED__NLOS__NLOS,
413                 false, UwbMetrics.INVALID_DISTANCE, 0,
414                 RSSI_DEFAULT_DBM,
415                 true, AZIMUTH_DEFAULT_DEGREE,
416                 AZIMUTH_DEFAULT_DEGREE / 10, AZIMUTH_FOM_DEFAULT,
417                 true, ELEVATION_DEFAULT_DEGREE,
418                 ELEVATION_DEFAULT_DEGREE / 10, ELEVATION_FOM_DEFAULT,
419                 UwbStatsLog.UWB_RANGING_MEASUREMENT_RECEIVED__RANGING_TYPE__DL_TDOA,
420                 UwbMetrics.INVALID_DISTANCE, AZIMUTH_FILTERED_DEGREE, AZIMUTH_FOM_FILTERED,
421                 ELEVATION_FILTERED_DEGREE, ELEVATION_FOM_FILTERED
422         ));
423     }
424 
425     @Test
testLoggingRangingResultOwrAoaMeasurement()426     public void testLoggingRangingResultOwrAoaMeasurement() throws Exception {
427         when(mRangingData.getRangingMeasuresType()).thenReturn(
428                 (int) UwbUciConstants.RANGING_MEASUREMENT_TYPE_OWR_AOA);
429         when(mFilteredRangingMeasurement.getDistanceMeasurement()).thenReturn(null);
430 
431         mUwbMetrics.logRangingInitEvent(mUwbSession, UwbUciConstants.STATUS_CODE_OK);
432         addElapsedTimeMs(DEFAULT_RANGING_RESULT_LOG_INTERVAL_MS);
433         mUwbMetrics.logRangingResult(UwbStatsLog.UWB_SESSION_INITIATED__PROFILE__FIRA,
434                 mRangingData, mFilteredRangingMeasurement);
435 
436         ExtendedMockito.verify(() -> UwbStatsLog.write(
437                 UwbStatsLog.UWB_RANGING_MEASUREMENT_RECEIVED,
438                 UwbStatsLog.UWB_SESSION_INITIATED__PROFILE__FIRA,
439                 UwbStatsLog.UWB_RANGING_MEASUREMENT_RECEIVED__NLOS__NLOS,
440                 false, UwbMetrics.INVALID_DISTANCE, 0,
441                 RangingMeasurement.RSSI_UNKNOWN,
442                 true, AZIMUTH_DEFAULT_DEGREE,
443                 AZIMUTH_DEFAULT_DEGREE / 10, AZIMUTH_FOM_DEFAULT,
444                 true, ELEVATION_DEFAULT_DEGREE,
445                 ELEVATION_DEFAULT_DEGREE / 10, ELEVATION_FOM_DEFAULT,
446                 UwbStatsLog.UWB_RANGING_MEASUREMENT_RECEIVED__RANGING_TYPE__OWR_AOA,
447                 UwbMetrics.INVALID_DISTANCE, AZIMUTH_FILTERED_DEGREE, AZIMUTH_FOM_FILTERED,
448                 ELEVATION_FILTERED_DEGREE, ELEVATION_FOM_FILTERED
449         ));
450     }
451 
452     @Test
testReportDeviceSuccessErrorCount()453     public void testReportDeviceSuccessErrorCount() throws Exception {
454         mUwbMetrics.logUwbStateChangeEvent(true, false, true);
455         ExtendedMockito.verify(() -> UwbStatsLog.write(UwbStatsLog.UWB_DEVICE_ERROR_REPORTED,
456                 UwbStatsLog.UWB_DEVICE_ERROR_REPORTED__TYPE__INIT_ERROR), times(0));
457 
458         mUwbMetrics.logUwbStateChangeEvent(true, false, false);
459         ExtendedMockito.verify(() -> UwbStatsLog.write(UwbStatsLog.UWB_DEVICE_ERROR_REPORTED,
460                 UwbStatsLog.UWB_DEVICE_ERROR_REPORTED__TYPE__INIT_ERROR));
461 
462         mUwbMetrics.logUwbStateChangeEvent(true, true, false);
463         mUwbMetrics.incrementDeviceStatusErrorCount();
464         ExtendedMockito.verify(() -> UwbStatsLog.write(UwbStatsLog.UWB_DEVICE_ERROR_REPORTED,
465                 UwbStatsLog.UWB_DEVICE_ERROR_REPORTED__TYPE__DEVICE_STATUS_ERROR));
466         mUwbMetrics.incrementUciGenericErrorCount();
467         ExtendedMockito.verify(() -> UwbStatsLog.write(UwbStatsLog.UWB_DEVICE_ERROR_REPORTED,
468                 UwbStatsLog.UWB_DEVICE_ERROR_REPORTED__TYPE__UCI_GENERIC_ERROR));
469     }
470 
471     @Test
testDumpStatsNoCrash()472     public void testDumpStatsNoCrash() throws Exception {
473         mUwbMetrics.logRangingInitEvent(mUwbSession, UwbUciConstants.STATUS_CODE_OK);
474         mUwbMetrics.logRangingInitEvent(mUwbSession,
475                 UwbUciConstants.STATUS_CODE_INVALID_PARAM);
476 
477         addElapsedTimeMs(DEFAULT_RANGING_RESULT_LOG_INTERVAL_MS);
478         mUwbMetrics.logRangingResult(UwbStatsLog.UWB_SESSION_INITIATED__PROFILE__CCC, mRangingData,
479                 mFilteredRangingMeasurement);
480         addElapsedTimeMs(DEFAULT_RANGING_RESULT_LOG_INTERVAL_MS);
481         mUwbMetrics.logRangingResult(UwbStatsLog.UWB_SESSION_INITIATED__PROFILE__FIRA,
482                 mRangingData, mFilteredRangingMeasurement);
483 
484         ByteArrayOutputStream stream = new ByteArrayOutputStream();
485         PrintWriter writer = new PrintWriter(stream);
486         mUwbMetrics.dump(null, writer, null);
487     }
488 }
489