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     @Test
testSelectAllSecureViaProviderApi()132     public void testSelectAllSecureViaProviderApi() throws Exception {
133         setSettingViaProviderApiAndAssertSuccessfulChange(SETTING_TYPE_SECURE,
134                 FAKE_SETTING_NAME, FAKE_SETTING_VALUE, false);
135         try {
136             queryAllSettingsViaProviderApiSettingAndAssertSettingPresent(SETTING_TYPE_SECURE,
137                     FAKE_SETTING_NAME);
138         } finally {
139             deleteStringViaProviderApi(SETTING_TYPE_SECURE, FAKE_SETTING_NAME);
140         }
141     }
142 
143     @Test
testSelectAllSystemViaProviderApi()144     public void testSelectAllSystemViaProviderApi() throws Exception {
145         setSettingViaProviderApiAndAssertSuccessfulChange(SETTING_TYPE_SYSTEM,
146                 FAKE_SETTING_NAME, FAKE_SETTING_VALUE, true);
147         try {
148             queryAllSettingsViaProviderApiSettingAndAssertSettingPresent(SETTING_TYPE_SYSTEM,
149                     FAKE_SETTING_NAME);
150         } finally {
151             deleteStringViaProviderApi(SETTING_TYPE_SYSTEM, FAKE_SETTING_NAME);
152         }
153     }
154 
155     @Test
testQueryUpdateDeleteGlobalViaProviderApi()156     public void testQueryUpdateDeleteGlobalViaProviderApi() throws Exception {
157         doTestQueryUpdateDeleteGlobalViaProviderApiForType(SETTING_TYPE_GLOBAL);
158     }
159 
160     @Test
testQueryUpdateDeleteSecureViaProviderApi()161     public void testQueryUpdateDeleteSecureViaProviderApi() throws Exception {
162         doTestQueryUpdateDeleteGlobalViaProviderApiForType(SETTING_TYPE_SECURE);
163     }
164 
165     @Test
testQueryUpdateDeleteSystemViaProviderApi()166     public void testQueryUpdateDeleteSystemViaProviderApi() throws Exception {
167         doTestQueryUpdateDeleteGlobalViaProviderApiForType(SETTING_TYPE_SYSTEM);
168     }
169 
170     @Test
testBulkInsertGlobalViaProviderApi()171     public void testBulkInsertGlobalViaProviderApi() throws Exception {
172         toTestBulkInsertViaProviderApiForType(SETTING_TYPE_GLOBAL);
173     }
174 
175     @Test
testBulkInsertSystemViaProviderApi()176     public void testBulkInsertSystemViaProviderApi() throws Exception {
177         toTestBulkInsertViaProviderApiForType(SETTING_TYPE_SYSTEM);
178     }
179 
180     @Test
testBulkInsertSecureViaProviderApi()181     public void testBulkInsertSecureViaProviderApi() throws Exception {
182         toTestBulkInsertViaProviderApiForType(SETTING_TYPE_SECURE);
183     }
184 
185     @Test
testAppCannotRunsSystemOutOfMemoryWritingSystemSettings()186     public void testAppCannotRunsSystemOutOfMemoryWritingSystemSettings() throws Exception {
187         int insertedCount = 0;
188         try {
189             for (; insertedCount < 1200; insertedCount++) {
190                 Log.w(LOG_TAG, "Adding app specific setting: " + insertedCount);
191                 insertStringViaProviderApi(SETTING_TYPE_SYSTEM,
192                         String.valueOf(insertedCount), FAKE_SETTING_VALUE, false);
193             }
194             fail("Adding app specific settings must be bound.");
195         } catch (Exception e) {
196             // expected
197         } finally {
198             for (; insertedCount >= 0; insertedCount--) {
199                 Log.w(LOG_TAG, "Removing app specific setting: " + insertedCount);
200                 deleteStringViaProviderApi(SETTING_TYPE_SYSTEM,
201                         String.valueOf(insertedCount));
202             }
203         }
204     }
205 
206     @Test
testQueryStringInBracketsGlobalViaProviderApiForType()207     public void testQueryStringInBracketsGlobalViaProviderApiForType() throws Exception {
208         doTestQueryStringInBracketsViaProviderApiForType(SETTING_TYPE_GLOBAL);
209     }
210 
211     @Test
testQueryStringInBracketsSecureViaProviderApiForType()212     public void testQueryStringInBracketsSecureViaProviderApiForType() throws Exception {
213         doTestQueryStringInBracketsViaProviderApiForType(SETTING_TYPE_SECURE);
214     }
215 
216     @Test
testQueryStringInBracketsSystemViaProviderApiForType()217     public void testQueryStringInBracketsSystemViaProviderApiForType() throws Exception {
218         doTestQueryStringInBracketsViaProviderApiForType(SETTING_TYPE_SYSTEM);
219     }
220 
221     @Test
testQueryStringWithAppendedNameToUriViaProviderApi()222     public void testQueryStringWithAppendedNameToUriViaProviderApi() throws Exception {
223         // Make sure we have a clean slate.
224         deleteStringViaProviderApi(SETTING_TYPE_SYSTEM, FAKE_SETTING_NAME);
225 
226         try {
227             // Insert the setting.
228             final Uri uri = insertStringViaProviderApi(SETTING_TYPE_SYSTEM, FAKE_SETTING_NAME,
229                     FAKE_SETTING_VALUE, false);
230             Uri expectUri = Uri.withAppendedPath(getBaseUriForType(SETTING_TYPE_SYSTEM),
231                     FAKE_SETTING_NAME);
232             assertEquals("Did not get expected Uri.", expectUri, uri);
233 
234             // Make sure the first setting is there.
235             String firstValue = queryStringViaProviderApi(SETTING_TYPE_SYSTEM, FAKE_SETTING_NAME,
236                     false, true);
237             assertEquals("Setting must be present", FAKE_SETTING_VALUE, firstValue);
238         } finally {
239             // Clean up.
240             deleteStringViaProviderApi(SETTING_TYPE_SYSTEM, FAKE_SETTING_NAME);
241         }
242     }
243 
244     @Test
testResetModePackageDefaultsGlobal()245     public void testResetModePackageDefaultsGlobal() throws Exception {
246         testResetModePackageDefaultsCommon(SETTING_TYPE_GLOBAL);
247     }
248 
249     @Test
testResetModePackageDefaultsSecure()250     public void testResetModePackageDefaultsSecure() throws Exception {
251         testResetModePackageDefaultsCommon(SETTING_TYPE_SECURE);
252     }
253 
testResetModePackageDefaultsCommon(int type)254     private void testResetModePackageDefaultsCommon(int type) throws Exception {
255         // Make sure we have a clean slate.
256         setSettingViaShell(type, FAKE_SETTING_NAME, null, true);
257         try {
258             // Set a value but don't make it the default
259             setSettingViaShell(type, FAKE_SETTING_NAME,
260                     FAKE_SETTING_VALUE, false);
261 
262             // Reset the changes made by the "shell/root" package
263             resetToDefaultsViaShell(type, "com.android.shell");
264             resetToDefaultsViaShell(type, "root");
265 
266             // Make sure the old APIs don't set defaults
267             assertNull(getSetting(type, FAKE_SETTING_NAME));
268 
269             // Set a value and make it the default
270             setSettingViaShell(type, FAKE_SETTING_NAME,
271                     FAKE_SETTING_VALUE, true);
272             // Change the setting from the default
273             setSettingViaShell(type, FAKE_SETTING_NAME,
274                     FAKE_SETTING_VALUE_2, false);
275 
276             // Reset the changes made by this package
277             resetToDefaultsViaShell(type, "com.android.shell");
278             resetToDefaultsViaShell(type, "root");
279 
280             // Make sure the old APIs don't set defaults
281             assertEquals(FAKE_SETTING_VALUE, getSetting(type, FAKE_SETTING_NAME));
282         } finally {
283             // Make sure we have a clean slate.
284             setSettingViaShell(type, FAKE_SETTING_NAME, null, true);
285         }
286     }
287 
288     @Test
testResetModePackageDefaultsWithTokensGlobal()289     public void testResetModePackageDefaultsWithTokensGlobal() throws Exception {
290         testResetModePackageDefaultsWithTokensCommon(SETTING_TYPE_GLOBAL);
291     }
292 
293     @Test
testResetModePackageDefaultsWithTokensSecure()294     public void testResetModePackageDefaultsWithTokensSecure() throws Exception {
295         testResetModePackageDefaultsWithTokensCommon(SETTING_TYPE_SECURE);
296     }
297 
testResetModePackageDefaultsWithTokensCommon(int type)298     private void testResetModePackageDefaultsWithTokensCommon(int type) throws Exception {
299         // Make sure we have a clean slate.
300         setSettingViaShell(type, FAKE_SETTING_NAME, null, true);
301         setSettingViaShell(type, FAKE_SETTING_NAME_1, null, true);
302         try {
303             // Set a default value
304             setSettingViaShell(type, FAKE_SETTING_NAME,
305                     FAKE_SETTING_VALUE, true);
306             // Change the default and associate a token
307             setSettingViaShell(type, FAKE_SETTING_NAME,
308                     FAKE_SETTING_VALUE_2, "TOKEN1", false);
309 
310             // Set a default value
311             setSettingViaShell(type, FAKE_SETTING_NAME_1,
312                     FAKE_SETTING_VALUE, "TOKEN2", true);
313             // Change the default and associate a token
314             setSettingViaShell(type, FAKE_SETTING_NAME_1,
315                     FAKE_SETTING_VALUE_2, "TOKEN2", false);
316 
317             // Reset settings associated with TOKEN1
318             resetToDefaultsViaShell(type, "com.android.shell", "TOKEN1");
319             resetToDefaultsViaShell(type, "root", "TOKEN1");
320 
321             // Make sure TOKEN1 settings are reset
322             assertEquals(FAKE_SETTING_VALUE, getSetting(type,
323                     FAKE_SETTING_NAME));
324 
325             // Make sure TOKEN2 settings are not reset
326             assertEquals(FAKE_SETTING_VALUE_2, getSetting(type,
327                     FAKE_SETTING_NAME_1));
328 
329             // Reset settings associated with TOKEN2
330             resetToDefaultsViaShell(type, "com.android.shell", "TOKEN2");
331             resetToDefaultsViaShell(type, "root", "TOKEN2");
332 
333             // Make sure TOKEN2 settings are reset
334             assertEquals(FAKE_SETTING_VALUE, getSetting(type,
335                     FAKE_SETTING_NAME_1));
336         } finally {
337             // Make sure we have a clean slate.
338             setSettingViaShell(type, FAKE_SETTING_NAME, null, true);
339             setSettingViaShell(type, FAKE_SETTING_NAME_1, null, true);
340         }
341     }
342 
343     @Test
testResetModeUntrustedDefaultsGlobal()344     public void testResetModeUntrustedDefaultsGlobal() throws Exception {
345         testResetModeUntrustedDefaultsCommon(SETTING_TYPE_GLOBAL);
346     }
347 
348     @Test
testResetModeUntrustedDefaultsSecure()349     public void testResetModeUntrustedDefaultsSecure() throws Exception {
350         testResetModeUntrustedDefaultsCommon(SETTING_TYPE_SECURE);
351     }
352 
testResetModeUntrustedDefaultsCommon(int type)353     private void testResetModeUntrustedDefaultsCommon(int type) throws Exception {
354         // Make sure we have a clean slate.
355         putSetting(type, FAKE_SETTING_NAME, null);
356         setSettingViaShell(type, FAKE_SETTING_NAME_1, null, true);
357         try {
358             // Set a default setting as a trusted component
359             putSetting(type, FAKE_SETTING_NAME, FAKE_SETTING_VALUE);
360             // Change the setting as a trusted component
361             putSetting(type, FAKE_SETTING_NAME, FAKE_SETTING_VALUE_2);
362 
363             // Set a default setting as an untrusted component
364             setSettingViaShell(type, FAKE_SETTING_NAME_1,
365                     FAKE_SETTING_VALUE, true);
366             // Change the setting as an untrusted component
367             setSettingViaShell(type, FAKE_SETTING_NAME_1,
368                     FAKE_SETTING_VALUE_2, false);
369 
370             // Reset the untrusted changes to defaults
371             resetSettingsViaShell(type,
372                     Settings.RESET_MODE_UNTRUSTED_DEFAULTS);
373 
374             // Check whether only the untrusted changes set to defaults
375             assertEquals(FAKE_SETTING_VALUE_2, getSetting(type, FAKE_SETTING_NAME));
376             assertEquals(FAKE_SETTING_VALUE, getSetting(type, FAKE_SETTING_NAME_1));
377         } finally {
378             // Make sure we have a clean slate.
379             putSetting(type, FAKE_SETTING_NAME, null);
380             setSettingViaShell(type, FAKE_SETTING_NAME_1, null, true);
381         }
382     }
383 
384     @Test
testResetModeUntrustedClearGlobal()385     public void testResetModeUntrustedClearGlobal() throws Exception {
386         testResetModeUntrustedClearCommon(SETTING_TYPE_GLOBAL);
387     }
388 
389     @Test
testResetModeUntrustedClearSecure()390     public void testResetModeUntrustedClearSecure() throws Exception {
391         testResetModeUntrustedClearCommon(SETTING_TYPE_SECURE);
392     }
393 
testResetModeUntrustedClearCommon(int type)394     private void testResetModeUntrustedClearCommon(int type) throws Exception {
395         // Make sure we have a clean slate.
396         putSetting(type, FAKE_SETTING_NAME, null);
397         setSettingViaShell(type, FAKE_SETTING_NAME_1, null, true);
398         try {
399             // Set a default setting as a trusted component
400             putSetting(type, FAKE_SETTING_NAME, FAKE_SETTING_VALUE);
401             // Change the setting as a trusted component
402             putSetting(type, FAKE_SETTING_NAME, FAKE_SETTING_VALUE_2);
403 
404             // Set a default setting as an untrusted component
405             setSettingViaShell(type, FAKE_SETTING_NAME_1,
406                     FAKE_SETTING_VALUE, true);
407             // Change the setting as an untrusted component
408             setSettingViaShell(type, FAKE_SETTING_NAME_1,
409                     FAKE_SETTING_VALUE_2, false);
410 
411             // Clear the untrusted changes
412             resetSettingsViaShell(type,
413                     Settings.RESET_MODE_UNTRUSTED_CHANGES);
414 
415             // Check whether only the untrusted changes set to defaults
416             assertEquals(FAKE_SETTING_VALUE_2, getSetting(type, FAKE_SETTING_NAME));
417             assertNull(getSetting(type, FAKE_SETTING_NAME_1));
418         } finally {
419             // Make sure we have a clean slate.
420             putSetting(type, FAKE_SETTING_NAME, null);
421             setSettingViaShell(type, FAKE_SETTING_NAME_1, null, true);
422         }
423     }
424 
425     @Test
testResetModeTrustedDefaultsGlobal()426     public void testResetModeTrustedDefaultsGlobal() throws Exception {
427         testResetModeTrustedDefaultsCommon(SETTING_TYPE_GLOBAL);
428     }
429 
430     @Test
testResetModeTrustedDefaultsSecure()431     public void testResetModeTrustedDefaultsSecure() throws Exception {
432         testResetModeTrustedDefaultsCommon(SETTING_TYPE_SECURE);
433     }
434 
testResetModeTrustedDefaultsCommon(int type)435     private void testResetModeTrustedDefaultsCommon(int type) throws Exception {
436         // Make sure we have a clean slate.
437         putSetting(type, FAKE_SETTING_NAME, null);
438         setSettingViaShell(type, FAKE_SETTING_NAME_1, null, true);
439         try {
440             // Set a default setting as a trusted component
441             putSetting(type, FAKE_SETTING_NAME, FAKE_SETTING_VALUE);
442             // Change the setting as a trusted component
443             setSettingViaShell(type, FAKE_SETTING_NAME, FAKE_SETTING_VALUE_2, false);
444 
445             // Set a default setting as an untrusted component
446             setSettingViaShell(type, FAKE_SETTING_NAME_1,
447                     FAKE_SETTING_VALUE, true);
448             // Change the setting as an untrusted component
449             setSettingViaShell(type, FAKE_SETTING_NAME_1,
450                     FAKE_SETTING_VALUE_2, false);
451 
452             // Reset to trusted defaults
453             resetSettingsViaShell(type,
454                     Settings.RESET_MODE_TRUSTED_DEFAULTS);
455 
456             // Check whether snapped to trusted defaults
457             assertEquals(FAKE_SETTING_VALUE, getSetting(type, FAKE_SETTING_NAME));
458             assertNull(getSetting(type, FAKE_SETTING_NAME_1));
459         } finally {
460             // Make sure we have a clean slate.
461             putSetting(type, FAKE_SETTING_NAME, null);
462             setSettingViaShell(type, FAKE_SETTING_NAME_1, null, true);
463         }
464     }
465 
doTestQueryStringInBracketsViaProviderApiForType(int type)466     private void doTestQueryStringInBracketsViaProviderApiForType(int type) {
467         // Make sure we have a clean slate.
468         deleteStringViaProviderApi(type, FAKE_SETTING_NAME);
469 
470         try {
471             // Insert the setting.
472             final Uri uri = insertStringViaProviderApi(type, FAKE_SETTING_NAME,
473                     FAKE_SETTING_VALUE, false);
474             Uri expectUri = Uri.withAppendedPath(getBaseUriForType(type), FAKE_SETTING_NAME);
475             assertEquals("Did not get expected Uri.", expectUri, uri);
476 
477             // Make sure the first setting is there.
478             String firstValue = queryStringViaProviderApi(type, FAKE_SETTING_NAME, true, false);
479             assertEquals("Setting must be present", FAKE_SETTING_VALUE, firstValue);
480         } finally {
481             // Clean up.
482             deleteStringViaProviderApi(type, FAKE_SETTING_NAME);
483         }
484     }
485 
toTestBulkInsertViaProviderApiForType(int type)486     private void toTestBulkInsertViaProviderApiForType(int type) {
487         // Make sure we have a clean slate.
488         deleteStringViaProviderApi(type, FAKE_SETTING_NAME);
489         deleteStringViaProviderApi(type, FAKE_SETTING_NAME_1);
490         deleteStringViaProviderApi(type, FAKE_SETTING_NAME_2);
491 
492         try {
493             Uri uri = getBaseUriForType(type);
494             ContentValues[] allValues = new ContentValues[3];
495 
496             // Insert the first setting.
497             ContentValues firstValues = new ContentValues();
498             firstValues.put(Settings.NameValueTable.NAME, FAKE_SETTING_NAME);
499             firstValues.put(Settings.NameValueTable.VALUE, FAKE_SETTING_VALUE);
500             allValues[0] = firstValues;
501 
502             // Insert the second setting.
503             ContentValues secondValues = new ContentValues();
504             secondValues.put(Settings.NameValueTable.NAME, FAKE_SETTING_NAME_1);
505             secondValues.put(Settings.NameValueTable.VALUE, FAKE_SETTING_VALUE_1);
506             allValues[1] = secondValues;
507 
508             // Insert the third setting. (null)
509             ContentValues thirdValues = new ContentValues();
510             thirdValues.put(Settings.NameValueTable.NAME, FAKE_SETTING_NAME_2);
511             thirdValues.put(Settings.NameValueTable.VALUE, FAKE_SETTING_VALUE_2);
512             allValues[2] = thirdValues;
513 
514             // Verify insertion count.
515             final int insertCount = getContext().getContentResolver().bulkInsert(uri, allValues);
516             assertSame("Couldn't insert both values", 3, insertCount);
517 
518             // Make sure the first setting is there.
519             String firstValue = queryStringViaProviderApi(type, FAKE_SETTING_NAME);
520             assertEquals("First setting must be present", FAKE_SETTING_VALUE, firstValue);
521 
522             // Make sure the second setting is there.
523             String secondValue = queryStringViaProviderApi(type, FAKE_SETTING_NAME_1);
524             assertEquals("Second setting must be present", FAKE_SETTING_VALUE_1, secondValue);
525 
526             // Make sure the third setting is there.
527             String thirdValue = queryStringViaProviderApi(type, FAKE_SETTING_NAME_2);
528             assertEquals("Third setting must be present", FAKE_SETTING_VALUE_2, thirdValue);
529         } finally {
530             // Clean up.
531             deleteStringViaProviderApi(type, FAKE_SETTING_NAME);
532             deleteStringViaProviderApi(type, FAKE_SETTING_NAME_1);
533             deleteStringViaProviderApi(type, FAKE_SETTING_NAME_2);
534         }
535     }
536 
doTestQueryUpdateDeleteGlobalViaProviderApiForType(int type)537     private void doTestQueryUpdateDeleteGlobalViaProviderApiForType(int type) throws Exception {
538         // Make sure it is not there.
539         deleteStringViaProviderApi(type, FAKE_SETTING_NAME);
540 
541         // Now selection should return nothing.
542         String value = queryStringViaProviderApi(type, FAKE_SETTING_NAME);
543         assertNull("Setting should not be present.", value);
544 
545         // Insert the setting.
546         Uri uri = insertStringViaProviderApi(type,
547                 FAKE_SETTING_NAME, FAKE_SETTING_VALUE, false);
548         Uri expectUri = Uri.withAppendedPath(getBaseUriForType(type), FAKE_SETTING_NAME);
549         assertEquals("Did not get expected Uri.", expectUri, uri);
550 
551         // Now selection should return the setting.
552         value = queryStringViaProviderApi(type, FAKE_SETTING_NAME);
553         assertEquals("Setting should be present.", FAKE_SETTING_VALUE, value);
554 
555         // Update the setting.
556         final int changeCount = updateStringViaProviderApiSetting(type,
557                 FAKE_SETTING_NAME, FAKE_SETTING_VALUE_1);
558         assertEquals("Did not get expected change count.", 1, changeCount);
559 
560         // Now selection should return the new setting.
561         value = queryStringViaProviderApi(type, FAKE_SETTING_NAME);
562         assertEquals("Setting should be present.", FAKE_SETTING_VALUE_1, value);
563 
564         // Delete the setting.
565         final int deletedCount = deleteStringViaProviderApi(type,
566                 FAKE_SETTING_NAME);
567         assertEquals("Did not get expected deleted count", 1, deletedCount);
568 
569         // Now selection should return nothing.
570         value = queryStringViaProviderApi(type, FAKE_SETTING_NAME);
571         assertNull("Setting should not be present.", value);
572     }
573 
performSetAndGetSettingTestViaFrontEndApi(int type, int userId)574     private void performSetAndGetSettingTestViaFrontEndApi(int type, int userId)
575             throws Exception {
576         try {
577             // Change the setting and assert a successful change.
578             setSettingViaFrontEndApiAndAssertSuccessfulChange(type, FAKE_SETTING_NAME,
579                     FAKE_SETTING_VALUE, userId);
580         } finally {
581             // Remove the setting.
582             setStringViaFrontEndApiSetting(type, FAKE_SETTING_NAME, null, userId);
583         }
584     }
585 
performSetAndGetSettingTestViaProviderApi(int type)586     private void performSetAndGetSettingTestViaProviderApi(int type)
587             throws Exception {
588         try {
589             // Change the setting and assert a successful change.
590             setSettingViaProviderApiAndAssertSuccessfulChange(type, FAKE_SETTING_NAME,
591                     FAKE_SETTING_VALUE, true);
592         } finally {
593             // Remove the setting.
594             setSettingViaProviderApiAndAssertSuccessfulChange(type, FAKE_SETTING_NAME, null,
595                     true);
596         }
597     }
598 
setSettingViaFrontEndApiAndAssertSuccessfulChange(final int type, final String name, final String value, final int userId)599     private void setSettingViaFrontEndApiAndAssertSuccessfulChange(final int type,
600             final String name, final String value, final int userId) throws Exception {
601         setSettingAndAssertSuccessfulChange(() -> {
602             setStringViaFrontEndApiSetting(type, name, value, userId);
603         }, type, name, value, userId);
604     }
605 
setSettingViaProviderApiAndAssertSuccessfulChange(final int type, final String name, final String value, final boolean withTableRowUri)606     private void setSettingViaProviderApiAndAssertSuccessfulChange(final int type,
607             final String name, final String value, final boolean withTableRowUri)
608             throws Exception {
609         setSettingAndAssertSuccessfulChange(() -> {
610             insertStringViaProviderApi(type, name, value, withTableRowUri);
611         }, type, name, value, UserHandle.USER_SYSTEM);
612     }
613 
setSettingAndAssertSuccessfulChange(Runnable setCommand, final int type, final String name, final String value, final int userId)614     private void setSettingAndAssertSuccessfulChange(Runnable setCommand, final int type,
615             final String name, final String value, final int userId) throws Exception {
616         ContentResolver contentResolver = getContext().getContentResolver();
617 
618         final Uri settingUri = getBaseUriForType(type).buildUpon().appendPath(name).build();
619 
620         final AtomicBoolean success = new AtomicBoolean();
621 
622         ContentObserver contentObserver = new ContentObserver(new Handler(Looper.getMainLooper())) {
623             public void onChange(boolean selfChange, Uri changeUri, int changeId) {
624                 Log.i(LOG_TAG, "onChange(" + selfChange + ", " + changeUri + ", " + changeId + ")");
625                 assertEquals("Wrong change Uri", changeUri, settingUri);
626                 assertEquals("Wrong user id", userId, changeId);
627                 String changeValue = getStringViaFrontEndApiSetting(type, name, userId);
628                 assertEquals("Wrong setting value", value, changeValue);
629 
630                 success.set(true);
631 
632                 synchronized (mLock) {
633                     mLock.notifyAll();
634                 }
635             }
636         };
637 
638         contentResolver.registerContentObserver(settingUri, false, contentObserver, userId);
639 
640         try {
641             setCommand.run();
642 
643             final long startTimeMillis = SystemClock.uptimeMillis();
644             synchronized (mLock) {
645                 while (true) {
646                     if (success.get()) {
647                         return;
648                     }
649                     final long elapsedTimeMillis = SystemClock.uptimeMillis() - startTimeMillis;
650                     if (elapsedTimeMillis >= WAIT_FOR_SETTING_URI_CHANGE_TIMEOUT_MILLIS) {
651                         fail("Could not change setting for "
652                                 + WAIT_FOR_SETTING_URI_CHANGE_TIMEOUT_MILLIS + " ms");
653                     }
654                     final long remainingTimeMillis = WAIT_FOR_SETTING_URI_CHANGE_TIMEOUT_MILLIS
655                             - elapsedTimeMillis;
656                     try {
657                         mLock.wait(remainingTimeMillis);
658                     } catch (InterruptedException ie) {
659                         /* ignore */
660                     }
661                 }
662             }
663         } finally {
664             contentResolver.unregisterContentObserver(contentObserver);
665         }
666     }
667 
queryAllSettingsViaProviderApiSettingAndAssertSettingPresent(int type, String name)668     private void queryAllSettingsViaProviderApiSettingAndAssertSettingPresent(int type,
669             String name) {
670         Uri uri = getBaseUriForType(type);
671 
672         Cursor cursor = getContext().getContentResolver().query(uri, NAME_VALUE_COLUMNS,
673                 null, null, null);
674 
675         if (cursor == null || !cursor.moveToFirst()) {
676             fail("Nothing selected");
677         }
678 
679         try {
680             final int nameColumnIdx = cursor.getColumnIndex(Settings.NameValueTable.NAME);
681 
682             while (cursor.moveToNext()) {
683                 String currentName = cursor.getString(nameColumnIdx);
684                 if (name.equals(currentName)) {
685                     return;
686                 }
687             }
688 
689             fail("Not found setting: " + name);
690         } finally {
691             cursor.close();
692         }
693     }
694 
695     @Test
testLocationModeChanges_viaFrontEndApi()696     public void testLocationModeChanges_viaFrontEndApi() throws Exception {
697         setStringViaFrontEndApiSetting(
698                 SETTING_TYPE_SECURE,
699                 Settings.Secure.LOCATION_MODE,
700                 String.valueOf(Settings.Secure.LOCATION_MODE_OFF),
701                 UserHandle.USER_SYSTEM);
702         assertEquals(
703                 "Wrong location providers",
704                 "",
705                 getStringViaFrontEndApiSetting(
706                         SETTING_TYPE_SECURE,
707                         Settings.Secure.LOCATION_PROVIDERS_ALLOWED,
708                         UserHandle.USER_SYSTEM));
709 
710         setStringViaFrontEndApiSetting(
711                 SETTING_TYPE_SECURE,
712                 Settings.Secure.LOCATION_MODE,
713                 String.valueOf(Settings.Secure.LOCATION_MODE_BATTERY_SAVING),
714                 UserHandle.USER_SYSTEM);
715         assertEquals(
716                 "Wrong location providers",
717                 "network",
718                 getStringViaFrontEndApiSetting(
719                         SETTING_TYPE_SECURE,
720                         Settings.Secure.LOCATION_PROVIDERS_ALLOWED,
721                         UserHandle.USER_SYSTEM));
722 
723         setStringViaFrontEndApiSetting(
724                 SETTING_TYPE_SECURE,
725                 Settings.Secure.LOCATION_MODE,
726                 String.valueOf(Settings.Secure.LOCATION_MODE_HIGH_ACCURACY),
727                 UserHandle.USER_SYSTEM);
728         assertEquals(
729                 "Wrong location providers",
730                 "gps,network",
731                 getStringViaFrontEndApiSetting(
732                         SETTING_TYPE_SECURE,
733                         Settings.Secure.LOCATION_PROVIDERS_ALLOWED,
734                         UserHandle.USER_SYSTEM));
735     }
736 
737     @Test
testLocationProvidersAllowed_disableProviders()738     public void testLocationProvidersAllowed_disableProviders() throws Exception {
739         setStringViaFrontEndApiSetting(
740                 SETTING_TYPE_SECURE,
741                 Settings.Secure.LOCATION_MODE,
742                 String.valueOf(Settings.Secure.LOCATION_MODE_HIGH_ACCURACY),
743                 UserHandle.USER_SYSTEM);
744 
745         // Disable providers that were enabled
746         updateStringViaProviderApiSetting(
747                 SETTING_TYPE_SECURE,
748                 Settings.Secure.LOCATION_PROVIDERS_ALLOWED,
749                 "-gps,-network");
750         assertEquals(
751                 "Wrong location providers",
752                 "",
753                 queryStringViaProviderApi(
754                         SETTING_TYPE_SECURE, Settings.Secure.LOCATION_PROVIDERS_ALLOWED));
755 
756         // Disable a provider that was not enabled
757         updateStringViaProviderApiSetting(
758                 SETTING_TYPE_SECURE,
759                 Settings.Secure.LOCATION_PROVIDERS_ALLOWED,
760                 "-test");
761         assertEquals(
762                 "Wrong location providers",
763                 "",
764                 queryStringViaProviderApi(
765                         SETTING_TYPE_SECURE, Settings.Secure.LOCATION_PROVIDERS_ALLOWED));
766     }
767 
768     @Test
testLocationProvidersAllowed_enableAndDisable()769     public void testLocationProvidersAllowed_enableAndDisable() throws Exception {
770         setStringViaFrontEndApiSetting(
771                 SETTING_TYPE_SECURE,
772                 Settings.Secure.LOCATION_MODE,
773                 String.valueOf(Settings.Secure.LOCATION_MODE_OFF),
774                 UserHandle.USER_SYSTEM);
775 
776         updateStringViaProviderApiSetting(
777                 SETTING_TYPE_SECURE,
778                 Settings.Secure.LOCATION_PROVIDERS_ALLOWED,
779                 "+gps,+network,+test");
780         updateStringViaProviderApiSetting(
781                 SETTING_TYPE_SECURE, Settings.Secure.LOCATION_PROVIDERS_ALLOWED, "-test");
782 
783         assertEquals(
784                 "Wrong location providers",
785                 "gps,network",
786                 queryStringViaProviderApi(
787                         SETTING_TYPE_SECURE, Settings.Secure.LOCATION_PROVIDERS_ALLOWED));
788     }
789 
790     @Test
testLocationProvidersAllowedLocked_invalidInput()791     public void testLocationProvidersAllowedLocked_invalidInput() throws Exception {
792         setStringViaFrontEndApiSetting(
793                 SETTING_TYPE_SECURE,
794                 Settings.Secure.LOCATION_MODE,
795                 String.valueOf(Settings.Secure.LOCATION_MODE_OFF),
796                 UserHandle.USER_SYSTEM);
797 
798         // update providers with a invalid string
799         updateStringViaProviderApiSetting(
800                 SETTING_TYPE_SECURE,
801                 Settings.Secure.LOCATION_PROVIDERS_ALLOWED,
802                 "+gps, invalid-string");
803 
804         // Verifies providers list does not change
805         assertEquals(
806                 "Wrong location providers",
807                 "",
808                 queryStringViaProviderApi(
809                         SETTING_TYPE_SECURE, Settings.Secure.LOCATION_PROVIDERS_ALLOWED));
810     }
811 }
812