am 01b079f7: Merge "Make ContentObservers work across profiles" into mnc-dev

* commit '01b079f7d2dff0c9230e0f58842a473dc8c2cd06':
  Make ContentObservers work across profiles
This commit is contained in:
Benjamin Franz
2015-06-30 07:48:01 +00:00
committed by Android Git Automerger
2 changed files with 37 additions and 14 deletions

View File

@@ -1593,7 +1593,11 @@ public abstract class ContentResolver {
@NonNull ContentObserver observer) {
Preconditions.checkNotNull(uri, "uri");
Preconditions.checkNotNull(observer, "observer");
registerContentObserver(uri, notifyForDescendents, observer, UserHandle.myUserId());
registerContentObserver(
ContentProvider.getUriWithoutUserId(uri),
notifyForDescendents,
observer,
ContentProvider.getUserIdFromUri(uri, UserHandle.myUserId()));
}
/** @hide - designated user version */
@@ -1659,7 +1663,11 @@ public abstract class ContentResolver {
public void notifyChange(@NonNull Uri uri, @Nullable ContentObserver observer,
boolean syncToNetwork) {
Preconditions.checkNotNull(uri, "uri");
notifyChange(uri, observer, syncToNetwork, UserHandle.myUserId());
notifyChange(
ContentProvider.getUriWithoutUserId(uri),
observer,
syncToNetwork,
ContentProvider.getUserIdFromUri(uri, UserHandle.myUserId()));
}
/**

View File

@@ -23,12 +23,14 @@ import android.content.ComponentName;
import android.content.ContentResolver;
import android.content.Context;
import android.content.IContentService;
import android.content.Intent;
import android.content.ISyncStatusObserver;
import android.content.PeriodicSync;
import android.content.SyncAdapterType;
import android.content.SyncInfo;
import android.content.SyncRequest;
import android.content.SyncStatusInfo;
import android.content.pm.PackageManager;
import android.database.IContentObserver;
import android.database.sqlite.SQLiteException;
import android.net.Uri;
@@ -161,8 +163,9 @@ public final class ContentService extends IContentService.Stub {
* Register a content observer tied to a specific user's view of the provider.
* @param userHandle the user whose view of the provider is to be observed. May be
* the calling user without requiring any permission, otherwise the caller needs to
* hold the INTERACT_ACROSS_USERS_FULL permission. Pseudousers USER_ALL and
* USER_CURRENT are properly handled; all other pseudousers are forbidden.
* hold the INTERACT_ACROSS_USERS_FULL permission or hold a read uri grant to the uri.
* Pseudousers USER_ALL and USER_CURRENT are properly handled; all other pseudousers
* are forbidden.
*/
@Override
public void registerContentObserver(Uri uri, boolean notifyForDescendants,
@@ -171,8 +174,17 @@ public final class ContentService extends IContentService.Stub {
throw new IllegalArgumentException("You must pass a valid uri and observer");
}
enforceCrossUserPermission(userHandle,
"no permission to observe other users' provider view");
final int uid = Binder.getCallingUid();
final int pid = Binder.getCallingPid();
final int callingUserHandle = UserHandle.getCallingUserId();
// Registering an observer for any user other than the calling user requires uri grant or
// cross user permission
if (callingUserHandle != userHandle &&
mContext.checkUriPermission(uri, pid, uid, Intent.FLAG_GRANT_READ_URI_PERMISSION)
!= PackageManager.PERMISSION_GRANTED) {
enforceCrossUserPermission(userHandle,
"no permission to observe other users' provider view");
}
if (userHandle < 0) {
if (userHandle == UserHandle.USER_CURRENT) {
@@ -185,7 +197,7 @@ public final class ContentService extends IContentService.Stub {
synchronized (mRootNode) {
mRootNode.addObserverLocked(uri, observer, notifyForDescendants, mRootNode,
Binder.getCallingUid(), Binder.getCallingPid(), userHandle);
uid, pid, userHandle);
if (false) Log.v(TAG, "Registered observer " + observer + " at " + uri +
" with notifyForDescendants " + notifyForDescendants);
}
@@ -211,8 +223,9 @@ public final class ContentService extends IContentService.Stub {
* Notify observers of a particular user's view of the provider.
* @param userHandle the user whose view of the provider is to be notified. May be
* the calling user without requiring any permission, otherwise the caller needs to
* hold the INTERACT_ACROSS_USERS_FULL permission. Pseudousers USER_ALL and
* USER_CURRENT are properly interpreted; no other pseudousers are allowed.
* hold the INTERACT_ACROSS_USERS_FULL permission or hold a write uri grant to the uri.
* Pseudousers USER_ALL and USER_CURRENT are properly interpreted; no other pseudousers are
* allowed.
*/
@Override
public void notifyChange(Uri uri, IContentObserver observer,
@@ -223,11 +236,14 @@ public final class ContentService extends IContentService.Stub {
+ " from observer " + observer + ", syncToNetwork " + syncToNetwork);
}
// Notify for any user other than the caller's own requires permission.
final int uid = Binder.getCallingUid();
final int pid = Binder.getCallingPid();
final int callingUserHandle = UserHandle.getCallingUserId();
if (userHandle != callingUserHandle) {
mContext.enforceCallingOrSelfPermission(Manifest.permission.INTERACT_ACROSS_USERS,
"no permission to notify other users");
// Notify for any user other than the caller requires uri grant or cross user permission
if (callingUserHandle != userHandle &&
mContext.checkUriPermission(uri, pid, uid, Intent.FLAG_GRANT_WRITE_URI_PERMISSION)
!= PackageManager.PERMISSION_GRANTED) {
enforceCrossUserPermission(userHandle, "no permission to notify other users");
}
// We passed the permission check; resolve pseudouser targets as appropriate
@@ -240,7 +256,6 @@ public final class ContentService extends IContentService.Stub {
}
}
final int uid = Binder.getCallingUid();
// This makes it so that future permission checks will be in the context of this
// process rather than the caller's process. We will restore this before returning.
long identityToken = clearCallingIdentity();