• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2015 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package com.android.providers.settings;
18 
19 import static junit.framework.Assert.assertEquals;
20 import static junit.framework.Assert.assertNull;
21 import static junit.framework.Assert.assertSame;
22 import static junit.framework.Assert.fail;
23 
24 import android.content.ContentResolver;
25 import android.content.ContentValues;
26 import android.database.ContentObserver;
27 import android.database.Cursor;
28 import android.net.Uri;
29 import android.os.Handler;
30 import android.os.Looper;
31 import android.os.SystemClock;
32 import android.os.UserHandle;
33 import android.provider.Settings;
34 import android.util.Log;
35 
36 import org.junit.Test;
37 
38 import java.util.concurrent.atomic.AtomicBoolean;
39 
40 /**
41  * Tests for the SettingContentProvider.
42  *
43  * Before you run this test you must add a secondary user.
44  */
45 public class SettingsProviderTest extends BaseSettingsProviderTest {
46     private static final String LOG_TAG = "SettingsProviderTest";
47 
48     private static final long WAIT_FOR_SETTING_URI_CHANGE_TIMEOUT_MILLIS = 2000; // 2 sec
49 
50     private static final String[] NAME_VALUE_COLUMNS = new String[]{
51             Settings.NameValueTable.NAME, Settings.NameValueTable.VALUE
52     };
53 
54     private final Object mLock = new Object();
55 
56     @Test
testSetAndGetGlobalViaFrontEndApiForSystemUser()57     public void testSetAndGetGlobalViaFrontEndApiForSystemUser() throws Exception {
58         performSetAndGetSettingTestViaFrontEndApi(SETTING_TYPE_GLOBAL, UserHandle.USER_SYSTEM);
59     }
60 
61     @Test
testSetAndGetGlobalViaFrontEndApiForNonSystemUser()62     public void testSetAndGetGlobalViaFrontEndApiForNonSystemUser() throws Exception {
63         final int secondaryUserId = getSecondaryUserId();
64         if (secondaryUserId == UserHandle.USER_SYSTEM) {
65             Log.w(LOG_TAG, "No secondary user. Skipping "
66                     + "testSetAndGetGlobalViaFrontEndApiForNonSystemUser");
67             return;
68         }
69         performSetAndGetSettingTestViaFrontEndApi(SETTING_TYPE_GLOBAL, secondaryUserId);
70     }
71 
72     @Test
testSetAndGetSecureViaFrontEndApiForSystemUser()73     public void testSetAndGetSecureViaFrontEndApiForSystemUser() throws Exception {
74         performSetAndGetSettingTestViaFrontEndApi(SETTING_TYPE_SECURE, UserHandle.USER_SYSTEM);
75     }
76 
77     @Test
testSetAndGetSecureViaFrontEndApiForNonSystemUser()78     public void testSetAndGetSecureViaFrontEndApiForNonSystemUser() throws Exception {
79         final int secondaryUserId = getSecondaryUserId();
80         if (secondaryUserId == UserHandle.USER_SYSTEM) {
81             Log.w(LOG_TAG, "No secondary user. Skipping "
82                     + "testSetAndGetSecureViaFrontEndApiForNonSystemUser");
83             return;
84         }
85         performSetAndGetSettingTestViaFrontEndApi(SETTING_TYPE_SECURE, secondaryUserId);
86     }
87 
88     @Test
testSetAndGetSystemViaFrontEndApiForSystemUser()89     public void testSetAndGetSystemViaFrontEndApiForSystemUser() throws Exception {
90         performSetAndGetSettingTestViaFrontEndApi(SETTING_TYPE_SYSTEM, UserHandle.USER_SYSTEM);
91     }
92 
93     @Test
testSetAndGetSystemViaFrontEndApiForNonSystemUser()94     public void testSetAndGetSystemViaFrontEndApiForNonSystemUser() throws Exception {
95         final int secondaryUserId = getSecondaryUserId();
96         if (secondaryUserId == UserHandle.USER_SYSTEM) {
97             Log.w(LOG_TAG, "No secondary user. Skipping "
98                     + "testSetAndGetSystemViaFrontEndApiForNonSystemUser");
99             return;
100         }
101         performSetAndGetSettingTestViaFrontEndApi(SETTING_TYPE_SYSTEM, secondaryUserId);
102     }
103 
104     @Test
testSetAndGetGlobalViaProviderApi()105     public void testSetAndGetGlobalViaProviderApi() throws Exception {
106         performSetAndGetSettingTestViaProviderApi(SETTING_TYPE_GLOBAL);
107     }
108 
109     @Test
testSetAndGetSecureViaProviderApi()110     public void testSetAndGetSecureViaProviderApi() throws Exception {
111         performSetAndGetSettingTestViaProviderApi(SETTING_TYPE_SECURE);
112     }
113 
114     @Test
testSetAndGetSystemViaProviderApi()115     public void testSetAndGetSystemViaProviderApi() throws Exception {
116         performSetAndGetSettingTestViaProviderApi(SETTING_TYPE_SYSTEM);
117     }
118 
119     @Test
testSelectAllGlobalViaProviderApi()120     public void testSelectAllGlobalViaProviderApi() throws Exception {
121         setSettingViaProviderApiAndAssertSuccessfulChange(SETTING_TYPE_GLOBAL,
122                 FAKE_SETTING_NAME, FAKE_SETTING_VALUE, false);
123         try {
124             queryAllSettingsViaProviderApiSettingAndAssertSettingPresent(SETTING_TYPE_GLOBAL,
125                     FAKE_SETTING_NAME);
126         } finally {
127             deleteStringViaProviderApi(SETTING_TYPE_GLOBAL, FAKE_SETTING_NAME);
128         }
129     }
130 
131     // TODO(b/142206242): make this less flaky and re-enable it
132 //    @Test
133 //    public void testSelectAllSecureViaProviderApi() throws Exception {
134 //        setSettingViaProviderApiAndAssertSuccessfulChange(SETTING_TYPE_SECURE,
135 //                FAKE_SETTING_NAME, FAKE_SETTING_VALUE, false);
136 //        try {
137 //            queryAllSettingsViaProviderApiSettingAndAssertSettingPresent(SETTING_TYPE_SECURE,
138 //                    FAKE_SETTING_NAME);
139 //        } finally {
140 //            deleteStringViaProviderApi(SETTING_TYPE_SECURE, FAKE_SETTING_NAME);
141 //        }
142 //    }
143 
144     @Test
testSelectAllSystemViaProviderApi()145     public void testSelectAllSystemViaProviderApi() throws Exception {
146         setSettingViaProviderApiAndAssertSuccessfulChange(SETTING_TYPE_SYSTEM,
147                 FAKE_SETTING_NAME, FAKE_SETTING_VALUE, true);
148         try {
149             queryAllSettingsViaProviderApiSettingAndAssertSettingPresent(SETTING_TYPE_SYSTEM,
150                     FAKE_SETTING_NAME);
151         } finally {
152             deleteStringViaProviderApi(SETTING_TYPE_SYSTEM, FAKE_SETTING_NAME);
153         }
154     }
155 
156     @Test
testQueryUpdateDeleteGlobalViaProviderApi()157     public void testQueryUpdateDeleteGlobalViaProviderApi() throws Exception {
158         doTestQueryUpdateDeleteGlobalViaProviderApiForType(SETTING_TYPE_GLOBAL);
159     }
160 
161     @Test
testQueryUpdateDeleteSecureViaProviderApi()162     public void testQueryUpdateDeleteSecureViaProviderApi() throws Exception {
163         doTestQueryUpdateDeleteGlobalViaProviderApiForType(SETTING_TYPE_SECURE);
164     }
165 
166     @Test
testQueryUpdateDeleteSystemViaProviderApi()167     public void testQueryUpdateDeleteSystemViaProviderApi() throws Exception {
168         doTestQueryUpdateDeleteGlobalViaProviderApiForType(SETTING_TYPE_SYSTEM);
169     }
170 
171     @Test
testBulkInsertGlobalViaProviderApi()172     public void testBulkInsertGlobalViaProviderApi() throws Exception {
173         toTestBulkInsertViaProviderApiForType(SETTING_TYPE_GLOBAL);
174     }
175 
176     @Test
testBulkInsertSystemViaProviderApi()177     public void testBulkInsertSystemViaProviderApi() throws Exception {
178         toTestBulkInsertViaProviderApiForType(SETTING_TYPE_SYSTEM);
179     }
180 
181     @Test
testBulkInsertSecureViaProviderApi()182     public void testBulkInsertSecureViaProviderApi() throws Exception {
183         toTestBulkInsertViaProviderApiForType(SETTING_TYPE_SECURE);
184     }
185 
186     @Test
testAppCannotRunsSystemOutOfMemoryWritingSystemSettings()187     public void testAppCannotRunsSystemOutOfMemoryWritingSystemSettings() throws Exception {
188         int insertedCount = 0;
189         try {
190             for (; insertedCount < 1200; insertedCount++) {
191                 Log.w(LOG_TAG, "Adding app specific setting: " + insertedCount);
192                 insertStringViaProviderApi(SETTING_TYPE_SYSTEM,
193                         String.valueOf(insertedCount), FAKE_SETTING_VALUE, false);
194             }
195             fail("Adding app specific settings must be bound.");
196         } catch (Exception e) {
197             // expected
198         } finally {
199             for (; insertedCount >= 0; insertedCount--) {
200                 Log.w(LOG_TAG, "Removing app specific setting: " + insertedCount);
201                 deleteStringViaProviderApi(SETTING_TYPE_SYSTEM,
202                         String.valueOf(insertedCount));
203             }
204         }
205     }
206 
207     @Test
testQueryStringInBracketsGlobalViaProviderApiForType()208     public void testQueryStringInBracketsGlobalViaProviderApiForType() throws Exception {
209         doTestQueryStringInBracketsViaProviderApiForType(SETTING_TYPE_GLOBAL);
210     }
211 
212     @Test
testQueryStringInBracketsSecureViaProviderApiForType()213     public void testQueryStringInBracketsSecureViaProviderApiForType() throws Exception {
214         doTestQueryStringInBracketsViaProviderApiForType(SETTING_TYPE_SECURE);
215     }
216 
217     @Test
testQueryStringInBracketsSystemViaProviderApiForType()218     public void testQueryStringInBracketsSystemViaProviderApiForType() throws Exception {
219         doTestQueryStringInBracketsViaProviderApiForType(SETTING_TYPE_SYSTEM);
220     }
221 
222     @Test
testQueryStringWithAppendedNameToUriViaProviderApi()223     public void testQueryStringWithAppendedNameToUriViaProviderApi() throws Exception {
224         // Make sure we have a clean slate.
225         deleteStringViaProviderApi(SETTING_TYPE_SYSTEM, FAKE_SETTING_NAME);
226 
227         try {
228             // Insert the setting.
229             final Uri uri = insertStringViaProviderApi(SETTING_TYPE_SYSTEM, FAKE_SETTING_NAME,
230                     FAKE_SETTING_VALUE, false);
231             Uri expectUri = Uri.withAppendedPath(getBaseUriForType(SETTING_TYPE_SYSTEM),
232                     FAKE_SETTING_NAME);
233             assertEquals("Did not get expected Uri.", expectUri, uri);
234 
235             // Make sure the first setting is there.
236             String firstValue = queryStringViaProviderApi(SETTING_TYPE_SYSTEM, FAKE_SETTING_NAME,
237                     false, true);
238             assertEquals("Setting must be present", FAKE_SETTING_VALUE, firstValue);
239         } finally {
240             // Clean up.
241             deleteStringViaProviderApi(SETTING_TYPE_SYSTEM, FAKE_SETTING_NAME);
242         }
243     }
244 
245     @Test
testResetModePackageDefaultsGlobal()246     public void testResetModePackageDefaultsGlobal() throws Exception {
247         testResetModePackageDefaultsCommon(SETTING_TYPE_GLOBAL);
248     }
249 
250     @Test
testResetModePackageDefaultsSecure()251     public void testResetModePackageDefaultsSecure() throws Exception {
252         testResetModePackageDefaultsCommon(SETTING_TYPE_SECURE);
253     }
254 
testResetModePackageDefaultsCommon(int type)255     private void testResetModePackageDefaultsCommon(int type) throws Exception {
256         // Make sure we have a clean slate.
257         setSettingViaShell(type, FAKE_SETTING_NAME, null, true);
258         try {
259             // Set a value but don't make it the default
260             setSettingViaShell(type, FAKE_SETTING_NAME,
261                     FAKE_SETTING_VALUE, false);
262 
263             // Reset the changes made by the "shell/root" package
264             resetToDefaultsViaShell(type, "com.android.shell");
265             resetToDefaultsViaShell(type, "root");
266 
267             // Make sure the old APIs don't set defaults
268             assertNull(getSetting(type, FAKE_SETTING_NAME));
269 
270             // Set a value and make it the default
271             setSettingViaShell(type, FAKE_SETTING_NAME,
272                     FAKE_SETTING_VALUE, true);
273             // Change the setting from the default
274             setSettingViaShell(type, FAKE_SETTING_NAME,
275                     FAKE_SETTING_VALUE_2, false);
276 
277             // Reset the changes made by this package
278             resetToDefaultsViaShell(type, "com.android.shell");
279             resetToDefaultsViaShell(type, "root");
280 
281             // Make sure the old APIs don't set defaults
282             assertEquals(FAKE_SETTING_VALUE, getSetting(type, FAKE_SETTING_NAME));
283         } finally {
284             // Make sure we have a clean slate.
285             setSettingViaShell(type, FAKE_SETTING_NAME, null, true);
286         }
287     }
288 
289     @Test
testResetModePackageDefaultsWithTokensGlobal()290     public void testResetModePackageDefaultsWithTokensGlobal() throws Exception {
291         testResetModePackageDefaultsWithTokensCommon(SETTING_TYPE_GLOBAL);
292     }
293 
294     @Test
testResetModePackageDefaultsWithTokensSecure()295     public void testResetModePackageDefaultsWithTokensSecure() throws Exception {
296         testResetModePackageDefaultsWithTokensCommon(SETTING_TYPE_SECURE);
297     }
298 
testResetModePackageDefaultsWithTokensCommon(int type)299     private void testResetModePackageDefaultsWithTokensCommon(int type) throws Exception {
300         // Make sure we have a clean slate.
301         setSettingViaShell(type, FAKE_SETTING_NAME, null, true);
302         setSettingViaShell(type, FAKE_SETTING_NAME_1, null, true);
303         try {
304             // Set a default value
305             setSettingViaShell(type, FAKE_SETTING_NAME,
306                     FAKE_SETTING_VALUE, true);
307             // Change the default and associate a token
308             setSettingViaShell(type, FAKE_SETTING_NAME,
309                     FAKE_SETTING_VALUE_2, "TOKEN1", false);
310 
311             // Set a default value
312             setSettingViaShell(type, FAKE_SETTING_NAME_1,
313                     FAKE_SETTING_VALUE, "TOKEN2", true);
314             // Change the default and associate a token
315             setSettingViaShell(type, FAKE_SETTING_NAME_1,
316                     FAKE_SETTING_VALUE_2, "TOKEN2", false);
317 
318             // Reset settings associated with TOKEN1
319             resetToDefaultsViaShell(type, "com.android.shell", "TOKEN1");
320             resetToDefaultsViaShell(type, "root", "TOKEN1");
321 
322             // Make sure TOKEN1 settings are reset
323             assertEquals(FAKE_SETTING_VALUE, getSetting(type,
324                     FAKE_SETTING_NAME));
325 
326             // Make sure TOKEN2 settings are not reset
327             assertEquals(FAKE_SETTING_VALUE_2, getSetting(type,
328                     FAKE_SETTING_NAME_1));
329 
330             // Reset settings associated with TOKEN2
331             resetToDefaultsViaShell(type, "com.android.shell", "TOKEN2");
332             resetToDefaultsViaShell(type, "root", "TOKEN2");
333 
334             // Make sure TOKEN2 settings are reset
335             assertEquals(FAKE_SETTING_VALUE, getSetting(type,
336                     FAKE_SETTING_NAME_1));
337         } finally {
338             // Make sure we have a clean slate.
339             setSettingViaShell(type, FAKE_SETTING_NAME, null, true);
340             setSettingViaShell(type, FAKE_SETTING_NAME_1, null, true);
341         }
342     }
343 
344     @Test
testResetModeUntrustedDefaultsGlobal()345     public void testResetModeUntrustedDefaultsGlobal() throws Exception {
346         testResetModeUntrustedDefaultsCommon(SETTING_TYPE_GLOBAL);
347     }
348 
349     @Test
testResetModeUntrustedDefaultsSecure()350     public void testResetModeUntrustedDefaultsSecure() throws Exception {
351         testResetModeUntrustedDefaultsCommon(SETTING_TYPE_SECURE);
352     }
353 
testResetModeUntrustedDefaultsCommon(int type)354     private void testResetModeUntrustedDefaultsCommon(int type) throws Exception {
355         // Make sure we have a clean slate.
356         putSetting(type, FAKE_SETTING_NAME, null);
357         setSettingViaShell(type, FAKE_SETTING_NAME_1, null, true);
358         try {
359             // Set a default setting as a trusted component
360             putSetting(type, FAKE_SETTING_NAME, FAKE_SETTING_VALUE);
361             // Change the setting as a trusted component
362             putSetting(type, FAKE_SETTING_NAME, FAKE_SETTING_VALUE_2);
363 
364             // Set a default setting as an untrusted component
365             setSettingViaShell(type, FAKE_SETTING_NAME_1,
366                     FAKE_SETTING_VALUE, true);
367             // Change the setting as an untrusted component
368             setSettingViaShell(type, FAKE_SETTING_NAME_1,
369                     FAKE_SETTING_VALUE_2, false);
370 
371             // Reset the untrusted changes to defaults
372             resetSettingsViaShell(type,
373                     Settings.RESET_MODE_UNTRUSTED_DEFAULTS);
374 
375             // Check whether only the untrusted changes set to defaults
376             assertEquals(FAKE_SETTING_VALUE_2, getSetting(type, FAKE_SETTING_NAME));
377             assertEquals(FAKE_SETTING_VALUE, getSetting(type, FAKE_SETTING_NAME_1));
378         } finally {
379             // Make sure we have a clean slate.
380             putSetting(type, FAKE_SETTING_NAME, null);
381             setSettingViaShell(type, FAKE_SETTING_NAME_1, null, true);
382         }
383     }
384 
385     // TODO(b/142206242): make this less flaky and re-enable it
386 //    @Test
387 //    public void testResetModeUntrustedClearGlobal() throws Exception {
388 //        testResetModeUntrustedClearCommon(SETTING_TYPE_GLOBAL);
389 //    }
390 
391     @Test
testResetModeUntrustedClearSecure()392     public void testResetModeUntrustedClearSecure() throws Exception {
393         testResetModeUntrustedClearCommon(SETTING_TYPE_SECURE);
394     }
395 
testResetModeUntrustedClearCommon(int type)396     private void testResetModeUntrustedClearCommon(int type) throws Exception {
397         // Make sure we have a clean slate.
398         putSetting(type, FAKE_SETTING_NAME, null);
399         setSettingViaShell(type, FAKE_SETTING_NAME_1, null, true);
400         try {
401             // Set a default setting as a trusted component
402             putSetting(type, FAKE_SETTING_NAME, FAKE_SETTING_VALUE);
403             // Change the setting as a trusted component
404             putSetting(type, FAKE_SETTING_NAME, FAKE_SETTING_VALUE_2);
405 
406             // Set a default setting as an untrusted component
407             setSettingViaShell(type, FAKE_SETTING_NAME_1,
408                     FAKE_SETTING_VALUE, true);
409             // Change the setting as an untrusted component
410             setSettingViaShell(type, FAKE_SETTING_NAME_1,
411                     FAKE_SETTING_VALUE_2, false);
412 
413             // Clear the untrusted changes
414             resetSettingsViaShell(type,
415                     Settings.RESET_MODE_UNTRUSTED_CHANGES);
416 
417             // Check whether only the untrusted changes set to defaults
418             assertEquals(FAKE_SETTING_VALUE_2, getSetting(type, FAKE_SETTING_NAME));
419             assertNull(getSetting(type, FAKE_SETTING_NAME_1));
420         } finally {
421             // Make sure we have a clean slate.
422             putSetting(type, FAKE_SETTING_NAME, null);
423             setSettingViaShell(type, FAKE_SETTING_NAME_1, null, true);
424         }
425     }
426 
427     // TODO(b/142206242): make this less flaky and re-enable it
428 //    @Test
429 //    public void testResetModeTrustedDefaultsGlobal() throws Exception {
430 //        testResetModeTrustedDefaultsCommon(SETTING_TYPE_GLOBAL);
431 //    }
432 
433     @Test
testResetModeTrustedDefaultsSecure()434     public void testResetModeTrustedDefaultsSecure() throws Exception {
435         testResetModeTrustedDefaultsCommon(SETTING_TYPE_SECURE);
436     }
437 
testResetModeTrustedDefaultsCommon(int type)438     private void testResetModeTrustedDefaultsCommon(int type) throws Exception {
439         // Make sure we have a clean slate.
440         putSetting(type, FAKE_SETTING_NAME, null);
441         setSettingViaShell(type, FAKE_SETTING_NAME_1, null, true);
442         try {
443             // Set a default setting as a trusted component
444             putSetting(type, FAKE_SETTING_NAME, FAKE_SETTING_VALUE);
445             // Change the setting as a trusted component
446             setSettingViaShell(type, FAKE_SETTING_NAME, FAKE_SETTING_VALUE_2, false);
447 
448             // Set a default setting as an untrusted component
449             setSettingViaShell(type, FAKE_SETTING_NAME_1,
450                     FAKE_SETTING_VALUE, true);
451             // Change the setting as an untrusted component
452             setSettingViaShell(type, FAKE_SETTING_NAME_1,
453                     FAKE_SETTING_VALUE_2, false);
454 
455             // Reset to trusted defaults
456             resetSettingsViaShell(type,
457                     Settings.RESET_MODE_TRUSTED_DEFAULTS);
458 
459             // Check whether snapped to trusted defaults
460             assertEquals(FAKE_SETTING_VALUE, getSetting(type, FAKE_SETTING_NAME));
461             assertNull(getSetting(type, FAKE_SETTING_NAME_1));
462         } finally {
463             // Make sure we have a clean slate.
464             putSetting(type, FAKE_SETTING_NAME, null);
465             setSettingViaShell(type, FAKE_SETTING_NAME_1, null, true);
466         }
467     }
468 
doTestQueryStringInBracketsViaProviderApiForType(int type)469     private void doTestQueryStringInBracketsViaProviderApiForType(int type) {
470         // Make sure we have a clean slate.
471         deleteStringViaProviderApi(type, FAKE_SETTING_NAME);
472 
473         try {
474             // Insert the setting.
475             final Uri uri = insertStringViaProviderApi(type, FAKE_SETTING_NAME,
476                     FAKE_SETTING_VALUE, false);
477             Uri expectUri = Uri.withAppendedPath(getBaseUriForType(type), FAKE_SETTING_NAME);
478             assertEquals("Did not get expected Uri.", expectUri, uri);
479 
480             // Make sure the first setting is there.
481             String firstValue = queryStringViaProviderApi(type, FAKE_SETTING_NAME, true, false);
482             assertEquals("Setting must be present", FAKE_SETTING_VALUE, firstValue);
483         } finally {
484             // Clean up.
485             deleteStringViaProviderApi(type, FAKE_SETTING_NAME);
486         }
487     }
488 
toTestBulkInsertViaProviderApiForType(int type)489     private void toTestBulkInsertViaProviderApiForType(int type) {
490         // Make sure we have a clean slate.
491         deleteStringViaProviderApi(type, FAKE_SETTING_NAME);
492         deleteStringViaProviderApi(type, FAKE_SETTING_NAME_1);
493         deleteStringViaProviderApi(type, FAKE_SETTING_NAME_2);
494 
495         try {
496             Uri uri = getBaseUriForType(type);
497             ContentValues[] allValues = new ContentValues[3];
498 
499             // Insert the first setting.
500             ContentValues firstValues = new ContentValues();
501             firstValues.put(Settings.NameValueTable.NAME, FAKE_SETTING_NAME);
502             firstValues.put(Settings.NameValueTable.VALUE, FAKE_SETTING_VALUE);
503             allValues[0] = firstValues;
504 
505             // Insert the second setting.
506             ContentValues secondValues = new ContentValues();
507             secondValues.put(Settings.NameValueTable.NAME, FAKE_SETTING_NAME_1);
508             secondValues.put(Settings.NameValueTable.VALUE, FAKE_SETTING_VALUE_1);
509             allValues[1] = secondValues;
510 
511             // Insert the third setting. (null)
512             ContentValues thirdValues = new ContentValues();
513             thirdValues.put(Settings.NameValueTable.NAME, FAKE_SETTING_NAME_2);
514             thirdValues.put(Settings.NameValueTable.VALUE, FAKE_SETTING_VALUE_2);
515             allValues[2] = thirdValues;
516 
517             // Verify insertion count.
518             final int insertCount = getContext().getContentResolver().bulkInsert(uri, allValues);
519             assertSame("Couldn't insert both values", 3, insertCount);
520 
521             // Make sure the first setting is there.
522             String firstValue = queryStringViaProviderApi(type, FAKE_SETTING_NAME);
523             assertEquals("First setting must be present", FAKE_SETTING_VALUE, firstValue);
524 
525             // Make sure the second setting is there.
526             String secondValue = queryStringViaProviderApi(type, FAKE_SETTING_NAME_1);
527             assertEquals("Second setting must be present", FAKE_SETTING_VALUE_1, secondValue);
528 
529             // Make sure the third setting is there.
530             String thirdValue = queryStringViaProviderApi(type, FAKE_SETTING_NAME_2);
531             assertEquals("Third setting must be present", FAKE_SETTING_VALUE_2, thirdValue);
532         } finally {
533             // Clean up.
534             deleteStringViaProviderApi(type, FAKE_SETTING_NAME);
535             deleteStringViaProviderApi(type, FAKE_SETTING_NAME_1);
536             deleteStringViaProviderApi(type, FAKE_SETTING_NAME_2);
537         }
538     }
539 
doTestQueryUpdateDeleteGlobalViaProviderApiForType(int type)540     private void doTestQueryUpdateDeleteGlobalViaProviderApiForType(int type) throws Exception {
541         // Make sure it is not there.
542         deleteStringViaProviderApi(type, FAKE_SETTING_NAME);
543 
544         // Now selection should return nothing.
545         String value = queryStringViaProviderApi(type, FAKE_SETTING_NAME);
546         assertNull("Setting should not be present.", value);
547 
548         // Insert the setting.
549         Uri uri = insertStringViaProviderApi(type,
550                 FAKE_SETTING_NAME, FAKE_SETTING_VALUE, false);
551         Uri expectUri = Uri.withAppendedPath(getBaseUriForType(type), FAKE_SETTING_NAME);
552         assertEquals("Did not get expected Uri.", expectUri, uri);
553 
554         // Now selection should return the setting.
555         value = queryStringViaProviderApi(type, FAKE_SETTING_NAME);
556         assertEquals("Setting should be present.", FAKE_SETTING_VALUE, value);
557 
558         // Update the setting.
559         final int changeCount = updateStringViaProviderApiSetting(type,
560                 FAKE_SETTING_NAME, FAKE_SETTING_VALUE_1);
561         assertEquals("Did not get expected change count.", 1, changeCount);
562 
563         // Now selection should return the new setting.
564         value = queryStringViaProviderApi(type, FAKE_SETTING_NAME);
565         assertEquals("Setting should be present.", FAKE_SETTING_VALUE_1, value);
566 
567         // Delete the setting.
568         final int deletedCount = deleteStringViaProviderApi(type,
569                 FAKE_SETTING_NAME);
570         assertEquals("Did not get expected deleted count", 1, deletedCount);
571 
572         // Now selection should return nothing.
573         value = queryStringViaProviderApi(type, FAKE_SETTING_NAME);
574         assertNull("Setting should not be present.", value);
575     }
576 
performSetAndGetSettingTestViaFrontEndApi(int type, int userId)577     private void performSetAndGetSettingTestViaFrontEndApi(int type, int userId)
578             throws Exception {
579         try {
580             // Change the setting and assert a successful change.
581             setSettingViaFrontEndApiAndAssertSuccessfulChange(type, FAKE_SETTING_NAME,
582                     FAKE_SETTING_VALUE, userId);
583         } finally {
584             // Remove the setting.
585             setStringViaFrontEndApiSetting(type, FAKE_SETTING_NAME, null, userId);
586         }
587     }
588 
performSetAndGetSettingTestViaProviderApi(int type)589     private void performSetAndGetSettingTestViaProviderApi(int type)
590             throws Exception {
591         try {
592             // Change the setting and assert a successful change.
593             setSettingViaProviderApiAndAssertSuccessfulChange(type, FAKE_SETTING_NAME,
594                     FAKE_SETTING_VALUE, true);
595         } finally {
596             // Remove the setting.
597             setSettingViaProviderApiAndAssertSuccessfulChange(type, FAKE_SETTING_NAME, null,
598                     true);
599         }
600     }
601 
setSettingViaFrontEndApiAndAssertSuccessfulChange(final int type, final String name, final String value, final int userId)602     private void setSettingViaFrontEndApiAndAssertSuccessfulChange(final int type,
603             final String name, final String value, final int userId) throws Exception {
604         setSettingAndAssertSuccessfulChange(() -> {
605             setStringViaFrontEndApiSetting(type, name, value, userId);
606         }, type, name, value, userId);
607     }
608 
setSettingViaProviderApiAndAssertSuccessfulChange(final int type, final String name, final String value, final boolean withTableRowUri)609     private void setSettingViaProviderApiAndAssertSuccessfulChange(final int type,
610             final String name, final String value, final boolean withTableRowUri)
611             throws Exception {
612         setSettingAndAssertSuccessfulChange(() -> {
613             insertStringViaProviderApi(type, name, value, withTableRowUri);
614         }, type, name, value, UserHandle.USER_SYSTEM);
615     }
616 
setSettingAndAssertSuccessfulChange(Runnable setCommand, final int type, final String name, final String value, final int userId)617     private void setSettingAndAssertSuccessfulChange(Runnable setCommand, final int type,
618             final String name, final String value, final int userId) throws Exception {
619         ContentResolver contentResolver = getContext().getContentResolver();
620 
621         final Uri settingUri = getBaseUriForType(type).buildUpon().appendPath(name).build();
622 
623         final AtomicBoolean success = new AtomicBoolean();
624 
625         ContentObserver contentObserver = new ContentObserver(new Handler(Looper.getMainLooper())) {
626             public void onChange(boolean selfChange, Uri changeUri, int changeId) {
627                 Log.i(LOG_TAG, "onChange(" + selfChange + ", " + changeUri + ", " + changeId + ")");
628                 assertEquals("Wrong change Uri", changeUri, settingUri);
629                 assertEquals("Wrong user id", userId, changeId);
630                 String changeValue = getStringViaFrontEndApiSetting(type, name, userId);
631                 assertEquals("Wrong setting value", value, changeValue);
632 
633                 success.set(true);
634 
635                 synchronized (mLock) {
636                     mLock.notifyAll();
637                 }
638             }
639         };
640 
641         contentResolver.registerContentObserver(settingUri, false, contentObserver, userId);
642 
643         try {
644             setCommand.run();
645 
646             final long startTimeMillis = SystemClock.uptimeMillis();
647             synchronized (mLock) {
648                 while (true) {
649                     if (success.get()) {
650                         return;
651                     }
652                     final long elapsedTimeMillis = SystemClock.uptimeMillis() - startTimeMillis;
653                     if (elapsedTimeMillis >= WAIT_FOR_SETTING_URI_CHANGE_TIMEOUT_MILLIS) {
654                         fail("Could not change setting for "
655                                 + WAIT_FOR_SETTING_URI_CHANGE_TIMEOUT_MILLIS + " ms");
656                     }
657                     final long remainingTimeMillis = WAIT_FOR_SETTING_URI_CHANGE_TIMEOUT_MILLIS
658                             - elapsedTimeMillis;
659                     try {
660                         mLock.wait(remainingTimeMillis);
661                     } catch (InterruptedException ie) {
662                         /* ignore */
663                     }
664                 }
665             }
666         } finally {
667             contentResolver.unregisterContentObserver(contentObserver);
668         }
669     }
670 
queryAllSettingsViaProviderApiSettingAndAssertSettingPresent(int type, String name)671     private void queryAllSettingsViaProviderApiSettingAndAssertSettingPresent(int type,
672             String name) {
673         Uri uri = getBaseUriForType(type);
674 
675         Cursor cursor = getContext().getContentResolver().query(uri, NAME_VALUE_COLUMNS,
676                 null, null, null);
677 
678         if (cursor == null || !cursor.moveToFirst()) {
679             fail("Nothing selected");
680         }
681 
682         try {
683             final int nameColumnIdx = cursor.getColumnIndex(Settings.NameValueTable.NAME);
684 
685             while (cursor.moveToNext()) {
686                 String currentName = cursor.getString(nameColumnIdx);
687                 if (name.equals(currentName)) {
688                     return;
689                 }
690             }
691 
692             fail("Not found setting: " + name);
693         } finally {
694             cursor.close();
695         }
696     }
697 }
698