diff --git a/core/java/android/content/Context.java b/core/java/android/content/Context.java index f979a0c585828..61dd7476aae03 100644 --- a/core/java/android/content/Context.java +++ b/core/java/android/content/Context.java @@ -3062,6 +3062,14 @@ public abstract class Context { * "content://foo". It will not remove any prefix grants that exist at a * higher level. * + *

Prior to {@link android.os.Build.VERSION_CODES#L}, if you did not have + * regular permission access to a Uri, but had received access to it through + * a specific Uri permission grant, you could not revoke that grant with this + * function and a {@link SecurityException} would be thrown. As of + * {@link android.os.Build.VERSION_CODES#L}, this function will not throw a security exception, + * but will remove whatever permission grants to the Uri had been given to the app + * (or none).

+ * * @param uri The Uri you would like to revoke access to. * @param modeFlags The desired access modes. Any combination of * {@link Intent#FLAG_GRANT_READ_URI_PERMISSION diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java index 5845ad0b01fa3..ad04787fb9839 100755 --- a/services/core/java/com/android/server/am/ActivityManagerService.java +++ b/services/core/java/com/android/server/am/ActivityManagerService.java @@ -7468,12 +7468,33 @@ public final class ActivityManagerService extends ActivityManagerNative // Does the caller have this permission on the URI? 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 " + grantUri); - //} + // Have they don't have direct access to the URI, then revoke any URI + // permissions that have been granted to them. + final ArrayMap perms = mGrantedUriPermissions.get(callingUid); + if (perms != null) { + boolean persistChanged = false; + for (Iterator it = perms.values().iterator(); it.hasNext();) { + final UriPermission perm = it.next(); + 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); + persistChanged |= perm.revokeModes( + modeFlags | Intent.FLAG_GRANT_PERSISTABLE_URI_PERMISSION); + if (perm.modeFlags == 0) { + it.remove(); + } + } + } + if (perms.isEmpty()) { + mGrantedUriPermissions.remove(callingUid); + } + if (persistChanged) { + schedulePersistUriGrants(); + } + } + return; } boolean persistChanged = false;