summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--core/java/android/app/ActivityManagerNative.java52
-rw-r--r--core/java/android/app/ContextImpl.java33
-rw-r--r--core/java/android/app/IActivityManager.java24
-rw-r--r--core/java/android/content/ClipData.java21
-rw-r--r--core/java/android/content/ContentProvider.java114
-rw-r--r--core/java/android/content/ContentProviderOperation.java27
-rw-r--r--core/java/android/content/ContentProviderResult.java10
-rw-r--r--core/java/android/content/ContentResolver.java11
-rw-r--r--core/java/android/content/Intent.java36
-rw-r--r--core/java/com/android/internal/app/IntentForwarderActivity.java1
-rw-r--r--core/java/com/android/internal/util/XmlUtils.java9
-rw-r--r--services/core/java/com/android/server/am/ActivityManagerService.java269
-rw-r--r--services/core/java/com/android/server/am/UriPermission.java10
-rw-r--r--services/core/java/com/android/server/am/UriPermissionOwner.java6
-rw-r--r--services/core/java/com/android/server/clipboard/ClipboardService.java21
15 files changed, 479 insertions, 165 deletions
diff --git a/core/java/android/app/ActivityManagerNative.java b/core/java/android/app/ActivityManagerNative.java
index ec2868a..296e9d3 100644
--- a/core/java/android/app/ActivityManagerNative.java
+++ b/core/java/android/app/ActivityManagerNative.java
@@ -1114,7 +1114,8 @@ public abstract class ActivityManagerNative extends Binder implements IActivityM
int pid = data.readInt();
int uid = data.readInt();
int mode = data.readInt();
- int res = checkUriPermission(uri, pid, uid, mode);
+ int userId = data.readInt();
+ int res = checkUriPermission(uri, pid, uid, mode, userId);
reply.writeNoException();
reply.writeInt(res);
return true;
@@ -1139,7 +1140,8 @@ public abstract class ActivityManagerNative extends Binder implements IActivityM
String targetPkg = data.readString();
Uri uri = Uri.CREATOR.createFromParcel(data);
int mode = data.readInt();
- grantUriPermission(app, targetPkg, uri, mode);
+ int userId = data.readInt();
+ grantUriPermission(app, targetPkg, uri, mode, userId);
reply.writeNoException();
return true;
}
@@ -1150,7 +1152,8 @@ public abstract class ActivityManagerNative extends Binder implements IActivityM
IApplicationThread app = ApplicationThreadNative.asInterface(b);
Uri uri = Uri.CREATOR.createFromParcel(data);
int mode = data.readInt();
- revokeUriPermission(app, uri, mode);
+ int userId = data.readInt();
+ revokeUriPermission(app, uri, mode, userId);
reply.writeNoException();
return true;
}
@@ -1159,7 +1162,8 @@ public abstract class ActivityManagerNative extends Binder implements IActivityM
data.enforceInterface(IActivityManager.descriptor);
Uri uri = Uri.CREATOR.createFromParcel(data);
int mode = data.readInt();
- takePersistableUriPermission(uri, mode);
+ int userId = data.readInt();
+ takePersistableUriPermission(uri, mode, userId);
reply.writeNoException();
return true;
}
@@ -1168,7 +1172,8 @@ public abstract class ActivityManagerNative extends Binder implements IActivityM
data.enforceInterface(IActivityManager.descriptor);
Uri uri = Uri.CREATOR.createFromParcel(data);
int mode = data.readInt();
- releasePersistableUriPermission(uri, mode);
+ int userId = data.readInt();
+ releasePersistableUriPermission(uri, mode, userId);
reply.writeNoException();
return true;
}
@@ -1602,7 +1607,8 @@ public abstract class ActivityManagerNative extends Binder implements IActivityM
String targetPkg = data.readString();
Uri uri = Uri.CREATOR.createFromParcel(data);
int mode = data.readInt();
- grantUriPermissionFromOwner(owner, fromUid, targetPkg, uri, mode);
+ int userId = data.readInt();
+ grantUriPermissionFromOwner(owner, fromUid, targetPkg, uri, mode, userId);
reply.writeNoException();
return true;
}
@@ -1612,10 +1618,11 @@ public abstract class ActivityManagerNative extends Binder implements IActivityM
IBinder owner = data.readStrongBinder();
Uri uri = null;
if (data.readInt() != 0) {
- Uri.CREATOR.createFromParcel(data);
+ uri = Uri.CREATOR.createFromParcel(data);
}
int mode = data.readInt();
- revokeUriPermissionFromOwner(owner, uri, mode);
+ int userId = data.readInt();
+ revokeUriPermissionFromOwner(owner, uri, mode, userId);
reply.writeNoException();
return true;
}
@@ -1626,7 +1633,8 @@ public abstract class ActivityManagerNative extends Binder implements IActivityM
String targetPkg = data.readString();
Uri uri = Uri.CREATOR.createFromParcel(data);
int modeFlags = data.readInt();
- int res = checkGrantUriPermission(callingUid, targetPkg, uri, modeFlags);
+ int userId = data.readInt();
+ int res = checkGrantUriPermission(callingUid, targetPkg, uri, modeFlags, userId);
reply.writeNoException();
reply.writeInt(res);
return true;
@@ -3540,7 +3548,7 @@ class ActivityManagerProxy implements IActivityManager
reply.recycle();
return res;
}
- public int checkUriPermission(Uri uri, int pid, int uid, int mode)
+ public int checkUriPermission(Uri uri, int pid, int uid, int mode, int userId)
throws RemoteException {
Parcel data = Parcel.obtain();
Parcel reply = Parcel.obtain();
@@ -3549,6 +3557,7 @@ class ActivityManagerProxy implements IActivityManager
data.writeInt(pid);
data.writeInt(uid);
data.writeInt(mode);
+ data.writeInt(userId);
mRemote.transact(CHECK_URI_PERMISSION_TRANSACTION, data, reply, 0);
reply.readException();
int res = reply.readInt();
@@ -3557,7 +3566,7 @@ class ActivityManagerProxy implements IActivityManager
return res;
}
public void grantUriPermission(IApplicationThread caller, String targetPkg,
- Uri uri, int mode) throws RemoteException {
+ Uri uri, int mode, int userId) throws RemoteException {
Parcel data = Parcel.obtain();
Parcel reply = Parcel.obtain();
data.writeInterfaceToken(IActivityManager.descriptor);
@@ -3565,19 +3574,21 @@ class ActivityManagerProxy implements IActivityManager
data.writeString(targetPkg);
uri.writeToParcel(data, 0);
data.writeInt(mode);
+ data.writeInt(userId);
mRemote.transact(GRANT_URI_PERMISSION_TRANSACTION, data, reply, 0);
reply.readException();
data.recycle();
reply.recycle();
}
public void revokeUriPermission(IApplicationThread caller, Uri uri,
- int mode) throws RemoteException {
+ int mode, int userId) throws RemoteException {
Parcel data = Parcel.obtain();
Parcel reply = Parcel.obtain();
data.writeInterfaceToken(IActivityManager.descriptor);
data.writeStrongBinder(caller.asBinder());
uri.writeToParcel(data, 0);
data.writeInt(mode);
+ data.writeInt(userId);
mRemote.transact(REVOKE_URI_PERMISSION_TRANSACTION, data, reply, 0);
reply.readException();
data.recycle();
@@ -3585,12 +3596,14 @@ class ActivityManagerProxy implements IActivityManager
}
@Override
- public void takePersistableUriPermission(Uri uri, int mode) throws RemoteException {
+ public void takePersistableUriPermission(Uri uri, int mode, int userId)
+ throws RemoteException {
Parcel data = Parcel.obtain();
Parcel reply = Parcel.obtain();
data.writeInterfaceToken(IActivityManager.descriptor);
uri.writeToParcel(data, 0);
data.writeInt(mode);
+ data.writeInt(userId);
mRemote.transact(TAKE_PERSISTABLE_URI_PERMISSION_TRANSACTION, data, reply, 0);
reply.readException();
data.recycle();
@@ -3598,12 +3611,14 @@ class ActivityManagerProxy implements IActivityManager
}
@Override
- public void releasePersistableUriPermission(Uri uri, int mode) throws RemoteException {
+ public void releasePersistableUriPermission(Uri uri, int mode, int userId)
+ throws RemoteException {
Parcel data = Parcel.obtain();
Parcel reply = Parcel.obtain();
data.writeInterfaceToken(IActivityManager.descriptor);
uri.writeToParcel(data, 0);
data.writeInt(mode);
+ data.writeInt(userId);
mRemote.transact(RELEASE_PERSISTABLE_URI_PERMISSION_TRANSACTION, data, reply, 0);
reply.readException();
data.recycle();
@@ -4157,7 +4172,7 @@ class ActivityManagerProxy implements IActivityManager
}
public void grantUriPermissionFromOwner(IBinder owner, int fromUid, String targetPkg,
- Uri uri, int mode) throws RemoteException {
+ Uri uri, int mode, int userId) throws RemoteException {
Parcel data = Parcel.obtain();
Parcel reply = Parcel.obtain();
data.writeInterfaceToken(IActivityManager.descriptor);
@@ -4166,6 +4181,7 @@ class ActivityManagerProxy implements IActivityManager
data.writeString(targetPkg);
uri.writeToParcel(data, 0);
data.writeInt(mode);
+ data.writeInt(userId);
mRemote.transact(GRANT_URI_PERMISSION_TRANSACTION, data, reply, 0);
reply.readException();
data.recycle();
@@ -4173,7 +4189,7 @@ class ActivityManagerProxy implements IActivityManager
}
public void revokeUriPermissionFromOwner(IBinder owner, Uri uri,
- int mode) throws RemoteException {
+ int mode, int userId) throws RemoteException {
Parcel data = Parcel.obtain();
Parcel reply = Parcel.obtain();
data.writeInterfaceToken(IActivityManager.descriptor);
@@ -4185,6 +4201,7 @@ class ActivityManagerProxy implements IActivityManager
data.writeInt(0);
}
data.writeInt(mode);
+ data.writeInt(userId);
mRemote.transact(REVOKE_URI_PERMISSION_TRANSACTION, data, reply, 0);
reply.readException();
data.recycle();
@@ -4192,7 +4209,7 @@ class ActivityManagerProxy implements IActivityManager
}
public int checkGrantUriPermission(int callingUid, String targetPkg,
- Uri uri, int modeFlags) throws RemoteException {
+ Uri uri, int modeFlags, int userId) throws RemoteException {
Parcel data = Parcel.obtain();
Parcel reply = Parcel.obtain();
data.writeInterfaceToken(IActivityManager.descriptor);
@@ -4200,6 +4217,7 @@ class ActivityManagerProxy implements IActivityManager
data.writeString(targetPkg);
uri.writeToParcel(data, 0);
data.writeInt(modeFlags);
+ data.writeInt(userId);
mRemote.transact(CHECK_GRANT_URI_PERMISSION_TRANSACTION, data, reply, 0);
reply.readException();
int res = reply.readInt();
diff --git a/core/java/android/app/ContextImpl.java b/core/java/android/app/ContextImpl.java
index 801182d..b4d8942 100644
--- a/core/java/android/app/ContextImpl.java
+++ b/core/java/android/app/ContextImpl.java
@@ -26,6 +26,7 @@ import com.android.internal.util.Preconditions;
import android.bluetooth.BluetoothManager;
import android.content.BroadcastReceiver;
import android.content.ComponentName;
+import android.content.ContentProvider;
import android.content.ContentResolver;
import android.content.Context;
import android.content.ContextWrapper;
@@ -1818,8 +1819,8 @@ class ContextImpl extends Context {
public void grantUriPermission(String toPackage, Uri uri, int modeFlags) {
try {
ActivityManagerNative.getDefault().grantUriPermission(
- mMainThread.getApplicationThread(), toPackage, uri,
- modeFlags);
+ mMainThread.getApplicationThread(), toPackage,
+ ContentProvider.getUriWithoutUserId(uri), modeFlags, resolveUserId(uri));
} catch (RemoteException e) {
}
}
@@ -1828,8 +1829,8 @@ class ContextImpl extends Context {
public void revokeUriPermission(Uri uri, int modeFlags) {
try {
ActivityManagerNative.getDefault().revokeUriPermission(
- mMainThread.getApplicationThread(), uri,
- modeFlags);
+ mMainThread.getApplicationThread(),
+ ContentProvider.getUriWithoutUserId(uri), modeFlags, resolveUserId(uri));
} catch (RemoteException e) {
}
}
@@ -1838,12 +1839,17 @@ class ContextImpl extends Context {
public int checkUriPermission(Uri uri, int pid, int uid, int modeFlags) {
try {
return ActivityManagerNative.getDefault().checkUriPermission(
- uri, pid, uid, modeFlags);
+ ContentProvider.getUriWithoutUserId(uri), pid, uid, modeFlags,
+ resolveUserId(uri));
} catch (RemoteException e) {
return PackageManager.PERMISSION_DENIED;
}
}
+ private int resolveUserId(Uri uri) {
+ return ContentProvider.getUserIdFromUri(uri, getUserId());
+ }
+
@Override
public int checkCallingUriPermission(Uri uri, int modeFlags) {
int pid = Binder.getCallingPid();
@@ -2280,12 +2286,16 @@ class ContextImpl extends Context {
@Override
protected IContentProvider acquireProvider(Context context, String auth) {
- return mMainThread.acquireProvider(context, auth, mUser.getIdentifier(), true);
+ return mMainThread.acquireProvider(context,
+ ContentProvider.getAuthorityWithoutUserId(auth),
+ resolveUserIdFromAuthority(auth), true);
}
@Override
protected IContentProvider acquireExistingProvider(Context context, String auth) {
- return mMainThread.acquireExistingProvider(context, auth, mUser.getIdentifier(), true);
+ return mMainThread.acquireExistingProvider(context,
+ ContentProvider.getAuthorityWithoutUserId(auth),
+ resolveUserIdFromAuthority(auth), true);
}
@Override
@@ -2295,7 +2305,9 @@ class ContextImpl extends Context {
@Override
protected IContentProvider acquireUnstableProvider(Context c, String auth) {
- return mMainThread.acquireProvider(c, auth, mUser.getIdentifier(), false);
+ return mMainThread.acquireProvider(c,
+ ContentProvider.getAuthorityWithoutUserId(auth),
+ resolveUserIdFromAuthority(auth), false);
}
@Override
@@ -2312,5 +2324,10 @@ class ContextImpl extends Context {
public void appNotRespondingViaProvider(IContentProvider icp) {
mMainThread.appNotRespondingViaProvider(icp.asBinder());
}
+
+ /** @hide */
+ protected int resolveUserIdFromAuthority(String auth) {
+ return ContentProvider.getUserIdFromAuthority(auth, mUser.getIdentifier());
+ }
}
}
diff --git a/core/java/android/app/IActivityManager.java b/core/java/android/app/IActivityManager.java
index 074b427..a30a64a 100644
--- a/core/java/android/app/IActivityManager.java
+++ b/core/java/android/app/IActivityManager.java
@@ -210,14 +210,16 @@ public interface IActivityManager extends IInterface {
public int checkPermission(String permission, int pid, int uid)
throws RemoteException;
- public int checkUriPermission(Uri uri, int pid, int uid, int mode)
+ public int checkUriPermission(Uri uri, int pid, int uid, int mode, int userId)
+ throws RemoteException;
+ public void grantUriPermission(IApplicationThread caller, String targetPkg, Uri uri,
+ int mode, int userId) throws RemoteException;
+ public void revokeUriPermission(IApplicationThread caller, Uri uri, int mode, int userId)
+ throws RemoteException;
+ public void takePersistableUriPermission(Uri uri, int modeFlags, int userId)
+ throws RemoteException;
+ public void releasePersistableUriPermission(Uri uri, int modeFlags, int userId)
throws RemoteException;
- public void grantUriPermission(IApplicationThread caller, String targetPkg,
- Uri uri, int mode) throws RemoteException;
- public void revokeUriPermission(IApplicationThread caller, Uri uri,
- int mode) throws RemoteException;
- public void takePersistableUriPermission(Uri uri, int modeFlags) throws RemoteException;
- public void releasePersistableUriPermission(Uri uri, int modeFlags) throws RemoteException;
public ParceledListSlice<UriPermission> getPersistedUriPermissions(
String packageName, boolean incoming) throws RemoteException;
@@ -323,12 +325,12 @@ public interface IActivityManager extends IInterface {
public IBinder newUriPermissionOwner(String name) throws RemoteException;
public void grantUriPermissionFromOwner(IBinder owner, int fromUid, String targetPkg,
- Uri uri, int mode) throws RemoteException;
+ Uri uri, int mode, int userId) throws RemoteException;
public void revokeUriPermissionFromOwner(IBinder owner, Uri uri,
- int mode) throws RemoteException;
+ int mode, int userId) throws RemoteException;
- public int checkGrantUriPermission(int callingUid, String targetPkg,
- Uri uri, int modeFlags) throws RemoteException;
+ public int checkGrantUriPermission(int callingUid, String targetPkg, Uri uri,
+ int modeFlags, int userId) throws RemoteException;
// Cause the specified process to dump the specified heap.
public boolean dumpHeap(String process, int userId, boolean managed, String path,
diff --git a/core/java/android/content/ClipData.java b/core/java/android/content/ClipData.java
index 50c4fed..b44abf9 100644
--- a/core/java/android/content/ClipData.java
+++ b/core/java/android/content/ClipData.java
@@ -16,6 +16,7 @@
package android.content;
+import static android.content.ContentProvider.maybeAddUserId;
import android.content.res.AssetFileDescriptor;
import android.graphics.Bitmap;
import android.net.Uri;
@@ -186,7 +187,7 @@ public class ClipData implements Parcelable {
final CharSequence mText;
final String mHtmlText;
final Intent mIntent;
- final Uri mUri;
+ Uri mUri;
/**
* Create an Item consisting of a single block of (possibly styled) text.
@@ -809,6 +810,24 @@ public class ClipData implements Parcelable {
}
}
+ /**
+ * Prepare this {@link ClipData} to leave an app process.
+ *
+ * @hide
+ */
+ public void prepareToLeaveUser(int userId) {
+ final int size = mItems.size();
+ for (int i = 0; i < size; i++) {
+ final Item item = mItems.get(i);
+ if (item.mIntent != null) {
+ item.mIntent.prepareToLeaveUser(userId);
+ }
+ if (item.mUri != null) {
+ item.mUri = maybeAddUserId(item.mUri, userId);
+ }
+ }
+ }
+
@Override
public String toString() {
StringBuilder b = new StringBuilder(128);
diff --git a/core/java/android/content/ContentProvider.java b/core/java/android/content/ContentProvider.java
index 02c850b..be9782f 100644
--- a/core/java/android/content/ContentProvider.java
+++ b/core/java/android/content/ContentProvider.java
@@ -36,6 +36,7 @@ import android.os.ParcelFileDescriptor;
import android.os.Process;
import android.os.UserHandle;
import android.util.Log;
+import android.text.TextUtils;
import java.io.File;
import java.io.FileDescriptor;
@@ -195,6 +196,7 @@ public abstract class ContentProvider implements ComponentCallbacks2 {
return rejectQuery(uri, projection, selection, selectionArgs, sortOrder,
CancellationSignal.fromTransport(cancellationSignal));
}
+ uri = getUriWithoutUserId(uri);
final String original = setCallingPackage(callingPkg);
try {
return ContentProvider.this.query(
@@ -207,6 +209,7 @@ public abstract class ContentProvider implements ComponentCallbacks2 {
@Override
public String getType(Uri uri) {
+ uri = getUriWithoutUserId(uri);
return ContentProvider.this.getType(uri);
}
@@ -215,9 +218,11 @@ public abstract class ContentProvider implements ComponentCallbacks2 {
if (enforceWritePermission(callingPkg, uri) != AppOpsManager.MODE_ALLOWED) {
return rejectInsert(uri, initialValues);
}
+ int userId = getUserIdFromUri(uri);
+ uri = getUriWithoutUserId(uri);
final String original = setCallingPackage(callingPkg);
try {
- return ContentProvider.this.insert(uri, initialValues);
+ return maybeAddUserId(ContentProvider.this.insert(uri, initialValues), userId);
} finally {
setCallingPackage(original);
}
@@ -228,6 +233,7 @@ public abstract class ContentProvider implements ComponentCallbacks2 {
if (enforceWritePermission(callingPkg, uri) != AppOpsManager.MODE_ALLOWED) {
return 0;
}
+ uri = getUriWithoutUserId(uri);
final String original = setCallingPackage(callingPkg);
try {
return ContentProvider.this.bulkInsert(uri, initialValues);
@@ -240,24 +246,39 @@ public abstract class ContentProvider implements ComponentCallbacks2 {
public ContentProviderResult[] applyBatch(String callingPkg,
ArrayList<ContentProviderOperation> operations)
throws OperationApplicationException {
- for (ContentProviderOperation operation : operations) {
+ int numOperations = operations.size();
+ final int[] userIds = new int[numOperations];
+ for (int i = 0; i < numOperations; i++) {
+ ContentProviderOperation operation = operations.get(i);
+ userIds[i] = getUserIdFromUri(operation.getUri());
if (operation.isReadOperation()) {
if (enforceReadPermission(callingPkg, operation.getUri())
!= AppOpsManager.MODE_ALLOWED) {
throw new OperationApplicationException("App op not allowed", 0);
}
}
-
if (operation.isWriteOperation()) {
if (enforceWritePermission(callingPkg, operation.getUri())
!= AppOpsManager.MODE_ALLOWED) {
throw new OperationApplicationException("App op not allowed", 0);
}
}
+ if (userIds[i] != UserHandle.USER_CURRENT) {
+ // Removing the user id from the uri.
+ operation = new ContentProviderOperation(operation, true);
+ }
+ operations.set(i, operation);
}
final String original = setCallingPackage(callingPkg);
try {
- return ContentProvider.this.applyBatch(operations);
+ ContentProviderResult[] results = ContentProvider.this.applyBatch(operations);
+ for (int i = 0; i < results.length ; i++) {
+ if (userIds[i] != UserHandle.USER_CURRENT) {
+ // Adding the userId to the uri.
+ results[i] = new ContentProviderResult(results[i], userIds[i]);
+ }
+ }
+ return results;
} finally {
setCallingPackage(original);
}
@@ -268,6 +289,7 @@ public abstract class ContentProvider implements ComponentCallbacks2 {
if (enforceWritePermission(callingPkg, uri) != AppOpsManager.MODE_ALLOWED) {
return 0;
}
+ uri = getUriWithoutUserId(uri);
final String original = setCallingPackage(callingPkg);
try {
return ContentProvider.this.delete(uri, selection, selectionArgs);
@@ -282,6 +304,7 @@ public abstract class ContentProvider implements ComponentCallbacks2 {
if (enforceWritePermission(callingPkg, uri) != AppOpsManager.MODE_ALLOWED) {
return 0;
}
+ uri = getUriWithoutUserId(uri);
final String original = setCallingPackage(callingPkg);
try {
return ContentProvider.this.update(uri, values, selection, selectionArgs);
@@ -295,6 +318,7 @@ public abstract class ContentProvider implements ComponentCallbacks2 {
String callingPkg, Uri uri, String mode, ICancellationSignal cancellationSignal)
throws FileNotFoundException {
enforceFilePermission(callingPkg, uri, mode);
+ uri = getUriWithoutUserId(uri);
final String original = setCallingPackage(callingPkg);
try {
return ContentProvider.this.openFile(
@@ -309,6 +333,7 @@ public abstract class ContentProvider implements ComponentCallbacks2 {
String callingPkg, Uri uri, String mode, ICancellationSignal cancellationSignal)
throws FileNotFoundException {
enforceFilePermission(callingPkg, uri, mode);
+ uri = getUriWithoutUserId(uri);
final String original = setCallingPackage(callingPkg);
try {
return ContentProvider.this.openAssetFile(
@@ -330,6 +355,7 @@ public abstract class ContentProvider implements ComponentCallbacks2 {
@Override
public String[] getStreamTypes(Uri uri, String mimeTypeFilter) {
+ uri = getUriWithoutUserId(uri);
return ContentProvider.this.getStreamTypes(uri, mimeTypeFilter);
}
@@ -337,6 +363,7 @@ public abstract class ContentProvider implements ComponentCallbacks2 {
public AssetFileDescriptor openTypedAssetFile(String callingPkg, Uri uri, String mimeType,
Bundle opts, ICancellationSignal cancellationSignal) throws FileNotFoundException {
enforceFilePermission(callingPkg, uri, "r");
+ uri = getUriWithoutUserId(uri);
final String original = setCallingPackage(callingPkg);
try {
return ContentProvider.this.openTypedAssetFile(
@@ -356,9 +383,11 @@ public abstract class ContentProvider implements ComponentCallbacks2 {
if (enforceReadPermission(callingPkg, uri) != AppOpsManager.MODE_ALLOWED) {
return null;
}
+ int userId = getUserIdFromUri(uri);
+ uri = getUriWithoutUserId(uri);
final String original = setCallingPackage(callingPkg);
try {
- return ContentProvider.this.canonicalize(uri);
+ return maybeAddUserId(ContentProvider.this.canonicalize(uri), userId);
} finally {
setCallingPackage(original);
}
@@ -369,9 +398,11 @@ public abstract class ContentProvider implements ComponentCallbacks2 {
if (enforceReadPermission(callingPkg, uri) != AppOpsManager.MODE_ALLOWED) {
return null;
}
+ int userId = getUserIdFromUri(uri);
+ uri = getUriWithoutUserId(uri);
final String original = setCallingPackage(callingPkg);
try {
- return ContentProvider.this.uncanonicalize(uri);
+ return maybeAddUserId(ContentProvider.this.uncanonicalize(uri), userId);
} finally {
setCallingPackage(original);
}
@@ -1680,4 +1711,75 @@ public abstract class ContentProvider implements ComponentCallbacks2 {
public void dump(FileDescriptor fd, PrintWriter writer, String[] args) {
writer.println("nothing to dump");
}
+
+ /** @hide */
+ public static int getUserIdFromAuthority(String auth, int defaultUserId) {
+ if (auth == null) return defaultUserId;
+ int end = auth.indexOf('@');
+ if (end == -1) return defaultUserId;
+ String userIdString = auth.substring(0, end);
+ try {
+ return Integer.parseInt(userIdString);
+ } catch (NumberFormatException e) {
+ Log.w(TAG, "Error parsing userId.", e);
+ return UserHandle.USER_NULL;
+ }
+ }
+
+ /** @hide */
+ public static int getUserIdFromAuthority(String auth) {
+ return getUserIdFromAuthority(auth, UserHandle.USER_CURRENT);
+ }
+
+ /** @hide */
+ public static int getUserIdFromUri(Uri uri, int defaultUserId) {
+ if (uri == null) return defaultUserId;
+ return getUserIdFromAuthority(uri.getAuthority(), defaultUserId);
+ }
+
+ /** @hide */
+ public static int getUserIdFromUri(Uri uri) {
+ return getUserIdFromUri(uri, UserHandle.USER_CURRENT);
+ }
+
+ /**
+ * Removes userId part from authority string. Expects format:
+ * userId@some.authority
+ * If there is no userId in the authority, it symply returns the argument
+ * @hide
+ */
+ public static String getAuthorityWithoutUserId(String auth) {
+ if (auth == null) return null;
+ int end = auth.indexOf('@');
+ return auth.substring(end+1);
+ }
+
+ /** @hide */
+ public static Uri getUriWithoutUserId(Uri uri) {
+ if (uri == null) return null;
+ Uri.Builder builder = uri.buildUpon();
+ builder.authority(getAuthorityWithoutUserId(uri.getAuthority()));
+ return builder.build();
+ }
+
+ /** @hide */
+ public static boolean uriHasUserId(Uri uri) {
+ if (uri == null) return false;
+ return !TextUtils.isEmpty(uri.getUserInfo());
+ }
+
+ /** @hide */
+ public static Uri maybeAddUserId(Uri uri, int userId) {
+ if (uri == null) return null;
+ if (userId != UserHandle.USER_CURRENT
+ && ContentResolver.SCHEME_CONTENT.equals(uri.getScheme())) {
+ if (!uriHasUserId(uri)) {
+ //We don't add the user Id if there's already one
+ Uri.Builder builder = uri.buildUpon();
+ builder.encodedAuthority("" + userId + "@" + uri.getEncodedAuthority());
+ return builder.build();
+ }
+ }
+ return uri;
+ }
}
diff --git a/core/java/android/content/ContentProviderOperation.java b/core/java/android/content/ContentProviderOperation.java
index 12e9bab..136e54d 100644
--- a/core/java/android/content/ContentProviderOperation.java
+++ b/core/java/android/content/ContentProviderOperation.java
@@ -16,6 +16,7 @@
package android.content;
+import android.content.ContentProvider;
import android.database.Cursor;
import android.net.Uri;
import android.os.Parcel;
@@ -87,6 +88,31 @@ public class ContentProviderOperation implements Parcelable {
mYieldAllowed = source.readInt() != 0;
}
+ /** @hide */
+ public ContentProviderOperation(ContentProviderOperation cpo, boolean removeUserIdFromUri) {
+ mType = cpo.mType;
+ if (removeUserIdFromUri) {
+ mUri = ContentProvider.getUriWithoutUserId(cpo.mUri);
+ } else {
+ mUri = cpo.mUri;
+ }
+ mValues = cpo.mValues;
+ mSelection = cpo.mSelection;
+ mSelectionArgs = cpo.mSelectionArgs;
+ mExpectedCount = cpo.mExpectedCount;
+ mSelectionArgsBackReferences = cpo.mSelectionArgsBackReferences;
+ mValuesBackReferences = cpo.mValuesBackReferences;
+ mYieldAllowed = cpo.mYieldAllowed;
+ }
+
+ /** @hide */
+ public ContentProviderOperation getWithoutUserIdInUri() {
+ if (ContentProvider.uriHasUserId(mUri)) {
+ return new ContentProviderOperation(this, true);
+ }
+ return this;
+ }
+
public void writeToParcel(Parcel dest, int flags) {
dest.writeInt(mType);
Uri.writeToParcel(dest, mUri);
@@ -387,7 +413,6 @@ public class ContentProviderOperation implements Parcelable {
}
};
-
/**
* Used to add parameters to a {@link ContentProviderOperation}. The {@link Builder} is
* first created by calling {@link ContentProviderOperation#newInsert(android.net.Uri)},
diff --git a/core/java/android/content/ContentProviderResult.java b/core/java/android/content/ContentProviderResult.java
index 5d188ef..ec3d002 100644
--- a/core/java/android/content/ContentProviderResult.java
+++ b/core/java/android/content/ContentProviderResult.java
@@ -16,7 +16,9 @@
package android.content;
+import android.content.ContentProvider;
import android.net.Uri;
+import android.os.UserHandle;
import android.os.Parcelable;
import android.os.Parcel;
@@ -50,6 +52,12 @@ public class ContentProviderResult implements Parcelable {
}
}
+ /** @hide */
+ public ContentProviderResult(ContentProviderResult cpr, int userId) {
+ uri = ContentProvider.maybeAddUserId(cpr.uri, userId);
+ count = cpr.count;
+ }
+
public void writeToParcel(Parcel dest, int flags) {
if (uri == null) {
dest.writeInt(1);
@@ -81,4 +89,4 @@ public class ContentProviderResult implements Parcelable {
}
return "ContentProviderResult(count=" + count + ")";
}
-} \ No newline at end of file
+}
diff --git a/core/java/android/content/ContentResolver.java b/core/java/android/content/ContentResolver.java
index 5b41394..7642e13 100644
--- a/core/java/android/content/ContentResolver.java
+++ b/core/java/android/content/ContentResolver.java
@@ -1643,7 +1643,8 @@ public abstract class ContentResolver {
*/
public void takePersistableUriPermission(Uri uri, @Intent.AccessUriMode int modeFlags) {
try {
- ActivityManagerNative.getDefault().takePersistableUriPermission(uri, modeFlags);
+ ActivityManagerNative.getDefault().takePersistableUriPermission(
+ ContentProvider.getUriWithoutUserId(uri), modeFlags, resolveUserId(uri));
} catch (RemoteException e) {
}
}
@@ -1658,7 +1659,8 @@ public abstract class ContentResolver {
*/
public void releasePersistableUriPermission(Uri uri, @Intent.AccessUriMode int modeFlags) {
try {
- ActivityManagerNative.getDefault().releasePersistableUriPermission(uri, modeFlags);
+ ActivityManagerNative.getDefault().releasePersistableUriPermission(
+ ContentProvider.getUriWithoutUserId(uri), modeFlags, resolveUserId(uri));
} catch (RemoteException e) {
}
}
@@ -2462,4 +2464,9 @@ public abstract class ContentResolver {
private final Context mContext;
final String mPackageName;
private static final String TAG = "ContentResolver";
+
+ /** @hide */
+ public int resolveUserId(Uri uri) {
+ return ContentProvider.getUserIdFromUri(uri, mContext.getUserId());
+ }
}
diff --git a/core/java/android/content/Intent.java b/core/java/android/content/Intent.java
index 3cfc56c..076f657 100644
--- a/core/java/android/content/Intent.java
+++ b/core/java/android/content/Intent.java
@@ -26,6 +26,7 @@ import android.annotation.IntDef;
import android.annotation.SdkConstant;
import android.annotation.SdkConstant.SdkConstantType;
import android.content.pm.ActivityInfo;
+import static android.content.ContentProvider.maybeAddUserId;
import android.content.pm.PackageManager;
import android.content.pm.ResolveInfo;
import android.content.res.Resources;
@@ -7433,6 +7434,41 @@ public class Intent implements Parcelable, Cloneable {
}
/**
+ * Prepare this {@link Intent} to be sent to another user
+ *
+ * @hide
+ */
+ public void prepareToLeaveUser(int userId) {
+ Uri data = getData();
+ if (data != null) {
+ mData = maybeAddUserId(data, userId);
+ }
+ if (mSelector != null) {
+ mSelector.prepareToLeaveUser(userId);
+ }
+ if (mClipData != null) {
+ mClipData.prepareToLeaveUser(userId);
+ }
+ String action = getAction();
+ if (ACTION_SEND.equals(action)) {
+ final Uri stream = getParcelableExtra(EXTRA_STREAM);
+ if (stream != null) {
+ putExtra(EXTRA_STREAM, maybeAddUserId(stream, userId));
+ }
+ }
+ if (ACTION_SEND_MULTIPLE.equals(action)) {
+ final ArrayList<Uri> streams = getParcelableArrayListExtra(EXTRA_STREAM);
+ if (streams != null) {
+ ArrayList<Uri> newStreams = new ArrayList<Uri>();
+ for (int i = 0; i < streams.size(); i++) {
+ newStreams.add(maybeAddUserId(streams.get(i), userId));
+ }
+ putParcelableArrayListExtra(EXTRA_STREAM, newStreams);
+ }
+ }
+ }
+
+ /**
* Migrate any {@link #EXTRA_STREAM} in {@link #ACTION_SEND} and
* {@link #ACTION_SEND_MULTIPLE} to {@link ClipData}. Also inspects nested
* intents in {@link #ACTION_CHOOSER}.
diff --git a/core/java/com/android/internal/app/IntentForwarderActivity.java b/core/java/com/android/internal/app/IntentForwarderActivity.java
index 2f74372..47ef65a 100644
--- a/core/java/com/android/internal/app/IntentForwarderActivity.java
+++ b/core/java/com/android/internal/app/IntentForwarderActivity.java
@@ -84,6 +84,7 @@ public class IntentForwarderActivity extends Activity {
Slog.e(TAG, "PackageManagerService is dead?");
}
if (canForward) {
+ newIntent.prepareToLeaveUser(callingUserId);
startActivityAsUser(newIntent, userDest);
} else {
Slog.wtf(TAG, "the intent: " + newIntent + "cannot be forwarded from user "
diff --git a/core/java/com/android/internal/util/XmlUtils.java b/core/java/com/android/internal/util/XmlUtils.java
index b35de93..5b59599 100644
--- a/core/java/com/android/internal/util/XmlUtils.java
+++ b/core/java/com/android/internal/util/XmlUtils.java
@@ -912,6 +912,15 @@ public class XmlUtils {
}
}
+ public static int readIntAttribute(XmlPullParser in, String name, int defaultValue) {
+ final String value = in.getAttributeValue(null, name);
+ try {
+ return Integer.parseInt(value);
+ } catch (NumberFormatException e) {
+ return defaultValue;
+ }
+ }
+
public static int readIntAttribute(XmlPullParser in, String name) throws IOException {
final String value = in.getAttributeValue(null, name);
try {
diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java
index 344268a..d6457c3 100644
--- a/services/core/java/com/android/server/am/ActivityManagerService.java
+++ b/services/core/java/com/android/server/am/ActivityManagerService.java
@@ -722,6 +722,8 @@ public final class ActivityManagerService extends ActivityManagerNative
private static final String TAG_URI_GRANTS = "uri-grants";
private static final String TAG_URI_GRANT = "uri-grant";
private static final String ATTR_USER_HANDLE = "userHandle";
+ private static final String ATTR_SOURCE_USER_ID = "sourceUserId";
+ private static final String ATTR_TARGET_USER_ID = "targetUserId";
private static final String ATTR_SOURCE_PKG = "sourcePkg";
private static final String ATTR_TARGET_PKG = "targetPkg";
private static final String ATTR_URI = "uri";
@@ -739,10 +741,12 @@ public final class ActivityManagerService extends ActivityManagerNative
mGrantedUriPermissions = new SparseArray<ArrayMap<GrantUri, UriPermission>>();
public static class GrantUri {
+ public final int sourceUserId;
public final Uri uri;
- public final boolean prefix;
+ public boolean prefix;
- public GrantUri(Uri uri, boolean prefix) {
+ public GrantUri(int sourceUserId, Uri uri, boolean prefix) {
+ this.sourceUserId = sourceUserId;
this.uri = uri;
this.prefix = prefix;
}
@@ -756,18 +760,28 @@ public final class ActivityManagerService extends ActivityManagerNative
public boolean equals(Object o) {
if (o instanceof GrantUri) {
GrantUri other = (GrantUri) o;
- return uri.equals(other.uri) && prefix == other.prefix;
+ return uri.equals(other.uri) && (sourceUserId == other.sourceUserId)
+ && prefix == other.prefix;
}
return false;
}
@Override
public String toString() {
- if (prefix) {
- return uri.toString() + " [prefix]";
- } else {
- return uri.toString();
- }
+ String result = Integer.toString(sourceUserId) + " @ " + uri.toString();
+ if (prefix) result += " [prefix]";
+ return result;
+ }
+
+ public String toSafeString() {
+ String result = Integer.toString(sourceUserId) + " @ " + uri.toSafeString();
+ if (prefix) result += " [prefix]";
+ return result;
+ }
+
+ public static GrantUri resolve(int defaultSourceUserHandle, Uri uri) {
+ return new GrantUri(ContentProvider.getUserIdFromUri(uri, defaultSourceUserHandle),
+ ContentProvider.getUriWithoutUserId(uri), false);
}
}
@@ -5991,9 +6005,9 @@ public final class ActivityManagerService extends ActivityManagerNative
* in {@link ContentProvider}.
*/
private final boolean checkHoldingPermissionsLocked(
- IPackageManager pm, ProviderInfo pi, Uri uri, int uid, final int modeFlags) {
+ IPackageManager pm, ProviderInfo pi, GrantUri grantUri, int uid, final int modeFlags) {
if (DEBUG_URI_PERMISSION) Slog.v(TAG,
- "checkHoldingPermissionsLocked: uri=" + uri + " uid=" + uid);
+ "checkHoldingPermissionsLocked: uri=" + grantUri + " uid=" + uid);
if (pi.applicationInfo.uid == uid) {
return true;
@@ -6022,7 +6036,7 @@ public final class ActivityManagerService extends ActivityManagerNative
// check if target holds any <path-permission> that match uri
final PathPermission[] pps = pi.pathPermissions;
if (pps != null) {
- final String path = uri.getPath();
+ final String path = grantUri.uri.getPath();
int i = pps.length;
while (i > 0 && (!readMet || !writeMet)) {
i--;
@@ -6087,32 +6101,33 @@ public final class ActivityManagerService extends ActivityManagerNative
return pi;
}
- private UriPermission findUriPermissionLocked(int targetUid, GrantUri uri) {
+ private UriPermission findUriPermissionLocked(int targetUid, GrantUri grantUri) {
final ArrayMap<GrantUri, UriPermission> targetUris = mGrantedUriPermissions.get(targetUid);
if (targetUris != null) {
- return targetUris.get(uri);
+ return targetUris.get(grantUri);
}
return null;
}
private UriPermission findOrCreateUriPermissionLocked(String sourcePkg,
- String targetPkg, int targetUid, GrantUri uri) {
+ String targetPkg, int targetUid, GrantUri grantUri) {
ArrayMap<GrantUri, UriPermission> targetUris = mGrantedUriPermissions.get(targetUid);
if (targetUris == null) {
targetUris = Maps.newArrayMap();
mGrantedUriPermissions.put(targetUid, targetUris);
}
- UriPermission perm = targetUris.get(uri);
+ UriPermission perm = targetUris.get(grantUri);
if (perm == null) {
- perm = new UriPermission(sourcePkg, targetPkg, targetUid, uri);
- targetUris.put(uri, perm);
+ perm = new UriPermission(sourcePkg, targetPkg, targetUid, grantUri);
+ targetUris.put(grantUri, perm);
}
return perm;
}
- private final boolean checkUriPermissionLocked(Uri uri, int uid, final int modeFlags) {
+ private final boolean checkUriPermissionLocked(GrantUri grantUri, int uid,
+ final int modeFlags) {
final boolean persistable = (modeFlags & Intent.FLAG_GRANT_PERSISTABLE_URI_PERMISSION) != 0;
final int minStrength = persistable ? UriPermission.STRENGTH_PERSISTABLE
: UriPermission.STRENGTH_OWNED;
@@ -6126,7 +6141,7 @@ public final class ActivityManagerService extends ActivityManagerNative
if (perms == null) return false;
// First look for exact match
- final UriPermission exactPerm = perms.get(new GrantUri(uri, false));
+ final UriPermission exactPerm = perms.get(grantUri);
if (exactPerm != null && exactPerm.getStrength(modeFlags) >= minStrength) {
return true;
}
@@ -6135,7 +6150,7 @@ public final class ActivityManagerService extends ActivityManagerNative
final int N = perms.size();
for (int i = 0; i < N; i++) {
final UriPermission perm = perms.valueAt(i);
- if (perm.uri.prefix && uri.isPathPrefixMatch(perm.uri.uri)
+ if (perm.uri.prefix && grantUri.uri.isPathPrefixMatch(perm.uri.uri)
&& perm.getStrength(modeFlags) >= minStrength) {
return true;
}
@@ -6145,7 +6160,8 @@ public final class ActivityManagerService extends ActivityManagerNative
}
@Override
- public int checkUriPermission(Uri uri, int pid, int uid, final int modeFlags) {
+ public int checkUriPermission(Uri uri, int pid, int uid,
+ final int modeFlags, int userId) {
enforceNotIsolatedCaller("checkUriPermission");
// Another redirected-binder-call permissions check as in
@@ -6161,7 +6177,7 @@ public final class ActivityManagerService extends ActivityManagerNative
return PackageManager.PERMISSION_GRANTED;
}
synchronized (this) {
- return checkUriPermissionLocked(uri, uid, modeFlags)
+ return checkUriPermissionLocked(new GrantUri(userId, uri, false), uid, modeFlags)
? PackageManager.PERMISSION_GRANTED
: PackageManager.PERMISSION_DENIED;
}
@@ -6176,30 +6192,31 @@ public final class ActivityManagerService extends ActivityManagerNative
* If you already know the uid of the target, you can supply it in
* lastTargetUid else set that to -1.
*/
- int checkGrantUriPermissionLocked(int callingUid, String targetPkg,
- Uri uri, final int modeFlags, int lastTargetUid) {
+ int checkGrantUriPermissionLocked(int callingUid, String targetPkg, GrantUri grantUri,
+ final int modeFlags, int lastTargetUid) {
if (!Intent.isAccessUriMode(modeFlags)) {
return -1;
}
if (targetPkg != null) {
if (DEBUG_URI_PERMISSION) Slog.v(TAG,
- "Checking grant " + targetPkg + " permission to " + uri);
+ "Checking grant " + targetPkg + " permission to " + grantUri);
}
final IPackageManager pm = AppGlobals.getPackageManager();
// If this is not a content: uri, we can't do anything with it.
- if (!ContentResolver.SCHEME_CONTENT.equals(uri.getScheme())) {
+ if (!ContentResolver.SCHEME_CONTENT.equals(grantUri.uri.getScheme())) {
if (DEBUG_URI_PERMISSION) Slog.v(TAG,
- "Can't grant URI permission for non-content URI: " + uri);
+ "Can't grant URI permission for non-content URI: " + grantUri);
return -1;
}
- final String authority = uri.getAuthority();
- final ProviderInfo pi = getProviderInfoLocked(authority, UserHandle.getUserId(callingUid));
+ final String authority = grantUri.uri.getAuthority();
+ final ProviderInfo pi = getProviderInfoLocked(authority, grantUri.sourceUserId);
if (pi == null) {
- Slog.w(TAG, "No content provider found for permission check: " + uri.toSafeString());
+ Slog.w(TAG, "No content provider found for permission check: " +
+ grantUri.uri.toSafeString());
return -1;
}
@@ -6219,10 +6236,10 @@ public final class ActivityManagerService extends ActivityManagerNative
if (targetUid >= 0) {
// First... does the target actually need this permission?
- if (checkHoldingPermissionsLocked(pm, pi, uri, targetUid, modeFlags)) {
+ if (checkHoldingPermissionsLocked(pm, pi, grantUri, targetUid, modeFlags)) {
// No need to grant the target this permission.
if (DEBUG_URI_PERMISSION) Slog.v(TAG,
- "Target " + targetPkg + " already has full permission to " + uri);
+ "Target " + targetPkg + " already has full permission to " + grantUri);
return -1;
}
} else {
@@ -6248,14 +6265,14 @@ public final class ActivityManagerService extends ActivityManagerNative
throw new SecurityException("Provider " + pi.packageName
+ "/" + pi.name
+ " does not allow granting of Uri permissions (uri "
- + uri + ")");
+ + grantUri + ")");
}
if (pi.uriPermissionPatterns != null) {
final int N = pi.uriPermissionPatterns.length;
boolean allowed = false;
for (int i=0; i<N; i++) {
if (pi.uriPermissionPatterns[i] != null
- && pi.uriPermissionPatterns[i].match(uri.getPath())) {
+ && pi.uriPermissionPatterns[i].match(grantUri.uri.getPath())) {
allowed = true;
break;
}
@@ -6264,35 +6281,35 @@ public final class ActivityManagerService extends ActivityManagerNative
throw new SecurityException("Provider " + pi.packageName
+ "/" + pi.name
+ " does not allow granting of permission to path of Uri "
- + uri);
+ + grantUri);
}
}
// Third... does the caller itself have permission to access
// this uri?
- if (callingUid != Process.myUid()) {
- if (!checkHoldingPermissionsLocked(pm, pi, uri, callingUid, modeFlags)) {
+ if (UserHandle.getAppId(callingUid) != Process.SYSTEM_UID) {
+ if (!checkHoldingPermissionsLocked(pm, pi, grantUri, callingUid, modeFlags)) {
// Require they hold a strong enough Uri permission
- if (!checkUriPermissionLocked(uri, callingUid, modeFlags)) {
+ if (!checkUriPermissionLocked(grantUri, callingUid, modeFlags)) {
throw new SecurityException("Uid " + callingUid
- + " does not have permission to uri " + uri);
+ + " does not have permission to uri " + grantUri);
}
}
}
-
return targetUid;
}
@Override
- public int checkGrantUriPermission(int callingUid, String targetPkg,
- Uri uri, final int modeFlags) {
+ public int checkGrantUriPermission(int callingUid, String targetPkg, Uri uri,
+ final int modeFlags, int userId) {
enforceNotIsolatedCaller("checkGrantUriPermission");
synchronized(this) {
- return checkGrantUriPermissionLocked(callingUid, targetPkg, uri, modeFlags, -1);
+ return checkGrantUriPermissionLocked(callingUid, targetPkg,
+ new GrantUri(userId, uri, false), modeFlags, -1);
}
}
- void grantUriPermissionUncheckedLocked(int targetUid, String targetPkg, Uri uri,
+ void grantUriPermissionUncheckedLocked(int targetUid, String targetPkg, GrantUri grantUri,
final int modeFlags, UriPermissionOwner owner) {
if (!Intent.isAccessUriMode(modeFlags)) {
return;
@@ -6303,36 +6320,40 @@ public final class ActivityManagerService extends ActivityManagerNative
// the target.
if (DEBUG_URI_PERMISSION) Slog.v(TAG,
- "Granting " + targetPkg + "/" + targetUid + " permission to " + uri);
+ "Granting " + targetPkg + "/" + targetUid + " permission to " + grantUri);
- final String authority = uri.getAuthority();
- final ProviderInfo pi = getProviderInfoLocked(authority, UserHandle.getUserId(targetUid));
+ final String authority = grantUri.uri.getAuthority();
+ final ProviderInfo pi = getProviderInfoLocked(authority, grantUri.sourceUserId);
if (pi == null) {
- Slog.w(TAG, "No content provider found for grant: " + uri.toSafeString());
+ Slog.w(TAG, "No content provider found for grant: " + grantUri.toSafeString());
return;
}
- final boolean prefix = (modeFlags & Intent.FLAG_GRANT_PREFIX_URI_PERMISSION) != 0;
+ if ((modeFlags & Intent.FLAG_GRANT_PREFIX_URI_PERMISSION) != 0) {
+ grantUri.prefix = true;
+ }
final UriPermission perm = findOrCreateUriPermissionLocked(
- pi.packageName, targetPkg, targetUid, new GrantUri(uri, prefix));
+ pi.packageName, targetPkg, targetUid, grantUri);
perm.grantModes(modeFlags, owner);
}
- void grantUriPermissionLocked(int callingUid, String targetPkg, Uri uri,
+ void grantUriPermissionLocked(int callingUid, String targetPkg, GrantUri grantUri,
final int modeFlags, UriPermissionOwner owner) {
if (targetPkg == null) {
throw new NullPointerException("targetPkg");
}
- int targetUid = checkGrantUriPermissionLocked(callingUid, targetPkg, uri, modeFlags, -1);
+ int targetUid = checkGrantUriPermissionLocked(callingUid, targetPkg, grantUri, modeFlags,
+ -1);
if (targetUid < 0) {
return;
}
- grantUriPermissionUncheckedLocked(targetUid, targetPkg, uri, modeFlags, owner);
+ grantUriPermissionUncheckedLocked(targetUid, targetPkg, grantUri, modeFlags,
+ owner);
}
- static class NeededUriGrants extends ArrayList<Uri> {
+ static class NeededUriGrants extends ArrayList<GrantUri> {
final String targetPkg;
final int targetUid;
final int flags;
@@ -6369,13 +6390,14 @@ public final class ActivityManagerService extends ActivityManagerNative
}
if (data != null) {
- int targetUid = checkGrantUriPermissionLocked(callingUid, targetPkg, data,
- mode, needed != null ? needed.targetUid : -1);
+ GrantUri grantUri = GrantUri.resolve(UserHandle.getUserId(callingUid), data);
+ int targetUid = checkGrantUriPermissionLocked(callingUid, targetPkg, grantUri, mode,
+ needed != null ? needed.targetUid : -1);
if (targetUid > 0) {
if (needed == null) {
needed = new NeededUriGrants(targetPkg, targetUid, mode);
}
- needed.add(data);
+ needed.add(grantUri);
}
}
if (clip != null) {
@@ -6383,13 +6405,14 @@ public final class ActivityManagerService extends ActivityManagerNative
Uri uri = clip.getItemAt(i).getUri();
if (uri != null) {
int targetUid = -1;
- targetUid = checkGrantUriPermissionLocked(callingUid, targetPkg, uri,
- mode, needed != null ? needed.targetUid : -1);
+ GrantUri grantUri = GrantUri.resolve(UserHandle.getUserId(callingUid), uri);
+ targetUid = checkGrantUriPermissionLocked(callingUid, targetPkg, grantUri, mode,
+ needed != null ? needed.targetUid : -1);
if (targetUid > 0) {
if (needed == null) {
needed = new NeededUriGrants(targetPkg, targetUid, mode);
}
- needed.add(uri);
+ needed.add(grantUri);
}
} else {
Intent clipIntent = clip.getItemAt(i).getIntent();
@@ -6414,8 +6437,9 @@ public final class ActivityManagerService extends ActivityManagerNative
UriPermissionOwner owner) {
if (needed != null) {
for (int i=0; i<needed.size(); i++) {
+ GrantUri grantUri = needed.get(i);
grantUriPermissionUncheckedLocked(needed.targetUid, needed.targetPkg,
- needed.get(i), needed.flags, owner);
+ grantUri, needed.flags, owner);
}
}
}
@@ -6432,20 +6456,21 @@ public final class ActivityManagerService extends ActivityManagerNative
}
@Override
- public void grantUriPermission(IApplicationThread caller, String targetPkg,
- Uri uri, final int modeFlags) {
+ public void grantUriPermission(IApplicationThread caller, String targetPkg, Uri uri,
+ final int modeFlags, int userId) {
enforceNotIsolatedCaller("grantUriPermission");
+ GrantUri grantUri = new GrantUri(userId, uri, false);
synchronized(this) {
final ProcessRecord r = getRecordForAppLocked(caller);
if (r == null) {
throw new SecurityException("Unable to find app for caller "
+ caller
- + " when granting permission to uri " + uri);
+ + " when granting permission to uri " + grantUri);
}
if (targetPkg == null) {
throw new IllegalArgumentException("null target");
}
- if (uri == null) {
+ if (grantUri == null) {
throw new IllegalArgumentException("null uri");
}
@@ -6454,7 +6479,7 @@ public final class ActivityManagerService extends ActivityManagerNative
| Intent.FLAG_GRANT_PERSISTABLE_URI_PERMISSION
| Intent.FLAG_GRANT_PREFIX_URI_PERMISSION);
- grantUriPermissionLocked(r.uid, targetPkg, uri, modeFlags, null);
+ grantUriPermissionLocked(r.uid, targetPkg, grantUri, modeFlags, null);
}
}
@@ -6474,24 +6499,25 @@ public final class ActivityManagerService extends ActivityManagerNative
}
}
- private void revokeUriPermissionLocked(int callingUid, Uri uri, final int modeFlags) {
- if (DEBUG_URI_PERMISSION) Slog.v(TAG, "Revoking all granted permissions to " + uri);
+ private void revokeUriPermissionLocked(int callingUid, GrantUri grantUri, final int modeFlags) {
+ if (DEBUG_URI_PERMISSION) Slog.v(TAG, "Revoking all granted permissions to " + grantUri);
final IPackageManager pm = AppGlobals.getPackageManager();
- final String authority = uri.getAuthority();
- final ProviderInfo pi = getProviderInfoLocked(authority, UserHandle.getUserId(callingUid));
+ final String authority = grantUri.uri.getAuthority();
+ final ProviderInfo pi = getProviderInfoLocked(authority, grantUri.sourceUserId);
if (pi == null) {
- Slog.w(TAG, "No content provider found for permission revoke: " + uri.toSafeString());
+ Slog.w(TAG, "No content provider found for permission revoke: "
+ + grantUri.toSafeString());
return;
}
// Does the caller have this permission on the URI?
- if (!checkHoldingPermissionsLocked(pm, pi, uri, callingUid, modeFlags)) {
+ if (!checkHoldingPermissionsLocked(pm, pi, grantUri, callingUid, modeFlags)) {
// Right now, if you are not the original owner of the permission,
// you are not allowed to revoke it.
//if (!checkUriPermissionLocked(uri, callingUid, modeFlags)) {
throw new SecurityException("Uid " + callingUid
- + " does not have permission to uri " + uri);
+ + " does not have permission to uri " + grantUri);
//}
}
@@ -6505,7 +6531,8 @@ public final class ActivityManagerService extends ActivityManagerNative
for (Iterator<UriPermission> it = perms.values().iterator(); it.hasNext();) {
final UriPermission perm = it.next();
- if (perm.uri.uri.isPathPrefixMatch(uri)) {
+ if (perm.uri.sourceUserId == grantUri.sourceUserId
+ && perm.uri.uri.isPathPrefixMatch(grantUri.uri)) {
if (DEBUG_URI_PERMISSION)
Slog.v(TAG,
"Revoking " + perm.targetUid + " permission to " + perm.uri);
@@ -6530,8 +6557,8 @@ public final class ActivityManagerService extends ActivityManagerNative
}
@Override
- public void revokeUriPermission(IApplicationThread caller, Uri uri,
- final int modeFlags) {
+ public void revokeUriPermission(IApplicationThread caller, Uri uri, final int modeFlags,
+ int userId) {
enforceNotIsolatedCaller("revokeUriPermission");
synchronized(this) {
final ProcessRecord r = getRecordForAppLocked(caller);
@@ -6551,14 +6578,14 @@ public final class ActivityManagerService extends ActivityManagerNative
final IPackageManager pm = AppGlobals.getPackageManager();
final String authority = uri.getAuthority();
- final ProviderInfo pi = getProviderInfoLocked(authority, r.userId);
+ final ProviderInfo pi = getProviderInfoLocked(authority, userId);
if (pi == null) {
Slog.w(TAG, "No content provider found for permission revoke: "
+ uri.toSafeString());
return;
}
- revokeUriPermissionLocked(r.uid, uri, modeFlags);
+ revokeUriPermissionLocked(r.uid, new GrantUri(userId, uri, false), modeFlags);
}
}
@@ -6628,8 +6655,8 @@ public final class ActivityManagerService extends ActivityManagerNative
}
@Override
- public void grantUriPermissionFromOwner(IBinder token, int fromUid, String targetPkg,
- Uri uri, final int modeFlags) {
+ public void grantUriPermissionFromOwner(IBinder token, int fromUid, String targetPkg, Uri uri,
+ final int modeFlags, int userId) {
synchronized(this) {
UriPermissionOwner owner = UriPermissionOwner.fromExternalToken(token);
if (owner == null) {
@@ -6649,12 +6676,13 @@ public final class ActivityManagerService extends ActivityManagerNative
throw new IllegalArgumentException("null uri");
}
- grantUriPermissionLocked(fromUid, targetPkg, uri, modeFlags, owner);
+ grantUriPermissionLocked(fromUid, targetPkg, new GrantUri(userId, uri, false),
+ modeFlags, owner);
}
}
@Override
- public void revokeUriPermissionFromOwner(IBinder token, Uri uri, int mode) {
+ public void revokeUriPermissionFromOwner(IBinder token, Uri uri, int mode, int userId) {
synchronized(this) {
UriPermissionOwner owner = UriPermissionOwner.fromExternalToken(token);
if (owner == null) {
@@ -6664,7 +6692,7 @@ public final class ActivityManagerService extends ActivityManagerNative
if (uri == null) {
owner.removeUriPermissionsLocked(mode);
} else {
- owner.removeUriPermissionLocked(uri, mode);
+ owner.removeUriPermissionLocked(new GrantUri(userId, uri, false), mode);
}
}
}
@@ -6703,7 +6731,8 @@ public final class ActivityManagerService extends ActivityManagerNative
out.startTag(null, TAG_URI_GRANTS);
for (UriPermission.Snapshot perm : persist) {
out.startTag(null, TAG_URI_GRANT);
- writeIntAttribute(out, ATTR_USER_HANDLE, perm.userHandle);
+ writeIntAttribute(out, ATTR_SOURCE_USER_ID, perm.uri.sourceUserId);
+ writeIntAttribute(out, ATTR_TARGET_USER_ID, perm.targetUserId);
out.attribute(null, ATTR_SOURCE_PKG, perm.sourcePkg);
out.attribute(null, ATTR_TARGET_PKG, perm.targetPkg);
out.attribute(null, ATTR_URI, String.valueOf(perm.uri.uri));
@@ -6739,7 +6768,18 @@ public final class ActivityManagerService extends ActivityManagerNative
final String tag = in.getName();
if (type == START_TAG) {
if (TAG_URI_GRANT.equals(tag)) {
- final int userHandle = readIntAttribute(in, ATTR_USER_HANDLE);
+ final int sourceUserId;
+ final int targetUserId;
+ final int userHandle = readIntAttribute(in,
+ ATTR_USER_HANDLE, UserHandle.USER_NULL);
+ if (userHandle != UserHandle.USER_NULL) {
+ // For backwards compatibility.
+ sourceUserId = userHandle;
+ targetUserId = userHandle;
+ } else {
+ sourceUserId = readIntAttribute(in, ATTR_SOURCE_USER_ID);
+ targetUserId = readIntAttribute(in, ATTR_TARGET_USER_ID);
+ }
final String sourcePkg = in.getAttributeValue(null, ATTR_SOURCE_PKG);
final String targetPkg = in.getAttributeValue(null, ATTR_TARGET_PKG);
final Uri uri = Uri.parse(in.getAttributeValue(null, ATTR_URI));
@@ -6749,17 +6789,18 @@ public final class ActivityManagerService extends ActivityManagerNative
// Sanity check that provider still belongs to source package
final ProviderInfo pi = getProviderInfoLocked(
- uri.getAuthority(), userHandle);
+ uri.getAuthority(), sourceUserId);
if (pi != null && sourcePkg.equals(pi.packageName)) {
int targetUid = -1;
try {
targetUid = AppGlobals.getPackageManager()
- .getPackageUid(targetPkg, userHandle);
+ .getPackageUid(targetPkg, targetUserId);
} catch (RemoteException e) {
}
if (targetUid != -1) {
final UriPermission perm = findOrCreateUriPermissionLocked(
- sourcePkg, targetPkg, targetUid, new GrantUri(uri, prefix));
+ sourcePkg, targetPkg, targetUid,
+ new GrantUri(sourceUserId, uri, prefix));
perm.initPersistedModes(modeFlags, createdTime);
}
} else {
@@ -6781,7 +6822,7 @@ public final class ActivityManagerService extends ActivityManagerNative
}
@Override
- public void takePersistableUriPermission(Uri uri, final int modeFlags) {
+ public void takePersistableUriPermission(Uri uri, final int modeFlags, int userId) {
enforceNotIsolatedCaller("takePersistableUriPermission");
Preconditions.checkFlagsArgument(modeFlags,
@@ -6790,9 +6831,12 @@ public final class ActivityManagerService extends ActivityManagerNative
synchronized (this) {
final int callingUid = Binder.getCallingUid();
boolean persistChanged = false;
+ GrantUri grantUri = new GrantUri(userId, uri, false);
- UriPermission exactPerm = findUriPermissionLocked(callingUid, new GrantUri(uri, false));
- UriPermission prefixPerm = findUriPermissionLocked(callingUid, new GrantUri(uri, true));
+ UriPermission exactPerm = findUriPermissionLocked(callingUid,
+ new GrantUri(userId, uri, false));
+ UriPermission prefixPerm = findUriPermissionLocked(callingUid,
+ new GrantUri(userId, uri, true));
final boolean exactValid = (exactPerm != null)
&& ((modeFlags & exactPerm.persistableModeFlags) == modeFlags);
@@ -6801,7 +6845,7 @@ public final class ActivityManagerService extends ActivityManagerNative
if (!(exactValid || prefixValid)) {
throw new SecurityException("No persistable permission grants found for UID "
- + callingUid + " and Uri " + uri.toSafeString());
+ + callingUid + " and Uri " + grantUri.toSafeString());
}
if (exactValid) {
@@ -6820,7 +6864,7 @@ public final class ActivityManagerService extends ActivityManagerNative
}
@Override
- public void releasePersistableUriPermission(Uri uri, final int modeFlags) {
+ public void releasePersistableUriPermission(Uri uri, final int modeFlags, int userId) {
enforceNotIsolatedCaller("releasePersistableUriPermission");
Preconditions.checkFlagsArgument(modeFlags,
@@ -6830,8 +6874,10 @@ public final class ActivityManagerService extends ActivityManagerNative
final int callingUid = Binder.getCallingUid();
boolean persistChanged = false;
- UriPermission exactPerm = findUriPermissionLocked(callingUid, new GrantUri(uri, false));
- UriPermission prefixPerm = findUriPermissionLocked(callingUid, new GrantUri(uri, true));
+ UriPermission exactPerm = findUriPermissionLocked(callingUid,
+ new GrantUri(userId, uri, false));
+ UriPermission prefixPerm = findUriPermissionLocked(callingUid,
+ new GrantUri(userId, uri, true));
if (exactPerm == null && prefixPerm == null) {
throw new SecurityException("No permission grants found for UID " + callingUid
+ " and Uri " + uri.toSafeString());
@@ -7676,9 +7722,25 @@ public final class ActivityManagerService extends ActivityManagerNative
* in {@link ContentProvider}.
*/
private final String checkContentProviderPermissionLocked(
- ProviderInfo cpi, ProcessRecord r) {
+ ProviderInfo cpi, ProcessRecord r, int userId) {
final int callingPid = (r != null) ? r.pid : Binder.getCallingPid();
final int callingUid = (r != null) ? r.uid : Binder.getCallingUid();
+ final ArrayMap<GrantUri, UriPermission> perms = mGrantedUriPermissions.get(callingUid);
+ // Looking for cross-user grants before to enforce the typical cross-users permissions
+ if (userId != UserHandle.getUserId(callingUid)) {
+ if (perms != null) {
+ for (GrantUri grantUri : perms.keySet()) {
+ if (grantUri.sourceUserId == userId) {
+ String authority = grantUri.uri.getAuthority();
+ if (authority.equals(cpi.authority)) {
+ return null;
+ }
+ }
+ }
+ }
+ }
+ userId = handleIncomingUser(callingPid, callingUid, userId,
+ false, true, "checkContentProviderPermissionLocked", null);
if (checkComponentPermission(cpi.readPermission, callingPid, callingUid,
cpi.applicationInfo.uid, cpi.exported)
== PackageManager.PERMISSION_GRANTED) {
@@ -7709,10 +7771,9 @@ public final class ActivityManagerService extends ActivityManagerNative
}
}
- final ArrayMap<GrantUri, UriPermission> perms = mGrantedUriPermissions.get(callingUid);
if (perms != null) {
- for (GrantUri uri : perms.keySet()) {
- if (uri.uri.getAuthority().equals(cpi.authority)) {
+ for (GrantUri grantUri : perms.keySet()) {
+ if (grantUri.uri.getAuthority().equals(cpi.authority)) {
return null;
}
}
@@ -7820,7 +7881,7 @@ public final class ActivityManagerService extends ActivityManagerNative
if (providerRunning) {
cpi = cpr.info;
String msg;
- if ((msg=checkContentProviderPermissionLocked(cpi, r)) != null) {
+ if ((msg=checkContentProviderPermissionLocked(cpi, r, userId)) != null) {
throw new SecurityException(msg);
}
@@ -7908,7 +7969,7 @@ public final class ActivityManagerService extends ActivityManagerNative
cpi.applicationInfo = getAppInfoForUser(cpi.applicationInfo, userId);
String msg;
- if ((msg=checkContentProviderPermissionLocked(cpi, r)) != null) {
+ if ((msg=checkContentProviderPermissionLocked(cpi, r, userId)) != null) {
throw new SecurityException(msg);
}
@@ -8074,6 +8135,7 @@ public final class ActivityManagerService extends ActivityManagerNative
return cpr != null ? cpr.newHolder(conn) : null;
}
+ @Override
public final ContentProviderHolder getContentProvider(
IApplicationThread caller, String name, int userId, boolean stable) {
enforceNotIsolatedCaller("getContentProvider");
@@ -8083,9 +8145,8 @@ public final class ActivityManagerService extends ActivityManagerNative
Slog.w(TAG, msg);
throw new SecurityException(msg);
}
-
- userId = handleIncomingUser(Binder.getCallingPid(), Binder.getCallingUid(), userId,
- false, true, "getContentProvider", null);
+ // The incoming user check is now handled in checkContentProviderPermissionLocked() to deal
+ // with cross-user grant.
return getContentProviderImpl(caller, name, null, stable, userId);
}
diff --git a/services/core/java/com/android/server/am/UriPermission.java b/services/core/java/com/android/server/am/UriPermission.java
index 4970b8d..284086d 100644
--- a/services/core/java/com/android/server/am/UriPermission.java
+++ b/services/core/java/com/android/server/am/UriPermission.java
@@ -44,7 +44,7 @@ final class UriPermission {
public static final int STRENGTH_GLOBAL = 2;
public static final int STRENGTH_PERSISTABLE = 3;
- final int userHandle;
+ final int targetUserId;
final String sourcePkg;
final String targetPkg;
@@ -86,7 +86,7 @@ final class UriPermission {
private String stringName;
UriPermission(String sourcePkg, String targetPkg, int targetUid, GrantUri uri) {
- this.userHandle = UserHandle.getUserId(targetUid);
+ this.targetUserId = UserHandle.getUserId(targetUid);
this.sourcePkg = sourcePkg;
this.targetPkg = targetPkg;
this.targetUid = targetUid;
@@ -307,7 +307,7 @@ final class UriPermission {
void dump(PrintWriter pw, String prefix) {
pw.print(prefix);
- pw.print("userHandle=" + userHandle);
+ pw.print("targetUserId=" + targetUserId);
pw.print(" sourcePkg=" + sourcePkg);
pw.println(" targetPkg=" + targetPkg);
@@ -352,7 +352,7 @@ final class UriPermission {
* {@link UriPermission#persistedModeFlags} state.
*/
public static class Snapshot {
- final int userHandle;
+ final int targetUserId;
final String sourcePkg;
final String targetPkg;
final GrantUri uri;
@@ -360,7 +360,7 @@ final class UriPermission {
final long persistedCreateTime;
private Snapshot(UriPermission perm) {
- this.userHandle = perm.userHandle;
+ this.targetUserId = perm.targetUserId;
this.sourcePkg = perm.sourcePkg;
this.targetPkg = perm.targetPkg;
this.uri = perm.uri;
diff --git a/services/core/java/com/android/server/am/UriPermissionOwner.java b/services/core/java/com/android/server/am/UriPermissionOwner.java
index 65d7047..ae83940 100644
--- a/services/core/java/com/android/server/am/UriPermissionOwner.java
+++ b/services/core/java/com/android/server/am/UriPermissionOwner.java
@@ -70,13 +70,13 @@ final class UriPermissionOwner {
removeUriPermissionLocked(null, mode);
}
- void removeUriPermissionLocked(Uri uri, int mode) {
+ void removeUriPermissionLocked(ActivityManagerService.GrantUri grantUri, int mode) {
if ((mode & Intent.FLAG_GRANT_READ_URI_PERMISSION) != 0
&& mReadPerms != null) {
Iterator<UriPermission> it = mReadPerms.iterator();
while (it.hasNext()) {
UriPermission perm = it.next();
- if (uri == null || uri.equals(perm.uri)) {
+ if (grantUri == null || grantUri.equals(perm.uri)) {
perm.removeReadOwner(this);
service.removeUriPermissionIfNeededLocked(perm);
it.remove();
@@ -91,7 +91,7 @@ final class UriPermissionOwner {
Iterator<UriPermission> it = mWritePerms.iterator();
while (it.hasNext()) {
UriPermission perm = it.next();
- if (uri == null || uri.equals(perm.uri)) {
+ if (grantUri == null || grantUri.equals(perm.uri)) {
perm.removeWriteOwner(this);
service.removeUriPermissionIfNeededLocked(perm);
it.remove();
diff --git a/services/core/java/com/android/server/clipboard/ClipboardService.java b/services/core/java/com/android/server/clipboard/ClipboardService.java
index f47d66d..15e3e89 100644
--- a/services/core/java/com/android/server/clipboard/ClipboardService.java
+++ b/services/core/java/com/android/server/clipboard/ClipboardService.java
@@ -23,6 +23,7 @@ import android.app.IActivityManager;
import android.content.BroadcastReceiver;
import android.content.ClipData;
import android.content.ClipDescription;
+import android.content.ContentProvider;
import android.content.IClipboard;
import android.content.IOnPrimaryClipChangedListener;
import android.content.Context;
@@ -255,7 +256,8 @@ public class ClipboardService extends IClipboard.Stub {
long ident = Binder.clearCallingIdentity();
try {
// This will throw SecurityException for us.
- mAm.checkGrantUriPermission(uid, null, uri, Intent.FLAG_GRANT_READ_URI_PERMISSION);
+ mAm.checkGrantUriPermission(uid, null, ContentProvider.getUriWithoutUserId(uri),
+ Intent.FLAG_GRANT_READ_URI_PERMISSION, resolveUserId(uri, uid));
} catch (RemoteException e) {
} finally {
Binder.restoreCallingIdentity(ident);
@@ -282,8 +284,10 @@ public class ClipboardService extends IClipboard.Stub {
private final void grantUriLocked(Uri uri, String pkg) {
long ident = Binder.clearCallingIdentity();
try {
- mAm.grantUriPermissionFromOwner(mPermissionOwner, Process.myUid(), pkg, uri,
- Intent.FLAG_GRANT_READ_URI_PERMISSION);
+ mAm.grantUriPermissionFromOwner(mPermissionOwner, Process.myUid(), pkg,
+ ContentProvider.getUriWithoutUserId(uri),
+ Intent.FLAG_GRANT_READ_URI_PERMISSION,
+ resolveUserId(uri, Process.myUid()));
} catch (RemoteException e) {
} finally {
Binder.restoreCallingIdentity(ident);
@@ -331,9 +335,10 @@ public class ClipboardService extends IClipboard.Stub {
private final void revokeUriLocked(Uri uri) {
long ident = Binder.clearCallingIdentity();
try {
- mAm.revokeUriPermissionFromOwner(mPermissionOwner, uri,
- Intent.FLAG_GRANT_READ_URI_PERMISSION
- | Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
+ mAm.revokeUriPermissionFromOwner(mPermissionOwner,
+ ContentProvider.getUriWithoutUserId(uri),
+ Intent.FLAG_GRANT_READ_URI_PERMISSION | Intent.FLAG_GRANT_WRITE_URI_PERMISSION,
+ resolveUserId(uri, Process.myUid()));
} catch (RemoteException e) {
} finally {
Binder.restoreCallingIdentity(ident);
@@ -361,4 +366,8 @@ public class ClipboardService extends IClipboard.Stub {
revokeItemLocked(clipboard.primaryClip.getItemAt(i));
}
}
+
+ private final int resolveUserId(Uri uri, int uid) {
+ return ContentProvider.getUserIdFromUri(uri, UserHandle.getUserId(uid));
+ }
}