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.server.uwb.UwbTestUtils.DATA_PAYLOAD;
20 import static com.android.server.uwb.UwbTestUtils.PEER_EXTENDED_UWB_ADDRESS;
21 import static com.android.server.uwb.UwbTestUtils.PEER_SHORT_MAC_ADDRESS;
22 import static com.android.server.uwb.UwbTestUtils.PERSISTABLE_BUNDLE;
23 import static com.android.server.uwb.data.UwbUciConstants.MAC_ADDRESSING_MODE_SHORT;
24 import static com.android.server.uwb.data.UwbUciConstants.RANGING_MEASUREMENT_TYPE_DL_TDOA;
25 import static com.android.server.uwb.data.UwbUciConstants.RANGING_MEASUREMENT_TYPE_OWR_AOA;
26 import static com.android.server.uwb.data.UwbUciConstants.RANGING_MEASUREMENT_TYPE_TWO_WAY;
27 import static com.android.server.uwb.data.UwbUciConstants.STATUS_CODE_FAILED;
28 
29 import static com.google.common.truth.Truth.assertThat;
30 import static com.google.uwb.support.radar.RadarParams.RADAR_DATA_TYPE_RADAR_SWEEP_SAMPLES;
31 
32 import static org.mockito.ArgumentMatchers.anyInt;
33 import static org.mockito.ArgumentMatchers.argThat;
34 import static org.mockito.ArgumentMatchers.eq;
35 import static org.mockito.ArgumentMatchers.isA;
36 import static org.mockito.Mockito.any;
37 import static org.mockito.Mockito.clearInvocations;
38 import static org.mockito.Mockito.never;
39 import static org.mockito.Mockito.validateMockitoUsage;
40 import static org.mockito.Mockito.verify;
41 import static org.mockito.Mockito.verifyZeroInteractions;
42 import static org.mockito.Mockito.when;
43 
44 import android.content.AttributionSource;
45 import android.os.PersistableBundle;
46 import android.os.RemoteException;
47 import android.platform.test.annotations.Presubmit;
48 import android.platform.test.annotations.RequiresFlagsEnabled;
49 import android.platform.test.flag.junit.CheckFlagsRule;
50 import android.platform.test.flag.junit.DeviceFlagsValueProvider;
51 import android.util.Pair;
52 import android.uwb.IUwbOemExtensionCallback;
53 import android.uwb.IUwbRangingCallbacks;
54 import android.uwb.RangingChangeReason;
55 import android.uwb.RangingReport;
56 import android.uwb.SessionHandle;
57 import android.uwb.UwbAddress;
58 
59 import androidx.test.filters.SmallTest;
60 import androidx.test.runner.AndroidJUnit4;
61 
62 import com.android.server.uwb.data.UwbRadarData;
63 import com.android.server.uwb.data.UwbRangingData;
64 import com.android.server.uwb.data.UwbUciConstants;
65 import com.android.uwb.flags.Flags;
66 
67 import com.google.uwb.support.fira.FiraOnControleeRemovedParams;
68 import com.google.uwb.support.fira.FiraOpenSessionParams;
69 import com.google.uwb.support.fira.FiraParams;
70 import com.google.uwb.support.radar.RadarData;
71 import com.google.uwb.support.radar.RadarOpenSessionParams;
72 import com.google.uwb.support.radar.RadarParams;
73 
74 import org.junit.After;
75 import org.junit.Before;
76 import org.junit.Rule;
77 import org.junit.Test;
78 import org.junit.runner.RunWith;
79 import org.mockito.ArgumentCaptor;
80 import org.mockito.Mock;
81 import org.mockito.MockitoAnnotations;
82 
83 import java.util.Set;
84 
85 /**
86  * Unit tests for {@link com.android.server.uwb.UwbSettingsStore}.
87  */
88 @RunWith(AndroidJUnit4.class)
89 @SmallTest
90 @Presubmit
91 public class UwbSessionNotificationManagerTest {
92     private static final long TEST_ELAPSED_NANOS = 100L;
93     private static final int UID = 343453;
94     private static final String PACKAGE_NAME = "com.uwb.test";
95     private static final AttributionSource ATTRIBUTION_SOURCE =
96             new AttributionSource.Builder(UID).setPackageName(PACKAGE_NAME).build();
97 
98     @Mock private UwbInjector mUwbInjector;
99     @Mock private UwbSessionManager.UwbSession mUwbSession;
100     @Mock private UwbSessionManager.UwbSession mUwbRadarSession;
101     @Mock private SessionHandle mSessionHandle;
102     @Mock private IUwbRangingCallbacks mIUwbRangingCallbacks;
103     @Mock private FiraOpenSessionParams mFiraParams;
104     @Mock private RadarOpenSessionParams mRadarParams;
105     @Mock private UwbServiceCore mUwbServiceCore;
106     @Mock private UwbMetrics mUwbMetrics;
107     @Mock private IUwbOemExtensionCallback mIOemExtensionCallback;
108     @Rule
109     public final CheckFlagsRule mCheckFlagsRule = DeviceFlagsValueProvider.createCheckFlagsRule();
110 
111     private UwbSessionNotificationManager mUwbSessionNotificationManager;
112 
113     @Before
setUp()114     public void setUp() throws Exception {
115         MockitoAnnotations.initMocks(this);
116         when(mUwbSession.getSessionHandle()).thenReturn(mSessionHandle);
117         when(mUwbSession.getIUwbRangingCallbacks()).thenReturn(mIUwbRangingCallbacks);
118         when(mUwbSession.getProtocolName()).thenReturn(FiraParams.PROTOCOL_NAME);
119         when(mUwbSession.getParams()).thenReturn(mFiraParams);
120         when(mUwbSession.getAttributionSource()).thenReturn(ATTRIBUTION_SOURCE);
121         when(mUwbRadarSession.getSessionHandle()).thenReturn(mSessionHandle);
122         when(mUwbRadarSession.getIUwbRangingCallbacks()).thenReturn(mIUwbRangingCallbacks);
123         when(mUwbRadarSession.getProtocolName()).thenReturn(RadarParams.PROTOCOL_NAME);
124         when(mUwbRadarSession.getParams()).thenReturn(mRadarParams);
125         when(mUwbRadarSession.getAttributionSource()).thenReturn(ATTRIBUTION_SOURCE);
126         when(mFiraParams.getAoaResultRequest()).thenReturn(
127                 FiraParams.AOA_RESULT_REQUEST_MODE_REQ_AOA_RESULTS);
128         when(mFiraParams.hasRangingResultReportMessage()).thenReturn(false);
129         when(mFiraParams.hasControlMessage()).thenReturn(false);
130         when(mFiraParams.hasRangingControlPhase()).thenReturn(true);
131         when(mUwbInjector.checkUwbRangingPermissionForStartDataDelivery(any(), any()))
132                 .thenReturn(true);
133         when(mUwbInjector.getElapsedSinceBootNanos()).thenReturn(TEST_ELAPSED_NANOS);
134         when(mUwbInjector.getUwbServiceCore()).thenReturn(mUwbServiceCore);
135         when(mUwbServiceCore.isOemExtensionCbRegistered()).thenReturn(true);
136         when(mUwbServiceCore.getOemExtensionCallback()).thenReturn(mIOemExtensionCallback);
137         when(mIOemExtensionCallback.onRangingReportReceived(any())).thenAnswer(
138                 invocation -> invocation.getArgument(0));
139         when(mUwbInjector.getUwbMetrics()).thenReturn(mUwbMetrics);
140         mUwbSessionNotificationManager = new UwbSessionNotificationManager(mUwbInjector);
141     }
142 
143     /**
144      * Called after each testGG
145      */
146     @After
cleanup()147     public void cleanup() {
148         validateMockitoUsage();
149     }
150 
151     @Test
testOnRangingResultWithoutUwbRangingPermission()152     public void testOnRangingResultWithoutUwbRangingPermission() throws Exception {
153         Pair<UwbRangingData, RangingReport> testRangingDataAndRangingReport =
154                 UwbTestUtils.generateRangingDataAndRangingReport(
155                         PEER_SHORT_MAC_ADDRESS, MAC_ADDRESSING_MODE_SHORT,
156                         RANGING_MEASUREMENT_TYPE_TWO_WAY,
157                         true, true, false, false, TEST_ELAPSED_NANOS);
158         when(mUwbInjector.checkUwbRangingPermissionForStartDataDelivery(eq(ATTRIBUTION_SOURCE),
159                 any())).thenReturn(false);
160         when(mUwbSession.isDataDeliveryPermissionCheckNeeded()).thenReturn(true);
161         mUwbSessionNotificationManager.onRangingResult(
162                 mUwbSession, testRangingDataAndRangingReport.first);
163 
164         verify(mIUwbRangingCallbacks, never()).onRangingResult(any(), any());
165         verify(mUwbMetrics, never()).logRangingResult(anyInt(), any(), any());
166     }
167 
168     @Test
testOnRangingResult_forTwoWay_WithAoa()169     public void testOnRangingResult_forTwoWay_WithAoa() throws Exception {
170         Pair<UwbRangingData, RangingReport> testRangingDataAndRangingReport =
171                 UwbTestUtils.generateRangingDataAndRangingReport(
172                         PEER_SHORT_MAC_ADDRESS, MAC_ADDRESSING_MODE_SHORT,
173                         RANGING_MEASUREMENT_TYPE_TWO_WAY,
174                         true, true, false, false, TEST_ELAPSED_NANOS);
175         mUwbSessionNotificationManager.onRangingResult(
176                 mUwbSession, testRangingDataAndRangingReport.first);
177         verify(mIUwbRangingCallbacks).onRangingResult(
178                 mSessionHandle, testRangingDataAndRangingReport.second);
179         verify(mUwbMetrics).logRangingResult(anyInt(), eq(testRangingDataAndRangingReport.first),
180                 eq(testRangingDataAndRangingReport.second.getMeasurements().get(0)));
181     }
182 
183     @Test
testOnRangingResult_forTwoWay_WithNoAoa()184     public void testOnRangingResult_forTwoWay_WithNoAoa() throws Exception {
185         when(mFiraParams.getAoaResultRequest()).thenReturn(
186                 FiraParams.AOA_RESULT_REQUEST_MODE_NO_AOA_REPORT);
187         Pair<UwbRangingData, RangingReport> testRangingDataAndRangingReport =
188                 UwbTestUtils.generateRangingDataAndRangingReport(
189                         PEER_SHORT_MAC_ADDRESS, MAC_ADDRESSING_MODE_SHORT,
190                         RANGING_MEASUREMENT_TYPE_TWO_WAY,
191                         false, false, false, false, TEST_ELAPSED_NANOS);
192         mUwbSessionNotificationManager.onRangingResult(
193                 mUwbSession, testRangingDataAndRangingReport.first);
194         verify(mIUwbRangingCallbacks).onRangingResult(
195                 mSessionHandle, testRangingDataAndRangingReport.second);
196         verify(mUwbMetrics).logRangingResult(anyInt(), eq(testRangingDataAndRangingReport.first),
197                 eq(testRangingDataAndRangingReport.second.getMeasurements().get(0)));
198     }
199 
200     @Test
testOnRangingResult_forTwoWay_WithNoAoaElevation()201     public void testOnRangingResult_forTwoWay_WithNoAoaElevation() throws Exception {
202         when(mFiraParams.getAoaResultRequest()).thenReturn(
203                 FiraParams.AOA_RESULT_REQUEST_MODE_REQ_AOA_RESULTS_AZIMUTH_ONLY);
204         Pair<UwbRangingData, RangingReport> testRangingDataAndRangingReport =
205                 UwbTestUtils.generateRangingDataAndRangingReport(
206                         PEER_SHORT_MAC_ADDRESS, MAC_ADDRESSING_MODE_SHORT,
207                         RANGING_MEASUREMENT_TYPE_TWO_WAY,
208                         true, false, false, false, TEST_ELAPSED_NANOS);
209         mUwbSessionNotificationManager.onRangingResult(
210                 mUwbSession, testRangingDataAndRangingReport.first);
211         verify(mIUwbRangingCallbacks).onRangingResult(
212                 mSessionHandle, testRangingDataAndRangingReport.second);
213         verify(mUwbMetrics).logRangingResult(anyInt(), eq(testRangingDataAndRangingReport.first),
214                 eq(testRangingDataAndRangingReport.second.getMeasurements().get(0)));
215     }
216 
217     @Test
testOnRangingResult_forTwoWay_WithNoAoaAzimuth()218     public void testOnRangingResult_forTwoWay_WithNoAoaAzimuth() throws Exception {
219         when(mFiraParams.getAoaResultRequest()).thenReturn(
220                 FiraParams.AOA_RESULT_REQUEST_MODE_REQ_AOA_RESULTS_ELEVATION_ONLY);
221         Pair<UwbRangingData, RangingReport> testRangingDataAndRangingReport =
222                 UwbTestUtils.generateRangingDataAndRangingReport(
223                         PEER_SHORT_MAC_ADDRESS, MAC_ADDRESSING_MODE_SHORT,
224                         RANGING_MEASUREMENT_TYPE_TWO_WAY,
225                         false, true, false, false, TEST_ELAPSED_NANOS);
226         mUwbSessionNotificationManager.onRangingResult(
227                 mUwbSession, testRangingDataAndRangingReport.first);
228         verify(mIUwbRangingCallbacks).onRangingResult(
229                 mSessionHandle, testRangingDataAndRangingReport.second);
230         verify(mUwbMetrics).logRangingResult(anyInt(), eq(testRangingDataAndRangingReport.first),
231                 eq(testRangingDataAndRangingReport.second.getMeasurements().get(0)));
232     }
233 
234     @Test
testOnRangingResult_forTwoWay_WithAoaAndDestAoa()235     public void testOnRangingResult_forTwoWay_WithAoaAndDestAoa() throws Exception {
236         when(mFiraParams.getAoaResultRequest()).thenReturn(
237                 FiraParams.AOA_RESULT_REQUEST_MODE_REQ_AOA_RESULTS);
238         when(mFiraParams.hasRangingResultReportMessage()).thenReturn(true);
239         when(mFiraParams.hasControlMessage()).thenReturn(true);
240         when(mFiraParams.hasRangingControlPhase()).thenReturn(false);
241         when(mFiraParams.hasAngleOfArrivalAzimuthReport()).thenReturn(true);
242         when(mFiraParams.hasAngleOfArrivalElevationReport()).thenReturn(true);
243         Pair<UwbRangingData, RangingReport> testRangingDataAndRangingReport =
244                 UwbTestUtils.generateRangingDataAndRangingReport(
245                         PEER_SHORT_MAC_ADDRESS, MAC_ADDRESSING_MODE_SHORT,
246                         RANGING_MEASUREMENT_TYPE_TWO_WAY,
247                         true, true, true, true, TEST_ELAPSED_NANOS);
248         mUwbSessionNotificationManager.onRangingResult(
249                 mUwbSession, testRangingDataAndRangingReport.first);
250         verify(mIUwbRangingCallbacks).onRangingResult(
251                 mSessionHandle, testRangingDataAndRangingReport.second);
252         verify(mUwbMetrics).logRangingResult(anyInt(), eq(testRangingDataAndRangingReport.first),
253                 eq(testRangingDataAndRangingReport.second.getMeasurements().get(0)));
254     }
255 
256     @Test
testOnRangingResult_forTwoWay_WithAoaAndNoDestAzimuth()257     public void testOnRangingResult_forTwoWay_WithAoaAndNoDestAzimuth() throws Exception {
258         when(mFiraParams.getAoaResultRequest()).thenReturn(
259                 FiraParams.AOA_RESULT_REQUEST_MODE_REQ_AOA_RESULTS);
260         when(mFiraParams.hasRangingResultReportMessage()).thenReturn(true);
261         when(mFiraParams.hasControlMessage()).thenReturn(true);
262         when(mFiraParams.hasRangingControlPhase()).thenReturn(false);
263         when(mFiraParams.hasAngleOfArrivalAzimuthReport()).thenReturn(false);
264         when(mFiraParams.hasAngleOfArrivalElevationReport()).thenReturn(true);
265         Pair<UwbRangingData, RangingReport> testRangingDataAndRangingReport =
266                 UwbTestUtils.generateRangingDataAndRangingReport(
267                         PEER_SHORT_MAC_ADDRESS, MAC_ADDRESSING_MODE_SHORT,
268                         RANGING_MEASUREMENT_TYPE_TWO_WAY,
269                         true, true, false, true, TEST_ELAPSED_NANOS);
270         mUwbSessionNotificationManager.onRangingResult(
271                 mUwbSession, testRangingDataAndRangingReport.first);
272         verify(mIUwbRangingCallbacks).onRangingResult(
273                 mSessionHandle, testRangingDataAndRangingReport.second);
274         verify(mUwbMetrics).logRangingResult(anyInt(), eq(testRangingDataAndRangingReport.first),
275                 eq(testRangingDataAndRangingReport.second.getMeasurements().get(0)));
276     }
277 
278     @Test
testOnRangingResult_forTwoWay_WithAoaAndNoDestElevation()279     public void testOnRangingResult_forTwoWay_WithAoaAndNoDestElevation() throws Exception {
280         when(mFiraParams.getAoaResultRequest()).thenReturn(
281                 FiraParams.AOA_RESULT_REQUEST_MODE_REQ_AOA_RESULTS);
282         when(mFiraParams.hasRangingResultReportMessage()).thenReturn(true);
283         when(mFiraParams.hasControlMessage()).thenReturn(true);
284         when(mFiraParams.hasRangingControlPhase()).thenReturn(false);
285         when(mFiraParams.hasAngleOfArrivalAzimuthReport()).thenReturn(true);
286         when(mFiraParams.hasAngleOfArrivalElevationReport()).thenReturn(false);
287         Pair<UwbRangingData, RangingReport> testRangingDataAndRangingReport =
288                 UwbTestUtils.generateRangingDataAndRangingReport(
289                         PEER_SHORT_MAC_ADDRESS, MAC_ADDRESSING_MODE_SHORT,
290                         RANGING_MEASUREMENT_TYPE_TWO_WAY,
291                         true, true, true, false, TEST_ELAPSED_NANOS);
292         mUwbSessionNotificationManager.onRangingResult(
293                 mUwbSession, testRangingDataAndRangingReport.first);
294         verify(mIUwbRangingCallbacks).onRangingResult(
295                 mSessionHandle, testRangingDataAndRangingReport.second);
296         verify(mUwbMetrics).logRangingResult(anyInt(), eq(testRangingDataAndRangingReport.first),
297                 eq(testRangingDataAndRangingReport.second.getMeasurements().get(0)));
298     }
299 
300     @Test
testOnRangingResult_forTwoWay_WithNoAoaAndDestAoa()301     public void testOnRangingResult_forTwoWay_WithNoAoaAndDestAoa() throws Exception {
302         when(mFiraParams.getAoaResultRequest()).thenReturn(
303                 FiraParams.AOA_RESULT_REQUEST_MODE_NO_AOA_REPORT);
304         when(mFiraParams.hasRangingResultReportMessage()).thenReturn(true);
305         when(mFiraParams.hasControlMessage()).thenReturn(true);
306         when(mFiraParams.hasRangingControlPhase()).thenReturn(false);
307         when(mFiraParams.hasAngleOfArrivalAzimuthReport()).thenReturn(true);
308         when(mFiraParams.hasAngleOfArrivalElevationReport()).thenReturn(true);
309         Pair<UwbRangingData, RangingReport> testRangingDataAndRangingReport =
310                 UwbTestUtils.generateRangingDataAndRangingReport(
311                         PEER_SHORT_MAC_ADDRESS, MAC_ADDRESSING_MODE_SHORT,
312                         RANGING_MEASUREMENT_TYPE_TWO_WAY,
313                         false, false, true, true, TEST_ELAPSED_NANOS);
314         mUwbSessionNotificationManager.onRangingResult(
315                 mUwbSession, testRangingDataAndRangingReport.first);
316         verify(mIUwbRangingCallbacks).onRangingResult(
317                 mSessionHandle, testRangingDataAndRangingReport.second);
318         verify(mUwbMetrics).logRangingResult(anyInt(), eq(testRangingDataAndRangingReport.first),
319                 eq(testRangingDataAndRangingReport.second.getMeasurements().get(0)));
320     }
321 
322     @Test
testOnRangingResult_forTwoWay_WithNoAoaAzimuthAndDestAoa()323     public void testOnRangingResult_forTwoWay_WithNoAoaAzimuthAndDestAoa() throws Exception {
324         when(mFiraParams.getAoaResultRequest()).thenReturn(
325                 FiraParams.AOA_RESULT_REQUEST_MODE_REQ_AOA_RESULTS_ELEVATION_ONLY);
326         when(mFiraParams.hasRangingResultReportMessage()).thenReturn(true);
327         when(mFiraParams.hasControlMessage()).thenReturn(true);
328         when(mFiraParams.hasRangingControlPhase()).thenReturn(false);
329         when(mFiraParams.hasAngleOfArrivalAzimuthReport()).thenReturn(true);
330         when(mFiraParams.hasAngleOfArrivalElevationReport()).thenReturn(true);
331         Pair<UwbRangingData, RangingReport> testRangingDataAndRangingReport =
332                 UwbTestUtils.generateRangingDataAndRangingReport(
333                         PEER_SHORT_MAC_ADDRESS, MAC_ADDRESSING_MODE_SHORT,
334                         RANGING_MEASUREMENT_TYPE_TWO_WAY,
335                         false, true, true, true, TEST_ELAPSED_NANOS);
336         mUwbSessionNotificationManager.onRangingResult(
337                 mUwbSession, testRangingDataAndRangingReport.first);
338         verify(mIUwbRangingCallbacks).onRangingResult(
339                 mSessionHandle, testRangingDataAndRangingReport.second);
340         verify(mUwbMetrics).logRangingResult(anyInt(), eq(testRangingDataAndRangingReport.first),
341                 eq(testRangingDataAndRangingReport.second.getMeasurements().get(0)));
342     }
343 
344     @Test
testOnRangingResult_forTwoWay_WithNoAoaElevationAndDestAoa()345     public void testOnRangingResult_forTwoWay_WithNoAoaElevationAndDestAoa() throws Exception {
346         when(mFiraParams.getAoaResultRequest()).thenReturn(
347                 FiraParams.AOA_RESULT_REQUEST_MODE_REQ_AOA_RESULTS_AZIMUTH_ONLY);
348         when(mFiraParams.hasRangingResultReportMessage()).thenReturn(true);
349         when(mFiraParams.hasControlMessage()).thenReturn(true);
350         when(mFiraParams.hasRangingControlPhase()).thenReturn(false);
351         when(mFiraParams.hasAngleOfArrivalAzimuthReport()).thenReturn(true);
352         when(mFiraParams.hasAngleOfArrivalElevationReport()).thenReturn(true);
353         Pair<UwbRangingData, RangingReport> testRangingDataAndRangingReport =
354                 UwbTestUtils.generateRangingDataAndRangingReport(
355                         PEER_SHORT_MAC_ADDRESS, MAC_ADDRESSING_MODE_SHORT,
356                         RANGING_MEASUREMENT_TYPE_TWO_WAY,
357                         true, false, true, true, TEST_ELAPSED_NANOS);
358         mUwbSessionNotificationManager.onRangingResult(
359                 mUwbSession, testRangingDataAndRangingReport.first);
360         verify(mIUwbRangingCallbacks).onRangingResult(
361                 mSessionHandle, testRangingDataAndRangingReport.second);
362         verify(mUwbMetrics).logRangingResult(anyInt(), eq(testRangingDataAndRangingReport.first),
363                 eq(testRangingDataAndRangingReport.second.getMeasurements().get(0)));
364     }
365 
366     @Test
testOnRangingResult_forOwrAoa()367     public void testOnRangingResult_forOwrAoa() throws Exception {
368         Pair<UwbRangingData, RangingReport> testRangingDataAndRangingReport =
369                 UwbTestUtils.generateRangingDataAndRangingReport(
370                         PEER_SHORT_MAC_ADDRESS, MAC_ADDRESSING_MODE_SHORT,
371                         RANGING_MEASUREMENT_TYPE_OWR_AOA,
372                         true, true, false, false, TEST_ELAPSED_NANOS);
373         mUwbSessionNotificationManager.onRangingResult(
374                 mUwbSession, testRangingDataAndRangingReport.first);
375         verify(mIUwbRangingCallbacks).onRangingResult(
376                 mSessionHandle, testRangingDataAndRangingReport.second);
377         verify(mUwbMetrics).logRangingResult(anyInt(), eq(testRangingDataAndRangingReport.first),
378                 eq(testRangingDataAndRangingReport.second.getMeasurements().get(0)));
379     }
380 
381     @Test
testOnRangingResult_forDlTDoA()382     public void testOnRangingResult_forDlTDoA() throws Exception {
383         Pair<UwbRangingData, RangingReport> testRangingDataAndRangingReport =
384                 UwbTestUtils.generateRangingDataAndRangingReport(
385                         PEER_SHORT_MAC_ADDRESS, MAC_ADDRESSING_MODE_SHORT,
386                         RANGING_MEASUREMENT_TYPE_DL_TDOA,
387                         true, true, false, false, TEST_ELAPSED_NANOS);
388         mUwbSessionNotificationManager.onRangingResult(
389                 mUwbSession, testRangingDataAndRangingReport.first);
390         verify(mIUwbRangingCallbacks).onRangingResult(
391                 mSessionHandle, testRangingDataAndRangingReport.second);
392         verify(mUwbMetrics).logRangingResult(anyInt(), eq(testRangingDataAndRangingReport.first),
393                 eq(testRangingDataAndRangingReport.second.getMeasurements().get(0)));
394     }
395 
396     @Test
testOnRangingResult_badRangingDataForOwrAoa()397     public void testOnRangingResult_badRangingDataForOwrAoa() throws Exception {
398         UwbRangingData testRangingData = UwbTestUtils.generateBadOwrAoaMeasurementRangingData(
399                 MAC_ADDRESSING_MODE_SHORT, PEER_SHORT_MAC_ADDRESS);
400         mUwbSessionNotificationManager.onRangingResult(mUwbSession, testRangingData);
401         verifyZeroInteractions(mIUwbRangingCallbacks);
402     }
403 
404     @Test
testOnRangingOpened()405     public void testOnRangingOpened() throws Exception {
406         mUwbSessionNotificationManager.onRangingOpened(mUwbSession);
407 
408         verify(mIUwbRangingCallbacks).onRangingOpened(mSessionHandle);
409     }
410 
411     @Test
testOnRangingOpenFailed()412     public void testOnRangingOpenFailed() throws Exception {
413         int status = UwbUciConstants.STATUS_CODE_ERROR_MAX_SESSIONS_EXCEEDED;
414         mUwbSessionNotificationManager.onRangingOpenFailed(mUwbSession, status);
415 
416         verify(mIUwbRangingCallbacks).onRangingOpenFailed(eq(mSessionHandle),
417                 eq(UwbSessionNotificationHelper.convertUciStatusToApiReasonCode(status)),
418                 argThat(p -> (p.getInt("status_code")) == status));
419     }
420 
421     @Test
testOnRangingStarted()422     public void testOnRangingStarted() throws Exception {
423         mUwbSessionNotificationManager.onRangingStarted(mUwbSession, mUwbSession.getParams());
424 
425         verify(mIUwbRangingCallbacks).onRangingStarted(mSessionHandle,
426                 mUwbSession.getParams().toBundle());
427     }
428 
429     @Test
testOnRangingStartFailed()430     public void testOnRangingStartFailed() throws Exception {
431         int status =  UwbUciConstants.STATUS_CODE_INVALID_PARAM;
432         mUwbSessionNotificationManager.onRangingStartFailed(mUwbSession, status);
433 
434         verify(mIUwbRangingCallbacks).onRangingStartFailed(eq(mSessionHandle),
435                 eq(UwbSessionNotificationHelper.convertUciStatusToApiReasonCode(status)),
436                 argThat(p -> (p.getInt("status_code")) == status));
437     }
438 
439     @Test
testOnRangingStartFailedWithUciReasonCode()440     public void testOnRangingStartFailedWithUciReasonCode() throws Exception {
441         int reasonCode =  UwbUciConstants.REASON_ERROR_SESSION_KEY_NOT_FOUND;
442         mUwbSessionNotificationManager.onRangingStartFailedWithUciReasonCode(
443                 mUwbSession, reasonCode);
444 
445         int expectedStatusCode = UwbUciConstants.STATUS_CODE_ERROR_SESSION_NOT_EXIST;
446         verify(mIUwbRangingCallbacks).onRangingStartFailed(eq(mSessionHandle),
447                 eq(RangingChangeReason.PROTOCOL_SPECIFIC),
448                 argThat(p -> (p.getInt("status_code")) == expectedStatusCode));
449     }
450 
451     @Test
testOnRangingStoppedWithUciReasonCode_reasonLocalApi()452     public void testOnRangingStoppedWithUciReasonCode_reasonLocalApi() throws Exception {
453         int reasonCode = UwbUciConstants.REASON_STATE_CHANGE_WITH_SESSION_MANAGEMENT_COMMANDS;
454         mUwbSessionNotificationManager.onRangingStoppedWithUciReasonCode(mUwbSession, reasonCode);
455 
456         verify(mIUwbRangingCallbacks).onRangingStopped(
457                 eq(mSessionHandle), eq(RangingChangeReason.LOCAL_API),
458                 isA(PersistableBundle.class));
459     }
460     @Test
testOnRangingStoppedWithUciReasonCode_reasonMaxRRRetryReached()461     public void testOnRangingStoppedWithUciReasonCode_reasonMaxRRRetryReached() throws Exception {
462         int reasonCode = UwbUciConstants.REASON_MAX_RANGING_ROUND_RETRY_COUNT_REACHED;
463         mUwbSessionNotificationManager.onRangingStoppedWithUciReasonCode(mUwbSession, reasonCode);
464 
465         verify(mIUwbRangingCallbacks).onRangingStopped(
466                 eq(mSessionHandle), eq(RangingChangeReason.MAX_RR_RETRY_REACHED),
467                 isA(PersistableBundle.class));
468     }
469 
470     @Test
testOnRangingStoppedWithUciReasonCode_reasonRemoteRequest()471     public void testOnRangingStoppedWithUciReasonCode_reasonRemoteRequest() throws Exception {
472         int reasonCode = UwbUciConstants.REASON_MAX_NUMBER_OF_MEASUREMENTS_REACHED;
473         mUwbSessionNotificationManager.onRangingStoppedWithUciReasonCode(mUwbSession, reasonCode);
474 
475         verify(mIUwbRangingCallbacks).onRangingStopped(
476                 eq(mSessionHandle), eq(RangingChangeReason.REMOTE_REQUEST),
477                 isA(PersistableBundle.class));
478     }
479 
480     @Test
testOnRangingStoppedWithUciReasonCode_reasonBadParameters()481     public void testOnRangingStoppedWithUciReasonCode_reasonBadParameters() throws Exception {
482         Set<Integer> reasonCodes = Set.of(
483                 UwbUciConstants.REASON_ERROR_INSUFFICIENT_SLOTS_PER_RR,
484                 UwbUciConstants.REASON_ERROR_SLOT_LENGTH_NOT_SUPPORTED,
485                 UwbUciConstants.REASON_ERROR_INVALID_UL_TDOA_RANDOM_WINDOW,
486                 UwbUciConstants.REASON_ERROR_MAC_ADDRESS_MODE_NOT_SUPPORTED,
487                 UwbUciConstants.REASON_ERROR_INVALID_RANGING_INTERVAL,
488                 UwbUciConstants.REASON_ERROR_INVALID_STS_CONFIG,
489                 UwbUciConstants.REASON_ERROR_INVALID_RFRAME_CONFIG,
490                 UwbUciConstants.REASON_ERROR_HUS_NOT_ENOUGH_SLOTS,
491                 UwbUciConstants.REASON_ERROR_HUS_CFP_PHASE_TOO_SHORT,
492                 UwbUciConstants.REASON_ERROR_HUS_CAP_PHASE_TOO_SHORT,
493                 UwbUciConstants.REASON_ERROR_HUS_OTHERS);
494         for (int reasonCode : reasonCodes) {
495             clearInvocations(mIUwbRangingCallbacks);
496             mUwbSessionNotificationManager.onRangingStoppedWithUciReasonCode(mUwbSession,
497                     reasonCode);
498             verify(mIUwbRangingCallbacks).onRangingStopped(
499                     eq(mSessionHandle), eq(RangingChangeReason.BAD_PARAMETERS),
500                     isA(PersistableBundle.class));
501         }
502     }
503 
504     @Test
testOnRangingStoppedWithUciReasonCode_reasonSystemRegulation()505     public void testOnRangingStoppedWithUciReasonCode_reasonSystemRegulation() throws Exception {
506         int reasonCode = UwbUciConstants.REASON_REGULATION_UWB_OFF;
507         mUwbSessionNotificationManager.onRangingStoppedWithUciReasonCode(mUwbSession, reasonCode);
508 
509         verify(mIUwbRangingCallbacks).onRangingStopped(
510                 eq(mSessionHandle), eq(RangingChangeReason.SYSTEM_REGULATION),
511                 isA(PersistableBundle.class));
512     }
513 
514     @Test
testOnRangingStoppedWithApiReasonCode()515     public void  testOnRangingStoppedWithApiReasonCode() throws Exception {
516         mUwbSessionNotificationManager.onRangingStoppedWithApiReasonCode(
517                 mUwbSession, RangingChangeReason.SYSTEM_POLICY, new PersistableBundle());
518 
519         verify(mIUwbRangingCallbacks).onRangingStopped(
520                 eq(mSessionHandle), eq(RangingChangeReason.SYSTEM_POLICY),
521                 isA(PersistableBundle.class));
522     }
523 
524     @Test
testOnRangingStopped()525     public void testOnRangingStopped() throws Exception {
526         int status = UwbUciConstants.REASON_STATE_CHANGE_WITH_SESSION_MANAGEMENT_COMMANDS;
527         mUwbSessionNotificationManager.onRangingStopped(mUwbSession, status);
528 
529         verify(mIUwbRangingCallbacks).onRangingStopped(eq(mSessionHandle),
530                 eq(UwbSessionNotificationHelper.convertUciStatusToApiReasonCode(status)),
531                 argThat(p-> p.getInt("status_code") == status));
532     }
533 
534     @Test
535     @RequiresFlagsEnabled(Flags.FLAG_REASON_INBAND_SESSION_STOP)
testRangingStoppedDuetoInbandSignal()536     public void testRangingStoppedDuetoInbandSignal() throws Exception {
537         mUwbSessionNotificationManager.onRangingStoppedWithApiReasonCode(mUwbSession,
538                 RangingChangeReason.INBAND_SESSION_STOP, new PersistableBundle());
539 
540         verify(mIUwbRangingCallbacks).onRangingStopped(
541                 eq(mSessionHandle), eq(RangingChangeReason.INBAND_SESSION_STOP),
542                 isA(PersistableBundle.class));
543     }
544 
545     @Test
testOnRangingStopFailed()546     public void testOnRangingStopFailed() throws Exception {
547         int status = UwbUciConstants.STATUS_CODE_INVALID_RANGE;
548         mUwbSessionNotificationManager.onRangingStopFailed(mUwbSession, status);
549 
550         verify(mIUwbRangingCallbacks).onRangingStopFailed(eq(mSessionHandle),
551                 eq(UwbSessionNotificationHelper.convertUciStatusToApiReasonCode(status)),
552                 argThat(p -> (p.getInt("status_code")) == status));
553     }
554 
555     @Test
testOnRangingReconfigured()556     public void testOnRangingReconfigured() throws Exception {
557         mUwbSessionNotificationManager.onRangingReconfigured(mUwbSession);
558 
559         verify(mIUwbRangingCallbacks).onRangingReconfigured(eq(mSessionHandle), any());
560     }
561 
562     @Test
testOnRangingReconfigureFailed()563     public void testOnRangingReconfigureFailed() throws Exception {
564         int status =  UwbUciConstants.STATUS_CODE_INVALID_MESSAGE_SIZE;
565         mUwbSessionNotificationManager.onRangingReconfigureFailed(mUwbSession, status);
566 
567         verify(mIUwbRangingCallbacks).onRangingReconfigureFailed(eq(mSessionHandle),
568                 eq(UwbSessionNotificationHelper.convertUciStatusToApiReasonCode(status)),
569                 argThat(p -> (p.getInt("status_code")) == status));
570     }
571 
572     @Test
testOnControleeAdded()573     public void testOnControleeAdded() throws Exception {
574         mUwbSessionNotificationManager.onControleeAdded(mUwbSession);
575 
576         verify(mIUwbRangingCallbacks).onControleeAdded(eq(mSessionHandle), any());
577     }
578 
579     @Test
testOnControleeAddFailed()580     public void testOnControleeAddFailed() throws Exception {
581         int status =  UwbUciConstants.STATUS_CODE_INVALID_MESSAGE_SIZE;
582         mUwbSessionNotificationManager.onControleeAddFailed(mUwbSession, status);
583 
584         verify(mIUwbRangingCallbacks).onControleeAddFailed(eq(mSessionHandle),
585                 eq(UwbSessionNotificationHelper.convertUciStatusToApiReasonCode(status)),
586                 argThat(p -> (p.getInt("status_code")) == status));
587     }
588 
589     @Test
testOnControleeRemoved()590     public void testOnControleeRemoved() throws Exception {
591         UwbAddress address = UwbTestUtils.PEER_EXTENDED_UWB_ADDRESS;
592         int reason = FiraOnControleeRemovedParams.Reason.LOST_CONNECTION;
593 
594         ArgumentCaptor<PersistableBundle> bundleCaptor =
595                 ArgumentCaptor.forClass(PersistableBundle.class);
596 
597         mUwbSessionNotificationManager.onControleeRemoved(mUwbSession, address, reason);
598         verify(mIUwbRangingCallbacks).onControleeRemoved(eq(mSessionHandle),
599                 bundleCaptor.capture());
600 
601         FiraOnControleeRemovedParams params =
602                 FiraOnControleeRemovedParams.fromBundle(bundleCaptor.getValue());
603         assertThat(params.getAddress()).isEqualTo(address);
604         assertThat(params.getReason()).isEqualTo(reason);
605     }
606 
607     @Test
testOnControleeRemoveFailed()608     public void testOnControleeRemoveFailed() throws Exception {
609         int status =  UwbUciConstants.STATUS_CODE_INVALID_MESSAGE_SIZE;
610         mUwbSessionNotificationManager.onControleeRemoveFailed(mUwbSession, status);
611 
612         verify(mIUwbRangingCallbacks).onControleeRemoveFailed(eq(mSessionHandle),
613                 eq(UwbSessionNotificationHelper.convertUciStatusToApiReasonCode(status)),
614                 argThat(p -> (p.getInt("status_code")) == status));
615     }
616 
617     @Test
testOnRangingClosed()618     public void testOnRangingClosed() throws Exception {
619         int status = UwbUciConstants.REASON_ERROR_SLOT_LENGTH_NOT_SUPPORTED;
620         mUwbSessionNotificationManager.onRangingClosed(mUwbSession, status);
621 
622         verify(mIUwbRangingCallbacks).onRangingClosed(eq(mSessionHandle),
623                 eq(UwbSessionNotificationHelper.convertUciStatusToApiReasonCode(status)),
624                 argThat(p-> p.getInt("status_code") == status));
625     }
626 
627     @Test
testOnRangingClosedWithReasonCode()628     public void testOnRangingClosedWithReasonCode() throws Exception {
629         int reasonCode = RangingChangeReason.SYSTEM_POLICY;
630         mUwbSessionNotificationManager.onRangingClosedWithApiReasonCode(mUwbSession, reasonCode);
631 
632         verify(mIUwbRangingCallbacks).onRangingClosed(eq(mSessionHandle),
633                 eq(reasonCode),
634                 argThat(p-> p.isEmpty()));
635     }
636 
637     @Test
testOnDataReceived()638     public void testOnDataReceived() throws Exception {
639         mUwbSessionNotificationManager.onDataReceived(mUwbSession, PEER_EXTENDED_UWB_ADDRESS,
640                 PERSISTABLE_BUNDLE, DATA_PAYLOAD);
641 
642         verify(mIUwbRangingCallbacks).onDataReceived(eq(mSessionHandle), eq(
643                         PEER_EXTENDED_UWB_ADDRESS),
644                 eq(PERSISTABLE_BUNDLE), eq(DATA_PAYLOAD));
645     }
646 
647     @Test
testOnDataReceiveFailed()648     public void testOnDataReceiveFailed() throws Exception {
649         mUwbSessionNotificationManager.onDataReceiveFailed(mUwbSession, PEER_EXTENDED_UWB_ADDRESS,
650                 STATUS_CODE_FAILED, PERSISTABLE_BUNDLE);
651 
652         verify(mIUwbRangingCallbacks).onDataReceiveFailed(eq(mSessionHandle), eq(
653                         PEER_EXTENDED_UWB_ADDRESS),
654                 eq(STATUS_CODE_FAILED), eq(PERSISTABLE_BUNDLE));
655     }
656 
657     @Test
testOnDataSent()658     public void testOnDataSent() throws Exception {
659         mUwbSessionNotificationManager.onDataSent(mUwbSession, PEER_EXTENDED_UWB_ADDRESS,
660                 PERSISTABLE_BUNDLE);
661 
662         verify(mIUwbRangingCallbacks).onDataSent(eq(mSessionHandle), eq(PEER_EXTENDED_UWB_ADDRESS),
663                 eq(PERSISTABLE_BUNDLE));
664     }
665 
666     @Test
testOnDataSendFailed()667     public void testOnDataSendFailed() throws Exception {
668         mUwbSessionNotificationManager.onDataSendFailed(mUwbSession, PEER_EXTENDED_UWB_ADDRESS,
669                 STATUS_CODE_FAILED, PERSISTABLE_BUNDLE);
670 
671         verify(mIUwbRangingCallbacks).onDataSendFailed(eq(mSessionHandle), eq(
672                         PEER_EXTENDED_UWB_ADDRESS),
673                 eq(STATUS_CODE_FAILED), eq(PERSISTABLE_BUNDLE));
674     }
675 
676     @Test
testOnDataTransferPhaseConfigured()677     public void testOnDataTransferPhaseConfigured() throws Exception {
678         int dataTransferPhaseConfigStatus =
679                 UwbUciConstants.STATUS_CODE_DATA_TRANSFER_PHASE_CONFIG_DTPCM_CONFIG_SUCCESS;
680         mUwbSessionNotificationManager.onDataTransferPhaseConfigured(mUwbSession,
681                 dataTransferPhaseConfigStatus);
682 
683         verify(mIUwbRangingCallbacks).onDataTransferPhaseConfigured(eq(mSessionHandle),
684                 argThat(p -> (p.getInt("data_transfer_phase_config_status_code"))
685                       == dataTransferPhaseConfigStatus));
686     }
687 
688     @Test
testOnDataTransferPhaseConfigFailed()689     public void testOnDataTransferPhaseConfigFailed() throws Exception {
690         int dataTransferPhaseConfigStatus =
691                 UwbUciConstants.STATUS_CODE_DATA_TRANSFER_PHASE_CONFIG_ERROR_DUPLICATE_SLOT_ASSIGNMENT;
692         mUwbSessionNotificationManager.onDataTransferPhaseConfigFailed(mUwbSession,
693                 dataTransferPhaseConfigStatus);
694 
695         verify(mIUwbRangingCallbacks).onDataTransferPhaseConfigFailed(eq(mSessionHandle),
696                 eq(RangingChangeReason.PROTOCOL_SPECIFIC),
697                 argThat(p -> (p.getInt("data_transfer_phase_config_status_code"))
698                       == dataTransferPhaseConfigStatus));
699     }
700 
701     @Test
testOnHybridSessionControllerConfigured()702     public void testOnHybridSessionControllerConfigured() throws Exception {
703         mUwbSessionNotificationManager.onHybridSessionControllerConfigured(mUwbSession,
704                 UwbUciConstants.STATUS_CODE_OK);
705 
706         verify(mIUwbRangingCallbacks).onHybridSessionControllerConfigured(eq(mSessionHandle),
707                 argThat(p -> (p.getInt("status_code")) == UwbUciConstants.STATUS_CODE_OK));
708     }
709 
710     @Test
testOnHybridSessionControllerConfigurationFailed()711     public void testOnHybridSessionControllerConfigurationFailed() throws Exception {
712         mUwbSessionNotificationManager.onHybridSessionControllerConfigurationFailed(mUwbSession,
713                 UwbUciConstants.STATUS_CODE_FAILED);
714 
715         verify(mIUwbRangingCallbacks).onHybridSessionControllerConfigurationFailed(
716                 eq(mSessionHandle),
717                 eq(RangingChangeReason.UNKNOWN),
718                 argThat(p -> (p.getInt("status_code")) == UwbUciConstants.STATUS_CODE_FAILED));
719     }
720 
721     @Test
testOnHybridSessionControleeConfigured()722     public void testOnHybridSessionControleeConfigured() throws Exception {
723         mUwbSessionNotificationManager.onHybridSessionControleeConfigured(mUwbSession,
724                 UwbUciConstants.STATUS_CODE_OK);
725 
726         verify(mIUwbRangingCallbacks).onHybridSessionControleeConfigured(eq(mSessionHandle),
727                 argThat(p -> (p.getInt("status_code")) == UwbUciConstants.STATUS_CODE_OK));
728     }
729 
730     @Test
testOnHybridSessionControleeConfigurationFailed()731     public void testOnHybridSessionControleeConfigurationFailed() throws Exception {
732         mUwbSessionNotificationManager.onHybridSessionControleeConfigurationFailed(mUwbSession,
733                 UwbUciConstants.STATUS_CODE_FAILED);
734 
735         verify(mIUwbRangingCallbacks).onHybridSessionControleeConfigurationFailed(
736                 eq(mSessionHandle),
737                 eq(RangingChangeReason.UNKNOWN),
738                 argThat(p -> (p.getInt("status_code")) == UwbUciConstants.STATUS_CODE_FAILED));
739     }
740 
741     @Test
testOnRangingRoundsUpdateStatus()742     public void testOnRangingRoundsUpdateStatus() throws RemoteException {
743         PersistableBundle bundle = new PersistableBundle();
744         mUwbSessionNotificationManager.onRangingRoundsUpdateStatus(mUwbSession, bundle);
745 
746         verify(mIUwbRangingCallbacks).onRangingRoundsUpdateDtTagStatus(eq(mSessionHandle),
747                 eq(bundle));
748     }
749 
750     @Test
testonRadarDataMessageReceivedWithoutUwbRangingPermission()751     public void testonRadarDataMessageReceivedWithoutUwbRangingPermission() throws Exception {
752         Pair<UwbRadarData, RadarData> testUwbRadarDataAndRadarData =
753                 UwbTestUtils.generateUwbRadarDataAndRadarData(
754                         RADAR_DATA_TYPE_RADAR_SWEEP_SAMPLES);
755         when(mUwbInjector.checkUwbRangingPermissionForStartDataDelivery(eq(ATTRIBUTION_SOURCE),
756                 any())).thenReturn(false);
757         when(mUwbRadarSession.isDataDeliveryPermissionCheckNeeded()).thenReturn(true);
758         mUwbSessionNotificationManager.onRadarDataMessageReceived(
759                 mUwbRadarSession, testUwbRadarDataAndRadarData.first);
760 
761         verify(mIUwbRangingCallbacks, never()).onDataReceived(any(), any(), any(), any());
762     }
763 
764     @Test
testonRadarDataMessageReceived_forRadarSweepData()765     public void testonRadarDataMessageReceived_forRadarSweepData() throws Exception {
766         Pair<UwbRadarData, RadarData> testUwbRadarDataAndRadarData =
767                 UwbTestUtils.generateUwbRadarDataAndRadarData(
768                         RADAR_DATA_TYPE_RADAR_SWEEP_SAMPLES);
769         mUwbSessionNotificationManager.onRadarDataMessageReceived(
770                 mUwbRadarSession, testUwbRadarDataAndRadarData.first);
771 
772         verify(mIUwbRangingCallbacks).onDataReceived(
773                 eq(mSessionHandle),
774                 eq(UwbAddress.fromBytes(new byte[] {0x00, 0x00})),
775                 argThat(p -> p.getInt("sweep_offset")
776                         == testUwbRadarDataAndRadarData.second.getSweepOffset()),
777                 eq(new byte[] {}));
778     }
779 }
780