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.is_antenna_mode_config_supported)) 161 .thenReturn(false); 162 163 when(mContext.getResources()).thenReturn(mResources); 164 165 mDeviceConfigFacade = new DeviceConfigFacade(new Handler(mLooper.getLooper()), 166 mContext); 167 verify(() -> DeviceConfig.addOnPropertiesChangedListener(anyString(), any(), 168 mOnPropertiesChangedListenerCaptor.capture())); 169 } 170 171 /** 172 * Called after each test 173 */ 174 @After cleanup()175 public void cleanup() { 176 validateMockitoUsage(); 177 mSession.finishMocking(); 178 } 179 180 /** 181 * Verifies that default values are set correctly 182 */ 183 @Test testDefaultValue()184 public void testDefaultValue() throws Exception { 185 assertEquals(DeviceConfigFacade.DEFAULT_RANGING_RESULT_LOG_INTERVAL_MS, 186 mDeviceConfigFacade.getRangingResultLogIntervalMs()); 187 assertEquals(false, mDeviceConfigFacade.isDeviceErrorBugreportEnabled()); 188 assertEquals(false, mDeviceConfigFacade.isSessionInitErrorBugreportEnabled()); 189 assertEquals(DeviceConfigFacade.DEFAULT_BUG_REPORT_MIN_INTERVAL_MS, 190 mDeviceConfigFacade.getBugReportMinIntervalMs()); 191 192 assertEquals(true, mDeviceConfigFacade.isEnableFilters()); 193 assertEquals(true, mDeviceConfigFacade.isEnablePrimerEstElevation()); 194 assertEquals(true, mDeviceConfigFacade.isEnablePrimerAoA()); 195 assertEquals(true, mDeviceConfigFacade.isEnableBackAzimuth()); 196 assertEquals(true, mDeviceConfigFacade.isEnableBackAzimuthMasking()); 197 198 assertEquals(1, mDeviceConfigFacade.getFilterDistanceInliersPercent()); 199 assertEquals(2, mDeviceConfigFacade.getFilterDistanceWindow()); 200 assertEquals(3, mDeviceConfigFacade.getFilterAngleInliersPercent()); 201 assertEquals(4, mDeviceConfigFacade.getFilterAngleWindow()); 202 assertEquals(5, mDeviceConfigFacade.getPrimerFovDegree()); 203 assertEquals(PoseSourceType.ROTATION_VECTOR, mDeviceConfigFacade.getPoseSourceType()); 204 assertEquals(6, mDeviceConfigFacade.getPredictionTimeoutSeconds()); 205 assertEquals(7, mDeviceConfigFacade.getBackAzimuthWindow()); 206 assertEquals( 207 Math.toRadians(8), 208 mDeviceConfigFacade.getFrontAzimuthRadiansPerSecond(), 209 0.001); 210 assertEquals( 211 Math.toRadians(9), 212 mDeviceConfigFacade.getBackAzimuthRadiansPerSecond(), 213 0.001); 214 assertEquals( 215 Math.toRadians(10), 216 mDeviceConfigFacade.getMirrorScoreStdRadians(), 217 0.001); 218 assertEquals( 219 11 / 100F, 220 mDeviceConfigFacade.getBackNoiseInfluenceCoeff(), 221 0.001); 222 223 // true because FOV is 5: within limits. 224 assertEquals(true, mDeviceConfigFacade.isEnablePrimerFov()); 225 226 // Check the default values for the Advertising profile and Rx packet parameters. 227 assertEquals(5, mDeviceConfigFacade.getAdvertiseAoaCriteriaAngle()); 228 assertEquals(2000, mDeviceConfigFacade.getAdvertiseTimeThresholdMillis()); 229 assertEquals(12, mDeviceConfigFacade.getAdvertiseArraySizeToCheck()); 230 assertEquals(3, mDeviceConfigFacade.getAdvertiseArrayStartIndexToCalVariance()); 231 assertEquals(7, mDeviceConfigFacade.getAdvertiseArrayEndIndexToCalVariance()); 232 assertEquals(12, mDeviceConfigFacade.getAdvertiseTrustedVarianceValue()); 233 assertEquals(10, mDeviceConfigFacade.getRxDataMaxPacketsToStore()); 234 assertEquals(false, mDeviceConfigFacade.isBackgroundRangingEnabled()); 235 assertEquals(true, mDeviceConfigFacade.isRangingErrorStreakTimerEnabled()); 236 assertEquals(false, mDeviceConfigFacade.isCccRangingStoppedParamsSendEnabled()); 237 assertEquals(false, mDeviceConfigFacade.isCccAbsoluteUwbInitiationTimeEnabled()); 238 assertEquals(true, mDeviceConfigFacade.isLocationUseForCountryCodeEnabled()); 239 assertEquals(false, mDeviceConfigFacade.isUwbDisabledUntilFirstToggle()); 240 assertEquals(false, mDeviceConfigFacade.isPersistentCacheUseForCountryCodeEnabled()); 241 assertEquals(false, mDeviceConfigFacade.isHwIdleTurnOffEnabled()); 242 assertEquals(false, mDeviceConfigFacade.isAntennaModeConfigSupported()); 243 } 244 245 /** 246 * Verifies that all fields are updated properly. 247 */ 248 @Test testFieldUpdates()249 public void testFieldUpdates() throws Exception { 250 // These are interwoven (change then check, repeated) to make sure that copypasta 251 // errors didn't cause two values to get flipped. 252 253 // Simulate updating the fields, make sure the corresponding call is updated. 254 when(DeviceConfig.getInt(anyString(), eq("ranging_result_log_interval_ms"), 255 anyInt())).thenReturn(4000); 256 mOnPropertiesChangedListenerCaptor.getValue().onPropertiesChanged(null); 257 assertEquals(4000, mDeviceConfigFacade.getRangingResultLogIntervalMs()); 258 259 when(DeviceConfig.getBoolean(anyString(), eq("device_error_bugreport_enabled"), 260 anyBoolean())).thenReturn(true); 261 mOnPropertiesChangedListenerCaptor.getValue().onPropertiesChanged(null); 262 assertEquals(true, mDeviceConfigFacade.isDeviceErrorBugreportEnabled()); 263 264 when(DeviceConfig.getBoolean(anyString(), eq("session_init_error_bugreport_enabled"), 265 anyBoolean())).thenReturn(true); 266 mOnPropertiesChangedListenerCaptor.getValue().onPropertiesChanged(null); 267 assertEquals(true, mDeviceConfigFacade.isSessionInitErrorBugreportEnabled()); 268 269 when(DeviceConfig.getInt(anyString(), eq("bug_report_min_interval_ms"), 270 anyInt())).thenReturn(10 * 3600_000); 271 mOnPropertiesChangedListenerCaptor.getValue().onPropertiesChanged(null); 272 assertEquals(10 * 3600_000, mDeviceConfigFacade.getBugReportMinIntervalMs()); 273 274 when(DeviceConfig.getBoolean(anyString(), eq("enable_filters"), 275 anyBoolean())).thenReturn(false); 276 mOnPropertiesChangedListenerCaptor.getValue().onPropertiesChanged(null); 277 assertEquals(false, mDeviceConfigFacade.isEnableFilters()); 278 279 when(DeviceConfig.getBoolean(anyString(), eq("enable_primer_est_elevation"), 280 anyBoolean())).thenReturn(false); 281 mOnPropertiesChangedListenerCaptor.getValue().onPropertiesChanged(null); 282 assertEquals(false, mDeviceConfigFacade.isEnablePrimerEstElevation()); 283 284 when(DeviceConfig.getBoolean(anyString(), eq("enable_primer_aoa"), 285 anyBoolean())).thenReturn(false); 286 mOnPropertiesChangedListenerCaptor.getValue().onPropertiesChanged(null); 287 assertEquals(false, mDeviceConfigFacade.isEnablePrimerAoA()); 288 289 when(DeviceConfig.getBoolean(anyString(), eq("enable_azimuth_mirroring"), 290 anyBoolean())).thenReturn(false); 291 mOnPropertiesChangedListenerCaptor.getValue().onPropertiesChanged(null); 292 assertEquals(false, mDeviceConfigFacade.isEnableBackAzimuth()); 293 294 when(DeviceConfig.getBoolean(anyString(), eq("predict_rear_azimuths"), 295 anyBoolean())).thenReturn(false); 296 mOnPropertiesChangedListenerCaptor.getValue().onPropertiesChanged(null); 297 assertEquals(false, mDeviceConfigFacade.isEnableBackAzimuthMasking()); 298 299 when(DeviceConfig.getInt(anyString(), eq("filter_distance_inliers_percent"), 300 anyInt())).thenReturn(6); 301 mOnPropertiesChangedListenerCaptor.getValue().onPropertiesChanged(null); 302 assertEquals(6, mDeviceConfigFacade.getFilterDistanceInliersPercent()); 303 304 when(DeviceConfig.getInt(anyString(), eq("filter_distance_window"), 305 anyInt())).thenReturn(7); 306 mOnPropertiesChangedListenerCaptor.getValue().onPropertiesChanged(null); 307 assertEquals(7, mDeviceConfigFacade.getFilterDistanceWindow()); 308 309 when(DeviceConfig.getInt(anyString(), eq("filter_angle_inliers_percent"), 310 anyInt())).thenReturn(8); 311 mOnPropertiesChangedListenerCaptor.getValue().onPropertiesChanged(null); 312 assertEquals(8, mDeviceConfigFacade.getFilterAngleInliersPercent()); 313 314 when(DeviceConfig.getInt(anyString(), eq("filter_angle_window"), 315 anyInt())).thenReturn(9); 316 mOnPropertiesChangedListenerCaptor.getValue().onPropertiesChanged(null); 317 assertEquals(9, mDeviceConfigFacade.getFilterAngleWindow()); 318 319 when(DeviceConfig.getInt(anyString(), eq("primer_fov_degrees"), 320 anyInt())).thenReturn(0); 321 when(DeviceConfig.getString(anyString(), eq("pose_source_type"), 322 anyString())).thenReturn("NONE"); 323 when(DeviceConfig.getInt(anyString(), eq("prediction_timeout_seconds"), 324 anyInt())).thenReturn(5); 325 326 when(DeviceConfig.getInt(anyString(), eq("advertise_aoa_criteria_angle"), anyInt())) 327 .thenReturn(20); 328 when(DeviceConfig.getInt(anyString(), eq("advertise_time_threshold_millis"), anyInt())) 329 .thenReturn(3000); 330 when(DeviceConfig.getInt(anyString(), eq("advertise_array_size_to_check"), anyInt())) 331 .thenReturn(15); 332 when(DeviceConfig.getInt(anyString(), eq("advertise_array_start_index_to_cal_variance"), 333 anyInt())).thenReturn(3); 334 when(DeviceConfig.getInt(anyString(), eq("advertise_array_end_index_to_cal_variance"), 335 anyInt())).thenReturn(7); 336 when(DeviceConfig.getInt(anyString(), eq("advertise_trusted_variance_value"), anyInt())) 337 .thenReturn(12); 338 when(DeviceConfig.getInt(anyString(), eq("rx_data_max_packets_to_store"), 339 anyInt())).thenReturn(20); 340 when(DeviceConfig.getBoolean(anyString(), eq("background_ranging_enabled"), 341 anyBoolean())).thenReturn(true); 342 when(DeviceConfig.getBoolean(anyString(), eq("ranging_error_streak_timer_enabled"), 343 anyBoolean())).thenReturn(false); 344 when(DeviceConfig.getBoolean(anyString(), eq("ccc_ranging_stopped_params_send_enabled"), 345 anyBoolean())).thenReturn(true); 346 when(DeviceConfig.getBoolean(anyString(), eq("ccc_absolute_uwb_initiation_time_enabled"), 347 anyBoolean())).thenReturn(true); 348 when(DeviceConfig.getBoolean(anyString(), eq("location_use_for_country_code_enabled"), 349 anyBoolean())).thenReturn(false); 350 when(DeviceConfig.getBoolean(anyString(), eq("uwb_disabled_until_first_toggle"), 351 anyBoolean())).thenReturn(true); 352 when(DeviceConfig.getBoolean(anyString(), 353 eq("persistent_cache_use_for_country_code_enabled"), 354 anyBoolean())).thenReturn(true); 355 when(DeviceConfig.getBoolean(anyString(), eq("hw_idle_turn_off_enabled"), 356 anyBoolean())).thenReturn(true); 357 when(DeviceConfig.getBoolean(anyString(), eq("is_antenna_mode_config_supported"), 358 anyBoolean())).thenReturn(true); 359 360 mOnPropertiesChangedListenerCaptor.getValue().onPropertiesChanged(null); 361 assertEquals(0, mDeviceConfigFacade.getPrimerFovDegree()); 362 // false because FOV is 0. 363 assertEquals(false, mDeviceConfigFacade.isEnablePrimerFov()); 364 365 assertEquals(20, mDeviceConfigFacade.getAdvertiseAoaCriteriaAngle()); 366 assertEquals(3000, mDeviceConfigFacade.getAdvertiseTimeThresholdMillis()); 367 assertEquals(15, mDeviceConfigFacade.getAdvertiseArraySizeToCheck()); 368 assertEquals(3, mDeviceConfigFacade.getAdvertiseArrayStartIndexToCalVariance()); 369 assertEquals(7 , mDeviceConfigFacade.getAdvertiseArrayEndIndexToCalVariance()); 370 assertEquals(12, mDeviceConfigFacade.getAdvertiseTrustedVarianceValue()); 371 assertEquals(20, mDeviceConfigFacade.getRxDataMaxPacketsToStore()); 372 assertEquals(true, mDeviceConfigFacade.isBackgroundRangingEnabled()); 373 assertEquals(false, mDeviceConfigFacade.isRangingErrorStreakTimerEnabled()); 374 assertEquals(true, mDeviceConfigFacade.isCccRangingStoppedParamsSendEnabled()); 375 assertEquals(true, mDeviceConfigFacade.isCccAbsoluteUwbInitiationTimeEnabled()); 376 assertEquals(false, mDeviceConfigFacade.isLocationUseForCountryCodeEnabled()); 377 assertEquals(true, mDeviceConfigFacade.isUwbDisabledUntilFirstToggle()); 378 assertEquals(true, mDeviceConfigFacade.isPersistentCacheUseForCountryCodeEnabled()); 379 assertEquals(true, mDeviceConfigFacade.isHwIdleTurnOffEnabled()); 380 assertEquals(true, mDeviceConfigFacade.isAntennaModeConfigSupported()); 381 when(DeviceConfig.getString(anyString(), eq("pose_source_type"), 382 anyString())).thenReturn("NONE"); 383 mOnPropertiesChangedListenerCaptor.getValue().onPropertiesChanged(null); 384 assertEquals(PoseSourceType.NONE, mDeviceConfigFacade.getPoseSourceType()); 385 386 when(DeviceConfig.getInt(anyString(), eq("prediction_timeout_seconds"), 387 anyInt())).thenReturn(5); 388 mOnPropertiesChangedListenerCaptor.getValue().onPropertiesChanged(null); 389 assertEquals(5, mDeviceConfigFacade.getPredictionTimeoutSeconds()); 390 391 when(DeviceConfig.getInt(anyString(), eq("mirror_detection_window"), 392 anyInt())).thenReturn(11); 393 mOnPropertiesChangedListenerCaptor.getValue().onPropertiesChanged(null); 394 assertEquals(11, mDeviceConfigFacade.getBackAzimuthWindow()); 395 396 when(DeviceConfig.getInt(anyString(), eq("front_mirror_dps"), 397 anyInt())).thenReturn(12); 398 when(DeviceConfig.getInt(anyString(), eq("back_mirror_dps"), 399 anyInt())).thenReturn(13); 400 when(DeviceConfig.getInt(anyString(), eq("mirror_score_std_degrees"), 401 anyInt())).thenReturn(14); 402 when(DeviceConfig.getInt(anyString(), eq("back_noise_influence_percent"), 403 anyInt())).thenReturn(15); 404 405 mOnPropertiesChangedListenerCaptor.getValue().onPropertiesChanged(null); 406 assertEquals( 407 Math.toRadians(12), 408 mDeviceConfigFacade.getFrontAzimuthRadiansPerSecond(), 409 0.001); 410 assertEquals( 411 Math.toRadians(13), 412 mDeviceConfigFacade.getBackAzimuthRadiansPerSecond(), 413 0.001); 414 assertEquals( 415 Math.toRadians(14), 416 mDeviceConfigFacade.getMirrorScoreStdRadians(), 417 0.001); 418 assertEquals( 419 15 / 100F, 420 mDeviceConfigFacade.getBackNoiseInfluenceCoeff(), 421 0.001); 422 } 423 } 424