1 /* 2 * Copyright (C) 2021 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package com.android.server.uwb; 18 19 import static com.android.dx.mockito.inline.extended.ExtendedMockito.verify; 20 21 import static org.junit.Assert.assertEquals; 22 import static org.mockito.ArgumentMatchers.any; 23 import static org.mockito.ArgumentMatchers.anyBoolean; 24 import static org.mockito.ArgumentMatchers.anyInt; 25 import static org.mockito.ArgumentMatchers.anyLong; 26 import static org.mockito.ArgumentMatchers.anyString; 27 import static org.mockito.ArgumentMatchers.eq; 28 import static org.mockito.Mockito.validateMockitoUsage; 29 import static org.mockito.Mockito.when; 30 import static org.mockito.Mockito.withSettings; 31 32 import android.app.test.MockAnswerUtil; 33 import android.content.Context; 34 import android.content.res.Resources; 35 import android.os.Handler; 36 import android.os.test.TestLooper; 37 import android.provider.DeviceConfig; 38 39 import com.android.dx.mockito.inline.extended.ExtendedMockito; 40 import com.android.server.uwb.DeviceConfigFacade.PoseSourceType; 41 import com.android.uwb.resources.R; 42 43 import org.junit.After; 44 import org.junit.Before; 45 import org.junit.Test; 46 import org.mockito.ArgumentCaptor; 47 import org.mockito.Mock; 48 import org.mockito.MockitoAnnotations; 49 import org.mockito.MockitoSession; 50 51 public class DeviceConfigFacadeTest { 52 @Mock private Resources mResources; 53 @Mock private Context mContext; 54 55 final ArgumentCaptor<DeviceConfig.OnPropertiesChangedListener> 56 mOnPropertiesChangedListenerCaptor = 57 ArgumentCaptor.forClass(DeviceConfig.OnPropertiesChangedListener.class); 58 59 private DeviceConfigFacade mDeviceConfigFacade; 60 private TestLooper mLooper = new TestLooper(); 61 private MockitoSession mSession; 62 63 /** 64 * Setup the mocks and an instance of DeviceConfig before each test. 65 */ 66 @Before setUp()67 public void setUp() throws Exception { 68 MockitoAnnotations.initMocks(this); 69 // static mocking 70 mSession = ExtendedMockito.mockitoSession() 71 .mockStatic(DeviceConfig.class, withSettings().lenient()) 72 .startMocking(); 73 // Have DeviceConfig return the default value passed in. 74 when(DeviceConfig.getBoolean(anyString(), anyString(), anyBoolean())) 75 .then(new MockAnswerUtil.AnswerWithArguments() { 76 public boolean answer(String namespace, String field, boolean def) { 77 return def; 78 } 79 }); 80 when(DeviceConfig.getInt(anyString(), anyString(), anyInt())) 81 .then(new MockAnswerUtil.AnswerWithArguments() { 82 public int answer(String namespace, String field, int def) { 83 return def; 84 } 85 }); 86 when(DeviceConfig.getLong(anyString(), anyString(), anyLong())) 87 .then(new MockAnswerUtil.AnswerWithArguments() { 88 public long answer(String namespace, String field, long def) { 89 return def; 90 } 91 }); 92 when(DeviceConfig.getString(anyString(), anyString(), anyString())) 93 .then(new MockAnswerUtil.AnswerWithArguments() { 94 public String answer(String namespace, String field, String def) { 95 return def; 96 } 97 }); 98 99 when(mResources.getBoolean(R.bool.enable_filters)).thenReturn(true); 100 when(mResources.getBoolean(R.bool.enable_primer_est_elevation)).thenReturn(true); 101 when(mResources.getBoolean(R.bool.enable_primer_aoa)).thenReturn(true); 102 when(mResources.getInteger(R.integer.filter_distance_inliers_percent)) 103 .thenReturn(1); 104 when(mResources.getInteger(R.integer.filter_distance_window)) 105 .thenReturn(2); 106 when(mResources.getInteger(R.integer.filter_angle_inliers_percent)) 107 .thenReturn(3); 108 when(mResources.getInteger(R.integer.filter_angle_window)) 109 .thenReturn(4); 110 when(mResources.getInteger(R.integer.primer_fov_degrees)) 111 .thenReturn(5); 112 when(mResources.getString(R.string.pose_source_type)) 113 .thenReturn("ROTATION_VECTOR"); 114 when(mResources.getInteger(R.integer.prediction_timeout_seconds)) 115 .thenReturn(6); 116 when(mResources.getBoolean(R.bool.enable_azimuth_mirroring)).thenReturn(true); 117 when(mResources.getBoolean(R.bool.predict_rear_azimuths)).thenReturn(true); 118 when(mResources.getInteger(R.integer.mirror_detection_window)) 119 .thenReturn(7); 120 when(mResources.getInteger(R.integer.front_mirror_dps)) 121 .thenReturn(8); 122 when(mResources.getInteger(R.integer.back_mirror_dps)) 123 .thenReturn(9); 124 when(mResources.getInteger(R.integer.mirror_score_std_degrees)) 125 .thenReturn(10); 126 when(mResources.getInteger(R.integer.back_noise_influence_percent)) 127 .thenReturn(11); 128 129 // Setup the default values for the Advertising profile and Rx data packet parameters. 130 when(mResources.getInteger(R.integer.advertise_aoa_criteria_angle)) 131 .thenReturn(5); 132 when(mResources.getInteger(R.integer.advertise_time_threshold_millis)) 133 .thenReturn(2000); 134 when(mResources.getInteger(R.integer.advertise_array_size_to_check)) 135 .thenReturn(12); 136 when(mResources.getInteger(R.integer.advertise_array_start_index_to_cal_variance)) 137 .thenReturn(3); 138 when(mResources.getInteger(R.integer.advertise_array_end_index_to_cal_variance)) 139 .thenReturn(7); 140 when(mResources.getInteger(R.integer.advertise_trusted_variance_value)) 141 .thenReturn(12); 142 when(mResources.getInteger(R.integer.rx_data_max_packets_to_store)) 143 .thenReturn(10); 144 when(mResources.getBoolean(R.bool.background_ranging_enabled)) 145 .thenReturn(false); 146 when(mResources.getBoolean(R.bool.ranging_error_streak_timer_enabled)) 147 .thenReturn(true); 148 when(mResources.getBoolean(R.bool.ccc_ranging_stopped_params_send_enabled)) 149 .thenReturn(false); 150 when(mResources.getBoolean(R.bool.ccc_absolute_uwb_initiation_time_enabled)) 151 .thenReturn(false); 152 when(mResources.getBoolean(R.bool.location_use_for_country_code_enabled)) 153 .thenReturn(true); 154 when(mResources.getBoolean(R.bool.uwb_disabled_until_first_toggle)) 155 .thenReturn(false); 156 when(mResources.getBoolean(R.bool.persistent_cache_use_for_country_code_enabled)) 157 .thenReturn(false); 158 when(mResources.getBoolean(R.bool.hw_idle_turn_off_enabled)) 159 .thenReturn(false); 160 when(mResources.getBoolean(R.bool.fused_country_code_provider_enabled)) 161 .thenReturn(false); 162 when(mResources.getBoolean(R.bool.is_antenna_mode_config_supported)) 163 .thenReturn(false); 164 165 when(mContext.getResources()).thenReturn(mResources); 166 167 mDeviceConfigFacade = new DeviceConfigFacade(new Handler(mLooper.getLooper()), 168 mContext); 169 verify(() -> DeviceConfig.addOnPropertiesChangedListener(anyString(), any(), 170 mOnPropertiesChangedListenerCaptor.capture())); 171 } 172 173 /** 174 * Called after each test 175 */ 176 @After cleanup()177 public void cleanup() { 178 validateMockitoUsage(); 179 mSession.finishMocking(); 180 } 181 182 /** 183 * Verifies that default values are set correctly 184 */ 185 @Test testDefaultValue()186 public void testDefaultValue() throws Exception { 187 assertEquals(DeviceConfigFacade.DEFAULT_RANGING_RESULT_LOG_INTERVAL_MS, 188 mDeviceConfigFacade.getRangingResultLogIntervalMs()); 189 assertEquals(true, mDeviceConfigFacade.isDeviceErrorBugreportEnabled()); 190 assertEquals(true, mDeviceConfigFacade.isSessionInitErrorBugreportEnabled()); 191 assertEquals(DeviceConfigFacade.DEFAULT_BUG_REPORT_MIN_INTERVAL_MS, 192 mDeviceConfigFacade.getBugReportMinIntervalMs()); 193 194 assertEquals(true, mDeviceConfigFacade.isEnableFilters()); 195 assertEquals(true, mDeviceConfigFacade.isEnablePrimerEstElevation()); 196 assertEquals(true, mDeviceConfigFacade.isEnablePrimerAoA()); 197 assertEquals(true, mDeviceConfigFacade.isEnableBackAzimuth()); 198 assertEquals(true, mDeviceConfigFacade.isEnableBackAzimuthMasking()); 199 200 assertEquals(1, mDeviceConfigFacade.getFilterDistanceInliersPercent()); 201 assertEquals(2, mDeviceConfigFacade.getFilterDistanceWindow()); 202 assertEquals(3, mDeviceConfigFacade.getFilterAngleInliersPercent()); 203 assertEquals(4, mDeviceConfigFacade.getFilterAngleWindow()); 204 assertEquals(5, mDeviceConfigFacade.getPrimerFovDegree()); 205 assertEquals(PoseSourceType.ROTATION_VECTOR, mDeviceConfigFacade.getPoseSourceType()); 206 assertEquals(6, mDeviceConfigFacade.getPredictionTimeoutSeconds()); 207 assertEquals(7, mDeviceConfigFacade.getBackAzimuthWindow()); 208 assertEquals( 209 Math.toRadians(8), 210 mDeviceConfigFacade.getFrontAzimuthRadiansPerSecond(), 211 0.001); 212 assertEquals( 213 Math.toRadians(9), 214 mDeviceConfigFacade.getBackAzimuthRadiansPerSecond(), 215 0.001); 216 assertEquals( 217 Math.toRadians(10), 218 mDeviceConfigFacade.getMirrorScoreStdRadians(), 219 0.001); 220 assertEquals( 221 11 / 100F, 222 mDeviceConfigFacade.getBackNoiseInfluenceCoeff(), 223 0.001); 224 225 // true because FOV is 5: within limits. 226 assertEquals(true, mDeviceConfigFacade.isEnablePrimerFov()); 227 228 // Check the default values for the Advertising profile and Rx packet parameters. 229 assertEquals(5, mDeviceConfigFacade.getAdvertiseAoaCriteriaAngle()); 230 assertEquals(2000, mDeviceConfigFacade.getAdvertiseTimeThresholdMillis()); 231 assertEquals(12, mDeviceConfigFacade.getAdvertiseArraySizeToCheck()); 232 assertEquals(3, mDeviceConfigFacade.getAdvertiseArrayStartIndexToCalVariance()); 233 assertEquals(7, mDeviceConfigFacade.getAdvertiseArrayEndIndexToCalVariance()); 234 assertEquals(12, mDeviceConfigFacade.getAdvertiseTrustedVarianceValue()); 235 assertEquals(10, mDeviceConfigFacade.getRxDataMaxPacketsToStore()); 236 assertEquals(false, mDeviceConfigFacade.isBackgroundRangingEnabled()); 237 assertEquals(true, mDeviceConfigFacade.isRangingErrorStreakTimerEnabled()); 238 assertEquals(false, mDeviceConfigFacade.isCccRangingStoppedParamsSendEnabled()); 239 assertEquals(false, mDeviceConfigFacade.isCccAbsoluteUwbInitiationTimeEnabled()); 240 assertEquals(true, mDeviceConfigFacade.isLocationUseForCountryCodeEnabled()); 241 assertEquals(false, mDeviceConfigFacade.isUwbDisabledUntilFirstToggle()); 242 assertEquals(false, mDeviceConfigFacade.isPersistentCacheUseForCountryCodeEnabled()); 243 assertEquals(false, mDeviceConfigFacade.isHwIdleTurnOffEnabled()); 244 assertEquals(false, mDeviceConfigFacade.isFusedCountryCodeProviderEnabled()); 245 assertEquals(false, mDeviceConfigFacade.isAntennaModeConfigSupported()); 246 } 247 248 /** 249 * Verifies that all fields are updated properly. 250 */ 251 @Test testFieldUpdates()252 public void testFieldUpdates() throws Exception { 253 // These are interwoven (change then check, repeated) to make sure that copypasta 254 // errors didn't cause two values to get flipped. 255 256 // Simulate updating the fields, make sure the corresponding call is updated. 257 when(DeviceConfig.getInt(anyString(), eq("ranging_result_log_interval_ms"), 258 anyInt())).thenReturn(4000); 259 mOnPropertiesChangedListenerCaptor.getValue().onPropertiesChanged(null); 260 assertEquals(4000, mDeviceConfigFacade.getRangingResultLogIntervalMs()); 261 262 when(DeviceConfig.getBoolean(anyString(), eq("device_error_bugreport_enabled"), 263 anyBoolean())).thenReturn(true); 264 mOnPropertiesChangedListenerCaptor.getValue().onPropertiesChanged(null); 265 assertEquals(true, mDeviceConfigFacade.isDeviceErrorBugreportEnabled()); 266 267 when(DeviceConfig.getBoolean(anyString(), eq("session_init_error_bugreport_enabled"), 268 anyBoolean())).thenReturn(true); 269 mOnPropertiesChangedListenerCaptor.getValue().onPropertiesChanged(null); 270 assertEquals(true, mDeviceConfigFacade.isSessionInitErrorBugreportEnabled()); 271 272 when(DeviceConfig.getInt(anyString(), eq("bug_report_min_interval_ms"), 273 anyInt())).thenReturn(10 * 3600_000); 274 mOnPropertiesChangedListenerCaptor.getValue().onPropertiesChanged(null); 275 assertEquals(10 * 3600_000, mDeviceConfigFacade.getBugReportMinIntervalMs()); 276 277 when(DeviceConfig.getBoolean(anyString(), eq("enable_filters"), 278 anyBoolean())).thenReturn(false); 279 mOnPropertiesChangedListenerCaptor.getValue().onPropertiesChanged(null); 280 assertEquals(false, mDeviceConfigFacade.isEnableFilters()); 281 282 when(DeviceConfig.getBoolean(anyString(), eq("enable_primer_est_elevation"), 283 anyBoolean())).thenReturn(false); 284 mOnPropertiesChangedListenerCaptor.getValue().onPropertiesChanged(null); 285 assertEquals(false, mDeviceConfigFacade.isEnablePrimerEstElevation()); 286 287 when(DeviceConfig.getBoolean(anyString(), eq("enable_primer_aoa"), 288 anyBoolean())).thenReturn(false); 289 mOnPropertiesChangedListenerCaptor.getValue().onPropertiesChanged(null); 290 assertEquals(false, mDeviceConfigFacade.isEnablePrimerAoA()); 291 292 when(DeviceConfig.getBoolean(anyString(), eq("enable_azimuth_mirroring"), 293 anyBoolean())).thenReturn(false); 294 mOnPropertiesChangedListenerCaptor.getValue().onPropertiesChanged(null); 295 assertEquals(false, mDeviceConfigFacade.isEnableBackAzimuth()); 296 297 when(DeviceConfig.getBoolean(anyString(), eq("predict_rear_azimuths"), 298 anyBoolean())).thenReturn(false); 299 mOnPropertiesChangedListenerCaptor.getValue().onPropertiesChanged(null); 300 assertEquals(false, mDeviceConfigFacade.isEnableBackAzimuthMasking()); 301 302 when(DeviceConfig.getInt(anyString(), eq("filter_distance_inliers_percent"), 303 anyInt())).thenReturn(6); 304 mOnPropertiesChangedListenerCaptor.getValue().onPropertiesChanged(null); 305 assertEquals(6, mDeviceConfigFacade.getFilterDistanceInliersPercent()); 306 307 when(DeviceConfig.getInt(anyString(), eq("filter_distance_window"), 308 anyInt())).thenReturn(7); 309 mOnPropertiesChangedListenerCaptor.getValue().onPropertiesChanged(null); 310 assertEquals(7, mDeviceConfigFacade.getFilterDistanceWindow()); 311 312 when(DeviceConfig.getInt(anyString(), eq("filter_angle_inliers_percent"), 313 anyInt())).thenReturn(8); 314 mOnPropertiesChangedListenerCaptor.getValue().onPropertiesChanged(null); 315 assertEquals(8, mDeviceConfigFacade.getFilterAngleInliersPercent()); 316 317 when(DeviceConfig.getInt(anyString(), eq("filter_angle_window"), 318 anyInt())).thenReturn(9); 319 mOnPropertiesChangedListenerCaptor.getValue().onPropertiesChanged(null); 320 assertEquals(9, mDeviceConfigFacade.getFilterAngleWindow()); 321 322 when(DeviceConfig.getInt(anyString(), eq("primer_fov_degrees"), 323 anyInt())).thenReturn(0); 324 when(DeviceConfig.getString(anyString(), eq("pose_source_type"), 325 anyString())).thenReturn("NONE"); 326 when(DeviceConfig.getInt(anyString(), eq("prediction_timeout_seconds"), 327 anyInt())).thenReturn(5); 328 329 when(DeviceConfig.getInt(anyString(), eq("advertise_aoa_criteria_angle"), anyInt())) 330 .thenReturn(20); 331 when(DeviceConfig.getInt(anyString(), eq("advertise_time_threshold_millis"), anyInt())) 332 .thenReturn(3000); 333 when(DeviceConfig.getInt(anyString(), eq("advertise_array_size_to_check"), anyInt())) 334 .thenReturn(15); 335 when(DeviceConfig.getInt(anyString(), eq("advertise_array_start_index_to_cal_variance"), 336 anyInt())).thenReturn(3); 337 when(DeviceConfig.getInt(anyString(), eq("advertise_array_end_index_to_cal_variance"), 338 anyInt())).thenReturn(7); 339 when(DeviceConfig.getInt(anyString(), eq("advertise_trusted_variance_value"), anyInt())) 340 .thenReturn(12); 341 when(DeviceConfig.getInt(anyString(), eq("rx_data_max_packets_to_store"), 342 anyInt())).thenReturn(20); 343 when(DeviceConfig.getBoolean(anyString(), eq("background_ranging_enabled"), 344 anyBoolean())).thenReturn(true); 345 when(DeviceConfig.getBoolean(anyString(), eq("ranging_error_streak_timer_enabled"), 346 anyBoolean())).thenReturn(false); 347 when(DeviceConfig.getBoolean(anyString(), eq("ccc_ranging_stopped_params_send_enabled"), 348 anyBoolean())).thenReturn(true); 349 when(DeviceConfig.getBoolean(anyString(), eq("ccc_absolute_uwb_initiation_time_enabled"), 350 anyBoolean())).thenReturn(true); 351 when(DeviceConfig.getBoolean(anyString(), eq("location_use_for_country_code_enabled"), 352 anyBoolean())).thenReturn(false); 353 when(DeviceConfig.getBoolean(anyString(), eq("uwb_disabled_until_first_toggle"), 354 anyBoolean())).thenReturn(true); 355 when(DeviceConfig.getBoolean(anyString(), 356 eq("persistent_cache_use_for_country_code_enabled"), 357 anyBoolean())).thenReturn(true); 358 when(DeviceConfig.getBoolean(anyString(), eq("hw_idle_turn_off_enabled"), 359 anyBoolean())).thenReturn(true); 360 when(DeviceConfig.getBoolean(anyString(), eq("fused_country_code_provider_enabled"), 361 anyBoolean())).thenReturn(true); 362 when(DeviceConfig.getBoolean(anyString(), eq("is_antenna_mode_config_supported"), 363 anyBoolean())).thenReturn(true); 364 365 mOnPropertiesChangedListenerCaptor.getValue().onPropertiesChanged(null); 366 assertEquals(0, mDeviceConfigFacade.getPrimerFovDegree()); 367 // false because FOV is 0. 368 assertEquals(false, mDeviceConfigFacade.isEnablePrimerFov()); 369 370 assertEquals(20, mDeviceConfigFacade.getAdvertiseAoaCriteriaAngle()); 371 assertEquals(3000, mDeviceConfigFacade.getAdvertiseTimeThresholdMillis()); 372 assertEquals(15, mDeviceConfigFacade.getAdvertiseArraySizeToCheck()); 373 assertEquals(3, mDeviceConfigFacade.getAdvertiseArrayStartIndexToCalVariance()); 374 assertEquals(7 , mDeviceConfigFacade.getAdvertiseArrayEndIndexToCalVariance()); 375 assertEquals(12, mDeviceConfigFacade.getAdvertiseTrustedVarianceValue()); 376 assertEquals(20, mDeviceConfigFacade.getRxDataMaxPacketsToStore()); 377 assertEquals(true, mDeviceConfigFacade.isBackgroundRangingEnabled()); 378 assertEquals(false, mDeviceConfigFacade.isRangingErrorStreakTimerEnabled()); 379 assertEquals(true, mDeviceConfigFacade.isCccRangingStoppedParamsSendEnabled()); 380 assertEquals(true, mDeviceConfigFacade.isCccAbsoluteUwbInitiationTimeEnabled()); 381 assertEquals(false, mDeviceConfigFacade.isLocationUseForCountryCodeEnabled()); 382 assertEquals(true, mDeviceConfigFacade.isUwbDisabledUntilFirstToggle()); 383 assertEquals(true, mDeviceConfigFacade.isPersistentCacheUseForCountryCodeEnabled()); 384 assertEquals(true, mDeviceConfigFacade.isHwIdleTurnOffEnabled()); 385 assertEquals(true, mDeviceConfigFacade.isFusedCountryCodeProviderEnabled()); 386 assertEquals(true, mDeviceConfigFacade.isAntennaModeConfigSupported()); 387 when(DeviceConfig.getString(anyString(), eq("pose_source_type"), 388 anyString())).thenReturn("NONE"); 389 mOnPropertiesChangedListenerCaptor.getValue().onPropertiesChanged(null); 390 assertEquals(PoseSourceType.NONE, mDeviceConfigFacade.getPoseSourceType()); 391 392 when(DeviceConfig.getInt(anyString(), eq("prediction_timeout_seconds"), 393 anyInt())).thenReturn(5); 394 mOnPropertiesChangedListenerCaptor.getValue().onPropertiesChanged(null); 395 assertEquals(5, mDeviceConfigFacade.getPredictionTimeoutSeconds()); 396 397 when(DeviceConfig.getInt(anyString(), eq("mirror_detection_window"), 398 anyInt())).thenReturn(11); 399 mOnPropertiesChangedListenerCaptor.getValue().onPropertiesChanged(null); 400 assertEquals(11, mDeviceConfigFacade.getBackAzimuthWindow()); 401 402 when(DeviceConfig.getInt(anyString(), eq("front_mirror_dps"), 403 anyInt())).thenReturn(12); 404 when(DeviceConfig.getInt(anyString(), eq("back_mirror_dps"), 405 anyInt())).thenReturn(13); 406 when(DeviceConfig.getInt(anyString(), eq("mirror_score_std_degrees"), 407 anyInt())).thenReturn(14); 408 when(DeviceConfig.getInt(anyString(), eq("back_noise_influence_percent"), 409 anyInt())).thenReturn(15); 410 411 mOnPropertiesChangedListenerCaptor.getValue().onPropertiesChanged(null); 412 assertEquals( 413 Math.toRadians(12), 414 mDeviceConfigFacade.getFrontAzimuthRadiansPerSecond(), 415 0.001); 416 assertEquals( 417 Math.toRadians(13), 418 mDeviceConfigFacade.getBackAzimuthRadiansPerSecond(), 419 0.001); 420 assertEquals( 421 Math.toRadians(14), 422 mDeviceConfigFacade.getMirrorScoreStdRadians(), 423 0.001); 424 assertEquals( 425 15 / 100F, 426 mDeviceConfigFacade.getBackNoiseInfluenceCoeff(), 427 0.001); 428 } 429 } 430