1 /* 2 * Copyright (C) 2018 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.provider; 18 19 import static android.provider.DeviceConfig.Properties; 20 21 import static com.google.common.truth.Truth.assertThat; 22 23 import static org.testng.Assert.assertThrows; 24 25 import android.app.ActivityThread; 26 import android.content.ContentResolver; 27 import android.os.Bundle; 28 import android.platform.test.annotations.Presubmit; 29 30 import androidx.test.InstrumentationRegistry; 31 import androidx.test.filters.SmallTest; 32 import androidx.test.runner.AndroidJUnit4; 33 34 import org.junit.After; 35 import org.junit.Assert; 36 import org.junit.Test; 37 import org.junit.runner.RunWith; 38 39 import java.util.HashMap; 40 import java.util.Map; 41 import java.util.Objects; 42 import java.util.concurrent.CompletableFuture; 43 import java.util.concurrent.ExecutionException; 44 import java.util.concurrent.TimeUnit; 45 import java.util.concurrent.TimeoutException; 46 import java.util.concurrent.atomic.AtomicReference; 47 48 /** Tests that ensure appropriate settings are backed up. */ 49 @Presubmit 50 @RunWith(AndroidJUnit4.class) 51 @SmallTest 52 public class DeviceConfigTest { 53 private static final long WAIT_FOR_PROPERTY_CHANGE_TIMEOUT_MILLIS = 2000; // 2 sec 54 private static final String DEFAULT_VALUE = "test_default_value"; 55 private static final String NAMESPACE = "namespace1"; 56 private static final String KEY = "key1"; 57 private static final String KEY2 = "key2"; 58 private static final String KEY3 = "key3"; 59 private static final String KEY4 = "key4"; 60 private static final String VALUE = "value1"; 61 private static final String VALUE2 = "value2"; 62 private static final String VALUE3 = "value3"; 63 private static final String NULL_VALUE = "null"; 64 65 @After cleanUp()66 public void cleanUp() { 67 deleteViaContentProvider(NAMESPACE, KEY); 68 deleteViaContentProvider(NAMESPACE, KEY2); 69 deleteViaContentProvider(NAMESPACE, KEY3); 70 DeviceConfig.setSyncDisabledMode(DeviceConfig.SYNC_DISABLED_MODE_NONE); 71 } 72 73 @Test getProperty_empty()74 public void getProperty_empty() { 75 String result = DeviceConfig.getProperty(NAMESPACE, KEY); 76 assertThat(result).isNull(); 77 } 78 79 @Test getProperty_nullNamespace()80 public void getProperty_nullNamespace() { 81 try { 82 DeviceConfig.getProperty(null, KEY); 83 Assert.fail("Null namespace should have resulted in an NPE."); 84 } catch (NullPointerException e) { 85 // expected 86 } 87 } 88 89 @Test getProperty_nullName()90 public void getProperty_nullName() { 91 try { 92 DeviceConfig.getProperty(NAMESPACE, null); 93 Assert.fail("Null name should have resulted in an NPE."); 94 } catch (NullPointerException e) { 95 // expected 96 } 97 } 98 99 @Test getString_empty()100 public void getString_empty() { 101 final String default_value = "default_value"; 102 final String result = DeviceConfig.getString(NAMESPACE, KEY, default_value); 103 assertThat(result).isEqualTo(default_value); 104 } 105 106 @Test getString_nullDefault()107 public void getString_nullDefault() { 108 final String result = DeviceConfig.getString(NAMESPACE, KEY, null); 109 assertThat(result).isNull(); 110 } 111 112 @Test getString_nonEmpty()113 public void getString_nonEmpty() { 114 final String value = "new_value"; 115 final String default_value = "default"; 116 DeviceConfig.setProperty(NAMESPACE, KEY, value, false); 117 118 final String result = DeviceConfig.getString(NAMESPACE, KEY, default_value); 119 assertThat(result).isEqualTo(value); 120 } 121 122 @Test getString_nullNamespace()123 public void getString_nullNamespace() { 124 try { 125 DeviceConfig.getString(null, KEY, "default_value"); 126 Assert.fail("Null namespace should have resulted in an NPE."); 127 } catch (NullPointerException e) { 128 // expected 129 } 130 } 131 132 @Test getString_nullName()133 public void getString_nullName() { 134 try { 135 DeviceConfig.getString(NAMESPACE, null, "default_value"); 136 Assert.fail("Null name should have resulted in an NPE."); 137 } catch (NullPointerException e) { 138 // expected 139 } 140 } 141 142 @Test getBoolean_empty()143 public void getBoolean_empty() { 144 final boolean default_value = true; 145 final boolean result = DeviceConfig.getBoolean(NAMESPACE, KEY, default_value); 146 assertThat(result).isEqualTo(default_value); 147 } 148 149 @Test getBoolean_valid()150 public void getBoolean_valid() { 151 final boolean value = true; 152 final boolean default_value = false; 153 DeviceConfig.setProperty(NAMESPACE, KEY, String.valueOf(value), false); 154 155 final boolean result = DeviceConfig.getBoolean(NAMESPACE, KEY, default_value); 156 assertThat(result).isEqualTo(value); 157 } 158 159 @Test getBoolean_invalid()160 public void getBoolean_invalid() { 161 final boolean default_value = true; 162 DeviceConfig.setProperty(NAMESPACE, KEY, "not_a_boolean", false); 163 164 final boolean result = DeviceConfig.getBoolean(NAMESPACE, KEY, default_value); 165 // Anything non-null other than case insensitive "true" parses to false. 166 assertThat(result).isFalse(); 167 } 168 169 @Test getBoolean_nullNamespace()170 public void getBoolean_nullNamespace() { 171 try { 172 DeviceConfig.getBoolean(null, KEY, false); 173 Assert.fail("Null namespace should have resulted in an NPE."); 174 } catch (NullPointerException e) { 175 // expected 176 } 177 } 178 179 @Test getBoolean_nullName()180 public void getBoolean_nullName() { 181 try { 182 DeviceConfig.getBoolean(NAMESPACE, null, false); 183 Assert.fail("Null name should have resulted in an NPE."); 184 } catch (NullPointerException e) { 185 // expected 186 } 187 } 188 189 @Test getInt_empty()190 public void getInt_empty() { 191 final int default_value = 999; 192 final int result = DeviceConfig.getInt(NAMESPACE, KEY, default_value); 193 assertThat(result).isEqualTo(default_value); 194 } 195 196 @Test getInt_valid()197 public void getInt_valid() { 198 final int value = 123; 199 final int default_value = 999; 200 DeviceConfig.setProperty(NAMESPACE, KEY, String.valueOf(value), false); 201 202 final int result = DeviceConfig.getInt(NAMESPACE, KEY, default_value); 203 assertThat(result).isEqualTo(value); 204 } 205 206 @Test getInt_invalid()207 public void getInt_invalid() { 208 final int default_value = 999; 209 DeviceConfig.setProperty(NAMESPACE, KEY, "not_an_int", false); 210 211 final int result = DeviceConfig.getInt(NAMESPACE, KEY, default_value); 212 // Failure to parse results in using the default value 213 assertThat(result).isEqualTo(default_value); 214 } 215 216 @Test getInt_nullNamespace()217 public void getInt_nullNamespace() { 218 try { 219 DeviceConfig.getInt(null, KEY, 0); 220 Assert.fail("Null namespace should have resulted in an NPE."); 221 } catch (NullPointerException e) { 222 // expected 223 } 224 } 225 226 @Test getInt_nullName()227 public void getInt_nullName() { 228 try { 229 DeviceConfig.getInt(NAMESPACE, null, 0); 230 Assert.fail("Null name should have resulted in an NPE."); 231 } catch (NullPointerException e) { 232 // expected 233 } 234 } 235 236 @Test getLong_empty()237 public void getLong_empty() { 238 final long default_value = 123456; 239 final long result = DeviceConfig.getLong(NAMESPACE, KEY, default_value); 240 assertThat(result).isEqualTo(default_value); 241 } 242 243 @Test getLong_valid()244 public void getLong_valid() { 245 final long value = 456789; 246 final long default_value = 123456; 247 DeviceConfig.setProperty(NAMESPACE, KEY, String.valueOf(value), false); 248 249 final long result = DeviceConfig.getLong(NAMESPACE, KEY, default_value); 250 assertThat(result).isEqualTo(value); 251 } 252 253 @Test getLong_invalid()254 public void getLong_invalid() { 255 final long default_value = 123456; 256 DeviceConfig.setProperty(NAMESPACE, KEY, "not_a_long", false); 257 258 final long result = DeviceConfig.getLong(NAMESPACE, KEY, default_value); 259 // Failure to parse results in using the default value 260 assertThat(result).isEqualTo(default_value); 261 } 262 263 @Test getLong_nullNamespace()264 public void getLong_nullNamespace() { 265 try { 266 DeviceConfig.getLong(null, KEY, 0); 267 Assert.fail("Null namespace should have resulted in an NPE."); 268 } catch (NullPointerException e) { 269 // expected 270 } 271 } 272 273 @Test getLong_nullName()274 public void getLong_nullName() { 275 try { 276 DeviceConfig.getLong(NAMESPACE, null, 0); 277 Assert.fail("Null name should have resulted in an NPE."); 278 } catch (NullPointerException e) { 279 // expected 280 } 281 } 282 283 @Test getFloat_empty()284 public void getFloat_empty() { 285 final float default_value = 123.456f; 286 final float result = DeviceConfig.getFloat(NAMESPACE, KEY, default_value); 287 assertThat(result).isEqualTo(default_value); 288 } 289 290 @Test getFloat_valid()291 public void getFloat_valid() { 292 final float value = 456.789f; 293 final float default_value = 123.456f; 294 DeviceConfig.setProperty(NAMESPACE, KEY, String.valueOf(value), false); 295 296 final float result = DeviceConfig.getFloat(NAMESPACE, KEY, default_value); 297 assertThat(result).isEqualTo(value); 298 } 299 300 @Test getFloat_invalid()301 public void getFloat_invalid() { 302 final float default_value = 123.456f; 303 DeviceConfig.setProperty(NAMESPACE, KEY, "not_a_float", false); 304 305 final float result = DeviceConfig.getFloat(NAMESPACE, KEY, default_value); 306 // Failure to parse results in using the default value 307 assertThat(result).isEqualTo(default_value); 308 } 309 310 @Test getFloat_nullNamespace()311 public void getFloat_nullNamespace() { 312 try { 313 DeviceConfig.getFloat(null, KEY, 0); 314 Assert.fail("Null namespace should have resulted in an NPE."); 315 } catch (NullPointerException e) { 316 // expected 317 } 318 } 319 320 @Test getFloat_nullName()321 public void getFloat_nullName() { 322 try { 323 DeviceConfig.getFloat(NAMESPACE, null, 0); 324 Assert.fail("Null name should have resulted in an NPE."); 325 } catch (NullPointerException e) { 326 // expected 327 } 328 } 329 330 @Test setProperty_nullNamespace()331 public void setProperty_nullNamespace() { 332 try { 333 DeviceConfig.setProperty(null, KEY, VALUE, false); 334 Assert.fail("Null namespace should have resulted in an NPE."); 335 } catch (NullPointerException e) { 336 // expected 337 } 338 } 339 340 @Test setProperty_nullName()341 public void setProperty_nullName() { 342 try { 343 DeviceConfig.setProperty(NAMESPACE, null, VALUE, false); 344 Assert.fail("Null name should have resulted in an NPE."); 345 } catch (NullPointerException e) { 346 // expected 347 } 348 } 349 350 @Test setAndGetProperty_sameNamespace()351 public void setAndGetProperty_sameNamespace() { 352 DeviceConfig.setProperty(NAMESPACE, KEY, VALUE, false); 353 String result = DeviceConfig.getProperty(NAMESPACE, KEY); 354 assertThat(result).isEqualTo(VALUE); 355 } 356 357 @Test setAndGetProperty_differentNamespace()358 public void setAndGetProperty_differentNamespace() { 359 String newNamespace = "namespace2"; 360 DeviceConfig.setProperty(NAMESPACE, KEY, VALUE, false); 361 String result = DeviceConfig.getProperty(newNamespace, KEY); 362 assertThat(result).isNull(); 363 } 364 365 @Test setAndGetProperty_multipleNamespaces()366 public void setAndGetProperty_multipleNamespaces() { 367 String newNamespace = "namespace2"; 368 String newValue = "value2"; 369 DeviceConfig.setProperty(NAMESPACE, KEY, VALUE, false); 370 DeviceConfig.setProperty(newNamespace, KEY, newValue, false); 371 String result = DeviceConfig.getProperty(NAMESPACE, KEY); 372 assertThat(result).isEqualTo(VALUE); 373 result = DeviceConfig.getProperty(newNamespace, KEY); 374 assertThat(result).isEqualTo(newValue); 375 376 // clean up 377 deleteViaContentProvider(newNamespace, KEY); 378 } 379 380 @Test setAndGetProperty_overrideValue()381 public void setAndGetProperty_overrideValue() { 382 String newValue = "value2"; 383 DeviceConfig.setProperty(NAMESPACE, KEY, VALUE, false); 384 DeviceConfig.setProperty(NAMESPACE, KEY, newValue, false); 385 String result = DeviceConfig.getProperty(NAMESPACE, KEY); 386 assertThat(result).isEqualTo(newValue); 387 } 388 389 @Test resetToDefault_makeDefault()390 public void resetToDefault_makeDefault() { 391 DeviceConfig.setProperty(NAMESPACE, KEY, VALUE, true); 392 assertThat(DeviceConfig.getProperty(NAMESPACE, KEY)).isEqualTo(VALUE); 393 394 DeviceConfig.resetToDefaults(Settings.RESET_MODE_PACKAGE_DEFAULTS, NAMESPACE); 395 assertThat(DeviceConfig.getProperty(NAMESPACE, KEY)).isEqualTo(VALUE); 396 } 397 398 @Test resetToDefault_doNotMakeDefault()399 public void resetToDefault_doNotMakeDefault() { 400 DeviceConfig.setProperty(NAMESPACE, KEY, VALUE, false); 401 assertThat(DeviceConfig.getProperty(NAMESPACE, KEY)).isEqualTo(VALUE); 402 403 DeviceConfig.resetToDefaults(Settings.RESET_MODE_PACKAGE_DEFAULTS, NAMESPACE); 404 assertThat(DeviceConfig.getProperty(NAMESPACE, KEY)).isNull(); 405 } 406 407 @Test getProperties_fullNamespace()408 public void getProperties_fullNamespace() { 409 Properties properties = DeviceConfig.getProperties(NAMESPACE); 410 assertThat(properties.getKeyset()).isEmpty(); 411 412 DeviceConfig.setProperty(NAMESPACE, KEY, VALUE, false); 413 DeviceConfig.setProperty(NAMESPACE, KEY2, VALUE2, false); 414 properties = DeviceConfig.getProperties(NAMESPACE); 415 assertThat(properties.getKeyset()).containsExactly(KEY, KEY2); 416 assertThat(properties.getString(KEY, DEFAULT_VALUE)).isEqualTo(VALUE); 417 assertThat(properties.getString(KEY2, DEFAULT_VALUE)).isEqualTo(VALUE2); 418 419 DeviceConfig.setProperty(NAMESPACE, KEY, VALUE3, false); 420 properties = DeviceConfig.getProperties(NAMESPACE); 421 assertThat(properties.getKeyset()).containsExactly(KEY, KEY2); 422 assertThat(properties.getString(KEY, DEFAULT_VALUE)).isEqualTo(VALUE3); 423 assertThat(properties.getString(KEY2, DEFAULT_VALUE)).isEqualTo(VALUE2); 424 425 DeviceConfig.setProperty(NAMESPACE, KEY3, VALUE, false); 426 properties = DeviceConfig.getProperties(NAMESPACE); 427 assertThat(properties.getKeyset()).containsExactly(KEY, KEY2, KEY3); 428 assertThat(properties.getString(KEY, DEFAULT_VALUE)).isEqualTo(VALUE3); 429 assertThat(properties.getString(KEY2, DEFAULT_VALUE)).isEqualTo(VALUE2); 430 assertThat(properties.getString(KEY3, DEFAULT_VALUE)).isEqualTo(VALUE); 431 } 432 433 @Test getProperties_getString()434 public void getProperties_getString() { 435 DeviceConfig.setProperty(NAMESPACE, KEY, VALUE, false); 436 DeviceConfig.setProperty(NAMESPACE, KEY2, VALUE2, false); 437 438 Properties properties = DeviceConfig.getProperties(NAMESPACE, KEY, KEY2); 439 assertThat(properties.getKeyset()).containsExactly(KEY, KEY2); 440 assertThat(properties.getString(KEY, DEFAULT_VALUE)).isEqualTo(VALUE); 441 assertThat(properties.getString(KEY2, DEFAULT_VALUE)).isEqualTo(VALUE2); 442 } 443 444 @Test getProperties_getBoolean()445 public void getProperties_getBoolean() { 446 DeviceConfig.setProperty(NAMESPACE, KEY, "true", false); 447 DeviceConfig.setProperty(NAMESPACE, KEY2, "false", false); 448 DeviceConfig.setProperty(NAMESPACE, KEY3, "not a valid boolean", false); 449 450 Properties properties = DeviceConfig.getProperties(NAMESPACE, KEY, KEY2, KEY3); 451 assertThat(properties.getKeyset()).containsExactly(KEY, KEY2, KEY3); 452 assertThat(properties.getBoolean(KEY, true)).isTrue(); 453 assertThat(properties.getBoolean(KEY, false)).isTrue(); 454 assertThat(properties.getBoolean(KEY2, true)).isFalse(); 455 assertThat(properties.getBoolean(KEY2, false)).isFalse(); 456 // KEY3 was set to garbage, anything nonnull but "true" will parse as false 457 assertThat(properties.getBoolean(KEY3, true)).isFalse(); 458 assertThat(properties.getBoolean(KEY3, false)).isFalse(); 459 // If a key was not set, it will return the default value 460 assertThat(properties.getBoolean("missing_key", true)).isTrue(); 461 assertThat(properties.getBoolean("missing_key", false)).isFalse(); 462 } 463 464 @Test getProperties_getInt()465 public void getProperties_getInt() { 466 final int value = 101; 467 468 DeviceConfig.setProperty(NAMESPACE, KEY, Integer.toString(value), false); 469 DeviceConfig.setProperty(NAMESPACE, KEY2, "not a valid int", false); 470 471 Properties properties = DeviceConfig.getProperties(NAMESPACE, KEY, KEY2); 472 assertThat(properties.getKeyset()).containsExactly(KEY, KEY2); 473 assertThat(properties.getInt(KEY, -1)).isEqualTo(value); 474 // KEY2 was set to garbage, the default value is returned if an int cannot be parsed 475 assertThat(properties.getInt(KEY2, -1)).isEqualTo(-1); 476 } 477 478 @Test getProperties_getFloat()479 public void getProperties_getFloat() { 480 final float value = 101.010f; 481 482 DeviceConfig.setProperty(NAMESPACE, KEY, Float.toString(value), false); 483 DeviceConfig.setProperty(NAMESPACE, KEY2, "not a valid float", false); 484 485 Properties properties = DeviceConfig.getProperties(NAMESPACE, KEY, KEY2); 486 assertThat(properties.getKeyset()).containsExactly(KEY, KEY2); 487 assertThat(properties.getFloat(KEY, -1.0f)).isEqualTo(value); 488 // KEY2 was set to garbage, the default value is returned if a float cannot be parsed 489 assertThat(properties.getFloat(KEY2, -1.0f)).isEqualTo(-1.0f); 490 } 491 492 @Test getProperties_getLong()493 public void getProperties_getLong() { 494 final long value = 101; 495 496 DeviceConfig.setProperty(NAMESPACE, KEY, Long.toString(value), false); 497 DeviceConfig.setProperty(NAMESPACE, KEY2, "not a valid long", false); 498 499 Properties properties = DeviceConfig.getProperties(NAMESPACE, KEY, KEY2); 500 assertThat(properties.getKeyset()).containsExactly(KEY, KEY2); 501 assertThat(properties.getLong(KEY, -1)).isEqualTo(value); 502 // KEY2 was set to garbage, the default value is returned if a long cannot be parsed 503 assertThat(properties.getLong(KEY2, -1)).isEqualTo(-1); 504 } 505 506 @Test getProperties_defaults()507 public void getProperties_defaults() { 508 DeviceConfig.setProperty(NAMESPACE, KEY, VALUE, false); 509 DeviceConfig.setProperty(NAMESPACE, KEY3, VALUE3, false); 510 511 Properties properties = DeviceConfig.getProperties(NAMESPACE, KEY, KEY2); 512 assertThat(properties.getKeyset()).containsExactly(KEY); 513 assertThat(properties.getString(KEY, DEFAULT_VALUE)).isEqualTo(VALUE); 514 // not set in DeviceConfig, but requested in getProperties 515 assertThat(properties.getString(KEY2, DEFAULT_VALUE)).isEqualTo(DEFAULT_VALUE); 516 // set in DeviceConfig, but not requested in getProperties 517 assertThat(properties.getString(KEY3, DEFAULT_VALUE)).isEqualTo(DEFAULT_VALUE); 518 } 519 520 @Test setProperties()521 public void setProperties() throws DeviceConfig.BadConfigException { 522 Properties properties = new Properties.Builder(NAMESPACE).setString(KEY, VALUE) 523 .setString(KEY2, VALUE2).build(); 524 525 DeviceConfig.setProperties(properties); 526 properties = DeviceConfig.getProperties(NAMESPACE); 527 assertThat(properties.getKeyset()).containsExactly(KEY, KEY2); 528 assertThat(properties.getString(KEY, DEFAULT_VALUE)).isEqualTo(VALUE); 529 assertThat(properties.getString(KEY2, DEFAULT_VALUE)).isEqualTo(VALUE2); 530 531 properties = new Properties.Builder(NAMESPACE).setString(KEY, VALUE2) 532 .setString(KEY3, VALUE3).build(); 533 534 DeviceConfig.setProperties(properties); 535 properties = DeviceConfig.getProperties(NAMESPACE); 536 assertThat(properties.getKeyset()).containsExactly(KEY, KEY3); 537 assertThat(properties.getString(KEY, DEFAULT_VALUE)).isEqualTo(VALUE2); 538 assertThat(properties.getString(KEY3, DEFAULT_VALUE)).isEqualTo(VALUE3); 539 540 assertThat(properties.getKeyset()).doesNotContain(KEY2); 541 assertThat(properties.getString(KEY2, DEFAULT_VALUE)).isEqualTo(DEFAULT_VALUE); 542 } 543 544 @Test setProperties_multipleNamespaces()545 public void setProperties_multipleNamespaces() throws DeviceConfig.BadConfigException { 546 final String namespace2 = "namespace2"; 547 Properties properties1 = new Properties.Builder(NAMESPACE).setString(KEY, VALUE) 548 .setString(KEY2, VALUE2).build(); 549 Properties properties2 = new Properties.Builder(namespace2).setString(KEY2, VALUE) 550 .setString(KEY3, VALUE2).build(); 551 552 DeviceConfig.setProperties(properties1); 553 DeviceConfig.setProperties(properties2); 554 555 Properties properties = DeviceConfig.getProperties(NAMESPACE); 556 assertThat(properties.getKeyset()).containsExactly(KEY, KEY2); 557 assertThat(properties.getString(KEY, DEFAULT_VALUE)).isEqualTo(VALUE); 558 assertThat(properties.getString(KEY2, DEFAULT_VALUE)).isEqualTo(VALUE2); 559 560 assertThat(properties.getKeyset()).doesNotContain(KEY3); 561 assertThat(properties.getString(KEY3, DEFAULT_VALUE)).isEqualTo(DEFAULT_VALUE); 562 563 properties = DeviceConfig.getProperties(namespace2); 564 assertThat(properties.getKeyset()).containsExactly(KEY2, KEY3); 565 assertThat(properties.getString(KEY2, DEFAULT_VALUE)).isEqualTo(VALUE); 566 assertThat(properties.getString(KEY3, DEFAULT_VALUE)).isEqualTo(VALUE2); 567 568 assertThat(properties.getKeyset()).doesNotContain(KEY); 569 assertThat(properties.getString(KEY, DEFAULT_VALUE)).isEqualTo(DEFAULT_VALUE); 570 571 // clean up 572 deleteViaContentProvider(namespace2, KEY); 573 deleteViaContentProvider(namespace2, KEY2); 574 deleteViaContentProvider(namespace2, KEY3); 575 } 576 577 @Test propertiesBuilder()578 public void propertiesBuilder() { 579 boolean booleanValue = true; 580 int intValue = 123; 581 float floatValue = 4.56f; 582 long longValue = -789L; 583 String key4 = "key4"; 584 String key5 = "key5"; 585 586 Properties properties = new Properties.Builder(NAMESPACE).setString(KEY, VALUE) 587 .setBoolean(KEY2, booleanValue).setInt(KEY3, intValue).setLong(key4, longValue) 588 .setFloat(key5, floatValue).build(); 589 assertThat(properties.getNamespace()).isEqualTo(NAMESPACE); 590 assertThat(properties.getString(KEY, "defaultValue")).isEqualTo(VALUE); 591 assertThat(properties.getBoolean(KEY2, false)).isEqualTo(booleanValue); 592 assertThat(properties.getInt(KEY3, 0)).isEqualTo(intValue); 593 assertThat(properties.getLong("key4", 0L)).isEqualTo(longValue); 594 assertThat(properties.getFloat("key5", 0f)).isEqualTo(floatValue); 595 } 596 597 @Test banNamespaceProperties()598 public void banNamespaceProperties() throws DeviceConfig.BadConfigException { 599 // Given namespace will be permanently banned, thus it needs to be different every time 600 final String namespaceToBan = NAMESPACE + System.currentTimeMillis(); 601 Properties properties = new Properties.Builder(namespaceToBan).setString(KEY, VALUE) 602 .setString(KEY4, NULL_VALUE).build(); 603 // Set namespace properties 604 DeviceConfig.setProperties(properties); 605 // Ban namespace with related properties 606 DeviceConfig.resetToDefaults(Settings.RESET_MODE_PACKAGE_DEFAULTS, namespaceToBan); 607 // Verify given namespace properties are banned 608 assertThrows(DeviceConfig.BadConfigException.class, 609 () -> DeviceConfig.setProperties(properties)); 610 // Modify properties and verify we can set them 611 Properties modifiedProperties = new Properties.Builder(namespaceToBan).setString(KEY, VALUE) 612 .setString(KEY4, NULL_VALUE).setString(KEY2, VALUE2).build(); 613 DeviceConfig.setProperties(modifiedProperties); 614 modifiedProperties = DeviceConfig.getProperties(namespaceToBan); 615 assertThat(modifiedProperties.getKeyset()).containsExactly(KEY, KEY2, KEY4); 616 assertThat(modifiedProperties.getString(KEY, DEFAULT_VALUE)).isEqualTo(VALUE); 617 assertThat(modifiedProperties.getString(KEY2, DEFAULT_VALUE)).isEqualTo(VALUE2); 618 // Since value is null DEFAULT_VALUE should be returned 619 assertThat(modifiedProperties.getString(KEY4, DEFAULT_VALUE)).isEqualTo(DEFAULT_VALUE); 620 } 621 622 @Test banEntireDeviceConfig()623 public void banEntireDeviceConfig() throws DeviceConfig.BadConfigException { 624 // Given namespaces will be permanently banned, thus they need to be different every time 625 final String namespaceToBan1 = NAMESPACE + System.currentTimeMillis(); 626 final String namespaceToBan2 = NAMESPACE + System.currentTimeMillis() + 1; 627 628 // Set namespaces properties 629 Properties properties1 = new Properties.Builder(namespaceToBan1).setString(KEY, VALUE) 630 .setString(KEY4, NULL_VALUE).build(); 631 DeviceConfig.setProperties(properties1); 632 Properties properties2 = new Properties.Builder(namespaceToBan2).setString(KEY2, VALUE2) 633 .setString(KEY4, NULL_VALUE).build(); 634 DeviceConfig.setProperties(properties2); 635 636 // Ban entire DeviceConfig 637 DeviceConfig.resetToDefaults(Settings.RESET_MODE_PACKAGE_DEFAULTS, null); 638 639 // Verify given namespace properties are banned 640 assertThrows(DeviceConfig.BadConfigException.class, 641 () -> DeviceConfig.setProperties(properties1)); 642 assertThrows(DeviceConfig.BadConfigException.class, 643 () -> DeviceConfig.setProperties(properties2)); 644 645 // Modify properties and verify we can set them 646 Properties modifiedProperties1 = new Properties.Builder(namespaceToBan1).setString(KEY, 647 VALUE) 648 .setString(KEY4, NULL_VALUE).setString(KEY2, VALUE2).build(); 649 DeviceConfig.setProperties(modifiedProperties1); 650 modifiedProperties1 = DeviceConfig.getProperties(namespaceToBan1); 651 assertThat(modifiedProperties1.getKeyset()).containsExactly(KEY, KEY2, KEY4); 652 assertThat(modifiedProperties1.getString(KEY, DEFAULT_VALUE)).isEqualTo(VALUE); 653 assertThat(modifiedProperties1.getString(KEY2, DEFAULT_VALUE)).isEqualTo(VALUE2); 654 // Since value is null DEFAULT_VALUE should be returned 655 assertThat(modifiedProperties1.getString(KEY4, DEFAULT_VALUE)).isEqualTo(DEFAULT_VALUE); 656 657 Properties modifiedProperties2 = new Properties.Builder(namespaceToBan2).setString(KEY, 658 VALUE) 659 .setString(KEY3, NULL_VALUE).setString(KEY4, VALUE2).build(); 660 DeviceConfig.setProperties(modifiedProperties2); 661 modifiedProperties2 = DeviceConfig.getProperties(namespaceToBan2); 662 assertThat(modifiedProperties2.getKeyset()).containsExactly(KEY, KEY3, KEY4); 663 assertThat(modifiedProperties2.getString(KEY, DEFAULT_VALUE)).isEqualTo(VALUE); 664 assertThat(modifiedProperties2.getString(KEY4, DEFAULT_VALUE)).isEqualTo(VALUE2); 665 // Since value is null DEFAULT_VALUE should be returned 666 assertThat(modifiedProperties2.getString(KEY3, DEFAULT_VALUE)).isEqualTo(DEFAULT_VALUE); 667 } 668 669 @Test allConfigsUnbannedIfAnyUnbannedConfigUpdated()670 public void allConfigsUnbannedIfAnyUnbannedConfigUpdated() 671 throws DeviceConfig.BadConfigException { 672 // Given namespaces will be permanently banned, thus they need to be different every time 673 final String namespaceToBan1 = NAMESPACE + System.currentTimeMillis(); 674 final String namespaceToBan2 = NAMESPACE + System.currentTimeMillis() + 1; 675 676 // Set namespaces properties 677 Properties properties1 = new Properties.Builder(namespaceToBan1).setString(KEY, VALUE) 678 .setString(KEY4, NULL_VALUE).build(); 679 DeviceConfig.setProperties(properties1); 680 Properties properties2 = new Properties.Builder(namespaceToBan2).setString(KEY2, VALUE2) 681 .setString(KEY4, NULL_VALUE).build(); 682 DeviceConfig.setProperties(properties2); 683 684 // Ban namespace with related properties 685 DeviceConfig.resetToDefaults(Settings.RESET_MODE_PACKAGE_DEFAULTS, namespaceToBan1); 686 DeviceConfig.resetToDefaults(Settings.RESET_MODE_PACKAGE_DEFAULTS, namespaceToBan2); 687 688 // Verify given namespace properties are banned 689 assertThrows(DeviceConfig.BadConfigException.class, 690 () -> DeviceConfig.setProperties(properties1)); 691 assertThrows(DeviceConfig.BadConfigException.class, 692 () -> DeviceConfig.setProperties(properties2)); 693 694 // Modify properties and verify we can set them 695 Properties modifiedProperties1 = new Properties.Builder(namespaceToBan1).setString(KEY, 696 VALUE) 697 .setString(KEY4, NULL_VALUE).setString(KEY2, VALUE2).build(); 698 DeviceConfig.setProperties(modifiedProperties1); 699 modifiedProperties1 = DeviceConfig.getProperties(namespaceToBan1); 700 assertThat(modifiedProperties1.getKeyset()).containsExactly(KEY, KEY2, KEY4); 701 assertThat(modifiedProperties1.getString(KEY, DEFAULT_VALUE)).isEqualTo(VALUE); 702 assertThat(modifiedProperties1.getString(KEY2, DEFAULT_VALUE)).isEqualTo(VALUE2); 703 // Since value is null DEFAULT_VALUE should be returned 704 assertThat(modifiedProperties1.getString(KEY4, DEFAULT_VALUE)).isEqualTo(DEFAULT_VALUE); 705 706 // verify that other banned namespaces are unbanned now. 707 DeviceConfig.setProperties(properties2); 708 Properties result = DeviceConfig.getProperties(namespaceToBan2); 709 assertThat(result.getKeyset()).containsExactly(KEY2, KEY4); 710 assertThat(result.getString(KEY2, DEFAULT_VALUE)).isEqualTo(VALUE2); 711 // Since value is null DEFAULT_VALUE should be returned 712 assertThat(result.getString(KEY4, DEFAULT_VALUE)).isEqualTo(DEFAULT_VALUE); 713 } 714 715 @Test onPropertiesChangedListener_setPropertyCallback()716 public void onPropertiesChangedListener_setPropertyCallback() throws InterruptedException { 717 final AtomicReference<Properties> changedProperties = new AtomicReference<>(); 718 final CompletableFuture<Boolean> completed = new CompletableFuture<>(); 719 720 DeviceConfig.OnPropertiesChangedListener changeListener = (properties) -> { 721 changedProperties.set(properties); 722 completed.complete(true); 723 }; 724 725 try { 726 DeviceConfig.addOnPropertiesChangedListener(NAMESPACE, 727 Objects.requireNonNull(ActivityThread.currentApplication()).getMainExecutor(), 728 changeListener); 729 DeviceConfig.setProperty(NAMESPACE, KEY, VALUE, false); 730 731 assertThat(completed.get( 732 WAIT_FOR_PROPERTY_CHANGE_TIMEOUT_MILLIS, TimeUnit.MILLISECONDS)).isTrue(); 733 734 Properties properties = changedProperties.get(); 735 assertThat(properties.getNamespace()).isEqualTo(NAMESPACE); 736 assertThat(properties.getKeyset()).contains(KEY); 737 assertThat(properties.getString(KEY, "default_value")).isEqualTo(VALUE); 738 } catch (ExecutionException | TimeoutException | InterruptedException e) { 739 Assert.fail(e.getMessage()); 740 } finally { 741 DeviceConfig.removeOnPropertiesChangedListener(changeListener); 742 } 743 } 744 745 @Test onPropertiesChangedListener_setPropertiesCallback()746 public void onPropertiesChangedListener_setPropertiesCallback() { 747 DeviceConfig.setProperty(NAMESPACE, KEY, VALUE, false); 748 DeviceConfig.setProperty(NAMESPACE, KEY2, VALUE2, false); 749 750 Map<String, String> keyValues = new HashMap<>(2); 751 keyValues.put(KEY, VALUE2); 752 keyValues.put(KEY3, VALUE3); 753 Properties setProperties = new Properties(NAMESPACE, keyValues); 754 755 final AtomicReference<Properties> changedProperties = new AtomicReference<>(); 756 final CompletableFuture<Boolean> completed = new CompletableFuture<>(); 757 758 DeviceConfig.OnPropertiesChangedListener changeListener = (properties) -> { 759 changedProperties.set(properties); 760 completed.complete(true); 761 }; 762 763 try { 764 DeviceConfig.addOnPropertiesChangedListener(NAMESPACE, 765 Objects.requireNonNull(ActivityThread.currentApplication()).getMainExecutor(), 766 changeListener); 767 DeviceConfig.setProperties(setProperties); 768 769 assertThat(completed.get( 770 WAIT_FOR_PROPERTY_CHANGE_TIMEOUT_MILLIS, TimeUnit.MILLISECONDS)).isTrue(); 771 772 if (changedProperties.get().getKeyset().size() != 3) { 773 // Sometimes there are a few onChanged callback calls. Let's wait a bit more. 774 final int oneMoreOnChangedDelayMs = 100; 775 Thread.currentThread().sleep(oneMoreOnChangedDelayMs); 776 } 777 778 Properties properties = changedProperties.get(); 779 assertThat(properties.getNamespace()).isEqualTo(NAMESPACE); 780 assertThat(properties.getKeyset()).containsExactly(KEY, KEY2, KEY3); 781 // KEY updated from VALUE to VALUE2 782 assertThat(properties.getString(KEY, "default_value")).isEqualTo(VALUE2); 783 // KEY2 deleted (returns default_value) 784 assertThat(properties.getString(KEY2, "default_value")).isEqualTo("default_value"); 785 // KEY3 added with VALUE3 786 assertThat(properties.getString(KEY3, "default_value")).isEqualTo(VALUE3); 787 } catch (ExecutionException | TimeoutException | InterruptedException e) { 788 Assert.fail(e.getMessage()); 789 } catch (DeviceConfig.BadConfigException e) { 790 Assert.fail(e.getMessage()); 791 } finally { 792 DeviceConfig.removeOnPropertiesChangedListener(changeListener); 793 } 794 } 795 796 @Test syncDisabling()797 public void syncDisabling() throws Exception { 798 Properties properties1 = new Properties.Builder(NAMESPACE) 799 .setString(KEY, VALUE) 800 .build(); 801 Properties properties2 = new Properties.Builder(NAMESPACE) 802 .setString(KEY, VALUE2) 803 .build(); 804 805 try { 806 // Ensure the device starts in a known state. 807 DeviceConfig.setSyncDisabledMode(DeviceConfig.SYNC_DISABLED_MODE_NONE); 808 809 // Assert starting state. 810 assertThat(DeviceConfig.getSyncDisabledMode()) 811 .isEqualTo(DeviceConfig.SYNC_DISABLED_MODE_NONE); 812 assertThat(DeviceConfig.setProperties(properties1)).isTrue(); 813 assertThat(DeviceConfig.getProperties(NAMESPACE, KEY).getString(KEY, DEFAULT_VALUE)) 814 .isEqualTo(VALUE); 815 816 // Test disabled (persistent). Persistence is not actually tested, that would require 817 // a host test. 818 DeviceConfig.setSyncDisabledMode(DeviceConfig.SYNC_DISABLED_MODE_PERSISTENT); 819 assertThat(DeviceConfig.getSyncDisabledMode()) 820 .isEqualTo(DeviceConfig.SYNC_DISABLED_MODE_PERSISTENT); 821 assertThat(DeviceConfig.setProperties(properties2)).isFalse(); 822 assertThat(DeviceConfig.getProperties(NAMESPACE, KEY).getString(KEY, DEFAULT_VALUE)) 823 .isEqualTo(VALUE); 824 825 // Return to not disabled. 826 DeviceConfig.setSyncDisabledMode(DeviceConfig.SYNC_DISABLED_MODE_NONE); 827 assertThat(DeviceConfig.getSyncDisabledMode()) 828 .isEqualTo(DeviceConfig.SYNC_DISABLED_MODE_NONE); 829 assertThat(DeviceConfig.setProperties(properties2)).isTrue(); 830 assertThat(DeviceConfig.getProperties(NAMESPACE, KEY).getString(KEY, DEFAULT_VALUE)) 831 .isEqualTo(VALUE2); 832 833 // Test disabled (persistent). Absence of persistence is not actually tested, that would 834 // require a host test. 835 DeviceConfig.setSyncDisabledMode(DeviceConfig.SYNC_DISABLED_MODE_UNTIL_REBOOT); 836 assertThat(DeviceConfig.getSyncDisabledMode()) 837 .isEqualTo(DeviceConfig.SYNC_DISABLED_MODE_UNTIL_REBOOT); 838 assertThat(DeviceConfig.setProperties(properties1)).isFalse(); 839 assertThat(DeviceConfig.getProperties(NAMESPACE, KEY).getString(KEY, DEFAULT_VALUE)) 840 .isEqualTo(VALUE2); 841 842 // Return to not disabled. 843 DeviceConfig.setSyncDisabledMode(DeviceConfig.SYNC_DISABLED_MODE_NONE); 844 assertThat(DeviceConfig.getSyncDisabledMode()) 845 .isEqualTo(DeviceConfig.SYNC_DISABLED_MODE_NONE); 846 assertThat(DeviceConfig.setProperties(properties1)).isTrue(); 847 assertThat(DeviceConfig.getProperties(NAMESPACE, KEY).getString(KEY, DEFAULT_VALUE)) 848 .isEqualTo(VALUE); 849 } finally { 850 // Try to return to the default sync disabled state in case of failure. 851 DeviceConfig.setSyncDisabledMode(DeviceConfig.SYNC_DISABLED_MODE_NONE); 852 853 // NAMESPACE will be cleared by cleanUp() 854 } 855 } 856 deleteViaContentProvider(String namespace, String key)857 private static boolean deleteViaContentProvider(String namespace, String key) { 858 ContentResolver resolver = InstrumentationRegistry.getContext().getContentResolver(); 859 String compositeName = namespace + "/" + key; 860 Bundle result = resolver.call( 861 Settings.Config.CONTENT_URI, 862 Settings.CALL_METHOD_DELETE_CONFIG, 863 compositeName, 864 null); 865 assertThat(result).isNotNull(); 866 return compositeName.equals(result.getString(Settings.NameValueTable.VALUE)); 867 } 868 869 @Test deleteProperty_nullNamespace()870 public void deleteProperty_nullNamespace() { 871 try { 872 DeviceConfig.deleteProperty(null, KEY); 873 Assert.fail("Null namespace should have resulted in an NPE."); 874 } catch (NullPointerException e) { 875 // expected 876 } 877 } 878 879 @Test deleteProperty_nullName()880 public void deleteProperty_nullName() { 881 try { 882 DeviceConfig.deleteProperty(NAMESPACE, null); 883 Assert.fail("Null name should have resulted in an NPE."); 884 } catch (NullPointerException e) { 885 // expected 886 } 887 } 888 889 @Test deletePropertyString()890 public void deletePropertyString() { 891 final String value = "new_value"; 892 final String default_value = "default"; 893 DeviceConfig.setProperty(NAMESPACE, KEY, value, false); 894 DeviceConfig.deleteProperty(NAMESPACE, KEY); 895 final String result = DeviceConfig.getString(NAMESPACE, KEY, default_value); 896 assertThat(result).isEqualTo(default_value); 897 } 898 899 @Test deletePropertyBoolean()900 public void deletePropertyBoolean() { 901 final boolean value = true; 902 final boolean default_value = false; 903 DeviceConfig.setProperty(NAMESPACE, KEY, String.valueOf(value), false); 904 DeviceConfig.deleteProperty(NAMESPACE, KEY); 905 final boolean result = DeviceConfig.getBoolean(NAMESPACE, KEY, default_value); 906 assertThat(result).isEqualTo(default_value); 907 } 908 909 @Test deletePropertyInt()910 public void deletePropertyInt() { 911 final int value = 123; 912 final int default_value = 999; 913 DeviceConfig.setProperty(NAMESPACE, KEY, String.valueOf(value), false); 914 DeviceConfig.deleteProperty(NAMESPACE, KEY); 915 final int result = DeviceConfig.getInt(NAMESPACE, KEY, default_value); 916 assertThat(result).isEqualTo(default_value); 917 } 918 919 @Test deletePropertyLong()920 public void deletePropertyLong() { 921 final long value = 456789; 922 final long default_value = 123456; 923 DeviceConfig.setProperty(NAMESPACE, KEY, String.valueOf(value), false); 924 DeviceConfig.deleteProperty(NAMESPACE, KEY); 925 final long result = DeviceConfig.getLong(NAMESPACE, KEY, default_value); 926 assertThat(result).isEqualTo(default_value); 927 } 928 929 @Test deletePropertyFloat()930 public void deletePropertyFloat() { 931 final float value = 456.789f; 932 final float default_value = 123.456f; 933 DeviceConfig.setProperty(NAMESPACE, KEY, String.valueOf(value), false); 934 DeviceConfig.deleteProperty(NAMESPACE, KEY); 935 final float result = DeviceConfig.getFloat(NAMESPACE, KEY, default_value); 936 assertThat(result).isEqualTo(default_value); 937 } 938 939 @Test deleteProperty_empty()940 public void deleteProperty_empty() { 941 assertThat(DeviceConfig.deleteProperty(NAMESPACE, KEY)).isTrue(); 942 final String result = DeviceConfig.getString(NAMESPACE, KEY, null); 943 assertThat(result).isNull(); 944 } 945 } 946