• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2008 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package android.provider;
18 
19 import static org.hamcrest.Matchers.aMapWithSize;
20 import static org.hamcrest.Matchers.greaterThanOrEqualTo;
21 import static org.junit.Assert.assertThat;
22 
23 import android.content.ContentResolver;
24 import android.content.ContentUris;
25 import android.content.ContentValues;
26 import android.content.Context;
27 import android.content.Intent;
28 import android.content.pm.PackageManager;
29 import android.content.pm.ResolveInfo;
30 import android.content.pm.UserInfo;
31 import android.database.Cursor;
32 import android.net.Uri;
33 import android.os.Bundle;
34 import android.os.UserHandle;
35 import android.os.UserManager;
36 import android.test.AndroidTestCase;
37 
38 import androidx.test.filters.MediumTest;
39 import androidx.test.filters.SmallTest;
40 import androidx.test.filters.Suppress;
41 
42 import java.util.HashMap;
43 import java.util.List;
44 import java.util.Map;
45 
46 /** Unit test for SettingsProvider. */
47 public class SettingsProviderTest extends AndroidTestCase {
48 
49     @MediumTest
testNameValueCache()50     public void testNameValueCache() {
51         ContentResolver r = getContext().getContentResolver();
52         Settings.Secure.putString(r, "test_service", "Value");
53         assertEquals("Value", Settings.Secure.getString(r, "test_service"));
54 
55         // Make sure the value can be overwritten.
56         Settings.Secure.putString(r, "test_service", "New");
57         assertEquals("New", Settings.Secure.getString(r, "test_service"));
58 
59         // Also that delete works.
60         assertEquals(1, r.delete(Settings.Secure.getUriFor("test_service"), null, null));
61         assertEquals(null, Settings.Secure.getString(r, "test_service"));
62 
63         // Apps should not be able to use System settings.
64         try {
65             Settings.System.putString(r, "test_setting", "Value");
66             fail("IllegalArgumentException expected");
67         } catch (java.lang.IllegalArgumentException e) {
68             // expected
69         }
70     }
71 
72     @MediumTest
testRowNameContentUriForSecure()73     public void testRowNameContentUriForSecure() {
74         final String testKey = "testRowNameContentUriForSecure";
75         final String testValue = "testValue";
76         final String secondTestValue = "testValueNew";
77 
78         try {
79             testRowNameContentUri(Settings.Secure.CONTENT_URI, Settings.Secure.NAME,
80                     Settings.Secure.VALUE, testKey, testValue, secondTestValue);
81         } finally {
82             // clean up
83             Settings.Secure.putString(getContext().getContentResolver(), testKey, null);
84         }
85     }
86 
87     @MediumTest
testRowNameContentUriForSystem()88     public void testRowNameContentUriForSystem() {
89         final String testKey = Settings.System.VIBRATE_ON;
90         assertTrue("Settings.System.PUBLIC_SETTINGS cannot be empty.  We need to use one of it"
91                 + " for testing.  Only settings key in this collection will be accepted by the"
92                 + " framework.", Settings.System.PUBLIC_SETTINGS.contains(testKey));
93         final String testValue = "0";
94         final String secondTestValue = "1";
95         final String oldValue =
96                 Settings.System.getString(getContext().getContentResolver(), testKey);
97 
98         try {
99             testRowNameContentUri(Settings.System.CONTENT_URI, Settings.System.NAME,
100                     Settings.System.VALUE, testKey, testValue, secondTestValue);
101         } finally {
102             // restore old value
103             if (oldValue != null) {
104                 Settings.System.putString(getContext().getContentResolver(), testKey, oldValue);
105             }
106         }
107     }
108 
testRowNameContentUri(Uri table, String nameField, String valueField, String testKey, String testValue, String secondTestValue)109     private void testRowNameContentUri(Uri table, String nameField, String valueField,
110             String testKey, String testValue, String secondTestValue) {
111         ContentResolver r = getContext().getContentResolver();
112 
113         ContentValues v = new ContentValues();
114         v.put(nameField, testKey);
115         v.put(valueField, testValue);
116 
117         r.insert(table, v);
118         Uri uri = Uri.parse(table.toString() + "/" + testKey);
119 
120         // Query with a specific URI and no WHERE clause succeeds.
121         Cursor c = r.query(uri, null, null, null, null);
122         try {
123             assertTrue(c.moveToNext());
124             assertEquals(testKey, c.getString(c.getColumnIndex(nameField)));
125             assertEquals(testValue, c.getString(c.getColumnIndex(valueField)));
126             assertFalse(c.moveToNext());
127         } finally {
128             c.close();
129         }
130 
131         // Query with a specific URI and a WHERE clause fails.
132         try {
133             r.query(uri, null, "1", null, null);
134             fail("IllegalArgumentException expected");
135         } catch (IllegalArgumentException e) {
136             // expected
137         }
138 
139         // Query with a tablewide URI and a WHERE clause succeeds.
140         c = r.query(table, null, "name='" + testKey + "'", null, null);
141         try {
142             assertTrue(c.moveToNext());
143             assertEquals(testKey, c.getString(c.getColumnIndex(nameField)));
144             assertEquals(testValue, c.getString(c.getColumnIndex(valueField)));
145             assertFalse(c.moveToNext());
146         } finally {
147             c.close();
148         }
149 
150         v = new ContentValues();
151         // NAME is still needed, although the uri should be specific enough. Why?
152         v.put(nameField, testKey);
153         v.put(valueField, secondTestValue);
154         assertEquals(1, r.update(uri, v, null, null));
155 
156         c = r.query(uri, null, null, null, null);
157         try {
158             assertTrue(c.moveToNext());
159             assertEquals(testKey, c.getString(c.getColumnIndex(nameField)));
160             assertEquals(secondTestValue, c.getString(c.getColumnIndex(valueField)));
161             assertFalse(c.moveToNext());
162         } finally {
163             c.close();
164         }
165     }
166 
167     @MediumTest
testSettingsChangeForOtherUser()168     public void testSettingsChangeForOtherUser() {
169         UserManager um = (UserManager) getContext().getSystemService(Context.USER_SERVICE);
170         ContentResolver r = getContext().getContentResolver();
171 
172         // Make sure there's an owner
173         assertTrue(findUser(um, UserHandle.USER_SYSTEM));
174 
175         // create a new user to use for testing
176         UserInfo otherUser = um.createUser("TestUser1", UserInfo.FLAG_GUEST);
177         assertTrue(otherUser != null);
178         try {
179             assertNotSame("Current calling user id should not be the new guest user",
180                     otherUser.id, UserHandle.getCallingUserId());
181 
182             final String testKey = "testSettingsChangeForOtherUser";
183             final String testValue1 = "value1";
184             final String testValue2 = "value2";
185             Settings.Secure.putString(r, testKey, testValue1);
186             Settings.Secure.putStringForUser(r, testKey, testValue2, otherUser.id);
187 
188             assertEquals(testValue1, Settings.Secure.getString(r, testKey));
189             assertEquals(testValue2, Settings.Secure.getStringForUser(r, testKey, otherUser.id));
190 
191             assertNotSame("Current calling user id should not be the new guest user",
192                     otherUser.id, UserHandle.getCallingUserId());
193         } finally {
194             // Tidy up
195             um.removeUser(otherUser.id);
196         }
197     }
198 
199     @MediumTest
200     @Suppress  // Settings.Bookmarks uses a query format that's not supported now.
testRowNumberContentUri()201     public void testRowNumberContentUri() {
202         ContentResolver r = getContext().getContentResolver();
203 
204         // The bookmarks table (and everything else) uses standard row number content URIs.
205         Uri uri = Settings.Bookmarks.add(r, new Intent("TEST"),
206                 "Test Title", "Test Folder", '*', 123);
207 
208         assertTrue(ContentUris.parseId(uri) > 0);
209 
210         assertEquals("TEST", Settings.Bookmarks.getIntentForShortcut(r, '*').getAction());
211 
212         ContentValues v = new ContentValues();
213         v.put(Settings.Bookmarks.INTENT, "#Intent;action=TOAST;end");
214         assertEquals(1, r.update(uri, v, null, null));
215 
216         assertEquals("TOAST", Settings.Bookmarks.getIntentForShortcut(r, '*').getAction());
217 
218         assertEquals(1, r.delete(uri, null, null));
219 
220         assertEquals(null, Settings.Bookmarks.getIntentForShortcut(r, '*'));
221     }
222 
223     @MediumTest
testParseProviderList()224     public void testParseProviderList() {
225         ContentResolver r = getContext().getContentResolver();
226 
227         // We only accept "+value" and "-value"
228         // Test adding a value
229         Settings.Secure.putString(r, Settings.Secure.LOCATION_PROVIDERS_ALLOWED, "+test1");
230         assertTrue(Settings.Secure.getString(r, Settings.Secure.LOCATION_PROVIDERS_ALLOWED)
231                 .contains("test1"));
232 
233         // Test adding a second value
234         Settings.Secure.putString(r, Settings.Secure.LOCATION_PROVIDERS_ALLOWED, "+test2");
235         assertTrue(Settings.Secure.getString(r, Settings.Secure.LOCATION_PROVIDERS_ALLOWED)
236                 .contains("test1"));
237         assertTrue(Settings.Secure.getString(r, Settings.Secure.LOCATION_PROVIDERS_ALLOWED)
238                 .contains("test2"));
239 
240         // Test adding a third value
241         Settings.Secure.putString(r, Settings.Secure.LOCATION_PROVIDERS_ALLOWED, "+test3");
242         assertTrue(Settings.Secure.getString(r, Settings.Secure.LOCATION_PROVIDERS_ALLOWED)
243                 .contains("test1"));
244         assertTrue(Settings.Secure.getString(r, Settings.Secure.LOCATION_PROVIDERS_ALLOWED)
245                 .contains("test2"));
246         assertTrue(Settings.Secure.getString(r, Settings.Secure.LOCATION_PROVIDERS_ALLOWED)
247                 .contains("test3"));
248 
249         // Test deleting the first value in a 3 item list
250         Settings.Secure.putString(r, Settings.Secure.LOCATION_PROVIDERS_ALLOWED, "-test1");
251         assertFalse(Settings.Secure.getString(r, Settings.Secure.LOCATION_PROVIDERS_ALLOWED)
252                 .contains("test1"));
253 
254         // Test deleting the middle value in a 3 item list
255         Settings.Secure.putString(r, Settings.Secure.LOCATION_PROVIDERS_ALLOWED, "+test4");
256         assertTrue(Settings.Secure.getString(r, Settings.Secure.LOCATION_PROVIDERS_ALLOWED)
257                 .contains("test2"));
258         assertTrue(Settings.Secure.getString(r, Settings.Secure.LOCATION_PROVIDERS_ALLOWED)
259                 .contains("test3"));
260         assertTrue(Settings.Secure.getString(r, Settings.Secure.LOCATION_PROVIDERS_ALLOWED)
261                 .contains("test4"));
262         Settings.Secure.putString(r, Settings.Secure.LOCATION_PROVIDERS_ALLOWED, "-test3");
263         assertFalse(Settings.Secure.getString(r, Settings.Secure.LOCATION_PROVIDERS_ALLOWED)
264                 .contains("test3"));
265 
266         // Test deleting the last value in a 3 item list
267         Settings.Secure.putString(r, Settings.Secure.LOCATION_PROVIDERS_ALLOWED, "+test5");
268         assertTrue(Settings.Secure.getString(r, Settings.Secure.LOCATION_PROVIDERS_ALLOWED)
269                 .contains("test2"));
270         assertTrue(Settings.Secure.getString(r, Settings.Secure.LOCATION_PROVIDERS_ALLOWED)
271                 .contains("test4"));
272         assertTrue(Settings.Secure.getString(r, Settings.Secure.LOCATION_PROVIDERS_ALLOWED)
273                 .contains("test5"));
274         Settings.Secure.putString(r, Settings.Secure.LOCATION_PROVIDERS_ALLOWED, "-test5");
275         assertFalse(Settings.Secure.getString(r, Settings.Secure.LOCATION_PROVIDERS_ALLOWED)
276                 .contains("test5"));
277      }
278 
findUser(UserManager um, int userHandle)279     private boolean findUser(UserManager um, int userHandle) {
280         for (UserInfo user : um.getUsers()) {
281             if (user.id == userHandle) {
282                 return true;
283             }
284         }
285         return false;
286     }
287 
288     @MediumTest
testPerUserSettings()289     public void testPerUserSettings() {
290         UserManager um = (UserManager) getContext().getSystemService(Context.USER_SERVICE);
291         ContentResolver r = getContext().getContentResolver();
292 
293         // Make sure there's an owner
294         assertTrue(findUser(um, UserHandle.USER_SYSTEM));
295 
296         // create a new user to use for testing
297         UserInfo user = um.createUser("TestUser1", UserInfo.FLAG_GUEST);
298         assertTrue(user != null);
299 
300         try {
301             // Write some settings for that user as well as the current user
302             final String TEST_KEY = "test_setting";
303             final int SELF_VALUE = 40;
304             final int OTHER_VALUE = 27;
305 
306             Settings.Secure.putInt(r, TEST_KEY, SELF_VALUE);
307             Settings.Secure.putIntForUser(r, TEST_KEY, OTHER_VALUE, user.id);
308 
309             // Verify that they read back as intended
310             int myValue = Settings.Secure.getInt(r, TEST_KEY, 0);
311             int otherValue = Settings.Secure.getIntForUser(r, TEST_KEY, 0, user.id);
312             assertTrue("Running as user " + UserHandle.myUserId()
313                     + " and reading/writing as user " + user.id
314                     + ", expected to read " + SELF_VALUE + " but got " + myValue,
315                     myValue == SELF_VALUE);
316             assertTrue("Running as user " + UserHandle.myUserId()
317                     + " and reading/writing as user " + user.id
318                     + ", expected to read " + OTHER_VALUE + " but got " + otherValue,
319                     otherValue == OTHER_VALUE);
320         } finally {
321             // Tidy up
322             um.removeUser(user.id);
323         }
324     }
325 
326      @SmallTest
testSettings()327      public void testSettings() {
328         assertCanBeHandled(new Intent(Settings.ACTION_ACCESSIBILITY_SETTINGS));
329         assertCanBeHandled(new Intent(Settings.ACTION_ADD_ACCOUNT));
330         assertCanBeHandled(new Intent(Settings.ACTION_AIRPLANE_MODE_SETTINGS));
331         assertCanBeHandled(new Intent(Settings.ACTION_APN_SETTINGS));
332         assertCanBeHandled(new Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS)
333                 .setData(Uri.parse("package:" + getContext().getPackageName())));
334         assertCanBeHandled(new Intent(Settings.ACTION_APPLICATION_DEVELOPMENT_SETTINGS));
335         assertCanBeHandled(new Intent(Settings.ACTION_APPLICATION_SETTINGS));
336         assertCanBeHandled(new Intent(Settings.ACTION_BLUETOOTH_SETTINGS));
337         assertCanBeHandled(new Intent(Settings.ACTION_DATA_ROAMING_SETTINGS));
338         assertCanBeHandled(new Intent(Settings.ACTION_DATE_SETTINGS));
339         assertCanBeHandled(new Intent(Settings.ACTION_DEVICE_INFO_SETTINGS));
340         assertCanBeHandled(new Intent(Settings.ACTION_DISPLAY_SETTINGS));
341         assertCanBeHandled(new Intent(Settings.ACTION_INPUT_METHOD_SETTINGS));
342         assertCanBeHandled(new Intent(Settings.ACTION_INTERNAL_STORAGE_SETTINGS));
343         assertCanBeHandled(new Intent(Settings.ACTION_LOCALE_SETTINGS));
344         assertCanBeHandled(new Intent(Settings.ACTION_LOCATION_SOURCE_SETTINGS));
345         assertCanBeHandled(new Intent(Settings.ACTION_MANAGE_ALL_APPLICATIONS_SETTINGS));
346         assertCanBeHandled(new Intent(Settings.ACTION_MANAGE_APPLICATIONS_SETTINGS));
347         assertCanBeHandled(new Intent(Settings.ACTION_MEMORY_CARD_SETTINGS));
348         assertCanBeHandled(new Intent(Settings.ACTION_NETWORK_OPERATOR_SETTINGS));
349         assertCanBeHandled(new Intent(Settings.ACTION_PRIVACY_SETTINGS));
350         //TODO: seems no one is using this anymore.
351 //        assertCanBeHandled(new Intent(Settings.ACTION_QUICK_LAUNCH_SETTINGS));
352         assertCanBeHandled(new Intent(Settings.ACTION_SEARCH_SETTINGS));
353         assertCanBeHandled(new Intent(Settings.ACTION_SECURITY_SETTINGS));
354         assertCanBeHandled(new Intent(Settings.ACTION_SETTINGS));
355         assertCanBeHandled(new Intent(Settings.ACTION_SOUND_SETTINGS));
356         assertCanBeHandled(new Intent(Settings.ACTION_SYNC_SETTINGS));
357         assertCanBeHandled(new Intent(Settings.ACTION_SYSTEM_UPDATE_SETTINGS));
358         assertCanBeHandled(new Intent(Settings.ACTION_USER_DICTIONARY_SETTINGS));
359         assertCanBeHandled(new Intent(Settings.ACTION_WIFI_IP_SETTINGS));
360         assertCanBeHandled(new Intent(Settings.ACTION_WIFI_SETTINGS));
361         assertCanBeHandled(new Intent(Settings.ACTION_WIRELESS_SETTINGS));
362 
363         if (mContext.getPackageManager().hasSystemFeature(PackageManager.FEATURE_DEVICE_ADMIN)) {
364             assertCanBeHandled(new Intent(Settings.ACTION_ENTERPRISE_PRIVACY_SETTINGS));
365         }
366     }
367 
assertCanBeHandled(final Intent intent)368     private void assertCanBeHandled(final Intent intent) {
369         PackageManager packageManager = mContext.getPackageManager();
370         List<ResolveInfo> resolveInfoList = packageManager.queryIntentActivities(intent, 0);
371         assertNotNull(resolveInfoList);
372         // one or more activity can handle this intent.
373         assertTrue(resolveInfoList.size() > 0);
374     }
375 
376     @SmallTest
testValidSsaid()377     public void testValidSsaid() {
378         ContentResolver r = getContext().getContentResolver();
379 
380         // Verify ssaid
381         String ssaid = Settings.Secure.getString(r, Settings.Secure.ANDROID_ID);
382         assertTrue(ssaid != null);
383         assertTrue(ssaid.length() == 16);
384 
385         String ssaid2 = Settings.Secure.getString(r, Settings.Secure.ANDROID_ID);
386         assertTrue(ssaid2 != null);
387         assertTrue(ssaid2.length() == 16);
388 
389         assertTrue(ssaid.equals(ssaid2));
390     }
391 
392     @MediumTest
testCall_putAndGetConfig()393     public void testCall_putAndGetConfig() {
394         ContentResolver r = getContext().getContentResolver();
395         String name = "key1";
396         String value = "value1";
397         String newValue = "value2";
398         Bundle args = new Bundle();
399         args.putString(Settings.NameValueTable.VALUE, value);
400 
401         try {
402             // value is empty
403             Bundle results =
404                     r.call(DeviceConfig.CONTENT_URI, Settings.CALL_METHOD_GET_CONFIG, name, null);
405             assertNull(results.get(Settings.NameValueTable.VALUE));
406 
407             // save value
408             results = r.call(DeviceConfig.CONTENT_URI, Settings.CALL_METHOD_PUT_CONFIG, name, args);
409             assertNull(results);
410 
411             // value is no longer empty
412             results = r.call(DeviceConfig.CONTENT_URI, Settings.CALL_METHOD_GET_CONFIG, name, null);
413             assertEquals(value, results.get(Settings.NameValueTable.VALUE));
414 
415             // save new value
416             args.putString(Settings.NameValueTable.VALUE, newValue);
417             r.call(DeviceConfig.CONTENT_URI, Settings.CALL_METHOD_PUT_CONFIG, name, args);
418 
419             // new value is returned
420             results = r.call(DeviceConfig.CONTENT_URI, Settings.CALL_METHOD_GET_CONFIG, name, null);
421             assertEquals(newValue, results.get(Settings.NameValueTable.VALUE));
422         } finally {
423             // clean up
424             r.call(DeviceConfig.CONTENT_URI, Settings.CALL_METHOD_DELETE_CONFIG, name, null);
425         }
426     }
427 
428     @MediumTest
testCall_deleteConfig()429     public void testCall_deleteConfig() {
430         ContentResolver r = getContext().getContentResolver();
431         String name = "key1";
432         String value = "value1";
433         Bundle args = new Bundle();
434         args.putString(Settings.NameValueTable.VALUE, value);
435 
436         try {
437             // save value
438             r.call(DeviceConfig.CONTENT_URI, Settings.CALL_METHOD_PUT_CONFIG, name, args);
439 
440             // get value
441             Bundle results =
442                     r.call(DeviceConfig.CONTENT_URI, Settings.CALL_METHOD_GET_CONFIG, name, null);
443             assertEquals(value, results.get(Settings.NameValueTable.VALUE));
444 
445             // delete value
446             results = r.call(DeviceConfig.CONTENT_URI, Settings.CALL_METHOD_DELETE_CONFIG, name,
447                     null);
448 
449             // value is empty now
450             results = r.call(DeviceConfig.CONTENT_URI, Settings.CALL_METHOD_GET_CONFIG, name, null);
451             assertNull(results.get(Settings.NameValueTable.VALUE));
452         } finally {
453             // clean up
454             r.call(DeviceConfig.CONTENT_URI, Settings.CALL_METHOD_DELETE_CONFIG, name, null);
455         }
456     }
457 
458     @MediumTest
testCall_listConfig()459     public void testCall_listConfig() {
460         ContentResolver r = getContext().getContentResolver();
461         String prefix = "foo";
462         String newPrefix = "bar";
463         String name = prefix + "/" + "key1";
464         String newName = newPrefix + "/" + "key1";
465         String value = "value1";
466         String newValue = "value2";
467         Bundle args = new Bundle();
468         args.putString(Settings.NameValueTable.VALUE, value);
469 
470         try {
471             // save both values
472             r.call(DeviceConfig.CONTENT_URI, Settings.CALL_METHOD_PUT_CONFIG, name, args);
473             args.putString(Settings.NameValueTable.VALUE, newValue);
474             r.call(DeviceConfig.CONTENT_URI, Settings.CALL_METHOD_PUT_CONFIG, newName, args);
475 
476             // list all values
477             Bundle result = r.call(DeviceConfig.CONTENT_URI, Settings.CALL_METHOD_LIST_CONFIG,
478                     null, null);
479             Map<String, String> keyValueMap =
480                     (HashMap) result.getSerializable(Settings.NameValueTable.VALUE);
481             assertThat(keyValueMap.size(), greaterThanOrEqualTo(2));
482             assertEquals(value, keyValueMap.get(name));
483             assertEquals(newValue, keyValueMap.get(newName));
484 
485             // list values for prefix
486             args.putString(Settings.CALL_METHOD_PREFIX_KEY, prefix);
487             result = r.call(DeviceConfig.CONTENT_URI, Settings.CALL_METHOD_LIST_CONFIG, null, args);
488             keyValueMap = (HashMap) result.getSerializable(Settings.NameValueTable.VALUE);
489             assertThat(keyValueMap, aMapWithSize(1));
490             assertEquals(value, keyValueMap.get(name));
491         } finally {
492             // clean up
493             r.call(DeviceConfig.CONTENT_URI, Settings.CALL_METHOD_DELETE_CONFIG, name, null);
494             r.call(DeviceConfig.CONTENT_URI, Settings.CALL_METHOD_DELETE_CONFIG, newName, null);
495         }
496     }
497 }
498