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