Allow providers block folders in ACTION_OPEN_DOCUMENT_TREE
DocumentsContract - Add new flag FLAG_DIR_BLOCKS_TREE in Document ExternalStorageProvider - Add flag into DocumentInfo for blocking folder Change-Id: Ib557fe99d330788a3bd968bffd43b6658761514f Bug: 32370759 Test: atest DocumentsTest
This commit is contained in:
@@ -38234,6 +38234,7 @@ package android.provider {
|
||||
field public static final String COLUMN_MIME_TYPE = "mime_type";
|
||||
field public static final String COLUMN_SIZE = "_size";
|
||||
field public static final String COLUMN_SUMMARY = "summary";
|
||||
field public static final int FLAG_DIR_BLOCKS_TREE = 32768; // 0x8000
|
||||
field public static final int FLAG_DIR_PREFERS_GRID = 16; // 0x10
|
||||
field public static final int FLAG_DIR_PREFERS_LAST_MODIFIED = 32; // 0x20
|
||||
field public static final int FLAG_DIR_SUPPORTS_CREATE = 8; // 0x8
|
||||
|
||||
@@ -363,15 +363,22 @@ public final class DocumentsContract {
|
||||
* <p>
|
||||
* Type: INTEGER (int)
|
||||
*
|
||||
* @see #FLAG_SUPPORTS_WRITE
|
||||
* @see #FLAG_SUPPORTS_DELETE
|
||||
* @see #FLAG_SUPPORTS_THUMBNAIL
|
||||
* @see #FLAG_DIR_BLOCKS_TREE
|
||||
* @see #FLAG_DIR_PREFERS_GRID
|
||||
* @see #FLAG_DIR_PREFERS_LAST_MODIFIED
|
||||
* @see #FLAG_VIRTUAL_DOCUMENT
|
||||
* @see #FLAG_DIR_SUPPORTS_CREATE
|
||||
* @see #FLAG_PARTIAL
|
||||
* @see #FLAG_SUPPORTS_COPY
|
||||
* @see #FLAG_SUPPORTS_DELETE
|
||||
* @see #FLAG_SUPPORTS_METADATA
|
||||
* @see #FLAG_SUPPORTS_MOVE
|
||||
* @see #FLAG_SUPPORTS_REMOVE
|
||||
* @see #FLAG_SUPPORTS_RENAME
|
||||
* @see #FLAG_SUPPORTS_SETTINGS
|
||||
* @see #FLAG_SUPPORTS_THUMBNAIL
|
||||
* @see #FLAG_SUPPORTS_WRITE
|
||||
* @see #FLAG_VIRTUAL_DOCUMENT
|
||||
* @see #FLAG_WEB_LINKABLE
|
||||
*/
|
||||
public static final String COLUMN_FLAGS = "flags";
|
||||
|
||||
@@ -542,6 +549,23 @@ public final class DocumentsContract {
|
||||
* @see DocumentsContract#getDocumentMetadata(ContentInterface, Uri)
|
||||
*/
|
||||
public static final int FLAG_SUPPORTS_METADATA = 1 << 14;
|
||||
|
||||
/**
|
||||
* Flag indicating that a document is a directory that wants to block itself
|
||||
* from being selected when the user launches an {@link Intent#ACTION_OPEN_DOCUMENT_TREE}
|
||||
* intent. Only valid when {@link #COLUMN_MIME_TYPE} is {@link #MIME_TYPE_DIR}.
|
||||
* <p>
|
||||
* Note that this flag <em>only</em> applies to the single directory to which it is
|
||||
* applied. It does <em>not</em> block the user from selecting either a parent or
|
||||
* child directory during an {@link Intent#ACTION_OPEN_DOCUMENT_TREE} request.
|
||||
* In particular, the only way to guarantee that a specific directory can never
|
||||
* be granted via an {@link Intent#ACTION_OPEN_DOCUMENT_TREE} request is to ensure
|
||||
* that both it and <em>all of its parent directories</em> have set this flag.
|
||||
*
|
||||
* @see Intent#ACTION_OPEN_DOCUMENT_TREE
|
||||
* @see #COLUMN_FLAGS
|
||||
*/
|
||||
public static final int FLAG_DIR_BLOCKS_TREE = 1 << 15;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -17,6 +17,7 @@
|
||||
package com.android.internal.content;
|
||||
|
||||
import android.annotation.CallSuper;
|
||||
import android.annotation.NonNull;
|
||||
import android.annotation.Nullable;
|
||||
import android.content.ContentResolver;
|
||||
import android.content.Intent;
|
||||
@@ -552,6 +553,11 @@ public abstract class FileSystemProvider extends DocumentsProvider {
|
||||
flags |= Document.FLAG_SUPPORTS_DELETE;
|
||||
flags |= Document.FLAG_SUPPORTS_RENAME;
|
||||
flags |= Document.FLAG_SUPPORTS_MOVE;
|
||||
|
||||
if (shouldBlockFromTree(docId)) {
|
||||
flags |= Document.FLAG_DIR_BLOCKS_TREE;
|
||||
}
|
||||
|
||||
} else {
|
||||
flags |= Document.FLAG_SUPPORTS_WRITE;
|
||||
flags |= Document.FLAG_SUPPORTS_DELETE;
|
||||
@@ -592,6 +598,10 @@ public abstract class FileSystemProvider extends DocumentsProvider {
|
||||
return row;
|
||||
}
|
||||
|
||||
protected boolean shouldBlockFromTree(@NonNull String docId) {
|
||||
return false;
|
||||
}
|
||||
|
||||
protected boolean typeSupportsMetadata(String mimeType) {
|
||||
return MetadataReader.isSupportedMimeType(mimeType)
|
||||
|| Document.MIME_TYPE_DIR.equals(mimeType);
|
||||
|
||||
@@ -16,6 +16,7 @@
|
||||
|
||||
package com.android.externalstorage;
|
||||
|
||||
import android.annotation.NonNull;
|
||||
import android.annotation.Nullable;
|
||||
import android.app.usage.StorageStatsManager;
|
||||
import android.content.ContentResolver;
|
||||
@@ -298,6 +299,53 @@ public class ExternalStorageProvider extends FileSystemProvider {
|
||||
return projection != null ? projection : DEFAULT_ROOT_PROJECTION;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check that the directory is the root of storage or blocked file from tree.
|
||||
*
|
||||
* @param docId the docId of the directory to be checked
|
||||
* @return true, should be blocked from tree. Otherwise, false.
|
||||
*/
|
||||
@Override
|
||||
protected boolean shouldBlockFromTree(@NonNull String docId) {
|
||||
try {
|
||||
final File dir = getFileForDocId(docId, true /* visible */).getCanonicalFile();
|
||||
if (!dir.isDirectory()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
final String path = dir.getAbsolutePath();
|
||||
|
||||
// Block Download folder from tree
|
||||
if (MediaStore.Downloads.isDownloadDir(path)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
final ArrayMap<String, RootInfo> roots = new ArrayMap<>();
|
||||
|
||||
synchronized (mRootsLock) {
|
||||
roots.putAll(mRoots);
|
||||
}
|
||||
|
||||
// block root of storage
|
||||
for (int i = 0; i < roots.size(); i++) {
|
||||
RootInfo rootInfo = roots.valueAt(i);
|
||||
// skip home root
|
||||
if (TextUtils.equals(rootInfo.rootId, ROOT_ID_HOME)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// block the root of storage
|
||||
if (TextUtils.equals(path, rootInfo.visiblePath.getAbsolutePath())) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
} catch (IOException e) {
|
||||
throw new IllegalArgumentException(
|
||||
"Failed to determine if " + docId + " should block from tree " + ": " + e);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String getDocIdForFile(File file) throws FileNotFoundException {
|
||||
return getDocIdForFileMaybeCreate(file, false);
|
||||
|
||||
Reference in New Issue
Block a user