1 /*
2  * Copyright (C) 2023 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package com.android.server.remoteauth.ranging;
18 
19 import static android.content.pm.PackageManager.FEATURE_UWB;
20 import static android.uwb.UwbManager.AdapterStateCallback.STATE_ENABLED_INACTIVE;
21 
22 import static androidx.core.uwb.backend.impl.internal.RangingCapabilities.FIRA_DEFAULT_SUPPORTED_CONFIG_IDS;
23 import static androidx.core.uwb.backend.impl.internal.Utils.CONFIG_PROVISIONED_INDIVIDUAL_MULTICAST_DS_TWR;
24 import static androidx.core.uwb.backend.impl.internal.Utils.CONFIG_PROVISIONED_MULTICAST_DS_TWR;
25 import static androidx.core.uwb.backend.impl.internal.Utils.CONFIG_PROVISIONED_UNICAST_DS_TWR;
26 import static androidx.core.uwb.backend.impl.internal.Utils.CONFIG_PROVISIONED_UNICAST_DS_TWR_NO_AOA;
27 
28 import static com.android.server.remoteauth.ranging.RangingCapabilities.RANGING_METHOD_UWB;
29 import static com.android.server.remoteauth.ranging.SessionParameters.DEVICE_ROLE_INITIATOR;
30 
31 import static org.junit.Assert.assertArrayEquals;
32 import static org.junit.Assert.assertEquals;
33 import static org.junit.Assert.assertNotNull;
34 import static org.junit.Assert.assertNull;
35 import static org.junit.Assert.assertThrows;
36 import static org.mockito.ArgumentMatchers.any;
37 import static org.mockito.Mockito.times;
38 import static org.mockito.Mockito.verify;
39 import static org.mockito.Mockito.verifyZeroInteractions;
40 import static org.mockito.Mockito.when;
41 
42 import android.content.Context;
43 import android.content.pm.PackageManager;
44 import android.uwb.UwbManager;
45 
46 import androidx.test.ext.junit.runners.AndroidJUnit4;
47 
48 import com.android.server.remoteauth.ranging.RangingCapabilities.RangingMethod;
49 import com.android.server.remoteauth.ranging.SessionParameters.DeviceRole;
50 
51 import com.google.uwb.support.fira.FiraParams;
52 import com.google.uwb.support.fira.FiraSpecificationParams;
53 import com.google.uwb.support.generic.GenericSpecificationParams;
54 
55 import org.junit.Before;
56 import org.junit.Test;
57 import org.junit.runner.RunWith;
58 import org.mockito.Mock;
59 import org.mockito.MockitoAnnotations;
60 
61 import java.util.ArrayList;
62 import java.util.EnumSet;
63 import java.util.List;
64 
65 /** Unit test for {@link RangingManager}. */
66 @RunWith(AndroidJUnit4.class)
67 public class RangingManagerTest {
68     private static final List<Integer> TEST_UWB_SUPPORTED_CHANNELS = List.of(8, 9);
69     private static final FiraSpecificationParams TEST_FIRA_SPEC =
70             new FiraSpecificationParams.Builder()
71                     .setSupportedChannels(TEST_UWB_SUPPORTED_CHANNELS)
72                     .setStsCapabilities(EnumSet.allOf(FiraParams.StsCapabilityFlag.class))
73                     .build();
74     private static final GenericSpecificationParams TEST_GENERIC_SPEC =
75             new GenericSpecificationParams.Builder()
76                     .setFiraSpecificationParams(TEST_FIRA_SPEC)
77                     .build();
78     private static final String TEST_DEVICE_ID = "test_device_id";
79     @RangingMethod private static final int TEST_RANGING_METHOD = RANGING_METHOD_UWB;
80     @DeviceRole private static final int TEST_DEVICE_ROLE = DEVICE_ROLE_INITIATOR;
81     private static final float TEST_LOWER_PROXIMITY_BOUNDARY_M = 1.0f;
82     private static final float TEST_UPPER_PROXIMITY_BOUNDARY_M = 2.5f;
83     private static final boolean TEST_AUTO_DERIVE_PARAMS = true;
84     private static final byte[] TEST_BASE_KEY =
85             new byte[] {
86                 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d,
87                 0x0e, 0x0f
88             };
89     private static final byte[] TEST_SYNC_DATA =
90             new byte[] {
91                 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e,
92                 0x0f, 0x00
93             };
94     private static final SessionParameters TEST_SESSION_PARAMETER =
95             new SessionParameters.Builder()
96                     .setDeviceId(TEST_DEVICE_ID)
97                     .setRangingMethod(TEST_RANGING_METHOD)
98                     .setDeviceRole(TEST_DEVICE_ROLE)
99                     .setLowerProximityBoundaryM(TEST_LOWER_PROXIMITY_BOUNDARY_M)
100                     .setUpperProximityBoundaryM(TEST_UPPER_PROXIMITY_BOUNDARY_M)
101                     .setAutoDeriveParams(TEST_AUTO_DERIVE_PARAMS)
102                     .setBaseKey(TEST_BASE_KEY)
103                     .setSyncData(TEST_SYNC_DATA)
104                     .build();
105 
106     @Mock private Context mContext;
107     @Mock private PackageManager mPackageManager;
108     @Mock private UwbManager mUwbManager;
109 
110     private RangingManager mRangingManager;
111 
112     @Before
setUp()113     public void setUp() throws Exception {
114         MockitoAnnotations.initMocks(this);
115 
116         when(mContext.getSystemService(UwbManager.class)).thenReturn(mUwbManager);
117         when(mContext.getPackageManager()).thenReturn(mPackageManager);
118         when(mPackageManager.hasSystemFeature(FEATURE_UWB)).thenReturn(false);
119         when(mUwbManager.getAdapterState()).thenReturn(STATE_ENABLED_INACTIVE);
120         when(mUwbManager.getSpecificationInfo()).thenReturn(TEST_GENERIC_SPEC.toBundle());
121     }
122 
123     @Test
testConstruction()124     public void testConstruction() {
125         mRangingManager = new RangingManager(mContext);
126         verifyZeroInteractions(mUwbManager);
127     }
128 
129     @Test
testConstruction_withUwbEnabled()130     public void testConstruction_withUwbEnabled() {
131         when(mPackageManager.hasSystemFeature(FEATURE_UWB)).thenReturn(true);
132 
133         mRangingManager = new RangingManager(mContext);
134 
135         verify(mUwbManager).getAdapterState();
136         verify(mUwbManager).registerAdapterStateCallback(any(), any());
137     }
138 
139     @Test
testShutdown_withUwbEnabled()140     public void testShutdown_withUwbEnabled() {
141         when(mPackageManager.hasSystemFeature(FEATURE_UWB)).thenReturn(true);
142 
143         mRangingManager = new RangingManager(mContext);
144         mRangingManager.shutdown();
145 
146         verify(mUwbManager).registerAdapterStateCallback(any(), any());
147         verify(mUwbManager).unregisterAdapterStateCallback(any());
148     }
149 
150     @Test
testGetRangingCapabilities()151     public void testGetRangingCapabilities() {
152         mRangingManager = new RangingManager(mContext);
153         RangingCapabilities capabilities = mRangingManager.getRangingCapabilities();
154 
155         assertEquals(capabilities.getSupportedRangingMethods().size(), 0);
156         assertEquals(capabilities.getUwbRangingCapabilities(), null);
157     }
158 
159     @Test
testGetRangingCapabilities_withUwbEnabled()160     public void testGetRangingCapabilities_withUwbEnabled() {
161         when(mPackageManager.hasSystemFeature(FEATURE_UWB)).thenReturn(true);
162 
163         mRangingManager = new RangingManager(mContext);
164         RangingCapabilities capabilities = mRangingManager.getRangingCapabilities();
165 
166         List<Integer> supportedConfigIds = new ArrayList<>(FIRA_DEFAULT_SUPPORTED_CONFIG_IDS);
167         supportedConfigIds.add(CONFIG_PROVISIONED_UNICAST_DS_TWR);
168         supportedConfigIds.add(CONFIG_PROVISIONED_MULTICAST_DS_TWR);
169         supportedConfigIds.add(CONFIG_PROVISIONED_UNICAST_DS_TWR_NO_AOA);
170         supportedConfigIds.add(CONFIG_PROVISIONED_INDIVIDUAL_MULTICAST_DS_TWR);
171 
172         verify(mUwbManager, times(1)).getSpecificationInfo();
173         assertEquals(capabilities.getSupportedRangingMethods().size(), 1);
174         assertEquals((int) capabilities.getSupportedRangingMethods().get(0), RANGING_METHOD_UWB);
175         androidx.core.uwb.backend.impl.internal.RangingCapabilities uwbCapabilities =
176                 capabilities.getUwbRangingCapabilities();
177         assertNotNull(uwbCapabilities);
178         assertArrayEquals(
179                 uwbCapabilities.getSupportedChannels().toArray(),
180                 TEST_UWB_SUPPORTED_CHANNELS.toArray());
181         assertArrayEquals(
182                 uwbCapabilities.getSupportedConfigIds().toArray(), supportedConfigIds.toArray());
183     }
184 
185     @Test
testGetRangingCapabilities_multipleCalls()186     public void testGetRangingCapabilities_multipleCalls() {
187         when(mPackageManager.hasSystemFeature(FEATURE_UWB)).thenReturn(true);
188 
189         mRangingManager = new RangingManager(mContext);
190         RangingCapabilities capabilities1 = mRangingManager.getRangingCapabilities();
191         RangingCapabilities capabilities2 = mRangingManager.getRangingCapabilities();
192         RangingCapabilities capabilities3 = mRangingManager.getRangingCapabilities();
193 
194         verify(mUwbManager, times(1)).getSpecificationInfo();
195         assertEquals(capabilities1, capabilities2);
196         assertEquals(capabilities2, capabilities3);
197     }
198 
199     @Test
testCreateSession_nullSessionParameters()200     public void testCreateSession_nullSessionParameters() {
201         mRangingManager = new RangingManager(mContext);
202 
203         assertThrows(NullPointerException.class, () -> mRangingManager.createSession(null));
204     }
205 
206     @Test
testCreateSession_uwbSessionWithUwbDisabled()207     public void testCreateSession_uwbSessionWithUwbDisabled() {
208         mRangingManager = new RangingManager(mContext);
209 
210         assertNull(mRangingManager.createSession(TEST_SESSION_PARAMETER));
211     }
212 
213     @Test
testCreateSession_uwbSession()214     public void testCreateSession_uwbSession() {
215         when(mPackageManager.hasSystemFeature(FEATURE_UWB)).thenReturn(true);
216         mRangingManager = new RangingManager(mContext);
217 
218         assertNotNull(mRangingManager.createSession(TEST_SESSION_PARAMETER));
219     }
220 }
221