Skip to content

Commit afccaa8

Browse files
author
Christopher Tate
committed
Use myUserId() only in registerContentObserver()
The reason for this is a bit subtle: we want to guarantee that when a content observer is registered using the public API, it is *always* bound to the host user's view of the data behind the observed Uri, never the calling user's. Now, the reason it was the calling user in the first place is that the Settings provider (and potentially any singleton provider) needs the observers underlying Cursors returned from query() to be tied to the caller's user, not the provider's host user. In order to accomplish that now that the public-facing behavior is always tied to the host user, the concrete class that implements the Cursor type handled by the Settings provider has been extended with a new hidden API for setting a notification observer tied to an arbitrary user; and then the provider explicitly downcasts the query result's Cursor to that class in order to register the notification observer. We can do this safely because this is platform code; if we change the way that these underlying cursors are constructed, we can just fix this point of call to follow along. If they get out of sync in the future, the Settings provider will scream bloody murder in the log and throw a crashing exception. Bug 7231549 Change-Id: I0aaceebb8b4108c56f8b9964ca7f9e698ddd91c8
1 parent 7636693 commit afccaa8

File tree

3 files changed

+19
-3
lines changed

3 files changed

+19
-3
lines changed

core/java/android/content/ContentResolver.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1219,7 +1219,7 @@ public final ContentProviderClient acquireUnstableContentProviderClient(String n
12191219
public final void registerContentObserver(Uri uri, boolean notifyForDescendents,
12201220
ContentObserver observer)
12211221
{
1222-
registerContentObserver(uri, notifyForDescendents, observer, UserHandle.getCallingUserId());
1222+
registerContentObserver(uri, notifyForDescendents, observer, UserHandle.myUserId());
12231223
}
12241224

12251225
/** @hide - designated user version */

core/java/android/database/AbstractCursor.java

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
import android.content.ContentResolver;
2020
import android.net.Uri;
2121
import android.os.Bundle;
22+
import android.os.UserHandle;
2223
import android.util.Log;
2324

2425
import java.lang.ref.WeakReference;
@@ -350,14 +351,19 @@ protected void onChange(boolean selfChange) {
350351
* specific row URI, or a base URI for a whole class of content.
351352
*/
352353
public void setNotificationUri(ContentResolver cr, Uri notifyUri) {
354+
setNotificationUri(cr, notifyUri, UserHandle.myUserId());
355+
}
356+
357+
/** @hide - set the notification uri but with an observer for a particular user's view */
358+
public void setNotificationUri(ContentResolver cr, Uri notifyUri, int userHandle) {
353359
synchronized (mSelfObserverLock) {
354360
mNotifyUri = notifyUri;
355361
mContentResolver = cr;
356362
if (mSelfObserver != null) {
357363
mContentResolver.unregisterContentObserver(mSelfObserver);
358364
}
359365
mSelfObserver = new SelfContentObserver(this);
360-
mContentResolver.registerContentObserver(mNotifyUri, true, mSelfObserver);
366+
mContentResolver.registerContentObserver(mNotifyUri, true, mSelfObserver, userHandle);
361367
mSelfObserverRegistered = true;
362368
}
363369
}

packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@
3333
import android.content.IntentFilter;
3434
import android.content.pm.PackageManager;
3535
import android.content.res.AssetFileDescriptor;
36+
import android.database.AbstractCursor;
3637
import android.database.Cursor;
3738
import android.database.sqlite.SQLiteDatabase;
3839
import android.database.sqlite.SQLiteException;
@@ -685,7 +686,16 @@ private Cursor queryForUser(Uri url, String[] select, String where, String[] whe
685686
qb.setTables(args.table);
686687

687688
Cursor ret = qb.query(db, select, args.where, args.args, null, null, sort);
688-
ret.setNotificationUri(getContext().getContentResolver(), url);
689+
// the default Cursor interface does not support per-user observation
690+
try {
691+
AbstractCursor c = (AbstractCursor) ret;
692+
c.setNotificationUri(getContext().getContentResolver(), url, forUser);
693+
} catch (ClassCastException e) {
694+
// details of the concrete Cursor implementation have changed and this code has
695+
// not been updated to match -- complain and fail hard.
696+
Log.wtf(TAG, "Incompatible cursor derivation!");
697+
throw e;
698+
}
689699
return ret;
690700
}
691701

0 commit comments

Comments
 (0)