1 /* 2 * Copyright 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 android.uwb; 18 19 import static android.uwb.UwbManager.MESSAGE_TYPE_COMMAND; 20 21 import static com.google.common.truth.Truth.assertThat; 22 23 import static org.junit.Assert.assertThrows; 24 import static org.mockito.ArgumentMatchers.any; 25 import static org.mockito.ArgumentMatchers.eq; 26 import static org.mockito.Mockito.doThrow; 27 import static org.mockito.Mockito.mock; 28 import static org.mockito.Mockito.never; 29 import static org.mockito.Mockito.times; 30 import static org.mockito.Mockito.verify; 31 import static org.mockito.Mockito.when; 32 33 import android.content.AttributionSource; 34 import android.content.Context; 35 import android.os.PersistableBundle; 36 import android.os.RemoteException; 37 import android.uwb.UwbManager.AdapterStateCallback; 38 import android.uwb.UwbManager.AdfProvisionStateCallback; 39 import android.uwb.UwbManager.UwbVendorUciCallback; 40 41 import androidx.test.ext.junit.runners.AndroidJUnit4; 42 import androidx.test.filters.SmallTest; 43 44 import org.junit.Before; 45 import org.junit.Test; 46 import org.junit.runner.RunWith; 47 import org.mockito.Mock; 48 import org.mockito.MockitoAnnotations; 49 50 import java.util.List; 51 import java.util.concurrent.Executor; 52 import java.util.function.Consumer; 53 54 /** 55 * Test of {@link UwbManager}. 56 */ 57 @SmallTest 58 @RunWith(AndroidJUnit4.class) 59 public class UwbManagerTest { 60 61 @Mock private Context mContext; 62 @Mock private IUwbAdapter mIUwbAdapter; 63 @Mock private AdapterStateCallback mAdapterStateCallback; 64 @Mock private AdapterStateCallback mAdapterStateCallback2; 65 @Mock private UwbVendorUciCallback mUwbVendorUciCallback; 66 @Mock private UwbVendorUciCallback mUwbVendorUciCallback2; 67 68 private static final Executor EXECUTOR = UwbTestUtils.getExecutor(); 69 private static final String CHIP_ID = "CHIP_ID"; 70 private static final PersistableBundle PARAMS = new PersistableBundle(); 71 private static final PersistableBundle PARAMS2 = new PersistableBundle(); 72 private static final byte[] PAYLOAD = new byte[] {0x0, 0x1}; 73 private static final int MT = 1; 74 private static final int GID = 9; 75 private static final int OID = 1; 76 private static final int UID = 343453; 77 private static final String PACKAGE_NAME = "com.uwb.test"; 78 private static final AttributionSource ATTRIBUTION_SOURCE = 79 new AttributionSource.Builder(UID).setPackageName(PACKAGE_NAME).build(); 80 private static final long TIME_NANOS = 1001; 81 private static final long TIME_NANOS2 = 1002; 82 83 private UwbManager mUwbManager; 84 85 @Before setUp()86 public void setUp() throws Exception { 87 MockitoAnnotations.initMocks(this); 88 when(mContext.getAttributionSource()).thenReturn(ATTRIBUTION_SOURCE); 89 90 mUwbManager = new UwbManager(mContext, mIUwbAdapter); 91 } 92 93 @Test testRegisterUnregisterCallbacks()94 public void testRegisterUnregisterCallbacks() throws Exception { 95 // Register/unregister AdapterStateCallbacks 96 mUwbManager.registerAdapterStateCallback(EXECUTOR, mAdapterStateCallback); 97 verify(mIUwbAdapter, times(1)).registerAdapterStateCallbacks(any()); 98 mUwbManager.registerAdapterStateCallback(EXECUTOR, mAdapterStateCallback2); 99 verify(mIUwbAdapter, times(1)).registerAdapterStateCallbacks(any()); 100 mUwbManager.unregisterAdapterStateCallback(mAdapterStateCallback); 101 verify(mIUwbAdapter, never()).unregisterAdapterStateCallbacks(any()); 102 mUwbManager.unregisterAdapterStateCallback(mAdapterStateCallback2); 103 verify(mIUwbAdapter, times(1)).unregisterAdapterStateCallbacks(any()); 104 105 // Register/unregister UwbVendorUciCallback 106 mUwbManager.registerUwbVendorUciCallback(EXECUTOR, mUwbVendorUciCallback); 107 verify(mIUwbAdapter, times(1)).registerVendorExtensionCallback(any()); 108 mUwbManager.registerUwbVendorUciCallback(EXECUTOR, mUwbVendorUciCallback2); 109 verify(mIUwbAdapter, times(1)).registerVendorExtensionCallback(any()); 110 mUwbManager.unregisterUwbVendorUciCallback(mUwbVendorUciCallback); 111 verify(mIUwbAdapter, never()).unregisterVendorExtensionCallback(any()); 112 mUwbManager.unregisterUwbVendorUciCallback(mUwbVendorUciCallback2); 113 verify(mIUwbAdapter, times(1)).unregisterVendorExtensionCallback(any()); 114 } 115 116 @Test testGettersAndSetters()117 public void testGettersAndSetters() throws Exception { 118 // Get SpecificationInfo 119 when(mIUwbAdapter.getSpecificationInfo(/*chipId=*/ null)).thenReturn(PARAMS); 120 assertThat(mUwbManager.getSpecificationInfo()).isEqualTo(PARAMS); 121 when(mIUwbAdapter.getSpecificationInfo(CHIP_ID)).thenReturn(PARAMS2); 122 assertThat(mUwbManager.getSpecificationInfo(CHIP_ID)).isEqualTo(PARAMS2); 123 doThrow(new RemoteException()).when(mIUwbAdapter).getSpecificationInfo(/*chipId=*/ null); 124 assertThrows(RuntimeException.class, () -> mUwbManager.getSpecificationInfo()); 125 126 // Get elapsedRealtimeResolutionNanos 127 when(mIUwbAdapter.getTimestampResolutionNanos(/*chipId=*/ null)).thenReturn(TIME_NANOS); 128 assertThat(mUwbManager.elapsedRealtimeResolutionNanos()).isEqualTo(TIME_NANOS); 129 when(mIUwbAdapter.getTimestampResolutionNanos(CHIP_ID)).thenReturn(TIME_NANOS2); 130 assertThat(mUwbManager.elapsedRealtimeResolutionNanos(CHIP_ID)).isEqualTo(TIME_NANOS2); 131 doThrow(new RemoteException()) 132 .when(mIUwbAdapter) 133 .getTimestampResolutionNanos(/*chipId=*/ null); 134 assertThrows(RuntimeException.class, () -> mUwbManager.elapsedRealtimeResolutionNanos()); 135 136 // setUwbEnabled 137 mUwbManager.setUwbEnabled(/*enabled=*/ true); 138 verify(mIUwbAdapter, times(1)).setEnabled(true); 139 140 // Get IsUwbEnabled 141 when(mIUwbAdapter.getAdapterState()).thenReturn(AdapterState.STATE_ENABLED_ACTIVE); 142 assertThat(mUwbManager.isUwbEnabled()).isTrue(); 143 when(mIUwbAdapter.getAdapterState()).thenReturn(AdapterState.STATE_ENABLED_INACTIVE); 144 assertThat(mUwbManager.isUwbEnabled()).isTrue(); 145 when(mIUwbAdapter.getAdapterState()).thenReturn(AdapterState.STATE_DISABLED); 146 assertThat(mUwbManager.isUwbEnabled()).isFalse(); 147 doThrow(new RemoteException()).when(mIUwbAdapter).getAdapterState(); 148 assertThrows(RuntimeException.class, () -> mUwbManager.isUwbEnabled()); 149 150 // getChipInfos 151 when(mIUwbAdapter.getChipInfos()).thenReturn(List.of(PARAMS)); 152 assertThat(mUwbManager.getChipInfos()).isEqualTo(List.of(PARAMS)); 153 doThrow(new RemoteException()).when(mIUwbAdapter).getChipInfos(); 154 assertThrows(RuntimeException.class, () -> mUwbManager.getChipInfos()); 155 156 // getDefaultChipId 157 when(mIUwbAdapter.getDefaultChipId()).thenReturn(CHIP_ID); 158 assertThat(mUwbManager.getDefaultChipId()).isEqualTo(CHIP_ID); 159 doThrow(new RemoteException()).when(mIUwbAdapter).getDefaultChipId(); 160 assertThrows(RuntimeException.class, () -> mUwbManager.getDefaultChipId()); 161 162 // getAllServiceProfiles 163 when(mIUwbAdapter.getAllServiceProfiles()).thenReturn(PARAMS); 164 assertThat(mUwbManager.getAllServiceProfiles()).isEqualTo(PARAMS); 165 doThrow(new RemoteException()).when(mIUwbAdapter).getAllServiceProfiles(); 166 assertThrows(RuntimeException.class, () -> mUwbManager.getAllServiceProfiles()); 167 168 // getAllServiceProfiles 169 when(mIUwbAdapter.getAdfProvisioningAuthorities(PARAMS)).thenReturn(PARAMS); 170 assertThat(mUwbManager.getAdfProvisioningAuthorities(PARAMS)).isEqualTo(PARAMS); 171 doThrow(new RemoteException()).when(mIUwbAdapter).getAdfProvisioningAuthorities(PARAMS); 172 assertThrows( 173 RuntimeException.class, () -> mUwbManager.getAdfProvisioningAuthorities(PARAMS)); 174 175 // getAdfCertificateInfo 176 when(mIUwbAdapter.getAdfCertificateAndInfo(PARAMS)).thenReturn(PARAMS); 177 assertThat(mUwbManager.getAdfCertificateInfo(PARAMS)).isEqualTo(PARAMS); 178 doThrow(new RemoteException()).when(mIUwbAdapter).getAdfCertificateAndInfo(PARAMS); 179 assertThrows(RuntimeException.class, () -> mUwbManager.getAdfCertificateInfo(PARAMS)); 180 } 181 182 @Test testOpenRangingSession()183 public void testOpenRangingSession() throws Exception { 184 RangingSession.Callback callback = mock(RangingSession.Callback.class); 185 // null chip id 186 mUwbManager.openRangingSession(PARAMS, EXECUTOR, callback); 187 verify(mIUwbAdapter, times(1)) 188 .openRanging(eq(ATTRIBUTION_SOURCE), any(), any(), eq(PARAMS), eq(null)); 189 190 // Chip id not on valid list 191 assertThrows( 192 IllegalArgumentException.class, 193 () -> mUwbManager.openRangingSession(PARAMS, EXECUTOR, callback, CHIP_ID)); 194 195 // Chip id on valid list 196 when(mIUwbAdapter.getChipIds()).thenReturn(List.of(CHIP_ID)); 197 mUwbManager.openRangingSession(PARAMS, EXECUTOR, callback, CHIP_ID); 198 verify(mIUwbAdapter, times(1)) 199 .openRanging(eq(ATTRIBUTION_SOURCE), any(), any(), eq(PARAMS), eq(CHIP_ID)); 200 } 201 202 @Test testAddServiceProfile()203 public void testAddServiceProfile() throws Exception { 204 when(mIUwbAdapter.addServiceProfile(PARAMS)).thenReturn(PARAMS); 205 assertThat(mUwbManager.addServiceProfile(PARAMS)).isEqualTo(PARAMS); 206 doThrow(new RemoteException()).when(mIUwbAdapter).addServiceProfile(PARAMS); 207 assertThrows(RuntimeException.class, () -> mUwbManager.addServiceProfile(PARAMS)); 208 } 209 210 @Test testRemoveServiceProfile()211 public void testRemoveServiceProfile() throws Exception { 212 when(mIUwbAdapter.removeServiceProfile(PARAMS)) 213 .thenReturn(UwbManager.REMOVE_SERVICE_PROFILE_SUCCESS); 214 assertThat(mUwbManager.removeServiceProfile(PARAMS)) 215 .isEqualTo(UwbManager.REMOVE_SERVICE_PROFILE_SUCCESS); 216 doThrow(new RemoteException()).when(mIUwbAdapter).removeServiceProfile(PARAMS); 217 assertThrows(RuntimeException.class, () -> mUwbManager.removeServiceProfile(PARAMS)); 218 } 219 220 @Test testProvisionProfileAdfByScript()221 public void testProvisionProfileAdfByScript() throws Exception { 222 AdfProvisionStateCallback cb = mock(AdfProvisionStateCallback.class); 223 assertThrows( 224 IllegalArgumentException.class, 225 () -> mUwbManager.provisionProfileAdfByScript(PARAMS, /*executor=*/ null, cb)); 226 assertThrows( 227 IllegalArgumentException.class, 228 () -> 229 mUwbManager.provisionProfileAdfByScript( 230 PARAMS, EXECUTOR, /*callback=*/ null)); 231 doThrow(new RemoteException()) 232 .when(mIUwbAdapter) 233 .provisionProfileAdfByScript(eq(PARAMS), any()); 234 assertThrows( 235 RuntimeException.class, 236 () -> mUwbManager.provisionProfileAdfByScript(PARAMS, EXECUTOR, cb)); 237 } 238 239 @Test testRemoveProfileAdf()240 public void testRemoveProfileAdf() throws Exception { 241 when(mIUwbAdapter.removeProfileAdf(PARAMS)) 242 .thenReturn(UwbManager.REMOVE_PROFILE_ADF_SUCCESS); 243 assertThat(mUwbManager.removeProfileAdf(PARAMS)) 244 .isEqualTo(UwbManager.REMOVE_PROFILE_ADF_SUCCESS); 245 doThrow(new RemoteException()).when(mIUwbAdapter).removeProfileAdf(PARAMS); 246 assertThrows(RuntimeException.class, () -> mUwbManager.removeProfileAdf(PARAMS)); 247 } 248 249 @Test testSendVendorUciMessage()250 public void testSendVendorUciMessage() throws Exception { 251 when(mIUwbAdapter.sendVendorUciMessage(MESSAGE_TYPE_COMMAND, GID, OID, PAYLOAD)) 252 .thenReturn(UwbManager.SEND_VENDOR_UCI_SUCCESS); 253 assertThat(mUwbManager.sendVendorUciMessage(GID, OID, PAYLOAD)) 254 .isEqualTo(UwbManager.SEND_VENDOR_UCI_SUCCESS); 255 doThrow(new RemoteException()).when(mIUwbAdapter).sendVendorUciMessage(MESSAGE_TYPE_COMMAND, 256 GID, OID, PAYLOAD); 257 assertThrows( 258 RuntimeException.class, () -> mUwbManager.sendVendorUciMessage(GID, OID, PAYLOAD)); 259 } 260 261 @Test testSendVendorUciMessageWithMessageType()262 public void testSendVendorUciMessageWithMessageType() throws Exception { 263 when(mIUwbAdapter.sendVendorUciMessage(MT, GID, OID, PAYLOAD)) 264 .thenReturn(UwbManager.SEND_VENDOR_UCI_SUCCESS); 265 assertThat(mUwbManager.sendVendorUciMessage(MT, GID, OID, PAYLOAD)) 266 .isEqualTo(UwbManager.SEND_VENDOR_UCI_SUCCESS); 267 doThrow(new RemoteException()).when(mIUwbAdapter).sendVendorUciMessage(MT, GID, OID, 268 PAYLOAD); 269 assertThrows( 270 RuntimeException.class, () -> mUwbManager.sendVendorUciMessage(MT, GID, OID, 271 PAYLOAD)); 272 } 273 274 @Test testGetUwbActivityEnergyInfoAsync()275 public void testGetUwbActivityEnergyInfoAsync() throws Exception { 276 Consumer<UwbActivityEnergyInfo> listener = mock(Consumer.class); 277 // null Executor 278 assertThrows(NullPointerException.class, 279 () -> mUwbManager.getUwbActivityEnergyInfoAsync(null, listener)); 280 // null listener 281 assertThrows(NullPointerException.class, 282 () -> mUwbManager.getUwbActivityEnergyInfoAsync(EXECUTOR, null)); 283 284 mUwbManager.getUwbActivityEnergyInfoAsync(EXECUTOR, listener); 285 verify(mIUwbAdapter).getUwbActivityEnergyInfoAsync( 286 any(IOnUwbActivityEnergyInfoListener.Stub.class)); 287 } 288 } 289