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