Insert database row for apps bypassing scoped storage
Previously, for apps that bypassed scoped storage restrictions, scanFile
was used to insert a new database row for files created through file
path. ScanFile was called on FUSE RELEASE op which is a non-blocking
call. This can introduce some race conditions(Refer b/149989434). Now,
instead of calling scanFile, we insert a new database row on FUSE create.
Inserting a database row for files created through filePath but not
deleting the database row on delete might break some app functionality.
Keeping the insert code commented until we start deleting the database
row on FUSE unlink.
Test: atest FuseDaemonHostTest
Bug: 149989434
Change-Id: I9e50bb3aa69c5caf8975153403783c2483982068
diff --git a/src/com/android/providers/media/MediaProvider.java b/src/com/android/providers/media/MediaProvider.java
index 40325cb..b90329b 100644
--- a/src/com/android/providers/media/MediaProvider.java
+++ b/src/com/android/providers/media/MediaProvider.java
@@ -6058,6 +6058,21 @@
return false;
}
+ private Uri insertFileForFuse(@NonNull String path, @NonNull Uri uri, @NonNull String mimeType,
+ boolean useData) {
+ ContentValues values = new ContentValues();
+ values.put(FileColumns.OWNER_PACKAGE_NAME, getCallingPackageOrSelf());
+ values.put(MediaColumns.MIME_TYPE, mimeType);
+
+ if (useData) {
+ values.put(FileColumns.DATA, getAbsoluteSanitizedPath(path));
+ } else {
+ values.put(FileColumns.RELATIVE_PATH, extractRelativePath(path));
+ values.put(FileColumns.DISPLAY_NAME, extractDisplayName(path));
+ }
+ return insert(uri, values, Bundle.EMPTY);
+ }
+
/**
* Enforces file creation restrictions (see return values) for the given file on behalf of the
* app with the given {@code uid}. If the file is is added to the shared storage, creates a
@@ -6091,32 +6106,29 @@
return OsConstants.ENOENT;
}
+ final String mimeType = MimeUtils.resolveMimeType(new File(path));
+
if (shouldBypassFuseRestrictions(/*forWrite*/ true, path)) {
+ // TODO(b/145737191) Legacy apps don't expect FuseDaemon to update database.
+ // Inserting/deleting the database entry might break app functionality.
+ // Ignore insert errors for apps that bypass scoped storage restriction.
+ // insertFileForFuse(path, Files.getContentUriForPath(path), mimeType,
+ // /*useData*/ true);
return 0;
}
+
// Legacy apps that made is this far don't have the right storage permission and hence
// are not allowed to access anything other than their external app directory
if (isCallingPackageRequestingLegacy()) {
return OsConstants.EPERM;
}
- final String mimeType = MimeUtils.resolveMimeType(new File(path));
final Uri contentUri = getContentUriForFile(path, mimeType);
if (fileExists(path, contentUri)) {
return OsConstants.EEXIST;
}
- final String displayName = extractDisplayName(path);
- final String callingPackageName = getCallingPackageOrSelf();
- final String relativePath = extractRelativePath(path);
-
- ContentValues values = new ContentValues();
- values.put(FileColumns.RELATIVE_PATH, relativePath);
- values.put(FileColumns.DISPLAY_NAME, displayName);
- values.put(FileColumns.OWNER_PACKAGE_NAME, callingPackageName);
- values.put(MediaColumns.MIME_TYPE, mimeType);
-
- final Uri item = insert(contentUri, values);
+ final Uri item = insertFileForFuse(path, contentUri, mimeType, /*useData*/ false);
if (item == null) {
return OsConstants.EPERM;
}