diff options
author | Jeff Sharkey <jsharkey@android.com> | 2013-08-31 15:02:20 -0700 |
---|---|---|
committer | Jeff Sharkey <jsharkey@android.com> | 2013-08-31 16:58:28 -0700 |
commit | ae9b51bfa313c51a31af30875a71255d7b6d2e61 (patch) | |
tree | 97179597056ef53aafbf952b22bf332954de0649 /packages/ExternalStorageProvider/src/com/android | |
parent | aeb16e2435f9975b9fa1fc4b747796647a21292e (diff) | |
download | frameworks_base-ae9b51bfa313c51a31af30875a71255d7b6d2e61.zip frameworks_base-ae9b51bfa313c51a31af30875a71255d7b6d2e61.tar.gz frameworks_base-ae9b51bfa313c51a31af30875a71255d7b6d2e61.tar.bz2 |
Refactoring of DocumentsContract.
Combines related columns and constants onto the same class so they
are easier to discover. Move back to surfacing roots with columns
so they are consistent with documents.
Advanced roots are represented with a flag instead of distinct
types. Flags to indicate supporting of well-known media types,
instead of arbitrary an MIME filter. Reintroduce well-formed rootId
to support recents.
Always use the expanded version of "documents" in constants, methods,
and argument names.
Refactor DocumentProvider method names to clearly distinguish if
a single item or multiple could be returned, and of which type. Add
documentation to clearly define which methods have already been
overridden.
Bug: 10567506, 10567557
Change-Id: I981f26ab82f2b520a19aa1ce66f659de50d7fac0
Diffstat (limited to 'packages/ExternalStorageProvider/src/com/android')
-rw-r--r-- | packages/ExternalStorageProvider/src/com/android/externalstorage/ExternalStorageProvider.java | 167 |
1 files changed, 97 insertions, 70 deletions
diff --git a/packages/ExternalStorageProvider/src/com/android/externalstorage/ExternalStorageProvider.java b/packages/ExternalStorageProvider/src/com/android/externalstorage/ExternalStorageProvider.java index 583ecc9..de8c29a 100644 --- a/packages/ExternalStorageProvider/src/com/android/externalstorage/ExternalStorageProvider.java +++ b/packages/ExternalStorageProvider/src/com/android/externalstorage/ExternalStorageProvider.java @@ -26,9 +26,8 @@ import android.media.ExifInterface; import android.os.CancellationSignal; import android.os.Environment; import android.os.ParcelFileDescriptor; -import android.provider.DocumentsContract.DocumentColumns; -import android.provider.DocumentsContract.DocumentRoot; -import android.provider.DocumentsContract.Documents; +import android.provider.DocumentsContract.Document; +import android.provider.DocumentsContract.Root; import android.provider.DocumentsProvider; import android.webkit.MimeTypeMap; @@ -41,7 +40,6 @@ import java.io.IOException; import java.util.ArrayList; import java.util.HashMap; import java.util.LinkedList; -import java.util.List; import java.util.Map; public class ExternalStorageProvider extends DocumentsProvider { @@ -49,36 +47,54 @@ public class ExternalStorageProvider extends DocumentsProvider { // docId format: root:path/to/file - private static final String[] SUPPORTED_COLUMNS = new String[] { - DocumentColumns.DOC_ID, DocumentColumns.DISPLAY_NAME, DocumentColumns.SIZE, - DocumentColumns.MIME_TYPE, DocumentColumns.LAST_MODIFIED, DocumentColumns.FLAGS + private static final String[] DEFAULT_ROOT_PROJECTION = new String[] { + Root.COLUMN_ROOT_ID, Root.COLUMN_ROOT_TYPE, Root.COLUMN_FLAGS, Root.COLUMN_ICON, + Root.COLUMN_TITLE, Root.COLUMN_SUMMARY, Root.COLUMN_DOCUMENT_ID, + Root.COLUMN_AVAILABLE_BYTES, }; - private ArrayList<DocumentRoot> mRoots; - private HashMap<String, DocumentRoot> mTagToRoot; - private HashMap<String, File> mTagToPath; + private static final String[] DEFAULT_DOCUMENT_PROJECTION = new String[] { + Document.COLUMN_DOCUMENT_ID, Document.COLUMN_MIME_TYPE, Document.COLUMN_DISPLAY_NAME, + Document.COLUMN_LAST_MODIFIED, Document.COLUMN_FLAGS, Document.COLUMN_SIZE, + }; + + private static class RootInfo { + public String rootId; + public int rootType; + public int flags; + public int icon; + public String title; + public String docId; + } + + private ArrayList<RootInfo> mRoots; + private HashMap<String, RootInfo> mIdToRoot; + private HashMap<String, File> mIdToPath; @Override public boolean onCreate() { mRoots = Lists.newArrayList(); - mTagToRoot = Maps.newHashMap(); - mTagToPath = Maps.newHashMap(); + mIdToRoot = Maps.newHashMap(); + mIdToPath = Maps.newHashMap(); // TODO: support multiple storage devices try { - final String tag = "primary"; + final String rootId = "primary"; final File path = Environment.getExternalStorageDirectory(); - mTagToPath.put(tag, path); - - final DocumentRoot root = new DocumentRoot(); - root.docId = getDocIdForFile(path); - root.rootType = DocumentRoot.ROOT_TYPE_DEVICE_ADVANCED; - root.title = getContext().getString(R.string.root_internal_storage); + mIdToPath.put(rootId, path); + + final RootInfo root = new RootInfo(); + root.rootId = "primary"; + root.rootType = Root.ROOT_TYPE_DEVICE; + root.flags = Root.FLAG_SUPPORTS_CREATE | Root.FLAG_LOCAL_ONLY | Root.FLAG_ADVANCED + | Root.FLAG_PROVIDES_AUDIO | Root.FLAG_PROVIDES_VIDEO + | Root.FLAG_PROVIDES_IMAGES; root.icon = R.drawable.ic_pdf; - root.flags = DocumentRoot.FLAG_LOCAL_ONLY; + root.title = getContext().getString(R.string.root_internal_storage); + root.docId = getDocIdForFile(path); mRoots.add(root); - mTagToRoot.put(tag, root); + mIdToRoot.put(rootId, root); } catch (FileNotFoundException e) { throw new IllegalStateException(e); } @@ -86,12 +102,20 @@ public class ExternalStorageProvider extends DocumentsProvider { return true; } + private static String[] resolveRootProjection(String[] projection) { + return projection != null ? projection : DEFAULT_ROOT_PROJECTION; + } + + private static String[] resolveDocumentProjection(String[] projection) { + return projection != null ? projection : DEFAULT_DOCUMENT_PROJECTION; + } + private String getDocIdForFile(File file) throws FileNotFoundException { String path = file.getAbsolutePath(); // Find the most-specific root path Map.Entry<String, File> mostSpecific = null; - for (Map.Entry<String, File> root : mTagToPath.entrySet()) { + for (Map.Entry<String, File> root : mIdToPath.entrySet()) { final String rootPath = root.getValue().getPath(); if (path.startsWith(rootPath) && (mostSpecific == null || rootPath.length() > mostSpecific.getValue().getPath().length())) { @@ -121,7 +145,7 @@ public class ExternalStorageProvider extends DocumentsProvider { final String tag = docId.substring(0, splitIndex); final String path = docId.substring(splitIndex + 1); - File target = mTagToPath.get(tag); + File target = mIdToPath.get(tag); if (target == null) { throw new FileNotFoundException("No root for " + tag); } @@ -143,41 +167,48 @@ public class ExternalStorageProvider extends DocumentsProvider { int flags = 0; if (file.isDirectory()) { - flags |= Documents.FLAG_SUPPORTS_SEARCH; + flags |= Document.FLAG_DIR_SUPPORTS_SEARCH; } if (file.isDirectory() && file.canWrite()) { - flags |= Documents.FLAG_SUPPORTS_CREATE; + flags |= Document.FLAG_DIR_SUPPORTS_CREATE; } if (file.canWrite()) { - flags |= Documents.FLAG_SUPPORTS_WRITE; - flags |= Documents.FLAG_SUPPORTS_RENAME; - flags |= Documents.FLAG_SUPPORTS_DELETE; + flags |= Document.FLAG_SUPPORTS_WRITE; + flags |= Document.FLAG_SUPPORTS_DELETE; } final String displayName = file.getName(); final String mimeType = getTypeForFile(file); if (mimeType.startsWith("image/")) { - flags |= Documents.FLAG_SUPPORTS_THUMBNAIL; + flags |= Document.FLAG_SUPPORTS_THUMBNAIL; } final RowBuilder row = result.newRow(); - row.offer(DocumentColumns.DOC_ID, docId); - row.offer(DocumentColumns.DISPLAY_NAME, displayName); - row.offer(DocumentColumns.SIZE, file.length()); - row.offer(DocumentColumns.MIME_TYPE, mimeType); - row.offer(DocumentColumns.LAST_MODIFIED, file.lastModified()); - row.offer(DocumentColumns.FLAGS, flags); + row.offer(Document.COLUMN_DOCUMENT_ID, docId); + row.offer(Document.COLUMN_DISPLAY_NAME, displayName); + row.offer(Document.COLUMN_SIZE, file.length()); + row.offer(Document.COLUMN_MIME_TYPE, mimeType); + row.offer(Document.COLUMN_LAST_MODIFIED, file.lastModified()); + row.offer(Document.COLUMN_FLAGS, flags); } @Override - public List<DocumentRoot> getDocumentRoots() { - // Update free space - for (String tag : mTagToRoot.keySet()) { - final DocumentRoot root = mTagToRoot.get(tag); - final File path = mTagToPath.get(tag); - root.availableBytes = path.getFreeSpace(); + public Cursor queryRoots(String[] projection) throws FileNotFoundException { + final MatrixCursor result = new MatrixCursor(resolveRootProjection(projection)); + for (String rootId : mIdToPath.keySet()) { + final RootInfo root = mIdToRoot.get(rootId); + final File path = mIdToPath.get(rootId); + + final RowBuilder row = result.newRow(); + row.offer(Root.COLUMN_ROOT_ID, root.rootId); + row.offer(Root.COLUMN_ROOT_TYPE, root.rootType); + row.offer(Root.COLUMN_FLAGS, root.flags); + row.offer(Root.COLUMN_ICON, root.icon); + row.offer(Root.COLUMN_TITLE, root.title); + row.offer(Root.COLUMN_DOCUMENT_ID, root.docId); + row.offer(Root.COLUMN_AVAILABLE_BYTES, path.getFreeSpace()); } - return mRoots; + return result; } @Override @@ -187,7 +218,7 @@ public class ExternalStorageProvider extends DocumentsProvider { displayName = validateDisplayName(mimeType, displayName); final File file = new File(parent, displayName); - if (Documents.MIME_TYPE_DIR.equals(mimeType)) { + if (Document.MIME_TYPE_DIR.equals(mimeType)) { if (!file.mkdir()) { throw new IllegalStateException("Failed to mkdir " + file); } @@ -204,16 +235,6 @@ public class ExternalStorageProvider extends DocumentsProvider { } @Override - public void renameDocument(String docId, String displayName) throws FileNotFoundException { - final File file = getFileForDocId(docId); - final File newFile = new File(file.getParentFile(), displayName); - if (!file.renameTo(newFile)) { - throw new IllegalStateException("Failed to rename " + docId); - } - // TODO: update any outstanding grants - } - - @Override public void deleteDocument(String docId) throws FileNotFoundException { final File file = getFileForDocId(docId); if (!file.delete()) { @@ -222,16 +243,19 @@ public class ExternalStorageProvider extends DocumentsProvider { } @Override - public Cursor queryDocument(String docId) throws FileNotFoundException { - final MatrixCursor result = new MatrixCursor(SUPPORTED_COLUMNS); - includeFile(result, docId, null); + public Cursor queryDocument(String documentId, String[] projection) + throws FileNotFoundException { + final MatrixCursor result = new MatrixCursor(resolveDocumentProjection(projection)); + includeFile(result, documentId, null); return result; } @Override - public Cursor queryDocumentChildren(String docId) throws FileNotFoundException { - final MatrixCursor result = new MatrixCursor(SUPPORTED_COLUMNS); - final File parent = getFileForDocId(docId); + public Cursor queryChildDocuments( + String parentDocumentId, String[] projection, String sortOrder) + throws FileNotFoundException { + final MatrixCursor result = new MatrixCursor(resolveDocumentProjection(projection)); + final File parent = getFileForDocId(parentDocumentId); for (File file : parent.listFiles()) { includeFile(result, null, file); } @@ -239,9 +263,10 @@ public class ExternalStorageProvider extends DocumentsProvider { } @Override - public Cursor querySearch(String docId, String query) throws FileNotFoundException { - final MatrixCursor result = new MatrixCursor(SUPPORTED_COLUMNS); - final File parent = getFileForDocId(docId); + public Cursor querySearchDocuments(String parentDocumentId, String query, String[] projection) + throws FileNotFoundException { + final MatrixCursor result = new MatrixCursor(resolveDocumentProjection(projection)); + final File parent = getFileForDocId(parentDocumentId); final LinkedList<File> pending = new LinkedList<File>(); pending.add(parent); @@ -261,22 +286,24 @@ public class ExternalStorageProvider extends DocumentsProvider { } @Override - public String getType(String docId) throws FileNotFoundException { - final File file = getFileForDocId(docId); + public String getDocumentType(String documentId) throws FileNotFoundException { + final File file = getFileForDocId(documentId); return getTypeForFile(file); } @Override - public ParcelFileDescriptor openDocument(String docId, String mode, CancellationSignal signal) + public ParcelFileDescriptor openDocument( + String documentId, String mode, CancellationSignal signal) throws FileNotFoundException { - final File file = getFileForDocId(docId); + final File file = getFileForDocId(documentId); return ParcelFileDescriptor.open(file, ContentResolver.modeToMode(null, mode)); } @Override public AssetFileDescriptor openDocumentThumbnail( - String docId, Point sizeHint, CancellationSignal signal) throws FileNotFoundException { - final File file = getFileForDocId(docId); + String documentId, Point sizeHint, CancellationSignal signal) + throws FileNotFoundException { + final File file = getFileForDocId(documentId); final ParcelFileDescriptor pfd = ParcelFileDescriptor.open( file, ParcelFileDescriptor.MODE_READ_ONLY); @@ -294,7 +321,7 @@ public class ExternalStorageProvider extends DocumentsProvider { private static String getTypeForFile(File file) { if (file.isDirectory()) { - return Documents.MIME_TYPE_DIR; + return Document.MIME_TYPE_DIR; } else { return getTypeForName(file.getName()); } @@ -314,7 +341,7 @@ public class ExternalStorageProvider extends DocumentsProvider { } private static String validateDisplayName(String mimeType, String displayName) { - if (Documents.MIME_TYPE_DIR.equals(mimeType)) { + if (Document.MIME_TYPE_DIR.equals(mimeType)) { return displayName; } else { // Try appending meaningful extension if needed |