diff options
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) { |