am f6f453d1: am b4ee4428: Merge "Fix issue #17428001: Fix revokeUriPermissions" into lmp-dev

* commit 'f6f453d1baa77d3bed97936ffbe177d15055c8e8':
  Fix issue #17428001: Fix revokeUriPermissions
diff --git a/core/java/android/content/Context.java b/core/java/android/content/Context.java
index f979a0c..61dd7476 100644
--- a/core/java/android/content/Context.java
+++ b/core/java/android/content/Context.java
@@ -3062,6 +3062,14 @@
      * "content://foo".  It will not remove any prefix grants that exist at a
      * higher level.
      *
+     * <p>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).</p>
+     *
      * @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 5845ad0..ad04787 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 @@
 
         // 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<GrantUri, UriPermission> perms = mGrantedUriPermissions.get(callingUid);
+            if (perms != null) {
+                boolean persistChanged = false;
+                for (Iterator<UriPermission> 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;