Merge "Return to modifying raw /mnt/media_rw paths." into pi-dev
am: f7d3e028ae
Change-Id: I61692ebdc49233923863ce773bb42a07498551b0
This commit is contained in:
@@ -312,7 +312,7 @@ public class VolumeInfo implements Parcelable {
|
|||||||
* {@link android.Manifest.permission#WRITE_MEDIA_STORAGE}.
|
* {@link android.Manifest.permission#WRITE_MEDIA_STORAGE}.
|
||||||
*/
|
*/
|
||||||
public File getInternalPathForUser(int userId) {
|
public File getInternalPathForUser(int userId) {
|
||||||
if (type == TYPE_PUBLIC && !isVisible()) {
|
if (type == TYPE_PUBLIC) {
|
||||||
// TODO: plumb through cleaner path from vold
|
// TODO: plumb through cleaner path from vold
|
||||||
return new File(path.replace("/storage/", "/mnt/media_rw/"));
|
return new File(path.replace("/storage/", "/mnt/media_rw/"));
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
@@ -85,6 +85,14 @@ public abstract class FileSystemProvider extends DocumentsProvider {
|
|||||||
|
|
||||||
protected abstract Uri buildNotificationUri(String docId);
|
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
|
@Override
|
||||||
public boolean onCreate() {
|
public boolean onCreate() {
|
||||||
throw new UnsupportedOperationException(
|
throw new UnsupportedOperationException(
|
||||||
@@ -185,6 +193,7 @@ public abstract class FileSystemProvider extends DocumentsProvider {
|
|||||||
throw new IllegalStateException("Failed to mkdir " + file);
|
throw new IllegalStateException("Failed to mkdir " + file);
|
||||||
}
|
}
|
||||||
childId = getDocIdForFile(file);
|
childId = getDocIdForFile(file);
|
||||||
|
onDocIdChanged(childId);
|
||||||
addFolderToMediaStore(getFileForDocId(childId, true));
|
addFolderToMediaStore(getFileForDocId(childId, true));
|
||||||
} else {
|
} else {
|
||||||
try {
|
try {
|
||||||
@@ -192,6 +201,7 @@ public abstract class FileSystemProvider extends DocumentsProvider {
|
|||||||
throw new IllegalStateException("Failed to touch " + file);
|
throw new IllegalStateException("Failed to touch " + file);
|
||||||
}
|
}
|
||||||
childId = getDocIdForFile(file);
|
childId = getDocIdForFile(file);
|
||||||
|
onDocIdChanged(childId);
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
throw new IllegalStateException("Failed to touch " + file + ": " + 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 before = getFileForDocId(docId);
|
||||||
final File after = FileUtils.buildUniqueFile(before.getParentFile(), displayName);
|
final File after = FileUtils.buildUniqueFile(before.getParentFile(), displayName);
|
||||||
final File visibleFileBefore = getFileForDocId(docId, true);
|
|
||||||
if (!before.renameTo(after)) {
|
if (!before.renameTo(after)) {
|
||||||
throw new IllegalStateException("Failed to rename to " + after);
|
throw new IllegalStateException("Failed to rename to " + after);
|
||||||
}
|
}
|
||||||
|
|
||||||
final String afterDocId = getDocIdForFile(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)) {
|
if (!TextUtils.equals(docId, afterDocId)) {
|
||||||
scanFile(after);
|
scanFile(afterVisibleFile);
|
||||||
return afterDocId;
|
return afterDocId;
|
||||||
} else {
|
} else {
|
||||||
return null;
|
return null;
|
||||||
@@ -259,6 +273,8 @@ public abstract class FileSystemProvider extends DocumentsProvider {
|
|||||||
}
|
}
|
||||||
|
|
||||||
final String docId = getDocIdForFile(after);
|
final String docId = getDocIdForFile(after);
|
||||||
|
onDocIdChanged(sourceDocumentId);
|
||||||
|
onDocIdChanged(docId);
|
||||||
moveInMediaStore(visibleFileBefore, getFileForDocId(docId, true));
|
moveInMediaStore(visibleFileBefore, getFileForDocId(docId, true));
|
||||||
|
|
||||||
return docId;
|
return docId;
|
||||||
@@ -308,6 +324,7 @@ public abstract class FileSystemProvider extends DocumentsProvider {
|
|||||||
throw new IllegalStateException("Failed to delete " + file);
|
throw new IllegalStateException("Failed to delete " + file);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
onDocIdChanged(docId);
|
||||||
removeFromMediaStore(visibleFile, isDirectory);
|
removeFromMediaStore(visibleFile, isDirectory);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -418,7 +435,10 @@ public abstract class FileSystemProvider extends DocumentsProvider {
|
|||||||
try {
|
try {
|
||||||
// When finished writing, kick off media scanner
|
// When finished writing, kick off media scanner
|
||||||
return ParcelFileDescriptor.open(
|
return ParcelFileDescriptor.open(
|
||||||
file, pfdMode, mHandler, (IOException e) -> scanFile(visibleFile));
|
file, pfdMode, mHandler, (IOException e) -> {
|
||||||
|
onDocIdChanged(documentId);
|
||||||
|
scanFile(visibleFile);
|
||||||
|
});
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
throw new FileNotFoundException("Failed to open for writing: " + e);
|
throw new FileNotFoundException("Failed to open for writing: " + e);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -38,6 +38,9 @@ import android.provider.DocumentsContract.Document;
|
|||||||
import android.provider.DocumentsContract.Path;
|
import android.provider.DocumentsContract.Path;
|
||||||
import android.provider.DocumentsContract.Root;
|
import android.provider.DocumentsContract.Root;
|
||||||
import android.provider.Settings;
|
import android.provider.Settings;
|
||||||
|
import android.system.ErrnoException;
|
||||||
|
import android.system.Os;
|
||||||
|
import android.system.OsConstants;
|
||||||
import android.text.TextUtils;
|
import android.text.TextUtils;
|
||||||
import android.util.ArrayMap;
|
import android.util.ArrayMap;
|
||||||
import android.util.DebugUtils;
|
import android.util.DebugUtils;
|
||||||
@@ -360,14 +363,19 @@ public class ExternalStorageProvider extends FileSystemProvider {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected File getFileForDocId(String docId, boolean visible) throws FileNotFoundException {
|
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);
|
RootInfo root = getRootFromDocId(docId);
|
||||||
return buildFile(root, docId, visible);
|
return buildFile(root, docId, visible, mustExist);
|
||||||
}
|
}
|
||||||
|
|
||||||
private Pair<RootInfo, File> resolveDocId(String docId, boolean visible)
|
private Pair<RootInfo, File> resolveDocId(String docId, boolean visible)
|
||||||
throws FileNotFoundException {
|
throws FileNotFoundException {
|
||||||
RootInfo root = getRootFromDocId(docId);
|
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 {
|
private RootInfo getRootFromDocId(String docId) throws FileNotFoundException {
|
||||||
@@ -385,7 +393,7 @@ public class ExternalStorageProvider extends FileSystemProvider {
|
|||||||
return root;
|
return root;
|
||||||
}
|
}
|
||||||
|
|
||||||
private File buildFile(RootInfo root, String docId, boolean visible)
|
private File buildFile(RootInfo root, String docId, boolean visible, boolean mustExist)
|
||||||
throws FileNotFoundException {
|
throws FileNotFoundException {
|
||||||
final int splitIndex = docId.indexOf(':', 1);
|
final int splitIndex = docId.indexOf(':', 1);
|
||||||
final String path = docId.substring(splitIndex + 1);
|
final String path = docId.substring(splitIndex + 1);
|
||||||
@@ -398,7 +406,7 @@ public class ExternalStorageProvider extends FileSystemProvider {
|
|||||||
target.mkdirs();
|
target.mkdirs();
|
||||||
}
|
}
|
||||||
target = new File(target, path);
|
target = new File(target, path);
|
||||||
if (!target.exists()) {
|
if (mustExist && !target.exists()) {
|
||||||
throw new FileNotFoundException("Missing file for " + docId + " at " + target);
|
throw new FileNotFoundException("Missing file for " + docId + " at " + target);
|
||||||
}
|
}
|
||||||
return target;
|
return target;
|
||||||
@@ -409,6 +417,19 @@ public class ExternalStorageProvider extends FileSystemProvider {
|
|||||||
return DocumentsContract.buildChildDocumentsUri(AUTHORITY, docId);
|
return DocumentsContract.buildChildDocumentsUri(AUTHORITY, docId);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@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
|
@Override
|
||||||
public Cursor queryRoots(String[] projection) throws FileNotFoundException {
|
public Cursor queryRoots(String[] projection) throws FileNotFoundException {
|
||||||
final MatrixCursor result = new MatrixCursor(resolveRootProjection(projection));
|
final MatrixCursor result = new MatrixCursor(resolveRootProjection(projection));
|
||||||
|
|||||||
Reference in New Issue
Block a user