Gracefully handle content uris without id in checkUriPermission

Uri grants are allowed only if app has access to corresponding db row.
MediaProvider uri permission check works correctly for uris that
correspond to valid database row. However, for content uris of the
table, we always deny the permission.
Apps might not need this permission grant in most of the scenarios like
picker activities. However, some apps request for uri grant and we
kill the app if the permission is denied.

Changed checkUriPermission to allow uri grants on content uris without
ID if it is non prefix grants (This doesn't grant any extra access). i
If it's a prefix grant request, we always deny the permission grant as
prefix grant may allow apps to give access to all files.

Bug: 159995598
Bug: 115619667
Test: Manual. Verified that chat app doesn't crash while attaching image
Test: atest ExternalStorageHostTest#testGrantUriPermission
Test: atest ExternalStorageHostTest#testGrantUriPermission29
Merged-In: Ib0021d3fd34294bb7497c8827e7ee99d4ac64d73
Change-Id: Ib0021d3fd34294bb7497c8827e7ee99d4ac64d73
(cherry picked from commit 8bb104ab39e94a015207555a49d496954e4356f0)
diff --git a/src/com/android/providers/media/ b/src/com/android/providers/media/
index 0be8891..c7598db 100644
--- a/src/com/android/providers/media/
+++ b/src/com/android/providers/media/
@@ -2149,10 +2149,13 @@
             final int type;
+            final boolean forWrite;
             if ((modeFlags & Intent.FLAG_GRANT_WRITE_URI_PERMISSION) != 0) {
                 type = TYPE_UPDATE;
+                forWrite = true;
             } else {
                 type = TYPE_QUERY;
+                forWrite = false;
             final SQLiteQueryBuilder qb = getQueryBuilder(type, table, uri, Bundle.EMPTY, null);
@@ -2162,6 +2165,24 @@
                     return PackageManager.PERMISSION_GRANTED;
+            try {
+                if (ContentUris.parseId(uri) != -1) {
+                    return PackageManager.PERMISSION_DENIED;
+                }
+            } catch (NumberFormatException ignored) { }
+            // If the uri is a valid content uri and doesn't have a valid ID at the end of the uri,
+            // (i.e., uri is uri of the table not of the item/row), and app doesn't request prefix
+            // grant, we are willing to grant this uri permission since this doesn't grant them any
+            // extra access. This grant will only grant permissions on given uri, it will not grant
+            // access to db rows of the corresponding table.
+            if ((modeFlags & Intent.FLAG_GRANT_PREFIX_URI_PERMISSION) == 0) {
+                return PackageManager.PERMISSION_GRANTED;
+            }
+            // For prefix grant on the uri with content uri without id, we don't allow apps to
+            // grant access as they might end up granting access to all files.
         } finally {