• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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.server.uwb.UwbSessionManager.SESSION_OPEN_RANGING;
23 import static com.android.server.uwb.UwbTestUtils.DATA_PAYLOAD;
24 import static com.android.server.uwb.UwbTestUtils.MAX_DATA_SIZE;
25 import static com.android.server.uwb.UwbTestUtils.PEER_BAD_MAC_ADDRESS;
26 import static com.android.server.uwb.UwbTestUtils.PEER_EXTENDED_MAC_ADDRESS;
27 import static com.android.server.uwb.UwbTestUtils.PEER_EXTENDED_MAC_ADDRESS_2;
28 import static com.android.server.uwb.UwbTestUtils.PEER_EXTENDED_MAC_ADDRESS_2_LONG;
29 import static com.android.server.uwb.UwbTestUtils.PEER_EXTENDED_MAC_ADDRESS_LONG;
30 import static com.android.server.uwb.UwbTestUtils.PEER_EXTENDED_SHORT_MAC_ADDRESS;
31 import static com.android.server.uwb.UwbTestUtils.PEER_EXTENDED_SHORT_MAC_ADDRESS_LONG;
32 import static com.android.server.uwb.UwbTestUtils.PEER_EXTENDED_SHORT_UWB_ADDRESS;
33 import static com.android.server.uwb.UwbTestUtils.PEER_EXTENDED_UWB_ADDRESS;
34 import static com.android.server.uwb.UwbTestUtils.PEER_EXTENDED_UWB_ADDRESS_2;
35 import static com.android.server.uwb.UwbTestUtils.PEER_SHORT_MAC_ADDRESS;
36 import static com.android.server.uwb.UwbTestUtils.PEER_SHORT_MAC_ADDRESS_LONG;
37 import static com.android.server.uwb.UwbTestUtils.PEER_SHORT_UWB_ADDRESS;
38 import static com.android.server.uwb.UwbTestUtils.PERSISTABLE_BUNDLE;
39 import static com.android.server.uwb.UwbTestUtils.RANGING_MEASUREMENT_TYPE_UNDEFINED;
40 import static com.android.server.uwb.UwbTestUtils.TEST_SESSION_ID;
41 import static com.android.server.uwb.UwbTestUtils.TEST_SESSION_ID_2;
42 import static com.android.server.uwb.UwbTestUtils.TEST_SESSION_TYPE;
43 import static com.android.server.uwb.data.UwbUciConstants.MAC_ADDRESSING_MODE_EXTENDED;
44 import static com.android.server.uwb.data.UwbUciConstants.MAC_ADDRESSING_MODE_SHORT;
45 import static com.android.server.uwb.data.UwbUciConstants.RANGING_DEVICE_ROLE_ADVERTISER;
46 import static com.android.server.uwb.data.UwbUciConstants.RANGING_DEVICE_ROLE_OBSERVER;
47 import static com.android.server.uwb.data.UwbUciConstants.RANGING_MEASUREMENT_TYPE_OWR_AOA;
48 import static com.android.server.uwb.data.UwbUciConstants.RANGING_MEASUREMENT_TYPE_TWO_WAY;
49 import static com.android.server.uwb.data.UwbUciConstants.ROUND_USAGE_DS_TWR_DEFERRED_MODE;
50 import static com.android.server.uwb.data.UwbUciConstants.ROUND_USAGE_DS_TWR_NON_DEFERRED_MODE;
51 import static com.android.server.uwb.data.UwbUciConstants.ROUND_USAGE_OWR_AOA_MEASUREMENT;
52 import static com.android.server.uwb.data.UwbUciConstants.STATUS_CODE_DATA_TRANSFER_ERROR_DATA_TRANSFER;
53 import static com.android.server.uwb.data.UwbUciConstants.STATUS_CODE_DATA_TRANSFER_REPETITION_OK;
54 
55 import static com.google.common.truth.Truth.assertThat;
56 import static com.google.uwb.support.fira.FiraParams.PROTOCOL_NAME;
57 import static com.google.uwb.support.fira.FiraParams.RangeDataNtfConfigCapabilityFlag.HAS_RANGE_DATA_NTF_CONFIG_DISABLE;
58 import static com.google.uwb.support.fira.FiraParams.RangeDataNtfConfigCapabilityFlag.HAS_RANGE_DATA_NTF_CONFIG_ENABLE;
59 import static com.google.uwb.support.fira.FiraParams.SESSION_TYPE_RANGING;
60 import static com.google.uwb.support.fira.FiraParams.STATUS_CODE_OK;
61 
62 import static org.junit.Assert.assertNotNull;
63 import static org.junit.Assert.assertNull;
64 import static org.junit.Assert.assertThrows;
65 import static org.mockito.ArgumentMatchers.any;
66 import static org.mockito.ArgumentMatchers.anyByte;
67 import static org.mockito.ArgumentMatchers.anyInt;
68 import static org.mockito.ArgumentMatchers.anyLong;
69 import static org.mockito.ArgumentMatchers.anyString;
70 import static org.mockito.ArgumentMatchers.eq;
71 import static org.mockito.ArgumentMatchers.isA;
72 import static org.mockito.Mockito.atLeast;
73 import static org.mockito.Mockito.clearInvocations;
74 import static org.mockito.Mockito.doAnswer;
75 import static org.mockito.Mockito.doReturn;
76 import static org.mockito.Mockito.doThrow;
77 import static org.mockito.Mockito.mock;
78 import static org.mockito.Mockito.never;
79 import static org.mockito.Mockito.spy;
80 import static org.mockito.Mockito.times;
81 import static org.mockito.Mockito.verify;
82 import static org.mockito.Mockito.verifyNoMoreInteractions;
83 import static org.mockito.Mockito.verifyZeroInteractions;
84 import static org.mockito.Mockito.when;
85 
86 import android.app.ActivityManager;
87 import android.app.ActivityManager.OnUidImportanceListener;
88 import android.app.AlarmManager;
89 import android.content.AttributionSource;
90 import android.os.IBinder;
91 import android.os.PersistableBundle;
92 import android.os.Process;
93 import android.os.RemoteException;
94 import android.os.test.TestLooper;
95 import android.uwb.IUwbAdapter;
96 import android.uwb.IUwbRangingCallbacks;
97 import android.uwb.RangingChangeReason;
98 import android.uwb.SessionHandle;
99 import android.uwb.StateChangeReason;
100 import android.uwb.UwbAddress;
101 import android.uwb.UwbOemExtensionCallbackListener;
102 
103 import com.android.modules.utils.build.SdkLevel;
104 import com.android.server.uwb.UwbSessionManager.UwbSession;
105 import com.android.server.uwb.UwbSessionManager.WaitObj;
106 import com.android.server.uwb.advertisement.UwbAdvertiseManager;
107 import com.android.server.uwb.data.DtTagUpdateRangingRoundsStatus;
108 import com.android.server.uwb.data.UwbMulticastListUpdateStatus;
109 import com.android.server.uwb.data.UwbRangingData;
110 import com.android.server.uwb.data.UwbUciConstants;
111 import com.android.server.uwb.jni.NativeUwbManager;
112 import com.android.server.uwb.multchip.UwbMultichipData;
113 import com.android.server.uwb.params.TlvUtil;
114 
115 import com.google.uwb.support.base.Params;
116 import com.google.uwb.support.ccc.CccOpenRangingParams;
117 import com.google.uwb.support.ccc.CccParams;
118 import com.google.uwb.support.ccc.CccPulseShapeCombo;
119 import com.google.uwb.support.ccc.CccSpecificationParams;
120 import com.google.uwb.support.ccc.CccStartRangingParams;
121 import com.google.uwb.support.dltdoa.DlTDoARangingRoundsUpdate;
122 import com.google.uwb.support.fira.FiraOpenSessionParams;
123 import com.google.uwb.support.fira.FiraParams;
124 import com.google.uwb.support.fira.FiraProtocolVersion;
125 import com.google.uwb.support.fira.FiraRangingReconfigureParams;
126 import com.google.uwb.support.fira.FiraSpecificationParams;
127 import com.google.uwb.support.generic.GenericSpecificationParams;
128 
129 import org.junit.After;
130 import org.junit.Before;
131 import org.junit.Test;
132 import org.mockito.ArgumentCaptor;
133 import org.mockito.Captor;
134 import org.mockito.Mock;
135 import org.mockito.MockitoAnnotations;
136 
137 import java.util.Arrays;
138 import java.util.Collections;
139 import java.util.EnumSet;
140 import java.util.List;
141 import java.util.Optional;
142 import java.util.Set;
143 import java.util.concurrent.ExecutionException;
144 import java.util.concurrent.ExecutorService;
145 import java.util.concurrent.FutureTask;
146 import java.util.concurrent.TimeoutException;
147 
148 public class UwbSessionManagerTest {
149     private static final String TEST_CHIP_ID = "testChipId";
150     private static final long MAX_FIRA_SESSION_NUM = 5;
151     private static final long MAX_CCC_SESSION_NUM = 1;
152     private static final int UID = 343453;
153     private static final String PACKAGE_NAME = "com.uwb.test";
154     private static final int UID_2 = 67;
155     private static final String PACKAGE_NAME_2 = "com.android.uwb.2";
156     private static final AttributionSource ATTRIBUTION_SOURCE =
157             new AttributionSource.Builder(UID).setPackageName(PACKAGE_NAME).build();
158     private static final AttributionSource ATTRIBUTION_SOURCE_2 =
159             new AttributionSource.Builder(UID_2).setPackageName(PACKAGE_NAME_2).build();
160     private static final SessionHandle SESSION_HANDLE =
161             new SessionHandle(TEST_SESSION_ID, ATTRIBUTION_SOURCE, 1);
162     private static final SessionHandle SESSION_HANDLE_2 =
163             new SessionHandle(TEST_SESSION_ID_2, ATTRIBUTION_SOURCE_2, 2);
164     private static final UwbAddress UWB_DEST_ADDRESS =
165             UwbAddress.fromBytes(new byte[] {(byte) 0x03, (byte) 0x04 });
166     private static final UwbAddress UWB_DEST_ADDRESS_2 =
167             UwbAddress.fromBytes(new byte[] {(byte) 0x05, (byte) 0x06 });
168     private static final UwbAddress UWB_DEST_ADDRESS_3 =
169             UwbAddress.fromBytes(new byte[] {(byte) 0x07, (byte) 0x08 });
170     private static final int TEST_RANGING_INTERVAL_MS = 200;
171     private static final byte DATA_SEQUENCE_NUM = 0;
172     private static final byte DATA_SEQUENCE_NUM_1 = 2;
173 
174     private static final int SOURCE_END_POINT = 100;
175     private static final int DEST_END_POINT = 200;
176     private static final int HANDLE_ID = 12;
177     private static final int MAX_RX_DATA_PACKETS_TO_STORE = 10;
178     private static final int PID = Process.myPid();
179 
180     @Mock
181     private UwbConfigurationManager mUwbConfigurationManager;
182     @Mock
183     private NativeUwbManager mNativeUwbManager;
184     @Mock
185     private UwbMetrics mUwbMetrics;
186     @Mock
187     private UwbAdvertiseManager mUwbAdvertiseManager;
188     @Mock
189     private UwbSessionNotificationManager mUwbSessionNotificationManager;
190     @Mock
191     private UwbInjector mUwbInjector;
192     @Mock
193     private ExecutorService mExecutorService;
194     @Mock
195     private AlarmManager mAlarmManager;
196     @Mock
197     private ActivityManager mActivityManager;
198     @Mock
199     private UwbServiceCore mUwbServiceCore;
200     @Mock
201     private DeviceConfigFacade mDeviceConfigFacade;
202     @Mock
203     private CccSpecificationParams mCccSpecificationParams;
204     @Mock
205     private UwbMultichipData mUwbMultichipData;
206     private TestLooper mTestLooper = new TestLooper();
207     private UwbSessionManager mUwbSessionManager;
208     @Captor
209     private ArgumentCaptor<OnUidImportanceListener> mOnUidImportanceListenerArgumentCaptor;
210     private GenericSpecificationParams.Builder mSpecificationParamsBuilder;
211 
212     @Before
setup()213     public void setup() throws ExecutionException, InterruptedException, TimeoutException {
214         MockitoAnnotations.initMocks(this);
215         when(mUwbInjector.isSystemApp(UID, PACKAGE_NAME)).thenReturn(true);
216         when(mUwbInjector.isForegroundAppOrService(UID, PACKAGE_NAME)).thenReturn(true);
217         when(mUwbInjector.getUwbServiceCore()).thenReturn(mUwbServiceCore);
218         when(mUwbInjector.getDeviceConfigFacade()).thenReturn(mDeviceConfigFacade);
219         when(mUwbInjector.getMultichipData()).thenReturn(mUwbMultichipData);
220         doAnswer(invocation -> {
221             FutureTask t = invocation.getArgument(0);
222             t.run();
223             return t.get();
224         }).when(mUwbInjector).runTaskOnSingleThreadExecutor(any(FutureTask.class), anyInt());
225         mSpecificationParamsBuilder = new GenericSpecificationParams.Builder()
226                 .setCccSpecificationParams(mCccSpecificationParams)
227                 .setFiraSpecificationParams(
228                         new FiraSpecificationParams.Builder()
229                                 .setSupportedChannels(List.of(9))
230                                 .setRangeDataNtfConfigCapabilities(
231                                         EnumSet.of(
232                                                 HAS_RANGE_DATA_NTF_CONFIG_DISABLE,
233                                                 HAS_RANGE_DATA_NTF_CONFIG_ENABLE))
234                                 .build());
235         when(mUwbServiceCore.getCachedSpecificationParams(any())).thenReturn(
236                 mSpecificationParamsBuilder.build());
237         when(mCccSpecificationParams.getMaxRangingSessionNumber()).thenReturn(
238                 (int) MAX_CCC_SESSION_NUM);
239         when(mUwbMultichipData.getDefaultChipId()).thenReturn("default");
240         when(mDeviceConfigFacade.isBackgroundRangingEnabled()).thenReturn(false);
241         when(mDeviceConfigFacade.isRangingErrorStreakTimerEnabled()).thenReturn(true);
242 
243         // TODO: Don't use spy.
244         mUwbSessionManager = spy(new UwbSessionManager(
245                 mUwbConfigurationManager,
246                 mNativeUwbManager,
247                 mUwbMetrics,
248                 mUwbAdvertiseManager,
249                 mUwbSessionNotificationManager,
250                 mUwbInjector,
251                 mAlarmManager,
252                 mActivityManager,
253                 mTestLooper.getLooper()));
254 
255         verify(mActivityManager).addOnUidImportanceListener(
256                 mOnUidImportanceListenerArgumentCaptor.capture(), anyInt());
257     }
258 
259     /**
260      * Called after each test
261      */
262     @After
cleanup()263     public void cleanup() { }
264 
265     @Test
onDataReceived_extendedMacAddressFormat_owrAoA()266     public void onDataReceived_extendedMacAddressFormat_owrAoA() {
267         UwbSession mockUwbSession = mock(UwbSession.class);
268         when(mockUwbSession.getWaitObj()).thenReturn(mock(WaitObj.class));
269         when(mockUwbSession.getRangingRoundUsage()).thenReturn(ROUND_USAGE_OWR_AOA_MEASUREMENT);
270         doReturn(mockUwbSession)
271                 .when(mUwbSessionManager).getUwbSession(eq(TEST_SESSION_ID));
272 
273         mUwbSessionManager.onDataReceived(TEST_SESSION_ID, UwbUciConstants.STATUS_CODE_OK,
274                 DATA_SEQUENCE_NUM, PEER_EXTENDED_MAC_ADDRESS, SOURCE_END_POINT, DEST_END_POINT,
275                 DATA_PAYLOAD);
276         verify(mockUwbSession).addReceivedDataInfo(isA(UwbSessionManager.ReceivedDataInfo.class));
277         verify(mUwbMetrics).logDataRx(eq(mockUwbSession), eq(UwbUciConstants.STATUS_CODE_OK));
278     }
279 
280     @Test
onDataReceived_unsupportedMacAddressLength_owrAoa()281     public void onDataReceived_unsupportedMacAddressLength_owrAoa() {
282         UwbSession mockUwbSession = mock(UwbSession.class);
283         when(mockUwbSession.getWaitObj()).thenReturn(mock(WaitObj.class));
284         when(mockUwbSession.getRangingRoundUsage()).thenReturn(ROUND_USAGE_OWR_AOA_MEASUREMENT);
285         doReturn(mockUwbSession)
286                 .when(mUwbSessionManager).getUwbSession(eq(TEST_SESSION_ID));
287 
288         mUwbSessionManager.onDataReceived(TEST_SESSION_ID, UwbUciConstants.STATUS_CODE_OK,
289                 DATA_SEQUENCE_NUM, PEER_BAD_MAC_ADDRESS, SOURCE_END_POINT, DEST_END_POINT,
290                 DATA_PAYLOAD);
291         verify(mockUwbSession, never()).addReceivedDataInfo(
292                 isA(UwbSessionManager.ReceivedDataInfo.class));
293         verify(mUwbMetrics, never()).logDataRx(eq(mockUwbSession),
294                 eq(UwbUciConstants.STATUS_CODE_OK));
295     }
296 
297     @Test
onDataReceived_shortMacAddressFormat_owrAoa()298     public void onDataReceived_shortMacAddressFormat_owrAoa() {
299         UwbSession mockUwbSession = mock(UwbSession.class);
300         when(mockUwbSession.getWaitObj()).thenReturn(mock(WaitObj.class));
301         when(mockUwbSession.getRangingRoundUsage()).thenReturn(ROUND_USAGE_OWR_AOA_MEASUREMENT);
302         doReturn(mockUwbSession)
303                 .when(mUwbSessionManager).getUwbSession(eq(TEST_SESSION_ID));
304 
305         mUwbSessionManager.onDataReceived(TEST_SESSION_ID, UwbUciConstants.STATUS_CODE_OK,
306                 DATA_SEQUENCE_NUM, PEER_EXTENDED_SHORT_MAC_ADDRESS, SOURCE_END_POINT,
307                 DEST_END_POINT, DATA_PAYLOAD);
308         verify(mockUwbSession).addReceivedDataInfo(isA(UwbSessionManager.ReceivedDataInfo.class));
309         verify(mUwbMetrics).logDataRx(eq(mockUwbSession), eq(UwbUciConstants.STATUS_CODE_OK));
310     }
311 
312     @Test
onDataReceived_shortMacAddressFormat_dsTwr()313     public void onDataReceived_shortMacAddressFormat_dsTwr() {
314         UwbSession mockUwbSession = mock(UwbSession.class);
315         when(mockUwbSession.getWaitObj()).thenReturn(mock(WaitObj.class));
316         when(mockUwbSession.getRangingRoundUsage()).thenReturn(
317                 ROUND_USAGE_DS_TWR_NON_DEFERRED_MODE);
318         doReturn(mockUwbSession)
319                 .when(mUwbSessionManager).getUwbSession(eq(TEST_SESSION_ID));
320 
321         mUwbSessionManager.onDataReceived(TEST_SESSION_ID, UwbUciConstants.STATUS_CODE_OK,
322                 DATA_SEQUENCE_NUM, PEER_EXTENDED_SHORT_MAC_ADDRESS, SOURCE_END_POINT,
323                 DEST_END_POINT, DATA_PAYLOAD);
324 
325         verify(mUwbSessionNotificationManager).onDataReceived(
326                 isA(UwbSession.class), eq(PEER_EXTENDED_SHORT_UWB_ADDRESS),
327                 isA(PersistableBundle.class), eq(DATA_PAYLOAD));
328         verify(mUwbMetrics).logDataRx(eq(mockUwbSession), eq(UwbUciConstants.STATUS_CODE_OK));
329         verify(mockUwbSession, never()).addReceivedDataInfo(
330                 isA(UwbSessionManager.ReceivedDataInfo.class));
331     }
332 
333     @Test
onRangeDataNotificationReceivedWithValidUwbSession_twoWay()334     public void onRangeDataNotificationReceivedWithValidUwbSession_twoWay() {
335         UwbRangingData uwbRangingData = UwbTestUtils.generateRangingData(
336                 RANGING_MEASUREMENT_TYPE_TWO_WAY, MAC_ADDRESSING_MODE_EXTENDED,
337                 UwbUciConstants.STATUS_CODE_OK);
338         UwbSession mockUwbSession = mock(UwbSession.class);
339         when(mockUwbSession.getWaitObj()).thenReturn(mock(WaitObj.class));
340         doReturn(mockUwbSession)
341                 .when(mUwbSessionManager).getUwbSession(eq(TEST_SESSION_ID));
342 
343         mUwbSessionManager.onRangeDataNotificationReceived(uwbRangingData);
344 
345         verify(mUwbSessionNotificationManager)
346                 .onRangingResult(eq(mockUwbSession), eq(uwbRangingData));
347     }
348 
349     @Test
onRangeDataNotificationReceivedWithInvalidSession_twoWay()350     public void onRangeDataNotificationReceivedWithInvalidSession_twoWay() {
351         UwbRangingData uwbRangingData = UwbTestUtils.generateRangingData(
352                 RANGING_MEASUREMENT_TYPE_TWO_WAY, MAC_ADDRESSING_MODE_EXTENDED,
353                 UwbUciConstants.STATUS_CODE_OK);
354         doReturn(null)
355                 .when(mUwbSessionManager).getUwbSession(eq(TEST_SESSION_ID));
356 
357         mUwbSessionManager.onRangeDataNotificationReceived(uwbRangingData);
358 
359         verify(mUwbSessionNotificationManager, never())
360                 .onRangingResult(any(), eq(uwbRangingData));
361     }
362 
363     // Test scenario for receiving Application payload data followed by a RANGE_DATA_NTF with an
364     // OWR Aoa Measurement (such that the ExtendedMacAddress format is used for the remote device).
365     @Test
onRangeDataNotificationReceived_owrAoa_success_extendedMacAddress()366     public void onRangeDataNotificationReceived_owrAoa_success_extendedMacAddress()
367             throws RemoteException {
368         UwbSession mockUwbSession = mock(UwbSession.class);
369         when(mockUwbSession.getWaitObj()).thenReturn(mock(WaitObj.class));
370         when(mockUwbSession.getRangingRoundUsage()).thenReturn(ROUND_USAGE_OWR_AOA_MEASUREMENT);
371         doReturn(mockUwbSession)
372                 .when(mUwbSessionManager).getUwbSession(eq(TEST_SESSION_ID));
373         UwbOemExtensionCallbackListener mUwbOemExtensionCallbackListener =
374                 mock(UwbOemExtensionCallbackListener.class);
375         when(mUwbServiceCore.isOemExtensionCbRegistered()).thenReturn(true);
376         when(mUwbServiceCore.getOemExtensionCallback())
377                 .thenReturn(mUwbOemExtensionCallbackListener);
378         when(mUwbOemExtensionCallbackListener.onCheckPointedTarget(any())).thenReturn(true);
379 
380         // First call onDataReceived() to get the application payload data.
381         mUwbSessionManager.onDataReceived(TEST_SESSION_ID, UwbUciConstants.STATUS_CODE_OK,
382                 DATA_SEQUENCE_NUM, PEER_EXTENDED_MAC_ADDRESS, SOURCE_END_POINT, DEST_END_POINT,
383                 DATA_PAYLOAD);
384         verify(mockUwbSession).addReceivedDataInfo(isA(UwbSessionManager.ReceivedDataInfo.class));
385         verify(mUwbMetrics).logDataRx(eq(mockUwbSession), eq(UwbUciConstants.STATUS_CODE_OK));
386 
387         // Next call onRangeDataNotificationReceived() to process the RANGE_DATA_NTF.
388         UwbRangingData uwbRangingData = UwbTestUtils.generateRangingData(
389                 RANGING_MEASUREMENT_TYPE_OWR_AOA, MAC_ADDRESSING_MODE_EXTENDED,
390                 UwbUciConstants.STATUS_CODE_OK);
391         Params firaParams = setupFiraParams(
392                 RANGING_DEVICE_ROLE_OBSERVER, Optional.of(ROUND_USAGE_OWR_AOA_MEASUREMENT));
393         when(mockUwbSession.getParams()).thenReturn(firaParams);
394         when(mUwbAdvertiseManager.isPointedTarget(PEER_EXTENDED_MAC_ADDRESS)).thenReturn(true);
395         when(mockUwbSession.getAllReceivedDataInfo(PEER_EXTENDED_MAC_ADDRESS_LONG))
396                 .thenReturn(List.of(buildReceivedDataInfo(PEER_EXTENDED_MAC_ADDRESS_LONG)));
397         mUwbSessionManager.onRangeDataNotificationReceived(uwbRangingData);
398 
399         verify(mUwbSessionNotificationManager)
400                 .onRangingResult(eq(mockUwbSession), eq(uwbRangingData));
401         verify(mUwbAdvertiseManager).updateAdvertiseTarget(uwbRangingData.mRangingOwrAoaMeasure);
402         verify(mUwbSessionNotificationManager)
403                 .onDataReceived(eq(mockUwbSession), eq(PEER_EXTENDED_UWB_ADDRESS),
404                         isA(PersistableBundle.class), eq(DATA_PAYLOAD));
405         verify(mUwbAdvertiseManager).removeAdvertiseTarget(PEER_EXTENDED_MAC_ADDRESS_LONG);
406         verify(mUwbMetrics).logDataToUpperLayer(eq(mockUwbSession), eq(1));
407     }
408 
409     // Test scenario for receiving Application payload data followed by a RANGE_DATA_NTF with an
410     // OWR Aoa Measurement (such that the ShortMacAddress format is used for the remote device).
411     @Test
onRangeDataNotificationReceived_owrAoa_success_shortMacAddress()412     public void onRangeDataNotificationReceived_owrAoa_success_shortMacAddress()
413             throws RemoteException {
414         UwbSession mockUwbSession = mock(UwbSession.class);
415         when(mockUwbSession.getWaitObj()).thenReturn(mock(WaitObj.class));
416         when(mockUwbSession.getRangingRoundUsage()).thenReturn(ROUND_USAGE_OWR_AOA_MEASUREMENT);
417         doReturn(mockUwbSession)
418                 .when(mUwbSessionManager).getUwbSession(eq(TEST_SESSION_ID));
419         UwbOemExtensionCallbackListener mUwbOemExtensionCallbackListener =
420                 mock(UwbOemExtensionCallbackListener.class);
421         when(mUwbServiceCore.isOemExtensionCbRegistered()).thenReturn(true);
422         when(mUwbServiceCore.getOemExtensionCallback())
423                 .thenReturn(mUwbOemExtensionCallbackListener);
424         when(mUwbOemExtensionCallbackListener.onCheckPointedTarget(any())).thenReturn(true);
425 
426         // First call onDataReceived() to get the application payload data. This should always have
427         // the MacAddress (in 8 Bytes), even for a Short MacAddress (MSB are zeroed out).
428         mUwbSessionManager.onDataReceived(TEST_SESSION_ID, UwbUciConstants.STATUS_CODE_OK,
429                 DATA_SEQUENCE_NUM, PEER_EXTENDED_SHORT_MAC_ADDRESS,
430                 SOURCE_END_POINT, DEST_END_POINT, DATA_PAYLOAD);
431         verify(mockUwbSession).addReceivedDataInfo(isA(UwbSessionManager.ReceivedDataInfo.class));
432         verify(mUwbMetrics).logDataRx(eq(mockUwbSession), eq(UwbUciConstants.STATUS_CODE_OK));
433 
434         // Next call onRangeDataNotificationReceived() to process the RANGE_DATA_NTF.
435         UwbRangingData uwbRangingData = UwbTestUtils.generateRangingData(
436                 RANGING_MEASUREMENT_TYPE_OWR_AOA, MAC_ADDRESSING_MODE_SHORT,
437                 UwbUciConstants.STATUS_CODE_OK);
438         Params firaParams = setupFiraParams(
439                 RANGING_DEVICE_ROLE_OBSERVER, Optional.of(ROUND_USAGE_OWR_AOA_MEASUREMENT));
440         when(mockUwbSession.getParams()).thenReturn(firaParams);
441         when(mUwbAdvertiseManager.isPointedTarget(PEER_SHORT_MAC_ADDRESS)).thenReturn(true);
442         when(mockUwbSession.getAllReceivedDataInfo(PEER_EXTENDED_SHORT_MAC_ADDRESS_LONG))
443                 .thenReturn(List.of(buildReceivedDataInfo(PEER_EXTENDED_SHORT_MAC_ADDRESS_LONG)));
444         mUwbSessionManager.onRangeDataNotificationReceived(uwbRangingData);
445 
446         verify(mUwbSessionNotificationManager)
447                 .onRangingResult(eq(mockUwbSession), eq(uwbRangingData));
448         verify(mUwbAdvertiseManager).updateAdvertiseTarget(uwbRangingData.mRangingOwrAoaMeasure);
449         verify(mUwbSessionNotificationManager)
450                 .onDataReceived(eq(mockUwbSession), eq(PEER_SHORT_UWB_ADDRESS),
451                         isA(PersistableBundle.class), eq(DATA_PAYLOAD));
452         verify(mUwbAdvertiseManager).removeAdvertiseTarget(PEER_SHORT_MAC_ADDRESS_LONG);
453         verify(mUwbMetrics).logDataToUpperLayer(eq(mockUwbSession), eq(1));
454     }
455 
456     // Test scenario for receiving Application payload data followed by a RANGE_DATA_NTF with an
457     // OWR Aoa Measurement, from Multiple advertiser devices in a UWB session.
458     @Test
onRangeDataNotificationReceived_owrAoa_success_multipleAdvertisers()459     public void onRangeDataNotificationReceived_owrAoa_success_multipleAdvertisers() {
460         UwbSession mockUwbSession = mock(UwbSession.class);
461         when(mockUwbSession.getWaitObj()).thenReturn(mock(WaitObj.class));
462         when(mockUwbSession.getRangingRoundUsage()).thenReturn(ROUND_USAGE_OWR_AOA_MEASUREMENT);
463         doReturn(mockUwbSession)
464                 .when(mUwbSessionManager).getUwbSession(eq(TEST_SESSION_ID));
465 
466         // First call onDataReceived() to get the application payload data.
467         mUwbSessionManager.onDataReceived(TEST_SESSION_ID, UwbUciConstants.STATUS_CODE_OK,
468                 DATA_SEQUENCE_NUM, PEER_EXTENDED_MAC_ADDRESS, SOURCE_END_POINT, DEST_END_POINT,
469                 DATA_PAYLOAD);
470         mUwbSessionManager.onDataReceived(TEST_SESSION_ID, UwbUciConstants.STATUS_CODE_OK,
471                 DATA_SEQUENCE_NUM_1, PEER_EXTENDED_MAC_ADDRESS, SOURCE_END_POINT, DEST_END_POINT,
472                 DATA_PAYLOAD);
473 
474         mUwbSessionManager.onDataReceived(TEST_SESSION_ID, UwbUciConstants.STATUS_CODE_OK,
475                 DATA_SEQUENCE_NUM, PEER_EXTENDED_MAC_ADDRESS_2, SOURCE_END_POINT, DEST_END_POINT,
476                 DATA_PAYLOAD);
477         mUwbSessionManager.onDataReceived(TEST_SESSION_ID, UwbUciConstants.STATUS_CODE_OK,
478                 DATA_SEQUENCE_NUM_1, PEER_EXTENDED_MAC_ADDRESS_2, SOURCE_END_POINT, DEST_END_POINT,
479                 DATA_PAYLOAD);
480 
481         verify(mockUwbSession, times(4)).addReceivedDataInfo(
482                 isA(UwbSessionManager.ReceivedDataInfo.class));
483         verify(mUwbMetrics, times(4)).logDataRx(
484                 eq(mockUwbSession), eq(UwbUciConstants.STATUS_CODE_OK));
485 
486         // Next call onRangeDataNotificationReceived() to process the RANGE_DATA_NTF.
487         UwbRangingData uwbRangingData1 = UwbTestUtils.generateRangingData(
488                 RANGING_MEASUREMENT_TYPE_OWR_AOA, MAC_ADDRESSING_MODE_EXTENDED,
489                 PEER_EXTENDED_MAC_ADDRESS, UwbUciConstants.STATUS_CODE_OK);
490         UwbRangingData uwbRangingData2 = UwbTestUtils.generateRangingData(
491                 RANGING_MEASUREMENT_TYPE_OWR_AOA, MAC_ADDRESSING_MODE_EXTENDED,
492                 PEER_EXTENDED_MAC_ADDRESS_2, UwbUciConstants.STATUS_CODE_OK);
493         Params firaParams = setupFiraParams(
494                 RANGING_DEVICE_ROLE_OBSERVER, Optional.of(ROUND_USAGE_OWR_AOA_MEASUREMENT));
495         when(mockUwbSession.getParams()).thenReturn(firaParams);
496         when(mUwbAdvertiseManager.isPointedTarget(PEER_EXTENDED_MAC_ADDRESS)).thenReturn(true);
497         when(mUwbAdvertiseManager.isPointedTarget(PEER_EXTENDED_MAC_ADDRESS_2)).thenReturn(true);
498         when(mockUwbSession.getAllReceivedDataInfo(PEER_EXTENDED_MAC_ADDRESS_LONG))
499                 .thenReturn(List.of(
500                         buildReceivedDataInfo(PEER_EXTENDED_MAC_ADDRESS_LONG, DATA_SEQUENCE_NUM),
501                         buildReceivedDataInfo(
502                                 PEER_EXTENDED_MAC_ADDRESS_LONG, DATA_SEQUENCE_NUM_1)));
503         when(mockUwbSession.getAllReceivedDataInfo(PEER_EXTENDED_MAC_ADDRESS_2_LONG))
504                 .thenReturn(List.of(
505                         buildReceivedDataInfo(PEER_EXTENDED_MAC_ADDRESS_2_LONG, DATA_SEQUENCE_NUM),
506                         buildReceivedDataInfo(
507                                 PEER_EXTENDED_MAC_ADDRESS_2_LONG, DATA_SEQUENCE_NUM_1)));
508         mUwbSessionManager.onRangeDataNotificationReceived(uwbRangingData1);
509         mUwbSessionManager.onRangeDataNotificationReceived(uwbRangingData2);
510 
511         verify(mUwbSessionNotificationManager)
512                 .onRangingResult(eq(mockUwbSession), eq(uwbRangingData1));
513         verify(mUwbSessionNotificationManager)
514                 .onRangingResult(eq(mockUwbSession), eq(uwbRangingData2));
515         verify(mUwbAdvertiseManager).updateAdvertiseTarget(uwbRangingData1.mRangingOwrAoaMeasure);
516         verify(mUwbAdvertiseManager).updateAdvertiseTarget(uwbRangingData2.mRangingOwrAoaMeasure);
517         verify(mUwbSessionNotificationManager, times(2))
518                 .onDataReceived(eq(mockUwbSession), eq(PEER_EXTENDED_UWB_ADDRESS),
519                         isA(PersistableBundle.class), eq(DATA_PAYLOAD));
520         verify(mUwbSessionNotificationManager, times(2))
521                 .onDataReceived(eq(mockUwbSession), eq(PEER_EXTENDED_UWB_ADDRESS_2),
522                         isA(PersistableBundle.class), eq(DATA_PAYLOAD));
523         verify(mUwbAdvertiseManager).removeAdvertiseTarget(PEER_EXTENDED_MAC_ADDRESS_LONG);
524         verify(mUwbAdvertiseManager).removeAdvertiseTarget(PEER_EXTENDED_MAC_ADDRESS_2_LONG);
525         verify(mUwbMetrics, times(2)).logDataToUpperLayer(eq(mockUwbSession), eq(2));
526     }
527 
528     @Test
onRangeDataNotificationReceived_owrAoa_CheckPointedTarget_Failed()529     public void onRangeDataNotificationReceived_owrAoa_CheckPointedTarget_Failed()
530             throws RemoteException {
531         UwbSession mockUwbSession = mock(UwbSession.class);
532         when(mockUwbSession.getWaitObj()).thenReturn(mock(WaitObj.class));
533         when(mockUwbSession.getRangingRoundUsage()).thenReturn(ROUND_USAGE_OWR_AOA_MEASUREMENT);
534         doReturn(mockUwbSession)
535                 .when(mUwbSessionManager).getUwbSession(eq(TEST_SESSION_ID));
536         UwbOemExtensionCallbackListener mUwbOemExtensionCallbackListener =
537                 mock(UwbOemExtensionCallbackListener.class);
538         when(mUwbServiceCore.isOemExtensionCbRegistered()).thenReturn(true);
539         when(mUwbServiceCore.getOemExtensionCallback())
540                 .thenReturn(mUwbOemExtensionCallbackListener);
541         when(mUwbOemExtensionCallbackListener.onCheckPointedTarget(any())).thenReturn(false);
542 
543         // First call onDataReceived() to get the application payload data. This should always have
544         // the MacAddress (in 8 Bytes), even for a Short MacAddress (MSB are zeroed out).
545         mUwbSessionManager.onDataReceived(TEST_SESSION_ID, UwbUciConstants.STATUS_CODE_OK,
546                 DATA_SEQUENCE_NUM, PEER_EXTENDED_SHORT_MAC_ADDRESS,
547                 SOURCE_END_POINT, DEST_END_POINT, DATA_PAYLOAD);
548 
549         // Next call onRangeDataNotificationReceived() to process the RANGE_DATA_NTF.
550         UwbRangingData uwbRangingData = UwbTestUtils.generateRangingData(
551                 RANGING_MEASUREMENT_TYPE_OWR_AOA, MAC_ADDRESSING_MODE_SHORT,
552                 UwbUciConstants.STATUS_CODE_OK);
553         Params firaParams = setupFiraParams(
554                 RANGING_DEVICE_ROLE_OBSERVER, Optional.of(ROUND_USAGE_OWR_AOA_MEASUREMENT));
555         when(mockUwbSession.getParams()).thenReturn(firaParams);
556         when(mUwbAdvertiseManager.isPointedTarget(PEER_SHORT_MAC_ADDRESS)).thenReturn(true);
557         mUwbSessionManager.onRangeDataNotificationReceived(uwbRangingData);
558 
559         verify(mUwbSessionNotificationManager)
560                 .onRangingResult(eq(mockUwbSession), eq(uwbRangingData));
561         verify(mUwbAdvertiseManager).updateAdvertiseTarget(uwbRangingData.mRangingOwrAoaMeasure);
562         verify(mUwbSessionNotificationManager, never())
563                 .onDataReceived(eq(mockUwbSession), eq(PEER_SHORT_UWB_ADDRESS),
564                         isA(PersistableBundle.class), eq(DATA_PAYLOAD));
565         verify(mUwbAdvertiseManager, never()).removeAdvertiseTarget(PEER_SHORT_MAC_ADDRESS_LONG);
566     }
567 
568     @Test
onRangeDataNotificationReceived_owrAoa_missingUwbSession()569     public void onRangeDataNotificationReceived_owrAoa_missingUwbSession() {
570         UwbRangingData uwbRangingData = UwbTestUtils.generateRangingData(
571                 RANGING_MEASUREMENT_TYPE_OWR_AOA, MAC_ADDRESSING_MODE_EXTENDED,
572                 UwbUciConstants.STATUS_CODE_OK);
573 
574         // Setup the test scenario such that the UwbSession (from the RANGE_DATA_NTF) doesn't exist.
575         doReturn(null)
576                 .when(mUwbSessionManager).getUwbSession(eq(TEST_SESSION_ID));
577 
578         // First call onDataReceived() to get the application payload data.
579         mUwbSessionManager.onDataReceived(TEST_SESSION_ID, UwbUciConstants.STATUS_CODE_OK,
580                 DATA_SEQUENCE_NUM, PEER_EXTENDED_MAC_ADDRESS, SOURCE_END_POINT, DEST_END_POINT,
581                 DATA_PAYLOAD);
582 
583         // Next call onRangeDataNotificationReceived() to process the RANGE_DATA_NTF.
584         mUwbSessionManager.onRangeDataNotificationReceived(uwbRangingData);
585 
586         verifyZeroInteractions(mUwbAdvertiseManager, mUwbSessionNotificationManager, mUwbMetrics);
587     }
588 
589     @Test
onRangeDataNotificationReceived_incorrectRangingMeasureType()590     public void onRangeDataNotificationReceived_incorrectRangingMeasureType() {
591         UwbRangingData uwbRangingData = UwbTestUtils.generateRangingData(
592                 RANGING_MEASUREMENT_TYPE_UNDEFINED, MAC_ADDRESSING_MODE_EXTENDED,
593                 UwbUciConstants.STATUS_CODE_OK);
594         UwbSession mockUwbSession = mock(UwbSession.class);
595         when(mockUwbSession.getWaitObj()).thenReturn(mock(WaitObj.class));
596         when(mockUwbSession.getRangingRoundUsage()).thenReturn(ROUND_USAGE_OWR_AOA_MEASUREMENT);
597         doReturn(mockUwbSession)
598                 .when(mUwbSessionManager).getUwbSession(eq(TEST_SESSION_ID));
599 
600         // First call onDataReceived() to get the application payload data.
601         mUwbSessionManager.onDataReceived(TEST_SESSION_ID, UwbUciConstants.STATUS_CODE_OK,
602                 DATA_SEQUENCE_NUM, PEER_EXTENDED_MAC_ADDRESS, SOURCE_END_POINT, DEST_END_POINT,
603                 DATA_PAYLOAD);
604         verify(mockUwbSession).addReceivedDataInfo(isA(UwbSessionManager.ReceivedDataInfo.class));
605         verify(mUwbMetrics).logDataRx(eq(mockUwbSession), eq(UwbUciConstants.STATUS_CODE_OK));
606 
607         // Next call onRangeDataNotificationReceived() to process the RANGE_DATA_NTF.
608         mUwbSessionManager.onRangeDataNotificationReceived(uwbRangingData);
609 
610         verify(mUwbSessionNotificationManager)
611                 .onRangingResult(eq(mockUwbSession), eq(uwbRangingData));
612         verifyZeroInteractions(mUwbAdvertiseManager);
613     }
614 
615     @Test
onRangeDataNotificationReceived_owrAoa_incorrectRangingRoundUsage()616     public void onRangeDataNotificationReceived_owrAoa_incorrectRangingRoundUsage() {
617         UwbRangingData uwbRangingData = UwbTestUtils.generateRangingData(
618                 RANGING_MEASUREMENT_TYPE_OWR_AOA, MAC_ADDRESSING_MODE_EXTENDED,
619                 UwbUciConstants.STATUS_CODE_OK);
620         UwbSession mockUwbSession = mock(UwbSession.class);
621         when(mockUwbSession.getWaitObj()).thenReturn(mock(WaitObj.class));
622         when(mockUwbSession.getRangingRoundUsage()).thenReturn(ROUND_USAGE_OWR_AOA_MEASUREMENT);
623         doReturn(mockUwbSession)
624                 .when(mUwbSessionManager).getUwbSession(eq(TEST_SESSION_ID));
625 
626         // First call onDataReceived() to get the application payload data.
627         mUwbSessionManager.onDataReceived(TEST_SESSION_ID, UwbUciConstants.STATUS_CODE_OK,
628                 DATA_SEQUENCE_NUM, PEER_EXTENDED_MAC_ADDRESS, SOURCE_END_POINT, DEST_END_POINT,
629                 DATA_PAYLOAD);
630         verify(mockUwbSession).addReceivedDataInfo(isA(UwbSessionManager.ReceivedDataInfo.class));
631         verify(mUwbMetrics).logDataRx(eq(mockUwbSession), eq(UwbUciConstants.STATUS_CODE_OK));
632 
633         // Next call onRangeDataNotificationReceived() to process the RANGE_DATA_NTF (with an
634         // incorrect RangingRoundUsage value).
635         Params firaParams = setupFiraParams(
636                 RANGING_DEVICE_ROLE_OBSERVER, Optional.of(ROUND_USAGE_DS_TWR_DEFERRED_MODE));
637         when(mockUwbSession.getParams()).thenReturn(firaParams);
638         mUwbSessionManager.onRangeDataNotificationReceived(uwbRangingData);
639 
640         verify(mUwbSessionNotificationManager)
641                 .onRangingResult(eq(mockUwbSession), eq(uwbRangingData));
642         verifyZeroInteractions(mUwbAdvertiseManager);
643     }
644 
645     @Test
onRangeDataNotificationReceived_owrAoa_incorrectDeviceRole()646     public void onRangeDataNotificationReceived_owrAoa_incorrectDeviceRole() {
647         UwbRangingData uwbRangingData = UwbTestUtils.generateRangingData(
648                 RANGING_MEASUREMENT_TYPE_OWR_AOA, MAC_ADDRESSING_MODE_EXTENDED,
649                 UwbUciConstants.STATUS_CODE_OK);
650         UwbSession mockUwbSession = mock(UwbSession.class);
651         when(mockUwbSession.getWaitObj()).thenReturn(mock(WaitObj.class));
652         when(mockUwbSession.getRangingRoundUsage()).thenReturn(ROUND_USAGE_OWR_AOA_MEASUREMENT);
653         doReturn(mockUwbSession)
654                 .when(mUwbSessionManager).getUwbSession(eq(TEST_SESSION_ID));
655 
656         // First call onDataReceived() to get the application payload data.
657         mUwbSessionManager.onDataReceived(TEST_SESSION_ID, UwbUciConstants.STATUS_CODE_OK,
658                 DATA_SEQUENCE_NUM, PEER_EXTENDED_MAC_ADDRESS, SOURCE_END_POINT, DEST_END_POINT,
659                 DATA_PAYLOAD);
660         verify(mockUwbSession).addReceivedDataInfo(isA(UwbSessionManager.ReceivedDataInfo.class));
661         verify(mUwbMetrics).logDataRx(eq(mockUwbSession), eq(UwbUciConstants.STATUS_CODE_OK));
662 
663         // Next call onRangeDataNotificationReceived() to process the RANGE_DATA_NTF.
664         Params firaParams = setupFiraParams(
665                 RANGING_DEVICE_ROLE_ADVERTISER, Optional.of(ROUND_USAGE_OWR_AOA_MEASUREMENT));
666         when(mockUwbSession.getParams()).thenReturn(firaParams);
667         mUwbSessionManager.onRangeDataNotificationReceived(uwbRangingData);
668 
669         verify(mUwbSessionNotificationManager)
670                 .onRangingResult(eq(mockUwbSession), eq(uwbRangingData));
671         verifyZeroInteractions(mUwbAdvertiseManager);
672     }
673 
674     @Test
onRangeDataNotificationReceived_owrAoa_receivedDataNotCalled()675     public void onRangeDataNotificationReceived_owrAoa_receivedDataNotCalled() {
676         UwbRangingData uwbRangingData = UwbTestUtils.generateRangingData(
677                 RANGING_MEASUREMENT_TYPE_OWR_AOA, MAC_ADDRESSING_MODE_EXTENDED,
678                 UwbUciConstants.STATUS_CODE_OK);
679         UwbSession mockUwbSession = mock(UwbSession.class);
680         when(mockUwbSession.getWaitObj()).thenReturn(mock(WaitObj.class));
681         when(mockUwbSession.getRangingRoundUsage()).thenReturn(ROUND_USAGE_OWR_AOA_MEASUREMENT);
682         doReturn(mockUwbSession)
683                 .when(mUwbSessionManager).getUwbSession(eq(TEST_SESSION_ID));
684 
685         // Skip call to mUwbSessionManager.onDataReceived(). This means there is no application
686         // payload data, and so mUwbSessionNotificationManager.onDataReceived() shouldn't be called.
687         Params firaParams = setupFiraParams(
688                 RANGING_DEVICE_ROLE_OBSERVER, Optional.of(ROUND_USAGE_OWR_AOA_MEASUREMENT));
689         when(mockUwbSession.getParams()).thenReturn(firaParams);
690         when(mUwbAdvertiseManager.isPointedTarget(PEER_EXTENDED_MAC_ADDRESS)).thenReturn(true);
691         when(mockUwbSession.getAllReceivedDataInfo(PEER_EXTENDED_MAC_ADDRESS_LONG))
692                 .thenReturn(List.of());
693         mUwbSessionManager.onRangeDataNotificationReceived(uwbRangingData);
694 
695         verify(mUwbSessionNotificationManager)
696                 .onRangingResult(eq(mockUwbSession), eq(uwbRangingData));
697         verify(mUwbAdvertiseManager).updateAdvertiseTarget(uwbRangingData.mRangingOwrAoaMeasure);
698         verifyZeroInteractions(mUwbSessionNotificationManager);
699         verify(mUwbMetrics, never()).logDataToUpperLayer(eq(mockUwbSession), anyInt());
700     }
701 
702     @Test
onRangeDataNotificationReceived_owrAoa_receivedDataDifferentMacAddress()703     public void onRangeDataNotificationReceived_owrAoa_receivedDataDifferentMacAddress() {
704         UwbRangingData uwbRangingData = UwbTestUtils.generateRangingData(
705                 RANGING_MEASUREMENT_TYPE_OWR_AOA, 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         // onDataReceived() called for a different MacAddress, which should be equivalent to it
714         // not being called.
715         mUwbSessionManager.onDataReceived(TEST_SESSION_ID, UwbUciConstants.STATUS_CODE_OK,
716                 DATA_SEQUENCE_NUM, PEER_EXTENDED_MAC_ADDRESS_2, SOURCE_END_POINT, DEST_END_POINT,
717                 DATA_PAYLOAD);
718         verify(mockUwbSession).addReceivedDataInfo(isA(UwbSessionManager.ReceivedDataInfo.class));
719         verify(mUwbMetrics).logDataRx(eq(mockUwbSession), eq(UwbUciConstants.STATUS_CODE_OK));
720 
721         // Next call onRangeDataNotificationReceived() to process the RANGE_DATA_NTF.
722         Params firaParams = setupFiraParams(
723                 RANGING_DEVICE_ROLE_OBSERVER, Optional.of(ROUND_USAGE_OWR_AOA_MEASUREMENT));
724         when(mockUwbSession.getParams()).thenReturn(firaParams);
725         when(mUwbAdvertiseManager.isPointedTarget(PEER_EXTENDED_MAC_ADDRESS)).thenReturn(true);
726         when(mockUwbSession.getAllReceivedDataInfo(PEER_EXTENDED_MAC_ADDRESS_LONG))
727                 .thenReturn(List.of());
728         mUwbSessionManager.onRangeDataNotificationReceived(uwbRangingData);
729 
730         verify(mUwbSessionNotificationManager)
731                 .onRangingResult(eq(mockUwbSession), eq(uwbRangingData));
732         verify(mUwbAdvertiseManager).updateAdvertiseTarget(uwbRangingData.mRangingOwrAoaMeasure);
733         verifyZeroInteractions(mUwbSessionNotificationManager);
734         verify(mUwbMetrics, never()).logDataToUpperLayer(eq(mockUwbSession), anyInt());
735     }
736 
737     @Test
onRangeDataNotificationReceived_owrAoa_receivedDataDifferentUwbSession()738     public void onRangeDataNotificationReceived_owrAoa_receivedDataDifferentUwbSession() {
739         UwbRangingData uwbRangingData = UwbTestUtils.generateRangingData(
740                 RANGING_MEASUREMENT_TYPE_OWR_AOA, MAC_ADDRESSING_MODE_EXTENDED,
741                 UwbUciConstants.STATUS_CODE_OK);
742         UwbSession mockUwbSession = mock(UwbSession.class);
743         when(mockUwbSession.getWaitObj()).thenReturn(mock(WaitObj.class));
744         when(mockUwbSession.getRangingRoundUsage()).thenReturn(ROUND_USAGE_OWR_AOA_MEASUREMENT);
745         doReturn(mockUwbSession)
746                 .when(mUwbSessionManager).getUwbSession(eq(TEST_SESSION_ID));
747         UwbSession mockUwbSession2 = mock(UwbSession.class);
748         when(mockUwbSession2.getWaitObj()).thenReturn(mock(WaitObj.class));
749         when(mockUwbSession2.getRangingRoundUsage()).thenReturn(ROUND_USAGE_OWR_AOA_MEASUREMENT);
750         doReturn(mockUwbSession2)
751                 .when(mUwbSessionManager).getUwbSession(eq(TEST_SESSION_ID_2));
752 
753         // onDataReceived() called for a different UwbSessionID, which should be equivalent to it
754         // not being called.
755         mUwbSessionManager.onDataReceived(TEST_SESSION_ID_2, UwbUciConstants.STATUS_CODE_OK,
756                 DATA_SEQUENCE_NUM, PEER_EXTENDED_MAC_ADDRESS, SOURCE_END_POINT, DEST_END_POINT,
757                 DATA_PAYLOAD);
758         verify(mockUwbSession2).addReceivedDataInfo(isA(UwbSessionManager.ReceivedDataInfo.class));
759         verify(mUwbMetrics).logDataRx(eq(mockUwbSession2), eq(UwbUciConstants.STATUS_CODE_OK));
760 
761         // Next call onRangeDataNotificationReceived() to process the RANGE_DATA_NTF. Setup such
762         // that there is no ReceivedDataInfo returned for the UwbSession (to simulate the test
763         // scenario).
764         Params firaParams = setupFiraParams(
765                 RANGING_DEVICE_ROLE_OBSERVER, Optional.of(ROUND_USAGE_OWR_AOA_MEASUREMENT));
766         when(mockUwbSession.getParams()).thenReturn(firaParams);
767         when(mUwbAdvertiseManager.isPointedTarget(PEER_EXTENDED_MAC_ADDRESS)).thenReturn(true);
768         when(mockUwbSession.getAllReceivedDataInfo(PEER_EXTENDED_MAC_ADDRESS_LONG))
769                 .thenReturn(List.of());
770         mUwbSessionManager.onRangeDataNotificationReceived(uwbRangingData);
771 
772         verify(mUwbSessionNotificationManager)
773                 .onRangingResult(eq(mockUwbSession), eq(uwbRangingData));
774         verify(mUwbAdvertiseManager).updateAdvertiseTarget(uwbRangingData.mRangingOwrAoaMeasure);
775         verifyZeroInteractions(mUwbSessionNotificationManager);
776         verify(mUwbMetrics, never()).logDataToUpperLayer(eq(mockUwbSession), anyInt());
777     }
778 
779     @Test
onRangeDataNotificationReceived_owrAoa_notPointedTarget()780     public void onRangeDataNotificationReceived_owrAoa_notPointedTarget() {
781         UwbRangingData uwbRangingData = UwbTestUtils.generateRangingData(
782                 RANGING_MEASUREMENT_TYPE_OWR_AOA, MAC_ADDRESSING_MODE_EXTENDED,
783                 UwbUciConstants.STATUS_CODE_OK);
784         UwbSession mockUwbSession = mock(UwbSession.class);
785         when(mockUwbSession.getWaitObj()).thenReturn(mock(WaitObj.class));
786         when(mockUwbSession.getRangingRoundUsage()).thenReturn(ROUND_USAGE_OWR_AOA_MEASUREMENT);
787         doReturn(mockUwbSession)
788                 .when(mUwbSessionManager).getUwbSession(eq(TEST_SESSION_ID));
789 
790         mUwbSessionManager.onDataReceived(TEST_SESSION_ID, UwbUciConstants.STATUS_CODE_OK,
791                 DATA_SEQUENCE_NUM, PEER_EXTENDED_MAC_ADDRESS, SOURCE_END_POINT, DEST_END_POINT,
792                 DATA_PAYLOAD);
793         verify(mockUwbSession).addReceivedDataInfo(isA(UwbSessionManager.ReceivedDataInfo.class));
794         verify(mUwbMetrics).logDataRx(eq(mockUwbSession), eq(UwbUciConstants.STATUS_CODE_OK));
795 
796         // Setup isPointedTarget() to return false.
797         when(mUwbAdvertiseManager.isPointedTarget(PEER_EXTENDED_MAC_ADDRESS)).thenReturn(false);
798         mUwbSessionManager.onRangeDataNotificationReceived(uwbRangingData);
799 
800         verify(mUwbSessionNotificationManager)
801                 .onRangingResult(eq(mockUwbSession), eq(uwbRangingData));
802         verify(mUwbAdvertiseManager, never()).removeAdvertiseTarget(isA(Long.class));
803         verifyZeroInteractions(mUwbSessionNotificationManager);
804     }
805 
806     @Test
onMulticastListUpdateNotificationReceivedWithValidSession()807     public void onMulticastListUpdateNotificationReceivedWithValidSession() {
808         UwbMulticastListUpdateStatus mockUwbMulticastListUpdateStatus =
809                 mock(UwbMulticastListUpdateStatus.class);
810         UwbSession mockUwbSession = mock(UwbSession.class);
811         when(mockUwbSession.getWaitObj()).thenReturn(mock(WaitObj.class));
812         doReturn(mockUwbSession)
813                 .when(mUwbSessionManager).getUwbSession(anyInt());
814 
815         mUwbSessionManager.onMulticastListUpdateNotificationReceived(
816                 mockUwbMulticastListUpdateStatus);
817 
818         verify(mockUwbSession, times(2)).getWaitObj();
819         verify(mockUwbSession)
820                 .setMulticastListUpdateStatus(eq(mockUwbMulticastListUpdateStatus));
821     }
822 
823     @Test
onSessionStatusNotificationReceived_max_retry()824     public void onSessionStatusNotificationReceived_max_retry() {
825         UwbSession mockUwbSession = mock(UwbSession.class);
826         when(mockUwbSession.getSessionId()).thenReturn(TEST_SESSION_ID);
827         mUwbSessionManager.mSessionTable.put(mock(SessionHandle.class), mockUwbSession);
828         when(mockUwbSession.getWaitObj()).thenReturn(mock(WaitObj.class));
829         when(mockUwbSession.getSessionState()).thenReturn(UwbUciConstants.UWB_SESSION_STATE_ACTIVE);
830 
831         mUwbSessionManager.onSessionStatusNotificationReceived(
832                 TEST_SESSION_ID,
833                 UwbUciConstants.UWB_SESSION_STATE_IDLE,
834                 UwbUciConstants.REASON_MAX_RANGING_ROUND_RETRY_COUNT_REACHED);
835 
836         verify(mockUwbSession, times(2)).getWaitObj();
837         verify(mockUwbSession).setSessionState(eq(UwbUciConstants.UWB_SESSION_STATE_IDLE));
838         verify(mUwbSessionNotificationManager).onRangingStoppedWithUciReasonCode(
839                 eq(mockUwbSession),
840                 eq(UwbUciConstants.REASON_MAX_RANGING_ROUND_RETRY_COUNT_REACHED));
841     }
842 
843     @Test
onSessionStatusNotificationReceived_session_mgmt_cmds()844     public void onSessionStatusNotificationReceived_session_mgmt_cmds() {
845         UwbSession mockUwbSession = mock(UwbSession.class);
846         when(mockUwbSession.getSessionId()).thenReturn(TEST_SESSION_ID);
847         mUwbSessionManager.mSessionTable.put(mock(SessionHandle.class), mockUwbSession);
848         when(mockUwbSession.getWaitObj()).thenReturn(mock(WaitObj.class));
849         when(mockUwbSession.getSessionState()).thenReturn(UwbUciConstants.UWB_SESSION_STATE_ACTIVE);
850 
851         mUwbSessionManager.onSessionStatusNotificationReceived(
852                 TEST_SESSION_ID,
853                 UwbUciConstants.UWB_SESSION_STATE_IDLE,
854                 UwbUciConstants.REASON_STATE_CHANGE_WITH_SESSION_MANAGEMENT_COMMANDS);
855 
856         verify(mockUwbSession, times(2)).getWaitObj();
857         verify(mockUwbSession).setSessionState(eq(UwbUciConstants.UWB_SESSION_STATE_IDLE));
858         verify(mUwbSessionNotificationManager, never()).onRangingStoppedWithUciReasonCode(
859                 any(), anyInt());
860     }
861 
862     @Test
initSession_ExistedSession()863     public void initSession_ExistedSession() throws RemoteException {
864         IUwbRangingCallbacks mockRangingCallbacks = mock(IUwbRangingCallbacks.class);
865         doReturn(true).when(mUwbSessionManager).isExistedSession(anyInt());
866 
867         mUwbSessionManager.initSession(ATTRIBUTION_SOURCE, mock(SessionHandle.class),
868                 TEST_SESSION_ID, TEST_SESSION_TYPE, "any", mock(Params.class), mockRangingCallbacks,
869                 TEST_CHIP_ID);
870 
871         verify(mockRangingCallbacks).onRangingOpenFailed(
872                 any(), eq(RangingChangeReason.BAD_PARAMETERS), any());
873         assertThat(mTestLooper.nextMessage()).isNull();
874     }
875 
876     @Test
initFiraSession_maxSessionsExceeded()877     public void initFiraSession_maxSessionsExceeded() throws RemoteException {
878         doReturn(MAX_FIRA_SESSION_NUM).when(mUwbSessionManager).getFiraSessionCount();
879         doReturn(false).when(mUwbSessionManager).isExistedSession(anyInt());
880         IUwbRangingCallbacks mockRangingCallbacks = mock(IUwbRangingCallbacks.class);
881 
882         mUwbSessionManager.initSession(ATTRIBUTION_SOURCE, mock(SessionHandle.class),
883                 TEST_SESSION_ID, TEST_SESSION_TYPE, FiraParams.PROTOCOL_NAME, mock(Params.class),
884                 mockRangingCallbacks,
885                 TEST_CHIP_ID);
886 
887         verify(mockRangingCallbacks).onRangingOpenFailed(any(),
888                 eq(RangingChangeReason.MAX_SESSIONS_REACHED), any());
889         assertThat(mTestLooper.nextMessage()).isNull();
890     }
891 
892     @Test
initCccSession_maxSessionsExceeded()893     public void initCccSession_maxSessionsExceeded() throws RemoteException {
894         doReturn(MAX_CCC_SESSION_NUM).when(mUwbSessionManager).getCccSessionCount();
895         doReturn(false).when(mUwbSessionManager).isExistedSession(anyInt());
896         IUwbRangingCallbacks mockRangingCallbacks = mock(IUwbRangingCallbacks.class);
897 
898         mUwbSessionManager.initSession(ATTRIBUTION_SOURCE, mock(SessionHandle.class),
899                 TEST_SESSION_ID, TEST_SESSION_TYPE, CccParams.PROTOCOL_NAME, mock(Params.class),
900                 mockRangingCallbacks,
901                 TEST_CHIP_ID);
902 
903         verify(mockRangingCallbacks).onRangingOpenFailed(any(),
904                 eq(RangingChangeReason.MAX_SESSIONS_REACHED), any());
905         assertThat(mTestLooper.nextMessage()).isNull();
906     }
907 
908     @Test
initSession_UwbSession_RemoteException()909     public void initSession_UwbSession_RemoteException() throws RemoteException {
910         doReturn(0).when(mUwbSessionManager).getSessionCount();
911         doReturn(0L).when(mUwbSessionManager).getCccSessionCount();
912         doReturn(0L).when(mUwbSessionManager).getFiraSessionCount();
913         doReturn(false).when(mUwbSessionManager).isExistedSession(anyInt());
914         IUwbRangingCallbacks mockRangingCallbacks = mock(IUwbRangingCallbacks.class);
915         SessionHandle mockSessionHandle = mock(SessionHandle.class);
916         Params mockParams = mock(FiraParams.class);
917         IBinder mockBinder = mock(IBinder.class);
918         UwbSession uwbSession = spy(
919                 mUwbSessionManager.new UwbSession(ATTRIBUTION_SOURCE, mockSessionHandle,
920                         TEST_SESSION_ID, TEST_SESSION_TYPE, FiraParams.PROTOCOL_NAME, mockParams,
921                         mockRangingCallbacks, TEST_CHIP_ID));
922         doReturn(mockBinder).when(uwbSession).getBinder();
923         doReturn(uwbSession).when(mUwbSessionManager).createUwbSession(any(), any(), anyInt(),
924                 anyByte(), anyString(), any(), any(), anyString());
925         doThrow(new RemoteException()).when(mockBinder).linkToDeath(any(), anyInt());
926 
927         mUwbSessionManager.initSession(ATTRIBUTION_SOURCE, mockSessionHandle, TEST_SESSION_ID,
928                 TEST_SESSION_TYPE, FiraParams.PROTOCOL_NAME, mockParams, mockRangingCallbacks,
929                 TEST_CHIP_ID);
930 
931         verify(uwbSession).binderDied();
932         verify(mockRangingCallbacks).onRangingOpenFailed(any(), anyInt(), any());
933         verify(mockBinder, atLeast(1)).unlinkToDeath(any(), anyInt());
934         assertThat(mTestLooper.nextMessage()).isNull();
935     }
936 
937     @Test
initSession_success()938     public void initSession_success() throws RemoteException {
939         doReturn(0).when(mUwbSessionManager).getSessionCount();
940         doReturn(0L).when(mUwbSessionManager).getCccSessionCount();
941         doReturn(0L).when(mUwbSessionManager).getFiraSessionCount();
942         doReturn(false).when(mUwbSessionManager).isExistedSession(anyInt());
943         IUwbRangingCallbacks mockRangingCallbacks = mock(IUwbRangingCallbacks.class);
944         SessionHandle mockSessionHandle = mock(SessionHandle.class);
945         Params mockParams = mock(FiraParams.class);
946         IBinder mockBinder = mock(IBinder.class);
947 
948         UwbSession uwbSession = spy(
949                 mUwbSessionManager.new UwbSession(ATTRIBUTION_SOURCE, mockSessionHandle,
950                         TEST_SESSION_ID, TEST_SESSION_TYPE, FiraParams.PROTOCOL_NAME, mockParams,
951                         mockRangingCallbacks, TEST_CHIP_ID));
952         doReturn(mockBinder).when(uwbSession).getBinder();
953         doReturn(uwbSession).when(mUwbSessionManager).createUwbSession(any(), any(), anyInt(),
954                 anyByte(), anyString(), any(), any(), anyString());
955 
956         mUwbSessionManager.initSession(ATTRIBUTION_SOURCE, mockSessionHandle, TEST_SESSION_ID,
957                 TEST_SESSION_TYPE, FiraParams.PROTOCOL_NAME, mockParams, mockRangingCallbacks,
958                 TEST_CHIP_ID);
959 
960         verify(uwbSession, never()).binderDied();
961         verify(mockRangingCallbacks, never()).onRangingOpenFailed(any(), anyInt(), any());
962         verify(mockBinder, never()).unlinkToDeath(any(), anyInt());
963         assertThat(mUwbSessionManager.getUwbSession(TEST_SESSION_ID)).isEqualTo(uwbSession);
964         assertThat(mTestLooper.nextMessage().what).isEqualTo(1); // SESSION_OPEN_RANGING
965     }
966 
967     @Test
initSessionMaxSessions_lowestPrioritySessionReplaced()968     public void initSessionMaxSessions_lowestPrioritySessionReplaced() throws RemoteException {
969         doReturn(false).when(mUwbInjector).isSystemApp(UID, PACKAGE_NAME);
970         doReturn(true).when(mUwbInjector).isSystemApp(UID_2, PACKAGE_NAME_2);
971         doReturn(1L).when(mUwbSessionManager).getMaxFiraSessionsNumber(TEST_CHIP_ID);
972         IUwbRangingCallbacks mockRangingCallbacks = mock(IUwbRangingCallbacks.class);
973         Params mockParams = mock(FiraParams.class);
974         IBinder mockBinder = mock(IBinder.class);
975 
976         when(mNativeUwbManager.initSession(anyInt(), anyByte(), anyString()))
977                 .thenReturn((byte) UwbUciConstants.STATUS_CODE_OK);
978         when(mNativeUwbManager.deInitSession(anyInt(), anyString()))
979                 .thenReturn((byte) UwbUciConstants.STATUS_CODE_OK);
980         when(mUwbConfigurationManager.setAppConfigurations(anyInt(), any(), anyString()))
981                 .thenReturn(UwbUciConstants.STATUS_CODE_OK);
982 
983         // Init session for 3rd party FG app
984         UwbSession lowPrioUwbSession = spy(
985                 mUwbSessionManager.new UwbSession(ATTRIBUTION_SOURCE, SESSION_HANDLE,
986                         TEST_SESSION_ID, TEST_SESSION_TYPE, FiraParams.PROTOCOL_NAME, mockParams,
987                         mockRangingCallbacks, TEST_CHIP_ID));
988         doReturn(lowPrioUwbSession).when(mUwbSessionManager).createUwbSession(any(), any(),
989                 anyInt(),
990                 anyByte(), anyString(), any(), any(), anyString());
991         doReturn(UwbUciConstants.UWB_SESSION_STATE_INIT,
992                 UwbUciConstants.UWB_SESSION_STATE_IDLE).when(lowPrioUwbSession).getSessionState();
993         doReturn(mock(WaitObj.class)).when(lowPrioUwbSession).getWaitObj();
994         doReturn(mockBinder).when(lowPrioUwbSession).getBinder();
995 
996         mUwbSessionManager.initSession(ATTRIBUTION_SOURCE, SESSION_HANDLE, TEST_SESSION_ID,
997                 TEST_SESSION_TYPE, FiraParams.PROTOCOL_NAME, mockParams, mockRangingCallbacks,
998                 TEST_CHIP_ID);
999 
1000         assertThat(mUwbSessionManager.getUwbSession(TEST_SESSION_ID)).isEqualTo(lowPrioUwbSession);
1001         mTestLooper.dispatchNext();
1002 
1003         // Init session for system app
1004         UwbSession highPrioUwbSession = spy(
1005                 mUwbSessionManager.new UwbSession(ATTRIBUTION_SOURCE_2, SESSION_HANDLE_2,
1006                         TEST_SESSION_ID_2, TEST_SESSION_TYPE, FiraParams.PROTOCOL_NAME, mockParams,
1007                         mockRangingCallbacks, TEST_CHIP_ID));
1008         doReturn(mockBinder).when(highPrioUwbSession).getBinder();
1009         doReturn(mock(WaitObj.class)).when(highPrioUwbSession).getWaitObj();
1010         doReturn(UwbUciConstants.UWB_SESSION_STATE_INIT,
1011                 UwbUciConstants.UWB_SESSION_STATE_IDLE).when(highPrioUwbSession).getSessionState();
1012         doReturn(highPrioUwbSession).when(mUwbSessionManager).createUwbSession(any(), any(),
1013                 anyInt(),
1014                 anyByte(), anyString(), any(), any(), anyString());
1015         mUwbSessionManager.initSession(ATTRIBUTION_SOURCE_2, SESSION_HANDLE_2, TEST_SESSION_ID_2,
1016                 TEST_SESSION_TYPE, FiraParams.PROTOCOL_NAME, mockParams, mockRangingCallbacks,
1017                 TEST_CHIP_ID);
1018         mTestLooper.dispatchAll();
1019 
1020         verify(mNativeUwbManager).initSession(TEST_SESSION_ID, TEST_SESSION_TYPE, TEST_CHIP_ID);
1021         verify(mNativeUwbManager).deInitSession(TEST_SESSION_ID, TEST_CHIP_ID);
1022         verify(mNativeUwbManager).initSession(TEST_SESSION_ID_2, TEST_SESSION_TYPE, TEST_CHIP_ID);
1023         verify(mockRangingCallbacks, never()).onRangingOpenFailed(any(), anyInt(), any());
1024         verify(mUwbSessionNotificationManager).onRangingOpened(lowPrioUwbSession);
1025         verify(mUwbSessionNotificationManager).onRangingClosed(lowPrioUwbSession,
1026                 UwbUciConstants.STATUS_CODE_ERROR_MAX_SESSIONS_EXCEEDED);
1027         verify(mUwbSessionNotificationManager).onRangingOpened(highPrioUwbSession);
1028         assertThat(mUwbSessionManager.getUwbSession(TEST_SESSION_ID)).isNull();
1029         assertThat(mUwbSessionManager.getUwbSession(TEST_SESSION_ID_2)).isEqualTo(
1030                 highPrioUwbSession);
1031     }
1032 
1033     @Test
testNeedsAppConfigUpdate_setAppConfigCalledOnStartRanging()1034     public void testNeedsAppConfigUpdate_setAppConfigCalledOnStartRanging() throws RemoteException {
1035         UwbSession mockUwbSession = mock(UwbSession.class);
1036 
1037         doReturn(true).when(mUwbSessionManager).isExistedSession(any());
1038         doReturn(TEST_SESSION_ID).when(mUwbSessionManager).getSessionId(any());
1039         doReturn(mockUwbSession).when(mUwbSessionManager).getUwbSession(anyInt());
1040         doReturn(UwbUciConstants.UWB_SESSION_STATE_IDLE)
1041                 .when(mUwbSessionManager).getCurrentSessionState(anyInt());
1042         doReturn(PROTOCOL_NAME).when(mockUwbSession).getProtocolName();
1043         doReturn(mock(WaitObj.class)).when(mockUwbSession).getWaitObj();
1044         when(mockUwbSession.getNeedsAppConfigUpdate()).thenReturn(true);
1045 
1046         mUwbSessionManager.startRanging(mock(SessionHandle.class), mock(Params.class));
1047         mTestLooper.dispatchAll();
1048 
1049         verify(mUwbConfigurationManager).setAppConfigurations(anyInt(), any(),
1050                 any());
1051     }
1052 
1053     @Test
testCreateUwbSession_correctSessionPrioritiesSet()1054     public void testCreateUwbSession_correctSessionPrioritiesSet() throws RemoteException {
1055         IUwbRangingCallbacks mockRangingCallbacks = mock(IUwbRangingCallbacks.class);
1056         SessionHandle mockSessionHandle = mock(SessionHandle.class);
1057         FiraOpenSessionParams mockFiraOpenSessionParams = mock(FiraOpenSessionParams.class);
1058         Params mockCccParams = mock(CccParams.class);
1059         FiraOpenSessionParams.Builder mockFiraBuilder = mock(FiraOpenSessionParams.Builder.class);
1060 
1061         when(mockFiraOpenSessionParams.toBuilder()).thenReturn(mockFiraBuilder);
1062         when(mockFiraBuilder.setSessionPriority(anyInt())).thenReturn(mockFiraBuilder);
1063         when(mockFiraBuilder.build()).thenReturn(mockFiraOpenSessionParams);
1064         when(mockFiraOpenSessionParams.getSessionPriority()).thenReturn(
1065                 UwbSession.DEFAULT_SESSION_PRIORITY);
1066 
1067         // System session
1068         String systemPackageName = "com.google.uwb";
1069         when(mUwbInjector.isSystemApp(UID, systemPackageName)).thenReturn(true);
1070         AttributionSource attributionSourceSystemApp =
1071                 new AttributionSource.Builder(UID).setPackageName(systemPackageName).build();
1072         UwbSession systemUwbSession =
1073                 mUwbSessionManager.new UwbSession(attributionSourceSystemApp, mockSessionHandle,
1074                         TEST_SESSION_ID, TEST_SESSION_TYPE, FiraParams.PROTOCOL_NAME,
1075                         mockFiraOpenSessionParams,
1076                         mockRangingCallbacks, TEST_CHIP_ID);
1077 
1078         assertThat(systemUwbSession.getStackSessionPriority()).isEqualTo(
1079                 UwbSession.SYSTEM_APP_SESSION_PRIORITY);
1080         verify(mockFiraBuilder).setSessionPriority(UwbSession.SYSTEM_APP_SESSION_PRIORITY);
1081 
1082         // CCC session
1083         UwbSession cccUwbSession =
1084                 mUwbSessionManager.new UwbSession(attributionSourceSystemApp, mockSessionHandle,
1085                         TEST_SESSION_ID, TEST_SESSION_TYPE, CccParams.PROTOCOL_NAME, mockCccParams,
1086                         mockRangingCallbacks, TEST_CHIP_ID);
1087 
1088         assertThat(cccUwbSession.getStackSessionPriority()).isEqualTo(
1089                 UwbSession.CCC_SESSION_PRIORITY);
1090 
1091         // 3rd party foreground session
1092         String nonSystemPackageName = "com.something.app";
1093         when(mUwbInjector.isForegroundAppOrService(UID, nonSystemPackageName))
1094                 .thenReturn(true);
1095         AttributionSource attributionSourceNonSystemApp =
1096                 new AttributionSource.Builder(UID).setPackageName(nonSystemPackageName).build();
1097         UwbSession nonSystemFgUwbSession =
1098                 mUwbSessionManager.new UwbSession(attributionSourceNonSystemApp, mockSessionHandle,
1099                         TEST_SESSION_ID, TEST_SESSION_TYPE, FiraParams.PROTOCOL_NAME,
1100                         mockFiraOpenSessionParams,
1101                         mockRangingCallbacks, TEST_CHIP_ID);
1102 
1103         assertThat(nonSystemFgUwbSession.getStackSessionPriority()).isEqualTo(
1104                 UwbSession.FG_SESSION_PRIORITY);
1105         verify(mockFiraBuilder).setSessionPriority(UwbSession.FG_SESSION_PRIORITY);
1106 
1107 
1108         // 3rd party background session
1109         when(mUwbInjector.isForegroundAppOrService(UID, nonSystemPackageName))
1110                 .thenReturn(false);
1111         UwbSession nonSystemBgUwbSession =
1112                 mUwbSessionManager.new UwbSession(attributionSourceNonSystemApp, mockSessionHandle,
1113                         TEST_SESSION_ID, TEST_SESSION_TYPE, FiraParams.PROTOCOL_NAME,
1114                         mockFiraOpenSessionParams,
1115                         mockRangingCallbacks, TEST_CHIP_ID);
1116 
1117         assertThat(nonSystemBgUwbSession.getStackSessionPriority()).isEqualTo(
1118                 UwbSession.BG_SESSION_PRIORITY);
1119         verify(mockFiraBuilder).setSessionPriority(UwbSession.BG_SESSION_PRIORITY);
1120 
1121     }
1122 
1123     @Test
initSession_controleeList()1124     public void initSession_controleeList() throws RemoteException {
1125         doReturn(0).when(mUwbSessionManager).getSessionCount();
1126         doReturn(0L).when(mUwbSessionManager).getCccSessionCount();
1127         doReturn(0L).when(mUwbSessionManager).getFiraSessionCount();
1128         doReturn(false).when(mUwbSessionManager).isExistedSession(anyInt());
1129         IUwbRangingCallbacks mockRangingCallbacks = mock(IUwbRangingCallbacks.class);
1130         SessionHandle mockSessionHandle = mock(SessionHandle.class);
1131         FiraOpenSessionParams mockParams = mock(FiraOpenSessionParams.class);
1132         FiraOpenSessionParams.Builder mockBuilder = mock(FiraOpenSessionParams.Builder.class);
1133         IBinder mockBinder = mock(IBinder.class);
1134 
1135         when(mockParams.getDestAddressList())
1136                 .thenReturn(Collections.singletonList(UWB_DEST_ADDRESS));
1137         when(mockParams.toBuilder()).thenReturn(mockBuilder);
1138         when(mockBuilder.setSessionPriority(anyInt())).thenReturn(mockBuilder);
1139         when(mockBuilder.build()).thenReturn(mockParams);
1140 
1141         UwbSession uwbSession = spy(
1142                 mUwbSessionManager.new UwbSession(ATTRIBUTION_SOURCE, mockSessionHandle,
1143                         TEST_SESSION_ID, TEST_SESSION_TYPE, FiraParams.PROTOCOL_NAME, mockParams,
1144                         mockRangingCallbacks, TEST_CHIP_ID));
1145         doReturn(mockBinder).when(uwbSession).getBinder();
1146         doReturn(uwbSession).when(mUwbSessionManager).createUwbSession(any(), any(), anyInt(),
1147                 anyByte(), anyString(), any(), any(), anyString());
1148 
1149         mUwbSessionManager.initSession(ATTRIBUTION_SOURCE, mockSessionHandle, TEST_SESSION_ID,
1150                 TEST_SESSION_TYPE, FiraParams.PROTOCOL_NAME, mockParams, mockRangingCallbacks,
1151                 TEST_CHIP_ID);
1152 
1153         assertThat(uwbSession.getControleeList().size() == 1
1154                 && uwbSession.getControleeList().get(0).getUwbAddress().equals(UWB_DEST_ADDRESS))
1155                 .isTrue();
1156 
1157         assertThat(uwbSession.getControlee(UWB_DEST_ADDRESS)
1158                 .getUwbAddress().equals(UWB_DEST_ADDRESS)).isTrue();
1159 
1160         verify(uwbSession, never()).binderDied();
1161         verify(mockRangingCallbacks, never()).onRangingOpenFailed(any(), anyInt(), any());
1162         verify(mockBinder, never()).unlinkToDeath(any(), anyInt());
1163         assertThat(mUwbSessionManager.getUwbSession(TEST_SESSION_ID)).isEqualTo(uwbSession);
1164         assertThat(mTestLooper.nextMessage().what).isEqualTo(1); // SESSION_OPEN_RANGING
1165     }
1166 
1167     @Test
startRanging_notExistedSession()1168     public void startRanging_notExistedSession() {
1169         doReturn(false).when(mUwbSessionManager).isExistedSession(any());
1170         doReturn(TEST_SESSION_ID).when(mUwbSessionManager).getSessionId(any());
1171         doReturn(mock(UwbSession.class)).when(mUwbSessionManager).getUwbSession(anyInt());
1172         doReturn(UwbUciConstants.UWB_SESSION_STATE_IDLE)
1173                 .when(mUwbSessionManager).getCurrentSessionState(anyInt());
1174 
1175         mUwbSessionManager.startRanging(mock(SessionHandle.class), mock(Params.class));
1176 
1177         assertThat(mTestLooper.nextMessage()).isNull();
1178     }
1179 
1180     @Test
startRanging_currentSessionStateIdle()1181     public void startRanging_currentSessionStateIdle() {
1182         doReturn(true).when(mUwbSessionManager).isExistedSession(any());
1183         doReturn(TEST_SESSION_ID).when(mUwbSessionManager).getSessionId(any());
1184         UwbSession uwbSession = mock(UwbSession.class);
1185         when(uwbSession.getProtocolName()).thenReturn(FiraParams.PROTOCOL_NAME);
1186         doReturn(uwbSession).when(mUwbSessionManager).getUwbSession(anyInt());
1187         doReturn(UwbUciConstants.UWB_SESSION_STATE_IDLE)
1188                 .when(mUwbSessionManager).getCurrentSessionState(anyInt());
1189 
1190         mUwbSessionManager.startRanging(mock(SessionHandle.class), mock(Params.class));
1191 
1192         assertThat(mTestLooper.nextMessage().what).isEqualTo(2); // SESSION_START_RANGING
1193     }
1194 
1195     @Test
startRanging_currentSessionStateActive()1196     public void startRanging_currentSessionStateActive() {
1197         doReturn(true).when(mUwbSessionManager).isExistedSession(any());
1198         doReturn(TEST_SESSION_ID).when(mUwbSessionManager).getSessionId(any());
1199         UwbSession mockUwbSession = mock(UwbSession.class);
1200         doReturn(mockUwbSession).when(mUwbSessionManager).getUwbSession(anyInt());
1201         when(mockUwbSession.getProtocolName()).thenReturn(CccParams.PROTOCOL_NAME);
1202         doReturn(UwbUciConstants.UWB_SESSION_STATE_ACTIVE)
1203                 .when(mUwbSessionManager).getCurrentSessionState(anyInt());
1204 
1205         mUwbSessionManager.startRanging(mock(SessionHandle.class), mock(Params.class));
1206 
1207         verify(mUwbSessionNotificationManager).onRangingStartFailed(
1208                 any(), eq(UwbUciConstants.STATUS_CODE_REJECTED));
1209     }
1210 
1211     @Test
startRanging_currentSessiionStateInvalid()1212     public void startRanging_currentSessiionStateInvalid() {
1213         doReturn(true).when(mUwbSessionManager).isExistedSession(any());
1214         doReturn(TEST_SESSION_ID).when(mUwbSessionManager).getSessionId(any());
1215         doReturn(mock(UwbSession.class)).when(mUwbSessionManager).getUwbSession(anyInt());
1216         doReturn(UwbUciConstants.UWB_SESSION_STATE_ERROR)
1217                 .when(mUwbSessionManager).getCurrentSessionState(anyInt());
1218 
1219         mUwbSessionManager.startRanging(mock(SessionHandle.class), mock(Params.class));
1220 
1221         verify(mUwbSessionNotificationManager)
1222                 .onRangingStartFailed(any(), eq(UwbUciConstants.STATUS_CODE_FAILED));
1223     }
1224 
1225     @Test
stopRanging_notExistedSession()1226     public void stopRanging_notExistedSession() {
1227         doReturn(false).when(mUwbSessionManager).isExistedSession(any());
1228         doReturn(TEST_SESSION_ID).when(mUwbSessionManager).getSessionId(any());
1229         doReturn(mock(UwbSession.class)).when(mUwbSessionManager).getUwbSession(anyInt());
1230         doReturn(UwbUciConstants.UWB_SESSION_STATE_ACTIVE)
1231                 .when(mUwbSessionManager).getCurrentSessionState(anyInt());
1232 
1233         mUwbSessionManager.stopRanging(mock(SessionHandle.class));
1234 
1235         assertThat(mTestLooper.nextMessage()).isNull();
1236     }
1237 
1238     @Test
stopRanging_currentSessionStateActive()1239     public void stopRanging_currentSessionStateActive() {
1240         doReturn(true).when(mUwbSessionManager).isExistedSession(any());
1241         doReturn(TEST_SESSION_ID).when(mUwbSessionManager).getSessionId(any());
1242         doReturn(mock(UwbSession.class)).when(mUwbSessionManager).getUwbSession(anyInt());
1243         doReturn(UwbUciConstants.UWB_SESSION_STATE_ACTIVE)
1244                 .when(mUwbSessionManager).getCurrentSessionState(anyInt());
1245 
1246         mUwbSessionManager.stopRanging(mock(SessionHandle.class));
1247 
1248         assertThat(mTestLooper.nextMessage().what).isEqualTo(3); // SESSION_STOP_RANGING
1249     }
1250 
1251     @Test
stopRanging_currentSessionStateActive_owrAoa()1252     public void stopRanging_currentSessionStateActive_owrAoa() {
1253         UwbSession mockUwbSession = mock(UwbSession.class);
1254 
1255         doReturn(true).when(mUwbSessionManager).isExistedSession(any());
1256         doReturn(TEST_SESSION_ID).when(mUwbSessionManager).getSessionId(any());
1257         doReturn(mockUwbSession).when(mUwbSessionManager).getUwbSession(anyInt());
1258         doReturn(UwbUciConstants.UWB_SESSION_STATE_ACTIVE)
1259                 .when(mUwbSessionManager).getCurrentSessionState(anyInt());
1260         when(mNativeUwbManager.stopRanging(eq(TEST_SESSION_ID), anyString()))
1261                 .thenReturn((byte) UwbUciConstants.STATUS_CODE_OK);
1262 
1263         doReturn(PROTOCOL_NAME).when(mockUwbSession).getProtocolName();
1264         doReturn(0).when(mockUwbSession).getCurrentFiraRangingIntervalMs();
1265 
1266         // Setup the UwbSession to have the peer device's MacAddress stored (which happens when
1267         // a valid RANGE_DATA_NTF with an OWR AoA Measurement is received).
1268         doReturn(Set.of(PEER_EXTENDED_MAC_ADDRESS_LONG)).when(mockUwbSession)
1269                 .getRemoteMacAddressList();
1270 
1271         mUwbSessionManager.stopRanging(mock(SessionHandle.class));
1272         mTestLooper.dispatchNext();
1273 
1274         verify(mUwbAdvertiseManager).removeAdvertiseTarget(PEER_EXTENDED_MAC_ADDRESS_LONG);
1275     }
1276 
1277     @Test
stopRanging_currentSessionStateIdle()1278     public void stopRanging_currentSessionStateIdle() {
1279         doReturn(true).when(mUwbSessionManager).isExistedSession(any());
1280         doReturn(TEST_SESSION_ID).when(mUwbSessionManager).getSessionId(any());
1281         doReturn(mock(UwbSession.class)).when(mUwbSessionManager).getUwbSession(anyInt());
1282         doReturn(UwbUciConstants.UWB_SESSION_STATE_IDLE)
1283                 .when(mUwbSessionManager).getCurrentSessionState(anyInt());
1284 
1285         mUwbSessionManager.stopRanging(mock(SessionHandle.class));
1286 
1287         verify(mUwbSessionNotificationManager).onRangingStopped(any(),
1288                 eq(UwbUciConstants.REASON_STATE_CHANGE_WITH_SESSION_MANAGEMENT_COMMANDS));
1289     }
1290 
1291     @Test
stopRanging_currentSessionStateInvalid()1292     public void stopRanging_currentSessionStateInvalid() {
1293         doReturn(true).when(mUwbSessionManager).isExistedSession(any());
1294         doReturn(TEST_SESSION_ID).when(mUwbSessionManager).getSessionId(any());
1295         doReturn(mock(UwbSession.class)).when(mUwbSessionManager).getUwbSession(anyInt());
1296         doReturn(UwbUciConstants.UWB_SESSION_STATE_ERROR)
1297                 .when(mUwbSessionManager).getCurrentSessionState(anyInt());
1298 
1299         mUwbSessionManager.stopRanging(mock(SessionHandle.class));
1300 
1301         verify(mUwbSessionNotificationManager).onRangingStopFailed(any(),
1302                 eq(UwbUciConstants.STATUS_CODE_REJECTED));
1303     }
1304 
1305     @Test
getUwbSession_success()1306     public void getUwbSession_success() {
1307         UwbSession mockUwbSession = mock(UwbSession.class);
1308         when(mockUwbSession.getSessionId()).thenReturn(TEST_SESSION_ID);
1309         mUwbSessionManager.mSessionTable.put(mock(SessionHandle.class), mockUwbSession);
1310 
1311         UwbSession actualUwbSession = mUwbSessionManager.getUwbSession(TEST_SESSION_ID);
1312 
1313         assertThat(actualUwbSession).isEqualTo(mockUwbSession);
1314     }
1315 
1316     @Test
getUwbSession_failed()1317     public void getUwbSession_failed() {
1318         UwbSession mockUwbSession = mock(UwbSession.class);
1319         when(mockUwbSession.getSessionId()).thenReturn(TEST_SESSION_ID);
1320         mUwbSessionManager.mSessionTable.put(mock(SessionHandle.class), mockUwbSession);
1321 
1322         UwbSession actualUwbSession = mUwbSessionManager.getUwbSession(TEST_SESSION_ID - 1);
1323 
1324         assertThat(actualUwbSession).isNull();
1325     }
1326 
1327     @Test
getSessionId_success()1328     public void getSessionId_success() {
1329         UwbSession mockUwbSession = mock(UwbSession.class);
1330         when(mockUwbSession.getSessionId()).thenReturn(TEST_SESSION_ID);
1331         SessionHandle mockSessionHandle = mock(SessionHandle.class);
1332         mUwbSessionManager.mSessionTable.put(mockSessionHandle, mockUwbSession);
1333         when(mockUwbSession.getSessionHandle()).thenReturn(mockSessionHandle);
1334 
1335         int actualSessionId = mUwbSessionManager.getSessionId(mockSessionHandle);
1336 
1337         assertThat(actualSessionId).isEqualTo(TEST_SESSION_ID);
1338     }
1339 
1340     @Test
getSessionId_failed()1341     public void getSessionId_failed() {
1342         UwbSession mockUwbSession = mock(UwbSession.class);
1343         when(mockUwbSession.getSessionId()).thenReturn(TEST_SESSION_ID);
1344         SessionHandle mockSessionHandle = mock(SessionHandle.class);
1345         mUwbSessionManager.mSessionTable.put(mockSessionHandle, mockUwbSession);
1346         when(mockUwbSession.getSessionHandle()).thenReturn(mockSessionHandle);
1347 
1348         Integer actualSessionId = mUwbSessionManager.getSessionId(mock(SessionHandle.class));
1349 
1350         assertThat(actualSessionId).isNull();
1351     }
1352 
1353     @Test
isExistedSession_sessionHandle_success()1354     public void isExistedSession_sessionHandle_success() {
1355         doReturn(TEST_SESSION_ID).when(mUwbSessionManager).getSessionId(any());
1356 
1357         boolean result = mUwbSessionManager.isExistedSession(mock(SessionHandle.class));
1358 
1359         assertThat(result).isTrue();
1360     }
1361 
1362     @Test
iexExistedSession_sessionHandle_failed()1363     public void iexExistedSession_sessionHandle_failed() {
1364         doReturn(null).when(mUwbSessionManager).getSessionId(any());
1365 
1366         boolean result = mUwbSessionManager.isExistedSession(mock(SessionHandle.class));
1367 
1368         assertThat(result).isFalse();
1369     }
1370 
1371     @Test
isExistedSession_sessionId_success()1372     public void isExistedSession_sessionId_success() {
1373         UwbSession mockUwbSession = mock(UwbSession.class);
1374         when(mockUwbSession.getSessionId()).thenReturn(TEST_SESSION_ID);
1375         mUwbSessionManager.mSessionTable.put(mock(SessionHandle.class), mockUwbSession);
1376 
1377         boolean result = mUwbSessionManager.isExistedSession(TEST_SESSION_ID);
1378 
1379         assertThat(result).isTrue();
1380     }
1381 
1382     @Test
iexExistedSession_sessionId_failed()1383     public void iexExistedSession_sessionId_failed() {
1384         boolean result = mUwbSessionManager.isExistedSession(TEST_SESSION_ID);
1385 
1386         assertThat(result).isFalse();
1387     }
1388 
1389     @Test
stopAllRanging()1390     public void stopAllRanging() {
1391         UwbSession mockUwbSession1 = mock(UwbSession.class);
1392         when(mockUwbSession1.getSessionId()).thenReturn(TEST_SESSION_ID);
1393         when(mockUwbSession1.getChipId()).thenReturn(TEST_CHIP_ID);
1394         mUwbSessionManager.mSessionTable.put(mock(SessionHandle.class), mockUwbSession1);
1395 
1396         UwbSession mockUwbSession2 = mock(UwbSession.class);
1397         when(mockUwbSession2.getSessionId()).thenReturn(TEST_SESSION_ID + 100);
1398         when(mockUwbSession2.getChipId()).thenReturn(TEST_CHIP_ID);
1399         mUwbSessionManager.mSessionTable.put(mock(SessionHandle.class), mockUwbSession2);
1400 
1401         when(mNativeUwbManager.stopRanging(eq(TEST_SESSION_ID), anyString()))
1402                 .thenReturn((byte) UwbUciConstants.STATUS_CODE_FAILED);
1403         when(mNativeUwbManager.stopRanging(eq(TEST_SESSION_ID + 100), anyString()))
1404                 .thenReturn((byte) UwbUciConstants.STATUS_CODE_OK);
1405 
1406         mUwbSessionManager.stopAllRanging();
1407 
1408         verify(mNativeUwbManager, times(2))
1409                 .stopRanging(anyInt(), anyString());
1410         verify(mockUwbSession1, never()).setSessionState(anyInt());
1411         verify(mockUwbSession2).setSessionState(eq(UwbUciConstants.UWB_SESSION_STATE_IDLE));
1412     }
1413 
1414     @Test
setCurrentSessionState()1415     public void setCurrentSessionState() {
1416         UwbSession mockUwbSession = mock(UwbSession.class);
1417         when(mockUwbSession.getSessionId()).thenReturn(TEST_SESSION_ID);
1418         mUwbSessionManager.mSessionTable.put(mock(SessionHandle.class), mockUwbSession);
1419 
1420         mUwbSessionManager.setCurrentSessionState(
1421                 TEST_SESSION_ID, UwbUciConstants.UWB_SESSION_STATE_ACTIVE);
1422 
1423         verify(mockUwbSession).setSessionState(eq(UwbUciConstants.UWB_SESSION_STATE_ACTIVE));
1424     }
1425 
1426     @Test
getCurrentSessionState_nullSession()1427     public void getCurrentSessionState_nullSession() {
1428         int actualStatus = mUwbSessionManager.getCurrentSessionState(TEST_SESSION_ID);
1429 
1430         assertThat(actualStatus).isEqualTo(UwbUciConstants.UWB_SESSION_STATE_ERROR);
1431     }
1432 
1433     @Test
getCurrentSessionState_success()1434     public void getCurrentSessionState_success() {
1435         UwbSession mockUwbSession = mock(UwbSession.class);
1436         when(mockUwbSession.getSessionId()).thenReturn(TEST_SESSION_ID);
1437         when(mockUwbSession.getSessionState()).thenReturn(UwbUciConstants.UWB_SESSION_STATE_ACTIVE);
1438         mUwbSessionManager.mSessionTable.put(mock(SessionHandle.class), mockUwbSession);
1439 
1440         int actualStatus = mUwbSessionManager.getCurrentSessionState(TEST_SESSION_ID);
1441 
1442         assertThat(actualStatus).isEqualTo(UwbUciConstants.UWB_SESSION_STATE_ACTIVE);
1443     }
1444 
1445     @Test
getSessionIdSet()1446     public void getSessionIdSet() {
1447         UwbSession mockUwbSession = mock(UwbSession.class);
1448         when(mockUwbSession.getSessionId()).thenReturn(TEST_SESSION_ID);
1449         mUwbSessionManager.mSessionTable.put(mock(SessionHandle.class), mockUwbSession);
1450 
1451         Set<Integer> actualSessionIds = mUwbSessionManager.getSessionIdSet();
1452 
1453         assertThat(actualSessionIds).hasSize(1);
1454         assertThat(actualSessionIds.contains(TEST_SESSION_ID)).isTrue();
1455     }
1456 
1457     @Test
reconfigure_notExistedSession()1458     public void reconfigure_notExistedSession() {
1459         doReturn(false).when(mUwbSessionManager).isExistedSession(any());
1460 
1461         int actualStatus = mUwbSessionManager.reconfigure(
1462                 mock(SessionHandle.class), mock(Params.class));
1463 
1464         assertThat(actualStatus).isEqualTo(UwbUciConstants.STATUS_CODE_ERROR_SESSION_NOT_EXIST);
1465     }
1466 
setUpUwbSessionForExecution(AttributionSource attributionSource)1467     private UwbSession setUpUwbSessionForExecution(AttributionSource attributionSource) {
1468         return setUpUwbSessionForExecution(attributionSource, setupFiraParams());
1469     }
1470 
setUpUwbSessionForExecution(AttributionSource attributionSource, Params params)1471     private UwbSession setUpUwbSessionForExecution(AttributionSource attributionSource,
1472             Params params) {
1473         // setup message
1474         doReturn(0).when(mUwbSessionManager).getSessionCount();
1475         doReturn(0L).when(mUwbSessionManager).getFiraSessionCount();
1476         doReturn(false).when(mUwbSessionManager).isExistedSession(anyInt());
1477         IUwbRangingCallbacks mockRangingCallbacks = mock(IUwbRangingCallbacks.class);
1478         SessionHandle mockSessionHandle = mock(SessionHandle.class);
1479         IBinder mockBinder = mock(IBinder.class);
1480         UwbSession uwbSession = spy(
1481                 mUwbSessionManager.new UwbSession(attributionSource, mockSessionHandle,
1482                         TEST_SESSION_ID, TEST_SESSION_TYPE, FiraParams.PROTOCOL_NAME, params,
1483                         mockRangingCallbacks, TEST_CHIP_ID));
1484         doReturn(mockBinder).when(uwbSession).getBinder();
1485         doReturn(uwbSession).when(mUwbSessionManager).createUwbSession(any(), any(), anyInt(),
1486                 anyByte(), anyString(), any(), any(), anyString());
1487         doReturn(mock(WaitObj.class)).when(uwbSession).getWaitObj();
1488 
1489         return uwbSession;
1490     }
1491 
setupFiraParams()1492     private Params setupFiraParams() {
1493         return setupFiraParams(FiraParams.RANGING_DEVICE_ROLE_INITIATOR, Optional.empty());
1494     }
1495 
setupFiraParams(int deviceRole, Optional<Integer> rangingRoundUsageOptional)1496     private Params setupFiraParams(int deviceRole, Optional<Integer> rangingRoundUsageOptional) {
1497         FiraOpenSessionParams.Builder paramsBuilder = new FiraOpenSessionParams.Builder()
1498                 .setDeviceAddress(UwbAddress.fromBytes(new byte[] {(byte) 0x01, (byte) 0x02 }))
1499                 .setVendorId(new byte[] { (byte) 0x00, (byte) 0x01 })
1500                 .setStaticStsIV(new byte[] { (byte) 0x01, (byte) 0x02, (byte) 0x03,
1501                         (byte) 0x04, (byte) 0x05, (byte) 0x06 })
1502                 .setDestAddressList(Arrays.asList(
1503                         UWB_DEST_ADDRESS))
1504                 .setProtocolVersion(new FiraProtocolVersion(1, 0))
1505                 .setSessionId(10)
1506                 .setSessionType(SESSION_TYPE_RANGING)
1507                 .setDeviceType(FiraParams.RANGING_DEVICE_TYPE_CONTROLLER)
1508                 .setDeviceRole(deviceRole)
1509                 .setMultiNodeMode(FiraParams.MULTI_NODE_MODE_UNICAST)
1510                 .setRangingIntervalMs(TEST_RANGING_INTERVAL_MS);
1511 
1512         if (rangingRoundUsageOptional.isPresent()) {
1513             paramsBuilder.setRangingRoundUsage(rangingRoundUsageOptional.get());
1514         }
1515 
1516         return paramsBuilder.build();
1517     }
1518 
setUpCccUwbSessionForExecution()1519     private UwbSession setUpCccUwbSessionForExecution() throws RemoteException {
1520         // setup message
1521         doReturn(0).when(mUwbSessionManager).getSessionCount();
1522         doReturn(0L).when(mUwbSessionManager).getCccSessionCount();
1523         doReturn(false).when(mUwbSessionManager).isExistedSession(anyInt());
1524         IUwbRangingCallbacks mockRangingCallbacks = mock(IUwbRangingCallbacks.class);
1525         SessionHandle mockSessionHandle = mock(SessionHandle.class);
1526         Params params = new CccOpenRangingParams.Builder()
1527                 .setProtocolVersion(CccParams.PROTOCOL_VERSION_1_0)
1528                 .setUwbConfig(CccParams.UWB_CONFIG_0)
1529                 .setPulseShapeCombo(
1530                         new CccPulseShapeCombo(
1531                                 CccParams.PULSE_SHAPE_SYMMETRICAL_ROOT_RAISED_COSINE,
1532                                 CccParams.PULSE_SHAPE_SYMMETRICAL_ROOT_RAISED_COSINE))
1533                 .setSessionId(1)
1534                 .setRanMultiplier(4)
1535                 .setChannel(CccParams.UWB_CHANNEL_9)
1536                 .setNumChapsPerSlot(CccParams.CHAPS_PER_SLOT_3)
1537                 .setNumResponderNodes(1)
1538                 .setNumSlotsPerRound(CccParams.SLOTS_PER_ROUND_6)
1539                 .setSyncCodeIndex(1)
1540                 .setHoppingConfigMode(CccParams.HOPPING_CONFIG_MODE_NONE)
1541                 .setHoppingSequence(CccParams.HOPPING_SEQUENCE_DEFAULT)
1542                 .build();
1543         IBinder mockBinder = mock(IBinder.class);
1544         UwbSession uwbSession = spy(
1545                 mUwbSessionManager.new UwbSession(ATTRIBUTION_SOURCE, mockSessionHandle,
1546                         TEST_SESSION_ID, TEST_SESSION_TYPE, CccParams.PROTOCOL_NAME, params,
1547                         mockRangingCallbacks, TEST_CHIP_ID));
1548         doReturn(mockBinder).when(uwbSession).getBinder();
1549         doReturn(uwbSession).when(mUwbSessionManager).createUwbSession(any(), any(), anyInt(),
1550                 anyByte(), anyString(), any(), any(), anyString());
1551         doReturn(mock(WaitObj.class)).when(uwbSession).getWaitObj();
1552 
1553         return uwbSession;
1554     }
1555 
1556     @Test
openRanging_success()1557     public void openRanging_success() throws Exception {
1558         UwbSession uwbSession = setUpUwbSessionForExecution(ATTRIBUTION_SOURCE);
1559         // stub for openRanging conditions
1560         when(mNativeUwbManager.initSession(anyInt(), anyByte(), anyString()))
1561                 .thenReturn((byte) UwbUciConstants.STATUS_CODE_OK);
1562         doReturn(UwbUciConstants.UWB_SESSION_STATE_INIT,
1563                 UwbUciConstants.UWB_SESSION_STATE_IDLE).when(uwbSession).getSessionState();
1564         when(mUwbConfigurationManager.setAppConfigurations(anyInt(), any(), anyString()))
1565                 .thenReturn(UwbUciConstants.STATUS_CODE_OK);
1566 
1567 
1568         mUwbSessionManager.initSession(ATTRIBUTION_SOURCE, uwbSession.getSessionHandle(),
1569                 TEST_SESSION_ID, TEST_SESSION_TYPE, FiraParams.PROTOCOL_NAME,
1570                 uwbSession.getParams(), uwbSession.getIUwbRangingCallbacks(), TEST_CHIP_ID);
1571         mTestLooper.dispatchAll();
1572 
1573         verify(mNativeUwbManager).initSession(eq(TEST_SESSION_ID), anyByte(), eq(TEST_CHIP_ID));
1574         verify(mUwbConfigurationManager)
1575                 .setAppConfigurations(eq(TEST_SESSION_ID), any(), eq(TEST_CHIP_ID));
1576         verify(mUwbSessionNotificationManager).onRangingOpened(eq(uwbSession));
1577         verify(mUwbMetrics).logRangingInitEvent(eq(uwbSession),
1578                 eq(UwbUciConstants.STATUS_CODE_OK));
1579     }
1580 
1581     @Test
openRanging_timeout()1582     public void openRanging_timeout() throws Exception {
1583         UwbSession uwbSession = setUpUwbSessionForExecution(ATTRIBUTION_SOURCE);
1584         // stub for openRanging conditions
1585         when(mNativeUwbManager.initSession(anyInt(), anyByte(), anyString()))
1586                 .thenThrow(new IllegalStateException());
1587         doReturn(UwbUciConstants.UWB_SESSION_STATE_INIT,
1588                 UwbUciConstants.UWB_SESSION_STATE_IDLE).when(uwbSession).getSessionState();
1589         when(mUwbConfigurationManager.setAppConfigurations(anyInt(), any(), anyString()))
1590                 .thenReturn(UwbUciConstants.STATUS_CODE_OK);
1591 
1592 
1593         mUwbSessionManager.initSession(ATTRIBUTION_SOURCE, uwbSession.getSessionHandle(),
1594                 TEST_SESSION_ID, TEST_SESSION_TYPE, FiraParams.PROTOCOL_NAME,
1595                 uwbSession.getParams(), uwbSession.getIUwbRangingCallbacks(), TEST_CHIP_ID);
1596         mTestLooper.dispatchAll();
1597 
1598         verify(mUwbMetrics).logRangingInitEvent(eq(uwbSession),
1599                 eq(UwbUciConstants.STATUS_CODE_FAILED));
1600         verify(mUwbSessionNotificationManager)
1601                 .onRangingOpenFailed(eq(uwbSession), eq(UwbUciConstants.STATUS_CODE_FAILED));
1602         verify(mNativeUwbManager).deInitSession(eq(TEST_SESSION_ID), eq(TEST_CHIP_ID));
1603     }
1604 
1605     @Test
openRanging_nativeInitSessionFailed()1606     public void openRanging_nativeInitSessionFailed() throws Exception {
1607         UwbSession uwbSession = setUpUwbSessionForExecution(ATTRIBUTION_SOURCE);
1608         // stub for openRanging conditions
1609         when(mNativeUwbManager.initSession(anyInt(), anyByte(), anyString()))
1610                 .thenReturn((byte) UwbUciConstants.STATUS_CODE_FAILED);
1611         doReturn(UwbUciConstants.UWB_SESSION_STATE_INIT,
1612                 UwbUciConstants.UWB_SESSION_STATE_IDLE).when(uwbSession).getSessionState();
1613         when(mUwbConfigurationManager.setAppConfigurations(anyInt(), any(), anyString()))
1614                 .thenReturn(UwbUciConstants.STATUS_CODE_OK);
1615 
1616 
1617         mUwbSessionManager.initSession(ATTRIBUTION_SOURCE, uwbSession.getSessionHandle(),
1618                 TEST_SESSION_ID, TEST_SESSION_TYPE, FiraParams.PROTOCOL_NAME,
1619                 uwbSession.getParams(), uwbSession.getIUwbRangingCallbacks(), TEST_CHIP_ID);
1620         mTestLooper.dispatchAll();
1621 
1622         verify(mUwbMetrics).logRangingInitEvent(eq(uwbSession),
1623                 eq(UwbUciConstants.STATUS_CODE_FAILED));
1624         verify(mUwbSessionNotificationManager)
1625                 .onRangingOpenFailed(eq(uwbSession), eq(UwbUciConstants.STATUS_CODE_FAILED));
1626         verify(mNativeUwbManager).deInitSession(eq(TEST_SESSION_ID), eq(TEST_CHIP_ID));
1627     }
1628 
1629     @Test
openRanging_setAppConfigurationFailed()1630     public void openRanging_setAppConfigurationFailed() throws Exception {
1631         UwbSession uwbSession = setUpUwbSessionForExecution(ATTRIBUTION_SOURCE);
1632         // stub for openRanging conditions
1633         when(mNativeUwbManager.initSession(anyInt(), anyByte(), anyString()))
1634                 .thenReturn((byte) UwbUciConstants.STATUS_CODE_OK);
1635         doReturn(UwbUciConstants.UWB_SESSION_STATE_INIT,
1636                 UwbUciConstants.UWB_SESSION_STATE_IDLE).when(uwbSession).getSessionState();
1637         when(mUwbConfigurationManager.setAppConfigurations(anyInt(), any(), anyString()))
1638                 .thenReturn(UwbUciConstants.STATUS_CODE_FAILED);
1639 
1640 
1641         mUwbSessionManager.initSession(ATTRIBUTION_SOURCE, uwbSession.getSessionHandle(),
1642                 TEST_SESSION_ID, TEST_SESSION_TYPE, FiraParams.PROTOCOL_NAME,
1643                 uwbSession.getParams(), uwbSession.getIUwbRangingCallbacks(), TEST_CHIP_ID);
1644         mTestLooper.dispatchAll();
1645 
1646         verify(mUwbMetrics).logRangingInitEvent(eq(uwbSession),
1647                 eq(UwbUciConstants.STATUS_CODE_FAILED));
1648         verify(mUwbSessionNotificationManager)
1649                 .onRangingOpenFailed(eq(uwbSession), eq(UwbUciConstants.STATUS_CODE_FAILED));
1650         verify(mNativeUwbManager).deInitSession(eq(TEST_SESSION_ID), eq(TEST_CHIP_ID));
1651     }
1652 
1653     @Test
openRanging_wrongInitState()1654     public void openRanging_wrongInitState() throws Exception {
1655         UwbSession uwbSession = setUpUwbSessionForExecution(ATTRIBUTION_SOURCE);
1656         // stub for openRanging conditions
1657         when(mNativeUwbManager.initSession(anyInt(), anyByte(), anyString()))
1658                 .thenReturn((byte) UwbUciConstants.STATUS_CODE_OK);
1659         doReturn(UwbUciConstants.UWB_SESSION_STATE_ERROR,
1660                 UwbUciConstants.UWB_SESSION_STATE_IDLE).when(uwbSession).getSessionState();
1661         when(mUwbConfigurationManager.setAppConfigurations(anyInt(), any(), anyString()))
1662                 .thenReturn(UwbUciConstants.STATUS_CODE_FAILED);
1663 
1664 
1665         mUwbSessionManager.initSession(ATTRIBUTION_SOURCE, uwbSession.getSessionHandle(),
1666                 TEST_SESSION_ID, TEST_SESSION_TYPE, FiraParams.PROTOCOL_NAME,
1667                 uwbSession.getParams(), uwbSession.getIUwbRangingCallbacks(), TEST_CHIP_ID);
1668         mTestLooper.dispatchAll();
1669 
1670         verify(mUwbMetrics).logRangingInitEvent(eq(uwbSession),
1671                 eq(UwbUciConstants.STATUS_CODE_FAILED));
1672         verify(mUwbSessionNotificationManager)
1673                 .onRangingOpenFailed(eq(uwbSession), eq(UwbUciConstants.STATUS_CODE_FAILED));
1674         verify(mNativeUwbManager).deInitSession(eq(TEST_SESSION_ID), eq(TEST_CHIP_ID));
1675     }
1676 
1677     @Test
openRanging_wrongIdleState()1678     public void openRanging_wrongIdleState() throws Exception {
1679         UwbSession uwbSession = setUpUwbSessionForExecution(ATTRIBUTION_SOURCE);
1680         // stub for openRanging conditions
1681         when(mNativeUwbManager.initSession(anyInt(), anyByte(), anyString()))
1682                 .thenReturn((byte) UwbUciConstants.STATUS_CODE_OK);
1683         doReturn(UwbUciConstants.UWB_SESSION_STATE_INIT,
1684                 UwbUciConstants.UWB_SESSION_STATE_ERROR).when(uwbSession).getSessionState();
1685         when(mUwbConfigurationManager.setAppConfigurations(anyInt(), any(), anyString()))
1686                 .thenReturn(UwbUciConstants.STATUS_CODE_FAILED);
1687 
1688 
1689         mUwbSessionManager.initSession(ATTRIBUTION_SOURCE, uwbSession.getSessionHandle(),
1690                 TEST_SESSION_ID, TEST_SESSION_TYPE, FiraParams.PROTOCOL_NAME,
1691                 uwbSession.getParams(), uwbSession.getIUwbRangingCallbacks(), TEST_CHIP_ID);
1692         mTestLooper.dispatchAll();
1693 
1694         verify(mUwbMetrics).logRangingInitEvent(eq(uwbSession),
1695                 eq(UwbUciConstants.STATUS_CODE_FAILED));
1696         verify(mUwbSessionNotificationManager)
1697                 .onRangingOpenFailed(eq(uwbSession),
1698                         eq(UwbUciConstants.STATUS_CODE_FAILED));
1699         verify(mNativeUwbManager).deInitSession(eq(TEST_SESSION_ID), eq(TEST_CHIP_ID));
1700     }
1701 
1702     @Test
testInitSessionWithNonSystemAppInFg()1703     public void testInitSessionWithNonSystemAppInFg() throws Exception {
1704         when(mUwbInjector.isSystemApp(UID, PACKAGE_NAME)).thenReturn(false);
1705         when(mUwbInjector.isForegroundAppOrService(UID, PACKAGE_NAME)).thenReturn(true);
1706 
1707         UwbSession uwbSession = setUpUwbSessionForExecution(ATTRIBUTION_SOURCE);
1708         mUwbSessionManager.initSession(ATTRIBUTION_SOURCE, uwbSession.getSessionHandle(),
1709                 TEST_SESSION_ID, TEST_SESSION_TYPE, FiraParams.PROTOCOL_NAME,
1710                 uwbSession.getParams(), uwbSession.getIUwbRangingCallbacks(), TEST_CHIP_ID);
1711 
1712         // OPEN_RANGING message scheduled.
1713         assertThat(mTestLooper.nextMessage().what).isEqualTo(SESSION_OPEN_RANGING);
1714         assertThat(mTestLooper.isIdle()).isFalse();
1715     }
1716 
1717     @Test
testInitSessionWithNonSystemAppNotInFg()1718     public void testInitSessionWithNonSystemAppNotInFg() throws Exception {
1719         when(mUwbInjector.isSystemApp(UID, PACKAGE_NAME)).thenReturn(false);
1720         when(mUwbInjector.isForegroundAppOrService(UID, PACKAGE_NAME)).thenReturn(false);
1721 
1722         UwbSession uwbSession = setUpUwbSessionForExecution(ATTRIBUTION_SOURCE);
1723         mUwbSessionManager.initSession(ATTRIBUTION_SOURCE, uwbSession.getSessionHandle(),
1724                 TEST_SESSION_ID, TEST_SESSION_TYPE, FiraParams.PROTOCOL_NAME,
1725                 uwbSession.getParams(), uwbSession.getIUwbRangingCallbacks(), TEST_CHIP_ID);
1726 
1727         verify(uwbSession.getIUwbRangingCallbacks()).onRangingOpenFailed(
1728                 eq(uwbSession.getSessionHandle()), eq(StateChangeReason.SYSTEM_POLICY), any());
1729         // No OPEN_RANGING message scheduled.
1730         assertThat(mTestLooper.isIdle()).isFalse();
1731     }
1732 
1733     @Test
testInitSessionWithNonSystemAppNotInFg_WhenBgRangingEnabled()1734     public void testInitSessionWithNonSystemAppNotInFg_WhenBgRangingEnabled() throws Exception {
1735         when(mDeviceConfigFacade.isBackgroundRangingEnabled()).thenReturn(true);
1736         when(mUwbInjector.isSystemApp(UID, PACKAGE_NAME)).thenReturn(false);
1737         when(mUwbInjector.isForegroundAppOrService(UID, PACKAGE_NAME)).thenReturn(false);
1738 
1739         UwbSession uwbSession = setUpUwbSessionForExecution(ATTRIBUTION_SOURCE);
1740         mUwbSessionManager.initSession(ATTRIBUTION_SOURCE, uwbSession.getSessionHandle(),
1741                 TEST_SESSION_ID, TEST_SESSION_TYPE, FiraParams.PROTOCOL_NAME,
1742                 uwbSession.getParams(), uwbSession.getIUwbRangingCallbacks(), TEST_CHIP_ID);
1743 
1744         // OPEN_RANGING message scheduled.
1745         assertThat(mTestLooper.nextMessage().what).isEqualTo(SESSION_OPEN_RANGING);
1746         assertThat(mTestLooper.isIdle()).isFalse();
1747     }
1748 
initUwbSessionForNonSystemAppInFgInChain()1749     private UwbSession initUwbSessionForNonSystemAppInFgInChain() throws Exception {
1750         when(mUwbInjector.isSystemApp(UID_2, PACKAGE_NAME_2)).thenReturn(false);
1751         when(mUwbInjector.isForegroundAppOrService(UID_2, PACKAGE_NAME_2))
1752                 .thenReturn(true);
1753 
1754         // simulate system app triggered the request on behalf of a fg app in fg.
1755         AttributionSource attributionSource = new AttributionSource.Builder(UID)
1756                 .setPackageName(PACKAGE_NAME)
1757                 .setNext(new AttributionSource.Builder(UID_2)
1758                         .setPackageName(PACKAGE_NAME_2)
1759                         .build())
1760                 .build();
1761 
1762         UwbSession uwbSession = setUpUwbSessionForExecution(attributionSource);
1763         mUwbSessionManager.initSession(attributionSource, uwbSession.getSessionHandle(),
1764                 TEST_SESSION_ID, TEST_SESSION_TYPE, FiraParams.PROTOCOL_NAME,
1765                 uwbSession.getParams(), uwbSession.getIUwbRangingCallbacks(), TEST_CHIP_ID);
1766         return uwbSession;
1767     }
1768 
1769     @Test
testOpenRangingWithNonSystemAppInFgInChain()1770     public void testOpenRangingWithNonSystemAppInFgInChain() throws Exception {
1771         initUwbSessionForNonSystemAppInFgInChain();
1772 
1773         // OPEN_RANGING message scheduled.
1774         assertThat(mTestLooper.nextMessage().what).isEqualTo(SESSION_OPEN_RANGING);
1775         assertThat(mTestLooper.isIdle()).isFalse();
1776     }
1777 
1778     @Test
testOpenRangingWithNonSystemAppInFgInChain_MoveToBgAndStayThere()1779     public void testOpenRangingWithNonSystemAppInFgInChain_MoveToBgAndStayThere() throws Exception {
1780         UwbSession uwbSession = initUwbSessionForNonSystemAppInFgInChain();
1781 
1782         // Verify that an OPEN_RANGING message was scheduled.
1783         assertThat(mTestLooper.nextMessage().what).isEqualTo(SESSION_OPEN_RANGING);
1784 
1785         // Start Ranging
1786         when(mNativeUwbManager.startRanging(eq(TEST_SESSION_ID), anyString()))
1787                 .thenReturn((byte) UwbUciConstants.STATUS_CODE_OK);
1788         doReturn(UwbUciConstants.UWB_SESSION_STATE_IDLE,
1789                 UwbUciConstants.UWB_SESSION_STATE_ACTIVE).when(uwbSession).getSessionState();
1790         mUwbSessionManager.startRanging(
1791                 uwbSession.getSessionHandle(), uwbSession.getParams());
1792         mTestLooper.dispatchAll();
1793 
1794         verify(mUwbSessionNotificationManager).onRangingStarted(eq(uwbSession), any());
1795         verify(mUwbMetrics).longRangingStartEvent(
1796                 eq(uwbSession), eq(UwbUciConstants.STATUS_CODE_OK));
1797 
1798         // Move the non-privileged app to background, this should result in the session getting
1799         // reconfigured (to disable the ranging data notifications).
1800         mOnUidImportanceListenerArgumentCaptor.getValue().onUidImportance(
1801                 UID_2, IMPORTANCE_BACKGROUND);
1802         mTestLooper.dispatchAll();
1803         ArgumentCaptor<Params> paramsArgumentCaptor = ArgumentCaptor.forClass(Params.class);
1804         verify(mUwbConfigurationManager).setAppConfigurations(
1805                 eq(TEST_SESSION_ID), paramsArgumentCaptor.capture(), eq(TEST_CHIP_ID));
1806         FiraRangingReconfigureParams firaParams =
1807                 (FiraRangingReconfigureParams) paramsArgumentCaptor.getValue();
1808         assertThat(firaParams.getRangeDataNtfConfig()).isEqualTo(
1809                 FiraParams.RANGE_DATA_NTF_CONFIG_DISABLE);
1810         verify(mUwbSessionNotificationManager, never()).onRangingReconfigured(eq(uwbSession));
1811 
1812         // Verify the appropriate timer is setup.
1813         ArgumentCaptor<AlarmManager.OnAlarmListener> alarmListenerCaptor =
1814                 ArgumentCaptor.forClass(AlarmManager.OnAlarmListener.class);
1815         verify(mAlarmManager).setExact(
1816                 anyInt(), anyLong(), eq(UwbSession.NON_PRIVILEGED_BG_APP_TIMER_TAG),
1817                 alarmListenerCaptor.capture(), any());
1818         assertThat(alarmListenerCaptor.getValue()).isNotNull();
1819 
1820         // Now fire the timer callback.
1821         doReturn(UwbUciConstants.UWB_SESSION_STATE_ACTIVE,
1822                  UwbUciConstants.UWB_SESSION_STATE_IDLE).when(uwbSession).getSessionState();
1823         alarmListenerCaptor.getValue().onAlarm();
1824 
1825         // Expect session stop.
1826         mTestLooper.dispatchAll();
1827         verify(mUwbSessionNotificationManager).onRangingStoppedWithApiReasonCode(
1828                 eq(uwbSession), eq(RangingChangeReason.SYSTEM_POLICY));
1829         verify(mUwbMetrics).longRangingStopEvent(eq(uwbSession));
1830     }
1831 
1832     @Test
1833     public void
testOpenRangingWithNonSystemAppInFgInChain_MoveToBgAndStayThere_WhenBgRangingEnabled()1834             testOpenRangingWithNonSystemAppInFgInChain_MoveToBgAndStayThere_WhenBgRangingEnabled()
1835             throws Exception {
1836         when(mDeviceConfigFacade.isBackgroundRangingEnabled()).thenReturn(true);
1837         UwbSession uwbSession = initUwbSessionForNonSystemAppInFgInChain();
1838 
1839         // Verify that an OPEN_RANGING message was scheduled.
1840         assertThat(mTestLooper.nextMessage().what).isEqualTo(SESSION_OPEN_RANGING);
1841 
1842         // Start Ranging
1843         when(mNativeUwbManager.startRanging(eq(TEST_SESSION_ID), anyString()))
1844                 .thenReturn((byte) UwbUciConstants.STATUS_CODE_OK);
1845         doReturn(UwbUciConstants.UWB_SESSION_STATE_IDLE,
1846                 UwbUciConstants.UWB_SESSION_STATE_ACTIVE).when(uwbSession).getSessionState();
1847         mUwbSessionManager.startRanging(
1848                 uwbSession.getSessionHandle(), uwbSession.getParams());
1849         mTestLooper.dispatchAll();
1850 
1851         verify(mUwbSessionNotificationManager).onRangingStarted(eq(uwbSession), any());
1852         verify(mUwbMetrics).longRangingStartEvent(
1853                 eq(uwbSession), eq(UwbUciConstants.STATUS_CODE_OK));
1854 
1855         // Move the non-privileged app to background, this should result in the session getting
1856         // reconfigured (to disable the ranging data notifications).
1857         mOnUidImportanceListenerArgumentCaptor.getValue().onUidImportance(
1858                 UID_2, IMPORTANCE_BACKGROUND);
1859         mTestLooper.dispatchAll();
1860         ArgumentCaptor<Params> paramsArgumentCaptor = ArgumentCaptor.forClass(Params.class);
1861         verify(mUwbConfigurationManager).setAppConfigurations(
1862                 eq(TEST_SESSION_ID), paramsArgumentCaptor.capture(), eq(TEST_CHIP_ID));
1863         FiraRangingReconfigureParams firaParams =
1864                 (FiraRangingReconfigureParams) paramsArgumentCaptor.getValue();
1865         assertThat(firaParams.getRangeDataNtfConfig()).isEqualTo(
1866                 FiraParams.RANGE_DATA_NTF_CONFIG_DISABLE);
1867         verify(mUwbSessionNotificationManager, never()).onRangingReconfigured(eq(uwbSession));
1868 
1869         // Verify the timer is not setup.
1870         verify(mAlarmManager, never()).setExact(
1871                 anyInt(), anyLong(), eq(UwbSession.NON_PRIVILEGED_BG_APP_TIMER_TAG),
1872                 any(), any());
1873     }
1874 
1875     @Test
testOpenRangingWithNonSystemAppInFgInChain_MoveToBgAndFg()1876     public void testOpenRangingWithNonSystemAppInFgInChain_MoveToBgAndFg() throws Exception {
1877         UwbSession uwbSession = initUwbSessionForNonSystemAppInFgInChain();
1878         // OPEN_RANGING message scheduled.
1879         assertThat(mTestLooper.nextMessage().what).isEqualTo(SESSION_OPEN_RANGING);
1880         mTestLooper.dispatchAll();
1881 
1882         // Move to background.
1883         mOnUidImportanceListenerArgumentCaptor.getValue().onUidImportance(
1884                 UID_2, IMPORTANCE_BACKGROUND);
1885         mTestLooper.dispatchAll();
1886         ArgumentCaptor<Params> paramsArgumentCaptor = ArgumentCaptor.forClass(Params.class);
1887         verify(mUwbConfigurationManager).setAppConfigurations(
1888                 eq(TEST_SESSION_ID), paramsArgumentCaptor.capture(), eq(TEST_CHIP_ID));
1889         FiraRangingReconfigureParams firaParams =
1890                 (FiraRangingReconfigureParams) paramsArgumentCaptor.getValue();
1891         assertThat(firaParams.getRangeDataNtfConfig()).isEqualTo(
1892                 FiraParams.RANGE_DATA_NTF_CONFIG_DISABLE);
1893         verify(mUwbSessionNotificationManager, never()).onRangingReconfigured(eq(uwbSession));
1894 
1895         // Move to foreground.
1896         mOnUidImportanceListenerArgumentCaptor.getValue().onUidImportance(
1897                 UID_2, IMPORTANCE_FOREGROUND);
1898         mTestLooper.dispatchAll();
1899         paramsArgumentCaptor = ArgumentCaptor.forClass(Params.class);
1900         verify(mUwbConfigurationManager, times(2)).setAppConfigurations(
1901                 eq(TEST_SESSION_ID), paramsArgumentCaptor.capture(), eq(TEST_CHIP_ID));
1902         firaParams = (FiraRangingReconfigureParams) paramsArgumentCaptor.getValue();
1903         assertThat(firaParams.getRangeDataNtfConfig()).isEqualTo(
1904                 FiraParams.RANGE_DATA_NTF_CONFIG_ENABLE);
1905         verify(mUwbSessionNotificationManager, never()).onRangingReconfigured(eq(uwbSession));
1906     }
1907 
1908     @Test
testOpenRangingWithNonSystemAppInFgInChain_MoveToBgTriggersSessionPriorityChange()1909     public void testOpenRangingWithNonSystemAppInFgInChain_MoveToBgTriggersSessionPriorityChange()
1910             throws Exception {
1911         UwbSession uwbSession = initUwbSessionForNonSystemAppInFgInChain();
1912 
1913         assertThat(uwbSession.getStackSessionPriority()).isEqualTo(UwbSession.FG_SESSION_PRIORITY);
1914         assertThat(mTestLooper.nextMessage().what).isEqualTo(SESSION_OPEN_RANGING);
1915         mTestLooper.dispatchAll();
1916 
1917         // Move to background.
1918         when(mUwbInjector.isForegroundAppOrService(UID_2, PACKAGE_NAME_2))
1919                 .thenReturn(false);
1920         mOnUidImportanceListenerArgumentCaptor.getValue().onUidImportance(
1921                 UID_2, ActivityManager.RunningAppProcessInfo.IMPORTANCE_CACHED);
1922         mTestLooper.dispatchAll();
1923 
1924         assertThat(uwbSession.getStackSessionPriority()).isEqualTo(UwbSession.BG_SESSION_PRIORITY);
1925     }
1926 
1927     @Test
testOpenRangingWithNonSystemAppNotInFgInChain()1928     public void testOpenRangingWithNonSystemAppNotInFgInChain() throws Exception {
1929         when(mUwbInjector.isSystemApp(UID_2, PACKAGE_NAME_2)).thenReturn(false);
1930         when(mUwbInjector.isForegroundAppOrService(UID_2, PACKAGE_NAME_2))
1931                 .thenReturn(false);
1932 
1933         // simulate system app triggered the request on behalf of a fg app not in fg.
1934         AttributionSource attributionSource = new AttributionSource.Builder(UID)
1935                 .setPackageName(PACKAGE_NAME)
1936                 .setNext(new AttributionSource.Builder(UID_2)
1937                         .setPackageName(PACKAGE_NAME_2)
1938                         .build())
1939                 .build();
1940         UwbSession uwbSession = setUpUwbSessionForExecution(attributionSource);
1941         mUwbSessionManager.initSession(attributionSource, uwbSession.getSessionHandle(),
1942                 TEST_SESSION_ID, TEST_SESSION_TYPE, FiraParams.PROTOCOL_NAME,
1943                 uwbSession.getParams(), uwbSession.getIUwbRangingCallbacks(), TEST_CHIP_ID);
1944 
1945         verify(uwbSession.getIUwbRangingCallbacks()).onRangingOpenFailed(
1946                 eq(uwbSession.getSessionHandle()), eq(StateChangeReason.SYSTEM_POLICY), any());
1947         // No OPEN_RANGING message scheduled.
1948         assertThat(mTestLooper.isIdle()).isFalse();
1949     }
1950 
prepareExistingUwbSessionCommon(UwbSession uwbSession)1951     private UwbSession prepareExistingUwbSessionCommon(UwbSession uwbSession) throws Exception {
1952         mUwbSessionManager.initSession(ATTRIBUTION_SOURCE, uwbSession.getSessionHandle(),
1953                 TEST_SESSION_ID, TEST_SESSION_TYPE, FiraParams.PROTOCOL_NAME,
1954                 uwbSession.getParams(), uwbSession.getIUwbRangingCallbacks(), TEST_CHIP_ID);
1955         mTestLooper.nextMessage(); // remove the OPEN_RANGING msg;
1956 
1957         assertThat(mTestLooper.isIdle()).isFalse();
1958 
1959         return uwbSession;
1960     }
prepareExistingUwbSession(Params params)1961     private UwbSession prepareExistingUwbSession(Params params) throws Exception {
1962         UwbSession uwbSession = setUpUwbSessionForExecution(ATTRIBUTION_SOURCE, params);
1963         return prepareExistingUwbSessionCommon(uwbSession);
1964     }
prepareExistingUwbSession()1965     private UwbSession prepareExistingUwbSession() throws Exception {
1966         UwbSession uwbSession = setUpUwbSessionForExecution(ATTRIBUTION_SOURCE);
1967         return prepareExistingUwbSessionCommon(uwbSession);
1968     }
1969 
prepareExistingUwbSessionActive()1970     private UwbSession prepareExistingUwbSessionActive() throws Exception {
1971         UwbSession uwbSession = prepareExistingUwbSession();
1972 
1973         // Setup the UwbSession to start ranging (and move it to active state).
1974         doReturn(UwbUciConstants.UWB_SESSION_STATE_IDLE).when(uwbSession).getSessionState();
1975         when(mNativeUwbManager.startRanging(eq(TEST_SESSION_ID), anyString()))
1976                 .thenReturn((byte) UwbUciConstants.STATUS_CODE_OK);
1977 
1978         mUwbSessionManager.startRanging(uwbSession.getSessionHandle(), uwbSession.getParams());
1979         mTestLooper.dispatchAll();
1980         doReturn(UwbUciConstants.UWB_SESSION_STATE_ACTIVE).when(uwbSession).getSessionState();
1981 
1982         return uwbSession;
1983     }
1984 
prepareExistingCccUwbSession()1985     private UwbSession prepareExistingCccUwbSession() throws Exception {
1986         UwbSession uwbSession = setUpCccUwbSessionForExecution();
1987         mUwbSessionManager.initSession(ATTRIBUTION_SOURCE, uwbSession.getSessionHandle(),
1988                 TEST_SESSION_ID, TEST_SESSION_TYPE, CccParams.PROTOCOL_NAME,
1989                 uwbSession.getParams(), uwbSession.getIUwbRangingCallbacks(), TEST_CHIP_ID);
1990         mTestLooper.nextMessage(); // remove the OPEN_RANGING msg;
1991 
1992         assertThat(mTestLooper.isIdle()).isFalse();
1993 
1994         return uwbSession;
1995     }
1996 
1997     @Test
reconfigure_calledSuccess()1998     public void reconfigure_calledSuccess() throws Exception {
1999         UwbSession uwbSession = prepareExistingUwbSession();
2000         FiraRangingReconfigureParams params =
2001                 new FiraRangingReconfigureParams.Builder()
2002                         .setBlockStrideLength(10)
2003                         .setRangeDataNtfConfig(1)
2004                         .setRangeDataProximityFar(10)
2005                         .setRangeDataProximityNear(2)
2006                         .build();
2007 
2008         int actualStatus = mUwbSessionManager.reconfigure(uwbSession.getSessionHandle(), params);
2009 
2010         assertThat(actualStatus).isEqualTo(0);
2011         assertThat(mTestLooper.nextMessage().what)
2012                 .isEqualTo(UwbSessionManager.SESSION_RECONFIG_RANGING);
2013 
2014         // Verify the cache has been updated.
2015         FiraOpenSessionParams firaParams = (FiraOpenSessionParams) uwbSession.getParams();
2016         assertThat(firaParams.getBlockStrideLength()).isEqualTo(10);
2017         assertThat(firaParams.getRangeDataNtfConfig()).isEqualTo(1);
2018         assertThat(firaParams.getRangeDataNtfProximityFar()).isEqualTo(10);
2019         assertThat(firaParams.getRangeDataNtfProximityNear()).isEqualTo(2);
2020     }
2021 
2022     @Test
startRanging_sessionStateIdle()2023     public void startRanging_sessionStateIdle() throws Exception {
2024         UwbSession uwbSession = prepareExistingUwbSession();
2025         // set up for start ranging
2026         doReturn(UwbUciConstants.UWB_SESSION_STATE_IDLE)
2027                 .when(uwbSession).getSessionState();
2028 
2029         mUwbSessionManager.startRanging(
2030                 uwbSession.getSessionHandle(), uwbSession.getParams());
2031 
2032         assertThat(mTestLooper.isIdle()).isTrue();
2033         assertThat(mTestLooper.nextMessage().what).isEqualTo(2); // SESSION_START_RANGING
2034     }
2035 
2036     @Test
startRanging_sessionStateActive()2037     public void startRanging_sessionStateActive() throws Exception {
2038         UwbSession uwbSession = prepareExistingUwbSession();
2039         // set up for start ranging
2040         doReturn(UwbUciConstants.UWB_SESSION_STATE_ACTIVE)
2041                 .when(uwbSession).getSessionState();
2042 
2043         mUwbSessionManager.startRanging(
2044                 uwbSession.getSessionHandle(), uwbSession.getParams());
2045 
2046         assertThat(mTestLooper.isIdle()).isFalse();
2047         verify(mUwbSessionNotificationManager).onRangingStartFailed(
2048                 eq(uwbSession), eq(UwbUciConstants.STATUS_CODE_REJECTED));
2049     }
2050 
2051     @Test
startRanging_sessionStateError()2052     public void startRanging_sessionStateError() throws Exception {
2053         UwbSession uwbSession = prepareExistingUwbSession();
2054         // set up for start ranging
2055         doReturn(UwbUciConstants.UWB_SESSION_STATE_ERROR)
2056                 .when(uwbSession).getSessionState();
2057 
2058         mUwbSessionManager.startRanging(
2059                 uwbSession.getSessionHandle(), uwbSession.getParams());
2060 
2061         assertThat(mTestLooper.isIdle()).isFalse();
2062         verify(mUwbSessionNotificationManager).onRangingStartFailed(
2063                 eq(uwbSession), eq(UwbUciConstants.STATUS_CODE_FAILED));
2064         verify(mUwbMetrics).longRangingStartEvent(
2065                 eq(uwbSession), eq(UwbUciConstants.STATUS_CODE_FAILED));
2066     }
2067 
2068     @Test
execStartRanging_success()2069     public void execStartRanging_success() throws Exception {
2070         UwbSession uwbSession = prepareExistingUwbSession();
2071         // set up for start ranging
2072         doReturn(UwbUciConstants.UWB_SESSION_STATE_IDLE, UwbUciConstants.UWB_SESSION_STATE_ACTIVE)
2073                 .when(uwbSession).getSessionState();
2074         when(mNativeUwbManager.startRanging(eq(TEST_SESSION_ID), anyString()))
2075                 .thenReturn((byte) UwbUciConstants.STATUS_CODE_OK);
2076 
2077         mUwbSessionManager.startRanging(
2078                 uwbSession.getSessionHandle(), uwbSession.getParams());
2079         mTestLooper.dispatchAll();
2080 
2081         verify(mUwbSessionNotificationManager).onRangingStarted(eq(uwbSession), any());
2082         verify(mUwbMetrics).longRangingStartEvent(
2083                 eq(uwbSession), eq(UwbUciConstants.STATUS_CODE_OK));
2084     }
2085 
2086     @Test
execStartRanging_onRangeDataNotification()2087     public void execStartRanging_onRangeDataNotification() throws Exception {
2088         UwbSession uwbSession = prepareExistingUwbSession();
2089         // set up for start ranging
2090         doReturn(UwbUciConstants.UWB_SESSION_STATE_IDLE, UwbUciConstants.UWB_SESSION_STATE_ACTIVE)
2091                 .when(uwbSession).getSessionState();
2092         when(mNativeUwbManager.startRanging(eq(TEST_SESSION_ID), anyString()))
2093                 .thenReturn((byte) UwbUciConstants.STATUS_CODE_OK);
2094 
2095         mUwbSessionManager.startRanging(
2096                 uwbSession.getSessionHandle(), uwbSession.getParams());
2097         mTestLooper.dispatchAll();
2098 
2099         verify(mUwbSessionNotificationManager).onRangingStarted(eq(uwbSession), any());
2100         verify(mUwbMetrics).longRangingStartEvent(
2101                 eq(uwbSession), eq(UwbUciConstants.STATUS_CODE_OK));
2102 
2103         // Now send a range data notification.
2104         UwbRangingData uwbRangingData = UwbTestUtils.generateRangingData(
2105                 RANGING_MEASUREMENT_TYPE_TWO_WAY, MAC_ADDRESSING_MODE_EXTENDED,
2106                 UwbUciConstants.STATUS_CODE_OK);
2107         mUwbSessionManager.onRangeDataNotificationReceived(uwbRangingData);
2108         verify(mUwbSessionNotificationManager).onRangingResult(uwbSession, uwbRangingData);
2109     }
2110 
2111     @Test
execStartRanging_twoWay_onRangeDataNotificationContinuousErrors()2112     public void execStartRanging_twoWay_onRangeDataNotificationContinuousErrors() throws Exception {
2113         startRanging_onRangeDataNotificationContinuousErrors(RANGING_MEASUREMENT_TYPE_TWO_WAY);
2114     }
2115 
2116     @Test
execStartRanging_owrAoa_onRangeDataNotificationContinuousErrors()2117     public void execStartRanging_owrAoa_onRangeDataNotificationContinuousErrors() throws Exception {
2118         startRanging_onRangeDataNotificationContinuousErrors(RANGING_MEASUREMENT_TYPE_OWR_AOA);
2119     }
2120 
startRanging_onRangeDataNotificationContinuousErrors( int rangingMeasurementType)2121     private void startRanging_onRangeDataNotificationContinuousErrors(
2122             int rangingMeasurementType) throws Exception {
2123         UwbSession uwbSession = prepareExistingUwbSession();
2124         // set up for start ranging
2125         doReturn(UwbUciConstants.UWB_SESSION_STATE_IDLE, UwbUciConstants.UWB_SESSION_STATE_ACTIVE)
2126                 .when(uwbSession).getSessionState();
2127         when(mNativeUwbManager.startRanging(eq(TEST_SESSION_ID), anyString()))
2128                 .thenReturn((byte) UwbUciConstants.STATUS_CODE_OK);
2129 
2130         mUwbSessionManager.startRanging(
2131                 uwbSession.getSessionHandle(), uwbSession.getParams());
2132         mTestLooper.dispatchAll();
2133 
2134         verify(mUwbSessionNotificationManager).onRangingStarted(eq(uwbSession), any());
2135         verify(mUwbMetrics).longRangingStartEvent(
2136                 eq(uwbSession), eq(UwbUciConstants.STATUS_CODE_OK));
2137 
2138         // Now send a range data notification with an error.
2139         UwbRangingData uwbRangingData = UwbTestUtils.generateRangingData(
2140                 rangingMeasurementType, MAC_ADDRESSING_MODE_EXTENDED,
2141                 UwbUciConstants.STATUS_CODE_RANGING_RX_TIMEOUT);
2142         mUwbSessionManager.onRangeDataNotificationReceived(uwbRangingData);
2143         verify(mUwbSessionNotificationManager).onRangingResult(uwbSession, uwbRangingData);
2144         ArgumentCaptor<AlarmManager.OnAlarmListener> alarmListenerCaptor =
2145                 ArgumentCaptor.forClass(AlarmManager.OnAlarmListener.class);
2146         verify(mAlarmManager).setExact(
2147                 anyInt(), anyLong(), anyString(), alarmListenerCaptor.capture(), any());
2148         assertThat(alarmListenerCaptor.getValue()).isNotNull();
2149 
2150         // Send one more error and ensure that the timer is not cancelled.
2151         uwbRangingData = UwbTestUtils.generateRangingData(
2152                 rangingMeasurementType, MAC_ADDRESSING_MODE_EXTENDED,
2153                 UwbUciConstants.STATUS_CODE_RANGING_RX_TIMEOUT);
2154         mUwbSessionManager.onRangeDataNotificationReceived(uwbRangingData);
2155         verify(mUwbSessionNotificationManager).onRangingResult(uwbSession, uwbRangingData);
2156 
2157         verify(mAlarmManager, never()).cancel(any(AlarmManager.OnAlarmListener.class));
2158 
2159         // set up for stop ranging
2160         doReturn(UwbUciConstants.UWB_SESSION_STATE_ACTIVE, UwbUciConstants.UWB_SESSION_STATE_IDLE)
2161                 .when(uwbSession).getSessionState();
2162         when(mNativeUwbManager.stopRanging(eq(TEST_SESSION_ID), anyString()))
2163                 .thenReturn((byte) UwbUciConstants.STATUS_CODE_OK);
2164 
2165         // Now fire the timer callback.
2166         alarmListenerCaptor.getValue().onAlarm();
2167 
2168         // Expect session stop.
2169         mTestLooper.dispatchNext();
2170         verify(mUwbSessionNotificationManager)
2171                 .onRangingStoppedWithApiReasonCode(eq(uwbSession),
2172                         eq(RangingChangeReason.SYSTEM_POLICY));
2173         verify(mUwbMetrics).longRangingStopEvent(eq(uwbSession));
2174     }
2175 
2176     @Test
2177     public void
execStartRanging_onRangeDataNotificationContinuousErrors_WhenErrorStreakTimerDisabled()2178             execStartRanging_onRangeDataNotificationContinuousErrors_WhenErrorStreakTimerDisabled()
2179             throws Exception {
2180         when(mDeviceConfigFacade.isRangingErrorStreakTimerEnabled()).thenReturn(false);
2181 
2182         UwbSession uwbSession = prepareExistingUwbSession();
2183         // set up for start ranging
2184         doReturn(UwbUciConstants.UWB_SESSION_STATE_IDLE, UwbUciConstants.UWB_SESSION_STATE_ACTIVE)
2185                 .when(uwbSession).getSessionState();
2186         when(mNativeUwbManager.startRanging(eq(TEST_SESSION_ID), anyString()))
2187                 .thenReturn((byte) UwbUciConstants.STATUS_CODE_OK);
2188 
2189         mUwbSessionManager.startRanging(
2190                 uwbSession.getSessionHandle(), uwbSession.getParams());
2191         mTestLooper.dispatchAll();
2192 
2193         verify(mUwbSessionNotificationManager).onRangingStarted(eq(uwbSession), any());
2194         verify(mUwbMetrics).longRangingStartEvent(
2195                 eq(uwbSession), eq(UwbUciConstants.STATUS_CODE_OK));
2196 
2197         // Now send a range data notification with an error.
2198         UwbRangingData uwbRangingData = UwbTestUtils.generateRangingData(
2199                 RANGING_MEASUREMENT_TYPE_TWO_WAY, MAC_ADDRESSING_MODE_EXTENDED,
2200                 UwbUciConstants.STATUS_CODE_RANGING_RX_TIMEOUT);
2201         mUwbSessionManager.onRangeDataNotificationReceived(uwbRangingData);
2202         verify(mUwbSessionNotificationManager).onRangingResult(uwbSession, uwbRangingData);
2203         // Ensure error streak timer is not started.
2204         verify(mAlarmManager, never()).setExact(
2205                 anyInt(), anyLong(), anyString(), any(), any());
2206     }
2207 
2208     @Test
execStartRanging_onRangeDataNotificationErrorFollowedBySuccess()2209     public void execStartRanging_onRangeDataNotificationErrorFollowedBySuccess() throws Exception {
2210         UwbSession uwbSession = prepareExistingUwbSession();
2211         // set up for start ranging
2212         doReturn(UwbUciConstants.UWB_SESSION_STATE_IDLE, UwbUciConstants.UWB_SESSION_STATE_ACTIVE)
2213                 .when(uwbSession).getSessionState();
2214         when(mNativeUwbManager.startRanging(eq(TEST_SESSION_ID), anyString()))
2215                 .thenReturn((byte) UwbUciConstants.STATUS_CODE_OK);
2216 
2217         mUwbSessionManager.startRanging(
2218                 uwbSession.getSessionHandle(), uwbSession.getParams());
2219         mTestLooper.dispatchAll();
2220 
2221         verify(mUwbSessionNotificationManager).onRangingStarted(eq(uwbSession), any());
2222         verify(mUwbMetrics).longRangingStartEvent(
2223                 eq(uwbSession), eq(UwbUciConstants.STATUS_CODE_OK));
2224 
2225         // Now send a range data notification with an error.
2226         UwbRangingData uwbRangingData = UwbTestUtils.generateRangingData(
2227                 RANGING_MEASUREMENT_TYPE_TWO_WAY, MAC_ADDRESSING_MODE_EXTENDED,
2228                 UwbUciConstants.STATUS_CODE_RANGING_RX_TIMEOUT);
2229         mUwbSessionManager.onRangeDataNotificationReceived(uwbRangingData);
2230         verify(mUwbSessionNotificationManager).onRangingResult(uwbSession, uwbRangingData);
2231         ArgumentCaptor<AlarmManager.OnAlarmListener> alarmListenerCaptor =
2232                 ArgumentCaptor.forClass(AlarmManager.OnAlarmListener.class);
2233         verify(mAlarmManager).setExact(
2234                 anyInt(), anyLong(), anyString(), alarmListenerCaptor.capture(), any());
2235         assertThat(alarmListenerCaptor.getValue()).isNotNull();
2236 
2237         // Send success and ensure that the timer is cancelled.
2238         uwbRangingData = UwbTestUtils.generateRangingData(
2239                 RANGING_MEASUREMENT_TYPE_TWO_WAY, MAC_ADDRESSING_MODE_EXTENDED,
2240                 UwbUciConstants.STATUS_CODE_OK);
2241         mUwbSessionManager.onRangeDataNotificationReceived(uwbRangingData);
2242         verify(mUwbSessionNotificationManager).onRangingResult(uwbSession, uwbRangingData);
2243 
2244         verify(mAlarmManager).cancel(any(AlarmManager.OnAlarmListener.class));
2245     }
2246 
2247     @Test
session_receivedDataInfo()2248     public void session_receivedDataInfo() throws Exception {
2249         UwbSession uwbSession = prepareExistingUwbSession();
2250 
2251         // Setup the UwbSession to have multiple data packets (being received) for multiple remote
2252         // devices. This includes some duplicate packets (same sequence number from same remote
2253         // device), which should be ignored.
2254         UwbSessionManager.ReceivedDataInfo deviceOnePacketOne = buildReceivedDataInfo(
2255                 PEER_EXTENDED_MAC_ADDRESS_LONG, DATA_SEQUENCE_NUM);
2256         UwbSessionManager.ReceivedDataInfo deviceOnePacketTwo = buildReceivedDataInfo(
2257                 PEER_EXTENDED_MAC_ADDRESS_LONG, DATA_SEQUENCE_NUM_1);
2258         UwbSessionManager.ReceivedDataInfo deviceTwoPacketOne = buildReceivedDataInfo(
2259                 PEER_EXTENDED_MAC_ADDRESS_2_LONG, DATA_SEQUENCE_NUM);
2260         UwbSessionManager.ReceivedDataInfo deviceTwoPacketTwo = buildReceivedDataInfo(
2261                 PEER_EXTENDED_MAC_ADDRESS_2_LONG, DATA_SEQUENCE_NUM_1);
2262         when(mDeviceConfigFacade.getRxDataMaxPacketsToStore())
2263                 .thenReturn(MAX_RX_DATA_PACKETS_TO_STORE);
2264 
2265         uwbSession.addReceivedDataInfo(deviceOnePacketOne);
2266         uwbSession.addReceivedDataInfo(deviceOnePacketTwo);
2267         uwbSession.addReceivedDataInfo(deviceOnePacketOne);
2268 
2269         uwbSession.addReceivedDataInfo(deviceTwoPacketOne);
2270         uwbSession.addReceivedDataInfo(deviceTwoPacketTwo);
2271         uwbSession.addReceivedDataInfo(deviceTwoPacketOne);
2272 
2273         // Verify that the first call to getAllReceivedDataInfo() for a device returns all it's
2274         // received packets, and the second call receives an empty list.
2275         assertThat(uwbSession.getAllReceivedDataInfo(PEER_EXTENDED_MAC_ADDRESS_LONG)).isEqualTo(
2276                 List.of(deviceOnePacketOne, deviceOnePacketTwo));
2277         assertThat(uwbSession.getAllReceivedDataInfo(PEER_EXTENDED_MAC_ADDRESS_LONG)).isEqualTo(
2278                 List.of());
2279         assertThat(uwbSession.getAllReceivedDataInfo(PEER_EXTENDED_MAC_ADDRESS_2_LONG)).isEqualTo(
2280                 List.of(deviceTwoPacketOne, deviceTwoPacketTwo));
2281         assertThat(uwbSession.getAllReceivedDataInfo(PEER_EXTENDED_MAC_ADDRESS_2_LONG)).isEqualTo(
2282                 List.of());
2283     }
2284 
2285     @Test
session_receivedDataInfo_maxCapacity()2286     public void session_receivedDataInfo_maxCapacity() throws Exception {
2287         UwbSession uwbSession = prepareExistingUwbSession();
2288 
2289         UwbSessionManager.ReceivedDataInfo rxPacketOne = buildReceivedDataInfo(
2290                 PEER_EXTENDED_MAC_ADDRESS_LONG, DATA_SEQUENCE_NUM + 1);
2291         UwbSessionManager.ReceivedDataInfo rxPacketTwo = buildReceivedDataInfo(
2292                 PEER_EXTENDED_MAC_ADDRESS_LONG, DATA_SEQUENCE_NUM + 2);
2293         UwbSessionManager.ReceivedDataInfo rxPacketThree = buildReceivedDataInfo(
2294                 PEER_EXTENDED_MAC_ADDRESS_LONG, DATA_SEQUENCE_NUM + 3);
2295         UwbSessionManager.ReceivedDataInfo rxPacketFour = buildReceivedDataInfo(
2296                 PEER_EXTENDED_MAC_ADDRESS_LONG, DATA_SEQUENCE_NUM + 4);
2297 
2298         // Setup the UwbSession to have multiple data packets (being received) from one remote
2299         // device, such that it's at the capacity. We send the packets out-of-order, but do want
2300         // to extract them in order.
2301         when(mDeviceConfigFacade.getRxDataMaxPacketsToStore()).thenReturn(3);
2302 
2303         // Case 1 - Setup the UwbSession to have multiple Rx data packets (beyond capacity), such
2304         // that the last packet is the smallest one and should be dropped.
2305         uwbSession.addReceivedDataInfo(rxPacketTwo);
2306         uwbSession.addReceivedDataInfo(rxPacketFour);
2307         uwbSession.addReceivedDataInfo(rxPacketThree);
2308         uwbSession.addReceivedDataInfo(rxPacketOne);
2309 
2310         // Verify that the first call to getAllReceivedDataInfo() returns the max capacity number of
2311         // packets (in-order), and the second call receives an empty list.
2312         assertThat(uwbSession.getAllReceivedDataInfo(PEER_EXTENDED_MAC_ADDRESS_LONG)).isEqualTo(
2313                 List.of(rxPacketTwo, rxPacketThree, rxPacketFour));
2314         assertThat(uwbSession.getAllReceivedDataInfo(PEER_EXTENDED_MAC_ADDRESS_LONG)).isEqualTo(
2315                 List.of());
2316 
2317         // Case 2 - Setup the UwbSession to have multiple Rx data packets (beyond capacity), such
2318         // that one of the stored packets is the smallest one and should be dropped.
2319         uwbSession.addReceivedDataInfo(rxPacketOne);
2320         uwbSession.addReceivedDataInfo(rxPacketTwo);
2321         uwbSession.addReceivedDataInfo(rxPacketFour);
2322         uwbSession.addReceivedDataInfo(rxPacketThree);
2323 
2324         assertThat(uwbSession.getAllReceivedDataInfo(PEER_EXTENDED_MAC_ADDRESS_LONG)).isEqualTo(
2325                 List.of(rxPacketTwo, rxPacketThree, rxPacketFour));
2326         assertThat(uwbSession.getAllReceivedDataInfo(PEER_EXTENDED_MAC_ADDRESS_LONG)).isEqualTo(
2327                 List.of());
2328 
2329         // Case 3 - Setup the UwbSession to have multiple Rx data packets (beyond capacity), such
2330         // that one of the stored packets is repeated. The repeated packet should be ignored.
2331         uwbSession.addReceivedDataInfo(rxPacketTwo);
2332         uwbSession.addReceivedDataInfo(rxPacketFour);
2333         uwbSession.addReceivedDataInfo(rxPacketThree);
2334         uwbSession.addReceivedDataInfo(rxPacketFour);
2335 
2336         assertThat(uwbSession.getAllReceivedDataInfo(PEER_EXTENDED_MAC_ADDRESS_LONG)).isEqualTo(
2337                 List.of(rxPacketTwo, rxPacketThree, rxPacketFour));
2338         assertThat(uwbSession.getAllReceivedDataInfo(PEER_EXTENDED_MAC_ADDRESS_LONG)).isEqualTo(
2339                 List.of());
2340     }
2341 
2342     @Test
execStartCccRanging_success()2343     public void execStartCccRanging_success() throws Exception {
2344         UwbSession uwbSession = prepareExistingCccUwbSession();
2345         // set up for start ranging
2346         doReturn(UwbUciConstants.UWB_SESSION_STATE_IDLE, UwbUciConstants.UWB_SESSION_STATE_ACTIVE)
2347                 .when(uwbSession).getSessionState();
2348         when(mNativeUwbManager.startRanging(eq(TEST_SESSION_ID), anyString()))
2349                 .thenReturn((byte) UwbUciConstants.STATUS_CODE_OK);
2350         CccStartRangingParams cccStartRangingParams = new CccStartRangingParams.Builder()
2351                 .setSessionId(TEST_SESSION_ID)
2352                 .setRanMultiplier(8)
2353                 .build();
2354         mUwbSessionManager.startRanging(
2355                 uwbSession.getSessionHandle(), cccStartRangingParams);
2356         mTestLooper.dispatchAll();
2357 
2358         // Verify the update logic.
2359         CccOpenRangingParams cccOpenRangingParams = (CccOpenRangingParams) uwbSession.getParams();
2360         assertThat(cccOpenRangingParams.getRanMultiplier()).isEqualTo(8);
2361     }
2362 
2363     @Test
execStartCccRangingWithNoStartParams_success()2364     public void execStartCccRangingWithNoStartParams_success() throws Exception {
2365         UwbSession uwbSession = prepareExistingCccUwbSession();
2366         // set up for start ranging
2367         doReturn(UwbUciConstants.UWB_SESSION_STATE_IDLE, UwbUciConstants.UWB_SESSION_STATE_ACTIVE)
2368                 .when(uwbSession).getSessionState();
2369         when(mNativeUwbManager.startRanging(eq(TEST_SESSION_ID), anyString()))
2370                 .thenReturn((byte) UwbUciConstants.STATUS_CODE_OK);
2371         mUwbSessionManager.startRanging(uwbSession.getSessionHandle(), null /* params */);
2372         mTestLooper.dispatchAll();
2373 
2374         // Verify that RAN multiplier from open is used.
2375         CccOpenRangingParams cccOpenRangingParams = (CccOpenRangingParams) uwbSession.getParams();
2376         assertThat(cccOpenRangingParams.getRanMultiplier()).isEqualTo(4);
2377     }
2378 
2379     @Test
execStartRanging_executionException()2380     public void execStartRanging_executionException() throws Exception {
2381         UwbSession uwbSession = prepareExistingUwbSession();
2382         // set up for start ranging
2383         doReturn(UwbUciConstants.UWB_SESSION_STATE_IDLE, UwbUciConstants.UWB_SESSION_STATE_ACTIVE)
2384                 .when(uwbSession).getSessionState();
2385         when(mNativeUwbManager.startRanging(eq(TEST_SESSION_ID), anyString()))
2386                 .thenThrow(new IllegalStateException());
2387 
2388         mUwbSessionManager.startRanging(
2389                 uwbSession.getSessionHandle(), uwbSession.getParams());
2390         mTestLooper.dispatchAll();
2391 
2392         verify(mUwbMetrics).longRangingStartEvent(
2393                 eq(uwbSession), eq(UwbUciConstants.STATUS_CODE_FAILED));
2394     }
2395 
2396     @Test
execStartRanging_nativeStartRangingFailed()2397     public void execStartRanging_nativeStartRangingFailed() throws Exception {
2398         UwbSession uwbSession = prepareExistingUwbSession();
2399         // set up for start ranging
2400         doReturn(UwbUciConstants.UWB_SESSION_STATE_IDLE, UwbUciConstants.UWB_SESSION_STATE_ACTIVE)
2401                 .when(uwbSession).getSessionState();
2402         when(mNativeUwbManager.startRanging(eq(TEST_SESSION_ID), anyString()))
2403                 .thenReturn((byte) UwbUciConstants.STATUS_CODE_FAILED);
2404 
2405         mUwbSessionManager.startRanging(
2406                 uwbSession.getSessionHandle(), uwbSession.getParams());
2407         mTestLooper.dispatchAll();
2408 
2409         verify(mUwbSessionNotificationManager).onRangingStartFailed(
2410                 eq(uwbSession), eq(UwbUciConstants.STATUS_CODE_FAILED));
2411         verify(mUwbMetrics).longRangingStartEvent(
2412                 eq(uwbSession), eq(UwbUciConstants.STATUS_CODE_FAILED));
2413     }
2414 
2415     @Test
execStartRanging_wrongSessionState()2416     public void execStartRanging_wrongSessionState() throws Exception {
2417         UwbSession uwbSession = prepareExistingUwbSession();
2418         // set up for start ranging
2419         doReturn(UwbUciConstants.UWB_SESSION_STATE_IDLE, UwbUciConstants.UWB_SESSION_STATE_ERROR)
2420                 .when(uwbSession).getSessionState();
2421         when(mNativeUwbManager.startRanging(eq(TEST_SESSION_ID), anyString()))
2422                 .thenReturn((byte) UwbUciConstants.STATUS_CODE_OK);
2423 
2424         mUwbSessionManager.startRanging(
2425                 uwbSession.getSessionHandle(), uwbSession.getParams());
2426         mTestLooper.dispatchAll();
2427 
2428         verify(mUwbSessionNotificationManager).onRangingStartFailed(
2429                 eq(uwbSession), eq(UwbUciConstants.STATUS_CODE_FAILED));
2430         verify(mUwbMetrics).longRangingStartEvent(
2431                 eq(uwbSession), eq(UwbUciConstants.STATUS_CODE_FAILED));
2432     }
2433 
doTest_sendData_success_validUwbSession(byte[] macAddress, int dataTransferStatus)2434     private void doTest_sendData_success_validUwbSession(byte[] macAddress, int dataTransferStatus)
2435             throws Exception {
2436         UwbAddress uwbAddress = UwbAddress.fromBytes(macAddress);
2437         UwbSession uwbSession = prepareExistingUwbSession();
2438 
2439         // Setup the UwbSession to start ranging (and move it to active state).
2440         doReturn(UwbUciConstants.UWB_SESSION_STATE_IDLE).when(uwbSession).getSessionState();
2441         when(mNativeUwbManager.startRanging(eq(TEST_SESSION_ID), anyString()))
2442                 .thenReturn((byte) UwbUciConstants.STATUS_CODE_OK);
2443 
2444         mUwbSessionManager.startRanging(uwbSession.getSessionHandle(), uwbSession.getParams());
2445         mTestLooper.dispatchAll();
2446         doReturn(UwbUciConstants.UWB_SESSION_STATE_ACTIVE).when(uwbSession).getSessionState();
2447 
2448         // Send data on the UWB session.
2449         when(mNativeUwbManager.sendData(eq(TEST_SESSION_ID), eq(macAddress),
2450                 eq(UwbUciConstants.UWB_DESTINATION_END_POINT_HOST), eq(DATA_SEQUENCE_NUM),
2451                 eq(DATA_PAYLOAD), eq(TEST_CHIP_ID)))
2452                 .thenReturn((byte) UwbUciConstants.STATUS_CODE_OK);
2453 
2454         mUwbSessionManager.sendData(
2455                 uwbSession.getSessionHandle(), uwbAddress, PERSISTABLE_BUNDLE, DATA_PAYLOAD);
2456         mTestLooper.dispatchNext();
2457 
2458         verify(mNativeUwbManager).sendData(eq(TEST_SESSION_ID), eq(macAddress),
2459                 eq(UwbUciConstants.UWB_DESTINATION_END_POINT_HOST), eq(DATA_SEQUENCE_NUM),
2460                 eq(DATA_PAYLOAD), eq(TEST_CHIP_ID));
2461 
2462         // A DataTransferStatusNtf is received indicating success.
2463         mUwbSessionManager.onDataSendStatus(
2464                 uwbSession.getSessionId(), dataTransferStatus, DATA_SEQUENCE_NUM);
2465         verify(mUwbSessionNotificationManager).onDataSent(
2466                 eq(uwbSession), eq(uwbAddress), eq(PERSISTABLE_BUNDLE));
2467         verify(mUwbMetrics).logDataTx(eq(uwbSession), eq(UwbUciConstants.STATUS_CODE_OK));
2468     }
2469 
2470     // Test case for scenario when a Data packet is successfully sent to a remote device (in
2471     // extended MacAddress format). The DataTransferStatus notification returns a success status
2472     // code (STATUS_CODE_DATA_TRANSFER_REPETITION_OK).
2473     @Test
sendData_success_validUwbSession_extendedMacAddress_statusRepetitionOk()2474     public void sendData_success_validUwbSession_extendedMacAddress_statusRepetitionOk()
2475             throws Exception {
2476         doTest_sendData_success_validUwbSession(
2477                 PEER_EXTENDED_MAC_ADDRESS, STATUS_CODE_DATA_TRANSFER_REPETITION_OK);
2478     }
2479 
2480     // Test case for scenario when a Data packet is successfully sent to a remote device (in
2481     // extended MacAddress format). The DataTransferStatus notification returns a success status
2482     // code (STATUS_CODE_OK).
2483     @Test
sendData_success_validUwbSession_extendedMacAddress_statusOk()2484     public void sendData_success_validUwbSession_extendedMacAddress_statusOk()
2485             throws Exception {
2486         doTest_sendData_success_validUwbSession(PEER_EXTENDED_MAC_ADDRESS, STATUS_CODE_OK);
2487     }
2488 
2489     // Test case for scenario when a Data packet is successfully sent to a remote device (in
2490     // short MacAddress format). The DataTransferStatus notification returns a success status
2491     // code (STATUS_CODE_DATA_TRANSFER_REPETITION_OK).
2492     @Test
sendData_success_validUwbSession_shortMacAddress_statusRepetitionOk()2493     public void sendData_success_validUwbSession_shortMacAddress_statusRepetitionOk()
2494             throws Exception {
2495         doTest_sendData_success_validUwbSession(
2496                 PEER_EXTENDED_SHORT_MAC_ADDRESS, STATUS_CODE_DATA_TRANSFER_REPETITION_OK);
2497     }
2498 
2499     // Test case for scenario when a Data packet is successfully sent to a remote device (in
2500     // short MacAddress format). The DataTransferStatus notification returns a success status
2501     // code (STATUS_CODE_OK).
2502     @Test
sendData_success_validUwbSession_shortMacAddress_statusOk()2503     public void sendData_success_validUwbSession_shortMacAddress_statusOk() throws Exception {
2504         doTest_sendData_success_validUwbSession(PEER_EXTENDED_SHORT_MAC_ADDRESS, STATUS_CODE_OK);
2505     }
2506 
2507     @Test
sendData_success_sequenceNumberRollover()2508     public void sendData_success_sequenceNumberRollover() throws Exception {
2509         // Setup a UwbSession to start ranging (and move it to active state).
2510         UwbSession uwbSession = prepareExistingUwbSessionActive();
2511         clearInvocations(mNativeUwbManager);
2512 
2513         // Send 257 data packets on the UWB session, so that the UCI sequence number rolls over,
2514         // back to 0.
2515         when(mNativeUwbManager.sendData(anyInt(), any(), anyByte(), anyByte(), any(), anyString()))
2516                 .thenReturn((byte) UwbUciConstants.STATUS_CODE_OK);
2517 
2518         for (int i = 0; i <= 256; i++) {
2519             mUwbSessionManager.sendData(uwbSession.getSessionHandle(), PEER_EXTENDED_UWB_ADDRESS,
2520                     PERSISTABLE_BUNDLE, DATA_PAYLOAD);
2521             mTestLooper.dispatchNext();
2522         }
2523 
2524         // Verify that there are 257 calls to mNativeUwbManager.sendData(), with the important
2525         // thing here being that there should be 2 calls for sequence_number = 0, and 1 call for all
2526         // the other sequence number values [1-255].
2527         for (int i = 0; i < 256; i++) {
2528             int expectedCount = (i == 0) ? 2 : 1;
2529             verify(mNativeUwbManager, times(expectedCount)).sendData(eq(TEST_SESSION_ID),
2530                     eq(PEER_EXTENDED_UWB_ADDRESS.toBytes()),
2531                     eq(UwbUciConstants.UWB_DESTINATION_END_POINT_HOST), eq((byte) i),
2532                     eq(DATA_PAYLOAD), eq(TEST_CHIP_ID));
2533         }
2534         verifyNoMoreInteractions(mNativeUwbManager);
2535         verify(mUwbMetrics, times(257)).logDataTx(eq(uwbSession),
2536                 eq(UwbUciConstants.STATUS_CODE_OK));
2537     }
2538 
2539     @Test
sendData_missingSessionHandle()2540     public void sendData_missingSessionHandle() throws Exception {
2541         // Setup a UwbSession to start ranging (and move it to active state).
2542         prepareExistingUwbSessionActive();
2543 
2544         // Send a Data packet with null SessionHandle, it should result in an error.
2545         mUwbSessionManager.sendData(
2546                 null /* sessionHandle */, PEER_EXTENDED_UWB_ADDRESS, PERSISTABLE_BUNDLE,
2547                 DATA_PAYLOAD);
2548         mTestLooper.dispatchNext();
2549 
2550         verify(mNativeUwbManager, never()).sendData(
2551                 eq(TEST_SESSION_ID), eq(PEER_EXTENDED_UWB_ADDRESS.toBytes()),
2552                 eq(UwbUciConstants.UWB_DESTINATION_END_POINT_HOST), eq(DATA_SEQUENCE_NUM),
2553                 eq(DATA_PAYLOAD), eq(TEST_CHIP_ID));
2554         verify(mUwbSessionNotificationManager).onDataSendFailed(
2555                 eq(null), eq(PEER_EXTENDED_UWB_ADDRESS),
2556                 eq(UwbUciConstants.STATUS_CODE_ERROR_SESSION_NOT_EXIST), eq(PERSISTABLE_BUNDLE));
2557     }
2558 
2559     @Test
sendData_invalidUwbSessionHandle()2560     public void sendData_invalidUwbSessionHandle() throws Exception {
2561         // Setup a uwbSession UwbSession to start ranging (and move it to active state), and a
2562         // different sessionHandle that doesn't map to the uwbSession.
2563         prepareExistingUwbSessionActive();
2564         SessionHandle sessionHandle = new SessionHandle(HANDLE_ID, ATTRIBUTION_SOURCE, PID);
2565 
2566         // Send a Data packet on the non-active UWB Session.
2567         mUwbSessionManager.sendData(
2568                 sessionHandle, PEER_EXTENDED_UWB_ADDRESS, PERSISTABLE_BUNDLE, DATA_PAYLOAD);
2569         mTestLooper.dispatchNext();
2570 
2571         verify(mNativeUwbManager, never()).sendData(
2572                 eq(TEST_SESSION_ID), eq(PEER_EXTENDED_UWB_ADDRESS.toBytes()),
2573                 eq(UwbUciConstants.UWB_DESTINATION_END_POINT_HOST), eq(DATA_SEQUENCE_NUM),
2574                 eq(DATA_PAYLOAD), eq(TEST_CHIP_ID));
2575         verify(mUwbSessionNotificationManager).onDataSendFailed(
2576                 eq(null), eq(PEER_EXTENDED_UWB_ADDRESS),
2577                 eq(UwbUciConstants.STATUS_CODE_ERROR_SESSION_NOT_EXIST), eq(PERSISTABLE_BUNDLE));
2578     }
2579 
2580     @Test
sendData_invalidUwbSessionState()2581     public void sendData_invalidUwbSessionState() throws Exception {
2582         // Setup a uwbSession and don't start ranging, so it remains in IDLE state.
2583         UwbSession uwbSession = prepareExistingUwbSession();
2584         doReturn(UwbUciConstants.UWB_SESSION_STATE_IDLE).when(uwbSession).getSessionState();
2585 
2586         // Attempt to send data on the UWB session.
2587         mUwbSessionManager.sendData(
2588                 uwbSession.getSessionHandle(), PEER_EXTENDED_UWB_ADDRESS, PERSISTABLE_BUNDLE, null);
2589         mTestLooper.dispatchNext();
2590 
2591         verify(mNativeUwbManager, never()).sendData(
2592                 eq(TEST_SESSION_ID), eq(PEER_EXTENDED_UWB_ADDRESS.toBytes()),
2593                 eq(UwbUciConstants.UWB_DESTINATION_END_POINT_HOST), eq(DATA_SEQUENCE_NUM),
2594                 eq(DATA_PAYLOAD), eq(TEST_CHIP_ID));
2595         verify(mUwbSessionNotificationManager).onDataSendFailed(
2596                 eq(uwbSession), eq(PEER_EXTENDED_UWB_ADDRESS),
2597                 eq(UwbUciConstants.STATUS_CODE_FAILED), eq(PERSISTABLE_BUNDLE));
2598     }
2599 
2600     @Test
sendData_missingDataPayload()2601     public void sendData_missingDataPayload() throws Exception {
2602         // Setup a uwbSession UwbSession to start ranging (and move it to active state).
2603         UwbSession uwbSession = prepareExistingUwbSessionActive();
2604 
2605         // Attempt to send data on the UWB session.
2606         mUwbSessionManager.sendData(
2607                 uwbSession.getSessionHandle(), PEER_EXTENDED_UWB_ADDRESS, PERSISTABLE_BUNDLE, null);
2608         mTestLooper.dispatchNext();
2609 
2610         verify(mNativeUwbManager, never()).sendData(
2611                 eq(TEST_SESSION_ID), eq(PEER_EXTENDED_UWB_ADDRESS.toBytes()),
2612                 eq(UwbUciConstants.UWB_DESTINATION_END_POINT_HOST), eq(DATA_SEQUENCE_NUM),
2613                 eq(DATA_PAYLOAD), eq(TEST_CHIP_ID));
2614         verify(mUwbSessionNotificationManager).onDataSendFailed(
2615                 eq(uwbSession), eq(PEER_EXTENDED_UWB_ADDRESS),
2616                 eq(UwbUciConstants.STATUS_CODE_INVALID_PARAM), eq(PERSISTABLE_BUNDLE));
2617     }
2618 
2619     @Test
sendData_missingRemoteDevice()2620     public void sendData_missingRemoteDevice() throws Exception {
2621         // Setup a uwbSession UwbSession to start ranging (and move it to active state).
2622         UwbSession uwbSession = prepareExistingUwbSessionActive();
2623 
2624         // Attempt to send data on the UWB session.
2625         mUwbSessionManager.sendData(
2626                 uwbSession.getSessionHandle(), null, PERSISTABLE_BUNDLE, DATA_PAYLOAD);
2627         mTestLooper.dispatchNext();
2628 
2629         verify(mNativeUwbManager, never()).sendData(
2630                 eq(TEST_SESSION_ID), eq(PEER_EXTENDED_UWB_ADDRESS.toBytes()),
2631                 eq(UwbUciConstants.UWB_DESTINATION_END_POINT_HOST), eq(DATA_SEQUENCE_NUM),
2632                 eq(DATA_PAYLOAD), eq(TEST_CHIP_ID));
2633         verify(mUwbSessionNotificationManager).onDataSendFailed(
2634                 eq(uwbSession), eq(null),
2635                 eq(UwbUciConstants.STATUS_CODE_INVALID_PARAM), eq(PERSISTABLE_BUNDLE));
2636     }
2637 
2638     @Test
sendData_dataSendFailure()2639     public void sendData_dataSendFailure() throws Exception {
2640         // Setup a uwbSession UwbSession to start ranging (and move it to active state).
2641         UwbSession uwbSession = prepareExistingUwbSessionActive();
2642 
2643         // Attempt to send data on the UWB session.
2644         when(mNativeUwbManager.sendData(eq(TEST_SESSION_ID),
2645                 eq(PEER_EXTENDED_UWB_ADDRESS.toBytes()),
2646                 eq(UwbUciConstants.UWB_DESTINATION_END_POINT_HOST), eq(DATA_SEQUENCE_NUM),
2647                 eq(DATA_PAYLOAD), eq(TEST_CHIP_ID)))
2648                 .thenReturn((byte) UwbUciConstants.STATUS_CODE_FAILED);
2649 
2650         mUwbSessionManager.sendData(uwbSession.getSessionHandle(), PEER_EXTENDED_UWB_ADDRESS,
2651                 PERSISTABLE_BUNDLE, DATA_PAYLOAD);
2652         mTestLooper.dispatchNext();
2653 
2654         verify(mNativeUwbManager).sendData(eq(TEST_SESSION_ID),
2655                 eq(PEER_EXTENDED_UWB_ADDRESS.toBytes()),
2656                 eq(UwbUciConstants.UWB_DESTINATION_END_POINT_HOST), eq(DATA_SEQUENCE_NUM),
2657                 eq(DATA_PAYLOAD), eq(TEST_CHIP_ID));
2658         verify(mUwbSessionNotificationManager).onDataSendFailed(
2659                 eq(uwbSession), eq(PEER_EXTENDED_UWB_ADDRESS),
2660                 eq(UwbUciConstants.STATUS_CODE_FAILED), eq(PERSISTABLE_BUNDLE));
2661         verify(mUwbMetrics).logDataTx(eq(uwbSession), eq(UwbUciConstants.STATUS_CODE_FAILED));
2662     }
2663 
2664     @Test
onDataSendStatus_sessionNotFound()2665     public void onDataSendStatus_sessionNotFound() throws Exception {
2666         // Setup a uwbSession UwbSession to start ranging (and move it to active state).
2667         UwbSession uwbSession = prepareExistingUwbSessionActive();
2668         clearInvocations(mUwbSessionNotificationManager);
2669 
2670         // Send data on the UWB session.
2671         when(mNativeUwbManager.sendData(eq(TEST_SESSION_ID),
2672                 eq(PEER_EXTENDED_UWB_ADDRESS.toBytes()),
2673                 eq(UwbUciConstants.UWB_DESTINATION_END_POINT_HOST), eq(DATA_SEQUENCE_NUM),
2674                 eq(DATA_PAYLOAD), eq(TEST_CHIP_ID)))
2675                 .thenReturn((byte) UwbUciConstants.STATUS_CODE_OK);
2676 
2677         mUwbSessionManager.sendData(uwbSession.getSessionHandle(), PEER_EXTENDED_UWB_ADDRESS,
2678                 PERSISTABLE_BUNDLE, DATA_PAYLOAD);
2679         mTestLooper.dispatchNext();
2680 
2681         verify(mNativeUwbManager).sendData(eq(TEST_SESSION_ID),
2682                 eq(PEER_EXTENDED_UWB_ADDRESS.toBytes()),
2683                 eq(UwbUciConstants.UWB_DESTINATION_END_POINT_HOST), eq(DATA_SEQUENCE_NUM),
2684                 eq(DATA_PAYLOAD), eq(TEST_CHIP_ID));
2685         verify(mUwbMetrics).logDataTx(eq(uwbSession), eq(UwbUciConstants.STATUS_CODE_OK));
2686 
2687         // We receive a DataTransferStatusNtf with a sessionId for a different UwbSession, so it
2688         // should be dropped (no onDataSend()/onDataSendFailure() notifications sent).
2689         mUwbSessionManager.onDataSendStatus(TEST_SESSION_ID_2, STATUS_CODE_OK, DATA_SEQUENCE_NUM);
2690         verifyNoMoreInteractions(mUwbSessionNotificationManager);
2691     }
2692 
2693     @Test
onDataSendStatus_dataSndPacketNotFound()2694     public void onDataSendStatus_dataSndPacketNotFound() throws Exception {
2695         // Setup a uwbSession UwbSession to start ranging (and move it to active state).
2696         UwbSession uwbSession = prepareExistingUwbSessionActive();
2697         clearInvocations(mUwbSessionNotificationManager);
2698 
2699         // Send data on the UWB session.
2700         when(mNativeUwbManager.sendData(eq(TEST_SESSION_ID),
2701                 eq(PEER_EXTENDED_UWB_ADDRESS.toBytes()),
2702                 eq(UwbUciConstants.UWB_DESTINATION_END_POINT_HOST), eq(DATA_SEQUENCE_NUM),
2703                 eq(DATA_PAYLOAD), eq(TEST_CHIP_ID)))
2704                 .thenReturn((byte) UwbUciConstants.STATUS_CODE_OK);
2705 
2706         mUwbSessionManager.sendData(uwbSession.getSessionHandle(), PEER_EXTENDED_UWB_ADDRESS,
2707                 PERSISTABLE_BUNDLE, DATA_PAYLOAD);
2708         mTestLooper.dispatchNext();
2709 
2710         verify(mNativeUwbManager).sendData(eq(TEST_SESSION_ID),
2711                 eq(PEER_EXTENDED_UWB_ADDRESS.toBytes()),
2712                 eq(UwbUciConstants.UWB_DESTINATION_END_POINT_HOST), eq(DATA_SEQUENCE_NUM),
2713                 eq(DATA_PAYLOAD), eq(TEST_CHIP_ID));
2714         verify(mUwbMetrics).logDataTx(eq(uwbSession), eq(UwbUciConstants.STATUS_CODE_OK));
2715 
2716         // We receive a DataTransferStatusNtf with an incorrect UCI sequence number (for which a
2717         // packet was never sent), so it should be dropped (no onDataSend()/onDataSendFailure()
2718         // notifications sent).
2719         mUwbSessionManager.onDataSendStatus(TEST_SESSION_ID, STATUS_CODE_OK, DATA_SEQUENCE_NUM_1);
2720         verifyNoMoreInteractions(mUwbSessionNotificationManager);
2721     }
2722 
2723     @Test
onDataSendStatus_errorStatus()2724     public void onDataSendStatus_errorStatus() throws Exception {
2725         // Setup a uwbSession UwbSession to start ranging (and move it to active state).
2726         UwbSession uwbSession = prepareExistingUwbSessionActive();
2727         clearInvocations(mUwbSessionNotificationManager);
2728 
2729         // Send data on the UWB session.
2730         when(mNativeUwbManager.sendData(eq(TEST_SESSION_ID),
2731                 eq(PEER_EXTENDED_UWB_ADDRESS.toBytes()),
2732                 eq(UwbUciConstants.UWB_DESTINATION_END_POINT_HOST), eq(DATA_SEQUENCE_NUM),
2733                 eq(DATA_PAYLOAD), eq(TEST_CHIP_ID)))
2734                 .thenReturn((byte) UwbUciConstants.STATUS_CODE_OK);
2735 
2736         mUwbSessionManager.sendData(uwbSession.getSessionHandle(), PEER_EXTENDED_UWB_ADDRESS,
2737                 PERSISTABLE_BUNDLE, DATA_PAYLOAD);
2738         mTestLooper.dispatchNext();
2739 
2740         verify(mNativeUwbManager).sendData(eq(TEST_SESSION_ID),
2741                 eq(PEER_EXTENDED_UWB_ADDRESS.toBytes()),
2742                 eq(UwbUciConstants.UWB_DESTINATION_END_POINT_HOST), eq(DATA_SEQUENCE_NUM),
2743                 eq(DATA_PAYLOAD), eq(TEST_CHIP_ID));
2744         verify(mUwbMetrics).logDataTx(eq(uwbSession), eq(UwbUciConstants.STATUS_CODE_OK));
2745 
2746         // We receive a DataTransferStatusNtf with an error status code.
2747         mUwbSessionManager.onDataSendStatus(TEST_SESSION_ID,
2748                 STATUS_CODE_DATA_TRANSFER_ERROR_DATA_TRANSFER, DATA_SEQUENCE_NUM);
2749         verify(mUwbSessionNotificationManager).onDataSendFailed(
2750                 eq(uwbSession), eq(PEER_EXTENDED_UWB_ADDRESS),
2751                 eq(STATUS_CODE_DATA_TRANSFER_ERROR_DATA_TRANSFER), eq(PERSISTABLE_BUNDLE));
2752     }
2753 
2754     @Test
onDataSendStatus_neverReceived()2755     public void onDataSendStatus_neverReceived() throws Exception {
2756         // Setup a uwbSession UwbSession to start ranging (and move it to active state).
2757         UwbSession uwbSession = prepareExistingUwbSessionActive();
2758         clearInvocations(mUwbSessionNotificationManager);
2759 
2760         // Send data on the UWB session.
2761         when(mNativeUwbManager.sendData(eq(TEST_SESSION_ID),
2762                 eq(PEER_EXTENDED_UWB_ADDRESS.toBytes()),
2763                 eq(UwbUciConstants.UWB_DESTINATION_END_POINT_HOST), eq(DATA_SEQUENCE_NUM),
2764                 eq(DATA_PAYLOAD), eq(TEST_CHIP_ID)))
2765                 .thenReturn((byte) UwbUciConstants.STATUS_CODE_OK);
2766 
2767         mUwbSessionManager.sendData(uwbSession.getSessionHandle(), PEER_EXTENDED_UWB_ADDRESS,
2768                 PERSISTABLE_BUNDLE, DATA_PAYLOAD);
2769         mTestLooper.dispatchNext();
2770 
2771         verify(mNativeUwbManager).sendData(eq(TEST_SESSION_ID),
2772                 eq(PEER_EXTENDED_UWB_ADDRESS.toBytes()),
2773                 eq(UwbUciConstants.UWB_DESTINATION_END_POINT_HOST), eq(DATA_SEQUENCE_NUM),
2774                 eq(DATA_PAYLOAD), eq(TEST_CHIP_ID));
2775         verify(mUwbMetrics).logDataTx(eq(uwbSession), eq(UwbUciConstants.STATUS_CODE_OK));
2776 
2777         // We never receive a DataTransferStatusNtf, so no onDataSend()/onDataSendFailure()
2778         // notifications are sent.
2779         verifyNoMoreInteractions(mUwbSessionNotificationManager);
2780         assertNotNull(uwbSession.getSendDataInfo(DATA_SEQUENCE_NUM));
2781 
2782         // Eventually Session DeInit is called, and the stored SendDataInfo(s) should be deleted.
2783         mUwbSessionManager.deInitSession(uwbSession.getSessionHandle());
2784         mTestLooper.dispatchNext();
2785         assertNull(uwbSession.getSendDataInfo(DATA_SEQUENCE_NUM));
2786     }
2787 
2788     @Test
stopRanging_sessionStateActive()2789     public void stopRanging_sessionStateActive() throws Exception {
2790         UwbSession uwbSession = prepareExistingUwbSession();
2791         // set up for stop ranging
2792         doReturn(UwbUciConstants.UWB_SESSION_STATE_ACTIVE).when(uwbSession).getSessionState();
2793 
2794         mUwbSessionManager.stopRanging(uwbSession.getSessionHandle());
2795 
2796         assertThat(mTestLooper.nextMessage().what).isEqualTo(3); // SESSION_STOP_RANGING
2797     }
2798 
2799     @Test
stopRanging_sessionStateIdle()2800     public void stopRanging_sessionStateIdle() throws Exception {
2801         UwbSession uwbSession = prepareExistingUwbSession();
2802         // set up for stop ranging
2803         doReturn(UwbUciConstants.UWB_SESSION_STATE_IDLE).when(uwbSession).getSessionState();
2804 
2805         mUwbSessionManager.stopRanging(uwbSession.getSessionHandle());
2806 
2807         verify(mUwbSessionNotificationManager).onRangingStopped(
2808                 eq(uwbSession),
2809                 eq(UwbUciConstants.REASON_STATE_CHANGE_WITH_SESSION_MANAGEMENT_COMMANDS));
2810         verify(mUwbMetrics).longRangingStopEvent(eq(uwbSession));
2811     }
2812 
2813     @Test
stopRanging_sessionStateError()2814     public void stopRanging_sessionStateError() throws Exception {
2815         UwbSession uwbSession = prepareExistingUwbSession();
2816         // set up for stop ranging
2817         doReturn(UwbUciConstants.UWB_SESSION_STATE_ERROR).when(uwbSession).getSessionState();
2818 
2819         mUwbSessionManager.stopRanging(uwbSession.getSessionHandle());
2820 
2821         verify(mUwbSessionNotificationManager).onRangingStopFailed(
2822                 eq(uwbSession), eq(UwbUciConstants.STATUS_CODE_REJECTED));
2823     }
2824 
2825     @Test
execStopRanging_success()2826     public void execStopRanging_success() throws Exception {
2827         UwbSession uwbSession = prepareExistingUwbSession();
2828         doReturn(UwbUciConstants.UWB_SESSION_STATE_ACTIVE, UwbUciConstants.UWB_SESSION_STATE_IDLE)
2829                 .when(uwbSession).getSessionState();
2830         when(mNativeUwbManager.stopRanging(eq(TEST_SESSION_ID), anyString()))
2831                 .thenReturn((byte) UwbUciConstants.STATUS_CODE_OK);
2832 
2833         mUwbSessionManager.stopRanging(uwbSession.getSessionHandle());
2834         mTestLooper.dispatchNext();
2835 
2836         verify(mUwbInjector).runTaskOnSingleThreadExecutor(
2837                 any(), eq(IUwbAdapter.RANGING_SESSION_START_THRESHOLD_MS));
2838         verify(mUwbSessionNotificationManager)
2839                 .onRangingStoppedWithApiReasonCode(eq(uwbSession),
2840                         eq(RangingChangeReason.LOCAL_API));
2841         verify(mUwbMetrics).longRangingStopEvent(eq(uwbSession));
2842     }
2843 
2844     @Test
execStopRanging_exception()2845     public void execStopRanging_exception() throws Exception {
2846         UwbSession uwbSession = prepareExistingUwbSession();
2847         doReturn(UwbUciConstants.UWB_SESSION_STATE_ACTIVE, UwbUciConstants.UWB_SESSION_STATE_IDLE)
2848                 .when(uwbSession).getSessionState();
2849         when(mNativeUwbManager.stopRanging(eq(TEST_SESSION_ID), anyString()))
2850                 .thenThrow(new IllegalStateException());
2851 
2852         mUwbSessionManager.stopRanging(uwbSession.getSessionHandle());
2853         mTestLooper.dispatchNext();
2854 
2855         verify(mUwbSessionNotificationManager, never()).onRangingStopped(any(), anyInt());
2856     }
2857 
2858     @Test
execStopRanging_nativeFailed()2859     public void execStopRanging_nativeFailed() throws Exception {
2860         UwbSession uwbSession = prepareExistingUwbSession();
2861         doReturn(UwbUciConstants.UWB_SESSION_STATE_ACTIVE, UwbUciConstants.UWB_SESSION_STATE_IDLE)
2862                 .when(uwbSession).getSessionState();
2863         when(mNativeUwbManager.stopRanging(eq(TEST_SESSION_ID), anyString()))
2864                 .thenReturn((byte) UwbUciConstants.STATUS_CODE_FAILED);
2865 
2866         mUwbSessionManager.stopRanging(uwbSession.getSessionHandle());
2867         mTestLooper.dispatchNext();
2868 
2869         verify(mUwbSessionNotificationManager)
2870                 .onRangingStopFailed(eq(uwbSession), eq(UwbUciConstants.STATUS_CODE_FAILED));
2871         verify(mUwbMetrics, never()).longRangingStopEvent(eq(uwbSession));
2872     }
2873 
2874     @Test
reconfigure_notExistingSession()2875     public void reconfigure_notExistingSession() {
2876         int status = mUwbSessionManager.reconfigure(mock(SessionHandle.class), mock(Params.class));
2877 
2878         assertThat(status).isEqualTo(UwbUciConstants.STATUS_CODE_ERROR_SESSION_NOT_EXIST);
2879     }
2880 
buildReconfigureParams()2881     private FiraRangingReconfigureParams buildReconfigureParams() {
2882         return buildReconfigureParams(FiraParams.MULTICAST_LIST_UPDATE_ACTION_ADD);
2883     }
2884 
buildReconfigureParams(int action)2885     private FiraRangingReconfigureParams buildReconfigureParams(int action) {
2886         FiraRangingReconfigureParams reconfigureParams =
2887                 new FiraRangingReconfigureParams.Builder()
2888                         .setAddressList(new UwbAddress[] {
2889                                 UwbAddress.fromBytes(new byte[] { (byte) 0x01, (byte) 0x02 }) })
2890                         .setAction(action)
2891                         .setSubSessionIdList(new int[] { 2 })
2892                         .build();
2893 
2894         return spy(reconfigureParams);
2895     }
2896 
buildReconfigureParamsV2()2897     private FiraRangingReconfigureParams buildReconfigureParamsV2() {
2898         return buildReconfigureParamsV2(
2899                 FiraParams.P_STS_MULTICAST_LIST_UPDATE_ACTION_ADD_16_BYTE);
2900     }
2901 
buildReconfigureParamsV2(int action)2902     private FiraRangingReconfigureParams buildReconfigureParamsV2(int action) {
2903         FiraRangingReconfigureParams reconfigureParams =
2904                 new FiraRangingReconfigureParams.Builder()
2905                         .setAddressList(new UwbAddress[] {
2906                                 UwbAddress.fromBytes(new byte[] { (byte) 0x01, (byte) 0x02 }) })
2907                         .setAction(action)
2908                         .setSubSessionIdList(new int[] { 2 })
2909                         .setSubSessionKeyList(new byte[] {0, 0, 0, 0, 1, 1, 1, 1,
2910                                 2, 2, 2, 2, 3, 3, 3, 3})
2911                         .build();
2912 
2913         return spy(reconfigureParams);
2914     }
2915 
2916     @Test
reconfigure_existingSession()2917     public void reconfigure_existingSession() throws Exception {
2918         UwbSession uwbSession = prepareExistingUwbSession();
2919 
2920         int status = mUwbSessionManager.reconfigure(
2921                 uwbSession.getSessionHandle(), buildReconfigureParamsV2());
2922 
2923         assertThat(status).isEqualTo(0);
2924         assertThat(mTestLooper.nextMessage().what).isEqualTo(4); // SESSION_RECONFIGURE_RANGING
2925     }
2926 
2927     @Test
execReconfigureAddControlee_success()2928     public void execReconfigureAddControlee_success() throws Exception {
2929         UwbSession uwbSession = prepareExistingUwbSession();
2930         FiraRangingReconfigureParams reconfigureParams =
2931                 buildReconfigureParams();
2932         when(mNativeUwbManager
2933                 .controllerMulticastListUpdate(anyInt(), anyInt(), anyInt(), any(), any(),
2934                         any(), anyString()))
2935                 .thenReturn((byte) UwbUciConstants.STATUS_CODE_OK);
2936         UwbMulticastListUpdateStatus uwbMulticastListUpdateStatus =
2937                 mock(UwbMulticastListUpdateStatus.class);
2938         when(uwbMulticastListUpdateStatus.getNumOfControlee()).thenReturn(1);
2939         when(uwbMulticastListUpdateStatus.getControleeUwbAddresses())
2940                 .thenReturn(new UwbAddress[] {UWB_DEST_ADDRESS_2});
2941         when(uwbMulticastListUpdateStatus.getStatus()).thenReturn(
2942                 new int[] { UwbUciConstants.STATUS_CODE_OK });
2943         doReturn(uwbMulticastListUpdateStatus).when(uwbSession).getMulticastListUpdateStatus();
2944         when(mUwbConfigurationManager.setAppConfigurations(anyInt(), any(), anyString()))
2945                 .thenReturn(UwbUciConstants.STATUS_CODE_OK);
2946 
2947         mUwbSessionManager.reconfigure(uwbSession.getSessionHandle(), reconfigureParams);
2948         mTestLooper.dispatchNext();
2949 
2950         // Make sure the original address is still there.
2951         assertThat(uwbSession.getControleeList().stream()
2952                 .anyMatch(e -> e.getUwbAddress().equals(UWB_DEST_ADDRESS)))
2953                 .isTrue();
2954 
2955         // Make sure this new address was added.
2956         assertThat(uwbSession.getControleeList().stream()
2957                 .anyMatch(e -> e.getUwbAddress().equals(UWB_DEST_ADDRESS_2)))
2958                 .isTrue();
2959 
2960         byte[] dstAddress =
2961                 getComputedMacAddress(reconfigureParams.getAddressList()[0].toBytes());
2962         verify(mNativeUwbManager).controllerMulticastListUpdate(
2963                 uwbSession.getSessionId(), reconfigureParams.getAction(), 1,
2964                 dstAddress, reconfigureParams.getSubSessionIdList(), null,
2965                 uwbSession.getChipId());
2966         verify(mUwbSessionNotificationManager).onControleeAdded(eq(uwbSession));
2967         verify(mUwbSessionNotificationManager).onRangingReconfigured(eq(uwbSession));
2968     }
2969 
2970     @Test
execReconfigureRemoveControleeV1_success()2971     public void execReconfigureRemoveControleeV1_success() throws Exception {
2972         UwbSession uwbSession = prepareExistingUwbSession();
2973         FiraRangingReconfigureParams reconfigureParams =
2974                 buildReconfigureParams(FiraParams.MULTICAST_LIST_UPDATE_ACTION_DELETE);
2975         when(mNativeUwbManager
2976                 .controllerMulticastListUpdate(anyInt(), anyInt(), anyInt(), any(), any(),
2977                         any(), anyString()))
2978                 .thenReturn((byte) UwbUciConstants.STATUS_CODE_OK);
2979         UwbMulticastListUpdateStatus uwbMulticastListUpdateStatus =
2980                 mock(UwbMulticastListUpdateStatus.class);
2981         when(uwbMulticastListUpdateStatus.getNumOfControlee()).thenReturn(1);
2982         when(uwbMulticastListUpdateStatus.getControleeUwbAddresses())
2983                 .thenReturn(new UwbAddress[] {UWB_DEST_ADDRESS});
2984         when(uwbMulticastListUpdateStatus.getStatus()).thenReturn(
2985                 new int[] { UwbUciConstants.STATUS_CODE_OK });
2986         doReturn(uwbMulticastListUpdateStatus).when(uwbSession).getMulticastListUpdateStatus();
2987         when(mUwbConfigurationManager.setAppConfigurations(anyInt(), any(), anyString()))
2988                 .thenReturn(UwbUciConstants.STATUS_CODE_OK);
2989 
2990         // Make sure the address exists in the first place. This should have been set up by
2991         //  prepareExistingUwbSession
2992         assertThat(uwbSession.getControleeList().stream()
2993                 .anyMatch(e -> e.getUwbAddress().equals(UWB_DEST_ADDRESS)))
2994                 .isTrue();
2995 
2996         mUwbSessionManager.reconfigure(uwbSession.getSessionHandle(), reconfigureParams);
2997         mTestLooper.dispatchNext();
2998 
2999         // Make sure the address was removed.
3000         assertThat(uwbSession.getControleeList().stream()
3001                 .anyMatch(e -> e.getUwbAddress().equals(UWB_DEST_ADDRESS)))
3002                 .isFalse();
3003 
3004         byte[] dstAddress = getComputedMacAddress(reconfigureParams.getAddressList()[0].toBytes());
3005         verify(mNativeUwbManager).controllerMulticastListUpdate(
3006                 uwbSession.getSessionId(), reconfigureParams.getAction(), 1,
3007                 dstAddress, reconfigureParams.getSubSessionIdList(), null,
3008                 uwbSession.getChipId());
3009         verify(mUwbSessionNotificationManager).onControleeRemoved(eq(uwbSession));
3010         verify(mUwbSessionNotificationManager).onRangingReconfigured(eq(uwbSession));
3011     }
3012 
3013     @Test
execReconfigureAddControleeV2_success()3014     public void execReconfigureAddControleeV2_success() throws Exception {
3015         UwbSession uwbSession = prepareExistingUwbSession();
3016         FiraRangingReconfigureParams reconfigureParams =
3017                 buildReconfigureParamsV2();
3018         when(mNativeUwbManager
3019                 .controllerMulticastListUpdate(anyInt(), anyInt(), anyInt(), any(), any(),
3020                                 any(), anyString()))
3021                 .thenReturn((byte) UwbUciConstants.STATUS_CODE_OK);
3022         UwbMulticastListUpdateStatus uwbMulticastListUpdateStatus =
3023                 mock(UwbMulticastListUpdateStatus.class);
3024         when(uwbMulticastListUpdateStatus.getNumOfControlee()).thenReturn(1);
3025         when(uwbMulticastListUpdateStatus.getControleeUwbAddresses())
3026                 .thenReturn(new UwbAddress[] {UWB_DEST_ADDRESS_2});
3027         when(uwbMulticastListUpdateStatus.getStatus()).thenReturn(
3028                 new int[] { UwbUciConstants.STATUS_CODE_OK });
3029         doReturn(uwbMulticastListUpdateStatus).when(uwbSession).getMulticastListUpdateStatus();
3030         when(mUwbConfigurationManager.setAppConfigurations(anyInt(), any(), anyString()))
3031                 .thenReturn(UwbUciConstants.STATUS_CODE_OK);
3032 
3033         mUwbSessionManager.reconfigure(uwbSession.getSessionHandle(), reconfigureParams);
3034         mTestLooper.dispatchNext();
3035 
3036         // Make sure the original address is still there.
3037         assertThat(uwbSession.getControleeList().stream()
3038                 .anyMatch(e -> e.getUwbAddress().equals(UWB_DEST_ADDRESS)))
3039                 .isTrue();
3040 
3041         // Make sure this new address was added.
3042         assertThat(uwbSession.getControleeList().stream()
3043                 .anyMatch(e -> e.getUwbAddress().equals(UWB_DEST_ADDRESS_2)))
3044                 .isTrue();
3045 
3046         byte[] dstAddress = getComputedMacAddress(reconfigureParams.getAddressList()[0].toBytes());
3047         verify(mNativeUwbManager).controllerMulticastListUpdate(
3048                 uwbSession.getSessionId(), reconfigureParams.getAction(), 1,
3049                 dstAddress, reconfigureParams.getSubSessionIdList(),
3050                 reconfigureParams.getSubSessionKeyList(), uwbSession.getChipId());
3051         verify(mUwbSessionNotificationManager).onControleeAdded(eq(uwbSession));
3052         verify(mUwbSessionNotificationManager).onRangingReconfigured(eq(uwbSession));
3053     }
3054 
3055     @Test
execReconfigure_nativeUpdateFailed()3056     public void execReconfigure_nativeUpdateFailed() throws Exception {
3057         UwbSession uwbSession = prepareExistingUwbSession();
3058         FiraRangingReconfigureParams reconfigureParams =
3059                 buildReconfigureParamsV2();
3060         when(mNativeUwbManager
3061                 .controllerMulticastListUpdate(anyInt(), anyInt(), anyInt(), any(), any(),
3062                                 any(), anyString()))
3063                 .thenReturn((byte) UwbUciConstants.STATUS_CODE_FAILED);
3064 
3065         mUwbSessionManager.reconfigure(uwbSession.getSessionHandle(), reconfigureParams);
3066         mTestLooper.dispatchNext();
3067 
3068         verify(mUwbSessionNotificationManager).onControleeAddFailed(eq(uwbSession),
3069                 eq(UwbUciConstants.STATUS_CODE_FAILED));
3070         verify(mUwbSessionNotificationManager).onRangingReconfigureFailed(
3071                 eq(uwbSession), eq(UwbUciConstants.STATUS_CODE_FAILED));
3072     }
3073 
3074     @Test
execReconfigure_uwbSessionUpdateMixedSuccess()3075     public void execReconfigure_uwbSessionUpdateMixedSuccess() throws Exception {
3076         UwbSession uwbSession = prepareExistingUwbSession();
3077         FiraRangingReconfigureParams reconfigureParams =
3078                 buildReconfigureParamsV2();
3079         when(mNativeUwbManager
3080                 .controllerMulticastListUpdate(anyInt(), anyInt(), anyInt(), any(), any(),
3081                         any(), anyString()))
3082                 .thenReturn((byte) UwbUciConstants.STATUS_CODE_OK);
3083         UwbMulticastListUpdateStatus uwbMulticastListUpdateStatus =
3084                 mock(UwbMulticastListUpdateStatus.class);
3085         when(uwbMulticastListUpdateStatus.getNumOfControlee()).thenReturn(2);
3086         when(uwbMulticastListUpdateStatus.getControleeUwbAddresses()).thenReturn(
3087                 new UwbAddress[] { UWB_DEST_ADDRESS_2, UWB_DEST_ADDRESS_3 });
3088         // One fail, one success
3089         when(uwbMulticastListUpdateStatus.getStatus()).thenReturn(
3090                 new int[] { UwbUciConstants.STATUS_CODE_FAILED, UwbUciConstants.STATUS_CODE_OK });
3091         doReturn(uwbMulticastListUpdateStatus).when(uwbSession).getMulticastListUpdateStatus();
3092 
3093         mUwbSessionManager.reconfigure(uwbSession.getSessionHandle(), reconfigureParams);
3094         mTestLooper.dispatchNext();
3095 
3096         // Fail callback for the first one.
3097         verify(mUwbSessionNotificationManager).onControleeAddFailed(eq(uwbSession),
3098                 eq(UwbUciConstants.STATUS_CODE_FAILED));
3099         // Success callback for the second.
3100         verify(mUwbSessionNotificationManager).onControleeAdded(eq(uwbSession));
3101 
3102         // Make sure the failed address was not added.
3103         assertThat(uwbSession.getControleeList().stream()
3104                 .anyMatch(e -> e.getUwbAddress().equals(UWB_DEST_ADDRESS_2)))
3105                 .isFalse();
3106 
3107         // Overall reconfigure fail.
3108         verify(mUwbSessionNotificationManager).onRangingReconfigureFailed(
3109                 eq(uwbSession), eq(UwbUciConstants.STATUS_CODE_FAILED));
3110     }
3111 
3112     @Test
execReconfigure_uwbSessionUpdateFailed()3113     public void execReconfigure_uwbSessionUpdateFailed() throws Exception {
3114         UwbSession uwbSession = prepareExistingUwbSession();
3115         FiraRangingReconfigureParams reconfigureParams =
3116                 buildReconfigureParamsV2();
3117         when(mNativeUwbManager
3118                 .controllerMulticastListUpdate(anyInt(), anyInt(), anyInt(), any(), any(),
3119                                 any(), anyString()))
3120                 .thenReturn((byte) UwbUciConstants.STATUS_CODE_OK);
3121         UwbMulticastListUpdateStatus uwbMulticastListUpdateStatus =
3122                 mock(UwbMulticastListUpdateStatus.class);
3123         when(uwbMulticastListUpdateStatus.getNumOfControlee()).thenReturn(1);
3124         when(uwbMulticastListUpdateStatus.getStatus()).thenReturn(
3125                 new int[] { UwbUciConstants.STATUS_CODE_FAILED });
3126         doReturn(uwbMulticastListUpdateStatus).when(uwbSession).getMulticastListUpdateStatus();
3127 
3128         mUwbSessionManager.reconfigure(uwbSession.getSessionHandle(), reconfigureParams);
3129         mTestLooper.dispatchNext();
3130 
3131         verify(mUwbSessionNotificationManager).onControleeAddFailed(eq(uwbSession),
3132                 eq(UwbUciConstants.STATUS_CODE_FAILED));
3133         verify(mUwbSessionNotificationManager).onRangingReconfigureFailed(
3134                 eq(uwbSession), eq(UwbUciConstants.STATUS_CODE_FAILED));
3135     }
3136 
3137     @Test
execReconfigureBlockStriding_success_stop()3138     public void execReconfigureBlockStriding_success_stop() throws Exception {
3139         UwbSession uwbSession = prepareExistingUwbSession();
3140         FiraRangingReconfigureParams reconfigureParams =
3141                 new FiraRangingReconfigureParams.Builder()
3142                         .setBlockStrideLength(10)
3143                         .build();
3144         when(mUwbConfigurationManager.setAppConfigurations(anyInt(), any(), anyString()))
3145                 .thenReturn(UwbUciConstants.STATUS_CODE_OK);
3146 
3147         mUwbSessionManager.reconfigure(uwbSession.getSessionHandle(), reconfigureParams);
3148         mTestLooper.dispatchNext();
3149 
3150         verify(mUwbSessionNotificationManager).onRangingReconfigured(uwbSession);
3151 
3152         doReturn(UwbUciConstants.UWB_SESSION_STATE_ACTIVE, UwbUciConstants.UWB_SESSION_STATE_IDLE)
3153                 .when(uwbSession).getSessionState();
3154         when(mNativeUwbManager.stopRanging(eq(TEST_SESSION_ID), anyString()))
3155                 .thenReturn((byte) UwbUciConstants.STATUS_CODE_OK);
3156 
3157         mUwbSessionManager.stopRanging(uwbSession.getSessionHandle());
3158         mTestLooper.dispatchNext();
3159 
3160         verify(mUwbInjector).runTaskOnSingleThreadExecutor(
3161                 any(), eq(TEST_RANGING_INTERVAL_MS * 4 * 11));
3162         verify(mUwbSessionNotificationManager)
3163                 .onRangingStoppedWithApiReasonCode(eq(uwbSession),
3164                         eq(RangingChangeReason.LOCAL_API));
3165         verify(mUwbMetrics).longRangingStopEvent(eq(uwbSession));
3166     }
3167 
3168     @Test
execReconfigure_setAppConfigurationsFailed()3169     public void execReconfigure_setAppConfigurationsFailed() throws Exception {
3170         UwbSession uwbSession = prepareExistingUwbSession();
3171         FiraRangingReconfigureParams reconfigureParams =
3172                 buildReconfigureParamsV2();
3173         when(mNativeUwbManager
3174                 .controllerMulticastListUpdate(anyInt(), anyInt(), anyInt(), any(), any(),
3175                                 any(), anyString()))
3176                 .thenReturn((byte) UwbUciConstants.STATUS_CODE_FAILED);
3177         UwbMulticastListUpdateStatus uwbMulticastListUpdateStatus =
3178                 mock(UwbMulticastListUpdateStatus.class);
3179         when(uwbMulticastListUpdateStatus.getStatus()).thenReturn(
3180                 new int[] { UwbUciConstants.STATUS_CODE_OK });
3181         doReturn(uwbMulticastListUpdateStatus).when(uwbSession).getMulticastListUpdateStatus();
3182         when(mUwbConfigurationManager.setAppConfigurations(anyInt(), any(), anyString()))
3183                 .thenReturn(UwbUciConstants.STATUS_CODE_FAILED);
3184 
3185         mUwbSessionManager.reconfigure(uwbSession.getSessionHandle(), reconfigureParams);
3186         mTestLooper.dispatchNext();
3187 
3188         verify(mUwbSessionNotificationManager).onRangingReconfigureFailed(
3189                 eq(uwbSession), eq(UwbUciConstants.STATUS_CODE_FAILED));
3190     }
3191 
3192     @Test
testQueryDataSize()3193     public void testQueryDataSize() throws Exception {
3194         UwbSession uwbSession = prepareExistingUwbSession();
3195 
3196         when(mNativeUwbManager.queryMaxDataSizeBytes(
3197                 eq(uwbSession.getSessionId()), eq(TEST_CHIP_ID)))
3198                 .thenReturn(MAX_DATA_SIZE);
3199         assertThat(mUwbSessionManager.queryMaxDataSizeBytes(uwbSession.getSessionHandle()))
3200                 .isEqualTo(MAX_DATA_SIZE);
3201     }
3202 
3203     @Test
testQueryDataSize_whenUwbSessionDoesNotExist()3204     public void testQueryDataSize_whenUwbSessionDoesNotExist() throws Exception {
3205         SessionHandle mockSessionHandle = mock(SessionHandle.class);
3206         assertThrows(IllegalStateException.class,
3207                 () -> mUwbSessionManager.queryMaxDataSizeBytes(mockSessionHandle));
3208     }
3209 
3210     @Test
deInitSession_notExistedSession()3211     public void deInitSession_notExistedSession() {
3212         doReturn(false).when(mUwbSessionManager).isExistedSession(any());
3213 
3214         mUwbSessionManager.deInitSession(mock(SessionHandle.class));
3215 
3216         verify(mUwbSessionManager, never()).getSessionId(any());
3217         assertThat(mTestLooper.nextMessage()).isNull();
3218     }
3219 
3220     @Test
deInitSession_success()3221     public void deInitSession_success() {
3222         doReturn(true).when(mUwbSessionManager).isExistedSession(any());
3223         doReturn(TEST_SESSION_ID).when(mUwbSessionManager).getSessionId(any());
3224 
3225         mUwbSessionManager.deInitSession(mock(SessionHandle.class));
3226 
3227         verify(mUwbSessionManager).getUwbSession(eq(TEST_SESSION_ID));
3228         assertThat(mTestLooper.nextMessage().what).isEqualTo(5); // SESSION_DEINIT
3229 
3230         verifyZeroInteractions(mUwbAdvertiseManager);
3231     }
3232 
3233     @Test
deInitSession_success_afterOwrAoaMeasurement()3234     public void deInitSession_success_afterOwrAoaMeasurement() {
3235         UwbSession mockUwbSession = mock(UwbSession.class);
3236         when(mockUwbSession.getWaitObj()).thenReturn(mock(WaitObj.class));
3237         when(mockUwbSession.getSessionHandle()).thenReturn(mock(SessionHandle.class));
3238         doReturn(mockUwbSession).when(mUwbSessionManager).getUwbSession(eq(TEST_SESSION_ID));
3239 
3240         // Setup the UwbSession to have the peer device's MacAddress stored (which happens when
3241         // a valid RANGE_DATA_NTF with an OWR AoA Measurement is received).
3242         doReturn(Set.of(PEER_EXTENDED_MAC_ADDRESS_LONG)).when(mockUwbSession)
3243                 .getRemoteMacAddressList();
3244 
3245         // Call deInitSession().
3246         IBinder mockBinder = mock(IBinder.class);
3247         doReturn(mockBinder).when(mockUwbSession).getBinder();
3248         doReturn(FiraParams.PROTOCOL_NAME).when(mockUwbSession).getProtocolName();
3249         doReturn(null).when(mockUwbSession).getAnyNonPrivilegedAppInAttributionSource();
3250         doReturn(true).when(mUwbSessionManager).isExistedSession(any());
3251         doReturn(TEST_SESSION_ID).when(mUwbSessionManager).getSessionId(any());
3252         mUwbSessionManager.deInitSession(mock(SessionHandle.class));
3253 
3254         mTestLooper.dispatchNext();
3255 
3256         verify(mUwbAdvertiseManager).removeAdvertiseTarget(PEER_EXTENDED_MAC_ADDRESS_LONG);
3257     }
3258 
3259     @Test
execDeInitSession()3260     public void execDeInitSession() throws Exception {
3261         UwbSession uwbSession = prepareExistingUwbSession();
3262 
3263         mUwbSessionManager.deInitSession(uwbSession.getSessionHandle());
3264 
3265         assertThat(mTestLooper.nextMessage().what).isEqualTo(5); // SESSION_DEINIT
3266     }
3267 
3268     @Test
execDeInitSession_success()3269     public void execDeInitSession_success() throws Exception {
3270         UwbSession uwbSession = prepareExistingUwbSession();
3271         when(mNativeUwbManager.deInitSession(eq(TEST_SESSION_ID), anyString()))
3272                 .thenReturn((byte) UwbUciConstants.STATUS_CODE_OK);
3273 
3274         mUwbSessionManager.deInitSession(uwbSession.getSessionHandle());
3275         mTestLooper.dispatchNext();
3276 
3277         verify(mUwbSessionNotificationManager).onRangingClosed(
3278                 eq(uwbSession), eq(UwbUciConstants.STATUS_CODE_OK));
3279         verify(mUwbMetrics).logRangingCloseEvent(
3280                 eq(uwbSession), eq(UwbUciConstants.STATUS_CODE_OK));
3281         assertThat(mUwbSessionManager.getSessionCount()).isEqualTo(0);
3282         assertThat(mUwbSessionManager.getCccSessionCount()).isEqualTo(0L);
3283         assertThat(mUwbSessionManager.getFiraSessionCount()).isEqualTo(0L);
3284         verifyZeroInteractions(mUwbAdvertiseManager);
3285     }
3286 
3287     @Test
execDeInitSession_failed()3288     public void execDeInitSession_failed() throws Exception {
3289         UwbSession uwbSession = prepareExistingUwbSession();
3290         when(mNativeUwbManager.deInitSession(eq(TEST_SESSION_ID), anyString()))
3291                 .thenReturn((byte) UwbUciConstants.STATUS_CODE_FAILED);
3292 
3293         mUwbSessionManager.deInitSession(uwbSession.getSessionHandle());
3294         mTestLooper.dispatchNext();
3295 
3296         verify(mUwbSessionNotificationManager).onRangingClosed(
3297                 eq(uwbSession), eq(UwbUciConstants.STATUS_CODE_FAILED));
3298         verify(mUwbAdvertiseManager, never()).removeAdvertiseTarget(isA(Long.class));
3299         verify(mUwbMetrics).logRangingCloseEvent(
3300                 eq(uwbSession), eq(UwbUciConstants.STATUS_CODE_FAILED));
3301         assertThat(mUwbSessionManager.getSessionCount()).isEqualTo(0);
3302         assertThat(mUwbSessionManager.getCccSessionCount()).isEqualTo(0L);
3303         assertThat(mUwbSessionManager.getFiraSessionCount()).isEqualTo(0L);
3304         verifyZeroInteractions(mUwbAdvertiseManager);
3305     }
3306 
3307     @Test
deinitAllSession()3308     public void deinitAllSession() {
3309         UwbSession mockUwbSession1 = mock(UwbSession.class);
3310         SessionHandle mockSessionHandle1 = mock(SessionHandle.class);
3311         when(mockUwbSession1.getSessionId()).thenReturn(TEST_SESSION_ID);
3312         when(mockUwbSession1.getBinder()).thenReturn(mock(IBinder.class));
3313         when(mockUwbSession1.getSessionId()).thenReturn(TEST_SESSION_ID);
3314         when(mockUwbSession1.getProtocolName()).thenReturn(FiraParams.PROTOCOL_NAME);
3315         when(mockUwbSession1.getSessionHandle()).thenReturn(mockSessionHandle1);
3316         mUwbSessionManager.mSessionTable.put(mockSessionHandle1, mockUwbSession1);
3317 
3318         UwbSession mockUwbSession2 = mock(UwbSession.class);
3319         SessionHandle mockSessionHandle2 = mock(SessionHandle.class);
3320         when(mockUwbSession2.getBinder()).thenReturn(mock(IBinder.class));
3321         when(mockUwbSession2.getSessionId()).thenReturn(TEST_SESSION_ID + 100);
3322         when(mockUwbSession2.getProtocolName()).thenReturn(FiraParams.PROTOCOL_NAME);
3323         when(mockUwbSession2.getSessionHandle()).thenReturn(mockSessionHandle2);
3324         mUwbSessionManager.mSessionTable.put(mockSessionHandle2, mockUwbSession2);
3325 
3326         mUwbSessionManager.deinitAllSession();
3327 
3328         verify(mUwbSessionNotificationManager, times(2))
3329                 .onRangingClosedWithApiReasonCode(any(), eq(RangingChangeReason.SYSTEM_POLICY));
3330         verify(mUwbSessionManager, times(2)).removeSession(any());
3331         // TODO: enable it when the deviceReset is enabled.
3332         // verify(mNativeUwbManager).deviceReset(eq(UwbUciConstants.UWBS_RESET));
3333         assertThat(mUwbSessionManager.getSessionCount()).isEqualTo(0);
3334         assertThat(mUwbSessionManager.getCccSessionCount()).isEqualTo(0L);
3335         assertThat(mUwbSessionManager.getFiraSessionCount()).isEqualTo(0L);
3336     }
3337 
3338     @Test
onSessionStatusNotification_session_deinit()3339     public void onSessionStatusNotification_session_deinit() throws Exception {
3340         UwbSession uwbSession = prepareExistingUwbSession();
3341         when(mNativeUwbManager.deInitSession(eq(TEST_SESSION_ID), anyString()))
3342                 .thenReturn((byte) UwbUciConstants.STATUS_CODE_OK);
3343 
3344         mUwbSessionManager.onSessionStatusNotificationReceived(
3345                 uwbSession.getSessionId(), UwbUciConstants.UWB_SESSION_STATE_DEINIT,
3346                 UwbUciConstants.REASON_STATE_CHANGE_WITH_SESSION_MANAGEMENT_COMMANDS);
3347         mTestLooper.dispatchNext();
3348 
3349         verify(mUwbSessionNotificationManager).onRangingClosedWithApiReasonCode(
3350                 eq(uwbSession), eq(RangingChangeReason.SYSTEM_POLICY));
3351         verify(mUwbMetrics).logRangingCloseEvent(
3352                 eq(uwbSession), eq(UwbUciConstants.STATUS_CODE_OK));
3353         assertThat(mUwbSessionManager.getSessionCount()).isEqualTo(0);
3354         assertThat(mUwbSessionManager.getCccSessionCount()).isEqualTo(0L);
3355         assertThat(mUwbSessionManager.getFiraSessionCount()).isEqualTo(0L);
3356     }
3357 
3358     @Test
onSessionStatusNotification_session_deinit_after_close()3359     public void onSessionStatusNotification_session_deinit_after_close() throws Exception {
3360         UwbSession uwbSession = prepareExistingUwbSession();
3361         when(mNativeUwbManager.deInitSession(eq(TEST_SESSION_ID), anyString()))
3362                 .thenReturn((byte) UwbUciConstants.STATUS_CODE_OK);
3363 
3364         mUwbSessionManager.deinitAllSession();
3365         verify(mUwbSessionNotificationManager).onRangingClosedWithApiReasonCode(
3366                 eq(uwbSession), eq(RangingChangeReason.SYSTEM_POLICY));
3367         verify(mUwbMetrics).logRangingCloseEvent(
3368                 eq(uwbSession), eq(UwbUciConstants.STATUS_CODE_OK));
3369         assertThat(mUwbSessionManager.getSessionCount()).isEqualTo(0);
3370         assertThat(mUwbSessionManager.getCccSessionCount()).isEqualTo(0L);
3371         assertThat(mUwbSessionManager.getFiraSessionCount()).isEqualTo(0L);
3372 
3373         // Ignore the stale deinit
3374         mUwbSessionManager.handleOnDeInit(uwbSession);
3375         verifyNoMoreInteractions(mUwbSessionNotificationManager);
3376     }
3377 
3378     @Test
onSessionStatusNotification_session_deinit_owrAoa()3379     public void onSessionStatusNotification_session_deinit_owrAoa() throws Exception {
3380         Params firaParams = setupFiraParams(
3381                 RANGING_DEVICE_ROLE_OBSERVER, Optional.of(ROUND_USAGE_OWR_AOA_MEASUREMENT));
3382         UwbSession uwbSession = prepareExistingUwbSession(firaParams);
3383 
3384         UwbRangingData uwbRangingData = UwbTestUtils.generateRangingData(
3385                 RANGING_MEASUREMENT_TYPE_OWR_AOA, MAC_ADDRESSING_MODE_EXTENDED,
3386                 UwbUciConstants.STATUS_CODE_OK);
3387 
3388         // First call onDataReceived() to get the application payload data.
3389         when(mDeviceConfigFacade.getRxDataMaxPacketsToStore())
3390                 .thenReturn(MAX_RX_DATA_PACKETS_TO_STORE);
3391         mUwbSessionManager.onDataReceived(TEST_SESSION_ID, UwbUciConstants.STATUS_CODE_OK,
3392                 DATA_SEQUENCE_NUM, PEER_EXTENDED_MAC_ADDRESS, SOURCE_END_POINT, DEST_END_POINT,
3393                 DATA_PAYLOAD);
3394 
3395         // Next call onRangeDataNotificationReceived() to process the RANGE_DATA_NTF. Setup
3396         // isPointedTarget() to return "false", as in that scenario the stored AdvertiseTarget
3397         // is not removed.
3398         when(mUwbAdvertiseManager.isPointedTarget(PEER_EXTENDED_MAC_ADDRESS)).thenReturn(false);
3399         mUwbSessionManager.onRangeDataNotificationReceived(uwbRangingData);
3400 
3401         verify(mUwbAdvertiseManager).updateAdvertiseTarget(uwbRangingData.mRangingOwrAoaMeasure);
3402         verify(mUwbAdvertiseManager).isPointedTarget(PEER_EXTENDED_MAC_ADDRESS);
3403 
3404         // Now call onSessionStatusNotificationReceived() on the same UwbSession, and verify that
3405         // removeAdvertiseTarget() is called to remove any stored OwR AoA Measurement(s).
3406         when(mNativeUwbManager.deInitSession(eq(TEST_SESSION_ID), anyString()))
3407                 .thenReturn((byte) UwbUciConstants.STATUS_CODE_OK);
3408 
3409         mUwbSessionManager.onSessionStatusNotificationReceived(
3410                 uwbSession.getSessionId(), UwbUciConstants.UWB_SESSION_STATE_DEINIT,
3411                 UwbUciConstants.REASON_STATE_CHANGE_WITH_SESSION_MANAGEMENT_COMMANDS);
3412         mTestLooper.dispatchNext();
3413 
3414         verify(mUwbSessionNotificationManager).onRangingClosedWithApiReasonCode(
3415                 eq(uwbSession), eq(RangingChangeReason.SYSTEM_POLICY));
3416         verify(mUwbMetrics).logRangingCloseEvent(
3417                 eq(uwbSession), eq(UwbUciConstants.STATUS_CODE_OK));
3418         assertThat(mUwbSessionManager.getSessionCount()).isEqualTo(0);
3419         assertThat(mUwbSessionManager.getCccSessionCount()).isEqualTo(0L);
3420         assertThat(mUwbSessionManager.getFiraSessionCount()).isEqualTo(0L);
3421 
3422         verify(mUwbAdvertiseManager).removeAdvertiseTarget(isA(Long.class));
3423     }
3424 
3425     @Test
testHandleClientDeath()3426     public void testHandleClientDeath() throws Exception {
3427         UwbSession uwbSession = prepareExistingUwbSession();
3428         when(mNativeUwbManager.deInitSession(eq(TEST_SESSION_ID), anyString()))
3429                 .thenReturn((byte) UwbUciConstants.STATUS_CODE_FAILED);
3430 
3431         uwbSession.binderDied();
3432 
3433         verify(mUwbMetrics).logRangingCloseEvent(
3434                 eq(uwbSession), eq(UwbUciConstants.STATUS_CODE_FAILED));
3435         assertThat(mUwbSessionManager.getSessionCount()).isEqualTo(0);
3436         assertThat(mUwbSessionManager.getCccSessionCount()).isEqualTo(0L);
3437         assertThat(mUwbSessionManager.getFiraSessionCount()).isEqualTo(0L);
3438     }
3439 
3440     @Test
testDtTagRangingRoundsUpdate()3441     public void testDtTagRangingRoundsUpdate() throws Exception {
3442         UwbSession uwbSession = prepareExistingUwbSession();
3443         byte[] indices = {1, 2};
3444         DtTagUpdateRangingRoundsStatus status = new DtTagUpdateRangingRoundsStatus(0,
3445                 indices.length, indices);
3446         PersistableBundle bundle = new DlTDoARangingRoundsUpdate.Builder()
3447                 .setSessionId(uwbSession.getSessionId())
3448                 .setNoOfRangingRounds(indices.length)
3449                 .setRangingRoundIndexes(indices)
3450                 .build()
3451                 .toBundle();
3452 
3453         when(mNativeUwbManager.sessionUpdateDtTagRangingRounds(anyInt(), anyInt(), any(),
3454                 anyString())).thenReturn(status);
3455 
3456         mUwbSessionManager.rangingRoundsUpdateDtTag(uwbSession.getSessionHandle(), bundle);
3457         mTestLooper.dispatchAll();
3458 
3459         verify(mNativeUwbManager).sessionUpdateDtTagRangingRounds(uwbSession.getSessionId(),
3460                 indices.length, indices, uwbSession.getChipId());
3461         verify(mUwbSessionNotificationManager).onRangingRoundsUpdateStatus(any(), any());
3462     }
3463 
buildReceivedDataInfo(long macAddress)3464     private UwbSessionManager.ReceivedDataInfo buildReceivedDataInfo(long macAddress) {
3465         return buildReceivedDataInfo(macAddress, DATA_SEQUENCE_NUM);
3466     }
3467 
buildReceivedDataInfo( long macAddress, long sequenceNum)3468     private UwbSessionManager.ReceivedDataInfo buildReceivedDataInfo(
3469             long macAddress, long sequenceNum) {
3470         UwbSessionManager.ReceivedDataInfo info = new UwbSessionManager.ReceivedDataInfo();
3471         info.sessionId = TEST_SESSION_ID;
3472         info.status = STATUS_CODE_OK;
3473         info.sequenceNum = sequenceNum;
3474         info.address = macAddress;
3475         info.sourceEndPoint = SOURCE_END_POINT;
3476         info.destEndPoint = DEST_END_POINT;
3477         info.payload = DATA_PAYLOAD;
3478         return info;
3479     }
3480 
getComputedMacAddress(byte[] address)3481     private static byte[] getComputedMacAddress(byte[] address) {
3482         if (!SdkLevel.isAtLeastU()) {
3483             return TlvUtil.getReverseBytes(address);
3484         }
3485         return address;
3486     }
3487 }
3488