summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--core/java/android/os/storage/VolumeInfo.java2
-rw-r--r--core/java/com/android/internal/content/FileSystemProvider.java28
-rw-r--r--packages/ExternalStorageProvider/src/com/android/externalstorage/ExternalStorageProvider.java29
3 files changed, 50 insertions, 9 deletions
diff --git a/core/java/android/os/storage/VolumeInfo.java b/core/java/android/os/storage/VolumeInfo.java
index 9e3e386eedb2..5c99f6c87d7c 100644
--- a/core/java/android/os/storage/VolumeInfo.java
+++ b/core/java/android/os/storage/VolumeInfo.java
@@ -312,7 +312,7 @@ public class VolumeInfo implements Parcelable {
* {@link android.Manifest.permission#WRITE_MEDIA_STORAGE}.
*/
public File getInternalPathForUser(int userId) {
- if (type == TYPE_PUBLIC && !isVisible()) {
+ if (type == TYPE_PUBLIC) {
// TODO: plumb through cleaner path from vold
return new File(path.replace("/storage/", "/mnt/media_rw/"));
} else {
diff --git a/core/java/com/android/internal/content/FileSystemProvider.java b/core/java/com/android/internal/content/FileSystemProvider.java
index a075705c2e40..b591163e8728 100644
--- a/core/java/com/android/internal/content/FileSystemProvider.java
+++ b/core/java/com/android/internal/content/FileSystemProvider.java
@@ -85,6 +85,14 @@ public abstract class FileSystemProvider extends DocumentsProvider {
protected abstract Uri buildNotificationUri(String docId);
+ /**
+ * Callback indicating that the given document has been modified. This gives
+ * the provider a hook to invalidate cached data, such as {@code sdcardfs}.
+ */
+ protected void onDocIdChanged(String docId) {
+ // Default is no-op
+ }
+
@Override
public boolean onCreate() {
throw new UnsupportedOperationException(
@@ -185,6 +193,7 @@ public abstract class FileSystemProvider extends DocumentsProvider {
throw new IllegalStateException("Failed to mkdir " + file);
}
childId = getDocIdForFile(file);
+ onDocIdChanged(childId);
addFolderToMediaStore(getFileForDocId(childId, true));
} else {
try {
@@ -192,6 +201,7 @@ public abstract class FileSystemProvider extends DocumentsProvider {
throw new IllegalStateException("Failed to touch " + file);
}
childId = getDocIdForFile(file);
+ onDocIdChanged(childId);
} catch (IOException e) {
throw new IllegalStateException("Failed to touch " + file + ": " + e);
}
@@ -227,16 +237,20 @@ public abstract class FileSystemProvider extends DocumentsProvider {
final File before = getFileForDocId(docId);
final File after = FileUtils.buildUniqueFile(before.getParentFile(), displayName);
- final File visibleFileBefore = getFileForDocId(docId, true);
if (!before.renameTo(after)) {
throw new IllegalStateException("Failed to rename to " + after);
}
final String afterDocId = getDocIdForFile(after);
- moveInMediaStore(visibleFileBefore, getFileForDocId(afterDocId, true));
+ onDocIdChanged(docId);
+ onDocIdChanged(afterDocId);
+
+ final File beforeVisibleFile = getFileForDocId(docId, true);
+ final File afterVisibleFile = getFileForDocId(afterDocId, true);
+ moveInMediaStore(beforeVisibleFile, afterVisibleFile);
if (!TextUtils.equals(docId, afterDocId)) {
- scanFile(after);
+ scanFile(afterVisibleFile);
return afterDocId;
} else {
return null;
@@ -259,6 +273,8 @@ public abstract class FileSystemProvider extends DocumentsProvider {
}
final String docId = getDocIdForFile(after);
+ onDocIdChanged(sourceDocumentId);
+ onDocIdChanged(docId);
moveInMediaStore(visibleFileBefore, getFileForDocId(docId, true));
return docId;
@@ -308,6 +324,7 @@ public abstract class FileSystemProvider extends DocumentsProvider {
throw new IllegalStateException("Failed to delete " + file);
}
+ onDocIdChanged(docId);
removeFromMediaStore(visibleFile, isDirectory);
}
@@ -418,7 +435,10 @@ public abstract class FileSystemProvider extends DocumentsProvider {
try {
// When finished writing, kick off media scanner
return ParcelFileDescriptor.open(
- file, pfdMode, mHandler, (IOException e) -> scanFile(visibleFile));
+ file, pfdMode, mHandler, (IOException e) -> {
+ onDocIdChanged(documentId);
+ scanFile(visibleFile);
+ });
} catch (IOException e) {
throw new FileNotFoundException("Failed to open for writing: " + e);
}
diff --git a/packages/ExternalStorageProvider/src/com/android/externalstorage/ExternalStorageProvider.java b/packages/ExternalStorageProvider/src/com/android/externalstorage/ExternalStorageProvider.java
index 2a82fc9b28df..0a720a5b234e 100644
--- a/packages/ExternalStorageProvider/src/com/android/externalstorage/ExternalStorageProvider.java
+++ b/packages/ExternalStorageProvider/src/com/android/externalstorage/ExternalStorageProvider.java
@@ -38,6 +38,9 @@ import android.provider.DocumentsContract.Document;
import android.provider.DocumentsContract.Path;
import android.provider.DocumentsContract.Root;
import android.provider.Settings;
+import android.system.ErrnoException;
+import android.system.Os;
+import android.system.OsConstants;
import android.text.TextUtils;
import android.util.ArrayMap;
import android.util.DebugUtils;
@@ -360,14 +363,19 @@ public class ExternalStorageProvider extends FileSystemProvider {
@Override
protected File getFileForDocId(String docId, boolean visible) throws FileNotFoundException {
+ return getFileForDocId(docId, visible, true);
+ }
+
+ private File getFileForDocId(String docId, boolean visible, boolean mustExist)
+ throws FileNotFoundException {
RootInfo root = getRootFromDocId(docId);
- return buildFile(root, docId, visible);
+ return buildFile(root, docId, visible, mustExist);
}
private Pair<RootInfo, File> resolveDocId(String docId, boolean visible)
throws FileNotFoundException {
RootInfo root = getRootFromDocId(docId);
- return Pair.create(root, buildFile(root, docId, visible));
+ return Pair.create(root, buildFile(root, docId, visible, true));
}
private RootInfo getRootFromDocId(String docId) throws FileNotFoundException {
@@ -385,7 +393,7 @@ public class ExternalStorageProvider extends FileSystemProvider {
return root;
}
- private File buildFile(RootInfo root, String docId, boolean visible)
+ private File buildFile(RootInfo root, String docId, boolean visible, boolean mustExist)
throws FileNotFoundException {
final int splitIndex = docId.indexOf(':', 1);
final String path = docId.substring(splitIndex + 1);
@@ -398,7 +406,7 @@ public class ExternalStorageProvider extends FileSystemProvider {
target.mkdirs();
}
target = new File(target, path);
- if (!target.exists()) {
+ if (mustExist && !target.exists()) {
throw new FileNotFoundException("Missing file for " + docId + " at " + target);
}
return target;
@@ -410,6 +418,19 @@ public class ExternalStorageProvider extends FileSystemProvider {
}
@Override
+ protected void onDocIdChanged(String docId) {
+ try {
+ // Touch the visible path to ensure that any sdcardfs caches have
+ // been updated to reflect underlying changes on disk.
+ final File visiblePath = getFileForDocId(docId, true, false);
+ if (visiblePath != null) {
+ Os.access(visiblePath.getAbsolutePath(), OsConstants.F_OK);
+ }
+ } catch (FileNotFoundException | ErrnoException ignored) {
+ }
+ }
+
+ @Override
public Cursor queryRoots(String[] projection) throws FileNotFoundException {
final MatrixCursor result = new MatrixCursor(resolveRootProjection(projection));
synchronized (mRootsLock) {