1 /*
2  * Copyright (C) 2022 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 android.app.ActivityManager.RunningAppProcessInfo.IMPORTANCE_BACKGROUND;
20 import static android.app.ActivityManager.RunningAppProcessInfo.IMPORTANCE_FOREGROUND;
21 
22 import static com.android.modules.utils.build.SdkLevel.isAtLeastV;
23 import static com.android.server.uwb.UwbSessionManager.SESSION_OPEN_RANGING;
24 import static com.android.server.uwb.UwbTestUtils.DATA_PAYLOAD;
25 import static com.android.server.uwb.UwbTestUtils.MAX_DATA_SIZE;
26 import static com.android.server.uwb.UwbTestUtils.PEER_BAD_MAC_ADDRESS;
27 import static com.android.server.uwb.UwbTestUtils.PEER_EXTENDED_MAC_ADDRESS;
28 import static com.android.server.uwb.UwbTestUtils.PEER_EXTENDED_MAC_ADDRESS_2;
29 import static com.android.server.uwb.UwbTestUtils.PEER_EXTENDED_MAC_ADDRESS_2_LONG;
30 import static com.android.server.uwb.UwbTestUtils.PEER_EXTENDED_MAC_ADDRESS_LONG;
31 import static com.android.server.uwb.UwbTestUtils.PEER_EXTENDED_SHORT_MAC_ADDRESS;
32 import static com.android.server.uwb.UwbTestUtils.PEER_EXTENDED_SHORT_MAC_ADDRESS_LONG;
33 import static com.android.server.uwb.UwbTestUtils.PEER_EXTENDED_SHORT_UWB_ADDRESS;
34 import static com.android.server.uwb.UwbTestUtils.PEER_EXTENDED_UWB_ADDRESS;
35 import static com.android.server.uwb.UwbTestUtils.PEER_EXTENDED_UWB_ADDRESS_2;
36 import static com.android.server.uwb.UwbTestUtils.PEER_SHORT_MAC_ADDRESS;
37 import static com.android.server.uwb.UwbTestUtils.PEER_SHORT_MAC_ADDRESS_LONG;
38 import static com.android.server.uwb.UwbTestUtils.PEER_SHORT_UWB_ADDRESS;
39 import static com.android.server.uwb.UwbTestUtils.PERSISTABLE_BUNDLE;
40 import static com.android.server.uwb.UwbTestUtils.RANGING_MEASUREMENT_TYPE_UNDEFINED;
41 import static com.android.server.uwb.UwbTestUtils.TEST_SESSION_ID;
42 import static com.android.server.uwb.UwbTestUtils.TEST_SESSION_ID_2;
43 import static com.android.server.uwb.UwbTestUtils.TEST_SESSION_TYPE;
44 import static com.android.server.uwb.data.UwbUciConstants.MAC_ADDRESSING_MODE_EXTENDED;
45 import static com.android.server.uwb.data.UwbUciConstants.MAC_ADDRESSING_MODE_SHORT;
46 import static com.android.server.uwb.data.UwbUciConstants.RANGING_DEVICE_ROLE_ADVERTISER;
47 import static com.android.server.uwb.data.UwbUciConstants.RANGING_DEVICE_ROLE_OBSERVER;
48 import static com.android.server.uwb.data.UwbUciConstants.RANGING_MEASUREMENT_TYPE_OWR_AOA;
49 import static com.android.server.uwb.data.UwbUciConstants.RANGING_MEASUREMENT_TYPE_TWO_WAY;
50 import static com.android.server.uwb.data.UwbUciConstants.ROUND_USAGE_DS_TWR_DEFERRED_MODE;
51 import static com.android.server.uwb.data.UwbUciConstants.ROUND_USAGE_DS_TWR_NON_DEFERRED_MODE;
52 import static com.android.server.uwb.data.UwbUciConstants.ROUND_USAGE_OWR_AOA_MEASUREMENT;
53 import static com.android.server.uwb.data.UwbUciConstants.STATUS_CODE_DATA_TRANSFER_ERROR_DATA_TRANSFER;
54 import static com.android.server.uwb.data.UwbUciConstants.STATUS_CODE_DATA_TRANSFER_OK;
55 import static com.android.server.uwb.data.UwbUciConstants.STATUS_CODE_DATA_TRANSFER_REPETITION_OK;
56 
57 import static com.google.common.truth.Truth.assertThat;
58 import static com.google.uwb.support.fira.FiraParams.PARTICIPATION_AS_DEFINED_DEVICE_ROLE;
59 import static com.google.uwb.support.fira.FiraParams.PROTOCOL_NAME;
60 import static com.google.uwb.support.fira.FiraParams.RangeDataNtfConfigCapabilityFlag.HAS_RANGE_DATA_NTF_CONFIG_DISABLE;
61 import static com.google.uwb.support.fira.FiraParams.RangeDataNtfConfigCapabilityFlag.HAS_RANGE_DATA_NTF_CONFIG_ENABLE;
62 import static com.google.uwb.support.fira.FiraParams.SESSION_TYPE_RANGING;
63 import static com.google.uwb.support.fira.FiraParams.STATUS_CODE_OK;
64 import static com.google.uwb.support.radar.RadarParams.RADAR_DATA_TYPE_RADAR_SWEEP_SAMPLES;
65 
66 import static org.junit.Assert.assertNotNull;
67 import static org.junit.Assert.assertNull;
68 import static org.junit.Assert.assertThrows;
69 import static org.mockito.ArgumentMatchers.any;
70 import static org.mockito.ArgumentMatchers.anyByte;
71 import static org.mockito.ArgumentMatchers.anyInt;
72 import static org.mockito.ArgumentMatchers.anyLong;
73 import static org.mockito.ArgumentMatchers.anyString;
74 import static org.mockito.ArgumentMatchers.eq;
75 import static org.mockito.ArgumentMatchers.isA;
76 import static org.mockito.Mockito.atLeast;
77 import static org.mockito.Mockito.clearInvocations;
78 import static org.mockito.Mockito.doAnswer;
79 import static org.mockito.Mockito.doReturn;
80 import static org.mockito.Mockito.doThrow;
81 import static org.mockito.Mockito.mock;
82 import static org.mockito.Mockito.never;
83 import static org.mockito.Mockito.spy;
84 import static org.mockito.Mockito.times;
85 import static org.mockito.Mockito.verify;
86 import static org.mockito.Mockito.verifyNoMoreInteractions;
87 import static org.mockito.Mockito.verifyZeroInteractions;
88 import static org.mockito.Mockito.when;
89 
90 import android.annotation.NonNull;
91 import android.annotation.Nullable;
92 import android.app.ActivityManager;
93 import android.app.ActivityManager.OnUidImportanceListener;
94 import android.app.AlarmManager;
95 import android.content.AttributionSource;
96 import android.os.IBinder;
97 import android.os.PersistableBundle;
98 import android.os.Process;
99 import android.os.RemoteException;
100 import android.os.test.TestLooper;
101 import android.permission.flags.Flags;
102 import android.util.Pair;
103 import android.uwb.IUwbAdapter;
104 import android.uwb.IUwbRangingCallbacks;
105 import android.uwb.RangingChangeReason;
106 import android.uwb.SessionHandle;
107 import android.uwb.StateChangeReason;
108 import android.uwb.UwbAddress;
109 import android.uwb.UwbOemExtensionCallbackListener;
110 
111 import com.android.modules.utils.build.SdkLevel;
112 import com.android.server.uwb.UwbSessionManager.UwbSession;
113 import com.android.server.uwb.UwbSessionManager.WaitObj;
114 import com.android.server.uwb.advertisement.UwbAdvertiseManager;
115 import com.android.server.uwb.data.DtTagUpdateRangingRoundsStatus;
116 import com.android.server.uwb.data.UwbDeviceInfoResponse;
117 import com.android.server.uwb.data.UwbMulticastListUpdateStatus;
118 import com.android.server.uwb.data.UwbRadarData;
119 import com.android.server.uwb.data.UwbRangingData;
120 import com.android.server.uwb.data.UwbUciConstants;
121 import com.android.server.uwb.jni.NativeUwbManager;
122 import com.android.server.uwb.multchip.UwbMultichipData;
123 import com.android.server.uwb.params.TlvUtil;
124 
125 import com.google.uwb.support.aliro.AliroOpenRangingParams;
126 import com.google.uwb.support.aliro.AliroParams;
127 import com.google.uwb.support.aliro.AliroPulseShapeCombo;
128 import com.google.uwb.support.aliro.AliroRangingStartedParams;
129 import com.google.uwb.support.aliro.AliroSpecificationParams;
130 import com.google.uwb.support.aliro.AliroStartRangingParams;
131 import com.google.uwb.support.base.Params;
132 import com.google.uwb.support.base.ProtocolVersion;
133 import com.google.uwb.support.ccc.CccOpenRangingParams;
134 import com.google.uwb.support.ccc.CccParams;
135 import com.google.uwb.support.ccc.CccPulseShapeCombo;
136 import com.google.uwb.support.ccc.CccRangingStartedParams;
137 import com.google.uwb.support.ccc.CccSpecificationParams;
138 import com.google.uwb.support.ccc.CccStartRangingParams;
139 import com.google.uwb.support.dltdoa.DlTDoARangingRoundsUpdate;
140 import com.google.uwb.support.fira.FiraDataTransferPhaseConfig;
141 import com.google.uwb.support.fira.FiraHybridSessionControleeConfig;
142 import com.google.uwb.support.fira.FiraHybridSessionControllerConfig;
143 import com.google.uwb.support.fira.FiraOpenSessionParams;
144 import com.google.uwb.support.fira.FiraParams;
145 import com.google.uwb.support.fira.FiraProtocolVersion;
146 import com.google.uwb.support.fira.FiraRangingReconfigureParams;
147 import com.google.uwb.support.fira.FiraSpecificationParams;
148 import com.google.uwb.support.generic.GenericSpecificationParams;
149 import com.google.uwb.support.radar.RadarOpenSessionParams;
150 import com.google.uwb.support.radar.RadarParams;
151 
152 import org.junit.After;
153 import org.junit.Before;
154 import org.junit.Test;
155 import org.mockito.ArgumentCaptor;
156 import org.mockito.Captor;
157 import org.mockito.Mock;
158 import org.mockito.MockitoAnnotations;
159 
160 import java.nio.ByteBuffer;
161 import java.nio.ByteOrder;
162 import java.util.ArrayList;
163 import java.util.Arrays;
164 import java.util.Collections;
165 import java.util.EnumSet;
166 import java.util.List;
167 import java.util.Optional;
168 import java.util.Set;
169 import java.util.concurrent.ConcurrentHashMap;
170 import java.util.concurrent.ExecutionException;
171 import java.util.concurrent.ExecutorService;
172 import java.util.concurrent.FutureTask;
173 import java.util.concurrent.TimeoutException;
174 
175 public class UwbSessionManagerTest {
176     private static final String TEST_CHIP_ID = "testChipId";
177     private static final long MAX_FIRA_SESSION_NUM = 5;
178     private static final long MAX_ALIRO_SESSION_NUM = 1;
179     private static final long MAX_CCC_SESSION_NUM = 1;
180     private static final int UID = 343453;
181     private static final String PACKAGE_NAME = "com.uwb.test";
182     private static final int UID_2 = 67;
183     private static final String PACKAGE_NAME_2 = "com.android.uwb.2";
184     private static final AttributionSource ATTRIBUTION_SOURCE =
185             new AttributionSource.Builder(UID).setPackageName(PACKAGE_NAME).build();
186     private static final AttributionSource ATTRIBUTION_SOURCE_2 =
187             new AttributionSource.Builder(UID_2).setPackageName(PACKAGE_NAME_2).build();
188     private static final SessionHandle SESSION_HANDLE =
189             new SessionHandle(TEST_SESSION_ID, ATTRIBUTION_SOURCE, 1);
190     private static final SessionHandle SESSION_HANDLE_2 =
191             new SessionHandle(TEST_SESSION_ID_2, ATTRIBUTION_SOURCE_2, 2);
192     private static final UwbAddress UWB_DEST_ADDRESS =
193             UwbAddress.fromBytes(new byte[] {(byte) 0x03, (byte) 0x04 });
194     private static final UwbAddress UWB_DEST_ADDRESS_2 =
195             UwbAddress.fromBytes(new byte[] {(byte) 0x05, (byte) 0x06 });
196     private static final UwbAddress UWB_DEST_ADDRESS_3 =
197             UwbAddress.fromBytes(new byte[] {(byte) 0x07, (byte) 0x08 });
198     private static final int TEST_RANGING_INTERVAL_MS = 200;
199     private static final short DATA_SEQUENCE_NUM = 0;
200     private static final short DATA_SEQUENCE_NUM_1 = 2;
201     private static final int DATA_TRANSMISSION_COUNT = 1;
202     private static final int DATA_TRANSMISSION_COUNT_3 = 3;
203     private static final int UWB_HUS_CONTROLLER_PHASE_LIST_SHORT_MAC_ADDRESS_SIZE = 11;
204     private static final int UWB_HUS_CONTROLLER_PHASE_LIST_EXTENDED_MAC_ADDRESS_SIZE = 17;
205     private static final int UWB_HUS_CONTROLEE_PHASE_LIST_SIZE = 5;
206     private static final FiraProtocolVersion FIRA_VERSION_1_0 = new FiraProtocolVersion(1, 0);
207     private static final FiraProtocolVersion FIRA_VERSION_1_1 = new FiraProtocolVersion(1, 1);
208     private static final FiraProtocolVersion FIRA_VERSION_2_0 = new FiraProtocolVersion(2, 0);
209     private static final FiraSpecificationParams FIRA_SPECIFICATION_PARAMS =
210             new FiraSpecificationParams.Builder()
211                     .setMinPhyVersionSupported(FIRA_VERSION_1_0)
212                     .setMaxPhyVersionSupported(FIRA_VERSION_1_1)
213                     .setSupportedChannels(List.of(9))
214                     .setRangeDataNtfConfigCapabilities(
215                             EnumSet.of(
216                                         HAS_RANGE_DATA_NTF_CONFIG_DISABLE,
217                                         HAS_RANGE_DATA_NTF_CONFIG_ENABLE))
218                     .build();
219 
220     private static final UwbDeviceInfoResponse UWB_DEVICE_INFO_RESPONSE_1_1 =
221             new UwbDeviceInfoResponse(
222                     UwbUciConstants.STATUS_CODE_OK,
223                     /* UciVersion 1.1 = */ 0x1001,
224                     /* MacVersion 1.1 = */ 0x1001,
225                     /* PhyVersion 1.1 = */ 0x1001,
226                     /* UciTestVersion 1.1 = */ 0x1001,
227                     /* vendor_spec_info = */ new byte[]{0x0a, 0x0b, 0x0c, 0x0d});
228     private static final UwbDeviceInfoResponse UWB_DEVICE_INFO_RESPONSE_2_0 =
229             new UwbDeviceInfoResponse(
230                     UwbUciConstants.STATUS_CODE_OK,
231                     /* UciVersion 2.0 = */ 0x0002,
232                     /* MacVersion 2.0 = */ 0x0002,
233                     /* PhyVersion 2.0 = */ 0x0002,
234                     /* UciTestVersion 2.0 = */ 0x0002,
235                     /* vendor_spec_info = */ new byte[]{0x0a, 0x0b, 0x0c, 0x0d});
236     private static final AliroOpenRangingParams ALIRO_OPEN_RANGING_PARAMS_DEFAULT =
237             new AliroOpenRangingParams.Builder()
238                     .setProtocolVersion(AliroParams.PROTOCOL_VERSION_1_0)
239                     .setUwbConfig(AliroParams.UWB_CONFIG_0)
240                     .setPulseShapeCombo(
241                             new AliroPulseShapeCombo(
242                                     AliroParams.PULSE_SHAPE_SYMMETRICAL_ROOT_RAISED_COSINE,
243                                     AliroParams.PULSE_SHAPE_SYMMETRICAL_ROOT_RAISED_COSINE))
244                     .setSessionId(1)
245                     .setRanMultiplier(4)
246                     .setChannel(AliroParams.UWB_CHANNEL_9)
247                     .setNumChapsPerSlot(AliroParams.CHAPS_PER_SLOT_3)
248                     .setNumResponderNodes(1)
249                     .setNumSlotsPerRound(AliroParams.SLOTS_PER_ROUND_6)
250                     .setSyncCodeIndex(1)
251                     .setHoppingConfigMode(AliroParams.HOPPING_CONFIG_MODE_NONE)
252                     .setHoppingSequence(AliroParams.HOPPING_SEQUENCE_DEFAULT)
253                     .build();
254     private static final CccOpenRangingParams CCC_OPEN_RANGING_PARAMS_DEFAULT =
255             new CccOpenRangingParams.Builder()
256                 .setProtocolVersion(CccParams.PROTOCOL_VERSION_1_0)
257                 .setUwbConfig(CccParams.UWB_CONFIG_0)
258                 .setPulseShapeCombo(
259                         new CccPulseShapeCombo(
260                                 CccParams.PULSE_SHAPE_SYMMETRICAL_ROOT_RAISED_COSINE,
261                                 CccParams.PULSE_SHAPE_SYMMETRICAL_ROOT_RAISED_COSINE))
262                 .setSessionId(1)
263                 .setRanMultiplier(4)
264                 .setChannel(CccParams.UWB_CHANNEL_9)
265                 .setNumChapsPerSlot(CccParams.CHAPS_PER_SLOT_3)
266                 .setNumResponderNodes(1)
267                 .setNumSlotsPerRound(CccParams.SLOTS_PER_ROUND_6)
268                 .setSyncCodeIndex(1)
269                 .setHoppingConfigMode(CccParams.HOPPING_CONFIG_MODE_NONE)
270                 .setHoppingSequence(CccParams.HOPPING_SEQUENCE_DEFAULT)
271                 .build();
272 
273     private FiraHybridSessionControllerConfig mHybridControllerParams =
274             new FiraHybridSessionControllerConfig.Builder()
275                 .setNumberOfPhases(2)
276                 .setUpdateTime(new byte[8])
277                 .setMacAddressMode((byte) 0)
278                 .addPhaseList(
279                         new FiraHybridSessionControllerConfig.FiraHybridSessionPhaseList(
280                                 SESSION_HANDLE.getId(), (short) 0x01, (short) 0x34,
281                                 (byte) PARTICIPATION_AS_DEFINED_DEVICE_ROLE, UWB_DEST_ADDRESS))
282                 .addPhaseList(
283                         new FiraHybridSessionControllerConfig.FiraHybridSessionPhaseList(
284                                 SESSION_HANDLE_2.getId(), (short) 0x37, (short) 0x64,
285                                 (byte) PARTICIPATION_AS_DEFINED_DEVICE_ROLE, UWB_DEST_ADDRESS_2))
286                 .build();
287     private FiraHybridSessionControleeConfig mHybridControleeParams =
288             new FiraHybridSessionControleeConfig.Builder()
289                 .setNumberOfPhases(2)
290                 .addPhaseList(
291                         new FiraHybridSessionControleeConfig.FiraHybridSessionPhaseList(
292                                 SESSION_HANDLE.getId(),
293                                 (byte) PARTICIPATION_AS_DEFINED_DEVICE_ROLE))
294                 .addPhaseList(
295                         new FiraHybridSessionControleeConfig.FiraHybridSessionPhaseList(
296                                 SESSION_HANDLE_2.getId(),
297                                 (byte) PARTICIPATION_AS_DEFINED_DEVICE_ROLE))
298                 .build();
299 
300     private static final long UWBS_TIMESTAMP = 2000000L;
301     private static final int HANDLE_ID = 12;
302     private static final int MAX_RX_DATA_PACKETS_TO_STORE = 10;
303     private static final int PID = Process.myPid();
304     private static final int REFERENCE_SESSION_HANDLE = 10;
305     private static final int SESSION_TOKEN = 1;
306 
307     @Mock
308     private UwbConfigurationManager mUwbConfigurationManager;
309     @Mock
310     private NativeUwbManager mNativeUwbManager;
311     @Mock
312     private UwbMetrics mUwbMetrics;
313     @Mock
314     private UwbAdvertiseManager mUwbAdvertiseManager;
315     @Mock
316     private UwbSessionNotificationManager mUwbSessionNotificationManager;
317     @Mock
318     private UwbInjector mUwbInjector;
319     @Mock
320     private ExecutorService mExecutorService;
321     @Mock
322     private AlarmManager mAlarmManager;
323     @Mock
324     private ActivityManager mActivityManager;
325     @Mock
326     private UwbServiceCore mUwbServiceCore;
327     @Mock
328     private DeviceConfigFacade mDeviceConfigFacade;
329     @Mock
330     private AliroSpecificationParams mAliroSpecificationParams;
331     @Mock
332     private CccSpecificationParams mCccSpecificationParams;
333     @Mock
334     private UwbMultichipData mUwbMultichipData;
335     private TestLooper mTestLooper = new TestLooper();
336     private UwbSessionManager mUwbSessionManager;
337     @Captor
338     private ArgumentCaptor<OnUidImportanceListener> mOnUidImportanceListenerArgumentCaptor;
339     private GenericSpecificationParams.Builder mSpecificationParamsBuilder;
340 
341     @Before
setup()342     public void setup() throws ExecutionException, InterruptedException, TimeoutException {
343         MockitoAnnotations.initMocks(this);
344         when(mUwbInjector.isSystemApp(UID, PACKAGE_NAME)).thenReturn(true);
345         when(mUwbInjector.isForegroundAppOrService(UID, PACKAGE_NAME)).thenReturn(true);
346         when(mUwbInjector.getUwbServiceCore()).thenReturn(mUwbServiceCore);
347         when(mUwbInjector.getDeviceConfigFacade()).thenReturn(mDeviceConfigFacade);
348         when(mUwbInjector.getMultichipData()).thenReturn(mUwbMultichipData);
349         doAnswer(invocation -> {
350             FutureTask t = invocation.getArgument(0);
351             t.run();
352             return t.get();
353         }).when(mUwbInjector).runTaskOnSingleThreadExecutor(any(FutureTask.class), anyInt());
354         mSpecificationParamsBuilder = new GenericSpecificationParams.Builder()
355                 .setAliroSpecificationParams(mAliroSpecificationParams)
356                 .setCccSpecificationParams(mCccSpecificationParams)
357                 .setFiraSpecificationParams(FIRA_SPECIFICATION_PARAMS);
358         when(mUwbServiceCore.getCachedSpecificationParams(any())).thenReturn(
359                 mSpecificationParamsBuilder.build());
360         when(mAliroSpecificationParams.getMaxRangingSessionNumber()).thenReturn(
361                 (int) MAX_ALIRO_SESSION_NUM);
362         when(mCccSpecificationParams.getMaxRangingSessionNumber()).thenReturn(
363                 (int) MAX_CCC_SESSION_NUM);
364         when(mUwbMultichipData.getDefaultChipId()).thenReturn("default");
365         when(mDeviceConfigFacade.isBackgroundRangingEnabled()).thenReturn(false);
366         when(mDeviceConfigFacade.isRangingErrorStreakTimerEnabled()).thenReturn(true);
367 
368         // TODO: Don't use spy.
369         mUwbSessionManager = spy(new UwbSessionManager(
370                 mUwbConfigurationManager,
371                 mNativeUwbManager,
372                 mUwbMetrics,
373                 mUwbAdvertiseManager,
374                 mUwbSessionNotificationManager,
375                 mUwbInjector,
376                 mAlarmManager,
377                 mActivityManager,
378                 mTestLooper.getLooper()));
379 
380         verify(mActivityManager).addOnUidImportanceListener(
381                 mOnUidImportanceListenerArgumentCaptor.capture(), anyInt());
382     }
383 
384     /**
385      * Called after each test
386      */
387     @After
cleanup()388     public void cleanup() { }
389 
390     @Test
onDataReceived_extendedMacAddressFormat_owrAoA()391     public void onDataReceived_extendedMacAddressFormat_owrAoA() {
392         UwbSession mockUwbSession = mock(UwbSession.class);
393         when(mockUwbSession.getWaitObj()).thenReturn(mock(WaitObj.class));
394         when(mockUwbSession.getRangingRoundUsage()).thenReturn(ROUND_USAGE_OWR_AOA_MEASUREMENT);
395         doReturn(mockUwbSession)
396                 .when(mUwbSessionManager).getUwbSession(eq(TEST_SESSION_ID));
397 
398         mUwbSessionManager.onDataReceived(TEST_SESSION_ID, UwbUciConstants.STATUS_CODE_OK,
399                 DATA_SEQUENCE_NUM, PEER_EXTENDED_MAC_ADDRESS, DATA_PAYLOAD);
400         verify(mockUwbSession).addReceivedDataInfo(isA(UwbSessionManager.ReceivedDataInfo.class));
401         verify(mUwbMetrics).logDataRx(eq(mockUwbSession), eq(UwbUciConstants.STATUS_CODE_OK));
402     }
403 
404     @Test
onDataReceived_unsupportedMacAddressLength_owrAoa()405     public void onDataReceived_unsupportedMacAddressLength_owrAoa() {
406         UwbSession mockUwbSession = mock(UwbSession.class);
407         when(mockUwbSession.getWaitObj()).thenReturn(mock(WaitObj.class));
408         when(mockUwbSession.getRangingRoundUsage()).thenReturn(ROUND_USAGE_OWR_AOA_MEASUREMENT);
409         doReturn(mockUwbSession)
410                 .when(mUwbSessionManager).getUwbSession(eq(TEST_SESSION_ID));
411 
412         mUwbSessionManager.onDataReceived(TEST_SESSION_ID, UwbUciConstants.STATUS_CODE_OK,
413                 DATA_SEQUENCE_NUM, PEER_BAD_MAC_ADDRESS, DATA_PAYLOAD);
414         verify(mockUwbSession, never()).addReceivedDataInfo(
415                 isA(UwbSessionManager.ReceivedDataInfo.class));
416         verify(mUwbMetrics, never()).logDataRx(eq(mockUwbSession),
417                 eq(UwbUciConstants.STATUS_CODE_OK));
418     }
419 
420     @Test
onDataReceived_shortMacAddressFormat_owrAoa()421     public void onDataReceived_shortMacAddressFormat_owrAoa() {
422         UwbSession mockUwbSession = mock(UwbSession.class);
423         when(mockUwbSession.getWaitObj()).thenReturn(mock(WaitObj.class));
424         when(mockUwbSession.getRangingRoundUsage()).thenReturn(ROUND_USAGE_OWR_AOA_MEASUREMENT);
425         doReturn(mockUwbSession)
426                 .when(mUwbSessionManager).getUwbSession(eq(TEST_SESSION_ID));
427 
428         mUwbSessionManager.onDataReceived(TEST_SESSION_ID, UwbUciConstants.STATUS_CODE_OK,
429                 DATA_SEQUENCE_NUM, PEER_EXTENDED_SHORT_MAC_ADDRESS, DATA_PAYLOAD);
430         verify(mockUwbSession).addReceivedDataInfo(isA(UwbSessionManager.ReceivedDataInfo.class));
431         verify(mUwbMetrics).logDataRx(eq(mockUwbSession), eq(UwbUciConstants.STATUS_CODE_OK));
432     }
433 
434     @Test
onDataReceived_shortMacAddressFormat_dsTwr()435     public void onDataReceived_shortMacAddressFormat_dsTwr() {
436         UwbSession mockUwbSession = mock(UwbSession.class);
437         when(mockUwbSession.getWaitObj()).thenReturn(mock(WaitObj.class));
438         when(mockUwbSession.getRangingRoundUsage()).thenReturn(
439                 ROUND_USAGE_DS_TWR_NON_DEFERRED_MODE);
440         doReturn(mockUwbSession)
441                 .when(mUwbSessionManager).getUwbSession(eq(TEST_SESSION_ID));
442 
443         mUwbSessionManager.onDataReceived(TEST_SESSION_ID, UwbUciConstants.STATUS_CODE_OK,
444                 DATA_SEQUENCE_NUM, PEER_EXTENDED_SHORT_MAC_ADDRESS, DATA_PAYLOAD);
445 
446         verify(mUwbSessionNotificationManager).onDataReceived(
447                 isA(UwbSession.class), eq(PEER_EXTENDED_SHORT_UWB_ADDRESS),
448                 isA(PersistableBundle.class), eq(DATA_PAYLOAD));
449         verify(mUwbMetrics).logDataRx(eq(mockUwbSession), eq(UwbUciConstants.STATUS_CODE_OK));
450         verify(mockUwbSession, never()).addReceivedDataInfo(
451                 isA(UwbSessionManager.ReceivedDataInfo.class));
452     }
453 
454     @Test
onRangeDataNotificationReceivedWithValidUwbSession_twoWay()455     public void onRangeDataNotificationReceivedWithValidUwbSession_twoWay() {
456         UwbRangingData uwbRangingData = UwbTestUtils.generateRangingData(
457                 RANGING_MEASUREMENT_TYPE_TWO_WAY, MAC_ADDRESSING_MODE_EXTENDED,
458                 UwbUciConstants.STATUS_CODE_OK);
459         UwbSession mockUwbSession = mock(UwbSession.class);
460         when(mockUwbSession.getWaitObj()).thenReturn(mock(WaitObj.class));
461         doReturn(mockUwbSession)
462                 .when(mUwbSessionManager).getUwbSession(eq(TEST_SESSION_ID));
463 
464         mUwbSessionManager.onRangeDataNotificationReceived(uwbRangingData);
465 
466         verify(mUwbSessionNotificationManager)
467                 .onRangingResult(eq(mockUwbSession), eq(uwbRangingData));
468     }
469 
470     @Test
onRangeDataNotificationReceivedWithInvalidSession_twoWay()471     public void onRangeDataNotificationReceivedWithInvalidSession_twoWay() {
472         UwbRangingData uwbRangingData = UwbTestUtils.generateRangingData(
473                 RANGING_MEASUREMENT_TYPE_TWO_WAY, MAC_ADDRESSING_MODE_EXTENDED,
474                 UwbUciConstants.STATUS_CODE_OK);
475         doReturn(null)
476                 .when(mUwbSessionManager).getUwbSession(eq(TEST_SESSION_ID));
477 
478         mUwbSessionManager.onRangeDataNotificationReceived(uwbRangingData);
479 
480         verify(mUwbSessionNotificationManager, never())
481                 .onRangingResult(any(), eq(uwbRangingData));
482     }
483 
484     // Test scenario for receiving Application payload data followed by a RANGE_DATA_NTF with an
485     // OWR Aoa Measurement (such that the ExtendedMacAddress format is used for the remote device).
486     @Test
onRangeDataNotificationReceived_owrAoa_success_extendedMacAddress()487     public void onRangeDataNotificationReceived_owrAoa_success_extendedMacAddress()
488             throws RemoteException {
489         UwbSession mockUwbSession = mock(UwbSession.class);
490         when(mockUwbSession.getWaitObj()).thenReturn(mock(WaitObj.class));
491         when(mockUwbSession.getRangingRoundUsage()).thenReturn(ROUND_USAGE_OWR_AOA_MEASUREMENT);
492         doReturn(mockUwbSession)
493                 .when(mUwbSessionManager).getUwbSession(eq(TEST_SESSION_ID));
494         UwbOemExtensionCallbackListener mUwbOemExtensionCallbackListener =
495                 mock(UwbOemExtensionCallbackListener.class);
496         when(mUwbServiceCore.isOemExtensionCbRegistered()).thenReturn(true);
497         when(mUwbServiceCore.getOemExtensionCallback())
498                 .thenReturn(mUwbOemExtensionCallbackListener);
499         when(mUwbOemExtensionCallbackListener.onCheckPointedTarget(any())).thenReturn(true);
500 
501         // First call onDataReceived() to get the application payload data.
502         mUwbSessionManager.onDataReceived(TEST_SESSION_ID, UwbUciConstants.STATUS_CODE_OK,
503                 DATA_SEQUENCE_NUM, PEER_EXTENDED_MAC_ADDRESS, DATA_PAYLOAD);
504         verify(mockUwbSession).addReceivedDataInfo(isA(UwbSessionManager.ReceivedDataInfo.class));
505         verify(mUwbMetrics).logDataRx(eq(mockUwbSession), eq(UwbUciConstants.STATUS_CODE_OK));
506 
507         // Next call onRangeDataNotificationReceived() to process the RANGE_DATA_NTF.
508         UwbRangingData uwbRangingData = UwbTestUtils.generateRangingData(
509                 RANGING_MEASUREMENT_TYPE_OWR_AOA, MAC_ADDRESSING_MODE_EXTENDED,
510                 UwbUciConstants.STATUS_CODE_OK);
511         Params firaParams = setupFiraParams(
512                 RANGING_DEVICE_ROLE_OBSERVER, Optional.of(ROUND_USAGE_OWR_AOA_MEASUREMENT));
513         when(mockUwbSession.getParams()).thenReturn(firaParams);
514         when(mUwbAdvertiseManager.isPointedTarget(PEER_EXTENDED_MAC_ADDRESS)).thenReturn(true);
515         when(mockUwbSession.getAllReceivedDataInfo(PEER_EXTENDED_MAC_ADDRESS_LONG))
516                 .thenReturn(List.of(buildReceivedDataInfo(PEER_EXTENDED_MAC_ADDRESS_LONG)));
517         mUwbSessionManager.onRangeDataNotificationReceived(uwbRangingData);
518 
519         verify(mUwbSessionNotificationManager)
520                 .onRangingResult(eq(mockUwbSession), eq(uwbRangingData));
521         verify(mUwbAdvertiseManager).updateAdvertiseTarget(uwbRangingData.mRangingOwrAoaMeasure);
522         verify(mUwbSessionNotificationManager)
523                 .onDataReceived(eq(mockUwbSession), eq(PEER_EXTENDED_UWB_ADDRESS),
524                         isA(PersistableBundle.class), eq(DATA_PAYLOAD));
525         verify(mUwbAdvertiseManager).removeAdvertiseTarget(PEER_EXTENDED_MAC_ADDRESS_LONG);
526         verify(mUwbMetrics).logDataToUpperLayer(eq(mockUwbSession), eq(1));
527     }
528 
529     // Test scenario for receiving Application payload data followed by a RANGE_DATA_NTF with an
530     // OWR Aoa Measurement (such that the ShortMacAddress format is used for the remote device).
531     @Test
onRangeDataNotificationReceived_owrAoa_success_shortMacAddress()532     public void onRangeDataNotificationReceived_owrAoa_success_shortMacAddress()
533             throws RemoteException {
534         UwbSession mockUwbSession = mock(UwbSession.class);
535         when(mockUwbSession.getWaitObj()).thenReturn(mock(WaitObj.class));
536         when(mockUwbSession.getRangingRoundUsage()).thenReturn(ROUND_USAGE_OWR_AOA_MEASUREMENT);
537         doReturn(mockUwbSession)
538                 .when(mUwbSessionManager).getUwbSession(eq(TEST_SESSION_ID));
539         UwbOemExtensionCallbackListener mUwbOemExtensionCallbackListener =
540                 mock(UwbOemExtensionCallbackListener.class);
541         when(mUwbServiceCore.isOemExtensionCbRegistered()).thenReturn(true);
542         when(mUwbServiceCore.getOemExtensionCallback())
543                 .thenReturn(mUwbOemExtensionCallbackListener);
544         when(mUwbOemExtensionCallbackListener.onCheckPointedTarget(any())).thenReturn(true);
545 
546         // First call onDataReceived() to get the application payload data. This should always have
547         // the MacAddress (in 8 Bytes), even for a Short MacAddress (MSB are zeroed out).
548         mUwbSessionManager.onDataReceived(TEST_SESSION_ID, UwbUciConstants.STATUS_CODE_OK,
549                 DATA_SEQUENCE_NUM, PEER_EXTENDED_SHORT_MAC_ADDRESS, DATA_PAYLOAD);
550         verify(mockUwbSession).addReceivedDataInfo(isA(UwbSessionManager.ReceivedDataInfo.class));
551         verify(mUwbMetrics).logDataRx(eq(mockUwbSession), eq(UwbUciConstants.STATUS_CODE_OK));
552 
553         // Next call onRangeDataNotificationReceived() to process the RANGE_DATA_NTF.
554         UwbRangingData uwbRangingData = UwbTestUtils.generateRangingData(
555                 RANGING_MEASUREMENT_TYPE_OWR_AOA, MAC_ADDRESSING_MODE_SHORT,
556                 UwbUciConstants.STATUS_CODE_OK);
557         Params firaParams = setupFiraParams(
558                 RANGING_DEVICE_ROLE_OBSERVER, Optional.of(ROUND_USAGE_OWR_AOA_MEASUREMENT));
559         when(mockUwbSession.getParams()).thenReturn(firaParams);
560         when(mUwbAdvertiseManager.isPointedTarget(PEER_SHORT_MAC_ADDRESS)).thenReturn(true);
561         when(mockUwbSession.getAllReceivedDataInfo(PEER_EXTENDED_SHORT_MAC_ADDRESS_LONG))
562                 .thenReturn(List.of(buildReceivedDataInfo(PEER_EXTENDED_SHORT_MAC_ADDRESS_LONG)));
563         mUwbSessionManager.onRangeDataNotificationReceived(uwbRangingData);
564 
565         verify(mUwbSessionNotificationManager)
566                 .onRangingResult(eq(mockUwbSession), eq(uwbRangingData));
567         verify(mUwbAdvertiseManager).updateAdvertiseTarget(uwbRangingData.mRangingOwrAoaMeasure);
568         verify(mUwbSessionNotificationManager)
569                 .onDataReceived(eq(mockUwbSession), eq(PEER_SHORT_UWB_ADDRESS),
570                         isA(PersistableBundle.class), eq(DATA_PAYLOAD));
571         verify(mUwbAdvertiseManager).removeAdvertiseTarget(PEER_SHORT_MAC_ADDRESS_LONG);
572         verify(mUwbMetrics).logDataToUpperLayer(eq(mockUwbSession), eq(1));
573     }
574 
575     // Test scenario for receiving Application payload data followed by a RANGE_DATA_NTF with an
576     // OWR Aoa Measurement, from Multiple advertiser devices in a UWB session.
577     @Test
onRangeDataNotificationReceived_owrAoa_success_multipleAdvertisers()578     public void onRangeDataNotificationReceived_owrAoa_success_multipleAdvertisers() {
579         UwbSession mockUwbSession = mock(UwbSession.class);
580         when(mockUwbSession.getWaitObj()).thenReturn(mock(WaitObj.class));
581         when(mockUwbSession.getRangingRoundUsage()).thenReturn(ROUND_USAGE_OWR_AOA_MEASUREMENT);
582         doReturn(mockUwbSession)
583                 .when(mUwbSessionManager).getUwbSession(eq(TEST_SESSION_ID));
584 
585         // First call onDataReceived() to get the application payload data.
586         mUwbSessionManager.onDataReceived(TEST_SESSION_ID, UwbUciConstants.STATUS_CODE_OK,
587                 DATA_SEQUENCE_NUM, PEER_EXTENDED_MAC_ADDRESS, DATA_PAYLOAD);
588         mUwbSessionManager.onDataReceived(TEST_SESSION_ID, UwbUciConstants.STATUS_CODE_OK,
589                 DATA_SEQUENCE_NUM_1, PEER_EXTENDED_MAC_ADDRESS, DATA_PAYLOAD);
590 
591         mUwbSessionManager.onDataReceived(TEST_SESSION_ID, UwbUciConstants.STATUS_CODE_OK,
592                 DATA_SEQUENCE_NUM, PEER_EXTENDED_MAC_ADDRESS_2, DATA_PAYLOAD);
593         mUwbSessionManager.onDataReceived(TEST_SESSION_ID, UwbUciConstants.STATUS_CODE_OK,
594                 DATA_SEQUENCE_NUM_1, PEER_EXTENDED_MAC_ADDRESS_2, DATA_PAYLOAD);
595 
596         verify(mockUwbSession, times(4)).addReceivedDataInfo(
597                 isA(UwbSessionManager.ReceivedDataInfo.class));
598         verify(mUwbMetrics, times(4)).logDataRx(
599                 eq(mockUwbSession), eq(UwbUciConstants.STATUS_CODE_OK));
600 
601         // Next call onRangeDataNotificationReceived() to process the RANGE_DATA_NTF.
602         UwbRangingData uwbRangingData1 = UwbTestUtils.generateRangingData(
603                 RANGING_MEASUREMENT_TYPE_OWR_AOA, MAC_ADDRESSING_MODE_EXTENDED,
604                 PEER_EXTENDED_MAC_ADDRESS, UwbUciConstants.STATUS_CODE_OK);
605         UwbRangingData uwbRangingData2 = UwbTestUtils.generateRangingData(
606                 RANGING_MEASUREMENT_TYPE_OWR_AOA, MAC_ADDRESSING_MODE_EXTENDED,
607                 PEER_EXTENDED_MAC_ADDRESS_2, UwbUciConstants.STATUS_CODE_OK);
608         Params firaParams = setupFiraParams(
609                 RANGING_DEVICE_ROLE_OBSERVER, Optional.of(ROUND_USAGE_OWR_AOA_MEASUREMENT));
610         when(mockUwbSession.getParams()).thenReturn(firaParams);
611         when(mUwbAdvertiseManager.isPointedTarget(PEER_EXTENDED_MAC_ADDRESS)).thenReturn(true);
612         when(mUwbAdvertiseManager.isPointedTarget(PEER_EXTENDED_MAC_ADDRESS_2)).thenReturn(true);
613         when(mockUwbSession.getAllReceivedDataInfo(PEER_EXTENDED_MAC_ADDRESS_LONG))
614                 .thenReturn(List.of(
615                         buildReceivedDataInfo(PEER_EXTENDED_MAC_ADDRESS_LONG, DATA_SEQUENCE_NUM),
616                         buildReceivedDataInfo(
617                                 PEER_EXTENDED_MAC_ADDRESS_LONG, DATA_SEQUENCE_NUM_1)));
618         when(mockUwbSession.getAllReceivedDataInfo(PEER_EXTENDED_MAC_ADDRESS_2_LONG))
619                 .thenReturn(List.of(
620                         buildReceivedDataInfo(PEER_EXTENDED_MAC_ADDRESS_2_LONG, DATA_SEQUENCE_NUM),
621                         buildReceivedDataInfo(
622                                 PEER_EXTENDED_MAC_ADDRESS_2_LONG, DATA_SEQUENCE_NUM_1)));
623         mUwbSessionManager.onRangeDataNotificationReceived(uwbRangingData1);
624         mUwbSessionManager.onRangeDataNotificationReceived(uwbRangingData2);
625 
626         verify(mUwbSessionNotificationManager)
627                 .onRangingResult(eq(mockUwbSession), eq(uwbRangingData1));
628         verify(mUwbSessionNotificationManager)
629                 .onRangingResult(eq(mockUwbSession), eq(uwbRangingData2));
630         verify(mUwbAdvertiseManager).updateAdvertiseTarget(uwbRangingData1.mRangingOwrAoaMeasure);
631         verify(mUwbAdvertiseManager).updateAdvertiseTarget(uwbRangingData2.mRangingOwrAoaMeasure);
632         verify(mUwbSessionNotificationManager, times(2))
633                 .onDataReceived(eq(mockUwbSession), eq(PEER_EXTENDED_UWB_ADDRESS),
634                         isA(PersistableBundle.class), eq(DATA_PAYLOAD));
635         verify(mUwbSessionNotificationManager, times(2))
636                 .onDataReceived(eq(mockUwbSession), eq(PEER_EXTENDED_UWB_ADDRESS_2),
637                         isA(PersistableBundle.class), eq(DATA_PAYLOAD));
638         verify(mUwbAdvertiseManager).removeAdvertiseTarget(PEER_EXTENDED_MAC_ADDRESS_LONG);
639         verify(mUwbAdvertiseManager).removeAdvertiseTarget(PEER_EXTENDED_MAC_ADDRESS_2_LONG);
640         verify(mUwbMetrics, times(2)).logDataToUpperLayer(eq(mockUwbSession), eq(2));
641     }
642 
643     @Test
onRangeDataNotificationReceived_owrAoa_CheckPointedTarget_Failed()644     public void onRangeDataNotificationReceived_owrAoa_CheckPointedTarget_Failed()
645             throws RemoteException {
646         UwbSession mockUwbSession = mock(UwbSession.class);
647         when(mockUwbSession.getWaitObj()).thenReturn(mock(WaitObj.class));
648         when(mockUwbSession.getRangingRoundUsage()).thenReturn(ROUND_USAGE_OWR_AOA_MEASUREMENT);
649         doReturn(mockUwbSession)
650                 .when(mUwbSessionManager).getUwbSession(eq(TEST_SESSION_ID));
651         UwbOemExtensionCallbackListener mUwbOemExtensionCallbackListener =
652                 mock(UwbOemExtensionCallbackListener.class);
653         when(mUwbServiceCore.isOemExtensionCbRegistered()).thenReturn(true);
654         when(mUwbServiceCore.getOemExtensionCallback())
655                 .thenReturn(mUwbOemExtensionCallbackListener);
656         when(mUwbOemExtensionCallbackListener.onCheckPointedTarget(any())).thenReturn(false);
657 
658         // First call onDataReceived() to get the application payload data. This should always have
659         // the MacAddress (in 8 Bytes), even for a Short MacAddress (MSB are zeroed out).
660         mUwbSessionManager.onDataReceived(TEST_SESSION_ID, UwbUciConstants.STATUS_CODE_OK,
661                 DATA_SEQUENCE_NUM, PEER_EXTENDED_SHORT_MAC_ADDRESS, DATA_PAYLOAD);
662 
663         // Next call onRangeDataNotificationReceived() to process the RANGE_DATA_NTF.
664         UwbRangingData uwbRangingData = UwbTestUtils.generateRangingData(
665                 RANGING_MEASUREMENT_TYPE_OWR_AOA, MAC_ADDRESSING_MODE_SHORT,
666                 UwbUciConstants.STATUS_CODE_OK);
667         Params firaParams = setupFiraParams(
668                 RANGING_DEVICE_ROLE_OBSERVER, Optional.of(ROUND_USAGE_OWR_AOA_MEASUREMENT));
669         when(mockUwbSession.getParams()).thenReturn(firaParams);
670         when(mUwbAdvertiseManager.isPointedTarget(PEER_SHORT_MAC_ADDRESS)).thenReturn(true);
671         mUwbSessionManager.onRangeDataNotificationReceived(uwbRangingData);
672 
673         verify(mUwbSessionNotificationManager)
674                 .onRangingResult(eq(mockUwbSession), eq(uwbRangingData));
675         verify(mUwbAdvertiseManager).updateAdvertiseTarget(uwbRangingData.mRangingOwrAoaMeasure);
676         verify(mUwbSessionNotificationManager, never())
677                 .onDataReceived(eq(mockUwbSession), eq(PEER_SHORT_UWB_ADDRESS),
678                         isA(PersistableBundle.class), eq(DATA_PAYLOAD));
679         verify(mUwbAdvertiseManager, never()).removeAdvertiseTarget(PEER_SHORT_MAC_ADDRESS_LONG);
680     }
681 
682     @Test
onRangeDataNotificationReceived_owrAoa_missingUwbSession()683     public void onRangeDataNotificationReceived_owrAoa_missingUwbSession() {
684         UwbRangingData uwbRangingData = UwbTestUtils.generateRangingData(
685                 RANGING_MEASUREMENT_TYPE_OWR_AOA, MAC_ADDRESSING_MODE_EXTENDED,
686                 UwbUciConstants.STATUS_CODE_OK);
687 
688         // Setup the test scenario such that the UwbSession (from the RANGE_DATA_NTF) doesn't exist.
689         doReturn(null)
690                 .when(mUwbSessionManager).getUwbSession(eq(TEST_SESSION_ID));
691 
692         // First call onDataReceived() to get the application payload data.
693         mUwbSessionManager.onDataReceived(TEST_SESSION_ID, UwbUciConstants.STATUS_CODE_OK,
694                 DATA_SEQUENCE_NUM, PEER_EXTENDED_MAC_ADDRESS, DATA_PAYLOAD);
695 
696         // Next call onRangeDataNotificationReceived() to process the RANGE_DATA_NTF.
697         mUwbSessionManager.onRangeDataNotificationReceived(uwbRangingData);
698 
699         verifyZeroInteractions(mUwbAdvertiseManager, mUwbSessionNotificationManager, mUwbMetrics);
700     }
701 
702     @Test
onRangeDataNotificationReceived_incorrectRangingMeasureType()703     public void onRangeDataNotificationReceived_incorrectRangingMeasureType() {
704         UwbRangingData uwbRangingData = UwbTestUtils.generateRangingData(
705                 RANGING_MEASUREMENT_TYPE_UNDEFINED, MAC_ADDRESSING_MODE_EXTENDED,
706                 UwbUciConstants.STATUS_CODE_OK);
707         UwbSession mockUwbSession = mock(UwbSession.class);
708         when(mockUwbSession.getWaitObj()).thenReturn(mock(WaitObj.class));
709         when(mockUwbSession.getRangingRoundUsage()).thenReturn(ROUND_USAGE_OWR_AOA_MEASUREMENT);
710         doReturn(mockUwbSession)
711                 .when(mUwbSessionManager).getUwbSession(eq(TEST_SESSION_ID));
712 
713         // First call onDataReceived() to get the application payload data.
714         mUwbSessionManager.onDataReceived(TEST_SESSION_ID, UwbUciConstants.STATUS_CODE_OK,
715                 DATA_SEQUENCE_NUM, PEER_EXTENDED_MAC_ADDRESS, DATA_PAYLOAD);
716         verify(mockUwbSession).addReceivedDataInfo(isA(UwbSessionManager.ReceivedDataInfo.class));
717         verify(mUwbMetrics).logDataRx(eq(mockUwbSession), eq(UwbUciConstants.STATUS_CODE_OK));
718 
719         // Next call onRangeDataNotificationReceived() to process the RANGE_DATA_NTF.
720         mUwbSessionManager.onRangeDataNotificationReceived(uwbRangingData);
721 
722         verify(mUwbSessionNotificationManager)
723                 .onRangingResult(eq(mockUwbSession), eq(uwbRangingData));
724         verifyZeroInteractions(mUwbAdvertiseManager);
725     }
726 
727     @Test
onRangeDataNotificationReceived_owrAoa_incorrectRangingRoundUsage()728     public void onRangeDataNotificationReceived_owrAoa_incorrectRangingRoundUsage() {
729         UwbRangingData uwbRangingData = UwbTestUtils.generateRangingData(
730                 RANGING_MEASUREMENT_TYPE_OWR_AOA, MAC_ADDRESSING_MODE_EXTENDED,
731                 UwbUciConstants.STATUS_CODE_OK);
732         UwbSession mockUwbSession = mock(UwbSession.class);
733         when(mockUwbSession.getWaitObj()).thenReturn(mock(WaitObj.class));
734         when(mockUwbSession.getRangingRoundUsage()).thenReturn(ROUND_USAGE_OWR_AOA_MEASUREMENT);
735         doReturn(mockUwbSession)
736                 .when(mUwbSessionManager).getUwbSession(eq(TEST_SESSION_ID));
737 
738         // First call onDataReceived() to get the application payload data.
739         mUwbSessionManager.onDataReceived(TEST_SESSION_ID, UwbUciConstants.STATUS_CODE_OK,
740                 DATA_SEQUENCE_NUM, PEER_EXTENDED_MAC_ADDRESS, DATA_PAYLOAD);
741         verify(mockUwbSession).addReceivedDataInfo(isA(UwbSessionManager.ReceivedDataInfo.class));
742         verify(mUwbMetrics).logDataRx(eq(mockUwbSession), eq(UwbUciConstants.STATUS_CODE_OK));
743 
744         // Next call onRangeDataNotificationReceived() to process the RANGE_DATA_NTF (with an
745         // incorrect RangingRoundUsage value).
746         Params firaParams = setupFiraParams(
747                 RANGING_DEVICE_ROLE_OBSERVER, Optional.of(ROUND_USAGE_DS_TWR_DEFERRED_MODE));
748         when(mockUwbSession.getParams()).thenReturn(firaParams);
749         mUwbSessionManager.onRangeDataNotificationReceived(uwbRangingData);
750 
751         verify(mUwbSessionNotificationManager)
752                 .onRangingResult(eq(mockUwbSession), eq(uwbRangingData));
753         verifyZeroInteractions(mUwbAdvertiseManager);
754     }
755 
756     @Test
onRangeDataNotificationReceived_owrAoa_incorrectDeviceRole()757     public void onRangeDataNotificationReceived_owrAoa_incorrectDeviceRole() {
758         UwbRangingData uwbRangingData = UwbTestUtils.generateRangingData(
759                 RANGING_MEASUREMENT_TYPE_OWR_AOA, MAC_ADDRESSING_MODE_EXTENDED,
760                 UwbUciConstants.STATUS_CODE_OK);
761         UwbSession mockUwbSession = mock(UwbSession.class);
762         when(mockUwbSession.getWaitObj()).thenReturn(mock(WaitObj.class));
763         when(mockUwbSession.getRangingRoundUsage()).thenReturn(ROUND_USAGE_OWR_AOA_MEASUREMENT);
764         doReturn(mockUwbSession)
765                 .when(mUwbSessionManager).getUwbSession(eq(TEST_SESSION_ID));
766 
767         // First call onDataReceived() to get the application payload data.
768         mUwbSessionManager.onDataReceived(TEST_SESSION_ID, UwbUciConstants.STATUS_CODE_OK,
769                 DATA_SEQUENCE_NUM, PEER_EXTENDED_MAC_ADDRESS, DATA_PAYLOAD);
770         verify(mockUwbSession).addReceivedDataInfo(isA(UwbSessionManager.ReceivedDataInfo.class));
771         verify(mUwbMetrics).logDataRx(eq(mockUwbSession), eq(UwbUciConstants.STATUS_CODE_OK));
772 
773         // Next call onRangeDataNotificationReceived() to process the RANGE_DATA_NTF.
774         Params firaParams = setupFiraParams(
775                 RANGING_DEVICE_ROLE_ADVERTISER, Optional.of(ROUND_USAGE_OWR_AOA_MEASUREMENT));
776         when(mockUwbSession.getParams()).thenReturn(firaParams);
777         mUwbSessionManager.onRangeDataNotificationReceived(uwbRangingData);
778 
779         verify(mUwbSessionNotificationManager)
780                 .onRangingResult(eq(mockUwbSession), eq(uwbRangingData));
781         verifyZeroInteractions(mUwbAdvertiseManager);
782     }
783 
784     @Test
onRangeDataNotificationReceived_owrAoa_receivedDataNotCalled()785     public void onRangeDataNotificationReceived_owrAoa_receivedDataNotCalled() {
786         UwbRangingData uwbRangingData = UwbTestUtils.generateRangingData(
787                 RANGING_MEASUREMENT_TYPE_OWR_AOA, MAC_ADDRESSING_MODE_EXTENDED,
788                 UwbUciConstants.STATUS_CODE_OK);
789         UwbSession mockUwbSession = mock(UwbSession.class);
790         when(mockUwbSession.getWaitObj()).thenReturn(mock(WaitObj.class));
791         when(mockUwbSession.getRangingRoundUsage()).thenReturn(ROUND_USAGE_OWR_AOA_MEASUREMENT);
792         doReturn(mockUwbSession)
793                 .when(mUwbSessionManager).getUwbSession(eq(TEST_SESSION_ID));
794 
795         // Skip call to mUwbSessionManager.onDataReceived(). This means there is no application
796         // payload data, and so mUwbSessionNotificationManager.onDataReceived() shouldn't be called.
797         Params firaParams = setupFiraParams(
798                 RANGING_DEVICE_ROLE_OBSERVER, Optional.of(ROUND_USAGE_OWR_AOA_MEASUREMENT));
799         when(mockUwbSession.getParams()).thenReturn(firaParams);
800         when(mUwbAdvertiseManager.isPointedTarget(PEER_EXTENDED_MAC_ADDRESS)).thenReturn(true);
801         when(mockUwbSession.getAllReceivedDataInfo(PEER_EXTENDED_MAC_ADDRESS_LONG))
802                 .thenReturn(List.of());
803         mUwbSessionManager.onRangeDataNotificationReceived(uwbRangingData);
804 
805         verify(mUwbSessionNotificationManager)
806                 .onRangingResult(eq(mockUwbSession), eq(uwbRangingData));
807         verify(mUwbAdvertiseManager).updateAdvertiseTarget(uwbRangingData.mRangingOwrAoaMeasure);
808         verifyZeroInteractions(mUwbSessionNotificationManager);
809         verify(mUwbMetrics, never()).logDataToUpperLayer(eq(mockUwbSession), anyInt());
810     }
811 
812     @Test
onRangeDataNotificationReceived_owrAoa_receivedDataDifferentMacAddress()813     public void onRangeDataNotificationReceived_owrAoa_receivedDataDifferentMacAddress() {
814         UwbRangingData uwbRangingData = UwbTestUtils.generateRangingData(
815                 RANGING_MEASUREMENT_TYPE_OWR_AOA, MAC_ADDRESSING_MODE_EXTENDED,
816                 UwbUciConstants.STATUS_CODE_OK);
817         UwbSession mockUwbSession = mock(UwbSession.class);
818         when(mockUwbSession.getWaitObj()).thenReturn(mock(WaitObj.class));
819         when(mockUwbSession.getRangingRoundUsage()).thenReturn(ROUND_USAGE_OWR_AOA_MEASUREMENT);
820         doReturn(mockUwbSession)
821                 .when(mUwbSessionManager).getUwbSession(eq(TEST_SESSION_ID));
822 
823         // onDataReceived() called for a different MacAddress, which should be equivalent to it
824         // not being called.
825         mUwbSessionManager.onDataReceived(TEST_SESSION_ID, UwbUciConstants.STATUS_CODE_OK,
826                 DATA_SEQUENCE_NUM, PEER_EXTENDED_MAC_ADDRESS_2, DATA_PAYLOAD);
827         verify(mockUwbSession).addReceivedDataInfo(isA(UwbSessionManager.ReceivedDataInfo.class));
828         verify(mUwbMetrics).logDataRx(eq(mockUwbSession), eq(UwbUciConstants.STATUS_CODE_OK));
829 
830         // Next call onRangeDataNotificationReceived() to process the RANGE_DATA_NTF.
831         Params firaParams = setupFiraParams(
832                 RANGING_DEVICE_ROLE_OBSERVER, Optional.of(ROUND_USAGE_OWR_AOA_MEASUREMENT));
833         when(mockUwbSession.getParams()).thenReturn(firaParams);
834         when(mUwbAdvertiseManager.isPointedTarget(PEER_EXTENDED_MAC_ADDRESS)).thenReturn(true);
835         when(mockUwbSession.getAllReceivedDataInfo(PEER_EXTENDED_MAC_ADDRESS_LONG))
836                 .thenReturn(List.of());
837         mUwbSessionManager.onRangeDataNotificationReceived(uwbRangingData);
838 
839         verify(mUwbSessionNotificationManager)
840                 .onRangingResult(eq(mockUwbSession), eq(uwbRangingData));
841         verify(mUwbAdvertiseManager).updateAdvertiseTarget(uwbRangingData.mRangingOwrAoaMeasure);
842         verifyZeroInteractions(mUwbSessionNotificationManager);
843         verify(mUwbMetrics, never()).logDataToUpperLayer(eq(mockUwbSession), anyInt());
844     }
845 
846     @Test
onRangeDataNotificationReceived_owrAoa_receivedDataDifferentUwbSession()847     public void onRangeDataNotificationReceived_owrAoa_receivedDataDifferentUwbSession() {
848         UwbRangingData uwbRangingData = UwbTestUtils.generateRangingData(
849                 RANGING_MEASUREMENT_TYPE_OWR_AOA, MAC_ADDRESSING_MODE_EXTENDED,
850                 UwbUciConstants.STATUS_CODE_OK);
851         UwbSession mockUwbSession = mock(UwbSession.class);
852         when(mockUwbSession.getWaitObj()).thenReturn(mock(WaitObj.class));
853         when(mockUwbSession.getRangingRoundUsage()).thenReturn(ROUND_USAGE_OWR_AOA_MEASUREMENT);
854         doReturn(mockUwbSession)
855                 .when(mUwbSessionManager).getUwbSession(eq(TEST_SESSION_ID));
856         UwbSession mockUwbSession2 = mock(UwbSession.class);
857         when(mockUwbSession2.getWaitObj()).thenReturn(mock(WaitObj.class));
858         when(mockUwbSession2.getRangingRoundUsage()).thenReturn(ROUND_USAGE_OWR_AOA_MEASUREMENT);
859         doReturn(mockUwbSession2)
860                 .when(mUwbSessionManager).getUwbSession(eq(TEST_SESSION_ID_2));
861 
862         // onDataReceived() called for a different UwbSessionID, which should be equivalent to it
863         // not being called.
864         mUwbSessionManager.onDataReceived(TEST_SESSION_ID_2, UwbUciConstants.STATUS_CODE_OK,
865                 DATA_SEQUENCE_NUM, PEER_EXTENDED_MAC_ADDRESS, DATA_PAYLOAD);
866         verify(mockUwbSession2).addReceivedDataInfo(isA(UwbSessionManager.ReceivedDataInfo.class));
867         verify(mUwbMetrics).logDataRx(eq(mockUwbSession2), eq(UwbUciConstants.STATUS_CODE_OK));
868 
869         // Next call onRangeDataNotificationReceived() to process the RANGE_DATA_NTF. Setup such
870         // that there is no ReceivedDataInfo returned for the UwbSession (to simulate the test
871         // scenario).
872         Params firaParams = setupFiraParams(
873                 RANGING_DEVICE_ROLE_OBSERVER, Optional.of(ROUND_USAGE_OWR_AOA_MEASUREMENT));
874         when(mockUwbSession.getParams()).thenReturn(firaParams);
875         when(mUwbAdvertiseManager.isPointedTarget(PEER_EXTENDED_MAC_ADDRESS)).thenReturn(true);
876         when(mockUwbSession.getAllReceivedDataInfo(PEER_EXTENDED_MAC_ADDRESS_LONG))
877                 .thenReturn(List.of());
878         mUwbSessionManager.onRangeDataNotificationReceived(uwbRangingData);
879 
880         verify(mUwbSessionNotificationManager)
881                 .onRangingResult(eq(mockUwbSession), eq(uwbRangingData));
882         verify(mUwbAdvertiseManager).updateAdvertiseTarget(uwbRangingData.mRangingOwrAoaMeasure);
883         verifyZeroInteractions(mUwbSessionNotificationManager);
884         verify(mUwbMetrics, never()).logDataToUpperLayer(eq(mockUwbSession), anyInt());
885     }
886 
887     @Test
onRangeDataNotificationReceived_owrAoa_notPointedTarget()888     public void onRangeDataNotificationReceived_owrAoa_notPointedTarget() {
889         UwbRangingData uwbRangingData = UwbTestUtils.generateRangingData(
890                 RANGING_MEASUREMENT_TYPE_OWR_AOA, MAC_ADDRESSING_MODE_EXTENDED,
891                 UwbUciConstants.STATUS_CODE_OK);
892         UwbSession mockUwbSession = mock(UwbSession.class);
893         when(mockUwbSession.getWaitObj()).thenReturn(mock(WaitObj.class));
894         when(mockUwbSession.getRangingRoundUsage()).thenReturn(ROUND_USAGE_OWR_AOA_MEASUREMENT);
895         doReturn(mockUwbSession)
896                 .when(mUwbSessionManager).getUwbSession(eq(TEST_SESSION_ID));
897 
898         mUwbSessionManager.onDataReceived(TEST_SESSION_ID, UwbUciConstants.STATUS_CODE_OK,
899                 DATA_SEQUENCE_NUM, PEER_EXTENDED_MAC_ADDRESS, DATA_PAYLOAD);
900         verify(mockUwbSession).addReceivedDataInfo(isA(UwbSessionManager.ReceivedDataInfo.class));
901         verify(mUwbMetrics).logDataRx(eq(mockUwbSession), eq(UwbUciConstants.STATUS_CODE_OK));
902 
903         // Setup isPointedTarget() to return false.
904         when(mUwbAdvertiseManager.isPointedTarget(PEER_EXTENDED_MAC_ADDRESS)).thenReturn(false);
905         mUwbSessionManager.onRangeDataNotificationReceived(uwbRangingData);
906 
907         verify(mUwbSessionNotificationManager)
908                 .onRangingResult(eq(mockUwbSession), eq(uwbRangingData));
909         verify(mUwbAdvertiseManager, never()).removeAdvertiseTarget(isA(Long.class));
910         verifyZeroInteractions(mUwbSessionNotificationManager);
911     }
912 
913     @Test
onMulticastListUpdateNotificationReceivedWithValidSession()914     public void onMulticastListUpdateNotificationReceivedWithValidSession() {
915         UwbMulticastListUpdateStatus mockUwbMulticastListUpdateStatus =
916                 mock(UwbMulticastListUpdateStatus.class);
917         UwbSession mockUwbSession = mock(UwbSession.class);
918         when(mockUwbSession.getWaitObj()).thenReturn(mock(WaitObj.class));
919         when(mockUwbSession.getOperationType())
920                 .thenReturn(UwbSessionManager.SESSION_RECONFIG_RANGING);
921         doReturn(mockUwbSession)
922                 .when(mUwbSessionManager).getUwbSession(anyInt());
923 
924         mUwbSessionManager.onMulticastListUpdateNotificationReceived(
925                 mockUwbMulticastListUpdateStatus);
926 
927         verify(mockUwbSession, times(2)).getWaitObj();
928         verify(mockUwbSession)
929                 .setMulticastListUpdateStatus(eq(mockUwbMulticastListUpdateStatus));
930     }
931 
932     @Test
onSessionStatusNotificationReceived_max_retry()933     public void onSessionStatusNotificationReceived_max_retry() {
934         UwbSession mockUwbSession = mock(UwbSession.class);
935         when(mockUwbSession.getSessionId()).thenReturn(TEST_SESSION_ID);
936         mUwbSessionManager.mSessionTable.put(mock(SessionHandle.class), mockUwbSession);
937         when(mockUwbSession.getWaitObj()).thenReturn(mock(WaitObj.class));
938         when(mockUwbSession.getSessionState()).thenReturn(UwbUciConstants.UWB_SESSION_STATE_ACTIVE);
939 
940         mUwbSessionManager.onSessionStatusNotificationReceived(
941                 TEST_SESSION_ID, SESSION_TOKEN,
942                 UwbUciConstants.UWB_SESSION_STATE_IDLE,
943                 UwbUciConstants.REASON_MAX_RANGING_ROUND_RETRY_COUNT_REACHED);
944 
945         verify(mockUwbSession, times(2)).getWaitObj();
946         verify(mockUwbSession).setSessionState(eq(UwbUciConstants.UWB_SESSION_STATE_IDLE));
947         verify(mUwbSessionNotificationManager).onRangingStoppedWithUciReasonCode(
948                 eq(mockUwbSession),
949                 eq(UwbUciConstants.REASON_MAX_RANGING_ROUND_RETRY_COUNT_REACHED));
950     }
951 
952     @Test
onSessionStatusNotificationReceived_session_mgmt_cmds()953     public void onSessionStatusNotificationReceived_session_mgmt_cmds() {
954         UwbSession mockUwbSession = mock(UwbSession.class);
955         when(mockUwbSession.getSessionId()).thenReturn(TEST_SESSION_ID);
956         mUwbSessionManager.mSessionTable.put(mock(SessionHandle.class), mockUwbSession);
957         when(mockUwbSession.getWaitObj()).thenReturn(mock(WaitObj.class));
958         when(mockUwbSession.getSessionState()).thenReturn(UwbUciConstants.UWB_SESSION_STATE_ACTIVE);
959 
960         mUwbSessionManager.onSessionStatusNotificationReceived(
961                 TEST_SESSION_ID, SESSION_TOKEN,
962                 UwbUciConstants.UWB_SESSION_STATE_IDLE,
963                 UwbUciConstants.REASON_STATE_CHANGE_WITH_SESSION_MANAGEMENT_COMMANDS);
964 
965         verify(mockUwbSession, times(2)).getWaitObj();
966         verify(mockUwbSession).setSessionState(eq(UwbUciConstants.UWB_SESSION_STATE_IDLE));
967         verify(mUwbSessionNotificationManager, never()).onRangingStoppedWithUciReasonCode(
968                 any(), anyInt());
969     }
970 
971     @Test
initSession_ExistedSession()972     public void initSession_ExistedSession() throws RemoteException {
973         IUwbRangingCallbacks mockRangingCallbacks = mock(IUwbRangingCallbacks.class);
974         doReturn(true).when(mUwbSessionManager).isExistedSession(anyInt());
975 
976         mUwbSessionManager.initSession(ATTRIBUTION_SOURCE, mock(SessionHandle.class),
977                 TEST_SESSION_ID, TEST_SESSION_TYPE, "any", mock(Params.class), mockRangingCallbacks,
978                 TEST_CHIP_ID);
979 
980         verify(mockRangingCallbacks).onRangingOpenFailed(
981                 any(), eq(RangingChangeReason.BAD_PARAMETERS), any());
982         assertThat(mTestLooper.nextMessage()).isNull();
983     }
984 
985     @Test
initFiraSession_maxSessionsExceeded()986     public void initFiraSession_maxSessionsExceeded() throws RemoteException {
987         doReturn(MAX_FIRA_SESSION_NUM).when(mUwbSessionManager).getFiraSessionCount();
988         doReturn(false).when(mUwbSessionManager).isExistedSession(anyInt());
989         IUwbRangingCallbacks mockRangingCallbacks = mock(IUwbRangingCallbacks.class);
990 
991         mUwbSessionManager.initSession(ATTRIBUTION_SOURCE, mock(SessionHandle.class),
992                 TEST_SESSION_ID, TEST_SESSION_TYPE, FiraParams.PROTOCOL_NAME, mock(Params.class),
993                 mockRangingCallbacks,
994                 TEST_CHIP_ID);
995 
996         verify(mockRangingCallbacks).onRangingOpenFailed(any(),
997                 eq(RangingChangeReason.MAX_SESSIONS_REACHED), any());
998         assertThat(mTestLooper.nextMessage()).isNull();
999     }
1000 
1001     @Test
initAliroSession_maxSessionsExceeded()1002     public void initAliroSession_maxSessionsExceeded() throws RemoteException {
1003         doReturn(MAX_ALIRO_SESSION_NUM).when(mUwbSessionManager).getAliroSessionCount();
1004         doReturn(false).when(mUwbSessionManager).isExistedSession(anyInt());
1005         IUwbRangingCallbacks mockRangingCallbacks = mock(IUwbRangingCallbacks.class);
1006 
1007         mUwbSessionManager.initSession(ATTRIBUTION_SOURCE, mock(SessionHandle.class),
1008                 TEST_SESSION_ID, TEST_SESSION_TYPE, AliroParams.PROTOCOL_NAME, mock(Params.class),
1009                 mockRangingCallbacks,
1010                 TEST_CHIP_ID);
1011 
1012         verify(mockRangingCallbacks).onRangingOpenFailed(any(),
1013                 eq(RangingChangeReason.MAX_SESSIONS_REACHED), any());
1014         assertThat(mTestLooper.nextMessage()).isNull();
1015     }
1016 
1017     @Test
initCccSession_maxSessionsExceeded()1018     public void initCccSession_maxSessionsExceeded() throws RemoteException {
1019         doReturn(MAX_CCC_SESSION_NUM).when(mUwbSessionManager).getCccSessionCount();
1020         doReturn(false).when(mUwbSessionManager).isExistedSession(anyInt());
1021         IUwbRangingCallbacks mockRangingCallbacks = mock(IUwbRangingCallbacks.class);
1022 
1023         mUwbSessionManager.initSession(ATTRIBUTION_SOURCE, mock(SessionHandle.class),
1024                 TEST_SESSION_ID, TEST_SESSION_TYPE, CccParams.PROTOCOL_NAME, mock(Params.class),
1025                 mockRangingCallbacks,
1026                 TEST_CHIP_ID);
1027 
1028         verify(mockRangingCallbacks).onRangingOpenFailed(any(),
1029                 eq(RangingChangeReason.MAX_SESSIONS_REACHED), any());
1030         assertThat(mTestLooper.nextMessage()).isNull();
1031     }
1032 
1033     @Test
initSession_UwbSession_RemoteException()1034     public void initSession_UwbSession_RemoteException() throws RemoteException {
1035         doReturn(0).when(mUwbSessionManager).getSessionCount();
1036         doReturn(0L).when(mUwbSessionManager).getAliroSessionCount();
1037         doReturn(0L).when(mUwbSessionManager).getCccSessionCount();
1038         doReturn(0L).when(mUwbSessionManager).getFiraSessionCount();
1039         doReturn(false).when(mUwbSessionManager).isExistedSession(anyInt());
1040         IUwbRangingCallbacks mockRangingCallbacks = mock(IUwbRangingCallbacks.class);
1041         SessionHandle mockSessionHandle = mock(SessionHandle.class);
1042         Params mockParams = mock(FiraParams.class);
1043         IBinder mockBinder = mock(IBinder.class);
1044         UwbSession uwbSession = spy(
1045                 mUwbSessionManager.new UwbSession(ATTRIBUTION_SOURCE, mockSessionHandle,
1046                         TEST_SESSION_ID, TEST_SESSION_TYPE, FiraParams.PROTOCOL_NAME, mockParams,
1047                         mockRangingCallbacks, TEST_CHIP_ID));
1048         doReturn(mockBinder).when(uwbSession).getBinder();
1049         doReturn(uwbSession).when(mUwbSessionManager).createUwbSession(any(), any(), anyInt(),
1050                 anyByte(), anyString(), any(), any(), anyString());
1051         doThrow(new RemoteException()).when(mockBinder).linkToDeath(any(), anyInt());
1052 
1053         mUwbSessionManager.initSession(ATTRIBUTION_SOURCE, mockSessionHandle, TEST_SESSION_ID,
1054                 TEST_SESSION_TYPE, FiraParams.PROTOCOL_NAME, mockParams, mockRangingCallbacks,
1055                 TEST_CHIP_ID);
1056 
1057         verify(uwbSession).binderDied();
1058         verify(mockRangingCallbacks).onRangingOpenFailed(any(), anyInt(), any());
1059         verify(mockBinder, atLeast(1)).unlinkToDeath(any(), anyInt());
1060         assertThat(mTestLooper.nextMessage()).isNull();
1061     }
1062 
1063     @Test
initSession_success()1064     public void initSession_success() throws RemoteException {
1065         doReturn(0).when(mUwbSessionManager).getSessionCount();
1066         doReturn(0L).when(mUwbSessionManager).getAliroSessionCount();
1067         doReturn(0L).when(mUwbSessionManager).getCccSessionCount();
1068         doReturn(0L).when(mUwbSessionManager).getFiraSessionCount();
1069         doReturn(false).when(mUwbSessionManager).isExistedSession(anyInt());
1070         IUwbRangingCallbacks mockRangingCallbacks = mock(IUwbRangingCallbacks.class);
1071         SessionHandle mockSessionHandle = mock(SessionHandle.class);
1072         Params mockParams = mock(FiraParams.class);
1073         IBinder mockBinder = mock(IBinder.class);
1074 
1075         UwbSession uwbSession = spy(
1076                 mUwbSessionManager.new UwbSession(ATTRIBUTION_SOURCE, mockSessionHandle,
1077                         TEST_SESSION_ID, TEST_SESSION_TYPE, FiraParams.PROTOCOL_NAME, mockParams,
1078                         mockRangingCallbacks, TEST_CHIP_ID));
1079         doReturn(mockBinder).when(uwbSession).getBinder();
1080         doReturn(uwbSession).when(mUwbSessionManager).createUwbSession(any(), any(), anyInt(),
1081                 anyByte(), anyString(), any(), any(), anyString());
1082 
1083         mUwbSessionManager.initSession(ATTRIBUTION_SOURCE, mockSessionHandle, TEST_SESSION_ID,
1084                 TEST_SESSION_TYPE, FiraParams.PROTOCOL_NAME, mockParams, mockRangingCallbacks,
1085                 TEST_CHIP_ID);
1086 
1087         verify(uwbSession, never()).binderDied();
1088         verify(mockRangingCallbacks, never()).onRangingOpenFailed(any(), anyInt(), any());
1089         verify(mockBinder, never()).unlinkToDeath(any(), anyInt());
1090         assertThat(mUwbSessionManager.getUwbSession(TEST_SESSION_ID)).isEqualTo(uwbSession);
1091         assertThat(mTestLooper.nextMessage().what).isEqualTo(1); // SESSION_OPEN_RANGING
1092     }
1093 
1094     @Test
initSessionMaxSessions_lowestPrioritySessionReplaced()1095     public void initSessionMaxSessions_lowestPrioritySessionReplaced() throws RemoteException {
1096         doReturn(false).when(mUwbInjector).isSystemApp(UID, PACKAGE_NAME);
1097         doReturn(true).when(mUwbInjector).isSystemApp(UID_2, PACKAGE_NAME_2);
1098         doReturn(1L).when(mUwbSessionManager).getMaxFiraSessionsNumber(TEST_CHIP_ID);
1099         IUwbRangingCallbacks mockRangingCallbacks = mock(IUwbRangingCallbacks.class);
1100         Params mockParams = mock(FiraParams.class);
1101         IBinder mockBinder = mock(IBinder.class);
1102 
1103         when(mNativeUwbManager.initSession(anyInt(), anyByte(), anyString()))
1104                 .thenReturn((byte) UwbUciConstants.STATUS_CODE_OK);
1105         when(mNativeUwbManager.deInitSession(anyInt(), anyString()))
1106                 .thenReturn((byte) UwbUciConstants.STATUS_CODE_OK);
1107         when(mUwbConfigurationManager.setAppConfigurations(anyInt(), any(), anyString(), any()))
1108                 .thenReturn(UwbUciConstants.STATUS_CODE_OK);
1109 
1110         // Init session for 3rd party FG app
1111         UwbSession lowPrioUwbSession = spy(
1112                 mUwbSessionManager.new UwbSession(ATTRIBUTION_SOURCE, SESSION_HANDLE,
1113                         TEST_SESSION_ID, TEST_SESSION_TYPE, FiraParams.PROTOCOL_NAME, mockParams,
1114                         mockRangingCallbacks, TEST_CHIP_ID));
1115         doReturn(lowPrioUwbSession).when(mUwbSessionManager).createUwbSession(any(), any(),
1116                 anyInt(),
1117                 anyByte(), anyString(), any(), any(), anyString());
1118         doReturn(UwbUciConstants.UWB_SESSION_STATE_INIT,
1119                 UwbUciConstants.UWB_SESSION_STATE_IDLE).when(lowPrioUwbSession).getSessionState();
1120         doReturn(mock(WaitObj.class)).when(lowPrioUwbSession).getWaitObj();
1121         doReturn(mockBinder).when(lowPrioUwbSession).getBinder();
1122 
1123         mUwbSessionManager.initSession(ATTRIBUTION_SOURCE, SESSION_HANDLE, TEST_SESSION_ID,
1124                 TEST_SESSION_TYPE, FiraParams.PROTOCOL_NAME, mockParams, mockRangingCallbacks,
1125                 TEST_CHIP_ID);
1126 
1127         assertThat(mUwbSessionManager.getUwbSession(TEST_SESSION_ID)).isEqualTo(lowPrioUwbSession);
1128         mTestLooper.dispatchNext();
1129 
1130         // Init session for system app
1131         UwbSession highPrioUwbSession = spy(
1132                 mUwbSessionManager.new UwbSession(ATTRIBUTION_SOURCE_2, SESSION_HANDLE_2,
1133                         TEST_SESSION_ID_2, TEST_SESSION_TYPE, FiraParams.PROTOCOL_NAME, mockParams,
1134                         mockRangingCallbacks, TEST_CHIP_ID));
1135         doReturn(mockBinder).when(highPrioUwbSession).getBinder();
1136         doReturn(mock(WaitObj.class)).when(highPrioUwbSession).getWaitObj();
1137         doReturn(UwbUciConstants.UWB_SESSION_STATE_INIT,
1138                 UwbUciConstants.UWB_SESSION_STATE_IDLE).when(highPrioUwbSession).getSessionState();
1139         doReturn(highPrioUwbSession).when(mUwbSessionManager).createUwbSession(any(), any(),
1140                 anyInt(),
1141                 anyByte(), anyString(), any(), any(), anyString());
1142         mUwbSessionManager.initSession(ATTRIBUTION_SOURCE_2, SESSION_HANDLE_2, TEST_SESSION_ID_2,
1143                 TEST_SESSION_TYPE, FiraParams.PROTOCOL_NAME, mockParams, mockRangingCallbacks,
1144                 TEST_CHIP_ID);
1145         mTestLooper.dispatchAll();
1146 
1147         verify(mNativeUwbManager).initSession(TEST_SESSION_ID, TEST_SESSION_TYPE, TEST_CHIP_ID);
1148         verify(mNativeUwbManager).deInitSession(TEST_SESSION_ID, TEST_CHIP_ID);
1149         verify(mNativeUwbManager).initSession(TEST_SESSION_ID_2, TEST_SESSION_TYPE, TEST_CHIP_ID);
1150         verify(mockRangingCallbacks, never()).onRangingOpenFailed(any(), anyInt(), any());
1151         verify(mUwbSessionNotificationManager).onRangingOpened(lowPrioUwbSession);
1152         verify(mUwbSessionNotificationManager).onRangingClosed(lowPrioUwbSession,
1153                 UwbUciConstants.STATUS_CODE_ERROR_MAX_SESSIONS_EXCEEDED);
1154         verify(mUwbSessionNotificationManager).onRangingOpened(highPrioUwbSession);
1155         assertThat(mUwbSessionManager.getUwbSession(TEST_SESSION_ID)).isNull();
1156         assertThat(mUwbSessionManager.getUwbSession(TEST_SESSION_ID_2)).isEqualTo(
1157                 highPrioUwbSession);
1158     }
1159 
1160     @Test
testNeedsAppConfigUpdate_setAppConfigCalledOnStartRanging()1161     public void testNeedsAppConfigUpdate_setAppConfigCalledOnStartRanging() throws RemoteException {
1162         UwbSession mockUwbSession = mock(UwbSession.class);
1163 
1164         doReturn(true).when(mUwbSessionManager).isExistedSession(any());
1165         doReturn(TEST_SESSION_ID).when(mUwbSessionManager).getSessionId(any());
1166         doReturn(mockUwbSession).when(mUwbSessionManager).getUwbSession(anyInt());
1167         doReturn(UwbUciConstants.UWB_SESSION_STATE_IDLE)
1168                 .when(mUwbSessionManager).getCurrentSessionState(anyInt());
1169         doReturn(PROTOCOL_NAME).when(mockUwbSession).getProtocolName();
1170         doReturn(mock(WaitObj.class)).when(mockUwbSession).getWaitObj();
1171         when(mockUwbSession.getNeedsAppConfigUpdate()).thenReturn(true);
1172 
1173         mUwbSessionManager.startRanging(mock(SessionHandle.class), mock(Params.class));
1174         mTestLooper.dispatchAll();
1175 
1176         verify(mUwbConfigurationManager).setAppConfigurations(
1177                 anyInt(), any(), any(), eq(FIRA_VERSION_1_1));
1178     }
1179 
1180     @Test
testCreateUwbSession_correctSessionPrioritiesSet()1181     public void testCreateUwbSession_correctSessionPrioritiesSet() throws RemoteException {
1182         IUwbRangingCallbacks mockRangingCallbacks = mock(IUwbRangingCallbacks.class);
1183         SessionHandle mockSessionHandle = mock(SessionHandle.class);
1184         FiraOpenSessionParams mockFiraOpenSessionParams = mock(FiraOpenSessionParams.class);
1185         Params mockCccParams = mock(CccParams.class);
1186         Params mockAliroParams = mock(AliroParams.class);
1187         FiraOpenSessionParams.Builder mockFiraBuilder = mock(FiraOpenSessionParams.Builder.class);
1188 
1189         when(mockFiraOpenSessionParams.toBuilder()).thenReturn(mockFiraBuilder);
1190         when(mockFiraBuilder.setSessionPriority(anyInt())).thenReturn(mockFiraBuilder);
1191         when(mockFiraBuilder.build()).thenReturn(mockFiraOpenSessionParams);
1192         when(mockFiraOpenSessionParams.getSessionPriority()).thenReturn(
1193                 UwbSession.DEFAULT_SESSION_PRIORITY);
1194 
1195         // System session
1196         String systemPackageName = "com.google.uwb";
1197         when(mUwbInjector.isSystemApp(UID, systemPackageName)).thenReturn(true);
1198         AttributionSource attributionSourceSystemApp =
1199                 new AttributionSource.Builder(UID).setPackageName(systemPackageName).build();
1200         UwbSession systemUwbSession =
1201                 mUwbSessionManager.new UwbSession(attributionSourceSystemApp, mockSessionHandle,
1202                         TEST_SESSION_ID, TEST_SESSION_TYPE, FiraParams.PROTOCOL_NAME,
1203                         mockFiraOpenSessionParams,
1204                         mockRangingCallbacks, TEST_CHIP_ID);
1205 
1206         assertThat(systemUwbSession.getStackSessionPriority()).isEqualTo(
1207                 UwbSession.SYSTEM_APP_SESSION_PRIORITY);
1208         verify(mockFiraBuilder).setSessionPriority(UwbSession.SYSTEM_APP_SESSION_PRIORITY);
1209 
1210         // CCC session
1211         UwbSession cccUwbSession =
1212                 mUwbSessionManager.new UwbSession(attributionSourceSystemApp, mockSessionHandle,
1213                         TEST_SESSION_ID, TEST_SESSION_TYPE, CccParams.PROTOCOL_NAME, mockCccParams,
1214                         mockRangingCallbacks, TEST_CHIP_ID);
1215 
1216         assertThat(cccUwbSession.getStackSessionPriority()).isEqualTo(
1217                 UwbSession.CCC_SESSION_PRIORITY);
1218 
1219         // ALIRO session
1220         UwbSession aliroUwbSession =
1221                 mUwbSessionManager.new UwbSession(attributionSourceSystemApp, mockSessionHandle,
1222                         TEST_SESSION_ID, TEST_SESSION_TYPE, AliroParams.PROTOCOL_NAME,
1223                         mockAliroParams, mockRangingCallbacks, TEST_CHIP_ID);
1224 
1225         assertThat(aliroUwbSession.getStackSessionPriority()).isEqualTo(
1226                 UwbSession.ALIRO_SESSION_PRIORITY);
1227 
1228         // 3rd party foreground session
1229         String nonSystemPackageName = "com.something.app";
1230         when(mUwbInjector.isForegroundAppOrService(UID, nonSystemPackageName))
1231                 .thenReturn(true);
1232         AttributionSource attributionSourceNonSystemApp =
1233                 new AttributionSource.Builder(UID).setPackageName(nonSystemPackageName).build();
1234         UwbSession nonSystemFgUwbSession =
1235                 mUwbSessionManager.new UwbSession(attributionSourceNonSystemApp, mockSessionHandle,
1236                         TEST_SESSION_ID, TEST_SESSION_TYPE, FiraParams.PROTOCOL_NAME,
1237                         mockFiraOpenSessionParams,
1238                         mockRangingCallbacks, TEST_CHIP_ID);
1239 
1240         assertThat(nonSystemFgUwbSession.getStackSessionPriority()).isEqualTo(
1241                 UwbSession.FG_SESSION_PRIORITY);
1242         verify(mockFiraBuilder).setSessionPriority(UwbSession.FG_SESSION_PRIORITY);
1243 
1244 
1245         // 3rd party background session
1246         when(mUwbInjector.isForegroundAppOrService(UID, nonSystemPackageName))
1247                 .thenReturn(false);
1248         UwbSession nonSystemBgUwbSession =
1249                 mUwbSessionManager.new UwbSession(attributionSourceNonSystemApp, mockSessionHandle,
1250                         TEST_SESSION_ID, TEST_SESSION_TYPE, FiraParams.PROTOCOL_NAME,
1251                         mockFiraOpenSessionParams,
1252                         mockRangingCallbacks, TEST_CHIP_ID);
1253 
1254         assertThat(nonSystemBgUwbSession.getStackSessionPriority()).isEqualTo(
1255                 UwbSession.BG_SESSION_PRIORITY);
1256         verify(mockFiraBuilder).setSessionPriority(UwbSession.BG_SESSION_PRIORITY);
1257 
1258     }
1259 
1260     @Test
initSession_controleeList()1261     public void initSession_controleeList() throws RemoteException {
1262         doReturn(0).when(mUwbSessionManager).getSessionCount();
1263         doReturn(0L).when(mUwbSessionManager).getCccSessionCount();
1264         doReturn(0L).when(mUwbSessionManager).getAliroSessionCount();
1265         doReturn(0L).when(mUwbSessionManager).getFiraSessionCount();
1266         doReturn(false).when(mUwbSessionManager).isExistedSession(anyInt());
1267         IUwbRangingCallbacks mockRangingCallbacks = mock(IUwbRangingCallbacks.class);
1268         SessionHandle mockSessionHandle = mock(SessionHandle.class);
1269         FiraOpenSessionParams mockParams = mock(FiraOpenSessionParams.class);
1270         FiraOpenSessionParams.Builder mockBuilder = mock(FiraOpenSessionParams.Builder.class);
1271         IBinder mockBinder = mock(IBinder.class);
1272 
1273         when(mockParams.getDestAddressList())
1274                 .thenReturn(Collections.singletonList(UWB_DEST_ADDRESS));
1275         when(mockParams.toBuilder()).thenReturn(mockBuilder);
1276         when(mockBuilder.setSessionPriority(anyInt())).thenReturn(mockBuilder);
1277         when(mockBuilder.build()).thenReturn(mockParams);
1278 
1279         UwbSession uwbSession = spy(
1280                 mUwbSessionManager.new UwbSession(ATTRIBUTION_SOURCE, mockSessionHandle,
1281                         TEST_SESSION_ID, TEST_SESSION_TYPE, FiraParams.PROTOCOL_NAME, mockParams,
1282                         mockRangingCallbacks, TEST_CHIP_ID));
1283         doReturn(mockBinder).when(uwbSession).getBinder();
1284         doReturn(uwbSession).when(mUwbSessionManager).createUwbSession(any(), any(), anyInt(),
1285                 anyByte(), anyString(), any(), any(), anyString());
1286 
1287         mUwbSessionManager.initSession(ATTRIBUTION_SOURCE, mockSessionHandle, TEST_SESSION_ID,
1288                 TEST_SESSION_TYPE, FiraParams.PROTOCOL_NAME, mockParams, mockRangingCallbacks,
1289                 TEST_CHIP_ID);
1290 
1291         assertThat(uwbSession.getControleeList().size() == 1
1292                 && uwbSession.getControleeList().get(0).getUwbAddress().equals(UWB_DEST_ADDRESS))
1293                 .isTrue();
1294 
1295         assertThat(uwbSession.getControlee(UWB_DEST_ADDRESS)
1296                 .getUwbAddress().equals(UWB_DEST_ADDRESS)).isTrue();
1297 
1298         verify(uwbSession, never()).binderDied();
1299         verify(mockRangingCallbacks, never()).onRangingOpenFailed(any(), anyInt(), any());
1300         verify(mockBinder, never()).unlinkToDeath(any(), anyInt());
1301         assertThat(mUwbSessionManager.getUwbSession(TEST_SESSION_ID)).isEqualTo(uwbSession);
1302         assertThat(mTestLooper.nextMessage().what).isEqualTo(1); // SESSION_OPEN_RANGING
1303     }
1304 
1305     @Test
startRanging_notExistedSession()1306     public void startRanging_notExistedSession() {
1307         doReturn(false).when(mUwbSessionManager).isExistedSession(any());
1308         doReturn(TEST_SESSION_ID).when(mUwbSessionManager).getSessionId(any());
1309         doReturn(mock(UwbSession.class)).when(mUwbSessionManager).getUwbSession(anyInt());
1310         doReturn(UwbUciConstants.UWB_SESSION_STATE_IDLE)
1311                 .when(mUwbSessionManager).getCurrentSessionState(anyInt());
1312 
1313         mUwbSessionManager.startRanging(mock(SessionHandle.class), mock(Params.class));
1314 
1315         assertThat(mTestLooper.nextMessage()).isNull();
1316     }
1317 
1318     @Test
startRanging_currentSessionStateIdle()1319     public void startRanging_currentSessionStateIdle() {
1320         doReturn(true).when(mUwbSessionManager).isExistedSession(any());
1321         doReturn(TEST_SESSION_ID).when(mUwbSessionManager).getSessionId(any());
1322         UwbSession uwbSession = mock(UwbSession.class);
1323         when(uwbSession.getProtocolName()).thenReturn(FiraParams.PROTOCOL_NAME);
1324         doReturn(uwbSession).when(mUwbSessionManager).getUwbSession(anyInt());
1325         doReturn(UwbUciConstants.UWB_SESSION_STATE_IDLE)
1326                 .when(mUwbSessionManager).getCurrentSessionState(anyInt());
1327 
1328         mUwbSessionManager.startRanging(mock(SessionHandle.class), mock(Params.class));
1329 
1330         assertThat(mTestLooper.nextMessage().what).isEqualTo(2); // SESSION_START_RANGING
1331     }
1332 
1333     @Test
startRanging_currentCccSessionStateActive()1334     public void startRanging_currentCccSessionStateActive() {
1335         doReturn(true).when(mUwbSessionManager).isExistedSession(any());
1336         doReturn(TEST_SESSION_ID).when(mUwbSessionManager).getSessionId(any());
1337         UwbSession mockUwbSession = mock(UwbSession.class);
1338         doReturn(mockUwbSession).when(mUwbSessionManager).getUwbSession(anyInt());
1339         when(mockUwbSession.getProtocolName()).thenReturn(CccParams.PROTOCOL_NAME);
1340         doReturn(UwbUciConstants.UWB_SESSION_STATE_ACTIVE)
1341                 .when(mUwbSessionManager).getCurrentSessionState(anyInt());
1342 
1343         mUwbSessionManager.startRanging(mock(SessionHandle.class), mock(Params.class));
1344 
1345         verify(mUwbSessionNotificationManager).onRangingStartFailed(
1346                 any(), eq(UwbUciConstants.STATUS_CODE_REJECTED));
1347     }
1348 
1349     @Test
startRanging_currentAliroSessionStateActive()1350     public void startRanging_currentAliroSessionStateActive() {
1351         doReturn(true).when(mUwbSessionManager).isExistedSession(any());
1352         doReturn(TEST_SESSION_ID).when(mUwbSessionManager).getSessionId(any());
1353         UwbSession mockUwbSession = mock(UwbSession.class);
1354         doReturn(mockUwbSession).when(mUwbSessionManager).getUwbSession(anyInt());
1355         when(mockUwbSession.getProtocolName()).thenReturn(AliroParams.PROTOCOL_NAME);
1356         doReturn(UwbUciConstants.UWB_SESSION_STATE_ACTIVE)
1357                 .when(mUwbSessionManager).getCurrentSessionState(anyInt());
1358 
1359         mUwbSessionManager.startRanging(mock(SessionHandle.class), mock(Params.class));
1360 
1361         verify(mUwbSessionNotificationManager).onRangingStartFailed(
1362                 any(), eq(UwbUciConstants.STATUS_CODE_REJECTED));
1363     }
1364 
1365     @Test
startRanging_currentSessionStateInvalid()1366     public void startRanging_currentSessionStateInvalid() {
1367         doReturn(true).when(mUwbSessionManager).isExistedSession(any());
1368         doReturn(TEST_SESSION_ID).when(mUwbSessionManager).getSessionId(any());
1369         doReturn(mock(UwbSession.class)).when(mUwbSessionManager).getUwbSession(anyInt());
1370         doReturn(UwbUciConstants.UWB_SESSION_STATE_ERROR)
1371                 .when(mUwbSessionManager).getCurrentSessionState(anyInt());
1372 
1373         mUwbSessionManager.startRanging(mock(SessionHandle.class), mock(Params.class));
1374 
1375         verify(mUwbSessionNotificationManager)
1376                 .onRangingStartFailed(any(), eq(UwbUciConstants.STATUS_CODE_FAILED));
1377     }
1378 
1379     @Test
stopRanging_notExistedSession()1380     public void stopRanging_notExistedSession() {
1381         doReturn(false).when(mUwbSessionManager).isExistedSession(any());
1382         doReturn(TEST_SESSION_ID).when(mUwbSessionManager).getSessionId(any());
1383         doReturn(mock(UwbSession.class)).when(mUwbSessionManager).getUwbSession(anyInt());
1384         doReturn(UwbUciConstants.UWB_SESSION_STATE_ACTIVE)
1385                 .when(mUwbSessionManager).getCurrentSessionState(anyInt());
1386 
1387         mUwbSessionManager.stopRanging(mock(SessionHandle.class));
1388 
1389         assertThat(mTestLooper.nextMessage()).isNull();
1390     }
1391 
1392     @Test
stopRanging_currentSessionStateActive()1393     public void stopRanging_currentSessionStateActive() {
1394         doReturn(true).when(mUwbSessionManager).isExistedSession(any());
1395         doReturn(TEST_SESSION_ID).when(mUwbSessionManager).getSessionId(any());
1396         doReturn(mock(UwbSession.class)).when(mUwbSessionManager).getUwbSession(anyInt());
1397         doReturn(UwbUciConstants.UWB_SESSION_STATE_ACTIVE)
1398                 .when(mUwbSessionManager).getCurrentSessionState(anyInt());
1399 
1400         mUwbSessionManager.stopRanging(mock(SessionHandle.class));
1401 
1402         assertThat(mTestLooper.nextMessage().what).isEqualTo(3); // SESSION_STOP_RANGING
1403     }
1404 
1405     @Test
stopRanging_currentSessionStateActive_owrAoa()1406     public void stopRanging_currentSessionStateActive_owrAoa() {
1407         UwbSession mockUwbSession = mock(UwbSession.class);
1408 
1409         doReturn(true).when(mUwbSessionManager).isExistedSession(any());
1410         doReturn(TEST_SESSION_ID).when(mUwbSessionManager).getSessionId(any());
1411         doReturn(mockUwbSession).when(mUwbSessionManager).getUwbSession(anyInt());
1412         doReturn(UwbUciConstants.UWB_SESSION_STATE_ACTIVE)
1413                 .when(mUwbSessionManager).getCurrentSessionState(anyInt());
1414         when(mNativeUwbManager.stopRanging(eq(TEST_SESSION_ID), anyString()))
1415                 .thenReturn((byte) UwbUciConstants.STATUS_CODE_OK);
1416 
1417         doReturn(PROTOCOL_NAME).when(mockUwbSession).getProtocolName();
1418         doReturn(0).when(mockUwbSession).getCurrentFiraRangingIntervalMs();
1419 
1420         // Setup the UwbSession to have the peer device's MacAddress stored (which happens when
1421         // a valid RANGE_DATA_NTF with an OWR AoA Measurement is received).
1422         doReturn(Set.of(PEER_EXTENDED_MAC_ADDRESS_LONG)).when(mockUwbSession)
1423                 .getRemoteMacAddressList();
1424 
1425         mUwbSessionManager.stopRanging(mock(SessionHandle.class));
1426         mTestLooper.dispatchNext();
1427 
1428         verify(mUwbAdvertiseManager).removeAdvertiseTarget(PEER_EXTENDED_MAC_ADDRESS_LONG);
1429     }
1430 
1431     @Test
stopRanging_currentSessionStateIdle()1432     public void stopRanging_currentSessionStateIdle() {
1433         doReturn(true).when(mUwbSessionManager).isExistedSession(any());
1434         doReturn(TEST_SESSION_ID).when(mUwbSessionManager).getSessionId(any());
1435         doReturn(mock(UwbSession.class)).when(mUwbSessionManager).getUwbSession(anyInt());
1436         doReturn(UwbUciConstants.UWB_SESSION_STATE_IDLE)
1437                 .when(mUwbSessionManager).getCurrentSessionState(anyInt());
1438 
1439         mUwbSessionManager.stopRanging(mock(SessionHandle.class));
1440 
1441         verify(mUwbSessionNotificationManager).onRangingStopped(any(),
1442                 eq(UwbUciConstants.REASON_STATE_CHANGE_WITH_SESSION_MANAGEMENT_COMMANDS));
1443     }
1444 
1445     @Test
stopRanging_currentSessionStateInvalid()1446     public void stopRanging_currentSessionStateInvalid() {
1447         doReturn(true).when(mUwbSessionManager).isExistedSession(any());
1448         doReturn(TEST_SESSION_ID).when(mUwbSessionManager).getSessionId(any());
1449         doReturn(mock(UwbSession.class)).when(mUwbSessionManager).getUwbSession(anyInt());
1450         doReturn(UwbUciConstants.UWB_SESSION_STATE_ERROR)
1451                 .when(mUwbSessionManager).getCurrentSessionState(anyInt());
1452 
1453         mUwbSessionManager.stopRanging(mock(SessionHandle.class));
1454 
1455         verify(mUwbSessionNotificationManager).onRangingStopFailed(any(),
1456                 eq(UwbUciConstants.STATUS_CODE_REJECTED));
1457     }
1458 
1459     @Test
getUwbSession_success()1460     public void getUwbSession_success() {
1461         UwbSession mockUwbSession = mock(UwbSession.class);
1462         when(mockUwbSession.getSessionId()).thenReturn(TEST_SESSION_ID);
1463         mUwbSessionManager.mSessionTable.put(mock(SessionHandle.class), mockUwbSession);
1464 
1465         UwbSession actualUwbSession = mUwbSessionManager.getUwbSession(TEST_SESSION_ID);
1466 
1467         assertThat(actualUwbSession).isEqualTo(mockUwbSession);
1468     }
1469 
1470     @Test
getUwbSession_failed()1471     public void getUwbSession_failed() {
1472         UwbSession mockUwbSession = mock(UwbSession.class);
1473         when(mockUwbSession.getSessionId()).thenReturn(TEST_SESSION_ID);
1474         mUwbSessionManager.mSessionTable.put(mock(SessionHandle.class), mockUwbSession);
1475 
1476         UwbSession actualUwbSession = mUwbSessionManager.getUwbSession(TEST_SESSION_ID - 1);
1477 
1478         assertThat(actualUwbSession).isNull();
1479     }
1480 
1481     @Test
getSessionId_success()1482     public void getSessionId_success() {
1483         UwbSession mockUwbSession = mock(UwbSession.class);
1484         when(mockUwbSession.getSessionId()).thenReturn(TEST_SESSION_ID);
1485         SessionHandle mockSessionHandle = mock(SessionHandle.class);
1486         mUwbSessionManager.mSessionTable.put(mockSessionHandle, mockUwbSession);
1487         when(mockUwbSession.getSessionHandle()).thenReturn(mockSessionHandle);
1488 
1489         int actualSessionId = mUwbSessionManager.getSessionId(mockSessionHandle);
1490 
1491         assertThat(actualSessionId).isEqualTo(TEST_SESSION_ID);
1492     }
1493 
1494     @Test
getSessionId_failed()1495     public void getSessionId_failed() {
1496         UwbSession mockUwbSession = mock(UwbSession.class);
1497         when(mockUwbSession.getSessionId()).thenReturn(TEST_SESSION_ID);
1498         SessionHandle mockSessionHandle = mock(SessionHandle.class);
1499         mUwbSessionManager.mSessionTable.put(mockSessionHandle, mockUwbSession);
1500         when(mockUwbSession.getSessionHandle()).thenReturn(mockSessionHandle);
1501 
1502         Integer actualSessionId = mUwbSessionManager.getSessionId(mock(SessionHandle.class));
1503 
1504         assertThat(actualSessionId).isNull();
1505     }
1506 
1507     @Test
isExistedSession_sessionHandle_success()1508     public void isExistedSession_sessionHandle_success() {
1509         doReturn(TEST_SESSION_ID).when(mUwbSessionManager).getSessionId(any());
1510 
1511         boolean result = mUwbSessionManager.isExistedSession(mock(SessionHandle.class));
1512 
1513         assertThat(result).isTrue();
1514     }
1515 
1516     @Test
iexExistedSession_sessionHandle_failed()1517     public void iexExistedSession_sessionHandle_failed() {
1518         doReturn(null).when(mUwbSessionManager).getSessionId(any());
1519 
1520         boolean result = mUwbSessionManager.isExistedSession(mock(SessionHandle.class));
1521 
1522         assertThat(result).isFalse();
1523     }
1524 
1525     @Test
isExistedSession_sessionId_success()1526     public void isExistedSession_sessionId_success() {
1527         UwbSession mockUwbSession = mock(UwbSession.class);
1528         when(mockUwbSession.getSessionId()).thenReturn(TEST_SESSION_ID);
1529         mUwbSessionManager.mSessionTable.put(mock(SessionHandle.class), mockUwbSession);
1530 
1531         boolean result = mUwbSessionManager.isExistedSession(TEST_SESSION_ID);
1532 
1533         assertThat(result).isTrue();
1534     }
1535 
1536     @Test
iexExistedSession_sessionId_failed()1537     public void iexExistedSession_sessionId_failed() {
1538         boolean result = mUwbSessionManager.isExistedSession(TEST_SESSION_ID);
1539 
1540         assertThat(result).isFalse();
1541     }
1542 
1543     @Test
stopAllRanging()1544     public void stopAllRanging() {
1545         UwbSession mockUwbSession1 = mock(UwbSession.class);
1546         when(mockUwbSession1.getSessionId()).thenReturn(TEST_SESSION_ID);
1547         when(mockUwbSession1.getChipId()).thenReturn(TEST_CHIP_ID);
1548         mUwbSessionManager.mSessionTable.put(mock(SessionHandle.class), mockUwbSession1);
1549 
1550         UwbSession mockUwbSession2 = mock(UwbSession.class);
1551         when(mockUwbSession2.getSessionId()).thenReturn(TEST_SESSION_ID + 100);
1552         when(mockUwbSession2.getChipId()).thenReturn(TEST_CHIP_ID);
1553         mUwbSessionManager.mSessionTable.put(mock(SessionHandle.class), mockUwbSession2);
1554 
1555         when(mNativeUwbManager.stopRanging(eq(TEST_SESSION_ID), anyString()))
1556                 .thenReturn((byte) UwbUciConstants.STATUS_CODE_FAILED);
1557         when(mNativeUwbManager.stopRanging(eq(TEST_SESSION_ID + 100), anyString()))
1558                 .thenReturn((byte) UwbUciConstants.STATUS_CODE_OK);
1559 
1560         mUwbSessionManager.stopAllRanging();
1561 
1562         verify(mNativeUwbManager, times(2))
1563                 .stopRanging(anyInt(), anyString());
1564         verify(mockUwbSession1, never()).setSessionState(anyInt());
1565         verify(mockUwbSession2).setSessionState(eq(UwbUciConstants.UWB_SESSION_STATE_IDLE));
1566     }
1567 
1568     @Test
setCurrentSessionState()1569     public void setCurrentSessionState() {
1570         UwbSession mockUwbSession = mock(UwbSession.class);
1571         when(mockUwbSession.getSessionId()).thenReturn(TEST_SESSION_ID);
1572         mUwbSessionManager.mSessionTable.put(mock(SessionHandle.class), mockUwbSession);
1573 
1574         mUwbSessionManager.setCurrentSessionState(
1575                 TEST_SESSION_ID, UwbUciConstants.UWB_SESSION_STATE_ACTIVE);
1576 
1577         verify(mockUwbSession).setSessionState(eq(UwbUciConstants.UWB_SESSION_STATE_ACTIVE));
1578     }
1579 
1580     @Test
getCurrentSessionState_nullSession()1581     public void getCurrentSessionState_nullSession() {
1582         int actualStatus = mUwbSessionManager.getCurrentSessionState(TEST_SESSION_ID);
1583 
1584         assertThat(actualStatus).isEqualTo(UwbUciConstants.UWB_SESSION_STATE_ERROR);
1585     }
1586 
1587     @Test
getCurrentSessionState_success()1588     public void getCurrentSessionState_success() {
1589         UwbSession mockUwbSession = mock(UwbSession.class);
1590         when(mockUwbSession.getSessionId()).thenReturn(TEST_SESSION_ID);
1591         when(mockUwbSession.getSessionState()).thenReturn(UwbUciConstants.UWB_SESSION_STATE_ACTIVE);
1592         mUwbSessionManager.mSessionTable.put(mock(SessionHandle.class), mockUwbSession);
1593 
1594         int actualStatus = mUwbSessionManager.getCurrentSessionState(TEST_SESSION_ID);
1595 
1596         assertThat(actualStatus).isEqualTo(UwbUciConstants.UWB_SESSION_STATE_ACTIVE);
1597     }
1598 
1599     @Test
getSessionIdSet()1600     public void getSessionIdSet() {
1601         UwbSession mockUwbSession = mock(UwbSession.class);
1602         when(mockUwbSession.getSessionId()).thenReturn(TEST_SESSION_ID);
1603         mUwbSessionManager.mSessionTable.put(mock(SessionHandle.class), mockUwbSession);
1604 
1605         Set<Integer> actualSessionIds = mUwbSessionManager.getSessionIdSet();
1606 
1607         assertThat(actualSessionIds).hasSize(1);
1608         assertThat(actualSessionIds.contains(TEST_SESSION_ID)).isTrue();
1609     }
1610 
1611     @Test
reconfigure_notExistedSession()1612     public void reconfigure_notExistedSession() {
1613         doReturn(false).when(mUwbSessionManager).isExistedSession(any());
1614 
1615         int actualStatus = mUwbSessionManager.reconfigure(
1616                 mock(SessionHandle.class), mock(Params.class));
1617 
1618         assertThat(actualStatus).isEqualTo(UwbUciConstants.STATUS_CODE_ERROR_SESSION_NOT_EXIST);
1619     }
1620 
setUpUwbSessionForExecution(AttributionSource attributionSource)1621     private UwbSession setUpUwbSessionForExecution(AttributionSource attributionSource) {
1622         return setUpUwbSessionForExecution(attributionSource, setupFiraParams());
1623     }
1624 
setUpUwbSessionForExecution(AttributionSource attributionSource, Params params)1625     private UwbSession setUpUwbSessionForExecution(AttributionSource attributionSource,
1626             Params params) {
1627         // setup message
1628         doReturn(0).when(mUwbSessionManager).getSessionCount();
1629         doReturn(0L).when(mUwbSessionManager).getFiraSessionCount();
1630         doReturn(false).when(mUwbSessionManager).isExistedSession(anyInt());
1631         IUwbRangingCallbacks mockRangingCallbacks = mock(IUwbRangingCallbacks.class);
1632         SessionHandle mockSessionHandle = mock(SessionHandle.class);
1633         IBinder mockBinder = mock(IBinder.class);
1634         byte sessionType = TEST_SESSION_TYPE;
1635         if (params.getProtocolName().equals(RadarParams.PROTOCOL_NAME)
1636                 && params instanceof RadarOpenSessionParams) {
1637             sessionType = (byte) RadarParams.SESSION_TYPE_RADAR;
1638         }
1639         UwbSession uwbSession = spy(
1640                 mUwbSessionManager.new UwbSession(attributionSource, mockSessionHandle,
1641                         TEST_SESSION_ID, sessionType, params.getProtocolName(), params,
1642                         mockRangingCallbacks, TEST_CHIP_ID));
1643         doReturn(mockBinder).when(uwbSession).getBinder();
1644         doReturn(uwbSession).when(mUwbSessionManager).createUwbSession(any(), any(), anyInt(),
1645                 anyByte(), anyString(), any(), any(), anyString());
1646         doReturn(mock(WaitObj.class)).when(uwbSession).getWaitObj();
1647 
1648         return uwbSession;
1649     }
1650 
setUpControlee(UwbSessionManager.UwbSession session, int macAddressingMode)1651     private UwbAddress setUpControlee(UwbSessionManager.UwbSession session,
1652                                       int macAddressingMode) {
1653         UwbAddress uwbAddress = (macAddressingMode == MAC_ADDRESSING_MODE_SHORT)
1654                 ? PEER_SHORT_UWB_ADDRESS : PEER_EXTENDED_UWB_ADDRESS;
1655 
1656         session.mMulticastRangingErrorStreakTimerListeners = spy(new ConcurrentHashMap<>());
1657         session.mControlees = spy(new ConcurrentHashMap<>());
1658         session.addControlee(uwbAddress);
1659         return uwbAddress;
1660     }
1661 
startRanging(UwbSession session)1662     private void startRanging(UwbSession session) {
1663         doReturn(UwbUciConstants.UWB_SESSION_STATE_IDLE, UwbUciConstants.UWB_SESSION_STATE_ACTIVE)
1664                 .when(session).getSessionState();
1665         when(mNativeUwbManager.startRanging(eq(TEST_SESSION_ID), anyString()))
1666                 .thenReturn((byte) UwbUciConstants.STATUS_CODE_OK);
1667 
1668         mUwbSessionManager.startRanging(
1669                 session.getSessionHandle(), session.getParams());
1670         mTestLooper.dispatchAll();
1671     }
1672 
setupFiraParams()1673     private Params setupFiraParams() {
1674         return setupFiraParams(FIRA_VERSION_2_0);
1675     }
1676 
setupFiraParams(FiraProtocolVersion firaProtocolVersion)1677     private Params setupFiraParams(FiraProtocolVersion firaProtocolVersion) {
1678         return setupFiraParams(
1679             FiraParams.RANGING_DEVICE_ROLE_INITIATOR,
1680             /* rangingRoundusageOptional = */ Optional.empty(),
1681             firaProtocolVersion);
1682     }
1683 
setupFiraParams( int deviceRole, Optional<Integer> rangingRoundUsageOptional)1684     private Params setupFiraParams(
1685             int deviceRole,
1686             Optional<Integer> rangingRoundUsageOptional) {
1687         return setupFiraParams(deviceRole, rangingRoundUsageOptional, FIRA_VERSION_1_0);
1688     }
1689 
setupFiraParams( int deviceRole, Optional<Integer> rangingRoundUsageOptional, FiraProtocolVersion firaProtocolVersion)1690     private Params setupFiraParams(
1691             int deviceRole,
1692             Optional<Integer> rangingRoundUsageOptional,
1693             FiraProtocolVersion firaProtocolVersion) {
1694         FiraOpenSessionParams.Builder paramsBuilder = new FiraOpenSessionParams.Builder()
1695                 .setDeviceAddress(UwbAddress.fromBytes(new byte[] {(byte) 0x01, (byte) 0x02 }))
1696                 .setVendorId(new byte[] { (byte) 0x00, (byte) 0x01 })
1697                 .setStaticStsIV(new byte[] { (byte) 0x01, (byte) 0x02, (byte) 0x03,
1698                         (byte) 0x04, (byte) 0x05, (byte) 0x06 })
1699                 .setDestAddressList(Arrays.asList(
1700                         UWB_DEST_ADDRESS))
1701                 .setProtocolVersion(firaProtocolVersion)
1702                 .setSessionId(10)
1703                 .setSessionType(SESSION_TYPE_RANGING)
1704                 .setDeviceType(FiraParams.RANGING_DEVICE_TYPE_CONTROLLER)
1705                 .setDeviceRole(deviceRole)
1706                 .setMultiNodeMode(FiraParams.MULTI_NODE_MODE_UNICAST)
1707                 .setRangingIntervalMs(TEST_RANGING_INTERVAL_MS);
1708 
1709         if (rangingRoundUsageOptional.isPresent()) {
1710             paramsBuilder.setRangingRoundUsage(rangingRoundUsageOptional.get());
1711         }
1712 
1713         return paramsBuilder.build();
1714     }
1715 
1716     // setup uwbsession with give sessionType
setUpUwbSessionForExecutionWithSessionType(byte sessionType, Params params)1717     private UwbSession setUpUwbSessionForExecutionWithSessionType(byte sessionType,
1718             Params params) {
1719         doReturn(0).when(mUwbSessionManager).getSessionCount();
1720         doReturn(0L).when(mUwbSessionManager).getFiraSessionCount();
1721         doReturn(false).when(mUwbSessionManager).isExistedSession(anyInt());
1722         IUwbRangingCallbacks mockRangingCallbacks = mock(IUwbRangingCallbacks.class);
1723         SessionHandle mockSessionHandle = mock(SessionHandle.class);
1724         IBinder mockBinder = mock(IBinder.class);
1725         UwbSession uwbSession = spy(
1726                 mUwbSessionManager.new UwbSession(ATTRIBUTION_SOURCE, mockSessionHandle,
1727                         TEST_SESSION_ID, sessionType, params.getProtocolName(), params,
1728                         mockRangingCallbacks, TEST_CHIP_ID));
1729         doReturn(mockBinder).when(uwbSession).getBinder();
1730         doReturn(uwbSession).when(mUwbSessionManager).createUwbSession(any(), any(), anyInt(),
1731                 anyByte(), anyString(), any(), any(), anyString());
1732         doReturn(mock(WaitObj.class)).when(uwbSession).getWaitObj();
1733 
1734         return uwbSession;
1735     }
1736 
setupRadarParams()1737     private Params setupRadarParams() {
1738         return new RadarOpenSessionParams.Builder()
1739                         .setSessionId(22)
1740                         .setBurstPeriod(100)
1741                         .setSweepPeriod(40)
1742                         .setSweepsPerBurst(16)
1743                         .setSamplesPerSweep(128)
1744                         .setChannelNumber(FiraParams.UWB_CHANNEL_5)
1745                         .setSweepOffset(-1)
1746                         .setRframeConfig(FiraParams.RFRAME_CONFIG_SP3)
1747                         .setPreambleDuration(RadarParams.PREAMBLE_DURATION_T16384_SYMBOLS)
1748                         .setPreambleCodeIndex(90)
1749                         .setSessionPriority(99)
1750                         .setBitsPerSample(RadarParams.BITS_PER_SAMPLES_32)
1751                         .setPrfMode(FiraParams.PRF_MODE_HPRF)
1752                         .setNumberOfBursts(1000)
1753                         .setRadarDataType(RadarParams.RADAR_DATA_TYPE_RADAR_SWEEP_SAMPLES)
1754                         .build();
1755     }
1756 
setUpCccUwbSessionForExecution(Params params)1757     private UwbSession setUpCccUwbSessionForExecution(Params params) throws RemoteException {
1758         // Setup message
1759         doReturn(0).when(mUwbSessionManager).getSessionCount();
1760         doReturn(0L).when(mUwbSessionManager).getCccSessionCount();
1761         doReturn(false).when(mUwbSessionManager).isExistedSession(anyInt());
1762         IUwbRangingCallbacks mockRangingCallbacks = mock(IUwbRangingCallbacks.class);
1763         SessionHandle mockSessionHandle = mock(SessionHandle.class);
1764         IBinder mockBinder = mock(IBinder.class);
1765         UwbSession uwbSession = spy(
1766                 mUwbSessionManager.new UwbSession(ATTRIBUTION_SOURCE, mockSessionHandle,
1767                         TEST_SESSION_ID, TEST_SESSION_TYPE, CccParams.PROTOCOL_NAME, params,
1768                         mockRangingCallbacks, TEST_CHIP_ID));
1769         doReturn(mockBinder).when(uwbSession).getBinder();
1770         doReturn(uwbSession).when(mUwbSessionManager).createUwbSession(any(), any(), anyInt(),
1771                 anyByte(), anyString(), any(), any(), anyString());
1772         doReturn(mock(WaitObj.class)).when(uwbSession).getWaitObj();
1773 
1774         return uwbSession;
1775     }
1776 
setUpAliroUwbSessionForExecution(Params params)1777     private UwbSession setUpAliroUwbSessionForExecution(Params params) throws RemoteException {
1778         // Setup message
1779         doReturn(0).when(mUwbSessionManager).getSessionCount();
1780         doReturn(0L).when(mUwbSessionManager).getAliroSessionCount();
1781         doReturn(false).when(mUwbSessionManager).isExistedSession(anyInt());
1782         IUwbRangingCallbacks mockRangingCallbacks = mock(IUwbRangingCallbacks.class);
1783         SessionHandle mockSessionHandle = mock(SessionHandle.class);
1784         IBinder mockBinder = mock(IBinder.class);
1785         UwbSession uwbSession = spy(
1786                 mUwbSessionManager.new UwbSession(ATTRIBUTION_SOURCE, mockSessionHandle,
1787                         TEST_SESSION_ID, TEST_SESSION_TYPE, AliroParams.PROTOCOL_NAME, params,
1788                         mockRangingCallbacks, TEST_CHIP_ID));
1789         doReturn(mockBinder).when(uwbSession).getBinder();
1790         doReturn(uwbSession).when(mUwbSessionManager).createUwbSession(any(), any(), anyInt(),
1791                 anyByte(), anyString(), any(), any(), anyString());
1792         doReturn(mock(WaitObj.class)).when(uwbSession).getWaitObj();
1793 
1794         return uwbSession;
1795     }
1796 
1797     // Test SESSION_INIT for a FiRa ranging session on a UWBS controller (UCI ver 1.1+).
1798     @Test
openRanging_success_fira_uwbs_v1_1()1799     public void openRanging_success_fira_uwbs_v1_1() throws Exception {
1800         UwbSession uwbSession = setUpUwbSessionForExecution(ATTRIBUTION_SOURCE);
1801         do_openRanging_success_absoluteInitiationTimeIsNotComputed(
1802                 FiraParams.PROTOCOL_NAME, uwbSession, UWB_DEVICE_INFO_RESPONSE_1_1,
1803                 FIRA_VERSION_1_1);
1804     }
1805 
1806     // Test SESSION_INIT for a CCC ranging session on a UWBS controller (UCI ver 1.1+).
1807     @Test
openRanging_success_ccc_uwbs_v1_1()1808     public void openRanging_success_ccc_uwbs_v1_1() throws Exception {
1809         UwbSession uwbSession = setUpCccUwbSessionForExecution(CCC_OPEN_RANGING_PARAMS_DEFAULT);
1810         do_openRanging_success_absoluteInitiationTimeIsNotComputed(
1811                 CccParams.PROTOCOL_NAME, uwbSession, UWB_DEVICE_INFO_RESPONSE_1_1,
1812                 FIRA_VERSION_1_1);
1813     }
1814 
1815     // Test SESSION_INIT for an ALIRO ranging session on a UWBS controller (UCI ver 1.1+).
1816     @Test
openRanging_success_aliro_uwbs_v1_1()1817     public void openRanging_success_aliro_uwbs_v1_1() throws Exception {
1818         UwbSession uwbSession = setUpAliroUwbSessionForExecution(ALIRO_OPEN_RANGING_PARAMS_DEFAULT);
1819         do_openRanging_success_absoluteInitiationTimeIsNotComputed(
1820                 AliroParams.PROTOCOL_NAME, uwbSession, UWB_DEVICE_INFO_RESPONSE_1_1,
1821                 FIRA_VERSION_1_1);
1822     }
1823 
1824     // Test SESSION_INIT for a CCC ranging session on a UWBS controller (UCI ver 2.0+). Currently,
1825     // we don't expect this to set the {@code CccOpenRangingParams.mAbsoluteInitiationTimeUs}
1826     // (at SESSION_INIT time), or, result in the UWBS_TIMESTAMP being fetched from the UWBS.
1827     @Test
openRanging_success_ccc_uwbs_v2_0_absoluteInitiationTimeComputationIsDisabled()1828     public void openRanging_success_ccc_uwbs_v2_0_absoluteInitiationTimeComputationIsDisabled()
1829             throws Exception {
1830         // Setup the flag to "false" (which is also the default value), so that absolute
1831         // UWB initiation time computation is disabled for a CCC ranging session.
1832         when(mDeviceConfigFacade.isCccAbsoluteUwbInitiationTimeEnabled()).thenReturn(false);
1833 
1834         CccOpenRangingParams params = CCC_OPEN_RANGING_PARAMS_DEFAULT.toBuilder()
1835                 .setInitiationTimeMs(1000)
1836                 .build();
1837         UwbSession uwbSession = setUpCccUwbSessionForExecution(params);
1838 
1839         do_openRanging_success_absoluteInitiationTimeIsNotComputed(
1840                 CccParams.PROTOCOL_NAME, uwbSession, UWB_DEVICE_INFO_RESPONSE_2_0,
1841                 FIRA_VERSION_2_0);
1842     }
1843 
1844     // Test SESSION_INIT for a ALIRO ranging session on a UWBS controller (UCI ver 2.0+). Currently,
1845     // we don't expect this to set the {@code AliroOpenRangingParams.mAbsoluteInitiationTimeUs}
1846     // (at SESSION_INIT time), or, result in the UWBS_TIMESTAMP being fetched from the UWBS.
1847     @Test
openRanging_success_aliro_uwbs_v2_0_absoluteInitiationTimeComputationIsDisabled()1848     public void openRanging_success_aliro_uwbs_v2_0_absoluteInitiationTimeComputationIsDisabled()
1849             throws Exception {
1850         // Setup the flag to "false" (which is also the default value), so that absolute
1851         // UWB initiation time computation is disabled for a CCC ranging session.
1852         when(mDeviceConfigFacade.isCccAbsoluteUwbInitiationTimeEnabled()).thenReturn(false);
1853 
1854         AliroOpenRangingParams params = ALIRO_OPEN_RANGING_PARAMS_DEFAULT.toBuilder()
1855                 .setInitiationTimeMs(1000)
1856                 .build();
1857         UwbSession uwbSession = setUpAliroUwbSessionForExecution(params);
1858 
1859         do_openRanging_success_absoluteInitiationTimeIsNotComputed(
1860                 AliroParams.PROTOCOL_NAME, uwbSession, UWB_DEVICE_INFO_RESPONSE_2_0,
1861                 FIRA_VERSION_2_0);
1862     }
1863 
1864     // Test SESSION_INIT for a CCC ranging session on a UWBS controller (UCI ver 2.0+). Currently,
1865     // we don't expect this to set the {@code CccOpenRangingParams.mAbsoluteInitiationTimeUs}
1866     // (at SESSION_INIT time), or, result in the UWBS_TIMESTAMP being fetched from the UWBS.
1867     @Test
openRanging_success_ccc_uwbs_v2_0_absoluteInitiationTimeComputationIsEnabled()1868     public void openRanging_success_ccc_uwbs_v2_0_absoluteInitiationTimeComputationIsEnabled()
1869             throws Exception {
1870         // Setup the flag to "true", so that absolute UWB initiation time computation
1871         // is enabled for a CCC ranging session.
1872         when(mDeviceConfigFacade.isCccAbsoluteUwbInitiationTimeEnabled()).thenReturn(true);
1873 
1874         UwbSession uwbSession = setUpCccUwbSessionForExecution(CCC_OPEN_RANGING_PARAMS_DEFAULT);
1875 
1876         do_openRanging_success_absoluteInitiationTimeIsNotComputed(
1877                 CccParams.PROTOCOL_NAME, uwbSession, UWB_DEVICE_INFO_RESPONSE_2_0,
1878                 FIRA_VERSION_2_0);
1879     }
1880 
1881     // Test SESSION_INIT for a ALIRO ranging session on a UWBS controller (UCI ver 2.0+). Currently,
1882     // we don't expect this to set the {@code AliroOpenRangingParams.mAbsoluteInitiationTimeUs}
1883     // (at SESSION_INIT time), or, result in the UWBS_TIMESTAMP being fetched from the UWBS.
1884     @Test
openRanging_success_aliro_uwbs_v2_0_absoluteInitiationTimeComputationIsEnabled()1885     public void openRanging_success_aliro_uwbs_v2_0_absoluteInitiationTimeComputationIsEnabled()
1886             throws Exception {
1887         // Setup the flag to "true", so that absolute UWB initiation time computation
1888         // is enabled for a ALIRO ranging session.
1889         when(mDeviceConfigFacade.isCccAbsoluteUwbInitiationTimeEnabled()).thenReturn(true);
1890 
1891         UwbSession uwbSession = setUpAliroUwbSessionForExecution(ALIRO_OPEN_RANGING_PARAMS_DEFAULT);
1892 
1893         do_openRanging_success_absoluteInitiationTimeIsNotComputed(
1894                 AliroParams.PROTOCOL_NAME, uwbSession, UWB_DEVICE_INFO_RESPONSE_2_0,
1895                 FIRA_VERSION_2_0);
1896     }
1897 
do_openRanging_success_absoluteInitiationTimeIsNotComputed( String protocolName, UwbSession uwbSession, UwbDeviceInfoResponse uwbDeviceInfoResponse, ProtocolVersion uwbsFiraVersion)1898     private void do_openRanging_success_absoluteInitiationTimeIsNotComputed(
1899             String protocolName, UwbSession uwbSession, UwbDeviceInfoResponse uwbDeviceInfoResponse,
1900             ProtocolVersion uwbsFiraVersion) throws Exception {
1901         // Setup the UWBS to return Fira UCI version as 2.0.
1902         when(mUwbServiceCore.getCachedDeviceInfoResponse(TEST_CHIP_ID)).thenReturn(
1903                 uwbDeviceInfoResponse);
1904 
1905         // Stub for openRanging conditions
1906         when(mNativeUwbManager.initSession(anyInt(), anyByte(), anyString()))
1907                 .thenReturn((byte) UwbUciConstants.STATUS_CODE_OK);
1908         doReturn(UwbUciConstants.UWB_SESSION_STATE_INIT,
1909                 UwbUciConstants.UWB_SESSION_STATE_IDLE).when(uwbSession).getSessionState();
1910         when(mUwbConfigurationManager.setAppConfigurations(anyInt(), any(), anyString(), any()))
1911                 .thenReturn(UwbUciConstants.STATUS_CODE_OK);
1912 
1913         mUwbSessionManager.initSession(ATTRIBUTION_SOURCE, uwbSession.getSessionHandle(),
1914                 TEST_SESSION_ID, TEST_SESSION_TYPE, protocolName,
1915                 uwbSession.getParams(), uwbSession.getIUwbRangingCallbacks(), TEST_CHIP_ID);
1916         mTestLooper.dispatchAll();
1917 
1918         // Verifications related to Open Ranging.
1919         verify(mNativeUwbManager).initSession(eq(TEST_SESSION_ID), anyByte(), eq(TEST_CHIP_ID));
1920         verify(mUwbConfigurationManager).setAppConfigurations(
1921                 eq(TEST_SESSION_ID), any(), eq(TEST_CHIP_ID), eq(uwbsFiraVersion));
1922         verify(mUwbSessionNotificationManager).onRangingOpened(eq(uwbSession));
1923         verify(mUwbMetrics).logRangingInitEvent(
1924                 eq(uwbSession), eq(UwbUciConstants.STATUS_CODE_OK));
1925 
1926         // Verify that queryUwbsTimestampMicros() is not called, as the "params" doesn't have the
1927         // "mInitiationTime" field set.
1928         verify(mUwbServiceCore, never()).queryUwbsTimestampMicros();
1929     }
1930 
1931     @Test
openRanging_success_Fira_2_0_absoluteInitiationTimeIsComputed()1932     public void openRanging_success_Fira_2_0_absoluteInitiationTimeIsComputed()
1933             throws Exception {
1934         // Set the InitationTime in the FiraOpenSessionParams.
1935         FiraOpenSessionParams firaParams = new
1936                 FiraOpenSessionParams.Builder(
1937                 (FiraOpenSessionParams) setupFiraParams(FIRA_VERSION_2_0))
1938                 .setInitiationTime(100L)
1939                 .build();
1940         UwbSession uwbSession = setUpUwbSessionForExecution(ATTRIBUTION_SOURCE, firaParams);
1941         do_openRanging_success_uwbs_2_0_absoluteInitiationTimeIsComputed(
1942                 FiraParams.PROTOCOL_NAME, uwbSession);
1943     }
1944 
1945     @Test
openRanging_success_Ccc_absoluteInitiationTimeIsComputed()1946     public void openRanging_success_Ccc_absoluteInitiationTimeIsComputed()
1947             throws Exception {
1948         // Setup the flag to "true", so that absolute UWB initiation time computation
1949         // is enabled for a CCC ranging session.
1950         when(mDeviceConfigFacade.isCccAbsoluteUwbInitiationTimeEnabled()).thenReturn(true);
1951 
1952         CccOpenRangingParams params = CCC_OPEN_RANGING_PARAMS_DEFAULT.toBuilder()
1953                 .setInitiationTimeMs(1000)
1954                 .build();
1955         UwbSession uwbSession = setUpCccUwbSessionForExecution(params);
1956 
1957         do_openRanging_success_uwbs_2_0_absoluteInitiationTimeIsComputed(
1958                 CccParams.PROTOCOL_NAME, uwbSession);
1959     }
1960 
1961     @Test
1962     public void
openRanging_success_Aliro_absoluteInitiationTimeIsComputed()1963             openRanging_success_Aliro_absoluteInitiationTimeIsComputed()
1964                     throws Exception {
1965         // Setup the flag to "true", so that absolute UWB initiation time computation
1966         // is enabled for a CCC ranging session.
1967         when(mDeviceConfigFacade.isCccAbsoluteUwbInitiationTimeEnabled()).thenReturn(true);
1968 
1969         AliroOpenRangingParams params = ALIRO_OPEN_RANGING_PARAMS_DEFAULT.toBuilder()
1970                 .setInitiationTimeMs(1000)
1971                 .build();
1972         UwbSession uwbSession = setUpAliroUwbSessionForExecution(params);
1973 
1974         do_openRanging_success_uwbs_2_0_absoluteInitiationTimeIsComputed(
1975                 AliroParams.PROTOCOL_NAME, uwbSession);
1976     }
1977 
1978     // Test SESSION_INIT for a Fira ranging session on a UWBS controller (UCI ver 2.0+). We expect
1979     // this to set the {@code FiraOpenSessionParams.mAbsoluteInitiationTime} (at SESSION_INIT time),
1980     // after fetching the UWBS_TIMESTAMP from the UWBS.
do_openRanging_success_uwbs_2_0_absoluteInitiationTimeIsComputed( String protocolName, UwbSession uwbSession)1981     private void do_openRanging_success_uwbs_2_0_absoluteInitiationTimeIsComputed(
1982             String protocolName, UwbSession uwbSession) throws Exception {
1983         // Setup the UWBS to return Fira UCI version as 2.0.
1984         when(mUwbServiceCore.getCachedDeviceInfoResponse(TEST_CHIP_ID)).thenReturn(
1985                 UWB_DEVICE_INFO_RESPONSE_2_0);
1986 
1987         // Stub for openRanging conditions
1988         when(mNativeUwbManager.initSession(anyInt(), anyByte(), anyString()))
1989                 .thenReturn((byte) UwbUciConstants.STATUS_CODE_OK);
1990         doReturn(UwbUciConstants.UWB_SESSION_STATE_INIT,
1991                 UwbUciConstants.UWB_SESSION_STATE_IDLE).when(uwbSession).getSessionState();
1992         when(mUwbConfigurationManager.setAppConfigurations(anyInt(), any(), anyString(), any()))
1993                 .thenReturn(UwbUciConstants.STATUS_CODE_OK);
1994 
1995         mUwbSessionManager.initSession(ATTRIBUTION_SOURCE, uwbSession.getSessionHandle(),
1996                 TEST_SESSION_ID, TEST_SESSION_TYPE, protocolName,
1997                 uwbSession.getParams(), uwbSession.getIUwbRangingCallbacks(), TEST_CHIP_ID);
1998         mTestLooper.dispatchAll();
1999 
2000         // Verifications related to CCC Open Ranging - we expect queryUwbsTimestampMicros()
2001         // to be called.
2002         verify(mNativeUwbManager).initSession(eq(TEST_SESSION_ID), anyByte(), eq(TEST_CHIP_ID));
2003         verify(mUwbServiceCore).queryUwbsTimestampMicros();
2004         verify(mUwbConfigurationManager).setAppConfigurations(
2005                 eq(TEST_SESSION_ID), any(), eq(TEST_CHIP_ID), eq(FIRA_VERSION_2_0));
2006         verify(mUwbSessionNotificationManager).onRangingOpened(eq(uwbSession));
2007         verify(mUwbMetrics).logRangingInitEvent(
2008                 eq(uwbSession), eq(UwbUciConstants.STATUS_CODE_OK));
2009     }
2010 
2011     @Test
openRanging_timeout()2012     public void openRanging_timeout() throws Exception {
2013         UwbSession uwbSession = setUpUwbSessionForExecution(ATTRIBUTION_SOURCE);
2014         // stub for openRanging conditions
2015         when(mNativeUwbManager.initSession(anyInt(), anyByte(), anyString()))
2016                 .thenThrow(new IllegalStateException());
2017         doReturn(UwbUciConstants.UWB_SESSION_STATE_INIT,
2018                 UwbUciConstants.UWB_SESSION_STATE_IDLE).when(uwbSession).getSessionState();
2019         when(mUwbConfigurationManager.setAppConfigurations(anyInt(), any(), anyString(), any()))
2020                 .thenReturn(UwbUciConstants.STATUS_CODE_OK);
2021 
2022 
2023         mUwbSessionManager.initSession(ATTRIBUTION_SOURCE, uwbSession.getSessionHandle(),
2024                 TEST_SESSION_ID, TEST_SESSION_TYPE, FiraParams.PROTOCOL_NAME,
2025                 uwbSession.getParams(), uwbSession.getIUwbRangingCallbacks(), TEST_CHIP_ID);
2026         mTestLooper.dispatchAll();
2027 
2028         verify(mUwbMetrics).logRangingInitEvent(eq(uwbSession),
2029                 eq(UwbUciConstants.STATUS_CODE_FAILED));
2030         verify(mUwbSessionNotificationManager)
2031                 .onRangingOpenFailed(eq(uwbSession), eq(UwbUciConstants.STATUS_CODE_FAILED));
2032         verify(mNativeUwbManager).deInitSession(eq(TEST_SESSION_ID), eq(TEST_CHIP_ID));
2033     }
2034 
2035     @Test
openRanging_nativeInitSessionFailed()2036     public void openRanging_nativeInitSessionFailed() throws Exception {
2037         UwbSession uwbSession = setUpUwbSessionForExecution(ATTRIBUTION_SOURCE);
2038         // stub for openRanging conditions
2039         when(mNativeUwbManager.initSession(anyInt(), anyByte(), anyString()))
2040                 .thenReturn((byte) UwbUciConstants.STATUS_CODE_FAILED);
2041         doReturn(UwbUciConstants.UWB_SESSION_STATE_INIT,
2042                 UwbUciConstants.UWB_SESSION_STATE_IDLE).when(uwbSession).getSessionState();
2043         when(mUwbConfigurationManager.setAppConfigurations(anyInt(), any(), anyString(), any()))
2044                 .thenReturn(UwbUciConstants.STATUS_CODE_OK);
2045 
2046 
2047         mUwbSessionManager.initSession(ATTRIBUTION_SOURCE, uwbSession.getSessionHandle(),
2048                 TEST_SESSION_ID, TEST_SESSION_TYPE, FiraParams.PROTOCOL_NAME,
2049                 uwbSession.getParams(), uwbSession.getIUwbRangingCallbacks(), TEST_CHIP_ID);
2050         mTestLooper.dispatchAll();
2051 
2052         verify(mUwbMetrics).logRangingInitEvent(eq(uwbSession),
2053                 eq(UwbUciConstants.STATUS_CODE_FAILED));
2054         verify(mUwbSessionNotificationManager)
2055                 .onRangingOpenFailed(eq(uwbSession), eq(UwbUciConstants.STATUS_CODE_FAILED));
2056         verify(mNativeUwbManager).deInitSession(eq(TEST_SESSION_ID), eq(TEST_CHIP_ID));
2057     }
2058 
2059     @Test
openRanging_setAppConfigurationFailed()2060     public void openRanging_setAppConfigurationFailed() throws Exception {
2061         UwbSession uwbSession = setUpUwbSessionForExecution(ATTRIBUTION_SOURCE);
2062         // stub for openRanging conditions
2063         when(mNativeUwbManager.initSession(anyInt(), anyByte(), anyString()))
2064                 .thenReturn((byte) UwbUciConstants.STATUS_CODE_OK);
2065         doReturn(UwbUciConstants.UWB_SESSION_STATE_INIT,
2066                 UwbUciConstants.UWB_SESSION_STATE_IDLE).when(uwbSession).getSessionState();
2067         when(mUwbConfigurationManager.setAppConfigurations(anyInt(), any(), anyString(), any()))
2068                 .thenReturn(UwbUciConstants.STATUS_CODE_FAILED);
2069 
2070 
2071         mUwbSessionManager.initSession(ATTRIBUTION_SOURCE, uwbSession.getSessionHandle(),
2072                 TEST_SESSION_ID, TEST_SESSION_TYPE, FiraParams.PROTOCOL_NAME,
2073                 uwbSession.getParams(), uwbSession.getIUwbRangingCallbacks(), TEST_CHIP_ID);
2074         mTestLooper.dispatchAll();
2075 
2076         verify(mUwbMetrics).logRangingInitEvent(eq(uwbSession),
2077                 eq(UwbUciConstants.STATUS_CODE_FAILED));
2078         verify(mUwbSessionNotificationManager)
2079                 .onRangingOpenFailed(eq(uwbSession), eq(UwbUciConstants.STATUS_CODE_FAILED));
2080         verify(mNativeUwbManager).deInitSession(eq(TEST_SESSION_ID), eq(TEST_CHIP_ID));
2081     }
2082 
2083     @Test
openRanging_wrongInitState()2084     public void openRanging_wrongInitState() throws Exception {
2085         UwbSession uwbSession = setUpUwbSessionForExecution(ATTRIBUTION_SOURCE);
2086         // stub for openRanging conditions
2087         when(mNativeUwbManager.initSession(anyInt(), anyByte(), anyString()))
2088                 .thenReturn((byte) UwbUciConstants.STATUS_CODE_OK);
2089         doReturn(UwbUciConstants.UWB_SESSION_STATE_ERROR,
2090                 UwbUciConstants.UWB_SESSION_STATE_IDLE).when(uwbSession).getSessionState();
2091         when(mUwbConfigurationManager.setAppConfigurations(anyInt(), any(), anyString(), any()))
2092                 .thenReturn(UwbUciConstants.STATUS_CODE_FAILED);
2093 
2094 
2095         mUwbSessionManager.initSession(ATTRIBUTION_SOURCE, uwbSession.getSessionHandle(),
2096                 TEST_SESSION_ID, TEST_SESSION_TYPE, FiraParams.PROTOCOL_NAME,
2097                 uwbSession.getParams(), uwbSession.getIUwbRangingCallbacks(), TEST_CHIP_ID);
2098         mTestLooper.dispatchAll();
2099 
2100         verify(mUwbMetrics).logRangingInitEvent(eq(uwbSession),
2101                 eq(UwbUciConstants.STATUS_CODE_FAILED));
2102         verify(mUwbSessionNotificationManager)
2103                 .onRangingOpenFailed(eq(uwbSession), eq(UwbUciConstants.STATUS_CODE_FAILED));
2104         verify(mNativeUwbManager).deInitSession(eq(TEST_SESSION_ID), eq(TEST_CHIP_ID));
2105     }
2106 
2107     @Test
openRanging_wrongIdleState()2108     public void openRanging_wrongIdleState() throws Exception {
2109         UwbSession uwbSession = setUpUwbSessionForExecution(ATTRIBUTION_SOURCE);
2110         // stub for openRanging conditions
2111         when(mNativeUwbManager.initSession(anyInt(), anyByte(), anyString()))
2112                 .thenReturn((byte) UwbUciConstants.STATUS_CODE_OK);
2113         doReturn(UwbUciConstants.UWB_SESSION_STATE_INIT,
2114                 UwbUciConstants.UWB_SESSION_STATE_ERROR).when(uwbSession).getSessionState();
2115         when(mUwbConfigurationManager.setAppConfigurations(anyInt(), any(), anyString(), any()))
2116                 .thenReturn(UwbUciConstants.STATUS_CODE_FAILED);
2117 
2118 
2119         mUwbSessionManager.initSession(ATTRIBUTION_SOURCE, uwbSession.getSessionHandle(),
2120                 TEST_SESSION_ID, TEST_SESSION_TYPE, FiraParams.PROTOCOL_NAME,
2121                 uwbSession.getParams(), uwbSession.getIUwbRangingCallbacks(), TEST_CHIP_ID);
2122         mTestLooper.dispatchAll();
2123 
2124         verify(mUwbMetrics).logRangingInitEvent(eq(uwbSession),
2125                 eq(UwbUciConstants.STATUS_CODE_FAILED));
2126         verify(mUwbSessionNotificationManager)
2127                 .onRangingOpenFailed(eq(uwbSession),
2128                         eq(UwbUciConstants.STATUS_CODE_FAILED));
2129         verify(mNativeUwbManager).deInitSession(eq(TEST_SESSION_ID), eq(TEST_CHIP_ID));
2130     }
2131 
2132     @Test
testInitSessionWithNonSystemAppInFg()2133     public void testInitSessionWithNonSystemAppInFg() throws Exception {
2134         when(mUwbInjector.isSystemApp(UID, PACKAGE_NAME)).thenReturn(false);
2135         when(mUwbInjector.isForegroundAppOrService(UID, PACKAGE_NAME)).thenReturn(true);
2136 
2137         UwbSession uwbSession = setUpUwbSessionForExecution(ATTRIBUTION_SOURCE);
2138         mUwbSessionManager.initSession(ATTRIBUTION_SOURCE, uwbSession.getSessionHandle(),
2139                 TEST_SESSION_ID, TEST_SESSION_TYPE, FiraParams.PROTOCOL_NAME,
2140                 uwbSession.getParams(), uwbSession.getIUwbRangingCallbacks(), TEST_CHIP_ID);
2141 
2142         // OPEN_RANGING message scheduled.
2143         assertThat(mTestLooper.nextMessage().what).isEqualTo(SESSION_OPEN_RANGING);
2144         assertThat(mTestLooper.isIdle()).isFalse();
2145     }
2146 
2147     @Test
testInitSessionWithNonSystemAppNotInFg()2148     public void testInitSessionWithNonSystemAppNotInFg() throws Exception {
2149         when(mUwbInjector.isSystemApp(UID, PACKAGE_NAME)).thenReturn(false);
2150         when(mUwbInjector.isForegroundAppOrService(UID, PACKAGE_NAME)).thenReturn(false);
2151 
2152         UwbSession uwbSession = setUpUwbSessionForExecution(ATTRIBUTION_SOURCE);
2153         mUwbSessionManager.initSession(ATTRIBUTION_SOURCE, uwbSession.getSessionHandle(),
2154                 TEST_SESSION_ID, TEST_SESSION_TYPE, FiraParams.PROTOCOL_NAME,
2155                 uwbSession.getParams(), uwbSession.getIUwbRangingCallbacks(), TEST_CHIP_ID);
2156 
2157         verify(uwbSession.getIUwbRangingCallbacks()).onRangingOpenFailed(
2158                 eq(uwbSession.getSessionHandle()), eq(StateChangeReason.SYSTEM_POLICY), any());
2159         // No OPEN_RANGING message scheduled.
2160         assertThat(mTestLooper.isIdle()).isFalse();
2161     }
2162 
2163     @Test
testInitSessionWithNonSystemAppNotInFg_WhenBgRangingEnabled()2164     public void testInitSessionWithNonSystemAppNotInFg_WhenBgRangingEnabled() throws Exception {
2165         when(mDeviceConfigFacade.isBackgroundRangingEnabled()).thenReturn(true);
2166         when(mUwbInjector.isSystemApp(UID, PACKAGE_NAME)).thenReturn(false);
2167         when(mUwbInjector.isForegroundAppOrService(UID, PACKAGE_NAME)).thenReturn(false);
2168 
2169         UwbSession uwbSession = setUpUwbSessionForExecution(ATTRIBUTION_SOURCE);
2170         mUwbSessionManager.initSession(ATTRIBUTION_SOURCE, uwbSession.getSessionHandle(),
2171                 TEST_SESSION_ID, TEST_SESSION_TYPE, FiraParams.PROTOCOL_NAME,
2172                 uwbSession.getParams(), uwbSession.getIUwbRangingCallbacks(), TEST_CHIP_ID);
2173 
2174         // OPEN_RANGING message scheduled.
2175         assertThat(mTestLooper.nextMessage().what).isEqualTo(SESSION_OPEN_RANGING);
2176         assertThat(mTestLooper.isIdle()).isFalse();
2177     }
2178 
setNextAttributionSource( @onNull AttributionSource.Builder builder, @Nullable AttributionSource nextAttributionSource)2179     private AttributionSource.Builder setNextAttributionSource(
2180             @NonNull AttributionSource.Builder builder,
2181             @Nullable AttributionSource nextAttributionSource) {
2182         if (isAtLeastV() && Flags.setNextAttributionSource()) {
2183             return builder.setNextAttributionSource(nextAttributionSource);
2184         } else {
2185             return builder.setNext(nextAttributionSource);
2186         }
2187     }
2188 
initUwbSessionForNonSystemAppInFgInChain()2189     private UwbSession initUwbSessionForNonSystemAppInFgInChain() throws Exception {
2190         when(mUwbInjector.isSystemApp(UID_2, PACKAGE_NAME_2)).thenReturn(false);
2191         when(mUwbInjector.isForegroundAppOrService(UID_2, PACKAGE_NAME_2))
2192                 .thenReturn(true);
2193 
2194         // simulate system app triggered the request on behalf of a fg app in fg.
2195         AttributionSource.Builder builder = new AttributionSource.Builder(UID)
2196                 .setPackageName(PACKAGE_NAME);
2197         builder = setNextAttributionSource(builder, new AttributionSource.Builder(UID_2)
2198                         .setPackageName(PACKAGE_NAME_2)
2199                         .build());
2200         AttributionSource attributionSource = builder.build();
2201 
2202         UwbSession uwbSession = setUpUwbSessionForExecution(attributionSource);
2203         mUwbSessionManager.initSession(attributionSource, uwbSession.getSessionHandle(),
2204                 TEST_SESSION_ID, TEST_SESSION_TYPE, FiraParams.PROTOCOL_NAME,
2205                 uwbSession.getParams(), uwbSession.getIUwbRangingCallbacks(), TEST_CHIP_ID);
2206         return uwbSession;
2207     }
2208 
initUwbSessionForNonSystemAppNotInFgInChain()2209     private UwbSession initUwbSessionForNonSystemAppNotInFgInChain() throws Exception {
2210         when(mUwbInjector.isSystemApp(UID_2, PACKAGE_NAME_2)).thenReturn(false);
2211         when(mUwbInjector.isForegroundAppOrService(UID_2, PACKAGE_NAME_2))
2212                 .thenReturn(false);
2213 
2214         // simulate system app triggered the request on behalf of a fg app in fg.
2215         AttributionSource attributionSource = new AttributionSource.Builder(UID)
2216                 .setPackageName(PACKAGE_NAME)
2217                 .setNext(new AttributionSource.Builder(UID_2)
2218                         .setPackageName(PACKAGE_NAME_2)
2219                         .build())
2220                 .build();
2221 
2222         UwbSession uwbSession = setUpUwbSessionForExecution(attributionSource);
2223         mUwbSessionManager.initSession(attributionSource, uwbSession.getSessionHandle(),
2224                 TEST_SESSION_ID, TEST_SESSION_TYPE, FiraParams.PROTOCOL_NAME,
2225                 uwbSession.getParams(), uwbSession.getIUwbRangingCallbacks(), TEST_CHIP_ID);
2226         return uwbSession;
2227     }
2228 
2229     @Test
testOpenRangingWithNonSystemAppInFgInChain()2230     public void testOpenRangingWithNonSystemAppInFgInChain() throws Exception {
2231         initUwbSessionForNonSystemAppInFgInChain();
2232 
2233         // OPEN_RANGING message scheduled.
2234         assertThat(mTestLooper.nextMessage().what).isEqualTo(SESSION_OPEN_RANGING);
2235         assertThat(mTestLooper.isIdle()).isFalse();
2236     }
2237 
2238     @Test
testOpenRangingWithNonSystemAppInFgInChain_MoveToBgAndStayThere()2239     public void testOpenRangingWithNonSystemAppInFgInChain_MoveToBgAndStayThere() throws Exception {
2240         UwbSession uwbSession = initUwbSessionForNonSystemAppInFgInChain();
2241 
2242         // Verify that an OPEN_RANGING message was scheduled.
2243         assertThat(mTestLooper.nextMessage().what).isEqualTo(SESSION_OPEN_RANGING);
2244 
2245         // Start Ranging
2246         when(mNativeUwbManager.startRanging(eq(TEST_SESSION_ID), anyString()))
2247                 .thenReturn((byte) UwbUciConstants.STATUS_CODE_OK);
2248         doReturn(UwbUciConstants.UWB_SESSION_STATE_IDLE,
2249                 UwbUciConstants.UWB_SESSION_STATE_ACTIVE).when(uwbSession).getSessionState();
2250         mUwbSessionManager.startRanging(
2251                 uwbSession.getSessionHandle(), uwbSession.getParams());
2252         mTestLooper.dispatchAll();
2253 
2254         verify(mUwbSessionNotificationManager).onRangingStarted(eq(uwbSession), any());
2255         verify(mUwbMetrics).longRangingStartEvent(
2256                 eq(uwbSession), eq(UwbUciConstants.STATUS_CODE_OK));
2257 
2258         // Move the non-privileged app to background, this should result in the session getting
2259         // reconfigured (to disable the ranging data notifications).
2260         mOnUidImportanceListenerArgumentCaptor.getValue().onUidImportance(
2261                 UID_2, IMPORTANCE_BACKGROUND);
2262         mTestLooper.dispatchAll();
2263         ArgumentCaptor<Params> paramsArgumentCaptor = ArgumentCaptor.forClass(Params.class);
2264         verify(mUwbConfigurationManager).setAppConfigurations(
2265                 eq(TEST_SESSION_ID), paramsArgumentCaptor.capture(), eq(TEST_CHIP_ID),
2266                 eq(FIRA_VERSION_1_1));
2267         FiraRangingReconfigureParams firaParams =
2268                 (FiraRangingReconfigureParams) paramsArgumentCaptor.getValue();
2269         assertThat(firaParams.getRangeDataNtfConfig()).isEqualTo(
2270                 FiraParams.RANGE_DATA_NTF_CONFIG_DISABLE);
2271         verify(mUwbSessionNotificationManager, never()).onRangingReconfigured(eq(uwbSession));
2272 
2273         // Verify the appropriate timer is setup.
2274         ArgumentCaptor<AlarmManager.OnAlarmListener> alarmListenerCaptor =
2275                 ArgumentCaptor.forClass(AlarmManager.OnAlarmListener.class);
2276         verify(mAlarmManager).setExact(
2277                 anyInt(), anyLong(), eq(UwbSession.NON_PRIVILEGED_BG_APP_TIMER_TAG),
2278                 alarmListenerCaptor.capture(), any());
2279         assertThat(alarmListenerCaptor.getValue()).isNotNull();
2280 
2281         // Now fire the timer callback.
2282         doReturn(UwbUciConstants.UWB_SESSION_STATE_ACTIVE,
2283                  UwbUciConstants.UWB_SESSION_STATE_IDLE).when(uwbSession).getSessionState();
2284         alarmListenerCaptor.getValue().onAlarm();
2285 
2286         // Expect session stop.
2287         mTestLooper.dispatchAll();
2288         verify(mUwbSessionNotificationManager).onRangingStoppedWithApiReasonCode(
2289                 eq(uwbSession), eq(RangingChangeReason.SYSTEM_POLICY), any());
2290         verify(mUwbMetrics).longRangingStopEvent(eq(uwbSession));
2291     }
2292 
2293     @Test
2294     public void
testOpenRangingWithNonSystemAppInFgInChain_MoveToBgAndStayThere_WhenBgRangingEnabled()2295             testOpenRangingWithNonSystemAppInFgInChain_MoveToBgAndStayThere_WhenBgRangingEnabled()
2296             throws Exception {
2297         when(mDeviceConfigFacade.isBackgroundRangingEnabled()).thenReturn(true);
2298         UwbSession uwbSession = initUwbSessionForNonSystemAppInFgInChain();
2299 
2300         // Verify that an OPEN_RANGING message was scheduled.
2301         assertThat(mTestLooper.nextMessage().what).isEqualTo(SESSION_OPEN_RANGING);
2302 
2303         // Start Ranging
2304         when(mNativeUwbManager.startRanging(eq(TEST_SESSION_ID), anyString()))
2305                 .thenReturn((byte) UwbUciConstants.STATUS_CODE_OK);
2306         doReturn(UwbUciConstants.UWB_SESSION_STATE_IDLE,
2307                 UwbUciConstants.UWB_SESSION_STATE_ACTIVE).when(uwbSession).getSessionState();
2308         mUwbSessionManager.startRanging(
2309                 uwbSession.getSessionHandle(), uwbSession.getParams());
2310         mTestLooper.dispatchAll();
2311 
2312         verify(mUwbSessionNotificationManager).onRangingStarted(eq(uwbSession), any());
2313         verify(mUwbMetrics).longRangingStartEvent(
2314                 eq(uwbSession), eq(UwbUciConstants.STATUS_CODE_OK));
2315 
2316         // Move the non-privileged app to background, this should result in the session getting
2317         // reconfigured (to disable the ranging data notifications).
2318         mOnUidImportanceListenerArgumentCaptor.getValue().onUidImportance(
2319                 UID_2, IMPORTANCE_BACKGROUND);
2320         mTestLooper.dispatchAll();
2321         ArgumentCaptor<Params> paramsArgumentCaptor = ArgumentCaptor.forClass(Params.class);
2322         verify(mUwbConfigurationManager).setAppConfigurations(
2323                 eq(TEST_SESSION_ID), paramsArgumentCaptor.capture(), eq(TEST_CHIP_ID),
2324                 eq(FIRA_VERSION_1_1));
2325         FiraRangingReconfigureParams firaParams =
2326                 (FiraRangingReconfigureParams) paramsArgumentCaptor.getValue();
2327         assertThat(firaParams.getRangeDataNtfConfig()).isEqualTo(
2328                 FiraParams.RANGE_DATA_NTF_CONFIG_DISABLE);
2329         verify(mUwbSessionNotificationManager, never()).onRangingReconfigured(eq(uwbSession));
2330 
2331         // Verify the timer is not setup.
2332         verify(mAlarmManager, never()).setExact(
2333                 anyInt(), anyLong(), eq(UwbSession.NON_PRIVILEGED_BG_APP_TIMER_TAG),
2334                 any(), any());
2335     }
2336 
2337     @Test
testOpenRangingWithNonSystemAppInFgInChain_StartInBg_WhenBgRangingEnabled()2338     public void testOpenRangingWithNonSystemAppInFgInChain_StartInBg_WhenBgRangingEnabled()
2339             throws Exception {
2340         when(mDeviceConfigFacade.isBackgroundRangingEnabled()).thenReturn(true);
2341         UwbSession uwbSession = initUwbSessionForNonSystemAppNotInFgInChain();
2342 
2343         // Verify that an OPEN_RANGING message was scheduled.
2344         assertThat(mTestLooper.nextMessage().what).isEqualTo(SESSION_OPEN_RANGING);
2345 
2346         // Start Ranging
2347         when(mNativeUwbManager.startRanging(eq(TEST_SESSION_ID), anyString()))
2348                 .thenReturn((byte) UwbUciConstants.STATUS_CODE_OK);
2349         doReturn(UwbUciConstants.UWB_SESSION_STATE_IDLE,
2350                 UwbUciConstants.UWB_SESSION_STATE_ACTIVE).when(uwbSession).getSessionState();
2351         mUwbSessionManager.startRanging(
2352                 uwbSession.getSessionHandle(), uwbSession.getParams());
2353         mTestLooper.dispatchAll();
2354 
2355         verify(mUwbSessionNotificationManager).onRangingStarted(eq(uwbSession), any());
2356         verify(mUwbMetrics).longRangingStartEvent(
2357                 eq(uwbSession), eq(UwbUciConstants.STATUS_CODE_OK));
2358 
2359         // Ensure that we reconfigure the session immediately to disable range data notifications.
2360         mTestLooper.dispatchAll();
2361         ArgumentCaptor<Params> paramsArgumentCaptor = ArgumentCaptor.forClass(Params.class);
2362         verify(mUwbConfigurationManager).setAppConfigurations(
2363                 eq(TEST_SESSION_ID), paramsArgumentCaptor.capture(), eq(TEST_CHIP_ID),
2364                 eq(FIRA_VERSION_1_1));
2365         FiraRangingReconfigureParams firaParams =
2366                 (FiraRangingReconfigureParams) paramsArgumentCaptor.getValue();
2367         assertThat(firaParams.getRangeDataNtfConfig()).isEqualTo(
2368                 FiraParams.RANGE_DATA_NTF_CONFIG_DISABLE);
2369         verify(mUwbSessionNotificationManager, never()).onRangingReconfigured(eq(uwbSession));
2370 
2371         // Verify the timer is not setup.
2372         verify(mAlarmManager, never()).setExact(
2373                 anyInt(), anyLong(), eq(UwbSession.NON_PRIVILEGED_BG_APP_TIMER_TAG),
2374                 any(), any());
2375     }
2376 
2377     @Test
testOpenRangingWithNonSystemAppInFgInChain_MoveToBgAndFg()2378     public void testOpenRangingWithNonSystemAppInFgInChain_MoveToBgAndFg() throws Exception {
2379         UwbSession uwbSession = initUwbSessionForNonSystemAppInFgInChain();
2380         // OPEN_RANGING message scheduled.
2381         assertThat(mTestLooper.nextMessage().what).isEqualTo(SESSION_OPEN_RANGING);
2382         mTestLooper.dispatchAll();
2383 
2384         // Move to background.
2385         mOnUidImportanceListenerArgumentCaptor.getValue().onUidImportance(
2386                 UID_2, IMPORTANCE_BACKGROUND);
2387         mTestLooper.dispatchAll();
2388         ArgumentCaptor<Params> paramsArgumentCaptor = ArgumentCaptor.forClass(Params.class);
2389         verify(mUwbConfigurationManager).setAppConfigurations(
2390                 eq(TEST_SESSION_ID), paramsArgumentCaptor.capture(), eq(TEST_CHIP_ID),
2391                 eq(FIRA_VERSION_1_1));
2392         FiraRangingReconfigureParams firaParams =
2393                 (FiraRangingReconfigureParams) paramsArgumentCaptor.getValue();
2394         assertThat(firaParams.getRangeDataNtfConfig()).isEqualTo(
2395                 FiraParams.RANGE_DATA_NTF_CONFIG_DISABLE);
2396         verify(mUwbSessionNotificationManager, never()).onRangingReconfigured(eq(uwbSession));
2397 
2398         // Move to foreground.
2399         mOnUidImportanceListenerArgumentCaptor.getValue().onUidImportance(
2400                 UID_2, IMPORTANCE_FOREGROUND);
2401         mTestLooper.dispatchAll();
2402         paramsArgumentCaptor = ArgumentCaptor.forClass(Params.class);
2403         verify(mUwbConfigurationManager, times(2)).setAppConfigurations(
2404                 eq(TEST_SESSION_ID), paramsArgumentCaptor.capture(), eq(TEST_CHIP_ID),
2405                 eq(FIRA_VERSION_1_1));
2406         firaParams = (FiraRangingReconfigureParams) paramsArgumentCaptor.getValue();
2407         assertThat(firaParams.getRangeDataNtfConfig()).isEqualTo(
2408                 FiraParams.RANGE_DATA_NTF_CONFIG_ENABLE);
2409         verify(mUwbSessionNotificationManager, never()).onRangingReconfigured(eq(uwbSession));
2410     }
2411 
2412     @Test
testOpenRangingWithNonSystemAppInFgInChain_MoveToBgTriggersSessionPriorityChange()2413     public void testOpenRangingWithNonSystemAppInFgInChain_MoveToBgTriggersSessionPriorityChange()
2414             throws Exception {
2415         UwbSession uwbSession = initUwbSessionForNonSystemAppInFgInChain();
2416 
2417         assertThat(uwbSession.getStackSessionPriority()).isEqualTo(UwbSession.FG_SESSION_PRIORITY);
2418         assertThat(mTestLooper.nextMessage().what).isEqualTo(SESSION_OPEN_RANGING);
2419         mTestLooper.dispatchAll();
2420 
2421         // Move to background.
2422         when(mUwbInjector.isForegroundAppOrService(UID_2, PACKAGE_NAME_2))
2423                 .thenReturn(false);
2424         mOnUidImportanceListenerArgumentCaptor.getValue().onUidImportance(
2425                 UID_2, ActivityManager.RunningAppProcessInfo.IMPORTANCE_CACHED);
2426         mTestLooper.dispatchAll();
2427 
2428         assertThat(uwbSession.getStackSessionPriority()).isEqualTo(UwbSession.BG_SESSION_PRIORITY);
2429     }
2430 
2431     @Test
testOpenRangingWithNonSystemAppNotInFgInChain()2432     public void testOpenRangingWithNonSystemAppNotInFgInChain() throws Exception {
2433         when(mUwbInjector.isSystemApp(UID_2, PACKAGE_NAME_2)).thenReturn(false);
2434         when(mUwbInjector.isForegroundAppOrService(UID_2, PACKAGE_NAME_2))
2435                 .thenReturn(false);
2436 
2437         // simulate system app triggered the request on behalf of a fg app not in fg.
2438         AttributionSource.Builder builder = new AttributionSource.Builder(UID)
2439                 .setPackageName(PACKAGE_NAME);
2440         builder = setNextAttributionSource(builder, new AttributionSource.Builder(UID_2)
2441                         .setPackageName(PACKAGE_NAME_2)
2442                         .build());
2443         AttributionSource attributionSource = builder.build();
2444         UwbSession uwbSession = setUpUwbSessionForExecution(attributionSource);
2445         mUwbSessionManager.initSession(attributionSource, uwbSession.getSessionHandle(),
2446                 TEST_SESSION_ID, TEST_SESSION_TYPE, FiraParams.PROTOCOL_NAME,
2447                 uwbSession.getParams(), uwbSession.getIUwbRangingCallbacks(), TEST_CHIP_ID);
2448 
2449         verify(uwbSession.getIUwbRangingCallbacks()).onRangingOpenFailed(
2450                 eq(uwbSession.getSessionHandle()), eq(StateChangeReason.SYSTEM_POLICY), any());
2451         // No OPEN_RANGING message scheduled.
2452         assertThat(mTestLooper.isIdle()).isFalse();
2453     }
2454 
prepareExistingUwbSessionCommon(UwbSession uwbSession)2455     private UwbSession prepareExistingUwbSessionCommon(UwbSession uwbSession) throws Exception {
2456         mUwbSessionManager.initSession(
2457                 ATTRIBUTION_SOURCE, uwbSession.getSessionHandle(), uwbSession.getSessionId(),
2458                 uwbSession.getSessionType(), uwbSession.getProtocolName(), uwbSession.getParams(),
2459                 uwbSession.getIUwbRangingCallbacks(), uwbSession.getChipId());
2460         mTestLooper.nextMessage(); // remove the OPEN_RANGING msg;
2461 
2462         assertThat(mTestLooper.isIdle()).isFalse();
2463 
2464         return uwbSession;
2465     }
prepareExistingUwbSession(Params params)2466     private UwbSession prepareExistingUwbSession(Params params) throws Exception {
2467         UwbSession uwbSession = setUpUwbSessionForExecution(ATTRIBUTION_SOURCE, params);
2468         return prepareExistingUwbSessionCommon(uwbSession);
2469     }
prepareExistingUwbSession()2470     private UwbSession prepareExistingUwbSession() throws Exception {
2471         UwbSession uwbSession = setUpUwbSessionForExecution(ATTRIBUTION_SOURCE);
2472         return prepareExistingUwbSessionCommon(uwbSession);
2473     }
2474 
prepareExistingUwbSessionActive(Params params)2475     private UwbSession prepareExistingUwbSessionActive(Params params) throws Exception {
2476         UwbSession uwbSession = setUpUwbSessionForExecution(ATTRIBUTION_SOURCE, params);
2477         uwbSession = prepareExistingUwbSessionCommon(uwbSession);
2478         return prepareExistingUwbSessionActiveCommon(uwbSession);
2479     }
2480 
prepareExistingUwbSessionActive()2481     private UwbSession prepareExistingUwbSessionActive() throws Exception {
2482         UwbSession uwbSession = setUpUwbSessionForExecution(ATTRIBUTION_SOURCE);
2483         uwbSession = prepareExistingUwbSessionCommon(uwbSession);
2484         return prepareExistingUwbSessionActiveCommon(uwbSession);
2485     }
2486 
prepareExistingUwbSessionActiveCommon(UwbSession uwbSession)2487     private UwbSession prepareExistingUwbSessionActiveCommon(UwbSession uwbSession)
2488             throws Exception {
2489         // Setup the UwbSession to start ranging (and move it to active state).
2490         doReturn(UwbUciConstants.UWB_SESSION_STATE_IDLE).when(uwbSession).getSessionState();
2491         when(mNativeUwbManager.startRanging(eq(TEST_SESSION_ID), anyString()))
2492                 .thenReturn((byte) UwbUciConstants.STATUS_CODE_OK);
2493 
2494         mUwbSessionManager.startRanging(uwbSession.getSessionHandle(), uwbSession.getParams());
2495         mTestLooper.dispatchAll();
2496         doReturn(UwbUciConstants.UWB_SESSION_STATE_ACTIVE).when(uwbSession).getSessionState();
2497 
2498         return uwbSession;
2499     }
2500 
prepareExistingCccUwbSession()2501     private UwbSession prepareExistingCccUwbSession() throws Exception {
2502         UwbSession uwbSession = setUpCccUwbSessionForExecution(CCC_OPEN_RANGING_PARAMS_DEFAULT);
2503         mUwbSessionManager.initSession(ATTRIBUTION_SOURCE, uwbSession.getSessionHandle(),
2504                 TEST_SESSION_ID, TEST_SESSION_TYPE, CccParams.PROTOCOL_NAME,
2505                 uwbSession.getParams(), uwbSession.getIUwbRangingCallbacks(), TEST_CHIP_ID);
2506         mTestLooper.nextMessage(); // remove the OPEN_RANGING msg;
2507 
2508         assertThat(mTestLooper.isIdle()).isFalse();
2509 
2510         return uwbSession;
2511     }
2512 
prepareExistingAliroUwbSession()2513     private UwbSession prepareExistingAliroUwbSession() throws Exception {
2514         UwbSession uwbSession = setUpAliroUwbSessionForExecution(ALIRO_OPEN_RANGING_PARAMS_DEFAULT);
2515         mUwbSessionManager.initSession(ATTRIBUTION_SOURCE, uwbSession.getSessionHandle(),
2516                 TEST_SESSION_ID, TEST_SESSION_TYPE, AliroParams.PROTOCOL_NAME,
2517                 uwbSession.getParams(), uwbSession.getIUwbRangingCallbacks(), TEST_CHIP_ID);
2518         mTestLooper.nextMessage(); // remove the OPEN_RANGING msg;
2519 
2520         assertThat(mTestLooper.isIdle()).isFalse();
2521 
2522         return uwbSession;
2523     }
2524 
prepareExistingUwbSessionWithSessionType(byte sessionType, Params params)2525     private UwbSession prepareExistingUwbSessionWithSessionType(byte sessionType, Params params)
2526                 throws Exception {
2527         UwbSession uwbSession = setUpUwbSessionForExecutionWithSessionType(sessionType, params);
2528         return prepareExistingUwbSessionCommon(uwbSession);
2529     }
2530 
2531     @Test
reconfigure_calledSuccess()2532     public void reconfigure_calledSuccess() throws Exception {
2533         UwbSession uwbSession = prepareExistingUwbSession();
2534         FiraRangingReconfigureParams params =
2535                 new FiraRangingReconfigureParams.Builder()
2536                         .setBlockStrideLength(10)
2537                         .setRangeDataNtfConfig(1)
2538                         .setRangeDataProximityFar(10)
2539                         .setRangeDataProximityNear(2)
2540                         .build();
2541 
2542         int actualStatus = mUwbSessionManager.reconfigure(uwbSession.getSessionHandle(), params);
2543 
2544         assertThat(actualStatus).isEqualTo(0);
2545         assertThat(mTestLooper.nextMessage().what)
2546                 .isEqualTo(UwbSessionManager.SESSION_RECONFIG_RANGING);
2547 
2548         // Verify the cache has been updated.
2549         FiraOpenSessionParams firaParams = (FiraOpenSessionParams) uwbSession.getParams();
2550         assertThat(firaParams.getBlockStrideLength()).isEqualTo(10);
2551         assertThat(firaParams.getRangeDataNtfConfig()).isEqualTo(1);
2552         assertThat(firaParams.getRangeDataNtfProximityFar()).isEqualTo(10);
2553         assertThat(firaParams.getRangeDataNtfProximityNear()).isEqualTo(2);
2554     }
2555 
2556     @Test
startRanging_sessionStateIdle()2557     public void startRanging_sessionStateIdle() throws Exception {
2558         UwbSession uwbSession = prepareExistingUwbSession();
2559         // set up for start ranging
2560         doReturn(UwbUciConstants.UWB_SESSION_STATE_IDLE)
2561                 .when(uwbSession).getSessionState();
2562 
2563         mUwbSessionManager.startRanging(
2564                 uwbSession.getSessionHandle(), uwbSession.getParams());
2565 
2566         assertThat(mTestLooper.isIdle()).isTrue();
2567         assertThat(mTestLooper.nextMessage().what).isEqualTo(2); // SESSION_START_RANGING
2568     }
2569 
2570     @Test
startRanging_sessionStateActive()2571     public void startRanging_sessionStateActive() throws Exception {
2572         UwbSession uwbSession = prepareExistingUwbSession();
2573         // set up for start ranging
2574         doReturn(UwbUciConstants.UWB_SESSION_STATE_ACTIVE)
2575                 .when(uwbSession).getSessionState();
2576 
2577         mUwbSessionManager.startRanging(
2578                 uwbSession.getSessionHandle(), uwbSession.getParams());
2579 
2580         assertThat(mTestLooper.isIdle()).isFalse();
2581         verify(mUwbSessionNotificationManager).onRangingStartFailed(
2582                 eq(uwbSession), eq(UwbUciConstants.STATUS_CODE_REJECTED));
2583     }
2584 
2585     @Test
startRanging_sessionStateError()2586     public void startRanging_sessionStateError() throws Exception {
2587         UwbSession uwbSession = prepareExistingUwbSession();
2588         // set up for start ranging
2589         doReturn(UwbUciConstants.UWB_SESSION_STATE_ERROR)
2590                 .when(uwbSession).getSessionState();
2591 
2592         mUwbSessionManager.startRanging(
2593                 uwbSession.getSessionHandle(), uwbSession.getParams());
2594 
2595         assertThat(mTestLooper.isIdle()).isFalse();
2596         verify(mUwbSessionNotificationManager).onRangingStartFailed(
2597                 eq(uwbSession), eq(UwbUciConstants.STATUS_CODE_FAILED));
2598         verify(mUwbMetrics).longRangingStartEvent(
2599                 eq(uwbSession), eq(UwbUciConstants.STATUS_CODE_FAILED));
2600     }
2601 
2602     @Test
execStartRanging_success_fira_1_x_relativeUwbInitiationTime()2603     public void execStartRanging_success_fira_1_x_relativeUwbInitiationTime() throws Exception {
2604         FiraProtocolVersion protocolVersion = new FiraProtocolVersion(1, 1);
2605         Params startRangingParams = setupFiraParams(protocolVersion);
2606         UwbSession uwbSession = prepareExistingUwbSession();
2607 
2608         do_execStartRanging_success_uwbs_1_x_relativeUwbInitiationTime(
2609                 uwbSession, startRangingParams, /* rangingStartedParams = */ null, protocolVersion);
2610 
2611         verify(mUwbSessionNotificationManager).onRangingStarted(eq(uwbSession), any());
2612         verify(mUwbMetrics).longRangingStartEvent(
2613                 eq(uwbSession), eq(UwbUciConstants.STATUS_CODE_OK));
2614 
2615         // Verify that setAppConfigurations() is not called for a Fira ranging session, as the
2616         // "params.mInitiationTime" field is not set, and so no re-configuration is needed
2617         // before the UWB ranging is started.
2618         verify(mUwbConfigurationManager, never()).setAppConfigurations(
2619                 anyInt(), any(), any(), eq(FIRA_VERSION_1_1));
2620     }
2621 
2622     @Test
execStartRanging_success_ccc_1_x_relativeUwbInitiationTime()2623     public void execStartRanging_success_ccc_1_x_relativeUwbInitiationTime() throws Exception {
2624         UwbSession uwbSession = prepareExistingCccUwbSession();
2625         CccStartRangingParams cccStartRangingParams = new CccStartRangingParams.Builder()
2626                 .setSessionId(TEST_SESSION_ID)
2627                 .setRanMultiplier(4)
2628                 .build();
2629         CccRangingStartedParams cccRangingStartedParams = new CccRangingStartedParams.Builder()
2630                 .setStartingStsIndex(0)
2631                 .setUwbTime0(1)
2632                 .setHopModeKey(0)
2633                 .setSyncCodeIndex(1)
2634                 .setRanMultiplier(4)
2635                 .build();
2636 
2637         do_execStartRanging_success_uwbs_1_x_relativeUwbInitiationTime(
2638                 uwbSession, cccStartRangingParams, cccRangingStartedParams,
2639                 CccParams.PROTOCOL_VERSION_1_0);
2640 
2641         // Verify the absolute UWB initiation time is not set in the CccOpenRangingParams.
2642         CccOpenRangingParams cccOpenRangingParams = (CccOpenRangingParams) uwbSession.getParams();
2643         assertThat(cccOpenRangingParams.getAbsoluteInitiationTimeUs()).isEqualTo(0);
2644     }
2645 
2646     @Test
execStartRanging_success_aliro_1_x_relativeUwbInitiationTime()2647     public void execStartRanging_success_aliro_1_x_relativeUwbInitiationTime() throws Exception {
2648         UwbSession uwbSession = prepareExistingAliroUwbSession();
2649         AliroStartRangingParams aliroStartRangingParams = new AliroStartRangingParams.Builder()
2650                 .setSessionId(TEST_SESSION_ID)
2651                 .setRanMultiplier(4)
2652                 .build();
2653         AliroRangingStartedParams aliroRangingStartedParams =
2654                 new AliroRangingStartedParams.Builder()
2655                         .setStartingStsIndex(0)
2656                         .setUwbTime0(1)
2657                         .setHopModeKey(0)
2658                         .setSyncCodeIndex(1)
2659                         .setRanMultiplier(4)
2660                         .build();
2661 
2662         do_execStartRanging_success_uwbs_1_x_relativeUwbInitiationTime(
2663                 uwbSession, aliroStartRangingParams, aliroRangingStartedParams,
2664                 AliroParams.PROTOCOL_VERSION_1_0);
2665 
2666         // Verify the absolute UWB initiation time is not set in the AliroOpenRangingParams.
2667         AliroOpenRangingParams aliroOpenRangingParams =
2668                 (AliroOpenRangingParams) uwbSession.getParams();
2669         assertThat(aliroOpenRangingParams.getAbsoluteInitiationTimeUs()).isEqualTo(0);
2670     }
2671 
do_execStartRanging_success_uwbs_1_x_relativeUwbInitiationTime( UwbSession uwbSession, Params startRangingParams, Params rangingStartedParams, ProtocolVersion protocolVersion)2672     private void do_execStartRanging_success_uwbs_1_x_relativeUwbInitiationTime(
2673             UwbSession uwbSession, Params startRangingParams, Params rangingStartedParams,
2674             ProtocolVersion protocolVersion) throws Exception {
2675         // Setup the UWBS to return Fira version as 1.1.
2676         when(mUwbServiceCore.getCachedDeviceInfoResponse(TEST_CHIP_ID)).thenReturn(
2677                 UWB_DEVICE_INFO_RESPONSE_1_1);
2678 
2679         // set up for start ranging
2680         doReturn(UwbUciConstants.UWB_SESSION_STATE_IDLE, UwbUciConstants.UWB_SESSION_STATE_ACTIVE)
2681                 .when(uwbSession).getSessionState();
2682         when(mNativeUwbManager.startRanging(eq(TEST_SESSION_ID), anyString()))
2683                 .thenReturn((byte) UwbUciConstants.STATUS_CODE_OK);
2684         when(mUwbConfigurationManager.getAppConfigurations(
2685                 eq(TEST_SESSION_ID), anyString(), any(), any(), eq(TEST_CHIP_ID),
2686                 eq(protocolVersion)))
2687                 .thenReturn(new Pair<>(UwbUciConstants.STATUS_CODE_OK, rangingStartedParams));
2688 
2689         // Start ranging on the UWB session
2690         mUwbSessionManager.startRanging(uwbSession.getSessionHandle(), startRangingParams);
2691         mTestLooper.dispatchAll();
2692 
2693         // Verify that the ranging started successfully.
2694         verify(mNativeUwbManager).startRanging(eq(TEST_SESSION_ID), anyString());
2695         verify(mUwbSessionNotificationManager).onRangingStarted(eq(uwbSession), any());
2696         verify(mUwbMetrics).longRangingStartEvent(
2697                 eq(uwbSession), eq(UwbUciConstants.STATUS_CODE_OK));
2698 
2699         // Verify that queryUwbsTimestampMicros() is not called for FiRa 1.x.
2700         verify(mUwbServiceCore, never()).queryUwbsTimestampMicros();
2701     }
2702 
2703     @Test
execStartRanging_success_fira_2_0_noUwbInitiationTimeConfigured()2704     public void execStartRanging_success_fira_2_0_noUwbInitiationTimeConfigured()
2705             throws Exception {
2706         Params firaParams = setupFiraParams(FIRA_VERSION_2_0);
2707         UwbSession uwbSession = prepareExistingUwbSession(firaParams);
2708 
2709         do_execStartRanging_success_uwbs_2_0_noUwbInitiationTimeConfigured(
2710                 uwbSession,
2711                 /* startRangingParams = */ firaParams,
2712                 /* rangingStartedParams = */ firaParams,
2713                 FIRA_VERSION_2_0);
2714 
2715         // Verify that setAppConfigurations() is not called, as the "params.mInitiationTime" field
2716         // is not set, and so no re-configuration is needed for a Fira session, before the
2717         // UWB ranging is started.
2718         verify(mUwbConfigurationManager, never()).setAppConfigurations(
2719                 anyInt(), any(), any(), eq(FIRA_VERSION_2_0));
2720     }
2721 
2722     @Test
execStartRanging_success_ccc_2_0_noUwbInitiationTimeConfigured()2723     public void execStartRanging_success_ccc_2_0_noUwbInitiationTimeConfigured()
2724             throws Exception {
2725         UwbSession uwbSession = prepareExistingCccUwbSession();
2726         Params startRangingParams = new CccStartRangingParams.Builder()
2727                 .setSessionId(TEST_SESSION_ID)
2728                 .setRanMultiplier(4)
2729                 .build();
2730         CccRangingStartedParams rangingStartedParams = new CccRangingStartedParams.Builder()
2731                 .setStartingStsIndex(0)
2732                 .setUwbTime0(1)
2733                 .setHopModeKey(0)
2734                 .setSyncCodeIndex(1)
2735                 .setRanMultiplier(4)
2736                 .build();
2737 
2738         do_execStartRanging_success_uwbs_2_0_noUwbInitiationTimeConfigured(
2739                 uwbSession, startRangingParams, rangingStartedParams,
2740                 CccParams.PROTOCOL_VERSION_1_0);
2741     }
2742 
2743     @Test
execStartRanging_success_aliro_2_0_noUwbInitiationTimeConfigured()2744     public void execStartRanging_success_aliro_2_0_noUwbInitiationTimeConfigured()
2745             throws Exception {
2746         UwbSession uwbSession = prepareExistingAliroUwbSession();
2747         Params startRangingParams = new AliroStartRangingParams.Builder()
2748                 .setSessionId(TEST_SESSION_ID)
2749                 .setRanMultiplier(4)
2750                 .build();
2751         AliroRangingStartedParams rangingStartedParams = new AliroRangingStartedParams.Builder()
2752                 .setStartingStsIndex(0)
2753                 .setUwbTime0(1)
2754                 .setHopModeKey(0)
2755                 .setSyncCodeIndex(1)
2756                 .setRanMultiplier(4)
2757                 .build();
2758 
2759         do_execStartRanging_success_uwbs_2_0_noUwbInitiationTimeConfigured(
2760                 uwbSession, startRangingParams, rangingStartedParams,
2761                 AliroParams.PROTOCOL_VERSION_1_0);
2762     }
2763 
2764     // Test UWB StartRanging on a Fira UCI version 2.0+ device, when the App doesn't configure
2765     // any UWB initiation time (relative or absolute). In this case, the UwbSessionManager is not
2766     // expected to query the UWBS timestamp.
do_execStartRanging_success_uwbs_2_0_noUwbInitiationTimeConfigured( UwbSession uwbSession, Params startRangingParams, Params rangingStartedParams, ProtocolVersion protocolVersion)2767     private void do_execStartRanging_success_uwbs_2_0_noUwbInitiationTimeConfigured(
2768             UwbSession uwbSession, Params startRangingParams, Params rangingStartedParams,
2769             ProtocolVersion protocolVersion)
2770             throws Exception {
2771         // Setup the UWBS to return Fira UCI version as 2.0.
2772         when(mUwbServiceCore.getCachedDeviceInfoResponse(TEST_CHIP_ID)).thenReturn(
2773                 UWB_DEVICE_INFO_RESPONSE_2_0);
2774 
2775         // Setup for start ranging.
2776         doReturn(UwbUciConstants.UWB_SESSION_STATE_IDLE, UwbUciConstants.UWB_SESSION_STATE_ACTIVE)
2777                 .when(uwbSession).getSessionState();
2778         when(mNativeUwbManager.startRanging(eq(TEST_SESSION_ID), anyString()))
2779                 .thenReturn((byte) UwbUciConstants.STATUS_CODE_OK);
2780         when(mUwbConfigurationManager.setAppConfigurations(anyInt(), any(), anyString(), any()))
2781                 .thenReturn(UwbUciConstants.STATUS_CODE_OK);
2782         when(mUwbConfigurationManager.getAppConfigurations(
2783                 eq(TEST_SESSION_ID), anyString(), any(), any(), eq(TEST_CHIP_ID),
2784                 eq(protocolVersion)))
2785                 .thenReturn(new Pair<>(UwbUciConstants.STATUS_CODE_OK, rangingStartedParams));
2786 
2787         mUwbSessionManager.startRanging(uwbSession.getSessionHandle(), startRangingParams);
2788         mTestLooper.dispatchAll();
2789 
2790         // Verify that the UWB ranging successfully started.
2791         verify(mNativeUwbManager).startRanging(eq(TEST_SESSION_ID), anyString());
2792         verify(mUwbSessionNotificationManager).onRangingStarted(eq(uwbSession), any());
2793         verify(mUwbMetrics).longRangingStartEvent(
2794                 eq(uwbSession), eq(UwbUciConstants.STATUS_CODE_OK));
2795 
2796         // Verify that queryUwbsTimestampMicros() is not called.
2797         verify(mUwbServiceCore, never()).queryUwbsTimestampMicros();
2798     }
2799 
2800     @Test
execStartRanging_success_fira_2_0_absoluteUwbInitiationTimeIsComputed()2801     public void execStartRanging_success_fira_2_0_absoluteUwbInitiationTimeIsComputed()
2802             throws Exception {
2803         // Setup the UWBS to return Fira UCI version as 2.0.
2804         when(mUwbServiceCore.getCachedDeviceInfoResponse(TEST_CHIP_ID)).thenReturn(
2805                 UWB_DEVICE_INFO_RESPONSE_2_0);
2806 
2807         // Setup the AbsoluteInitationTime in the FiraOpenSessionParams.
2808         Params params = setupFiraParams(FIRA_VERSION_2_0);
2809         FiraOpenSessionParams firaParams = new
2810                 FiraOpenSessionParams.Builder((FiraOpenSessionParams) params)
2811                         .setInitiationTime(100L)
2812                         .build();
2813         UwbSession uwbSession = prepareExistingUwbSession(firaParams);
2814 
2815         // Setup for start ranging.
2816         doReturn(UwbUciConstants.UWB_SESSION_STATE_IDLE, UwbUciConstants.UWB_SESSION_STATE_ACTIVE)
2817                 .when(uwbSession).getSessionState();
2818         when(mNativeUwbManager.startRanging(eq(TEST_SESSION_ID), anyString()))
2819                 .thenReturn((byte) UwbUciConstants.STATUS_CODE_OK);
2820         when(mUwbServiceCore.queryUwbsTimestampMicros()).thenReturn(UWBS_TIMESTAMP);
2821         when(mUwbConfigurationManager.setAppConfigurations(anyInt(), any(), anyString(), any()))
2822                 .thenReturn(UwbUciConstants.STATUS_CODE_OK);
2823 
2824         mUwbSessionManager.startRanging(uwbSession.getSessionHandle(), params);
2825         mTestLooper.dispatchAll();
2826 
2827         // Verify that queryUwbsTimestampMicros() is called. Currently unable to verify that the
2828         // FiraOpenSessionParams is changed and the absoluteInitiationTime field set in it, as
2829         // equals() is not implemented.
2830         verify(mUwbServiceCore).queryUwbsTimestampMicros();
2831         verify(mUwbConfigurationManager).setAppConfigurations(
2832                 anyInt(), any(), any(), eq(FIRA_VERSION_2_0));
2833         verify(mUwbSessionNotificationManager).onRangingStarted(eq(uwbSession), any());
2834         verify(mUwbMetrics).longRangingStartEvent(
2835                 eq(uwbSession), eq(UwbUciConstants.STATUS_CODE_OK));
2836     }
2837 
2838     // Test CCC StartRanging on a Fira UCI version 2.0+ device, when the App configures a relative
2839     // UWB initiation time, and the computation of an absolute UWB initiation time is enabled on
2840     // the device. In this case, the UwbSessionManager is expected to query the UWBS timestamp.
2841     @Test
execStartRanging_success_ccc_2_0_absoluteInitiationTimeComputationIsComputed()2842     public void execStartRanging_success_ccc_2_0_absoluteInitiationTimeComputationIsComputed()
2843             throws Exception {
2844         // Setup the flag to be "true", so that absolute UWB initiation time computation is
2845         // enabled for a CCC ranging session.
2846         when(mDeviceConfigFacade.isCccAbsoluteUwbInitiationTimeEnabled()).thenReturn(true);
2847 
2848         UwbSession uwbSession = prepareExistingCccUwbSession();
2849         Params cccStartRangingParams = new CccStartRangingParams.Builder()
2850                 .setSessionId(TEST_SESSION_ID)
2851                 .setRanMultiplier(4)
2852                 .setInitiationTimeMs(100)
2853                 .build();
2854         CccRangingStartedParams cccRangingStartedParams = new CccRangingStartedParams.Builder()
2855                 .setStartingStsIndex(0)
2856                 .setUwbTime0(1)
2857                 .setHopModeKey(0)
2858                 .setSyncCodeIndex(1)
2859                 .setRanMultiplier(4)
2860                 .build();
2861 
2862         do_execStartRanging_success_uwbs_2_0(uwbSession,
2863                 cccStartRangingParams, cccRangingStartedParams, CccParams.PROTOCOL_VERSION_1_0);
2864 
2865         // Verify that queryUwbsTimestampMicros() is called. Currently unable to verify that the
2866         // CccOpenRangingParams is changed and the absoluteInitiationTime field set in it, as
2867         // equals() is not implemented.
2868         verify(mUwbServiceCore).queryUwbsTimestampMicros();
2869         verify(mUwbConfigurationManager).setAppConfigurations(
2870                 anyInt(), any(), any(), eq(FIRA_VERSION_2_0));
2871     }
2872 
2873     // Test ALIRO StartRanging on a Fira UCI version 2.0+ device, when the App configures a relative
2874     // UWB initiation time, and the computation of an absolute UWB initiation time is enabled on
2875     // the device. In this case, the UwbSessionManager is expected to query the UWBS timestamp.
2876     @Test
execStartRanging_success_aliro_2_0_absoluteInitiationTimeComputationIsComputed()2877     public void execStartRanging_success_aliro_2_0_absoluteInitiationTimeComputationIsComputed()
2878             throws Exception {
2879         // Setup the flag to be "true", so that absolute UWB initiation time computation is
2880         // enabled for a CCC ranging session.
2881         //
2882         // We currently re-use the CCC flag for ALIRO.
2883         when(mDeviceConfigFacade.isCccAbsoluteUwbInitiationTimeEnabled()).thenReturn(true);
2884 
2885         UwbSession uwbSession = prepareExistingAliroUwbSession();
2886         Params aliroStartRangingParams = new AliroStartRangingParams.Builder()
2887                 .setSessionId(TEST_SESSION_ID)
2888                 .setRanMultiplier(4)
2889                 .setInitiationTimeMs(100)
2890                 .build();
2891         AliroRangingStartedParams aliroRangingStartedParams =
2892                 new AliroRangingStartedParams.Builder()
2893                         .setStartingStsIndex(0)
2894                         .setUwbTime0(1)
2895                         .setHopModeKey(0)
2896                         .setSyncCodeIndex(1)
2897                         .setRanMultiplier(4)
2898                         .build();
2899 
2900         do_execStartRanging_success_uwbs_2_0(uwbSession,
2901                 aliroStartRangingParams, aliroRangingStartedParams,
2902                 AliroParams.PROTOCOL_VERSION_1_0);
2903 
2904         // Verify that queryUwbsTimestampMicros() is called. Currently unable to verify that the
2905         // AliroOpenRangingParams is changed and the absoluteInitiationTime field set in it, as
2906         // equals() is not implemented.
2907         verify(mUwbServiceCore).queryUwbsTimestampMicros();
2908         verify(mUwbConfigurationManager).setAppConfigurations(
2909                 anyInt(), any(), any(), eq(FIRA_VERSION_2_0));
2910     }
2911 
2912     // Test CCC StartRanging on a Fira UCI version 2.0+ device, when the App configures a relative
2913     // UWB initiation time, and the computation of an absolute UWB initiation time is disabled on
2914     // the device. In this case, the UwbSessionManager is not expected to query the UWBS timestamp.
2915     @Test
execStartRanging_success_ccc_2_0_absoluteInitiationTimeComputationIsDisabled()2916     public void execStartRanging_success_ccc_2_0_absoluteInitiationTimeComputationIsDisabled()
2917             throws Exception {
2918         // Setup the flag to "false" (which is also the default value), so that absolute
2919         // UWB initiation time computation is disabled for a CCC ranging session.
2920         when(mDeviceConfigFacade.isCccAbsoluteUwbInitiationTimeEnabled()).thenReturn(false);
2921 
2922         UwbSession uwbSession = prepareExistingCccUwbSession();
2923         Params cccStartRangingParams = new CccStartRangingParams.Builder()
2924                 .setSessionId(TEST_SESSION_ID)
2925                 .setRanMultiplier(4)
2926                 .setInitiationTimeMs(100)
2927                 .build();
2928         CccRangingStartedParams cccRangingStartedParams = new CccRangingStartedParams.Builder()
2929                 .setStartingStsIndex(0)
2930                 .setUwbTime0(1)
2931                 .setHopModeKey(0)
2932                 .setSyncCodeIndex(1)
2933                 .setRanMultiplier(4)
2934                 .build();
2935 
2936         do_execStartRanging_success_uwbs_2_0(uwbSession,
2937                 cccStartRangingParams, cccRangingStartedParams, CccParams.PROTOCOL_VERSION_1_0);
2938 
2939         // Verify that queryUwbsTimestampMicros() is not called.
2940         verify(mUwbServiceCore, never()).queryUwbsTimestampMicros();
2941         verify(mUwbConfigurationManager).setAppConfigurations(
2942                 anyInt(), any(), any(), eq(FIRA_VERSION_2_0));
2943     }
2944 
2945     // Test ALIRO StartRanging on a Fira UCI version 2.0+ device, when the App configures a relative
2946     // UWB initiation time, and the computation of an absolute UWB initiation time is disabled on
2947     // the device. In this case, the UwbSessionManager is not expected to query the UWBS timestamp.
2948     @Test
execStartRanging_success_aliro_2_0_absoluteInitiationTimeComputationIsDisabled()2949     public void execStartRanging_success_aliro_2_0_absoluteInitiationTimeComputationIsDisabled()
2950             throws Exception {
2951         // Setup the flag to "false" (which is also the default value), so that absolute
2952         // UWB initiation time computation is disabled for a CCC ranging session.
2953         //
2954         // We currently re-use the CCC flag for ALIRO.
2955         when(mDeviceConfigFacade.isCccAbsoluteUwbInitiationTimeEnabled()).thenReturn(false);
2956 
2957         UwbSession uwbSession = prepareExistingAliroUwbSession();
2958         Params aliroStartRangingParams = new AliroStartRangingParams.Builder()
2959                 .setSessionId(TEST_SESSION_ID)
2960                 .setRanMultiplier(4)
2961                 .setInitiationTimeMs(100)
2962                 .build();
2963         AliroRangingStartedParams aliroRangingStartedParams =
2964                 new AliroRangingStartedParams.Builder()
2965                         .setStartingStsIndex(0)
2966                         .setUwbTime0(1)
2967                         .setHopModeKey(0)
2968                         .setSyncCodeIndex(1)
2969                         .setRanMultiplier(4)
2970                         .build();
2971 
2972         do_execStartRanging_success_uwbs_2_0(uwbSession,
2973                 aliroStartRangingParams, aliroRangingStartedParams,
2974                 AliroParams.PROTOCOL_VERSION_1_0);
2975 
2976         // Verify that queryUwbsTimestampMicros() is not called.
2977         verify(mUwbServiceCore, never()).queryUwbsTimestampMicros();
2978         verify(mUwbConfigurationManager).setAppConfigurations(
2979                 anyInt(), any(), any(), eq(FIRA_VERSION_2_0));
2980     }
2981 
2982     // Test FiRa StartRanging on a Fira UCI version 2.0+ device, when the App configures an absolute
2983     // UWB initiation time. In this case, the UwbSessionManager is not expected to query the UWBS
2984     // timestamp.
2985     @Test
execStartRanging_success_fira_2_0_absoluteUwbInitiationTimeUserConfigured()2986     public void execStartRanging_success_fira_2_0_absoluteUwbInitiationTimeUserConfigured()
2987             throws Exception {
2988         Params params = setupFiraParams(FIRA_VERSION_2_0);
2989 
2990         // Setup the AbsoluteInitationTime in the FiraOpenSessionParams.
2991         FiraOpenSessionParams firaParams = new
2992                 FiraOpenSessionParams.Builder((FiraOpenSessionParams) params)
2993                 .setAbsoluteInitiationTime(1000000L)
2994                 .build();
2995         UwbSession uwbSession = prepareExistingUwbSession(firaParams);
2996 
2997         do_execStartRanging_success_uwbs_2_0(uwbSession, params, null, FIRA_VERSION_2_0);
2998 
2999         // Verify that queryUwbsTimestampMicros() isn't called (which is the expected behavior as
3000         // the firaParams has the absolute_initiation_time field set).
3001         verify(mUwbServiceCore, never()).queryUwbsTimestampMicros();
3002     }
3003 
3004     // Test CCC StartRanging on a Fira UCI version 2.0+ device, when the App configures an absolute
3005     // UWB initiation time. In this case, the UwbSessionManager is not expected to query the UWBS
3006     // timestamp.
3007     @Test
execStartRanging_success_ccc_2_0_absoluteInitiationTimeUserConfigured()3008     public void execStartRanging_success_ccc_2_0_absoluteInitiationTimeUserConfigured()
3009             throws Exception {
3010         // Setup the flag to be "true", so that absolute UWB initiation time computation is
3011         // enabled for a CCC ranging session.
3012         when(mDeviceConfigFacade.isCccAbsoluteUwbInitiationTimeEnabled()).thenReturn(true);
3013 
3014         UwbSession uwbSession = prepareExistingCccUwbSession();
3015         CccStartRangingParams cccStartRangingParams = new CccStartRangingParams.Builder()
3016                 .setSessionId(TEST_SESSION_ID)
3017                 .setRanMultiplier(4)
3018                 .setAbsoluteInitiationTimeUs(8000)
3019                 .build();
3020         CccRangingStartedParams cccRangingStartedParams = new CccRangingStartedParams.Builder()
3021                 .setStartingStsIndex(0)
3022                 .setUwbTime0(1)
3023                 .setHopModeKey(0)
3024                 .setSyncCodeIndex(1)
3025                 .setRanMultiplier(4)
3026                 .build();
3027 
3028         do_execStartRanging_success_uwbs_2_0(uwbSession,
3029                 cccStartRangingParams, cccRangingStartedParams, CccParams.PROTOCOL_VERSION_1_0);
3030 
3031         // Verify that queryUwbsTimestampMicros() is not called when it is configured with
3032         // CccStartRangingParams
3033         verify(mUwbServiceCore, never()).queryUwbsTimestampMicros();
3034         verify(mUwbConfigurationManager).setAppConfigurations(
3035                 anyInt(), any(), any(), eq(FIRA_VERSION_2_0));
3036     }
3037 
3038     // Test ALIRO StartRanging on a Fira UCI version 2.0+ device, when the App configures an
3039     // absolute UWB initiation time. In this case, the UwbSessionManager is not expected to query
3040     // the UWBS timestamp.
3041     @Test
execStartRanging_success_aliro_2_0_absoluteInitiationTimeUserConfigured()3042     public void execStartRanging_success_aliro_2_0_absoluteInitiationTimeUserConfigured()
3043             throws Exception {
3044         // Setup the flag to be "true", so that absolute UWB initiation time computation is
3045         // enabled for a ALIRO ranging session.
3046         //
3047         // We currently use the CCC flag for ALIRO sessions also.
3048         when(mDeviceConfigFacade.isCccAbsoluteUwbInitiationTimeEnabled()).thenReturn(true);
3049 
3050         UwbSession uwbSession = prepareExistingAliroUwbSession();
3051         AliroStartRangingParams aliroStartRangingParams = new AliroStartRangingParams.Builder()
3052                 .setSessionId(TEST_SESSION_ID)
3053                 .setRanMultiplier(4)
3054                 .setAbsoluteInitiationTimeUs(8000)
3055                 .build();
3056         AliroRangingStartedParams aliroRangingStartedParams =
3057                 new AliroRangingStartedParams.Builder()
3058                         .setStartingStsIndex(0)
3059                         .setUwbTime0(1)
3060                         .setHopModeKey(0)
3061                         .setSyncCodeIndex(1)
3062                         .setRanMultiplier(4)
3063                         .build();
3064 
3065         do_execStartRanging_success_uwbs_2_0(uwbSession,
3066                 aliroStartRangingParams, aliroRangingStartedParams,
3067                 AliroParams.PROTOCOL_VERSION_1_0);
3068 
3069         // Verify that queryUwbsTimestampMicros() is not called when it is configured with
3070         // AliroStartRangingParams.
3071         verify(mUwbServiceCore, never()).queryUwbsTimestampMicros();
3072         verify(mUwbConfigurationManager).setAppConfigurations(
3073                 anyInt(), any(), any(), eq(FIRA_VERSION_2_0));
3074     }
3075 
do_execStartRanging_success_uwbs_2_0(UwbSession uwbSession, Params cccStartRangingParams, Params rangingStartedParams, ProtocolVersion protocolVersion)3076     private void do_execStartRanging_success_uwbs_2_0(UwbSession uwbSession,
3077             Params cccStartRangingParams, Params rangingStartedParams,
3078             ProtocolVersion protocolVersion) throws Exception {
3079         // Setup the UWBS to return Fira UCI version as 2.0.
3080         when(mUwbServiceCore.getCachedDeviceInfoResponse(TEST_CHIP_ID)).thenReturn(
3081                 UWB_DEVICE_INFO_RESPONSE_2_0);
3082 
3083         // Setup for start ranging.
3084         doReturn(UwbUciConstants.UWB_SESSION_STATE_IDLE, UwbUciConstants.UWB_SESSION_STATE_ACTIVE)
3085                 .when(uwbSession).getSessionState();
3086         when(mNativeUwbManager.startRanging(eq(TEST_SESSION_ID), anyString()))
3087                 .thenReturn((byte) UwbUciConstants.STATUS_CODE_OK);
3088         when(mUwbServiceCore.queryUwbsTimestampMicros()).thenReturn(UWBS_TIMESTAMP);
3089         when(mUwbConfigurationManager.setAppConfigurations(anyInt(), any(), anyString(), any()))
3090                 .thenReturn(UwbUciConstants.STATUS_CODE_OK);
3091         when(mUwbConfigurationManager.getAppConfigurations(
3092                 eq(TEST_SESSION_ID), anyString(), any(), any(), eq(TEST_CHIP_ID),
3093                 eq(protocolVersion)))
3094                 .thenReturn(new Pair<>(UwbUciConstants.STATUS_CODE_OK, rangingStartedParams));
3095 
3096         mUwbSessionManager.startRanging(uwbSession.getSessionHandle(), cccStartRangingParams);
3097         mTestLooper.dispatchAll();
3098 
3099         // Verify that the UWB ranging session was successfully started.
3100         verify(mNativeUwbManager).startRanging(eq(TEST_SESSION_ID), anyString());
3101         verify(mUwbSessionNotificationManager).onRangingStarted(eq(uwbSession), any());
3102         verify(mUwbMetrics).longRangingStartEvent(
3103                 eq(uwbSession), eq(UwbUciConstants.STATUS_CODE_OK));
3104     }
3105 
3106     @Test
execStartRanging_onRangeDataNotification()3107     public void execStartRanging_onRangeDataNotification() throws Exception {
3108         UwbSession uwbSession = prepareExistingUwbSession();
3109         // set up for start ranging
3110         doReturn(UwbUciConstants.UWB_SESSION_STATE_IDLE, UwbUciConstants.UWB_SESSION_STATE_ACTIVE)
3111                 .when(uwbSession).getSessionState();
3112         when(mNativeUwbManager.startRanging(eq(TEST_SESSION_ID), anyString()))
3113                 .thenReturn((byte) UwbUciConstants.STATUS_CODE_OK);
3114 
3115         mUwbSessionManager.startRanging(
3116                 uwbSession.getSessionHandle(), uwbSession.getParams());
3117         mTestLooper.dispatchAll();
3118 
3119         verify(mUwbSessionNotificationManager).onRangingStarted(eq(uwbSession), any());
3120         verify(mUwbMetrics).longRangingStartEvent(
3121                 eq(uwbSession), eq(UwbUciConstants.STATUS_CODE_OK));
3122 
3123         // Now send a range data notification.
3124         UwbRangingData uwbRangingData = UwbTestUtils.generateRangingData(
3125                 RANGING_MEASUREMENT_TYPE_TWO_WAY, MAC_ADDRESSING_MODE_EXTENDED,
3126                 UwbUciConstants.STATUS_CODE_OK);
3127         mUwbSessionManager.onRangeDataNotificationReceived(uwbRangingData);
3128         verify(mUwbSessionNotificationManager).onRangingResult(uwbSession, uwbRangingData);
3129     }
3130 
3131     @Test
execStartRanging_twoWay_onRangeDataNotificationContinuousErrors()3132     public void execStartRanging_twoWay_onRangeDataNotificationContinuousErrors() throws Exception {
3133         UwbSession uwbSession = prepareExistingUwbSession();
3134         UwbAddress controleeAddr = setUpControlee(uwbSession, MAC_ADDRESSING_MODE_SHORT);
3135         startRanging(uwbSession);
3136 
3137         verify(mUwbSessionNotificationManager).onRangingStarted(eq(uwbSession), any());
3138         verify(mUwbMetrics).longRangingStartEvent(
3139                 eq(uwbSession), eq(UwbUciConstants.STATUS_CODE_OK));
3140 
3141         // Now send a range data notification with an error.
3142         UwbRangingData uwbRangingData = UwbTestUtils.generateRangingData(
3143                 RANGING_MEASUREMENT_TYPE_TWO_WAY, MAC_ADDRESSING_MODE_SHORT,
3144                 UwbUciConstants.STATUS_CODE_RANGING_RX_TIMEOUT);
3145         mUwbSessionManager.onRangeDataNotificationReceived(uwbRangingData);
3146         verify(mUwbSessionNotificationManager).onRangingResult(uwbSession, uwbRangingData);
3147 
3148         // Verify that an alarm is started for the controlee
3149         ArgumentCaptor<UwbAddress> addressCaptor = ArgumentCaptor.forClass(UwbAddress.class);
3150         ArgumentCaptor<AlarmManager.OnAlarmListener> alarmListenerCaptor =
3151                 ArgumentCaptor.forClass(AlarmManager.OnAlarmListener.class);
3152         verify(uwbSession.mMulticastRangingErrorStreakTimerListeners).put(
3153                 addressCaptor.capture(),
3154                 alarmListenerCaptor.capture()
3155         );
3156         verify(mAlarmManager).setExact(
3157                 anyInt(), anyLong(), anyString(), eq(alarmListenerCaptor.getValue()), any());
3158         assertThat(addressCaptor.getValue()).isEqualTo(controleeAddr);
3159         assertThat(alarmListenerCaptor.getValue()).isNotNull();
3160 
3161         // Send one more error
3162         uwbRangingData = UwbTestUtils.generateRangingData(
3163                 RANGING_MEASUREMENT_TYPE_TWO_WAY, MAC_ADDRESSING_MODE_SHORT,
3164                 UwbUciConstants.STATUS_CODE_RANGING_RX_TIMEOUT);
3165         mUwbSessionManager.onRangeDataNotificationReceived(uwbRangingData);
3166         verify(mUwbSessionNotificationManager).onRangingResult(uwbSession, uwbRangingData);
3167 
3168         // Verify that the alarm is not cancelled
3169         verify(mAlarmManager, never()).cancel(any(AlarmManager.OnAlarmListener.class));
3170 
3171         // set up for stop ranging
3172         doReturn(UwbUciConstants.UWB_SESSION_STATE_ACTIVE, UwbUciConstants.UWB_SESSION_STATE_IDLE)
3173                 .when(uwbSession).getSessionState();
3174         when(mNativeUwbManager.stopRanging(eq(TEST_SESSION_ID), anyString()))
3175                 .thenReturn((byte) UwbUciConstants.STATUS_CODE_OK);
3176 
3177         // Now fire the timer callback.
3178         alarmListenerCaptor.getValue().onAlarm();
3179 
3180         // Expect session stop.
3181         mTestLooper.dispatchNext();
3182         verify(mUwbSessionNotificationManager)
3183                 .onRangingStoppedWithApiReasonCode(eq(uwbSession),
3184                         eq(RangingChangeReason.SYSTEM_POLICY), any());
3185         verify(mUwbMetrics).longRangingStopEvent(eq(uwbSession));
3186     }
3187 
3188     @Test
execStartRanging_owrAoa_onRangeDataNotificationContinuousErrors()3189     public void execStartRanging_owrAoa_onRangeDataNotificationContinuousErrors() throws Exception {
3190         UwbSession uwbSession = prepareExistingUwbSession();
3191         startRanging(uwbSession);
3192 
3193         // Now send a range data notification with an error.
3194         UwbRangingData uwbRangingData = UwbTestUtils.generateRangingData(
3195                 RANGING_MEASUREMENT_TYPE_OWR_AOA, MAC_ADDRESSING_MODE_SHORT,
3196                 UwbUciConstants.STATUS_CODE_RANGING_RX_TIMEOUT);
3197         mUwbSessionManager.onRangeDataNotificationReceived(uwbRangingData);
3198         verify(mUwbSessionNotificationManager).onRangingResult(uwbSession, uwbRangingData);
3199         ArgumentCaptor<AlarmManager.OnAlarmListener> alarmListenerCaptor =
3200                 ArgumentCaptor.forClass(AlarmManager.OnAlarmListener.class);
3201         verify(mAlarmManager).setExact(
3202                 anyInt(), anyLong(), anyString(), alarmListenerCaptor.capture(), any());
3203         assertThat(alarmListenerCaptor.getValue()).isNotNull();
3204 
3205         // Send one more error and ensure that the timer is not cancelled.
3206         uwbRangingData = UwbTestUtils.generateRangingData(
3207                 RANGING_MEASUREMENT_TYPE_OWR_AOA, MAC_ADDRESSING_MODE_SHORT,
3208                 UwbUciConstants.STATUS_CODE_RANGING_RX_TIMEOUT);
3209         mUwbSessionManager.onRangeDataNotificationReceived(uwbRangingData);
3210         verify(mUwbSessionNotificationManager).onRangingResult(uwbSession, uwbRangingData);
3211 
3212         verify(mAlarmManager, never()).cancel(any(AlarmManager.OnAlarmListener.class));
3213 
3214         // set up for stop ranging
3215         doReturn(UwbUciConstants.UWB_SESSION_STATE_ACTIVE, UwbUciConstants.UWB_SESSION_STATE_IDLE)
3216                 .when(uwbSession).getSessionState();
3217         when(mNativeUwbManager.stopRanging(eq(TEST_SESSION_ID), anyString()))
3218                 .thenReturn((byte) UwbUciConstants.STATUS_CODE_OK);
3219 
3220         // Now fire the timer callback.
3221         alarmListenerCaptor.getValue().onAlarm();
3222 
3223         // Expect session stop.
3224         mTestLooper.dispatchNext();
3225         verify(mUwbSessionNotificationManager)
3226                 .onRangingStoppedWithApiReasonCode(eq(uwbSession),
3227                         eq(RangingChangeReason.SYSTEM_POLICY), any());
3228         verify(mUwbMetrics).longRangingStopEvent(eq(uwbSession));
3229     }
3230 
3231     @Test
3232     public void
execStartRanging_onRangeDataNotificationContinuousErrors_WhenErrorStreakTimerDisabled()3233             execStartRanging_onRangeDataNotificationContinuousErrors_WhenErrorStreakTimerDisabled()
3234             throws Exception {
3235         when(mDeviceConfigFacade.isRangingErrorStreakTimerEnabled()).thenReturn(false);
3236 
3237         UwbSession uwbSession = prepareExistingUwbSession();
3238         startRanging(uwbSession);
3239 
3240         // Now send a range data notification with an error.
3241         UwbRangingData uwbRangingData = UwbTestUtils.generateRangingData(
3242                 RANGING_MEASUREMENT_TYPE_TWO_WAY, MAC_ADDRESSING_MODE_SHORT,
3243                 UwbUciConstants.STATUS_CODE_RANGING_RX_TIMEOUT);
3244         mUwbSessionManager.onRangeDataNotificationReceived(uwbRangingData);
3245         verify(mUwbSessionNotificationManager).onRangingResult(uwbSession, uwbRangingData);
3246         // Ensure error streak timer is not started.
3247         verify(mAlarmManager, never()).setExact(
3248                 anyInt(), anyLong(), anyString(), any(), any());
3249     }
3250 
3251     @Test
execStartRanging_onRangeDataNotificationErrorFollowedBySuccess()3252     public void execStartRanging_onRangeDataNotificationErrorFollowedBySuccess() throws Exception {
3253         UwbSession uwbSession = prepareExistingUwbSession();
3254         UwbAddress controleeAddr = setUpControlee(uwbSession, MAC_ADDRESSING_MODE_SHORT);
3255         startRanging(uwbSession);
3256 
3257         // Now send a range data notification with an error.
3258         UwbRangingData uwbRangingData = UwbTestUtils.generateRangingData(
3259                 RANGING_MEASUREMENT_TYPE_TWO_WAY, MAC_ADDRESSING_MODE_SHORT,
3260                 UwbUciConstants.STATUS_CODE_RANGING_RX_TIMEOUT);
3261 
3262         mUwbSessionManager.onRangeDataNotificationReceived(uwbRangingData);
3263         verify(mUwbSessionNotificationManager).onRangingResult(uwbSession, uwbRangingData);
3264         // Verify that an alarm is started for the controlee.
3265         ArgumentCaptor<UwbAddress> addressCaptor = ArgumentCaptor.forClass(UwbAddress.class);
3266         ArgumentCaptor<AlarmManager.OnAlarmListener> alarmListenerCaptor =
3267                 ArgumentCaptor.forClass(AlarmManager.OnAlarmListener.class);
3268         verify(uwbSession.mMulticastRangingErrorStreakTimerListeners).put(
3269                 addressCaptor.capture(),
3270                 alarmListenerCaptor.capture()
3271         );
3272         verify(mAlarmManager).setExact(
3273                 anyInt(), anyLong(), anyString(), eq(alarmListenerCaptor.getValue()), any());
3274         assertThat(addressCaptor.getValue()).isEqualTo(controleeAddr);
3275         assertThat(alarmListenerCaptor.getValue()).isNotNull();
3276         // Actually do the putting so that we can check for removal later.
3277         uwbSession.mMulticastRangingErrorStreakTimerListeners.put(addressCaptor.getValue(),
3278                 alarmListenerCaptor.getValue());
3279 
3280         // Send successful data and ensure that the controlee's timer is cancelled.
3281         uwbRangingData = UwbTestUtils.generateRangingData(
3282                 RANGING_MEASUREMENT_TYPE_TWO_WAY, MAC_ADDRESSING_MODE_SHORT,
3283                 UwbUciConstants.STATUS_CODE_OK);
3284         mUwbSessionManager.onRangeDataNotificationReceived(uwbRangingData);
3285         verify(mUwbSessionNotificationManager).onRangingResult(eq(uwbSession), eq(uwbRangingData));
3286         verify(mAlarmManager).cancel(eq(alarmListenerCaptor.getValue()));
3287         verify(uwbSession.mMulticastRangingErrorStreakTimerListeners)
3288                 .remove(eq(addressCaptor.getValue()));
3289     }
3290 
3291     @Test
session_receivedDataInfo()3292     public void session_receivedDataInfo() throws Exception {
3293         UwbSession uwbSession = prepareExistingUwbSession();
3294 
3295         // Setup the UwbSession to have multiple data packets (being received) for multiple remote
3296         // devices. This includes some duplicate packets (same sequence number from same remote
3297         // device), which should be ignored.
3298         UwbSessionManager.ReceivedDataInfo deviceOnePacketOne = buildReceivedDataInfo(
3299                 PEER_EXTENDED_MAC_ADDRESS_LONG, DATA_SEQUENCE_NUM);
3300         UwbSessionManager.ReceivedDataInfo deviceOnePacketTwo = buildReceivedDataInfo(
3301                 PEER_EXTENDED_MAC_ADDRESS_LONG, DATA_SEQUENCE_NUM_1);
3302         UwbSessionManager.ReceivedDataInfo deviceTwoPacketOne = buildReceivedDataInfo(
3303                 PEER_EXTENDED_MAC_ADDRESS_2_LONG, DATA_SEQUENCE_NUM);
3304         UwbSessionManager.ReceivedDataInfo deviceTwoPacketTwo = buildReceivedDataInfo(
3305                 PEER_EXTENDED_MAC_ADDRESS_2_LONG, DATA_SEQUENCE_NUM_1);
3306         when(mDeviceConfigFacade.getRxDataMaxPacketsToStore())
3307                 .thenReturn(MAX_RX_DATA_PACKETS_TO_STORE);
3308 
3309         uwbSession.addReceivedDataInfo(deviceOnePacketOne);
3310         uwbSession.addReceivedDataInfo(deviceOnePacketTwo);
3311         uwbSession.addReceivedDataInfo(deviceOnePacketOne);
3312 
3313         uwbSession.addReceivedDataInfo(deviceTwoPacketOne);
3314         uwbSession.addReceivedDataInfo(deviceTwoPacketTwo);
3315         uwbSession.addReceivedDataInfo(deviceTwoPacketOne);
3316 
3317         // Verify that the first call to getAllReceivedDataInfo() for a device returns all it's
3318         // received packets, and the second call receives an empty list.
3319         assertThat(uwbSession.getAllReceivedDataInfo(PEER_EXTENDED_MAC_ADDRESS_LONG)).isEqualTo(
3320                 List.of(deviceOnePacketOne, deviceOnePacketTwo));
3321         assertThat(uwbSession.getAllReceivedDataInfo(PEER_EXTENDED_MAC_ADDRESS_LONG)).isEqualTo(
3322                 List.of());
3323         assertThat(uwbSession.getAllReceivedDataInfo(PEER_EXTENDED_MAC_ADDRESS_2_LONG)).isEqualTo(
3324                 List.of(deviceTwoPacketOne, deviceTwoPacketTwo));
3325         assertThat(uwbSession.getAllReceivedDataInfo(PEER_EXTENDED_MAC_ADDRESS_2_LONG)).isEqualTo(
3326                 List.of());
3327     }
3328 
3329     @Test
session_receivedDataInfo_maxCapacity()3330     public void session_receivedDataInfo_maxCapacity() throws Exception {
3331         UwbSession uwbSession = prepareExistingUwbSession();
3332 
3333         UwbSessionManager.ReceivedDataInfo rxPacketOne = buildReceivedDataInfo(
3334                 PEER_EXTENDED_MAC_ADDRESS_LONG, DATA_SEQUENCE_NUM + 1);
3335         UwbSessionManager.ReceivedDataInfo rxPacketTwo = buildReceivedDataInfo(
3336                 PEER_EXTENDED_MAC_ADDRESS_LONG, DATA_SEQUENCE_NUM + 2);
3337         UwbSessionManager.ReceivedDataInfo rxPacketThree = buildReceivedDataInfo(
3338                 PEER_EXTENDED_MAC_ADDRESS_LONG, DATA_SEQUENCE_NUM + 3);
3339         UwbSessionManager.ReceivedDataInfo rxPacketFour = buildReceivedDataInfo(
3340                 PEER_EXTENDED_MAC_ADDRESS_LONG, DATA_SEQUENCE_NUM + 4);
3341 
3342         // Setup the UwbSession to have multiple data packets (being received) from one remote
3343         // device, such that it's at the capacity. We send the packets out-of-order, but do want
3344         // to extract them in order.
3345         when(mDeviceConfigFacade.getRxDataMaxPacketsToStore()).thenReturn(3);
3346 
3347         // Case 1 - Setup the UwbSession to have multiple Rx data packets (beyond capacity), such
3348         // that the last packet is the smallest one and should be dropped.
3349         uwbSession.addReceivedDataInfo(rxPacketTwo);
3350         uwbSession.addReceivedDataInfo(rxPacketFour);
3351         uwbSession.addReceivedDataInfo(rxPacketThree);
3352         uwbSession.addReceivedDataInfo(rxPacketOne);
3353 
3354         // Verify that the first call to getAllReceivedDataInfo() returns the max capacity number of
3355         // packets (in-order), and the second call receives an empty list.
3356         assertThat(uwbSession.getAllReceivedDataInfo(PEER_EXTENDED_MAC_ADDRESS_LONG)).isEqualTo(
3357                 List.of(rxPacketTwo, rxPacketThree, rxPacketFour));
3358         assertThat(uwbSession.getAllReceivedDataInfo(PEER_EXTENDED_MAC_ADDRESS_LONG)).isEqualTo(
3359                 List.of());
3360 
3361         // Case 2 - Setup the UwbSession to have multiple Rx data packets (beyond capacity), such
3362         // that one of the stored packets is the smallest one and should be dropped.
3363         uwbSession.addReceivedDataInfo(rxPacketOne);
3364         uwbSession.addReceivedDataInfo(rxPacketTwo);
3365         uwbSession.addReceivedDataInfo(rxPacketFour);
3366         uwbSession.addReceivedDataInfo(rxPacketThree);
3367 
3368         assertThat(uwbSession.getAllReceivedDataInfo(PEER_EXTENDED_MAC_ADDRESS_LONG)).isEqualTo(
3369                 List.of(rxPacketTwo, rxPacketThree, rxPacketFour));
3370         assertThat(uwbSession.getAllReceivedDataInfo(PEER_EXTENDED_MAC_ADDRESS_LONG)).isEqualTo(
3371                 List.of());
3372 
3373         // Case 3 - Setup the UwbSession to have multiple Rx data packets (beyond capacity), such
3374         // that one of the stored packets is repeated. The repeated packet should be ignored.
3375         uwbSession.addReceivedDataInfo(rxPacketTwo);
3376         uwbSession.addReceivedDataInfo(rxPacketFour);
3377         uwbSession.addReceivedDataInfo(rxPacketThree);
3378         uwbSession.addReceivedDataInfo(rxPacketFour);
3379 
3380         assertThat(uwbSession.getAllReceivedDataInfo(PEER_EXTENDED_MAC_ADDRESS_LONG)).isEqualTo(
3381                 List.of(rxPacketTwo, rxPacketThree, rxPacketFour));
3382         assertThat(uwbSession.getAllReceivedDataInfo(PEER_EXTENDED_MAC_ADDRESS_LONG)).isEqualTo(
3383                 List.of());
3384     }
3385 
3386     @Test
execStartCccRanging_success()3387     public void execStartCccRanging_success() throws Exception {
3388         UwbSession uwbSession = prepareExistingCccUwbSession();
3389         // set up for start ranging
3390         doReturn(UwbUciConstants.UWB_SESSION_STATE_IDLE, UwbUciConstants.UWB_SESSION_STATE_ACTIVE)
3391                 .when(uwbSession).getSessionState();
3392         when(mNativeUwbManager.startRanging(eq(TEST_SESSION_ID), anyString()))
3393                 .thenReturn((byte) UwbUciConstants.STATUS_CODE_OK);
3394         CccStartRangingParams cccStartRangingParams = new CccStartRangingParams.Builder()
3395                 .setSessionId(TEST_SESSION_ID)
3396                 .setRanMultiplier(8)
3397                 .build();
3398         mUwbSessionManager.startRanging(
3399                 uwbSession.getSessionHandle(), cccStartRangingParams);
3400         mTestLooper.dispatchAll();
3401 
3402         // Verify the update logic.
3403         CccOpenRangingParams cccOpenRangingParams = (CccOpenRangingParams) uwbSession.getParams();
3404         assertThat(cccOpenRangingParams.getRanMultiplier()).isEqualTo(8);
3405     }
3406 
3407     @Test
execStartAliroRanging_success()3408     public void execStartAliroRanging_success() throws Exception {
3409         UwbSession uwbSession = prepareExistingAliroUwbSession();
3410         // set up for start ranging
3411         doReturn(UwbUciConstants.UWB_SESSION_STATE_IDLE, UwbUciConstants.UWB_SESSION_STATE_ACTIVE)
3412                 .when(uwbSession).getSessionState();
3413         when(mNativeUwbManager.startRanging(eq(TEST_SESSION_ID), anyString()))
3414                 .thenReturn((byte) UwbUciConstants.STATUS_CODE_OK);
3415         AliroStartRangingParams aliroStartRangingParams = new AliroStartRangingParams.Builder()
3416                 .setSessionId(TEST_SESSION_ID)
3417                 .setRanMultiplier(8)
3418                 .build();
3419         mUwbSessionManager.startRanging(uwbSession.getSessionHandle(), aliroStartRangingParams);
3420         mTestLooper.dispatchAll();
3421 
3422         // Verify the update logic.
3423         AliroOpenRangingParams aliroOpenRangingParams =
3424                 (AliroOpenRangingParams) uwbSession.getParams();
3425         assertThat(aliroOpenRangingParams.getRanMultiplier()).isEqualTo(8);
3426     }
3427 
3428     @Test
execStartCccRangingWithNoStartParams_success()3429     public void execStartCccRangingWithNoStartParams_success() throws Exception {
3430         UwbSession uwbSession = prepareExistingCccUwbSession();
3431         // set up for start ranging
3432         doReturn(UwbUciConstants.UWB_SESSION_STATE_IDLE, UwbUciConstants.UWB_SESSION_STATE_ACTIVE)
3433                 .when(uwbSession).getSessionState();
3434         when(mNativeUwbManager.startRanging(eq(TEST_SESSION_ID), anyString()))
3435                 .thenReturn((byte) UwbUciConstants.STATUS_CODE_OK);
3436         mUwbSessionManager.startRanging(uwbSession.getSessionHandle(), null /* params */);
3437         mTestLooper.dispatchAll();
3438 
3439         // Verify that RAN multiplier from open is used.
3440         CccOpenRangingParams cccOpenRangingParams = (CccOpenRangingParams) uwbSession.getParams();
3441         assertThat(cccOpenRangingParams.getRanMultiplier()).isEqualTo(4);
3442     }
3443 
3444     @Test
execStartAliroRangingWithNoStartParams_success()3445     public void execStartAliroRangingWithNoStartParams_success() throws Exception {
3446         UwbSession uwbSession = prepareExistingAliroUwbSession();
3447         // set up for start ranging
3448         doReturn(UwbUciConstants.UWB_SESSION_STATE_IDLE, UwbUciConstants.UWB_SESSION_STATE_ACTIVE)
3449                 .when(uwbSession).getSessionState();
3450         when(mNativeUwbManager.startRanging(eq(TEST_SESSION_ID), anyString()))
3451                 .thenReturn((byte) UwbUciConstants.STATUS_CODE_OK);
3452         mUwbSessionManager.startRanging(uwbSession.getSessionHandle(), null /* params */);
3453         mTestLooper.dispatchAll();
3454 
3455         // Verify that RAN multiplier from open is used.
3456         AliroOpenRangingParams aliroOpenRangingParams =
3457                 (AliroOpenRangingParams) uwbSession.getParams();
3458         assertThat(aliroOpenRangingParams.getRanMultiplier()).isEqualTo(4);
3459     }
3460 
3461     @Test
execStartRanging_executionException()3462     public void execStartRanging_executionException() throws Exception {
3463         UwbSession uwbSession = prepareExistingUwbSession();
3464         // set up for start ranging
3465         doReturn(UwbUciConstants.UWB_SESSION_STATE_IDLE, UwbUciConstants.UWB_SESSION_STATE_ACTIVE)
3466                 .when(uwbSession).getSessionState();
3467         when(mNativeUwbManager.startRanging(eq(TEST_SESSION_ID), anyString()))
3468                 .thenThrow(new IllegalStateException());
3469 
3470         mUwbSessionManager.startRanging(
3471                 uwbSession.getSessionHandle(), uwbSession.getParams());
3472         mTestLooper.dispatchAll();
3473 
3474         verify(mUwbMetrics).longRangingStartEvent(
3475                 eq(uwbSession), eq(UwbUciConstants.STATUS_CODE_FAILED));
3476     }
3477 
3478     @Test
execStartRanging_nativeStartRangingFailed()3479     public void execStartRanging_nativeStartRangingFailed() throws Exception {
3480         UwbSession uwbSession = prepareExistingUwbSession();
3481         // set up for start ranging
3482         doReturn(UwbUciConstants.UWB_SESSION_STATE_IDLE, UwbUciConstants.UWB_SESSION_STATE_ACTIVE)
3483                 .when(uwbSession).getSessionState();
3484         when(mNativeUwbManager.startRanging(eq(TEST_SESSION_ID), anyString()))
3485                 .thenReturn((byte) UwbUciConstants.STATUS_CODE_FAILED);
3486 
3487         mUwbSessionManager.startRanging(
3488                 uwbSession.getSessionHandle(), uwbSession.getParams());
3489         mTestLooper.dispatchAll();
3490 
3491         verify(mUwbSessionNotificationManager).onRangingStartFailed(
3492                 eq(uwbSession), eq(UwbUciConstants.STATUS_CODE_FAILED));
3493         verify(mUwbMetrics).longRangingStartEvent(
3494                 eq(uwbSession), eq(UwbUciConstants.STATUS_CODE_FAILED));
3495     }
3496 
3497     @Test
execStartRanging_wrongSessionState()3498     public void execStartRanging_wrongSessionState() throws Exception {
3499         UwbSession uwbSession = prepareExistingUwbSession();
3500         // set up for start ranging
3501         doReturn(UwbUciConstants.UWB_SESSION_STATE_IDLE, UwbUciConstants.UWB_SESSION_STATE_ERROR)
3502                 .when(uwbSession).getSessionState();
3503         when(mNativeUwbManager.startRanging(eq(TEST_SESSION_ID), anyString()))
3504                 .thenReturn((byte) UwbUciConstants.STATUS_CODE_OK);
3505 
3506         mUwbSessionManager.startRanging(
3507                 uwbSession.getSessionHandle(), uwbSession.getParams());
3508         mTestLooper.dispatchAll();
3509 
3510         // In this scenario, there is no SESSION_STATUS_NTF received, so send an undefined
3511         // reasonCode (-1).
3512         verify(mUwbSessionNotificationManager).onRangingStartFailedWithUciReasonCode(
3513                 eq(uwbSession), eq(-1));
3514         verify(mUwbMetrics).longRangingStartEvent(
3515                 eq(uwbSession), eq(UwbUciConstants.STATUS_CODE_FAILED));
3516     }
3517 
3518     @Test
execStartRanging_sessionStateIdle_reasonSessionKeyNotFound()3519     public void execStartRanging_sessionStateIdle_reasonSessionKeyNotFound() throws Exception {
3520         UwbSession uwbSession = prepareExistingUwbSession();
3521 
3522         // set up for start ranging - it fails and session_state stays at IDLE.
3523         doReturn(UwbUciConstants.UWB_SESSION_STATE_IDLE).when(uwbSession).getSessionState();
3524         when(mNativeUwbManager.startRanging(eq(TEST_SESSION_ID), anyString()))
3525                 .thenReturn((byte) UwbUciConstants.STATUS_CODE_OK);
3526 
3527         // UWBS sends the SESSION_STATS_NTF with ReasonCode as REASON_ERROR_SESSION_KEY_NOT_FOUND.
3528         mUwbSessionManager.onSessionStatusNotificationReceived(
3529                 TEST_SESSION_ID, SESSION_TOKEN,
3530                 UwbUciConstants.UWB_SESSION_STATE_IDLE,
3531                 UwbUciConstants.REASON_ERROR_SESSION_KEY_NOT_FOUND);
3532 
3533         mUwbSessionManager.startRanging(
3534                 uwbSession.getSessionHandle(), uwbSession.getParams());
3535         mTestLooper.dispatchAll();
3536 
3537         verify(mUwbSessionNotificationManager).onRangingStartFailedWithUciReasonCode(
3538                 eq(uwbSession), eq(UwbUciConstants.REASON_ERROR_SESSION_KEY_NOT_FOUND));
3539         verify(mUwbMetrics).longRangingStartEvent(
3540                 eq(uwbSession), eq(UwbUciConstants.STATUS_CODE_ERROR_SESSION_NOT_EXIST));
3541     }
3542 
doTest_sendData_success_validUwbSession(byte[] macAddress, int dataTransferStatus)3543     private void doTest_sendData_success_validUwbSession(byte[] macAddress, int dataTransferStatus)
3544             throws Exception {
3545         UwbAddress uwbAddress = UwbAddress.fromBytes(macAddress);
3546         UwbSession uwbSession = prepareExistingUwbSession();
3547 
3548         // Setup the UwbSession to start ranging (and move it to active state).
3549         doReturn(UwbUciConstants.UWB_SESSION_STATE_IDLE).when(uwbSession).getSessionState();
3550         when(mNativeUwbManager.startRanging(eq(TEST_SESSION_ID), anyString()))
3551                 .thenReturn((byte) UwbUciConstants.STATUS_CODE_OK);
3552 
3553         mUwbSessionManager.startRanging(uwbSession.getSessionHandle(), uwbSession.getParams());
3554         mTestLooper.dispatchAll();
3555         doReturn(UwbUciConstants.UWB_SESSION_STATE_ACTIVE).when(uwbSession).getSessionState();
3556 
3557         // Send data on the UWB session.
3558         when(mNativeUwbManager.sendData(eq(TEST_SESSION_ID), eq(macAddress),
3559                 eq(DATA_SEQUENCE_NUM), eq(DATA_PAYLOAD), eq(TEST_CHIP_ID)))
3560                 .thenReturn((byte) UwbUciConstants.STATUS_CODE_OK);
3561 
3562         mUwbSessionManager.sendData(
3563                 uwbSession.getSessionHandle(), uwbAddress, PERSISTABLE_BUNDLE, DATA_PAYLOAD);
3564         mTestLooper.dispatchNext();
3565 
3566         verify(mNativeUwbManager).sendData(eq(TEST_SESSION_ID), eq(macAddress),
3567                 eq(DATA_SEQUENCE_NUM), eq(DATA_PAYLOAD), eq(TEST_CHIP_ID));
3568 
3569         // A DataTransferStatusNtf is received indicating success.
3570         mUwbSessionManager.onDataSendStatus(
3571                 uwbSession.getSessionId(), dataTransferStatus, DATA_SEQUENCE_NUM,
3572                 DATA_TRANSMISSION_COUNT);
3573         verify(mUwbSessionNotificationManager).onDataSent(
3574                 eq(uwbSession), eq(uwbAddress), eq(PERSISTABLE_BUNDLE));
3575         verify(mUwbMetrics).logDataTx(eq(uwbSession), eq(UwbUciConstants.STATUS_CODE_OK));
3576     }
3577 
3578     // Test case for scenario when a Data packet is successfully sent to a remote device (in
3579     // extended MacAddress format). The DataTransferStatus notification returns a success status
3580     // code (STATUS_CODE_DATA_TRANSFER_REPETITION_OK).
3581     @Test
sendData_success_validUwbSession_extendedMacAddress_statusRepetitionOk()3582     public void sendData_success_validUwbSession_extendedMacAddress_statusRepetitionOk()
3583             throws Exception {
3584         doTest_sendData_success_validUwbSession(
3585                 PEER_EXTENDED_MAC_ADDRESS, STATUS_CODE_DATA_TRANSFER_REPETITION_OK);
3586     }
3587 
3588     // Test case for scenario when a Data packet is successfully sent to a remote device (in
3589     // extended MacAddress format). The DataTransferStatus notification returns a success status
3590     // code (STATUS_CODE_OK).
3591     @Test
sendData_success_validUwbSession_extendedMacAddress_statusOk()3592     public void sendData_success_validUwbSession_extendedMacAddress_statusOk()
3593             throws Exception {
3594         doTest_sendData_success_validUwbSession(PEER_EXTENDED_MAC_ADDRESS, STATUS_CODE_OK);
3595     }
3596 
3597     // Test case for scenario when a Data packet is successfully sent to a remote device (in
3598     // short MacAddress format). The DataTransferStatus notification returns a success status
3599     // code (STATUS_CODE_DATA_TRANSFER_REPETITION_OK).
3600     @Test
sendData_success_validUwbSession_shortMacAddress_statusRepetitionOk()3601     public void sendData_success_validUwbSession_shortMacAddress_statusRepetitionOk()
3602             throws Exception {
3603         doTest_sendData_success_validUwbSession(
3604                 PEER_EXTENDED_SHORT_MAC_ADDRESS, STATUS_CODE_DATA_TRANSFER_REPETITION_OK);
3605     }
3606 
3607     // Test case for scenario when a Data packet is successfully sent to a remote device (in
3608     // short MacAddress format). The DataTransferStatus notification returns a success status
3609     // code (STATUS_CODE_OK).
3610     @Test
sendData_success_validUwbSession_shortMacAddress_statusOk()3611     public void sendData_success_validUwbSession_shortMacAddress_statusOk() throws Exception {
3612         doTest_sendData_success_validUwbSession(PEER_EXTENDED_SHORT_MAC_ADDRESS, STATUS_CODE_OK);
3613     }
3614 
3615     @Test
sendData_missingSessionHandle()3616     public void sendData_missingSessionHandle() throws Exception {
3617         // Setup a UwbSession to start ranging (and move it to active state).
3618         prepareExistingUwbSessionActive();
3619 
3620         // Send a Data packet with null SessionHandle, it should result in an error.
3621         mUwbSessionManager.sendData(
3622                 null /* sessionHandle */, PEER_EXTENDED_UWB_ADDRESS, PERSISTABLE_BUNDLE,
3623                 DATA_PAYLOAD);
3624         mTestLooper.dispatchNext();
3625 
3626         verify(mNativeUwbManager, never()).sendData(
3627                 eq(TEST_SESSION_ID), eq(PEER_EXTENDED_UWB_ADDRESS.toBytes()),
3628                 eq(DATA_SEQUENCE_NUM), eq(DATA_PAYLOAD), eq(TEST_CHIP_ID));
3629         verify(mUwbSessionNotificationManager).onDataSendFailed(
3630                 eq(null), eq(PEER_EXTENDED_UWB_ADDRESS),
3631                 eq(UwbUciConstants.STATUS_CODE_ERROR_SESSION_NOT_EXIST), eq(PERSISTABLE_BUNDLE));
3632     }
3633 
3634     @Test
sendData_invalidUwbSessionHandle()3635     public void sendData_invalidUwbSessionHandle() throws Exception {
3636         // Setup a uwbSession UwbSession to start ranging (and move it to active state), and a
3637         // different sessionHandle that doesn't map to the uwbSession.
3638         prepareExistingUwbSessionActive();
3639         SessionHandle sessionHandle = new SessionHandle(HANDLE_ID, ATTRIBUTION_SOURCE, PID);
3640 
3641         // Send a Data packet on the non-active UWB Session.
3642         mUwbSessionManager.sendData(
3643                 sessionHandle, PEER_EXTENDED_UWB_ADDRESS, PERSISTABLE_BUNDLE, DATA_PAYLOAD);
3644         mTestLooper.dispatchNext();
3645 
3646         verify(mNativeUwbManager, never()).sendData(
3647                 eq(TEST_SESSION_ID), eq(PEER_EXTENDED_UWB_ADDRESS.toBytes()),
3648                 eq(DATA_SEQUENCE_NUM), eq(DATA_PAYLOAD), eq(TEST_CHIP_ID));
3649         verify(mUwbSessionNotificationManager).onDataSendFailed(
3650                 eq(null), eq(PEER_EXTENDED_UWB_ADDRESS),
3651                 eq(UwbUciConstants.STATUS_CODE_ERROR_SESSION_NOT_EXIST), eq(PERSISTABLE_BUNDLE));
3652     }
3653 
3654     @Test
sendData_invalidUwbSessionState()3655     public void sendData_invalidUwbSessionState() throws Exception {
3656         // Setup a uwbSession and don't start ranging, so it remains in IDLE state.
3657         UwbSession uwbSession = prepareExistingUwbSession();
3658         doReturn(UwbUciConstants.UWB_SESSION_STATE_IDLE).when(uwbSession).getSessionState();
3659 
3660         // Attempt to send data on the UWB session.
3661         mUwbSessionManager.sendData(
3662                 uwbSession.getSessionHandle(), PEER_EXTENDED_UWB_ADDRESS, PERSISTABLE_BUNDLE, null);
3663         mTestLooper.dispatchNext();
3664 
3665         verify(mNativeUwbManager, never()).sendData(
3666                 eq(TEST_SESSION_ID), eq(PEER_EXTENDED_UWB_ADDRESS.toBytes()),
3667                 eq(DATA_SEQUENCE_NUM), eq(DATA_PAYLOAD), eq(TEST_CHIP_ID));
3668         verify(mUwbSessionNotificationManager).onDataSendFailed(
3669                 eq(uwbSession), eq(PEER_EXTENDED_UWB_ADDRESS),
3670                 eq(UwbUciConstants.STATUS_CODE_FAILED), eq(PERSISTABLE_BUNDLE));
3671     }
3672 
3673     @Test
sendData_missingDataPayload()3674     public void sendData_missingDataPayload() throws Exception {
3675         // Setup a uwbSession UwbSession to start ranging (and move it to active state).
3676         UwbSession uwbSession = prepareExistingUwbSessionActive();
3677 
3678         // Attempt to send data on the UWB session.
3679         mUwbSessionManager.sendData(
3680                 uwbSession.getSessionHandle(), PEER_EXTENDED_UWB_ADDRESS, PERSISTABLE_BUNDLE, null);
3681         mTestLooper.dispatchNext();
3682 
3683         verify(mNativeUwbManager, never()).sendData(
3684                 eq(TEST_SESSION_ID), eq(PEER_EXTENDED_UWB_ADDRESS.toBytes()),
3685                 eq(DATA_SEQUENCE_NUM), eq(DATA_PAYLOAD), eq(TEST_CHIP_ID));
3686         verify(mUwbSessionNotificationManager).onDataSendFailed(
3687                 eq(uwbSession), eq(PEER_EXTENDED_UWB_ADDRESS),
3688                 eq(UwbUciConstants.STATUS_CODE_INVALID_PARAM), eq(PERSISTABLE_BUNDLE));
3689     }
3690 
3691     @Test
sendData_missingRemoteDevice()3692     public void sendData_missingRemoteDevice() throws Exception {
3693         // Setup a uwbSession UwbSession to start ranging (and move it to active state).
3694         UwbSession uwbSession = prepareExistingUwbSessionActive();
3695 
3696         // Attempt to send data on the UWB session.
3697         mUwbSessionManager.sendData(
3698                 uwbSession.getSessionHandle(), null, PERSISTABLE_BUNDLE, DATA_PAYLOAD);
3699         mTestLooper.dispatchNext();
3700 
3701         verify(mNativeUwbManager, never()).sendData(
3702                 eq(TEST_SESSION_ID), eq(PEER_EXTENDED_UWB_ADDRESS.toBytes()),
3703                 eq(DATA_SEQUENCE_NUM), eq(DATA_PAYLOAD), eq(TEST_CHIP_ID));
3704         verify(mUwbSessionNotificationManager).onDataSendFailed(
3705                 eq(uwbSession), eq(null),
3706                 eq(UwbUciConstants.STATUS_CODE_INVALID_PARAM), eq(PERSISTABLE_BUNDLE));
3707     }
3708 
3709     @Test
sendData_dataSendFailure()3710     public void sendData_dataSendFailure() throws Exception {
3711         // Setup a uwbSession UwbSession to start ranging (and move it to active state).
3712         UwbSession uwbSession = prepareExistingUwbSessionActive();
3713 
3714         // Attempt to send data on the UWB session.
3715         when(mNativeUwbManager.sendData(eq(TEST_SESSION_ID),
3716                 eq(PEER_EXTENDED_UWB_ADDRESS.toBytes()),
3717                 eq(DATA_SEQUENCE_NUM), eq(DATA_PAYLOAD), eq(TEST_CHIP_ID)))
3718                 .thenReturn((byte) UwbUciConstants.STATUS_CODE_FAILED);
3719 
3720         mUwbSessionManager.sendData(uwbSession.getSessionHandle(), PEER_EXTENDED_UWB_ADDRESS,
3721                 PERSISTABLE_BUNDLE, DATA_PAYLOAD);
3722         mTestLooper.dispatchNext();
3723 
3724         verify(mNativeUwbManager).sendData(eq(TEST_SESSION_ID),
3725                 eq(PEER_EXTENDED_UWB_ADDRESS.toBytes()),
3726                 eq(DATA_SEQUENCE_NUM), eq(DATA_PAYLOAD), eq(TEST_CHIP_ID));
3727         verify(mUwbSessionNotificationManager).onDataSendFailed(
3728                 eq(uwbSession), eq(PEER_EXTENDED_UWB_ADDRESS),
3729                 eq(UwbUciConstants.STATUS_CODE_FAILED), eq(PERSISTABLE_BUNDLE));
3730         verify(mUwbMetrics).logDataTx(eq(uwbSession), eq(UwbUciConstants.STATUS_CODE_FAILED));
3731     }
3732 
3733     @Test
onDataSendStatus_sessionNotFound()3734     public void onDataSendStatus_sessionNotFound() throws Exception {
3735         // Setup a uwbSession UwbSession to start ranging (and move it to active state).
3736         UwbSession uwbSession = prepareExistingUwbSessionActive();
3737         clearInvocations(mUwbSessionNotificationManager);
3738 
3739         // Send data on the UWB session.
3740         when(mNativeUwbManager.sendData(eq(TEST_SESSION_ID),
3741                 eq(PEER_EXTENDED_UWB_ADDRESS.toBytes()),
3742                 eq(DATA_SEQUENCE_NUM), eq(DATA_PAYLOAD), eq(TEST_CHIP_ID)))
3743                 .thenReturn((byte) UwbUciConstants.STATUS_CODE_OK);
3744 
3745         mUwbSessionManager.sendData(uwbSession.getSessionHandle(), PEER_EXTENDED_UWB_ADDRESS,
3746                 PERSISTABLE_BUNDLE, DATA_PAYLOAD);
3747         mTestLooper.dispatchNext();
3748 
3749         verify(mNativeUwbManager).sendData(eq(TEST_SESSION_ID),
3750                 eq(PEER_EXTENDED_UWB_ADDRESS.toBytes()),
3751                 eq(DATA_SEQUENCE_NUM), eq(DATA_PAYLOAD), eq(TEST_CHIP_ID));
3752         verify(mUwbMetrics).logDataTx(eq(uwbSession), eq(UwbUciConstants.STATUS_CODE_OK));
3753 
3754         // We receive a DataTransferStatusNtf with a sessionId for a different UwbSession, so it
3755         // should be dropped (no onDataSend()/onDataSendFailure() notifications sent).
3756         mUwbSessionManager.onDataSendStatus(TEST_SESSION_ID_2, STATUS_CODE_OK, DATA_SEQUENCE_NUM,
3757                 DATA_TRANSMISSION_COUNT);
3758         verifyNoMoreInteractions(mUwbSessionNotificationManager);
3759     }
3760 
3761     @Test
onDataSendStatus_dataSndPacketNotFound()3762     public void onDataSendStatus_dataSndPacketNotFound() throws Exception {
3763         // Setup a uwbSession UwbSession to start ranging (and move it to active state).
3764         UwbSession uwbSession = prepareExistingUwbSessionActive();
3765         clearInvocations(mUwbSessionNotificationManager);
3766 
3767         // Send data on the UWB session.
3768         when(mNativeUwbManager.sendData(eq(TEST_SESSION_ID),
3769                 eq(PEER_EXTENDED_UWB_ADDRESS.toBytes()),
3770                 eq(DATA_SEQUENCE_NUM), eq(DATA_PAYLOAD), eq(TEST_CHIP_ID)))
3771                 .thenReturn((byte) UwbUciConstants.STATUS_CODE_OK);
3772 
3773         mUwbSessionManager.sendData(uwbSession.getSessionHandle(), PEER_EXTENDED_UWB_ADDRESS,
3774                 PERSISTABLE_BUNDLE, DATA_PAYLOAD);
3775         mTestLooper.dispatchNext();
3776 
3777         verify(mNativeUwbManager).sendData(eq(TEST_SESSION_ID),
3778                 eq(PEER_EXTENDED_UWB_ADDRESS.toBytes()),
3779                 eq(DATA_SEQUENCE_NUM), eq(DATA_PAYLOAD), eq(TEST_CHIP_ID));
3780         verify(mUwbMetrics).logDataTx(eq(uwbSession), eq(UwbUciConstants.STATUS_CODE_OK));
3781 
3782         // We receive a DataTransferStatusNtf with an incorrect UCI sequence number (for which a
3783         // packet was never sent), so it should be dropped (no onDataSend()/onDataSendFailure()
3784         // notifications sent).
3785         mUwbSessionManager.onDataSendStatus(TEST_SESSION_ID, STATUS_CODE_OK, DATA_SEQUENCE_NUM_1,
3786                 DATA_TRANSMISSION_COUNT);
3787         verifyNoMoreInteractions(mUwbSessionNotificationManager);
3788     }
3789 
3790     @Test
onDataSendStatus_errorStatus()3791     public void onDataSendStatus_errorStatus() throws Exception {
3792         // Setup a uwbSession UwbSession to start ranging (and move it to active state).
3793         UwbSession uwbSession = prepareExistingUwbSessionActive();
3794         clearInvocations(mUwbSessionNotificationManager);
3795 
3796         // Send data on the UWB session.
3797         when(mNativeUwbManager.sendData(eq(TEST_SESSION_ID),
3798                 eq(PEER_EXTENDED_UWB_ADDRESS.toBytes()),
3799                 eq(DATA_SEQUENCE_NUM), eq(DATA_PAYLOAD), eq(TEST_CHIP_ID)))
3800                 .thenReturn((byte) UwbUciConstants.STATUS_CODE_OK);
3801 
3802         mUwbSessionManager.sendData(uwbSession.getSessionHandle(), PEER_EXTENDED_UWB_ADDRESS,
3803                 PERSISTABLE_BUNDLE, DATA_PAYLOAD);
3804         mTestLooper.dispatchNext();
3805 
3806         verify(mNativeUwbManager).sendData(eq(TEST_SESSION_ID),
3807                 eq(PEER_EXTENDED_UWB_ADDRESS.toBytes()),
3808                 eq(DATA_SEQUENCE_NUM), eq(DATA_PAYLOAD), eq(TEST_CHIP_ID));
3809         verify(mUwbMetrics).logDataTx(eq(uwbSession), eq(UwbUciConstants.STATUS_CODE_OK));
3810 
3811         // We receive a DataTransferStatusNtf with an error status code.
3812         mUwbSessionManager.onDataSendStatus(TEST_SESSION_ID,
3813                 STATUS_CODE_DATA_TRANSFER_ERROR_DATA_TRANSFER, DATA_SEQUENCE_NUM,
3814                 DATA_TRANSMISSION_COUNT);
3815         verify(mUwbSessionNotificationManager).onDataSendFailed(
3816                 eq(uwbSession), eq(PEER_EXTENDED_UWB_ADDRESS),
3817                 eq(STATUS_CODE_DATA_TRANSFER_ERROR_DATA_TRANSFER), eq(PERSISTABLE_BUNDLE));
3818     }
3819 
3820     @Test
onDataSendStatus_neverReceived()3821     public void onDataSendStatus_neverReceived() throws Exception {
3822         // Setup a uwbSession UwbSession to start ranging (and move it to active state).
3823         UwbSession uwbSession = prepareExistingUwbSessionActive();
3824         clearInvocations(mUwbSessionNotificationManager);
3825 
3826         // Send data on the UWB session.
3827         when(mNativeUwbManager.sendData(eq(TEST_SESSION_ID),
3828                 eq(PEER_EXTENDED_UWB_ADDRESS.toBytes()),
3829                 eq(DATA_SEQUENCE_NUM), eq(DATA_PAYLOAD), eq(TEST_CHIP_ID)))
3830                 .thenReturn((byte) UwbUciConstants.STATUS_CODE_OK);
3831 
3832         mUwbSessionManager.sendData(uwbSession.getSessionHandle(), PEER_EXTENDED_UWB_ADDRESS,
3833                 PERSISTABLE_BUNDLE, DATA_PAYLOAD);
3834         mTestLooper.dispatchNext();
3835 
3836         verify(mNativeUwbManager).sendData(eq(TEST_SESSION_ID),
3837                 eq(PEER_EXTENDED_UWB_ADDRESS.toBytes()),
3838                 eq(DATA_SEQUENCE_NUM), eq(DATA_PAYLOAD), eq(TEST_CHIP_ID));
3839         verify(mUwbMetrics).logDataTx(eq(uwbSession), eq(UwbUciConstants.STATUS_CODE_OK));
3840 
3841         // We never receive a DataTransferStatusNtf, so no onDataSend()/onDataSendFailure()
3842         // notifications are sent.
3843         verifyNoMoreInteractions(mUwbSessionNotificationManager);
3844         assertNotNull(uwbSession.getSendDataInfo(DATA_SEQUENCE_NUM));
3845 
3846         // Eventually Session DeInit is called, and the stored SendDataInfo(s) should be deleted.
3847         mUwbSessionManager.deInitSession(uwbSession.getSessionHandle());
3848         mTestLooper.dispatchNext();
3849         assertNull(uwbSession.getSendDataInfo(DATA_SEQUENCE_NUM));
3850     }
3851 
3852     // Test case for scenario when a Data packet is successfully sent to a remote device (in
3853     // short MacAddress format). Verifies the deletion of stored data depending upon the status
3854     // code (STATUS_CODE_DATA_TRANSFER_REPETITION_OK) when data repetition count = 0.
3855     @Test
sendData_withZeroDataRepetitionCount()3856     public void sendData_withZeroDataRepetitionCount() throws Exception {
3857         FiraOpenSessionParams params = new FiraOpenSessionParams.Builder()
3858                 .setDeviceAddress(UwbAddress.fromBytes(new byte[] {(byte) 0x01, (byte) 0x02 }))
3859                 .setVendorId(new byte[] { (byte) 0x00, (byte) 0x01 })
3860                 .setStaticStsIV(new byte[] { (byte) 0x01, (byte) 0x02, (byte) 0x03,
3861                         (byte) 0x04, (byte) 0x05, (byte) 0x06 })
3862                 .setDestAddressList(Arrays.asList(
3863                         UWB_DEST_ADDRESS))
3864                 .setProtocolVersion(new FiraProtocolVersion(1, 0))
3865                 .setSessionId(10)
3866                 .setSessionType(FiraParams.SESSION_TYPE_RANGING_AND_IN_BAND_DATA)
3867                 .setDeviceType(FiraParams.RANGING_DEVICE_TYPE_CONTROLLER)
3868                 .setDeviceRole(FiraParams.RANGING_DEVICE_ROLE_INITIATOR)
3869                 .setMultiNodeMode(FiraParams.MULTI_NODE_MODE_UNICAST)
3870                 .setRangingIntervalMs(TEST_RANGING_INTERVAL_MS)
3871                 .setDataRepetitionCount(0)
3872                 .build();
3873         UwbSession uwbSession = prepareExistingUwbSessionActive(params);
3874         assertThat(uwbSession.getDataRepetitionCount()).isEqualTo(0);
3875 
3876         // Send the Data packet and simulate the onDataSendStatus() callback being received.
3877         mUwbSessionManager.sendData(
3878                 uwbSession.getSessionHandle(), PEER_EXTENDED_SHORT_UWB_ADDRESS, PERSISTABLE_BUNDLE,
3879                 DATA_PAYLOAD);
3880         mTestLooper.dispatchNext();
3881 
3882         // Since txCount is 0, stored data should not be deleted
3883         mUwbSessionManager.onDataSendStatus(TEST_SESSION_ID,
3884                 STATUS_CODE_DATA_TRANSFER_REPETITION_OK, DATA_SEQUENCE_NUM, 0);
3885         assertNotNull(uwbSession.getSendDataInfo(DATA_SEQUENCE_NUM));
3886 
3887         // Since txCount = DataRepetitionCount, stored data should removed
3888         mUwbSessionManager.onDataSendStatus(TEST_SESSION_ID,
3889                 STATUS_CODE_DATA_TRANSFER_OK, DATA_SEQUENCE_NUM, 1);
3890         assertNull(uwbSession.getSendDataInfo(DATA_SEQUENCE_NUM));
3891     }
3892 
3893     // Test case for scenario when a Data packet is successfully sent to a remote device (in
3894     // short MacAddress format). Verifies the deletion of stored data depending upon the status
3895     // code (STATUS_CODE_DATA_TRANSFER_REPETITION_OK) and data repetition count of the
3896     // DataTransferStatus notification.
3897     @Test
sendData_withNonZeroDataRepetitionCount()3898     public void sendData_withNonZeroDataRepetitionCount() throws Exception {
3899         FiraOpenSessionParams params = new FiraOpenSessionParams.Builder()
3900                 .setDeviceAddress(UwbAddress.fromBytes(new byte[] {(byte) 0x01, (byte) 0x02 }))
3901                 .setVendorId(new byte[] { (byte) 0x00, (byte) 0x01 })
3902                 .setStaticStsIV(new byte[] { (byte) 0x01, (byte) 0x02, (byte) 0x03,
3903                         (byte) 0x04, (byte) 0x05, (byte) 0x06 })
3904                 .setDestAddressList(Arrays.asList(
3905                         UWB_DEST_ADDRESS))
3906                 .setProtocolVersion(new FiraProtocolVersion(1, 0))
3907                 .setSessionId(10)
3908                 .setSessionType(FiraParams.SESSION_TYPE_RANGING_AND_IN_BAND_DATA)
3909                 .setDeviceType(FiraParams.RANGING_DEVICE_TYPE_CONTROLLER)
3910                 .setDeviceRole(FiraParams.RANGING_DEVICE_ROLE_INITIATOR)
3911                 .setMultiNodeMode(FiraParams.MULTI_NODE_MODE_UNICAST)
3912                 .setRangingIntervalMs(TEST_RANGING_INTERVAL_MS)
3913                 .setDataRepetitionCount(DATA_TRANSMISSION_COUNT_3)
3914                 .build();
3915         UwbSession uwbSession = prepareExistingUwbSessionActive(params);
3916         assertThat(uwbSession.getDataRepetitionCount()).isEqualTo(DATA_TRANSMISSION_COUNT_3);
3917 
3918         // Send the Data packet and simulate the onDataSendStatus() callback being received.
3919         mUwbSessionManager.sendData(
3920                 uwbSession.getSessionHandle(), PEER_EXTENDED_SHORT_UWB_ADDRESS, PERSISTABLE_BUNDLE,
3921                 DATA_PAYLOAD);
3922         mTestLooper.dispatchNext();
3923 
3924         mUwbSessionManager.onDataSendStatus(TEST_SESSION_ID,
3925                 STATUS_CODE_DATA_TRANSFER_REPETITION_OK, DATA_SEQUENCE_NUM,
3926                 DATA_TRANSMISSION_COUNT);
3927 
3928         // Since txCount < DataRepetitionCount, stored data should not be deleted
3929         assertNotNull(uwbSession.getSendDataInfo(DATA_SEQUENCE_NUM));
3930 
3931         // Now simulate the onDataSendStatus() callback being received with a higher TxCount value.
3932         mUwbSessionManager.onDataSendStatus(TEST_SESSION_ID,
3933                 STATUS_CODE_DATA_TRANSFER_OK, DATA_SEQUENCE_NUM,
3934                 DATA_TRANSMISSION_COUNT_3 + 1);
3935 
3936         // Since txCount = DataRepetitionCount, stored data should removed
3937         assertNull(uwbSession.getSendDataInfo(DATA_SEQUENCE_NUM));
3938     }
3939 
3940     @Test
stopRanging_sessionStateActive()3941     public void stopRanging_sessionStateActive() throws Exception {
3942         UwbSession uwbSession = prepareExistingUwbSession();
3943         // set up for stop ranging
3944         doReturn(UwbUciConstants.UWB_SESSION_STATE_ACTIVE).when(uwbSession).getSessionState();
3945 
3946         mUwbSessionManager.stopRanging(uwbSession.getSessionHandle());
3947 
3948         assertThat(mTestLooper.nextMessage().what).isEqualTo(3); // SESSION_STOP_RANGING
3949     }
3950 
3951     @Test
stopRanging_sessionStateIdle()3952     public void stopRanging_sessionStateIdle() throws Exception {
3953         UwbSession uwbSession = prepareExistingUwbSession();
3954         // set up for stop ranging
3955         doReturn(UwbUciConstants.UWB_SESSION_STATE_IDLE).when(uwbSession).getSessionState();
3956 
3957         mUwbSessionManager.stopRanging(uwbSession.getSessionHandle());
3958 
3959         verify(mUwbSessionNotificationManager).onRangingStopped(
3960                 eq(uwbSession),
3961                 eq(UwbUciConstants.REASON_STATE_CHANGE_WITH_SESSION_MANAGEMENT_COMMANDS));
3962         verify(mUwbMetrics).longRangingStopEvent(eq(uwbSession));
3963     }
3964 
3965     @Test
stopRanging_sessionStateError()3966     public void stopRanging_sessionStateError() throws Exception {
3967         UwbSession uwbSession = prepareExistingUwbSession();
3968         // set up for stop ranging
3969         doReturn(UwbUciConstants.UWB_SESSION_STATE_ERROR).when(uwbSession).getSessionState();
3970 
3971         mUwbSessionManager.stopRanging(uwbSession.getSessionHandle());
3972 
3973         verify(mUwbSessionNotificationManager).onRangingStopFailed(
3974                 eq(uwbSession), eq(UwbUciConstants.STATUS_CODE_REJECTED));
3975     }
3976 
3977     @Test
execStopRanging_success()3978     public void execStopRanging_success() throws Exception {
3979         UwbSession uwbSession = prepareExistingUwbSession();
3980         doReturn(UwbUciConstants.UWB_SESSION_STATE_ACTIVE, UwbUciConstants.UWB_SESSION_STATE_IDLE)
3981                 .when(uwbSession).getSessionState();
3982         when(mNativeUwbManager.stopRanging(eq(TEST_SESSION_ID), anyString()))
3983                 .thenReturn((byte) UwbUciConstants.STATUS_CODE_OK);
3984 
3985         mUwbSessionManager.stopRanging(uwbSession.getSessionHandle());
3986         mTestLooper.dispatchNext();
3987 
3988         verify(mUwbInjector).runTaskOnSingleThreadExecutor(
3989                 any(), eq(IUwbAdapter.RANGING_SESSION_START_THRESHOLD_MS));
3990         verify(mUwbSessionNotificationManager)
3991                 .onRangingStoppedWithApiReasonCode(eq(uwbSession),
3992                         eq(RangingChangeReason.LOCAL_API), any());
3993         verify(mUwbMetrics).longRangingStopEvent(eq(uwbSession));
3994     }
3995 
3996     @Test
execStopRanging_exception()3997     public void execStopRanging_exception() throws Exception {
3998         UwbSession uwbSession = prepareExistingUwbSession();
3999         doReturn(UwbUciConstants.UWB_SESSION_STATE_ACTIVE, UwbUciConstants.UWB_SESSION_STATE_IDLE)
4000                 .when(uwbSession).getSessionState();
4001         when(mNativeUwbManager.stopRanging(eq(TEST_SESSION_ID), anyString()))
4002                 .thenThrow(new IllegalStateException());
4003 
4004         mUwbSessionManager.stopRanging(uwbSession.getSessionHandle());
4005         mTestLooper.dispatchNext();
4006 
4007         verify(mUwbSessionNotificationManager, never()).onRangingStopped(any(), anyInt());
4008     }
4009 
4010     @Test
execStopRanging_nativeFailed()4011     public void execStopRanging_nativeFailed() throws Exception {
4012         UwbSession uwbSession = prepareExistingUwbSession();
4013         doReturn(UwbUciConstants.UWB_SESSION_STATE_ACTIVE).when(uwbSession).getSessionState();
4014         when(mNativeUwbManager.stopRanging(eq(TEST_SESSION_ID), anyString()))
4015                 .thenReturn((byte) UwbUciConstants.STATUS_CODE_FAILED);
4016 
4017         mUwbSessionManager.stopRanging(uwbSession.getSessionHandle());
4018         mTestLooper.dispatchNext();
4019 
4020         verify(mUwbSessionNotificationManager)
4021                 .onRangingStopFailed(eq(uwbSession), eq(UwbUciConstants.STATUS_CODE_FAILED));
4022         verify(mUwbMetrics, never()).longRangingStopEvent(eq(uwbSession));
4023     }
4024 
4025     @Test
testFiraSessionStoppedDuetoInbandSignal()4026     public void testFiraSessionStoppedDuetoInbandSignal() throws Exception {
4027         //Assuming that when session is in active state,
4028         //in-band signal is received and session moved IDLE state
4029         UwbSession uwbSession = prepareExistingUwbSession();
4030         doReturn(UwbUciConstants.UWB_SESSION_STATE_ACTIVE, UwbUciConstants.UWB_SESSION_STATE_IDLE)
4031                 .when(uwbSession).getSessionState();
4032         when(mNativeUwbManager.stopRanging(eq(TEST_SESSION_ID), anyString()))
4033                 .thenReturn((byte) UwbUciConstants.STATUS_CODE_REJECTED);
4034 
4035         mUwbSessionManager.stopRanging(uwbSession.getSessionHandle());
4036         mTestLooper.dispatchNext();
4037         verify(mUwbSessionNotificationManager)
4038                 .onRangingStoppedWithApiReasonCode(eq(uwbSession),
4039                 eq(RangingChangeReason.SYSTEM_POLICY), any());
4040     }
4041 
4042     @Test
testCCCSessionStoppedDuetoInbandSignal()4043     public void testCCCSessionStoppedDuetoInbandSignal() throws Exception {
4044         UwbSession uwbSession = prepareExistingCccUwbSession();
4045         CccRangingStartedParams cccRangingStartedParams = new CccRangingStartedParams.Builder()
4046                 .setStartingStsIndex(0)
4047                 .setUwbTime0(1)
4048                 .setHopModeKey(0)
4049                 .setSyncCodeIndex(1)
4050                 .setRanMultiplier(4)
4051                 .build();
4052         do_sessionStoppedDuetoInbandSignal(
4053                 uwbSession, cccRangingStartedParams, CccParams.PROTOCOL_VERSION_1_0);
4054     }
4055 
4056     @Test
testAliroSessionStoppedDuetoInbandSignal()4057     public void testAliroSessionStoppedDuetoInbandSignal() throws Exception {
4058         UwbSession uwbSession = prepareExistingAliroUwbSession();
4059         AliroRangingStartedParams aliroRangingStartedParams =
4060                 new AliroRangingStartedParams.Builder()
4061                         .setStartingStsIndex(0)
4062                         .setUwbTime0(1)
4063                         .setHopModeKey(0)
4064                         .setSyncCodeIndex(1)
4065                         .setRanMultiplier(4)
4066                         .build();
4067         do_sessionStoppedDuetoInbandSignal(
4068                 uwbSession, aliroRangingStartedParams, AliroParams.PROTOCOL_VERSION_1_0);
4069     }
4070 
do_sessionStoppedDuetoInbandSignal(UwbSession uwbSession, Params rangingStartedParams, ProtocolVersion protocolVersion)4071     private void do_sessionStoppedDuetoInbandSignal(UwbSession uwbSession,
4072              Params rangingStartedParams, ProtocolVersion protocolVersion) throws Exception {
4073         // Assuming that when session is in active state, an in-band signal is received and the
4074         // session is moved to IDLE state.
4075         when(mUwbConfigurationManager.getAppConfigurations(
4076                 eq(TEST_SESSION_ID), anyString(), any(), any(), eq(TEST_CHIP_ID),
4077                 eq(protocolVersion)))
4078                 .thenReturn(new Pair<>(UwbUciConstants.STATUS_CODE_OK, rangingStartedParams));
4079         doReturn(UwbUciConstants.UWB_SESSION_STATE_ACTIVE, UwbUciConstants.UWB_SESSION_STATE_IDLE)
4080                 .when(uwbSession).getSessionState();
4081         when(mNativeUwbManager.stopRanging(eq(TEST_SESSION_ID), anyString()))
4082                 .thenReturn((byte) UwbUciConstants.STATUS_CODE_REJECTED);
4083 
4084         mUwbSessionManager.stopRanging(uwbSession.getSessionHandle());
4085         mTestLooper.dispatchNext();
4086         verify(mUwbSessionNotificationManager)
4087                 .onRangingStoppedWithApiReasonCode(eq(uwbSession),
4088                         eq(RangingChangeReason.SYSTEM_POLICY), any());
4089     }
4090 
4091     @Test
reconfigure_notExistingSession()4092     public void reconfigure_notExistingSession() {
4093         int status = mUwbSessionManager.reconfigure(mock(SessionHandle.class), mock(Params.class));
4094 
4095         assertThat(status).isEqualTo(UwbUciConstants.STATUS_CODE_ERROR_SESSION_NOT_EXIST);
4096     }
4097 
buildReconfigureParams()4098     private FiraRangingReconfigureParams buildReconfigureParams() {
4099         return buildReconfigureParams(FiraParams.MULTICAST_LIST_UPDATE_ACTION_ADD);
4100     }
4101 
buildReconfigureParams(int action)4102     private FiraRangingReconfigureParams buildReconfigureParams(int action) {
4103         FiraRangingReconfigureParams reconfigureParams =
4104                 new FiraRangingReconfigureParams.Builder()
4105                         .setAddressList(new UwbAddress[] {
4106                                 UwbAddress.fromBytes(new byte[] { (byte) 0x01, (byte) 0x02 }) })
4107                         .setAction(action)
4108                         .setSubSessionIdList(new int[] { 2 })
4109                         .build();
4110 
4111         return spy(reconfigureParams);
4112     }
4113 
buildReconfigureParamsV2()4114     private FiraRangingReconfigureParams buildReconfigureParamsV2() {
4115         return buildReconfigureParamsV2(
4116                 FiraParams.P_STS_MULTICAST_LIST_UPDATE_ACTION_ADD_16_BYTE);
4117     }
4118 
buildReconfigureParamsV2(int action)4119     private FiraRangingReconfigureParams buildReconfigureParamsV2(int action) {
4120         FiraRangingReconfigureParams reconfigureParams =
4121                 new FiraRangingReconfigureParams.Builder()
4122                         .setAddressList(new UwbAddress[] {
4123                                 UwbAddress.fromBytes(new byte[] { (byte) 0x01, (byte) 0x02 }) })
4124                         .setAction(action)
4125                         .setSubSessionIdList(new int[] { 2 })
4126                         .setSubSessionKeyList(new byte[] {0, 0, 0, 0, 1, 1, 1, 1,
4127                                 2, 2, 2, 2, 3, 3, 3, 3})
4128                         .build();
4129 
4130         return spy(reconfigureParams);
4131     }
4132 
4133     @Test
reconfigure_existingSession()4134     public void reconfigure_existingSession() throws Exception {
4135         FiraOpenSessionParams firaParams = new
4136                 FiraOpenSessionParams.Builder(
4137                     (FiraOpenSessionParams) setupFiraParams(FIRA_VERSION_1_1))
4138                 .setSessionKey(new byte[]{0x5, 0x78, 0x5, 0x78, 0x5, 0x78, 0x5, 0x78, 0x5,
4139                     0x78, 0x5, 0x78, 0x5, 0x78, 0x5, 0x78})
4140                 .setStsConfig(FiraParams.STS_CONFIG_PROVISIONED_FOR_CONTROLEE_INDIVIDUAL_KEY)
4141                 .build();
4142         UwbSession uwbSession = prepareExistingUwbSession(firaParams);
4143 
4144         int status = mUwbSessionManager.reconfigure(
4145                 uwbSession.getSessionHandle(), buildReconfigureParamsV2());
4146 
4147         assertThat(status).isEqualTo(0);
4148         assertThat(mTestLooper.nextMessage().what).isEqualTo(4); // SESSION_RECONFIGURE_RANGING
4149     }
4150 
4151     @Test
execReconfigureAddControlee_success()4152     public void execReconfigureAddControlee_success() throws Exception {
4153         UwbSession uwbSession = prepareExistingUwbSession();
4154         FiraRangingReconfigureParams reconfigureParams =
4155                 buildReconfigureParams();
4156         UwbMulticastListUpdateStatus status = mock(UwbMulticastListUpdateStatus.class);
4157         when(mNativeUwbManager
4158                 .controllerMulticastListUpdate(anyInt(), anyInt(), anyInt(), any(), any(),
4159                         any(), anyString()))
4160                 .thenReturn(status);
4161         UwbMulticastListUpdateStatus uwbMulticastListUpdateStatus =
4162                 mock(UwbMulticastListUpdateStatus.class);
4163         when(uwbMulticastListUpdateStatus.getNumOfControlee()).thenReturn(1);
4164         when(uwbMulticastListUpdateStatus.getControleeUwbAddresses())
4165                 .thenReturn(new UwbAddress[] {UWB_DEST_ADDRESS_2});
4166         when(uwbMulticastListUpdateStatus.getStatus()).thenReturn(
4167                 new int[] { UwbUciConstants.STATUS_CODE_OK });
4168         doReturn(uwbMulticastListUpdateStatus).when(uwbSession).getMulticastListUpdateStatus();
4169         when(mUwbConfigurationManager.setAppConfigurations(anyInt(), any(), anyString(), any()))
4170                 .thenReturn(UwbUciConstants.STATUS_CODE_OK);
4171 
4172         mUwbSessionManager.reconfigure(uwbSession.getSessionHandle(), reconfigureParams);
4173         mTestLooper.dispatchNext();
4174 
4175         // Make sure the original address is still there.
4176         assertThat(uwbSession.getControleeList().stream()
4177                 .anyMatch(e -> e.getUwbAddress().equals(UWB_DEST_ADDRESS)))
4178                 .isTrue();
4179 
4180         // Make sure this new address was added.
4181         assertThat(uwbSession.getControleeList().stream()
4182                 .anyMatch(e -> e.getUwbAddress().equals(UWB_DEST_ADDRESS_2)))
4183                 .isTrue();
4184 
4185         byte[] dstAddress =
4186                 getComputedMacAddress(reconfigureParams.getAddressList()[0].toBytes());
4187         verify(mNativeUwbManager).controllerMulticastListUpdate(
4188                 uwbSession.getSessionId(), reconfigureParams.getAction(), 1,
4189                 dstAddress, reconfigureParams.getSubSessionIdList(), null,
4190                 uwbSession.getChipId());
4191         verify(mUwbSessionNotificationManager).onControleeAdded(eq(uwbSession));
4192         verify(mUwbSessionNotificationManager).onRangingReconfigured(eq(uwbSession));
4193     }
4194 
4195     @Test
execReconfigureAddControlee_failed()4196     public void execReconfigureAddControlee_failed() throws Exception {
4197         UwbSession uwbSession = prepareExistingUwbSession();
4198         FiraRangingReconfigureParams reconfigureParams =
4199                 buildReconfigureParamsV2(FiraParams.MULTICAST_LIST_UPDATE_ACTION_ADD);
4200 
4201         int status = mUwbSessionManager
4202                 .reconfigure(uwbSession.getSessionHandle(), reconfigureParams);
4203 
4204         assertThat(status).isEqualTo(UwbUciConstants.STATUS_CODE_REJECTED);
4205     }
4206 
4207     @Test
execReconfigureRemoveControleeV1_success()4208     public void execReconfigureRemoveControleeV1_success() throws Exception {
4209         UwbSession uwbSession = prepareExistingUwbSession();
4210         FiraRangingReconfigureParams reconfigureParams =
4211                 buildReconfigureParams(FiraParams.MULTICAST_LIST_UPDATE_ACTION_DELETE);
4212 
4213         UwbMulticastListUpdateStatus status = mock(UwbMulticastListUpdateStatus.class);
4214         when(mNativeUwbManager
4215                 .controllerMulticastListUpdate(anyInt(), anyInt(), anyInt(), any(), any(),
4216                         any(), anyString()))
4217                 .thenReturn(status);
4218         UwbMulticastListUpdateStatus uwbMulticastListUpdateStatus =
4219                 mock(UwbMulticastListUpdateStatus.class);
4220         when(uwbMulticastListUpdateStatus.getNumOfControlee()).thenReturn(1);
4221         when(uwbMulticastListUpdateStatus.getControleeUwbAddresses())
4222                 .thenReturn(new UwbAddress[] {UWB_DEST_ADDRESS});
4223         when(uwbMulticastListUpdateStatus.getStatus()).thenReturn(
4224                 new int[] { UwbUciConstants.STATUS_CODE_OK });
4225         doReturn(uwbMulticastListUpdateStatus).when(uwbSession).getMulticastListUpdateStatus();
4226         when(mUwbConfigurationManager.setAppConfigurations(anyInt(), any(), anyString(), any()))
4227                 .thenReturn(UwbUciConstants.STATUS_CODE_OK);
4228 
4229         // Make sure the address exists in the first place. This should have been set up by
4230         //  prepareExistingUwbSession
4231         assertThat(uwbSession.getControleeList().stream()
4232                 .anyMatch(e -> e.getUwbAddress().equals(UWB_DEST_ADDRESS)))
4233                 .isTrue();
4234 
4235         mUwbSessionManager.reconfigure(uwbSession.getSessionHandle(), reconfigureParams);
4236         mTestLooper.dispatchNext();
4237 
4238         // Make sure the address was removed.
4239         assertThat(uwbSession.getControleeList().stream()
4240                 .anyMatch(e -> e.getUwbAddress().equals(UWB_DEST_ADDRESS)))
4241                 .isFalse();
4242 
4243         byte[] dstAddress = getComputedMacAddress(reconfigureParams.getAddressList()[0].toBytes());
4244         verify(mNativeUwbManager).controllerMulticastListUpdate(
4245                 uwbSession.getSessionId(), reconfigureParams.getAction(), 1,
4246                 dstAddress, reconfigureParams.getSubSessionIdList(), null,
4247                 uwbSession.getChipId());
4248         verify(mUwbSessionNotificationManager).onControleeRemoved(eq(uwbSession),
4249                 eq(UWB_DEST_ADDRESS), anyInt());
4250         verify(mUwbSessionNotificationManager).onRangingReconfigured(eq(uwbSession));
4251     }
4252 
4253     @Test
execReconfigureRemoveControlee_failed()4254     public void execReconfigureRemoveControlee_failed() throws Exception {
4255         UwbSession uwbSession = prepareExistingUwbSession();
4256         FiraRangingReconfigureParams reconfigureParams =
4257                 buildReconfigureParamsV2(FiraParams.MULTICAST_LIST_UPDATE_ACTION_DELETE);
4258 
4259         int status = mUwbSessionManager
4260                 .reconfigure(uwbSession.getSessionHandle(), reconfigureParams);
4261 
4262         assertThat(status).isEqualTo(UwbUciConstants.STATUS_CODE_REJECTED);
4263     }
4264 
4265     @Test
execReconfigureAddControleeV2_success()4266     public void execReconfigureAddControleeV2_success() throws Exception {
4267         FiraOpenSessionParams firaParams = new
4268                 FiraOpenSessionParams.Builder(
4269                     (FiraOpenSessionParams) setupFiraParams(FIRA_VERSION_1_1))
4270                 .setSessionKey(new byte[]{0x5, 0x78, 0x5, 0x78, 0x5, 0x78, 0x5, 0x78, 0x5,
4271                     0x78, 0x5, 0x78, 0x5, 0x78, 0x5, 0x78})
4272                 .setStsConfig(FiraParams.STS_CONFIG_PROVISIONED_FOR_CONTROLEE_INDIVIDUAL_KEY)
4273                 .build();
4274         UwbSession uwbSession = prepareExistingUwbSession(firaParams);
4275         FiraRangingReconfigureParams reconfigureParams =
4276                 buildReconfigureParamsV2();
4277         UwbMulticastListUpdateStatus status = mock(UwbMulticastListUpdateStatus.class);
4278         when(mNativeUwbManager
4279                 .controllerMulticastListUpdate(anyInt(), anyInt(), anyInt(), any(), any(),
4280                                 any(), anyString()))
4281                 .thenReturn(status);
4282         UwbMulticastListUpdateStatus uwbMulticastListUpdateStatus =
4283                 mock(UwbMulticastListUpdateStatus.class);
4284         when(uwbMulticastListUpdateStatus.getNumOfControlee()).thenReturn(1);
4285         when(uwbMulticastListUpdateStatus.getControleeUwbAddresses())
4286                 .thenReturn(new UwbAddress[] {UWB_DEST_ADDRESS_2});
4287         when(uwbMulticastListUpdateStatus.getStatus()).thenReturn(
4288                 new int[] { UwbUciConstants.STATUS_CODE_OK });
4289         doReturn(uwbMulticastListUpdateStatus).when(uwbSession).getMulticastListUpdateStatus();
4290         when(mUwbConfigurationManager.setAppConfigurations(anyInt(), any(), anyString(), any()))
4291                 .thenReturn(UwbUciConstants.STATUS_CODE_OK);
4292 
4293         mUwbSessionManager.reconfigure(uwbSession.getSessionHandle(), reconfigureParams);
4294         mTestLooper.dispatchNext();
4295 
4296         // Make sure the original address is still there.
4297         assertThat(uwbSession.getControleeList().stream()
4298                 .anyMatch(e -> e.getUwbAddress().equals(UWB_DEST_ADDRESS)))
4299                 .isTrue();
4300 
4301         // Make sure this new address was added.
4302         assertThat(uwbSession.getControleeList().stream()
4303                 .anyMatch(e -> e.getUwbAddress().equals(UWB_DEST_ADDRESS_2)))
4304                 .isTrue();
4305 
4306         byte[] dstAddress = getComputedMacAddress(reconfigureParams.getAddressList()[0].toBytes());
4307         verify(mNativeUwbManager).controllerMulticastListUpdate(
4308                 uwbSession.getSessionId(), reconfigureParams.getAction(), 1,
4309                 dstAddress, reconfigureParams.getSubSessionIdList(),
4310                 reconfigureParams.getSubSessionKeyList(), uwbSession.getChipId());
4311         verify(mUwbSessionNotificationManager).onControleeAdded(eq(uwbSession));
4312         verify(mUwbSessionNotificationManager).onRangingReconfigured(eq(uwbSession));
4313     }
4314 
4315     @Test
execReconfigureAddControlee_fetchKeysFromSE_V2_success()4316     public void execReconfigureAddControlee_fetchKeysFromSE_V2_success() throws Exception {
4317         // When both sessionKey and subSessionKey are not provided from APP,
4318         // it will be fetched from SE
4319         FiraOpenSessionParams firaParams = new
4320                 FiraOpenSessionParams.Builder(
4321                     (FiraOpenSessionParams) setupFiraParams(FIRA_VERSION_1_1))
4322                 .setStsConfig(FiraParams.STS_CONFIG_PROVISIONED_FOR_CONTROLEE_INDIVIDUAL_KEY)
4323                 .build();
4324         UwbSession uwbSession = prepareExistingUwbSession(firaParams);
4325         FiraRangingReconfigureParams reconfigureParams =
4326                 buildReconfigureParams(FiraParams.P_STS_MULTICAST_LIST_UPDATE_ACTION_ADD_16_BYTE);
4327         UwbMulticastListUpdateStatus status = mock(UwbMulticastListUpdateStatus.class);
4328         when(mNativeUwbManager
4329                 .controllerMulticastListUpdate(anyInt(), anyInt(), anyInt(), any(), any(),
4330                                 any(), anyString()))
4331                 .thenReturn(status);
4332         UwbMulticastListUpdateStatus uwbMulticastListUpdateStatus =
4333                 mock(UwbMulticastListUpdateStatus.class);
4334         when(uwbMulticastListUpdateStatus.getNumOfControlee()).thenReturn(1);
4335         when(uwbMulticastListUpdateStatus.getControleeUwbAddresses())
4336                 .thenReturn(new UwbAddress[] {UWB_DEST_ADDRESS_2});
4337         when(uwbMulticastListUpdateStatus.getStatus()).thenReturn(
4338                 new int[] { UwbUciConstants.STATUS_CODE_OK });
4339         doReturn(uwbMulticastListUpdateStatus).when(uwbSession).getMulticastListUpdateStatus();
4340         when(mUwbConfigurationManager.setAppConfigurations(anyInt(), any(), anyString(), any()))
4341                 .thenReturn(UwbUciConstants.STATUS_CODE_OK);
4342 
4343         mUwbSessionManager.reconfigure(uwbSession.getSessionHandle(), reconfigureParams);
4344         mTestLooper.dispatchNext();
4345 
4346         // Make sure the original address is still there.
4347         assertThat(uwbSession.getControleeList().stream()
4348                 .anyMatch(e -> e.getUwbAddress().equals(UWB_DEST_ADDRESS)))
4349                 .isTrue();
4350 
4351         // Make sure this new address was added.
4352         assertThat(uwbSession.getControleeList().stream()
4353                 .anyMatch(e -> e.getUwbAddress().equals(UWB_DEST_ADDRESS_2)))
4354                 .isTrue();
4355 
4356         byte[] dstAddress = getComputedMacAddress(reconfigureParams.getAddressList()[0].toBytes());
4357         verify(mNativeUwbManager).controllerMulticastListUpdate(
4358                 uwbSession.getSessionId(), reconfigureParams.getAction(), 1,
4359                 dstAddress, reconfigureParams.getSubSessionIdList(),
4360                 reconfigureParams.getSubSessionKeyList(), uwbSession.getChipId());
4361         verify(mUwbSessionNotificationManager).onControleeAdded(eq(uwbSession));
4362         verify(mUwbSessionNotificationManager).onRangingReconfigured(eq(uwbSession));
4363     }
4364 
4365     @Test
execReconfigureAddControlee_onlyWithSessionKey_failed()4366     public void execReconfigureAddControlee_onlyWithSessionKey_failed() throws Exception {
4367         //If sessionKey is only provided from app, reconfigure will be rejected from sessionManager
4368         FiraOpenSessionParams firaParams = new
4369                 FiraOpenSessionParams.Builder(
4370                     (FiraOpenSessionParams) setupFiraParams(FIRA_VERSION_1_1))
4371                 .setSessionKey(new byte[]{0x5, 0x78, 0x5, 0x78, 0x5, 0x78, 0x5, 0x78, 0x5,
4372                     0x78, 0x5, 0x78, 0x5, 0x78, 0x5, 0x78})
4373                 .setStsConfig(FiraParams.STS_CONFIG_PROVISIONED_FOR_CONTROLEE_INDIVIDUAL_KEY)
4374                 .build();
4375         UwbSession uwbSession = prepareExistingUwbSession(firaParams);
4376         FiraRangingReconfigureParams reconfigureParams =
4377                 buildReconfigureParams(FiraParams.P_STS_MULTICAST_LIST_UPDATE_ACTION_ADD_16_BYTE);
4378 
4379         int status = mUwbSessionManager
4380                 .reconfigure(uwbSession.getSessionHandle(), reconfigureParams);
4381 
4382         assertThat(status).isEqualTo(UwbUciConstants.STATUS_CODE_REJECTED);
4383     }
4384 
4385     @Test
execReconfigureAddControlee_onlyWithSubSessionKey_failed()4386     public void execReconfigureAddControlee_onlyWithSubSessionKey_failed() throws Exception {
4387         //If subSessionKeyList is only provided from app,
4388         //reconfigure will be rejected from sessionManager
4389         FiraOpenSessionParams firaParams = new
4390                 FiraOpenSessionParams.Builder(
4391                     (FiraOpenSessionParams) setupFiraParams(FIRA_VERSION_1_1))
4392                 .setStsConfig(FiraParams.STS_CONFIG_PROVISIONED_FOR_CONTROLEE_INDIVIDUAL_KEY)
4393                 .build();
4394         UwbSession uwbSession = prepareExistingUwbSession(firaParams);
4395         FiraRangingReconfigureParams reconfigureParams =
4396                 buildReconfigureParamsV2();
4397 
4398         int status = mUwbSessionManager
4399                 .reconfigure(uwbSession.getSessionHandle(), reconfigureParams);
4400 
4401         assertThat(status).isEqualTo(UwbUciConstants.STATUS_CODE_REJECTED);
4402     }
4403 
4404     @Test
execReconfigure_nativeUpdateFailed()4405     public void execReconfigure_nativeUpdateFailed() throws Exception {
4406         FiraOpenSessionParams firaParams = new
4407                 FiraOpenSessionParams.Builder(
4408                     (FiraOpenSessionParams) setupFiraParams(FIRA_VERSION_1_1))
4409                 .setSessionKey(new byte[]{0x5, 0x78, 0x5, 0x78, 0x5, 0x78, 0x5, 0x78, 0x5,
4410                     0x78, 0x5, 0x78, 0x5, 0x78, 0x5, 0x78})
4411                 .setStsConfig(FiraParams.STS_CONFIG_PROVISIONED_FOR_CONTROLEE_INDIVIDUAL_KEY)
4412                 .build();
4413         UwbSession uwbSession = prepareExistingUwbSession(firaParams);
4414         FiraRangingReconfigureParams reconfigureParams =
4415                 buildReconfigureParamsV2();
4416         //return status > 0 indicates failure
4417         //TBD: update session and address from params
4418         UwbMulticastListUpdateStatus status = mock(UwbMulticastListUpdateStatus.class);
4419         when(status.getNumOfControlee()).thenReturn(1);
4420         when(status.getControleeUwbAddresses()).thenReturn(
4421                 new UwbAddress[] { UWB_DEST_ADDRESS_2 });
4422         when(status.getStatus()).thenReturn(
4423                 new int[] { UwbUciConstants.STATUS_CODE_FAILED });
4424         when(mNativeUwbManager
4425                 .controllerMulticastListUpdate(anyInt(), anyInt(), anyInt(), any(), any(),
4426                                 any(), anyString()))
4427                 .thenReturn(status);
4428 
4429         mUwbSessionManager.reconfigure(uwbSession.getSessionHandle(), reconfigureParams);
4430         mTestLooper.dispatchNext();
4431 
4432         verify(mUwbSessionNotificationManager).onControleeAddFailed(eq(uwbSession),
4433                 eq(UwbUciConstants.STATUS_CODE_FAILED));
4434         verify(mUwbSessionNotificationManager).onRangingReconfigureFailed(
4435                 eq(uwbSession), eq(UwbUciConstants.STATUS_CODE_FAILED));
4436     }
4437 
4438     @Test
execReconfigure_uwbSessionUpdateMixedSuccess()4439     public void execReconfigure_uwbSessionUpdateMixedSuccess() throws Exception {
4440         FiraOpenSessionParams firaParams = new
4441                 FiraOpenSessionParams.Builder(
4442                     (FiraOpenSessionParams) setupFiraParams(FIRA_VERSION_1_1))
4443                 .setSessionKey(new byte[]{0x5, 0x78, 0x5, 0x78, 0x5, 0x78, 0x5, 0x78, 0x5,
4444                     0x78, 0x5, 0x78, 0x5, 0x78, 0x5, 0x78})
4445                 .setStsConfig(FiraParams.STS_CONFIG_PROVISIONED_FOR_CONTROLEE_INDIVIDUAL_KEY)
4446                 .build();
4447         UwbSession uwbSession = prepareExistingUwbSession(firaParams);
4448         FiraRangingReconfigureParams reconfigureParams =
4449                 buildReconfigureParamsV2();
4450         UwbMulticastListUpdateStatus uwbMulticastListUpdateStatus =
4451                 mock(UwbMulticastListUpdateStatus.class);
4452         when(uwbMulticastListUpdateStatus.getNumOfControlee()).thenReturn(2);
4453         when(uwbMulticastListUpdateStatus.getControleeUwbAddresses()).thenReturn(
4454                 new UwbAddress[] { UWB_DEST_ADDRESS_2, UWB_DEST_ADDRESS_3 });
4455         // One fail, one success
4456         when(uwbMulticastListUpdateStatus.getStatus()).thenReturn(
4457                 new int[] { UwbUciConstants.STATUS_CODE_FAILED, UwbUciConstants.STATUS_CODE_OK });
4458         when(mNativeUwbManager
4459                 .controllerMulticastListUpdate(anyInt(), anyInt(), anyInt(), any(), any(),
4460                         any(), anyString()))
4461                 .thenReturn(uwbMulticastListUpdateStatus);
4462         doReturn(uwbMulticastListUpdateStatus).when(uwbSession).getMulticastListUpdateStatus();
4463 
4464         mUwbSessionManager.reconfigure(uwbSession.getSessionHandle(), reconfigureParams);
4465         mTestLooper.dispatchNext();
4466 
4467         // Fail callback for the first one.
4468         verify(mUwbSessionNotificationManager).onControleeAddFailed(eq(uwbSession),
4469                 eq(UwbUciConstants.STATUS_CODE_FAILED));
4470         // Success callback for the second.
4471         verify(mUwbSessionNotificationManager).onControleeAdded(eq(uwbSession));
4472 
4473         // Make sure the failed address was not added.
4474         assertThat(uwbSession.getControleeList().stream()
4475                 .anyMatch(e -> e.getUwbAddress().equals(UWB_DEST_ADDRESS_2)))
4476                 .isFalse();
4477 
4478         // Overall reconfigure fail.
4479         verify(mUwbSessionNotificationManager).onRangingReconfigureFailed(
4480                 eq(uwbSession), eq(UwbUciConstants.STATUS_CODE_FAILED));
4481     }
4482 
4483     @Test
execReconfigure_uwbSessionUpdateFailed()4484     public void execReconfigure_uwbSessionUpdateFailed() throws Exception {
4485         FiraOpenSessionParams firaParams = new
4486                 FiraOpenSessionParams.Builder(
4487                     (FiraOpenSessionParams) setupFiraParams(FIRA_VERSION_1_1))
4488                 .setSessionKey(new byte[]{0x5, 0x78, 0x5, 0x78, 0x5, 0x78, 0x5, 0x78, 0x5,
4489                     0x78, 0x5, 0x78, 0x5, 0x78, 0x5, 0x78})
4490                 .setStsConfig(FiraParams.STS_CONFIG_PROVISIONED_FOR_CONTROLEE_INDIVIDUAL_KEY)
4491                 .build();
4492         UwbSession uwbSession = prepareExistingUwbSession(firaParams);
4493         FiraRangingReconfigureParams reconfigureParams =
4494                 buildReconfigureParamsV2();
4495         UwbMulticastListUpdateStatus status = mock(UwbMulticastListUpdateStatus.class);
4496         when(mNativeUwbManager
4497                 .controllerMulticastListUpdate(anyInt(), anyInt(), anyInt(), any(), any(),
4498                                 any(), anyString()))
4499                 .thenReturn(status);
4500         UwbMulticastListUpdateStatus uwbMulticastListUpdateStatus =
4501                 mock(UwbMulticastListUpdateStatus.class);
4502         when(uwbMulticastListUpdateStatus.getNumOfControlee()).thenReturn(1);
4503         when(uwbMulticastListUpdateStatus.getStatus()).thenReturn(
4504                 new int[] { UwbUciConstants.STATUS_CODE_FAILED });
4505         doReturn(uwbMulticastListUpdateStatus).when(uwbSession).getMulticastListUpdateStatus();
4506 
4507         mUwbSessionManager.reconfigure(uwbSession.getSessionHandle(), reconfigureParams);
4508         mTestLooper.dispatchNext();
4509 
4510         verify(mUwbSessionNotificationManager).onControleeAddFailed(eq(uwbSession),
4511                 eq(UwbUciConstants.STATUS_CODE_FAILED));
4512         verify(mUwbSessionNotificationManager).onRangingReconfigureFailed(
4513                 eq(uwbSession), eq(UwbUciConstants.STATUS_CODE_FAILED));
4514     }
4515 
4516     @Test
execReconfigureBlockStriding_success_stop()4517     public void execReconfigureBlockStriding_success_stop() throws Exception {
4518         UwbSession uwbSession = prepareExistingUwbSession();
4519         FiraRangingReconfigureParams reconfigureParams =
4520                 new FiraRangingReconfigureParams.Builder()
4521                         .setBlockStrideLength(10)
4522                         .build();
4523         when(mUwbConfigurationManager.setAppConfigurations(anyInt(), any(), anyString(), any()))
4524                 .thenReturn(UwbUciConstants.STATUS_CODE_OK);
4525 
4526         mUwbSessionManager.reconfigure(uwbSession.getSessionHandle(), reconfigureParams);
4527         mTestLooper.dispatchNext();
4528 
4529         verify(mUwbSessionNotificationManager).onRangingReconfigured(uwbSession);
4530 
4531         doReturn(UwbUciConstants.UWB_SESSION_STATE_ACTIVE, UwbUciConstants.UWB_SESSION_STATE_IDLE)
4532                 .when(uwbSession).getSessionState();
4533         when(mNativeUwbManager.stopRanging(eq(TEST_SESSION_ID), anyString()))
4534                 .thenReturn((byte) UwbUciConstants.STATUS_CODE_OK);
4535 
4536         mUwbSessionManager.stopRanging(uwbSession.getSessionHandle());
4537         mTestLooper.dispatchNext();
4538 
4539         verify(mUwbInjector).runTaskOnSingleThreadExecutor(
4540                 any(), eq(TEST_RANGING_INTERVAL_MS * 4 * 11));
4541         verify(mUwbSessionNotificationManager)
4542                 .onRangingStoppedWithApiReasonCode(eq(uwbSession),
4543                         eq(RangingChangeReason.LOCAL_API), any());
4544         verify(mUwbMetrics).longRangingStopEvent(eq(uwbSession));
4545     }
4546 
4547     @Test
execReconfigure_setAppConfigurationsFailed()4548     public void execReconfigure_setAppConfigurationsFailed() throws Exception {
4549         FiraOpenSessionParams firaParams = new
4550                 FiraOpenSessionParams.Builder(
4551                     (FiraOpenSessionParams) setupFiraParams(FIRA_VERSION_1_1))
4552                 .setSessionKey(new byte[]{0x5, 0x78, 0x5, 0x78, 0x5, 0x78, 0x5, 0x78, 0x5,
4553                     0x78, 0x5, 0x78, 0x5, 0x78, 0x5, 0x78})
4554                 .setStsConfig(FiraParams.STS_CONFIG_PROVISIONED_FOR_CONTROLEE_INDIVIDUAL_KEY)
4555                 .build();
4556         UwbSession uwbSession = prepareExistingUwbSession(firaParams);
4557         FiraRangingReconfigureParams reconfigureParams =
4558                 buildReconfigureParamsV2();
4559         UwbMulticastListUpdateStatus status = mock(UwbMulticastListUpdateStatus.class);
4560         when(mNativeUwbManager
4561                 .controllerMulticastListUpdate(anyInt(), anyInt(), anyInt(), any(), any(),
4562                                 any(), anyString()))
4563                 .thenReturn(status);
4564         when(status.getNumOfControlee()).thenReturn(1);
4565         UwbMulticastListUpdateStatus uwbMulticastListUpdateStatus =
4566                 mock(UwbMulticastListUpdateStatus.class);
4567         when(uwbMulticastListUpdateStatus.getStatus()).thenReturn(
4568                 new int[] { UwbUciConstants.STATUS_CODE_OK });
4569         doReturn(uwbMulticastListUpdateStatus).when(uwbSession).getMulticastListUpdateStatus();
4570         when(mUwbConfigurationManager.setAppConfigurations(anyInt(), any(), anyString(), any()))
4571                 .thenReturn(UwbUciConstants.STATUS_CODE_FAILED);
4572 
4573         mUwbSessionManager.reconfigure(uwbSession.getSessionHandle(), reconfigureParams);
4574         mTestLooper.dispatchNext();
4575 
4576         verify(mUwbSessionNotificationManager).onRangingReconfigureFailed(
4577                 eq(uwbSession), eq(UwbUciConstants.STATUS_CODE_FAILED));
4578     }
4579 
4580     @Test
testSetDataTransferPhaseConfig()4581     public void testSetDataTransferPhaseConfig() throws Exception {
4582         FiraOpenSessionParams params = new FiraOpenSessionParams.Builder()
4583                 .setDeviceAddress(UwbAddress.fromBytes(new byte[] {(byte) 0x01, (byte) 0x02 }))
4584                 .setVendorId(new byte[] { (byte) 0x00, (byte) 0x01 })
4585                 .setStaticStsIV(new byte[] { (byte) 0x01, (byte) 0x02, (byte) 0x03,
4586                         (byte) 0x04, (byte) 0x05, (byte) 0x06 })
4587                 .setDestAddressList(Arrays.asList(
4588                         UWB_DEST_ADDRESS))
4589                 .setProtocolVersion(new FiraProtocolVersion(1, 0))
4590                 .setSessionId(10)
4591                 .setSessionType(FiraParams.SESSION_TYPE_DATA_TRANSFER)
4592                 .setDeviceType(FiraParams.RANGING_DEVICE_TYPE_CONTROLLER)
4593                 .setDeviceRole(FiraParams.RANGING_DEVICE_ROLE_INITIATOR)
4594                 .setMultiNodeMode(FiraParams.MULTI_NODE_MODE_UNICAST)
4595                 .setRangingIntervalMs(TEST_RANGING_INTERVAL_MS)
4596                 .setDataRepetitionCount(0)
4597                 .build();
4598         UwbSession uwbSession = prepareExistingUwbSessionWithSessionType(
4599                 (byte) FiraParams.SESSION_TYPE_DATA_TRANSFER, params);
4600         byte dtpcmRepetition = 0;
4601         byte dataTransferControl = 0;
4602         byte dtpmlSize = 2;
4603         byte[] slotBitmapBytes = new byte[] { 0x10, 0x20 };
4604 
4605         List<FiraDataTransferPhaseConfig.FiraDataTransferPhaseManagementList>
4606                     firaDataTransferPhaseManagementList =  new ArrayList<>();
4607 
4608         ByteBuffer expectedMacAddressBuf = ByteBuffer.allocate(
4609                 UwbAddress.SHORT_ADDRESS_BYTE_LENGTH * dtpmlSize);
4610 
4611         // Setup Phase #1
4612         byte[] macAddressBytes = new byte[]{0x22, 0x11};
4613         UwbAddress uwbAddress = UwbAddress.fromBytes(macAddressBytes);
4614         expectedMacAddressBuf.put(getComputedMacAddress(macAddressBytes));
4615         firaDataTransferPhaseManagementList.add(
4616                 new FiraDataTransferPhaseConfig.FiraDataTransferPhaseManagementList(
4617                 uwbAddress, new byte[] {(byte) 0x10}));
4618 
4619         // Setup Phase #2
4620         macAddressBytes = new byte[]{0x44, 0x33};
4621         uwbAddress = UwbAddress.fromBytes(macAddressBytes);
4622         expectedMacAddressBuf.put(getComputedMacAddress(macAddressBytes));
4623         firaDataTransferPhaseManagementList.add(
4624                 new FiraDataTransferPhaseConfig.FiraDataTransferPhaseManagementList(
4625                 uwbAddress, new byte[] {(byte) 0x20}));
4626 
4627         FiraDataTransferPhaseConfig firaDataTransferPhaseConfig =
4628                 new FiraDataTransferPhaseConfig.Builder()
4629                    .setDtpcmRepetition((byte) dtpcmRepetition)
4630                    .setMacAddressMode((byte) 0)
4631                    .setSlotBitmapSize((byte) 0)
4632                    .setDataTransferPhaseManagementList(firaDataTransferPhaseManagementList)
4633                    .build();
4634 
4635         byte[] expectedMacAddressBytes = expectedMacAddressBuf.array();
4636         when(mNativeUwbManager.setDataTransferPhaseConfig(eq(TEST_SESSION_ID),
4637                 eq(dtpcmRepetition), eq(dataTransferControl), eq(dtpmlSize),
4638                 eq(expectedMacAddressBytes), eq(slotBitmapBytes), eq(TEST_CHIP_ID)))
4639                 .thenReturn((byte) UwbUciConstants.STATUS_CODE_OK);
4640 
4641         mUwbSessionManager.setDataTransferPhaseConfig(
4642                 uwbSession.getSessionHandle(), firaDataTransferPhaseConfig.toBundle());
4643         mTestLooper.dispatchNext();
4644 
4645         verify(mNativeUwbManager).setDataTransferPhaseConfig(TEST_SESSION_ID,
4646                 dtpcmRepetition, dataTransferControl, dtpmlSize, expectedMacAddressBytes,
4647                 slotBitmapBytes, TEST_CHIP_ID);
4648     }
4649 
4650     @Test
testSetDataTransferPhaseConfigNonZeroslotBitMap()4651     public void testSetDataTransferPhaseConfigNonZeroslotBitMap() throws Exception {
4652         FiraOpenSessionParams params = new FiraOpenSessionParams.Builder()
4653                 .setDeviceAddress(UwbAddress.fromBytes(new byte[] {(byte) 0x01, (byte) 0x02 }))
4654                 .setVendorId(new byte[] { (byte) 0x00, (byte) 0x01 })
4655                 .setStaticStsIV(new byte[] { (byte) 0x01, (byte) 0x02, (byte) 0x03,
4656                         (byte) 0x04, (byte) 0x05, (byte) 0x06 })
4657                 .setDestAddressList(Arrays.asList(
4658                         UWB_DEST_ADDRESS))
4659                 .setProtocolVersion(new FiraProtocolVersion(1, 0))
4660                 .setSessionId(10)
4661                 .setSessionType(FiraParams.SESSION_TYPE_RANGING_AND_IN_BAND_DATA)
4662                 .setDeviceType(FiraParams.RANGING_DEVICE_TYPE_CONTROLLER)
4663                 .setDeviceRole(FiraParams.RANGING_DEVICE_ROLE_INITIATOR)
4664                 .setMultiNodeMode(FiraParams.MULTI_NODE_MODE_UNICAST)
4665                 .setRangingIntervalMs(TEST_RANGING_INTERVAL_MS)
4666                 .setDataRepetitionCount(0)
4667                 .build();
4668         UwbSession uwbSession = prepareExistingUwbSessionWithSessionType(
4669                 (byte) FiraParams.SESSION_TYPE_RANGING_AND_IN_BAND_DATA, params);
4670         byte dtpcmRepetition = 0;
4671         byte dataTransferControl = 4;
4672         byte dtpmlSize = 2;
4673         byte[] slotBitmapBytes = new byte[]
4674                 { 0x10, 0x20, 0x30, 0x40, 0x50, 0x60, 0x70, (byte) 0x80 };
4675 
4676         List<FiraDataTransferPhaseConfig.FiraDataTransferPhaseManagementList>
4677                     firaDataTransferPhaseManagementList =  new ArrayList<>();
4678         ByteBuffer expectedMacAddressBuf = ByteBuffer.allocate(
4679                 UwbAddress.SHORT_ADDRESS_BYTE_LENGTH * dtpmlSize);
4680 
4681         // Setup Phase #1
4682         byte[] macAddressBytes = new byte[]{0x22, 0x11};
4683         UwbAddress uwbAddress = UwbAddress.fromBytes(macAddressBytes);
4684         expectedMacAddressBuf.put(getComputedMacAddress(macAddressBytes));
4685         firaDataTransferPhaseManagementList.add(
4686                 new FiraDataTransferPhaseConfig.FiraDataTransferPhaseManagementList(
4687                 uwbAddress, new byte[] {0x10, 0x20, 0x30, 0x40}));
4688 
4689         // Setup Phase #2
4690         macAddressBytes = new byte[]{0x44, 0x33};
4691         uwbAddress = UwbAddress.fromBytes(macAddressBytes);
4692         expectedMacAddressBuf.put(getComputedMacAddress(macAddressBytes));
4693         firaDataTransferPhaseManagementList.add(
4694                 new FiraDataTransferPhaseConfig.FiraDataTransferPhaseManagementList(
4695                 uwbAddress, new byte[] {0x50, 0x60, 0x70, (byte) 0x80}));
4696 
4697         FiraDataTransferPhaseConfig firaDataTransferPhaseConfig =
4698                 new FiraDataTransferPhaseConfig.Builder()
4699                    .setDtpcmRepetition((byte) dtpcmRepetition)
4700                    .setMacAddressMode((byte) 0)
4701                    .setSlotBitmapSize((byte) 2)
4702                    .setDataTransferPhaseManagementList(firaDataTransferPhaseManagementList)
4703                    .build();
4704 
4705         byte[] expectedMacAddressBytes = expectedMacAddressBuf.array();
4706         when(mNativeUwbManager.setDataTransferPhaseConfig(eq(TEST_SESSION_ID),
4707                 eq(dtpcmRepetition), eq(dataTransferControl), eq(dtpmlSize),
4708                 eq(expectedMacAddressBytes), eq(slotBitmapBytes), eq(TEST_CHIP_ID)))
4709                 .thenReturn((byte) UwbUciConstants.STATUS_CODE_OK);
4710 
4711         mUwbSessionManager.setDataTransferPhaseConfig(
4712                 uwbSession.getSessionHandle(), firaDataTransferPhaseConfig.toBundle());
4713         mTestLooper.dispatchNext();
4714 
4715         verify(mNativeUwbManager).setDataTransferPhaseConfig(TEST_SESSION_ID,
4716                 dtpcmRepetition, dataTransferControl, dtpmlSize, expectedMacAddressBytes,
4717                 slotBitmapBytes, TEST_CHIP_ID);
4718     }
4719 
4720     @Test
testSetDataTransferPhaseConfigFailedDueToInvalidSessionType()4721     public void testSetDataTransferPhaseConfigFailedDueToInvalidSessionType() throws Exception {
4722         byte dtpcmRepetition = 0;
4723         byte dataTransferControl = 0;
4724         byte dtpmlSize = 2;
4725         byte[] slotBitmapBytes = new byte[] { 0x10, 0x20 };
4726         /** By default SESSION_TYPE_RANGING is used, so testcase is expected to
4727          *  fail due to Invalid session type for data transfer phase config
4728          */
4729         UwbSession uwbSession = prepareExistingUwbSessionActive();
4730 
4731         List<FiraDataTransferPhaseConfig.FiraDataTransferPhaseManagementList>
4732                     firaDataTransferPhaseManagementList =  new ArrayList<>();
4733         ByteBuffer expectedMacAddressBuf = ByteBuffer.allocate(
4734                 UwbAddress.SHORT_ADDRESS_BYTE_LENGTH * dtpmlSize);
4735 
4736         // Setup Phase #1
4737         byte[] macAddressBytes = new byte[]{0x22, 0x11};
4738         UwbAddress uwbAddress = UwbAddress.fromBytes(macAddressBytes);
4739         expectedMacAddressBuf.put(getComputedMacAddress(macAddressBytes));
4740         firaDataTransferPhaseManagementList.add(
4741                 new FiraDataTransferPhaseConfig.FiraDataTransferPhaseManagementList(
4742                 uwbAddress, new byte[] {(byte) 0x10}));
4743 
4744         // Setup Phase #2
4745         macAddressBytes = new byte[]{0x44, 0x33};
4746         uwbAddress = UwbAddress.fromBytes(macAddressBytes);
4747         expectedMacAddressBuf.put(getComputedMacAddress(macAddressBytes));
4748         firaDataTransferPhaseManagementList.add(
4749                 new FiraDataTransferPhaseConfig.FiraDataTransferPhaseManagementList(
4750                 uwbAddress, new byte[] {(byte) 0x20, 0x30})); //Invalid slot bit map
4751 
4752         FiraDataTransferPhaseConfig firaDataTransferPhaseConfig =
4753                 new FiraDataTransferPhaseConfig.Builder()
4754                    .setDtpcmRepetition((byte) dtpcmRepetition)
4755                    .setMacAddressMode((byte) 0)
4756                    .setSlotBitmapSize((byte) 1)
4757                    .setDataTransferPhaseManagementList(firaDataTransferPhaseManagementList)
4758                    .build();
4759 
4760         mUwbSessionManager.setDataTransferPhaseConfig(
4761                 uwbSession.getSessionHandle(), firaDataTransferPhaseConfig.toBundle());
4762         mTestLooper.dispatchNext();
4763 
4764         byte[] expectedMacAddressBytes = expectedMacAddressBuf.array();
4765         verify(mNativeUwbManager, never()).setDataTransferPhaseConfig(TEST_SESSION_ID,
4766                 dtpcmRepetition, dataTransferControl, dtpmlSize, expectedMacAddressBytes,
4767                 slotBitmapBytes, TEST_CHIP_ID);
4768     }
4769 
4770     @Test
testSetDataTransferPhaseConfigFailedDueToInvalidList()4771     public void testSetDataTransferPhaseConfigFailedDueToInvalidList() throws Exception {
4772         UwbSession uwbSession = prepareExistingUwbSession();
4773         byte dtpcmRepetition = 0;
4774         byte dataTransferControl = 0;
4775         byte dtpmlSize = 2;
4776         byte[] slotBitmapBytes = new byte[] { 0x10, 0x20 };
4777 
4778         List<FiraDataTransferPhaseConfig.FiraDataTransferPhaseManagementList>
4779                     firaDataTransferPhaseManagementList = new ArrayList<>();
4780         ByteBuffer expectedMacAddressBuf = ByteBuffer.allocate(
4781                 UwbAddress.SHORT_ADDRESS_BYTE_LENGTH);
4782 
4783         // Setup Phase #1
4784         byte[] macAddressBytes = new byte[]{0x22, 0x11};
4785         UwbAddress uwbAddress = UwbAddress.fromBytes(macAddressBytes);
4786         expectedMacAddressBuf.put(getComputedMacAddress(macAddressBytes));
4787         firaDataTransferPhaseManagementList.add(
4788                 new FiraDataTransferPhaseConfig.FiraDataTransferPhaseManagementList(
4789                 uwbAddress, new byte[] {(byte) 0x10}));
4790 
4791         // Size of dtpml-Size is 2 but only one set of configs are provided
4792         FiraDataTransferPhaseConfig firaDataTransferPhaseConfig =
4793                 new FiraDataTransferPhaseConfig.Builder()
4794                    .setDtpcmRepetition((byte) dtpcmRepetition)
4795                    .setMacAddressMode((byte) 0)
4796                    .setSlotBitmapSize((byte) 1)
4797                    .setDataTransferPhaseManagementList(firaDataTransferPhaseManagementList)
4798                    .build();
4799 
4800         mUwbSessionManager.setDataTransferPhaseConfig(
4801                 uwbSession.getSessionHandle(), firaDataTransferPhaseConfig.toBundle());
4802         mTestLooper.dispatchNext();
4803 
4804         byte[] expectedMacAddressBytes = expectedMacAddressBuf.array();
4805         verify(mNativeUwbManager, never()).setDataTransferPhaseConfig(TEST_SESSION_ID,
4806                 dtpcmRepetition, dataTransferControl, dtpmlSize, expectedMacAddressBytes,
4807                 slotBitmapBytes, TEST_CHIP_ID);
4808     }
4809 
4810 
4811     @Test
testQueryDataSize()4812     public void testQueryDataSize() throws Exception {
4813         UwbSession uwbSession = prepareExistingUwbSession();
4814 
4815         when(mNativeUwbManager.queryMaxDataSizeBytes(
4816                 eq(uwbSession.getSessionId()), eq(TEST_CHIP_ID)))
4817                 .thenReturn(MAX_DATA_SIZE);
4818         assertThat(mUwbSessionManager.queryMaxDataSizeBytes(uwbSession.getSessionHandle()))
4819                 .isEqualTo(MAX_DATA_SIZE);
4820     }
4821 
4822     @Test
testQueryDataSize_whenUwbSessionDoesNotExist()4823     public void testQueryDataSize_whenUwbSessionDoesNotExist() throws Exception {
4824         SessionHandle mockSessionHandle = mock(SessionHandle.class);
4825         assertThrows(IllegalStateException.class,
4826                 () -> mUwbSessionManager.queryMaxDataSizeBytes(mockSessionHandle));
4827     }
4828 
4829     @Test
testReferenceTimeBase()4830     public void testReferenceTimeBase() throws Exception {
4831         Params refParams = setupFiraParams(new FiraProtocolVersion(2, 0));
4832         FiraOpenSessionParams refFiraParams = new
4833                 FiraOpenSessionParams.Builder((FiraOpenSessionParams) refParams)
4834                         .setSessionId(TEST_SESSION_ID)
4835                         .build();
4836         UwbSession refUwbSession = setUpUwbSessionForExecution(ATTRIBUTION_SOURCE, refFiraParams);
4837         mUwbSessionManager.initSession(ATTRIBUTION_SOURCE, refUwbSession.getSessionHandle(),
4838                 TEST_SESSION_ID, TEST_SESSION_TYPE, FiraParams.PROTOCOL_NAME,
4839                 refUwbSession.getParams(), refUwbSession.getIUwbRangingCallbacks(), TEST_CHIP_ID);
4840         when(mNativeUwbManager.initSession(anyInt(), anyByte(), anyString()))
4841                 .thenReturn((byte) UwbUciConstants.STATUS_CODE_OK);
4842         when(mNativeUwbManager.getSessionToken(eq(TEST_SESSION_ID), anyString()))
4843                 .thenReturn(REFERENCE_SESSION_HANDLE);
4844         doReturn(UwbUciConstants.UWB_SESSION_STATE_INIT,
4845                 UwbUciConstants.UWB_SESSION_STATE_IDLE).when(refUwbSession).getSessionState();
4846         mTestLooper.dispatchAll();
4847 
4848         Params params = setupFiraParams(new FiraProtocolVersion(2, 0));
4849         FiraOpenSessionParams firaParams = new
4850                 FiraOpenSessionParams.Builder((FiraOpenSessionParams) params)
4851                         .setSessionId(TEST_SESSION_ID_2)
4852                         .setSessionTimeBase(1, TEST_SESSION_ID, 200)
4853                         .build();
4854         UwbSession uwbSession = setUpUwbSessionForExecution(ATTRIBUTION_SOURCE, firaParams);
4855 
4856         when(mNativeUwbManager.initSession(anyInt(), anyByte(), anyString()))
4857                 .thenReturn((byte) UwbUciConstants.STATUS_CODE_OK);
4858         doReturn(UwbUciConstants.UWB_SESSION_STATE_INIT,
4859                 UwbUciConstants.UWB_SESSION_STATE_IDLE).when(uwbSession).getSessionState();
4860         mUwbSessionManager.initSession(ATTRIBUTION_SOURCE, uwbSession.getSessionHandle(),
4861                 TEST_SESSION_ID_2, TEST_SESSION_TYPE, FiraParams.PROTOCOL_NAME,
4862                 uwbSession.getParams(), uwbSession.getIUwbRangingCallbacks(), TEST_CHIP_ID);
4863         mTestLooper.dispatchAll();
4864 
4865         verify(uwbSession).updateFiraParamsForSessionTimeBase(REFERENCE_SESSION_HANDLE);
4866     }
4867 
4868 
4869     @Test
testsetHybridSessionControllerConfiguration_shortMacAddress()4870     public void testsetHybridSessionControllerConfiguration_shortMacAddress() throws Exception {
4871         FiraOpenSessionParams params = new FiraOpenSessionParams.Builder()
4872                 .setDeviceAddress(UwbAddress.fromBytes(new byte[] {(byte) 0x01, (byte) 0x02 }))
4873                 .setVendorId(new byte[] { (byte) 0x00, (byte) 0x01 })
4874                 .setStaticStsIV(new byte[] { (byte) 0x01, (byte) 0x02, (byte) 0x03,
4875                         (byte) 0x04, (byte) 0x05, (byte) 0x06 })
4876                 .setDestAddressList(Arrays.asList(
4877                         UWB_DEST_ADDRESS))
4878                 .setProtocolVersion(new FiraProtocolVersion(1, 0))
4879                 .setSessionId(10)
4880                 .setSessionType(FiraParams.SESSION_TYPE_IN_BAND_DATA_PHASE)
4881                 .setDeviceType(FiraParams.RANGING_DEVICE_TYPE_CONTROLLER)
4882                 .setDeviceRole(FiraParams.RANGING_DEVICE_ROLE_INITIATOR)
4883                 .setMultiNodeMode(FiraParams.MULTI_NODE_MODE_UNICAST)
4884                 .setRangingIntervalMs(TEST_RANGING_INTERVAL_MS)
4885                 .setScheduledMode(FiraParams.HYBRID_SCHEDULED_RANGING)
4886                 .setDataRepetitionCount(0)
4887                 .build();
4888         UwbSession uwbSession = prepareExistingUwbSessionWithSessionType(
4889                 (byte) FiraParams.SESSION_TYPE_IN_BAND_DATA_PHASE, params);
4890 
4891         byte messageControl = 0;
4892         int noOfPhases = 2;
4893         byte phaseParticipation = 0;
4894         byte [] updateTime = new byte[8];
4895         short startSlotIndex1 = 0x01, endSlotIndex1 = 0x34;
4896         short startSlotIndex2 = 0x37, endSlotIndex2 = 0x64;
4897 
4898         // Setup the expected byte-array for the Hybrid configuration.
4899         ByteBuffer expectedHybridConfigBytes = ByteBuffer.allocate(noOfPhases
4900                 * UWB_HUS_CONTROLLER_PHASE_LIST_SHORT_MAC_ADDRESS_SIZE);
4901         expectedHybridConfigBytes.order(ByteOrder.LITTLE_ENDIAN);
4902 
4903         expectedHybridConfigBytes.putInt(0); //SessionToken
4904         expectedHybridConfigBytes.putShort(startSlotIndex1);
4905         expectedHybridConfigBytes.putShort(endSlotIndex1);
4906         expectedHybridConfigBytes.put(phaseParticipation);
4907         expectedHybridConfigBytes.put(getComputedMacAddress(UWB_DEST_ADDRESS.toBytes()));
4908 
4909         expectedHybridConfigBytes.putInt(0); //SessionToken
4910         expectedHybridConfigBytes.putShort(startSlotIndex2);
4911         expectedHybridConfigBytes.putShort(endSlotIndex2);
4912         expectedHybridConfigBytes.put(phaseParticipation);
4913         expectedHybridConfigBytes.put(getComputedMacAddress(UWB_DEST_ADDRESS_2.toBytes()));
4914 
4915         when(mNativeUwbManager.setHybridSessionControllerConfiguration(
4916                 anyInt(), anyByte(), anyInt(), any(), any(), anyString()))
4917                .thenReturn((byte) UwbUciConstants.STATUS_CODE_OK);
4918 
4919         // Invoke the method that triggers the 'setHybridSessionControllerConfiguration'
4920         mUwbSessionManager.setHybridSessionControllerConfiguration(
4921                 uwbSession.getSessionHandle(), mHybridControllerParams.toBundle());
4922         mTestLooper.dispatchAll();
4923 
4924         verify(mNativeUwbManager).setHybridSessionControllerConfiguration(
4925                     uwbSession.getSessionId(), messageControl, noOfPhases,
4926                     updateTime, expectedHybridConfigBytes.array(), uwbSession.getChipId());
4927     }
4928 
4929     @Test
testsetHybridSessionControllerConfiguration_extendedMacAddress()4930     public void testsetHybridSessionControllerConfiguration_extendedMacAddress() throws Exception {
4931         FiraOpenSessionParams params = new FiraOpenSessionParams.Builder()
4932                 .setDeviceAddress(UwbAddress.fromBytes(new byte[] {(byte) 0x01, (byte) 0x02 }))
4933                 .setVendorId(new byte[] { (byte) 0x00, (byte) 0x01 })
4934                 .setStaticStsIV(new byte[] { (byte) 0x01, (byte) 0x02, (byte) 0x03,
4935                         (byte) 0x04, (byte) 0x05, (byte) 0x06 })
4936                 .setDestAddressList(Arrays.asList(
4937                         UWB_DEST_ADDRESS))
4938                 .setProtocolVersion(new FiraProtocolVersion(1, 0))
4939                 .setSessionId(10)
4940                 .setSessionType(FiraParams.SESSION_TYPE_RANGING_ONLY_PHASE)
4941                 .setDeviceType(FiraParams.RANGING_DEVICE_TYPE_CONTROLLER)
4942                 .setDeviceRole(FiraParams.RANGING_DEVICE_ROLE_INITIATOR)
4943                 .setMultiNodeMode(FiraParams.MULTI_NODE_MODE_UNICAST)
4944                 .setRangingIntervalMs(TEST_RANGING_INTERVAL_MS)
4945                 .setScheduledMode(FiraParams.HYBRID_SCHEDULED_RANGING)
4946                 .setDataRepetitionCount(0)
4947                 .build();
4948         UwbSession uwbSession = prepareExistingUwbSessionWithSessionType(
4949                 (byte) FiraParams.SESSION_TYPE_RANGING_ONLY_PHASE, params);
4950 
4951         byte[] updateTime = new byte[8];
4952         int noOfPhases = 2;
4953         short startSlotIndex1 = 0x01, endSlotIndex1 = 0x34;
4954         short startSlotIndex2 = 0x37, endSlotIndex2 = 0x64;
4955         byte messageControl = 1;
4956         byte phaseParticipation = 0;
4957         UwbAddress uwbAddress1 = UwbAddress.fromBytes(new byte[] {
4958                 0x11, 0x22, 0x33, 0x44, 0x55, 0x56, 0x57, 0x66 });
4959         UwbAddress uwbAddress2 = UwbAddress.fromBytes(new byte[] {
4960                 0x22, 0x22, 0x33, 0x44, 0x55, 0x56, 0x57, 0x66 });
4961 
4962         FiraHybridSessionControllerConfig hybridParams =
4963                 new FiraHybridSessionControllerConfig.Builder()
4964                 .setNumberOfPhases(noOfPhases)
4965                 .setUpdateTime(updateTime)
4966                 .setMacAddressMode((byte) 1)
4967                 .addPhaseList(
4968                         new FiraHybridSessionControllerConfig.FiraHybridSessionPhaseList(
4969                                 SESSION_HANDLE.getId(), startSlotIndex1, endSlotIndex1,
4970                                 phaseParticipation, uwbAddress1))
4971                 .addPhaseList(
4972                         new FiraHybridSessionControllerConfig.FiraHybridSessionPhaseList(
4973                                 SESSION_HANDLE_2.getId(), startSlotIndex2, endSlotIndex2,
4974                                 phaseParticipation, uwbAddress2))
4975                 .build();
4976 
4977         /* Setup the expected byte-array for the Hybrid configuration. */
4978         ByteBuffer expectedHybridConfigBytes = ByteBuffer.allocate(noOfPhases
4979                 * UWB_HUS_CONTROLLER_PHASE_LIST_EXTENDED_MAC_ADDRESS_SIZE);
4980         expectedHybridConfigBytes.order(ByteOrder.LITTLE_ENDIAN);
4981 
4982         expectedHybridConfigBytes.putInt(0); //SessionToken
4983         expectedHybridConfigBytes.putShort(startSlotIndex1);
4984         expectedHybridConfigBytes.putShort(endSlotIndex1);
4985         expectedHybridConfigBytes.put(phaseParticipation);
4986         expectedHybridConfigBytes.put(getComputedMacAddress(uwbAddress1.toBytes()));
4987 
4988         expectedHybridConfigBytes.putInt(0); //SessionToken
4989         expectedHybridConfigBytes.putShort(startSlotIndex2);
4990         expectedHybridConfigBytes.putShort(endSlotIndex2);
4991         expectedHybridConfigBytes.put(phaseParticipation);
4992         expectedHybridConfigBytes.put(getComputedMacAddress(uwbAddress2.toBytes()));
4993 
4994         when(mNativeUwbManager.setHybridSessionControllerConfiguration(
4995             anyInt(), anyByte(), anyInt(),
4996             any(), any(), anyString()))
4997             .thenReturn((byte) UwbUciConstants.STATUS_CODE_OK);
4998 
4999         // Invoke the method that triggers the 'setHybridSessionControllerConfiguration'
5000         mUwbSessionManager.setHybridSessionControllerConfiguration(
5001                 uwbSession.getSessionHandle(), hybridParams.toBundle());
5002         mTestLooper.dispatchAll();
5003 
5004         verify(mNativeUwbManager).setHybridSessionControllerConfiguration(
5005                 uwbSession.getSessionId(), messageControl, noOfPhases,
5006                 updateTime, expectedHybridConfigBytes.array(), uwbSession.getChipId());
5007     }
5008 
5009     @Test
testsetHybridSessionControllerWithInvalidInvalidSessionType()5010     public void testsetHybridSessionControllerWithInvalidInvalidSessionType() throws Exception {
5011         FiraOpenSessionParams params = new FiraOpenSessionParams.Builder()
5012                 .setDeviceAddress(UwbAddress.fromBytes(new byte[] {(byte) 0x01, (byte) 0x02 }))
5013                 .setVendorId(new byte[] { (byte) 0x00, (byte) 0x01 })
5014                 .setStaticStsIV(new byte[] { (byte) 0x01, (byte) 0x02, (byte) 0x03,
5015                         (byte) 0x04, (byte) 0x05, (byte) 0x06 })
5016                 .setDestAddressList(Arrays.asList(
5017                         UWB_DEST_ADDRESS))
5018                 .setProtocolVersion(new FiraProtocolVersion(1, 0))
5019                 .setSessionId(10)
5020                 .setSessionType(FiraParams.SESSION_TYPE_RANGING)
5021                 .setDeviceType(FiraParams.RANGING_DEVICE_TYPE_CONTROLLER)
5022                 .setDeviceRole(FiraParams.RANGING_DEVICE_ROLE_INITIATOR)
5023                 .setMultiNodeMode(FiraParams.MULTI_NODE_MODE_UNICAST)
5024                 .setRangingIntervalMs(TEST_RANGING_INTERVAL_MS)
5025                 .setScheduledMode(FiraParams.HYBRID_SCHEDULED_RANGING)
5026                 .setDataRepetitionCount(0)
5027                 .build();
5028         UwbSession uwbSession = prepareExistingUwbSessionWithSessionType(
5029                 (byte) FiraParams.SESSION_TYPE_RANGING, params);
5030 
5031 
5032         // Expected to fail due to invalid session type
5033         mUwbSessionManager.setHybridSessionControllerConfiguration(
5034                 uwbSession.getSessionHandle(), mHybridControllerParams.toBundle());
5035         mTestLooper.dispatchAll();
5036 
5037         verify(mUwbSessionNotificationManager).onHybridSessionControllerConfigurationFailed(
5038                 any(), anyInt());
5039     }
5040 
5041     @Test
testsetHybridSessionControllerWithInvalidScheduledMode()5042     public void testsetHybridSessionControllerWithInvalidScheduledMode() throws Exception {
5043         FiraOpenSessionParams params = new FiraOpenSessionParams.Builder()
5044                 .setDeviceAddress(UwbAddress.fromBytes(new byte[] {(byte) 0x01, (byte) 0x02 }))
5045                 .setVendorId(new byte[] { (byte) 0x00, (byte) 0x01 })
5046                 .setStaticStsIV(new byte[] { (byte) 0x01, (byte) 0x02, (byte) 0x03,
5047                         (byte) 0x04, (byte) 0x05, (byte) 0x06 })
5048                 .setDestAddressList(Arrays.asList(
5049                         UWB_DEST_ADDRESS))
5050                 .setProtocolVersion(new FiraProtocolVersion(1, 0))
5051                 .setSessionId(10)
5052                 .setSessionType(FiraParams.SESSION_TYPE_RANGING_WITH_DATA_PHASE)
5053                 .setDeviceType(FiraParams.RANGING_DEVICE_TYPE_CONTROLLER)
5054                 .setDeviceRole(FiraParams.RANGING_DEVICE_ROLE_INITIATOR)
5055                 .setMultiNodeMode(FiraParams.MULTI_NODE_MODE_UNICAST)
5056                 .setRangingIntervalMs(TEST_RANGING_INTERVAL_MS)
5057                 .setScheduledMode(FiraParams.TIME_SCHEDULED_RANGING)
5058                 .setDataRepetitionCount(0)
5059                 .build();
5060         UwbSession uwbSession = prepareExistingUwbSessionWithSessionType(
5061                 (byte) FiraParams.SESSION_TYPE_RANGING_WITH_DATA_PHASE, params);
5062 
5063 
5064         // Expected to fail due to invalid scheduled mode
5065         mUwbSessionManager.setHybridSessionControllerConfiguration(
5066                 uwbSession.getSessionHandle(), mHybridControllerParams.toBundle());
5067         mTestLooper.dispatchAll();
5068 
5069         verify(mUwbSessionNotificationManager).onHybridSessionControllerConfigurationFailed(
5070                 any(), anyInt());
5071     }
5072 
5073     @Test
testsetHybridSessionControllerWithInvalidDeviceType()5074     public void testsetHybridSessionControllerWithInvalidDeviceType() throws Exception {
5075         FiraOpenSessionParams params = new FiraOpenSessionParams.Builder()
5076                 .setDeviceAddress(UwbAddress.fromBytes(new byte[] {(byte) 0x01, (byte) 0x02 }))
5077                 .setVendorId(new byte[] { (byte) 0x00, (byte) 0x01 })
5078                 .setStaticStsIV(new byte[] { (byte) 0x01, (byte) 0x02, (byte) 0x03,
5079                         (byte) 0x04, (byte) 0x05, (byte) 0x06 })
5080                 .setDestAddressList(Arrays.asList(
5081                         UWB_DEST_ADDRESS))
5082                 .setProtocolVersion(new FiraProtocolVersion(1, 0))
5083                 .setSessionId(10)
5084                 .setSessionType(FiraParams.SESSION_TYPE_RANGING_WITH_DATA_PHASE)
5085                 .setDeviceType(FiraParams.RANGING_DEVICE_TYPE_CONTROLEE)
5086                 .setDeviceRole(FiraParams.RANGING_DEVICE_ROLE_INITIATOR)
5087                 .setMultiNodeMode(FiraParams.MULTI_NODE_MODE_UNICAST)
5088                 .setRangingIntervalMs(TEST_RANGING_INTERVAL_MS)
5089                 .setScheduledMode(FiraParams.HYBRID_SCHEDULED_RANGING)
5090                 .setDataRepetitionCount(0)
5091                 .build();
5092         UwbSession uwbSession = prepareExistingUwbSessionWithSessionType(
5093                 (byte) FiraParams.SESSION_TYPE_RANGING_WITH_DATA_PHASE, params);
5094 
5095 
5096         // Expected to fail due to invalid device type(controlee)
5097         mUwbSessionManager.setHybridSessionControllerConfiguration(
5098                 uwbSession.getSessionHandle(), mHybridControllerParams.toBundle());
5099         mTestLooper.dispatchAll();
5100 
5101         verify(mUwbSessionNotificationManager).onHybridSessionControllerConfigurationFailed(
5102                 any(), anyInt());
5103     }
5104 
5105     @Test
testsetHybridSessionControllerConfiguration_whenUwbSessionDoesNotExist()5106     public void testsetHybridSessionControllerConfiguration_whenUwbSessionDoesNotExist()
5107             throws Exception {
5108         SessionHandle mockSessionHandle = mock(SessionHandle.class);
5109         assertThrows(IllegalStateException.class,
5110                 () -> mUwbSessionManager.setHybridSessionControllerConfiguration(mockSessionHandle,
5111                         mock(PersistableBundle.class)));
5112     }
5113 
5114     @Test
testsetHybridSessionControleeConfiguration_whenUwbSessionDoesNotExist()5115     public void testsetHybridSessionControleeConfiguration_whenUwbSessionDoesNotExist()
5116             throws Exception {
5117         SessionHandle mockSessionHandle = mock(SessionHandle.class);
5118         assertThrows(IllegalStateException.class,
5119                 () -> mUwbSessionManager.setHybridSessionControleeConfiguration(mockSessionHandle,
5120                         mock(PersistableBundle.class)));
5121     }
5122 
5123     @Test
testsetHybridSessionControleeConfiguration()5124     public void testsetHybridSessionControleeConfiguration() throws Exception {
5125         FiraOpenSessionParams params = new FiraOpenSessionParams.Builder()
5126                 .setDeviceAddress(UwbAddress.fromBytes(new byte[] {(byte) 0x01, (byte) 0x02 }))
5127                 .setVendorId(new byte[] { (byte) 0x00, (byte) 0x01 })
5128                 .setStaticStsIV(new byte[] { (byte) 0x01, (byte) 0x02, (byte) 0x03,
5129                         (byte) 0x04, (byte) 0x05, (byte) 0x06 })
5130                 .setDestAddressList(Arrays.asList(
5131                         UWB_DEST_ADDRESS))
5132                 .setProtocolVersion(new FiraProtocolVersion(1, 0))
5133                 .setSessionId(10)
5134                 .setSessionType(FiraParams.SESSION_TYPE_RANGING_WITH_DATA_PHASE)
5135                 .setDeviceType(FiraParams.RANGING_DEVICE_TYPE_CONTROLEE)
5136                 .setDeviceRole(FiraParams.RANGING_DEVICE_ROLE_INITIATOR)
5137                 .setMultiNodeMode(FiraParams.MULTI_NODE_MODE_UNICAST)
5138                 .setRangingIntervalMs(TEST_RANGING_INTERVAL_MS)
5139                 .setScheduledMode(FiraParams.HYBRID_SCHEDULED_RANGING)
5140                 .setDataRepetitionCount(0)
5141                 .build();
5142         UwbSession uwbSession = prepareExistingUwbSessionWithSessionType(
5143                 (byte) FiraParams.SESSION_TYPE_RANGING_WITH_DATA_PHASE, params);
5144 
5145         int noOfPhases = 2;
5146         byte phaseParticipation = 0;
5147        // Setup the expected byte-array for the Hybrid configuration.
5148         ByteBuffer expectedHybridConfigBytes = ByteBuffer.allocate(noOfPhases
5149                 * UWB_HUS_CONTROLEE_PHASE_LIST_SIZE);
5150         expectedHybridConfigBytes.order(ByteOrder.LITTLE_ENDIAN);
5151 
5152         expectedHybridConfigBytes.putInt(0); //SessionToken
5153         expectedHybridConfigBytes.put(phaseParticipation);
5154         expectedHybridConfigBytes.putInt(0); //SessionToken
5155         expectedHybridConfigBytes.put(phaseParticipation);
5156         when(mNativeUwbManager.setHybridSessionControleeConfiguration(
5157             anyInt(), anyInt(), any(), anyString()))
5158             .thenReturn((byte) UwbUciConstants.STATUS_CODE_OK);
5159 
5160         // Invoke the method that triggers the 'setHybridSessionControllerConfiguration'
5161         mUwbSessionManager.setHybridSessionControleeConfiguration(
5162                 uwbSession.getSessionHandle(), mHybridControleeParams.toBundle());
5163         mTestLooper.dispatchAll();
5164 
5165         verify(mNativeUwbManager).setHybridSessionControleeConfiguration(
5166                 uwbSession.getSessionId(), noOfPhases, expectedHybridConfigBytes.array(),
5167                 uwbSession.getChipId());
5168     }
5169 
5170     @Test
testsetHybridSessionControleeWithInvalidInvalidSessionType()5171     public void testsetHybridSessionControleeWithInvalidInvalidSessionType() throws Exception {
5172         FiraOpenSessionParams params = new FiraOpenSessionParams.Builder()
5173                 .setDeviceAddress(UwbAddress.fromBytes(new byte[] {(byte) 0x01, (byte) 0x02 }))
5174                 .setVendorId(new byte[] { (byte) 0x00, (byte) 0x01 })
5175                 .setStaticStsIV(new byte[] { (byte) 0x01, (byte) 0x02, (byte) 0x03,
5176                         (byte) 0x04, (byte) 0x05, (byte) 0x06 })
5177                 .setDestAddressList(Arrays.asList(
5178                         UWB_DEST_ADDRESS))
5179                 .setProtocolVersion(new FiraProtocolVersion(1, 0))
5180                 .setSessionId(10)
5181                 .setSessionType(FiraParams.SESSION_TYPE_DATA_TRANSFER)
5182                 .setDeviceType(FiraParams.RANGING_DEVICE_TYPE_CONTROLEE)
5183                 .setDeviceRole(FiraParams.RANGING_DEVICE_ROLE_INITIATOR)
5184                 .setMultiNodeMode(FiraParams.MULTI_NODE_MODE_UNICAST)
5185                 .setRangingIntervalMs(TEST_RANGING_INTERVAL_MS)
5186                 .setScheduledMode(FiraParams.HYBRID_SCHEDULED_RANGING)
5187                 .setDataRepetitionCount(0)
5188                 .build();
5189         UwbSession uwbSession = prepareExistingUwbSessionWithSessionType(
5190                 (byte) FiraParams.SESSION_TYPE_DATA_TRANSFER, params);
5191 
5192 
5193         // Expected to fail due to invalid session type
5194         mUwbSessionManager.setHybridSessionControleeConfiguration(
5195                 uwbSession.getSessionHandle(), mHybridControleeParams.toBundle());
5196         mTestLooper.dispatchAll();
5197 
5198         verify(mUwbSessionNotificationManager).onHybridSessionControleeConfigurationFailed(
5199                 any(), anyInt());
5200     }
5201 
5202     @Test
testsetHybridSessionControleeWithInvalidScheduledMode()5203     public void testsetHybridSessionControleeWithInvalidScheduledMode() throws Exception {
5204         FiraOpenSessionParams params = new FiraOpenSessionParams.Builder()
5205                 .setDeviceAddress(UwbAddress.fromBytes(new byte[] {(byte) 0x01, (byte) 0x02 }))
5206                 .setVendorId(new byte[] { (byte) 0x00, (byte) 0x01 })
5207                 .setStaticStsIV(new byte[] { (byte) 0x01, (byte) 0x02, (byte) 0x03,
5208                         (byte) 0x04, (byte) 0x05, (byte) 0x06 })
5209                 .setDestAddressList(Arrays.asList(
5210                         UWB_DEST_ADDRESS))
5211                 .setProtocolVersion(new FiraProtocolVersion(1, 0))
5212                 .setSessionId(10)
5213                 .setSessionType(FiraParams.SESSION_TYPE_RANGING_WITH_DATA_PHASE)
5214                 .setDeviceType(FiraParams.RANGING_DEVICE_TYPE_CONTROLEE)
5215                 .setDeviceRole(FiraParams.RANGING_DEVICE_ROLE_INITIATOR)
5216                 .setMultiNodeMode(FiraParams.MULTI_NODE_MODE_UNICAST)
5217                 .setRangingIntervalMs(TEST_RANGING_INTERVAL_MS)
5218                 .setScheduledMode(FiraParams.TIME_SCHEDULED_RANGING)
5219                 .setDataRepetitionCount(0)
5220                 .build();
5221         UwbSession uwbSession = prepareExistingUwbSessionWithSessionType(
5222                 (byte) FiraParams.SESSION_TYPE_RANGING_WITH_DATA_PHASE, params);
5223 
5224 
5225         // Expected to fail due to invalid scheduded mode
5226         mUwbSessionManager.setHybridSessionControleeConfiguration(
5227                 uwbSession.getSessionHandle(), mHybridControleeParams.toBundle());
5228         mTestLooper.dispatchAll();
5229 
5230         verify(mUwbSessionNotificationManager).onHybridSessionControleeConfigurationFailed(
5231                 any(), anyInt());
5232     }
5233 
5234     @Test
testsetHybridSessionControleeWithInvalidDeviceType()5235     public void testsetHybridSessionControleeWithInvalidDeviceType() throws Exception {
5236         FiraOpenSessionParams params = new FiraOpenSessionParams.Builder()
5237                 .setDeviceAddress(UwbAddress.fromBytes(new byte[] {(byte) 0x01, (byte) 0x02 }))
5238                 .setVendorId(new byte[] { (byte) 0x00, (byte) 0x01 })
5239                 .setStaticStsIV(new byte[] { (byte) 0x01, (byte) 0x02, (byte) 0x03,
5240                         (byte) 0x04, (byte) 0x05, (byte) 0x06 })
5241                 .setDestAddressList(Arrays.asList(
5242                         UWB_DEST_ADDRESS))
5243                 .setProtocolVersion(new FiraProtocolVersion(1, 0))
5244                 .setSessionId(10)
5245                 .setSessionType(FiraParams.SESSION_TYPE_RANGING_WITH_DATA_PHASE)
5246                 .setDeviceType(FiraParams.RANGING_DEVICE_TYPE_CONTROLLER)
5247                 .setDeviceRole(FiraParams.RANGING_DEVICE_ROLE_INITIATOR)
5248                 .setMultiNodeMode(FiraParams.MULTI_NODE_MODE_UNICAST)
5249                 .setRangingIntervalMs(TEST_RANGING_INTERVAL_MS)
5250                 .setScheduledMode(FiraParams.HYBRID_SCHEDULED_RANGING)
5251                 .setDataRepetitionCount(0)
5252                 .build();
5253         UwbSession uwbSession = prepareExistingUwbSessionWithSessionType(
5254                 (byte) FiraParams.SESSION_TYPE_RANGING_WITH_DATA_PHASE, params);
5255 
5256 
5257         // Expected to fail due to invalid device type(controller)
5258         mUwbSessionManager.setHybridSessionControleeConfiguration(
5259                 uwbSession.getSessionHandle(), mHybridControleeParams.toBundle());
5260         mTestLooper.dispatchAll();
5261 
5262         verify(mUwbSessionNotificationManager).onHybridSessionControleeConfigurationFailed(
5263                 any(), anyInt());
5264     }
5265 
5266     @Test
deInitSession_notExistedSession()5267     public void deInitSession_notExistedSession() {
5268         doReturn(false).when(mUwbSessionManager).isExistedSession(any());
5269 
5270         mUwbSessionManager.deInitSession(mock(SessionHandle.class));
5271 
5272         verify(mUwbSessionManager, never()).getSessionId(any());
5273         assertThat(mTestLooper.nextMessage()).isNull();
5274     }
5275 
5276     @Test
deInitSession_success()5277     public void deInitSession_success() {
5278         doReturn(true).when(mUwbSessionManager).isExistedSession(any());
5279         doReturn(TEST_SESSION_ID).when(mUwbSessionManager).getSessionId(any());
5280 
5281         UwbSession mockUwbSession = mock(UwbSession.class);
5282         SessionHandle mockSessionHandle = mock(SessionHandle.class);
5283         mUwbSessionManager.mSessionTable.put(mockSessionHandle, mockUwbSession);
5284 
5285         mUwbSessionManager.deInitSession(mockSessionHandle);
5286 
5287         assertThat(mTestLooper.nextMessage().what).isEqualTo(5); // SESSION_DEINIT
5288 
5289         verifyZeroInteractions(mUwbAdvertiseManager);
5290     }
5291 
5292     @Test
deInitSession_success_afterOwrAoaMeasurement()5293     public void deInitSession_success_afterOwrAoaMeasurement() {
5294         UwbSession mockUwbSession = mock(UwbSession.class);
5295         SessionHandle mockSessionHandle = mock(SessionHandle.class);
5296         mUwbSessionManager.mSessionTable.put(mockSessionHandle, mockUwbSession);
5297 
5298         when(mockUwbSession.getWaitObj()).thenReturn(mock(WaitObj.class));
5299         when(mockUwbSession.getSessionHandle()).thenReturn(mockSessionHandle);
5300         doReturn(mockUwbSession).when(mUwbSessionManager).getUwbSession(eq(TEST_SESSION_ID));
5301 
5302         // Setup the UwbSession to have the peer device's MacAddress stored (which happens when
5303         // a valid RANGE_DATA_NTF with an OWR AoA Measurement is received).
5304         doReturn(Set.of(PEER_EXTENDED_MAC_ADDRESS_LONG)).when(mockUwbSession)
5305                 .getRemoteMacAddressList();
5306 
5307         // Call deInitSession().
5308         IBinder mockBinder = mock(IBinder.class);
5309         doReturn(mockBinder).when(mockUwbSession).getBinder();
5310         doReturn(FiraParams.PROTOCOL_NAME).when(mockUwbSession).getProtocolName();
5311         doReturn(null).when(mockUwbSession).getAnyNonPrivilegedAppInAttributionSource();
5312         doReturn(true).when(mUwbSessionManager).isExistedSession(any());
5313         doReturn(TEST_SESSION_ID).when(mUwbSessionManager).getSessionId(any());
5314         doReturn(TEST_SESSION_ID).when(mockUwbSession).getSessionId();
5315 
5316         mUwbSessionManager.deInitSession(mockSessionHandle);
5317         mTestLooper.dispatchNext();
5318 
5319         verify(mUwbAdvertiseManager).removeAdvertiseTarget(PEER_EXTENDED_MAC_ADDRESS_LONG);
5320     }
5321 
5322     @Test
execDeInitSession()5323     public void execDeInitSession() throws Exception {
5324         UwbSession uwbSession = prepareExistingUwbSession();
5325 
5326         mUwbSessionManager.deInitSession(uwbSession.getSessionHandle());
5327 
5328         assertThat(mTestLooper.nextMessage().what).isEqualTo(5); // SESSION_DEINIT
5329     }
5330 
5331     @Test
execDeInitSession_success()5332     public void execDeInitSession_success() throws Exception {
5333         UwbSession uwbSession = prepareExistingUwbSession();
5334         when(mNativeUwbManager.deInitSession(eq(TEST_SESSION_ID), anyString()))
5335                 .thenReturn((byte) UwbUciConstants.STATUS_CODE_OK);
5336 
5337         mUwbSessionManager.deInitSession(uwbSession.getSessionHandle());
5338         mTestLooper.dispatchNext();
5339 
5340         verify(mUwbSessionNotificationManager).onRangingClosed(
5341                 eq(uwbSession), eq(UwbUciConstants.STATUS_CODE_OK));
5342         verify(mUwbMetrics).logRangingCloseEvent(
5343                 eq(uwbSession), eq(UwbUciConstants.STATUS_CODE_OK));
5344         assertThat(mUwbSessionManager.getSessionCount()).isEqualTo(0);
5345         assertThat(mUwbSessionManager.getAliroSessionCount()).isEqualTo(0L);
5346         assertThat(mUwbSessionManager.getCccSessionCount()).isEqualTo(0L);
5347         assertThat(mUwbSessionManager.getFiraSessionCount()).isEqualTo(0L);
5348         verifyZeroInteractions(mUwbAdvertiseManager);
5349     }
5350 
5351     @Test
execDeInitSession_failed()5352     public void execDeInitSession_failed() throws Exception {
5353         UwbSession uwbSession = prepareExistingUwbSession();
5354         when(mNativeUwbManager.deInitSession(eq(TEST_SESSION_ID), anyString()))
5355                 .thenReturn((byte) UwbUciConstants.STATUS_CODE_FAILED);
5356 
5357         mUwbSessionManager.deInitSession(uwbSession.getSessionHandle());
5358         mTestLooper.dispatchNext();
5359 
5360         verify(mUwbSessionNotificationManager).onRangingClosed(
5361                 eq(uwbSession), eq(UwbUciConstants.STATUS_CODE_FAILED));
5362         verify(mUwbAdvertiseManager, never()).removeAdvertiseTarget(isA(Long.class));
5363         verify(mUwbMetrics).logRangingCloseEvent(
5364                 eq(uwbSession), eq(UwbUciConstants.STATUS_CODE_FAILED));
5365         assertThat(mUwbSessionManager.getSessionCount()).isEqualTo(0);
5366         assertThat(mUwbSessionManager.getAliroSessionCount()).isEqualTo(0L);
5367         assertThat(mUwbSessionManager.getCccSessionCount()).isEqualTo(0L);
5368         assertThat(mUwbSessionManager.getFiraSessionCount()).isEqualTo(0L);
5369         verifyZeroInteractions(mUwbAdvertiseManager);
5370     }
5371 
5372     @Test
execDeInitSession_multipleTimes()5373     public void execDeInitSession_multipleTimes() throws Exception {
5374         UwbSession uwbSession = prepareExistingUwbSession();
5375         when(mNativeUwbManager.deInitSession(eq(TEST_SESSION_ID), anyString()))
5376                 .thenReturn((byte) UwbUciConstants.STATUS_CODE_OK);
5377 
5378         // Call deInitSession() twice on the same UWB Session, and then proceed to dispatch the two
5379         // messages for both the calls. The second message should not have any effect, and silently
5380         // stop processing.
5381         mUwbSessionManager.deInitSession(uwbSession.getSessionHandle());
5382         mUwbSessionManager.deInitSession(uwbSession.getSessionHandle());
5383         mTestLooper.dispatchNext();
5384         mTestLooper.dispatchNext();
5385 
5386         // Verify the DeInit steps.
5387         verify(mUwbSessionNotificationManager, times(1)).onRangingClosed(
5388                 eq(uwbSession), eq(UwbUciConstants.STATUS_CODE_OK));
5389         verify(mUwbMetrics).logRangingCloseEvent(
5390                 eq(uwbSession), eq(UwbUciConstants.STATUS_CODE_OK));
5391         assertThat(mUwbSessionManager.getSessionCount()).isEqualTo(0);
5392         assertThat(mUwbSessionManager.getAliroSessionCount()).isEqualTo(0L);
5393         assertThat(mUwbSessionManager.getCccSessionCount()).isEqualTo(0L);
5394         assertThat(mUwbSessionManager.getFiraSessionCount()).isEqualTo(0L);
5395         verifyZeroInteractions(mUwbAdvertiseManager);
5396     }
5397 
5398     @Test
deinitAllSession()5399     public void deinitAllSession() {
5400         UwbSession mockUwbSession1 = mock(UwbSession.class);
5401         SessionHandle mockSessionHandle1 = mock(SessionHandle.class);
5402         when(mockUwbSession1.getSessionId()).thenReturn(TEST_SESSION_ID);
5403         when(mockUwbSession1.getBinder()).thenReturn(mock(IBinder.class));
5404         when(mockUwbSession1.getSessionId()).thenReturn(TEST_SESSION_ID);
5405         when(mockUwbSession1.getProtocolName()).thenReturn(FiraParams.PROTOCOL_NAME);
5406         when(mockUwbSession1.getSessionHandle()).thenReturn(mockSessionHandle1);
5407         mUwbSessionManager.mSessionTable.put(mockSessionHandle1, mockUwbSession1);
5408 
5409         UwbSession mockUwbSession2 = mock(UwbSession.class);
5410         SessionHandle mockSessionHandle2 = mock(SessionHandle.class);
5411         when(mockUwbSession2.getBinder()).thenReturn(mock(IBinder.class));
5412         when(mockUwbSession2.getSessionId()).thenReturn(TEST_SESSION_ID + 100);
5413         when(mockUwbSession2.getProtocolName()).thenReturn(FiraParams.PROTOCOL_NAME);
5414         when(mockUwbSession2.getSessionHandle()).thenReturn(mockSessionHandle2);
5415         mUwbSessionManager.mSessionTable.put(mockSessionHandle2, mockUwbSession2);
5416 
5417         mUwbSessionManager.deinitAllSession();
5418 
5419         verify(mUwbSessionNotificationManager, times(2))
5420                 .onRangingClosedWithApiReasonCode(any(), eq(RangingChangeReason.SYSTEM_POLICY));
5421         verify(mUwbSessionManager, times(2)).removeSession(any());
5422         // TODO: enable it when the deviceReset is enabled.
5423         // verify(mNativeUwbManager).deviceReset(eq(UwbUciConstants.UWBS_RESET));
5424         assertThat(mUwbSessionManager.getSessionCount()).isEqualTo(0);
5425         assertThat(mUwbSessionManager.getAliroSessionCount()).isEqualTo(0L);
5426         assertThat(mUwbSessionManager.getCccSessionCount()).isEqualTo(0L);
5427         assertThat(mUwbSessionManager.getFiraSessionCount()).isEqualTo(0L);
5428     }
5429 
5430     @Test
onSessionStatusNotification_session_deinit()5431     public void onSessionStatusNotification_session_deinit() throws Exception {
5432         UwbSession uwbSession = prepareExistingUwbSession();
5433         when(mNativeUwbManager.deInitSession(eq(TEST_SESSION_ID), anyString()))
5434                 .thenReturn((byte) UwbUciConstants.STATUS_CODE_OK);
5435 
5436         mUwbSessionManager.onSessionStatusNotificationReceived(
5437                 uwbSession.getSessionId(), SESSION_TOKEN,
5438                 UwbUciConstants.UWB_SESSION_STATE_DEINIT,
5439                 UwbUciConstants.REASON_STATE_CHANGE_WITH_SESSION_MANAGEMENT_COMMANDS);
5440         mTestLooper.dispatchNext();
5441 
5442         verify(mUwbSessionNotificationManager).onRangingClosedWithApiReasonCode(
5443                 eq(uwbSession), eq(RangingChangeReason.SYSTEM_POLICY));
5444         verify(mUwbMetrics).logRangingCloseEvent(
5445                 eq(uwbSession), eq(UwbUciConstants.STATUS_CODE_OK));
5446         assertThat(mUwbSessionManager.getSessionCount()).isEqualTo(0);
5447         assertThat(mUwbSessionManager.getAliroSessionCount()).isEqualTo(0L);
5448         assertThat(mUwbSessionManager.getCccSessionCount()).isEqualTo(0L);
5449         assertThat(mUwbSessionManager.getFiraSessionCount()).isEqualTo(0L);
5450     }
5451 
5452     @Test
onSessionStatusNotification_session_deinit_after_close()5453     public void onSessionStatusNotification_session_deinit_after_close() throws Exception {
5454         UwbSession uwbSession = prepareExistingUwbSession();
5455         when(mNativeUwbManager.deInitSession(eq(TEST_SESSION_ID), anyString()))
5456                 .thenReturn((byte) UwbUciConstants.STATUS_CODE_OK);
5457 
5458         mUwbSessionManager.deinitAllSession();
5459         verify(mUwbSessionNotificationManager).onRangingClosedWithApiReasonCode(
5460                 eq(uwbSession), eq(RangingChangeReason.SYSTEM_POLICY));
5461         verify(mUwbMetrics).logRangingCloseEvent(
5462                 eq(uwbSession), eq(UwbUciConstants.STATUS_CODE_OK));
5463         assertThat(mUwbSessionManager.getSessionCount()).isEqualTo(0);
5464         assertThat(mUwbSessionManager.getAliroSessionCount()).isEqualTo(0L);
5465         assertThat(mUwbSessionManager.getCccSessionCount()).isEqualTo(0L);
5466         assertThat(mUwbSessionManager.getFiraSessionCount()).isEqualTo(0L);
5467 
5468         // Ignore the stale deinit
5469         mUwbSessionManager.handleOnDeInit(uwbSession);
5470         verifyNoMoreInteractions(mUwbSessionNotificationManager);
5471     }
5472 
5473     @Test
onSessionStatusNotification_session_deinit_owrAoa()5474     public void onSessionStatusNotification_session_deinit_owrAoa() throws Exception {
5475         Params firaParams = setupFiraParams(
5476                 RANGING_DEVICE_ROLE_OBSERVER, Optional.of(ROUND_USAGE_OWR_AOA_MEASUREMENT));
5477         UwbSession uwbSession = prepareExistingUwbSession(firaParams);
5478 
5479         UwbRangingData uwbRangingData = UwbTestUtils.generateRangingData(
5480                 RANGING_MEASUREMENT_TYPE_OWR_AOA, MAC_ADDRESSING_MODE_EXTENDED,
5481                 UwbUciConstants.STATUS_CODE_OK);
5482 
5483         // First call onDataReceived() to get the application payload data.
5484         when(mDeviceConfigFacade.getRxDataMaxPacketsToStore())
5485                 .thenReturn(MAX_RX_DATA_PACKETS_TO_STORE);
5486         mUwbSessionManager.onDataReceived(TEST_SESSION_ID, UwbUciConstants.STATUS_CODE_OK,
5487                 DATA_SEQUENCE_NUM, PEER_EXTENDED_MAC_ADDRESS, DATA_PAYLOAD);
5488 
5489         // Next call onRangeDataNotificationReceived() to process the RANGE_DATA_NTF. Setup
5490         // isPointedTarget() to return "false", as in that scenario the stored AdvertiseTarget
5491         // is not removed.
5492         when(mUwbAdvertiseManager.isPointedTarget(PEER_EXTENDED_MAC_ADDRESS)).thenReturn(false);
5493         mUwbSessionManager.onRangeDataNotificationReceived(uwbRangingData);
5494 
5495         verify(mUwbAdvertiseManager).updateAdvertiseTarget(uwbRangingData.mRangingOwrAoaMeasure);
5496         verify(mUwbAdvertiseManager).isPointedTarget(PEER_EXTENDED_MAC_ADDRESS);
5497 
5498         // Now call onSessionStatusNotificationReceived() on the same UwbSession, and verify that
5499         // removeAdvertiseTarget() is called to remove any stored OwR AoA Measurement(s).
5500         when(mNativeUwbManager.deInitSession(eq(TEST_SESSION_ID), anyString()))
5501                 .thenReturn((byte) UwbUciConstants.STATUS_CODE_OK);
5502 
5503         mUwbSessionManager.onSessionStatusNotificationReceived(
5504                 uwbSession.getSessionId(), SESSION_TOKEN,
5505                 UwbUciConstants.UWB_SESSION_STATE_DEINIT,
5506                 UwbUciConstants.REASON_STATE_CHANGE_WITH_SESSION_MANAGEMENT_COMMANDS);
5507         mTestLooper.dispatchNext();
5508 
5509         verify(mUwbSessionNotificationManager).onRangingClosedWithApiReasonCode(
5510                 eq(uwbSession), eq(RangingChangeReason.SYSTEM_POLICY));
5511         verify(mUwbMetrics).logRangingCloseEvent(
5512                 eq(uwbSession), eq(UwbUciConstants.STATUS_CODE_OK));
5513         assertThat(mUwbSessionManager.getSessionCount()).isEqualTo(0);
5514         assertThat(mUwbSessionManager.getAliroSessionCount()).isEqualTo(0L);
5515         assertThat(mUwbSessionManager.getCccSessionCount()).isEqualTo(0L);
5516         assertThat(mUwbSessionManager.getFiraSessionCount()).isEqualTo(0L);
5517 
5518         verify(mUwbAdvertiseManager).removeAdvertiseTarget(isA(Long.class));
5519     }
5520 
5521     @Test
testHandleClientDeath()5522     public void testHandleClientDeath() throws Exception {
5523         UwbSession uwbSession = prepareExistingUwbSession();
5524         when(mNativeUwbManager.deInitSession(eq(TEST_SESSION_ID), anyString()))
5525                 .thenReturn((byte) UwbUciConstants.STATUS_CODE_FAILED);
5526 
5527         uwbSession.binderDied();
5528 
5529         verify(mUwbMetrics).logRangingCloseEvent(
5530                 eq(uwbSession), eq(UwbUciConstants.STATUS_CODE_FAILED));
5531         assertThat(mUwbSessionManager.getSessionCount()).isEqualTo(0);
5532         assertThat(mUwbSessionManager.getAliroSessionCount()).isEqualTo(0L);
5533         assertThat(mUwbSessionManager.getCccSessionCount()).isEqualTo(0L);
5534         assertThat(mUwbSessionManager.getFiraSessionCount()).isEqualTo(0L);
5535     }
5536 
5537     @Test
testDtTagRangingRoundsUpdate()5538     public void testDtTagRangingRoundsUpdate() throws Exception {
5539         UwbSession uwbSession = prepareExistingUwbSession();
5540         byte[] indices = {1, 2};
5541         DtTagUpdateRangingRoundsStatus status = new DtTagUpdateRangingRoundsStatus(0,
5542                 indices.length, indices);
5543         PersistableBundle bundle = new DlTDoARangingRoundsUpdate.Builder()
5544                 .setSessionId(uwbSession.getSessionId())
5545                 .setNoOfRangingRounds(indices.length)
5546                 .setRangingRoundIndexes(indices)
5547                 .build()
5548                 .toBundle();
5549 
5550         when(mNativeUwbManager.sessionUpdateDtTagRangingRounds(anyInt(), anyInt(), any(),
5551                 anyString())).thenReturn(status);
5552 
5553         mUwbSessionManager.rangingRoundsUpdateDtTag(uwbSession.getSessionHandle(), bundle);
5554         mTestLooper.dispatchAll();
5555 
5556         verify(mNativeUwbManager).sessionUpdateDtTagRangingRounds(uwbSession.getSessionId(),
5557                 indices.length, indices, uwbSession.getChipId());
5558         verify(mUwbSessionNotificationManager).onRangingRoundsUpdateStatus(any(), any());
5559     }
5560 
5561 
5562     @Test
onDataTransferPhaseConfigNotificationReceived()5563     public void onDataTransferPhaseConfigNotificationReceived()
5564             throws Exception {
5565         UwbSession uwbSession = prepareExistingUwbSession();
5566         //successfully setting the configuration
5567         mUwbSessionManager.onDataTransferPhaseConfigNotificationReceived(uwbSession.getSessionId(),
5568                 UwbUciConstants.STATUS_CODE_DATA_TRANSFER_PHASE_CONFIG_DTPCM_CONFIG_SUCCESS);
5569         mTestLooper.dispatchAll();
5570         verify(mUwbSessionNotificationManager)
5571                 .onDataTransferPhaseConfigured(
5572                 isA(UwbSession.class),
5573                 eq(UwbUciConstants.STATUS_CODE_DATA_TRANSFER_PHASE_CONFIG_DTPCM_CONFIG_SUCCESS));
5574 
5575         //failed to set the configuration
5576         mUwbSessionManager.onDataTransferPhaseConfigNotificationReceived(uwbSession.getSessionId(),
5577                 UwbUciConstants
5578                 .STATUS_CODE_DATA_TRANSFER_PHASE_CONFIG_ERROR_DUPLICATE_SLOT_ASSIGNMENT);
5579         mTestLooper.dispatchAll();
5580         verify(mUwbSessionNotificationManager).onDataTransferPhaseConfigFailed(
5581                 isA(UwbSession.class),
5582                 eq(UwbUciConstants.STATUS_CODE_DATA_TRANSFER_PHASE_CONFIG_ERROR_DUPLICATE_SLOT_ASSIGNMENT));
5583     }
5584 
5585 
5586     @Test
onRadarDataMessageReceivedWithValidUwbSession()5587     public void onRadarDataMessageReceivedWithValidUwbSession() {
5588         UwbRadarData uwbRadarData = UwbTestUtils.generateUwbRadarData(
5589                 RADAR_DATA_TYPE_RADAR_SWEEP_SAMPLES,
5590                 UwbUciConstants.STATUS_CODE_OK);
5591         UwbSession mockUwbSession = mock(UwbSession.class);
5592         when(mockUwbSession.getWaitObj()).thenReturn(mock(WaitObj.class));
5593         doReturn(mockUwbSession)
5594                 .when(mUwbSessionManager).getUwbSession(eq(TEST_SESSION_ID));
5595 
5596         mUwbSessionManager.onRadarDataMessageReceived(uwbRadarData);
5597 
5598         verify(mUwbSessionNotificationManager)
5599                 .onRadarDataMessageReceived(eq(mockUwbSession), eq(uwbRadarData));
5600     }
5601 
5602     @Test
onRadarDataMessageReceivedWithInvalidSession()5603     public void onRadarDataMessageReceivedWithInvalidSession() {
5604         UwbRadarData uwbRadarData = UwbTestUtils.generateUwbRadarData(
5605                 RADAR_DATA_TYPE_RADAR_SWEEP_SAMPLES,
5606                 UwbUciConstants.STATUS_CODE_OK);
5607         doReturn(null)
5608                 .when(mUwbSessionManager).getUwbSession(eq(TEST_SESSION_ID));
5609 
5610         mUwbSessionManager.onRadarDataMessageReceived(uwbRadarData);
5611 
5612         verify(mUwbSessionNotificationManager, never())
5613                 .onRadarDataMessageReceived(any(), eq(uwbRadarData));
5614     }
5615 
5616     @Test
execStartRanging_onRadarDataMessage()5617     public void execStartRanging_onRadarDataMessage() throws Exception {
5618         UwbSession uwbSession = prepareExistingUwbSession(setupRadarParams());
5619         // set up for start ranging
5620         doReturn(UwbUciConstants.UWB_SESSION_STATE_IDLE, UwbUciConstants.UWB_SESSION_STATE_ACTIVE)
5621                 .when(uwbSession).getSessionState();
5622         when(mNativeUwbManager.startRanging(eq(TEST_SESSION_ID), anyString()))
5623                 .thenReturn((byte) UwbUciConstants.STATUS_CODE_OK);
5624 
5625         mUwbSessionManager.startRanging(
5626                 uwbSession.getSessionHandle(), uwbSession.getParams());
5627         mTestLooper.dispatchAll();
5628 
5629         verify(mUwbSessionNotificationManager).onRangingStarted(eq(uwbSession), any());
5630         verify(mUwbMetrics).longRangingStartEvent(
5631                 eq(uwbSession), eq(UwbUciConstants.STATUS_CODE_OK));
5632 
5633         // Now send a radar data notification.
5634         UwbRadarData uwbRadarData = UwbTestUtils.generateUwbRadarData(
5635                 RADAR_DATA_TYPE_RADAR_SWEEP_SAMPLES,
5636                 UwbUciConstants.STATUS_CODE_OK);
5637         mUwbSessionManager.onRadarDataMessageReceived(uwbRadarData);
5638         verify(mUwbSessionNotificationManager)
5639                 .onRadarDataMessageReceived(uwbSession, uwbRadarData);
5640     }
5641 
buildReceivedDataInfo(long macAddress)5642     private UwbSessionManager.ReceivedDataInfo buildReceivedDataInfo(long macAddress) {
5643         return buildReceivedDataInfo(macAddress, DATA_SEQUENCE_NUM);
5644     }
5645 
buildReceivedDataInfo( long macAddress, long sequenceNum)5646     private UwbSessionManager.ReceivedDataInfo buildReceivedDataInfo(
5647             long macAddress, long sequenceNum) {
5648         UwbSessionManager.ReceivedDataInfo info = new UwbSessionManager.ReceivedDataInfo();
5649         info.sessionId = TEST_SESSION_ID;
5650         info.status = STATUS_CODE_OK;
5651         info.sequenceNum = sequenceNum;
5652         info.address = macAddress;
5653         info.payload = DATA_PAYLOAD;
5654         return info;
5655     }
5656 
getComputedMacAddress(byte[] address)5657     private static byte[] getComputedMacAddress(byte[] address) {
5658         if (!SdkLevel.isAtLeastU()) {
5659             return TlvUtil.getReverseBytes(address);
5660         }
5661         return address;
5662     }
5663 }
5664