diff options
author | Christopher Tate <ctate@google.com> | 2012-09-13 16:19:44 -0700 |
---|---|---|
committer | Christopher Tate <ctate@google.com> | 2012-09-13 19:15:54 -0700 |
commit | 78d2a66ac12e4c8f1303225514f573fb53af1dd9 (patch) | |
tree | 34125548e558c48d3677d43c5f9b4e7cde4d5f48 /core/tests | |
parent | 79d45660f2a83a7a771acf82c0bd0efed806abfa (diff) | |
download | frameworks_base-78d2a66ac12e4c8f1303225514f573fb53af1dd9.zip frameworks_base-78d2a66ac12e4c8f1303225514f573fb53af1dd9.tar.gz frameworks_base-78d2a66ac12e4c8f1303225514f573fb53af1dd9.tar.bz2 |
Fix Settings writes to a different user
Oops. Stacked bugs: first, the desired user handle was not properly
being passed from the call() entry point to the database operations;
then on top of that, the client-side cache management was still
looking in the local user's cache for the data, so a request to read
a different user's settings would return the local user's instead if
that key was already known to the local user's cache.
Reads and writes of a different user's settings are now uncached,
so they're relatively much slower. They're rare, however, so this
is not something to worry about unless we encounter a real world
case where it's a significant factor.
This CL also adds a bit of cross-user settings read/write testing
to the existing provider suite. These new tests caught both the
known wrong-user-write bug and discovered the client-side cache
bug, so yay.
Finally, the existing wholesale mutual-exclusion approach would
deadlock in certain circumstances due to the fact that the
settings database creation code might have to call out to the
Package Manager while populating the bookmark/shortcut table,
and the Package Manager would then call back into the settings
provider in the course of handling that request. The synchronization
regime has been significantly tightened up now: now the database
code [which is known to deal with concurrency itself] is allowed
to cope with multiple parallel openers of the same db; this
allows the settings provider to avoid calling out to other parts
of the system even implicitly while its internal lock is held.
Change-Id: Ib77d445b4a2ec658cc5c210830f6977c981f87ed
Diffstat (limited to 'core/tests')
-rw-r--r-- | core/tests/coretests/AndroidManifest.xml | 4 | ||||
-rw-r--r-- | core/tests/coretests/src/android/provider/SettingsProviderTest.java | 51 |
2 files changed, 55 insertions, 0 deletions
diff --git a/core/tests/coretests/AndroidManifest.xml b/core/tests/coretests/AndroidManifest.xml index dcd1bab..41f8536 100644 --- a/core/tests/coretests/AndroidManifest.xml +++ b/core/tests/coretests/AndroidManifest.xml @@ -69,6 +69,10 @@ <uses-permission android:name="com.google.android.googleapps.permission.GOOGLE_AUTH" /> <uses-permission android:name="com.google.android.googleapps.permission.GOOGLE_AUTH.ALL_SERVICES" /> + <uses-permission android:name="android.permission.MANAGE_USERS" /> + <uses-permission android:name="android.permission.INTERACT_ACROSS_USERS" /> + <uses-permission android:name="android.permission.INTERACT_ACROSS_USERS_FULL" /> + <uses-permission android:name="android.permission.RECEIVE_SMS"/> <uses-permission android:name="android.permission.INTERNET" /> <uses-permission android:name="android.permission.READ_CONTACTS" /> diff --git a/core/tests/coretests/src/android/provider/SettingsProviderTest.java b/core/tests/coretests/src/android/provider/SettingsProviderTest.java index 3e96dc4..6edd2dc 100644 --- a/core/tests/coretests/src/android/provider/SettingsProviderTest.java +++ b/core/tests/coretests/src/android/provider/SettingsProviderTest.java @@ -19,11 +19,15 @@ package android.provider; import android.content.ContentResolver; import android.content.ContentUris; import android.content.ContentValues; +import android.content.Context; import android.content.Intent; import android.content.pm.PackageManager; import android.content.pm.ResolveInfo; +import android.content.pm.UserInfo; import android.database.Cursor; import android.net.Uri; +import android.os.UserHandle; +import android.os.UserManager; import android.provider.Settings; import android.test.AndroidTestCase; import android.test.suitebuilder.annotation.MediumTest; @@ -197,6 +201,53 @@ public class SettingsProviderTest extends AndroidTestCase { Settings.Secure.getString(r, Settings.Secure.LOCATION_PROVIDERS_ALLOWED)); } + private boolean findUser(UserManager um, int userHandle) { + for (UserInfo user : um.getUsers()) { + if (user.id == userHandle) { + return true; + } + } + return false; + } + + @MediumTest + public void testPerUserSettings() { + UserManager um = (UserManager) getContext().getSystemService(Context.USER_SERVICE); + ContentResolver r = getContext().getContentResolver(); + + // Make sure there's an owner + assertTrue(findUser(um, UserHandle.USER_OWNER)); + + // create a new user to use for testing + UserInfo user = um.createUser("TestUser1", UserInfo.FLAG_GUEST); + assertTrue(user != null); + + try { + // Write some settings for that user as well as the current user + final String TEST_KEY = "test_setting"; + final int SELF_VALUE = 40; + final int OTHER_VALUE = 27; + + Settings.System.putInt(r, TEST_KEY, SELF_VALUE); + Settings.System.putIntForUser(r, TEST_KEY, OTHER_VALUE, user.id); + + // Verify that they read back as intended + int myValue = Settings.System.getInt(r, TEST_KEY, 0); + int otherValue = Settings.System.getIntForUser(r, TEST_KEY, 0, user.id); + assertTrue("Running as user " + UserHandle.myUserId() + + " and reading/writing as user " + user.id + + ", expected to read " + SELF_VALUE + " but got " + myValue, + myValue == SELF_VALUE); + assertTrue("Running as user " + UserHandle.myUserId() + + " and reading/writing as user " + user.id + + ", expected to read " + OTHER_VALUE + " but got " + otherValue, + otherValue == OTHER_VALUE); + } finally { + // Tidy up + um.removeUser(user.id); + } + } + @SmallTest public void testSettings() { assertCanBeHandled(new Intent(Settings.ACTION_ACCESSIBILITY_SETTINGS)); |