Loading api/current.txt +1 −0 Original line number Diff line number Diff line Loading @@ -38280,6 +38280,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 core/java/android/provider/DocumentsContract.java +28 −4 Original line number Diff line number Diff line Loading @@ -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"; Loading Loading @@ -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; } /** Loading core/java/com/android/internal/content/FileSystemProvider.java +10 −0 Original line number Diff line number Diff line Loading @@ -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; Loading Loading @@ -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; Loading Loading @@ -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); Loading packages/ExternalStorageProvider/src/com/android/externalstorage/ExternalStorageProvider.java +48 −0 Original line number Diff line number Diff line Loading @@ -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; Loading Loading @@ -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); Loading Loading
api/current.txt +1 −0 Original line number Diff line number Diff line Loading @@ -38280,6 +38280,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
core/java/android/provider/DocumentsContract.java +28 −4 Original line number Diff line number Diff line Loading @@ -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"; Loading Loading @@ -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; } /** Loading
core/java/com/android/internal/content/FileSystemProvider.java +10 −0 Original line number Diff line number Diff line Loading @@ -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; Loading Loading @@ -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; Loading Loading @@ -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); Loading
packages/ExternalStorageProvider/src/com/android/externalstorage/ExternalStorageProvider.java +48 −0 Original line number Diff line number Diff line Loading @@ -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; Loading Loading @@ -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); Loading