Loading core/java/android/app/ActivityManagerNative.java +35 −17 Original line number Diff line number Diff line Loading @@ -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; Loading @@ -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; } Loading @@ -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; } Loading @@ -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; } Loading @@ -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; } Loading Loading @@ -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; } Loading @@ -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; } Loading @@ -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; Loading Loading @@ -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(); Loading @@ -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(); Loading @@ -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); Loading @@ -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(); Loading @@ -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(); Loading @@ -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(); Loading Loading @@ -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); Loading @@ -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(); Loading @@ -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); Loading @@ -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(); Loading @@ -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); Loading @@ -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(); Loading core/java/android/app/ContextImpl.java +25 −8 Original line number Diff line number Diff line Loading @@ -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; Loading Loading @@ -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) { } } Loading @@ -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) { } } Loading @@ -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(); Loading Loading @@ -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 Loading @@ -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 Loading @@ -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()); } } } core/java/android/app/IActivityManager.java +13 −11 Original line number Diff line number Diff line Loading @@ -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; Loading Loading @@ -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, Loading core/java/android/content/ClipData.java +20 −1 Original line number Diff line number Diff line Loading @@ -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; Loading Loading @@ -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. Loading Loading @@ -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); Loading core/java/android/content/ContentProvider.java +108 −6 Original line number Diff line number Diff line Loading @@ -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; Loading Loading @@ -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( Loading @@ -207,6 +209,7 @@ public abstract class ContentProvider implements ComponentCallbacks2 { @Override public String getType(Uri uri) { uri = getUriWithoutUserId(uri); return ContentProvider.this.getType(uri); } Loading @@ -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); } Loading @@ -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); Loading @@ -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); } Loading @@ -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); Loading @@ -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); Loading @@ -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( Loading @@ -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( Loading @@ -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); } Loading @@ -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( Loading @@ -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); } Loading @@ -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); } Loading Loading @@ -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; } } Loading
core/java/android/app/ActivityManagerNative.java +35 −17 Original line number Diff line number Diff line Loading @@ -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; Loading @@ -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; } Loading @@ -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; } Loading @@ -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; } Loading @@ -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; } Loading Loading @@ -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; } Loading @@ -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; } Loading @@ -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; Loading Loading @@ -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(); Loading @@ -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(); Loading @@ -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); Loading @@ -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(); Loading @@ -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(); Loading @@ -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(); Loading Loading @@ -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); Loading @@ -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(); Loading @@ -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); Loading @@ -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(); Loading @@ -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); Loading @@ -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(); Loading
core/java/android/app/ContextImpl.java +25 −8 Original line number Diff line number Diff line Loading @@ -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; Loading Loading @@ -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) { } } Loading @@ -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) { } } Loading @@ -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(); Loading Loading @@ -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 Loading @@ -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 Loading @@ -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()); } } }
core/java/android/app/IActivityManager.java +13 −11 Original line number Diff line number Diff line Loading @@ -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; Loading Loading @@ -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, Loading
core/java/android/content/ClipData.java +20 −1 Original line number Diff line number Diff line Loading @@ -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; Loading Loading @@ -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. Loading Loading @@ -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); Loading
core/java/android/content/ContentProvider.java +108 −6 Original line number Diff line number Diff line Loading @@ -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; Loading Loading @@ -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( Loading @@ -207,6 +209,7 @@ public abstract class ContentProvider implements ComponentCallbacks2 { @Override public String getType(Uri uri) { uri = getUriWithoutUserId(uri); return ContentProvider.this.getType(uri); } Loading @@ -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); } Loading @@ -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); Loading @@ -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); } Loading @@ -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); Loading @@ -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); Loading @@ -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( Loading @@ -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( Loading @@ -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); } Loading @@ -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( Loading @@ -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); } Loading @@ -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); } Loading Loading @@ -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; } }