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