summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--AndroidManifest.xml3
-rw-r--r--src/com/android/providers/downloads/Constants.java2
-rw-r--r--src/com/android/providers/downloads/DownloadStorageProvider.java288
-rw-r--r--src/com/android/providers/downloads/TrampolineActivity.java10
-rw-r--r--ui/src/com/android/providers/downloads/ui/DownloadList.java6
5 files changed, 104 insertions, 205 deletions
diff --git a/AndroidManifest.xml b/AndroidManifest.xml
index cd8aec5..398f8f4 100644
--- a/AndroidManifest.xml
+++ b/AndroidManifest.xml
@@ -110,7 +110,8 @@
<!-- PackageInstaller really wants raw files -->
<activity
android:name=".TrampolineActivity"
- android:theme="@android:style/Theme.NoDisplay">
+ android:theme="@android:style/Theme.NoDisplay"
+ android:permission="android.permission.MANAGE_DOCUMENTS">
<intent-filter>
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
diff --git a/src/com/android/providers/downloads/Constants.java b/src/com/android/providers/downloads/Constants.java
index 3fbd400..e33a636 100644
--- a/src/com/android/providers/downloads/Constants.java
+++ b/src/com/android/providers/downloads/Constants.java
@@ -176,5 +176,5 @@ public class Constants {
public static final boolean LOGVV = LOCAL_LOGVV && LOGV;
public static final String STORAGE_AUTHORITY = "com.android.providers.downloads.documents";
- public static final String STORAGE_ROOT = "downloads";
+ public static final String STORAGE_DOC_ID_ROOT = "downloads";
}
diff --git a/src/com/android/providers/downloads/DownloadStorageProvider.java b/src/com/android/providers/downloads/DownloadStorageProvider.java
index b606e65..58df58a 100644
--- a/src/com/android/providers/downloads/DownloadStorageProvider.java
+++ b/src/com/android/providers/downloads/DownloadStorageProvider.java
@@ -18,63 +18,55 @@ package com.android.providers.downloads;
import android.app.DownloadManager;
import android.app.DownloadManager.Query;
-import android.content.ContentProvider;
-import android.content.ContentValues;
import android.content.Context;
-import android.content.UriMatcher;
+import android.content.res.AssetFileDescriptor;
import android.database.Cursor;
import android.database.MatrixCursor;
import android.database.MatrixCursor.RowBuilder;
-import android.net.Uri;
+import android.graphics.Point;
import android.os.Binder;
+import android.os.CancellationSignal;
import android.os.ParcelFileDescriptor;
import android.provider.DocumentsContract;
import android.provider.DocumentsContract.DocumentColumns;
+import android.provider.DocumentsContract.DocumentRoot;
import android.provider.DocumentsContract.Documents;
-import android.provider.DocumentsContract.RootColumns;
-import android.provider.DocumentsContract.Roots;
+import android.provider.DocumentsProvider;
+
+import com.google.common.collect.Lists;
import libcore.io.IoUtils;
import java.io.FileNotFoundException;
+import java.util.List;
/**
* Presents a {@link DocumentsContract} view of {@link DownloadManager}
* contents.
*/
-public class DownloadStorageProvider extends ContentProvider {
- private static final String AUTHORITY = Constants.STORAGE_AUTHORITY;
- private static final String ROOT = Constants.STORAGE_ROOT;
-
- private static final UriMatcher sMatcher = new UriMatcher(UriMatcher.NO_MATCH);
-
- private static final int URI_ROOTS = 1;
- private static final int URI_ROOTS_ID = 2;
- private static final int URI_DOCS_ID = 3;
- private static final int URI_DOCS_ID_CONTENTS = 4;
-
- static {
- sMatcher.addURI(AUTHORITY, "roots", URI_ROOTS);
- sMatcher.addURI(AUTHORITY, "roots/*", URI_ROOTS_ID);
- sMatcher.addURI(AUTHORITY, "roots/*/docs/*", URI_DOCS_ID);
- sMatcher.addURI(AUTHORITY, "roots/*/docs/*/contents", URI_DOCS_ID_CONTENTS);
- }
+public class DownloadStorageProvider extends DocumentsProvider {
+ private static final String DOC_ID_ROOT = Constants.STORAGE_DOC_ID_ROOT;
- private static final String[] ALL_ROOTS_COLUMNS = new String[] {
- RootColumns.ROOT_ID, RootColumns.ROOT_TYPE, RootColumns.ICON, RootColumns.TITLE,
- RootColumns.SUMMARY, RootColumns.AVAILABLE_BYTES
- };
-
- private static final String[] ALL_DOCUMENTS_COLUMNS = new String[] {
+ 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 DocumentRoot mRoot;
+
private DownloadManager mDm;
private DownloadManager.Query mBaseQuery;
@Override
public boolean onCreate() {
+
+ mRoot = new DocumentRoot();
+ mRoot.docId = DOC_ID_ROOT;
+ mRoot.rootType = DocumentRoot.ROOT_TYPE_SHORTCUT;
+ mRoot.title = getContext().getString(R.string.root_downloads);
+ mRoot.icon = R.mipmap.ic_launcher_download;
+ mRoot.flags = DocumentRoot.FLAG_LOCAL_ONLY;
+
mDm = (DownloadManager) getContext().getSystemService(Context.DOWNLOAD_SERVICE);
mDm.setAccessAllDownloads(true);
mBaseQuery = new DownloadManager.Query().setOnlyIncludeVisibleInDownloadsUi(true);
@@ -83,91 +75,98 @@ public class DownloadStorageProvider extends ContentProvider {
}
@Override
- public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs,
- String sortOrder) {
- switch (sMatcher.match(uri)) {
- case URI_ROOTS: {
- final MatrixCursor result = new MatrixCursor(
- projection != null ? projection : ALL_ROOTS_COLUMNS);
- includeDefaultRoot(result);
- return result;
- }
- case URI_ROOTS_ID: {
- final MatrixCursor result = new MatrixCursor(
- projection != null ? projection : ALL_ROOTS_COLUMNS);
- includeDefaultRoot(result);
- return result;
- }
- case URI_DOCS_ID: {
- final String docId = DocumentsContract.getDocId(uri);
- final MatrixCursor result = new MatrixCursor(
- projection != null ? projection : ALL_DOCUMENTS_COLUMNS);
+ public List<DocumentRoot> getDocumentRoots() {
+ return Lists.newArrayList(mRoot);
+ }
- if (Documents.DOC_ID_ROOT.equals(docId)) {
- includeDefaultDocument(result);
- } else {
- // Delegate to real provider
- final long token = Binder.clearCallingIdentity();
- Cursor cursor = null;
- try {
- cursor = mDm.query(
- new Query().setFilterById(getDownloadFromDocument(docId)));
- if (cursor.moveToFirst()) {
- includeDownloadFromCursor(result, cursor);
- }
- } finally {
- IoUtils.closeQuietly(cursor);
- Binder.restoreCallingIdentity(token);
- }
- }
- return result;
+ @Override
+ public void deleteDocument(String docId) throws FileNotFoundException {
+ // Delegate to real provider
+ final long token = Binder.clearCallingIdentity();
+ try {
+ if (mDm.remove(Long.parseLong(docId)) != 1) {
+ throw new IllegalStateException("Failed to delete " + docId);
}
- case URI_DOCS_ID_CONTENTS: {
- final String docId = DocumentsContract.getDocId(uri);
- final MatrixCursor result = new MatrixCursor(
- projection != null ? projection : ALL_DOCUMENTS_COLUMNS);
-
- if (!Documents.DOC_ID_ROOT.equals(docId)) {
- throw new UnsupportedOperationException("Unsupported Uri " + uri);
- }
+ } finally {
+ Binder.restoreCallingIdentity(token);
+ }
+ }
- // Delegate to real provider
- final long token = Binder.clearCallingIdentity();
- Cursor cursor = null;
- try {
- cursor = mDm.query(mBaseQuery);
- while (cursor.moveToNext()) {
- includeDownloadFromCursor(result, cursor);
- }
- } finally {
- IoUtils.closeQuietly(cursor);
- Binder.restoreCallingIdentity(token);
+ @Override
+ public Cursor queryDocument(String docId) throws FileNotFoundException {
+ final MatrixCursor result = new MatrixCursor(SUPPORTED_COLUMNS);
+
+ if (DOC_ID_ROOT.equals(docId)) {
+ includeDefaultDocument(result);
+ } else {
+ // Delegate to real provider
+ final long token = Binder.clearCallingIdentity();
+ Cursor cursor = null;
+ try {
+ cursor = mDm.query(new Query().setFilterById(Long.parseLong(docId)));
+ if (cursor.moveToFirst()) {
+ includeDownloadFromCursor(result, cursor);
}
- return result;
+ } finally {
+ IoUtils.closeQuietly(cursor);
+ Binder.restoreCallingIdentity(token);
}
- default: {
- throw new UnsupportedOperationException("Unsupported Uri " + uri);
+ }
+ return result;
+ }
+
+ @Override
+ public Cursor queryDocumentChildren(String docId) throws FileNotFoundException {
+ final MatrixCursor result = new MatrixCursor(SUPPORTED_COLUMNS);
+
+ // Delegate to real provider
+ final long token = Binder.clearCallingIdentity();
+ Cursor cursor = null;
+ try {
+ cursor = mDm.query(mBaseQuery);
+ while (cursor.moveToNext()) {
+ includeDownloadFromCursor(result, cursor);
}
+ } finally {
+ IoUtils.closeQuietly(cursor);
+ Binder.restoreCallingIdentity(token);
}
+ return result;
}
- private void includeDefaultRoot(MatrixCursor result) {
- final RowBuilder row = result.newRow();
- row.offer(RootColumns.ROOT_ID, ROOT);
- row.offer(RootColumns.ROOT_TYPE, Roots.ROOT_TYPE_SHORTCUT);
- row.offer(RootColumns.TITLE, getContext().getString(R.string.root_downloads));
+ @Override
+ public ParcelFileDescriptor openDocument(String docId, String mode, CancellationSignal signal)
+ throws FileNotFoundException {
+ if (!"r".equals(mode)) {
+ throw new IllegalArgumentException("Downloads are read-only");
+ }
+
+ // Delegate to real provider
+ final long token = Binder.clearCallingIdentity();
+ try {
+ return mDm.openDownloadedFile(Long.parseLong(docId));
+ } finally {
+ Binder.restoreCallingIdentity(token);
+ }
+ }
+
+ @Override
+ public AssetFileDescriptor openDocumentThumbnail(
+ String docId, Point sizeHint, CancellationSignal signal) throws FileNotFoundException {
+ // TODO: extend ExifInterface to support fds
+ final ParcelFileDescriptor pfd = openDocument(docId, "r", signal);
+ return new AssetFileDescriptor(pfd, 0, AssetFileDescriptor.UNKNOWN_LENGTH);
}
private void includeDefaultDocument(MatrixCursor result) {
final RowBuilder row = result.newRow();
- row.offer(DocumentColumns.DOC_ID, Documents.DOC_ID_ROOT);
- row.offer(DocumentColumns.DISPLAY_NAME, getContext().getString(R.string.root_downloads));
+ row.offer(DocumentColumns.DOC_ID, DOC_ID_ROOT);
row.offer(DocumentColumns.MIME_TYPE, Documents.MIME_TYPE_DIR);
}
private void includeDownloadFromCursor(MatrixCursor result, Cursor cursor) {
final long id = cursor.getLong(cursor.getColumnIndexOrThrow(DownloadManager.COLUMN_ID));
- final String docId = getDocumentFromDownload(id);
+ final String docId = String.valueOf(id);
final String displayName = cursor.getString(
cursor.getColumnIndexOrThrow(DownloadManager.COLUMN_TITLE));
@@ -225,101 +224,4 @@ public class DownloadStorageProvider extends ContentProvider {
row.offer(DocumentColumns.LAST_MODIFIED, lastModified);
row.offer(DocumentColumns.FLAGS, flags);
}
-
- private interface TypeQuery {
- final String[] PROJECTION = {
- DocumentColumns.MIME_TYPE };
-
- final int MIME_TYPE = 0;
- }
-
- @Override
- public String getType(Uri uri) {
- switch (sMatcher.match(uri)) {
- case URI_ROOTS: {
- return Roots.MIME_TYPE_DIR;
- }
- case URI_ROOTS_ID: {
- return Roots.MIME_TYPE_ITEM;
- }
- case URI_DOCS_ID: {
- final Cursor cursor = query(uri, TypeQuery.PROJECTION, null, null, null);
- try {
- if (cursor.moveToFirst()) {
- return cursor.getString(TypeQuery.MIME_TYPE);
- } else {
- return null;
- }
- } finally {
- IoUtils.closeQuietly(cursor);
- }
- }
- default: {
- throw new UnsupportedOperationException("Unsupported Uri " + uri);
- }
- }
- }
-
- public static long getDownloadFromDocument(String docId) {
- return Long.parseLong(docId.substring(docId.indexOf(':') + 1));
- }
-
- private String getDocumentFromDownload(long id) {
- return "id:" + id;
- }
-
- @Override
- public ParcelFileDescriptor openFile(Uri uri, String mode) throws FileNotFoundException {
- switch (sMatcher.match(uri)) {
- case URI_DOCS_ID: {
- final String docId = DocumentsContract.getDocId(uri);
-
- if (!"r".equals(mode)) {
- throw new IllegalArgumentException("Downloads are read-only");
- }
-
- // Delegate to real provider
- final long token = Binder.clearCallingIdentity();
- try {
- return mDm.openDownloadedFile(getDownloadFromDocument(docId));
- } finally {
- Binder.restoreCallingIdentity(token);
- }
- }
- default: {
- throw new UnsupportedOperationException("Unsupported Uri " + uri);
- }
- }
- }
-
- @Override
- public Uri insert(Uri uri, ContentValues values) {
- throw new UnsupportedOperationException("Unsupported Uri " + uri);
- }
-
- @Override
- public int update(Uri uri, ContentValues values, String selection, String[] selectionArgs) {
- throw new UnsupportedOperationException("Unsupported Uri " + uri);
- }
-
- @Override
- public int delete(Uri uri, String selection, String[] selectionArgs) {
- switch (sMatcher.match(uri)) {
- case URI_DOCS_ID: {
- final String docId = DocumentsContract.getDocId(uri);
-
- // Delegate to real provider
- // TODO: only storage UI should be allowed to delete?
- final long token = Binder.clearCallingIdentity();
- try {
- return mDm.remove(getDownloadFromDocument(docId));
- } finally {
- Binder.restoreCallingIdentity(token);
- }
- }
- default: {
- throw new UnsupportedOperationException("Unsupported Uri " + uri);
- }
- }
- }
}
diff --git a/src/com/android/providers/downloads/TrampolineActivity.java b/src/com/android/providers/downloads/TrampolineActivity.java
index a1e9916..0f494cf 100644
--- a/src/com/android/providers/downloads/TrampolineActivity.java
+++ b/src/com/android/providers/downloads/TrampolineActivity.java
@@ -17,10 +17,9 @@
package com.android.providers.downloads;
import android.app.Activity;
+import android.content.ContentUris;
import android.content.Intent;
-import android.net.Uri;
import android.os.Bundle;
-import android.provider.DocumentsContract;
/**
* PackageInstaller really wants raw files.
@@ -30,11 +29,8 @@ public class TrampolineActivity extends Activity {
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
- final Uri documentUri = getIntent().getData();
- final String docId = DocumentsContract.getDocId(documentUri);
- final long downloadId = DownloadStorageProvider.getDownloadFromDocument(docId);
-
- final Intent intent = OpenHelper.buildViewIntent(this, downloadId);
+ final long id = ContentUris.parseId(getIntent().getData());
+ final Intent intent = OpenHelper.buildViewIntent(this, id);
startActivity(intent);
finish();
}
diff --git a/ui/src/com/android/providers/downloads/ui/DownloadList.java b/ui/src/com/android/providers/downloads/ui/DownloadList.java
index 5753047..443491a 100644
--- a/ui/src/com/android/providers/downloads/ui/DownloadList.java
+++ b/ui/src/com/android/providers/downloads/ui/DownloadList.java
@@ -151,9 +151,9 @@ public class DownloadList extends Activity {
super.onCreate(icicle);
// Trampoline over to new management UI
- final Intent intent = new Intent(Intent.ACTION_MANAGE_DOCUMENT);
- intent.setData(DocumentsContract.buildRootUri(
- Constants.STORAGE_AUTHORITY, Constants.STORAGE_ROOT));
+ final Intent intent = new Intent(DocumentsContract.ACTION_MANAGE_DOCUMENTS);
+ intent.setData(DocumentsContract.buildDocumentUri(
+ Constants.STORAGE_AUTHORITY, Constants.STORAGE_DOC_ID_ROOT));
startActivity(intent);
finish();
}