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
17package android.provider;
18
19import android.content.ContentResolver;
20import android.content.ContentUris;
21import android.content.ContentValues;
22import android.content.Context;
23import android.content.Intent;
24import android.content.pm.PackageManager;
25import android.content.pm.ResolveInfo;
26import android.content.pm.UserInfo;
27import android.database.Cursor;
28import android.net.Uri;
29import android.os.UserHandle;
30import android.os.UserManager;
31import android.test.AndroidTestCase;
32import android.test.suitebuilder.annotation.MediumTest;
33import android.test.suitebuilder.annotation.SmallTest;
34import android.test.suitebuilder.annotation.Suppress;
35
36import java.util.List;
37
38/** Unit test for SettingsProvider. */
39public class SettingsProviderTest extends AndroidTestCase {
40    @MediumTest
41    public void testNameValueCache() {
42        ContentResolver r = getContext().getContentResolver();
43        Settings.Secure.putString(r, "test_service", "Value");
44        assertEquals("Value", Settings.Secure.getString(r, "test_service"));
45
46        // Make sure the value can be overwritten.
47        Settings.Secure.putString(r, "test_service", "New");
48        assertEquals("New", Settings.Secure.getString(r, "test_service"));
49
50        // Also that delete works.
51        assertEquals(1, r.delete(Settings.Secure.getUriFor("test_service"), null, null));
52        assertEquals(null, Settings.Secure.getString(r, "test_service"));
53
54        // Apps should not be able to use System settings.
55        try {
56            Settings.System.putString(r, "test_setting", "Value");
57            fail("IllegalArgumentException expected");
58        } catch (java.lang.IllegalArgumentException e) {
59            // expected
60        }
61    }
62
63    @MediumTest
64    public void testRowNameContentUriForSecure() {
65        final String testKey = "testRowNameContentUriForSecure";
66        final String testValue = "testValue";
67        final String secondTestValue = "testValueNew";
68
69        try {
70            testRowNameContentUri(Settings.Secure.CONTENT_URI, Settings.Secure.NAME,
71                    Settings.Secure.VALUE, testKey, testValue, secondTestValue);
72        } finally {
73            // clean up
74            Settings.Secure.putString(getContext().getContentResolver(), testKey, null);
75        }
76    }
77
78    @MediumTest
79    public void testRowNameContentUriForSystem() {
80        final String testKey = Settings.System.VIBRATE_ON;
81        assertTrue("Settings.System.PUBLIC_SETTINGS cannot be empty.  We need to use one of it"
82                + " for testing.  Only settings key in this collection will be accepted by the"
83                + " framework.", Settings.System.PUBLIC_SETTINGS.contains(testKey));
84        final String testValue = "0";
85        final String secondTestValue = "1";
86        final String oldValue =
87                Settings.System.getString(getContext().getContentResolver(), testKey);
88
89        try {
90            testRowNameContentUri(Settings.System.CONTENT_URI, Settings.System.NAME,
91                    Settings.System.VALUE, testKey, testValue, secondTestValue);
92        } finally {
93            // restore old value
94            if (oldValue != null) {
95                Settings.System.putString(getContext().getContentResolver(), testKey, oldValue);
96            }
97        }
98    }
99
100    private void testRowNameContentUri(Uri table, String nameField, String valueField,
101            String testKey, String testValue, String secondTestValue) {
102        ContentResolver r = getContext().getContentResolver();
103
104        ContentValues v = new ContentValues();
105        v.put(nameField, testKey);
106        v.put(valueField, testValue);
107
108        r.insert(table, v);
109        Uri uri = Uri.parse(table.toString() + "/" + testKey);
110
111        // Query with a specific URI and no WHERE clause succeeds.
112        Cursor c = r.query(uri, null, null, null, null);
113        try {
114            assertTrue(c.moveToNext());
115            assertEquals(testKey, c.getString(c.getColumnIndex(nameField)));
116            assertEquals(testValue, c.getString(c.getColumnIndex(valueField)));
117            assertFalse(c.moveToNext());
118        } finally {
119            c.close();
120        }
121
122        // Query with a specific URI and a WHERE clause fails.
123        try {
124            r.query(uri, null, "1", null, null);
125            fail("IllegalArgumentException expected");
126        } catch (IllegalArgumentException e) {
127            // expected
128        }
129
130        // Query with a tablewide URI and a WHERE clause succeeds.
131        c = r.query(table, null, "name='" + testKey + "'", null, null);
132        try {
133            assertTrue(c.moveToNext());
134            assertEquals(testKey, c.getString(c.getColumnIndex(nameField)));
135            assertEquals(testValue, c.getString(c.getColumnIndex(valueField)));
136            assertFalse(c.moveToNext());
137        } finally {
138            c.close();
139        }
140
141        v = new ContentValues();
142        // NAME is still needed, although the uri should be specific enough. Why?
143        v.put(nameField, testKey);
144        v.put(valueField, secondTestValue);
145        assertEquals(1, r.update(uri, v, null, null));
146
147        c = r.query(uri, null, null, null, null);
148        try {
149            assertTrue(c.moveToNext());
150            assertEquals(testKey, c.getString(c.getColumnIndex(nameField)));
151            assertEquals(secondTestValue, c.getString(c.getColumnIndex(valueField)));
152            assertFalse(c.moveToNext());
153        } finally {
154            c.close();
155        }
156    }
157
158    @MediumTest
159    public void testSettingsChangeForOtherUser() {
160        UserManager um = (UserManager) getContext().getSystemService(Context.USER_SERVICE);
161        ContentResolver r = getContext().getContentResolver();
162
163        // Make sure there's an owner
164        assertTrue(findUser(um, UserHandle.USER_SYSTEM));
165
166        // create a new user to use for testing
167        UserInfo otherUser = um.createUser("TestUser1", UserInfo.FLAG_GUEST);
168        assertTrue(otherUser != null);
169        try {
170            assertNotSame("Current calling user id should not be the new guest user",
171                    otherUser.id, UserHandle.getCallingUserId());
172
173            final String testKey = "testSettingsChangeForOtherUser";
174            final String testValue1 = "value1";
175            final String testValue2 = "value2";
176            Settings.Secure.putString(r, testKey, testValue1);
177            Settings.Secure.putStringForUser(r, testKey, testValue2, otherUser.id);
178
179            assertEquals(testValue1, Settings.Secure.getString(r, testKey));
180            assertEquals(testValue2, Settings.Secure.getStringForUser(r, testKey, otherUser.id));
181
182            assertNotSame("Current calling user id should not be the new guest user",
183                    otherUser.id, UserHandle.getCallingUserId());
184        } finally {
185            // Tidy up
186            um.removeUser(otherUser.id);
187        }
188    }
189
190    @MediumTest
191    @Suppress  // Settings.Bookmarks uses a query format that's not supported now.
192    public void testRowNumberContentUri() {
193        ContentResolver r = getContext().getContentResolver();
194
195        // The bookmarks table (and everything else) uses standard row number content URIs.
196        Uri uri = Settings.Bookmarks.add(r, new Intent("TEST"),
197                "Test Title", "Test Folder", '*', 123);
198
199        assertTrue(ContentUris.parseId(uri) > 0);
200
201        assertEquals("TEST", Settings.Bookmarks.getIntentForShortcut(r, '*').getAction());
202
203        ContentValues v = new ContentValues();
204        v.put(Settings.Bookmarks.INTENT, "#Intent;action=TOAST;end");
205        assertEquals(1, r.update(uri, v, null, null));
206
207        assertEquals("TOAST", Settings.Bookmarks.getIntentForShortcut(r, '*').getAction());
208
209        assertEquals(1, r.delete(uri, null, null));
210
211        assertEquals(null, Settings.Bookmarks.getIntentForShortcut(r, '*'));
212    }
213
214    @MediumTest
215    public void testParseProviderList() {
216        ContentResolver r = getContext().getContentResolver();
217
218        // We only accept "+value" and "-value"
219        // Test adding a value
220        Settings.Secure.putString(r, Settings.Secure.LOCATION_PROVIDERS_ALLOWED, "+test1");
221        assertTrue(Settings.Secure.getString(r, Settings.Secure.LOCATION_PROVIDERS_ALLOWED)
222                .contains("test1"));
223
224        // Test adding a second value
225        Settings.Secure.putString(r, Settings.Secure.LOCATION_PROVIDERS_ALLOWED, "+test2");
226        assertTrue(Settings.Secure.getString(r, Settings.Secure.LOCATION_PROVIDERS_ALLOWED)
227                .contains("test1"));
228        assertTrue(Settings.Secure.getString(r, Settings.Secure.LOCATION_PROVIDERS_ALLOWED)
229                .contains("test2"));
230
231        // Test adding a third value
232        Settings.Secure.putString(r, Settings.Secure.LOCATION_PROVIDERS_ALLOWED, "+test3");
233        assertTrue(Settings.Secure.getString(r, Settings.Secure.LOCATION_PROVIDERS_ALLOWED)
234                .contains("test1"));
235        assertTrue(Settings.Secure.getString(r, Settings.Secure.LOCATION_PROVIDERS_ALLOWED)
236                .contains("test2"));
237        assertTrue(Settings.Secure.getString(r, Settings.Secure.LOCATION_PROVIDERS_ALLOWED)
238                .contains("test3"));
239
240        // Test deleting the first value in a 3 item list
241        Settings.Secure.putString(r, Settings.Secure.LOCATION_PROVIDERS_ALLOWED, "-test1");
242        assertFalse(Settings.Secure.getString(r, Settings.Secure.LOCATION_PROVIDERS_ALLOWED)
243                .contains("test1"));
244
245        // Test deleting the middle value in a 3 item list
246        Settings.Secure.putString(r, Settings.Secure.LOCATION_PROVIDERS_ALLOWED, "+test4");
247        assertTrue(Settings.Secure.getString(r, Settings.Secure.LOCATION_PROVIDERS_ALLOWED)
248                .contains("test2"));
249        assertTrue(Settings.Secure.getString(r, Settings.Secure.LOCATION_PROVIDERS_ALLOWED)
250                .contains("test3"));
251        assertTrue(Settings.Secure.getString(r, Settings.Secure.LOCATION_PROVIDERS_ALLOWED)
252                .contains("test4"));
253        Settings.Secure.putString(r, Settings.Secure.LOCATION_PROVIDERS_ALLOWED, "-test3");
254        assertFalse(Settings.Secure.getString(r, Settings.Secure.LOCATION_PROVIDERS_ALLOWED)
255                .contains("test3"));
256
257        // Test deleting the last value in a 3 item list
258        Settings.Secure.putString(r, Settings.Secure.LOCATION_PROVIDERS_ALLOWED, "+test5");
259        assertTrue(Settings.Secure.getString(r, Settings.Secure.LOCATION_PROVIDERS_ALLOWED)
260                .contains("test2"));
261        assertTrue(Settings.Secure.getString(r, Settings.Secure.LOCATION_PROVIDERS_ALLOWED)
262                .contains("test4"));
263        assertTrue(Settings.Secure.getString(r, Settings.Secure.LOCATION_PROVIDERS_ALLOWED)
264                .contains("test5"));
265        Settings.Secure.putString(r, Settings.Secure.LOCATION_PROVIDERS_ALLOWED, "-test5");
266        assertFalse(Settings.Secure.getString(r, Settings.Secure.LOCATION_PROVIDERS_ALLOWED)
267                .contains("test5"));
268     }
269
270    private boolean findUser(UserManager um, int userHandle) {
271        for (UserInfo user : um.getUsers()) {
272            if (user.id == userHandle) {
273                return true;
274            }
275        }
276        return false;
277    }
278
279    @MediumTest
280    public void testPerUserSettings() {
281        UserManager um = (UserManager) getContext().getSystemService(Context.USER_SERVICE);
282        ContentResolver r = getContext().getContentResolver();
283
284        // Make sure there's an owner
285        assertTrue(findUser(um, UserHandle.USER_SYSTEM));
286
287        // create a new user to use for testing
288        UserInfo user = um.createUser("TestUser1", UserInfo.FLAG_GUEST);
289        assertTrue(user != null);
290
291        try {
292            // Write some settings for that user as well as the current user
293            final String TEST_KEY = "test_setting";
294            final int SELF_VALUE = 40;
295            final int OTHER_VALUE = 27;
296
297            Settings.Secure.putInt(r, TEST_KEY, SELF_VALUE);
298            Settings.Secure.putIntForUser(r, TEST_KEY, OTHER_VALUE, user.id);
299
300            // Verify that they read back as intended
301            int myValue = Settings.Secure.getInt(r, TEST_KEY, 0);
302            int otherValue = Settings.Secure.getIntForUser(r, TEST_KEY, 0, user.id);
303            assertTrue("Running as user " + UserHandle.myUserId()
304                    + " and reading/writing as user " + user.id
305                    + ", expected to read " + SELF_VALUE + " but got " + myValue,
306                    myValue == SELF_VALUE);
307            assertTrue("Running as user " + UserHandle.myUserId()
308                    + " and reading/writing as user " + user.id
309                    + ", expected to read " + OTHER_VALUE + " but got " + otherValue,
310                    otherValue == OTHER_VALUE);
311        } finally {
312            // Tidy up
313            um.removeUser(user.id);
314        }
315    }
316
317     @SmallTest
318     public void testSettings() {
319        assertCanBeHandled(new Intent(Settings.ACTION_ACCESSIBILITY_SETTINGS));
320        assertCanBeHandled(new Intent(Settings.ACTION_ADD_ACCOUNT));
321        assertCanBeHandled(new Intent(Settings.ACTION_AIRPLANE_MODE_SETTINGS));
322        assertCanBeHandled(new Intent(Settings.ACTION_APN_SETTINGS));
323        assertCanBeHandled(new Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS)
324                .setData(Uri.parse("package:" + getContext().getPackageName())));
325        assertCanBeHandled(new Intent(Settings.ACTION_APPLICATION_DEVELOPMENT_SETTINGS));
326        assertCanBeHandled(new Intent(Settings.ACTION_APPLICATION_SETTINGS));
327        assertCanBeHandled(new Intent(Settings.ACTION_BLUETOOTH_SETTINGS));
328        assertCanBeHandled(new Intent(Settings.ACTION_DATA_ROAMING_SETTINGS));
329        assertCanBeHandled(new Intent(Settings.ACTION_DATE_SETTINGS));
330        assertCanBeHandled(new Intent(Settings.ACTION_DEVICE_INFO_SETTINGS));
331        assertCanBeHandled(new Intent(Settings.ACTION_DISPLAY_SETTINGS));
332        assertCanBeHandled(new Intent(Settings.ACTION_INPUT_METHOD_SETTINGS));
333        assertCanBeHandled(new Intent(Settings.ACTION_INTERNAL_STORAGE_SETTINGS));
334        assertCanBeHandled(new Intent(Settings.ACTION_LOCALE_SETTINGS));
335        assertCanBeHandled(new Intent(Settings.ACTION_LOCATION_SOURCE_SETTINGS));
336        assertCanBeHandled(new Intent(Settings.ACTION_MANAGE_ALL_APPLICATIONS_SETTINGS));
337        assertCanBeHandled(new Intent(Settings.ACTION_MANAGE_APPLICATIONS_SETTINGS));
338        assertCanBeHandled(new Intent(Settings.ACTION_MEMORY_CARD_SETTINGS));
339        assertCanBeHandled(new Intent(Settings.ACTION_NETWORK_OPERATOR_SETTINGS));
340        assertCanBeHandled(new Intent(Settings.ACTION_PRIVACY_SETTINGS));
341        //TODO: seems no one is using this anymore.
342//        assertCanBeHandled(new Intent(Settings.ACTION_QUICK_LAUNCH_SETTINGS));
343        assertCanBeHandled(new Intent(Settings.ACTION_SEARCH_SETTINGS));
344        assertCanBeHandled(new Intent(Settings.ACTION_SECURITY_SETTINGS));
345        assertCanBeHandled(new Intent(Settings.ACTION_SETTINGS));
346        assertCanBeHandled(new Intent(Settings.ACTION_SOUND_SETTINGS));
347        assertCanBeHandled(new Intent(Settings.ACTION_SYNC_SETTINGS));
348        assertCanBeHandled(new Intent(Settings.ACTION_SYSTEM_UPDATE_SETTINGS));
349        assertCanBeHandled(new Intent(Settings.ACTION_USER_DICTIONARY_SETTINGS));
350        assertCanBeHandled(new Intent(Settings.ACTION_WIFI_IP_SETTINGS));
351        assertCanBeHandled(new Intent(Settings.ACTION_WIFI_SETTINGS));
352        assertCanBeHandled(new Intent(Settings.ACTION_WIRELESS_SETTINGS));
353    }
354
355    private void assertCanBeHandled(final Intent intent) {
356        PackageManager packageManager = mContext.getPackageManager();
357        List<ResolveInfo> resolveInfoList = packageManager.queryIntentActivities(intent, 0);
358        assertNotNull(resolveInfoList);
359        // one or more activity can handle this intent.
360        assertTrue(resolveInfoList.size() > 0);
361    }
362}
363