summaryrefslogtreecommitdiffstats
path: root/src/com/android/providers/downloads
diff options
context:
space:
mode:
Diffstat (limited to 'src/com/android/providers/downloads')
-rw-r--r--src/com/android/providers/downloads/Constants.java3
-rw-r--r--src/com/android/providers/downloads/DownloadNotifier.java31
-rw-r--r--src/com/android/providers/downloads/DownloadReceiver.java28
-rw-r--r--src/com/android/providers/downloads/DownloadService.java15
-rw-r--r--src/com/android/providers/downloads/DownloadStorageProvider.java52
-rw-r--r--src/com/android/providers/downloads/OpenHelper.java1
6 files changed, 122 insertions, 8 deletions
diff --git a/src/com/android/providers/downloads/Constants.java b/src/com/android/providers/downloads/Constants.java
index 7b8fcd24..6cea8086 100644
--- a/src/com/android/providers/downloads/Constants.java
+++ b/src/com/android/providers/downloads/Constants.java
@@ -54,6 +54,9 @@ public class Constants {
/** the intent that gets sent when clicking an incomplete/failed download */
public static final String ACTION_LIST = "android.intent.action.DOWNLOAD_LIST";
+ /** the intent that gets sent when canceling a download */
+ public static final String ACTION_CANCEL = "android.intent.action.DOWNLOAD_CANCEL";
+
/** the intent that gets sent when deleting the notification of a completed download */
public static final String ACTION_HIDE = "android.intent.action.DOWNLOAD_HIDE";
diff --git a/src/com/android/providers/downloads/DownloadNotifier.java b/src/com/android/providers/downloads/DownloadNotifier.java
index 60c249f9..2ff8b634 100644
--- a/src/com/android/providers/downloads/DownloadNotifier.java
+++ b/src/com/android/providers/downloads/DownloadNotifier.java
@@ -122,6 +122,15 @@ public class DownloadNotifier {
}
}
+ private static boolean isClusterDeleted(Collection<DownloadInfo> cluster) {
+ boolean wasDeleted = true;
+ for (DownloadInfo info : cluster) {
+ wasDeleted = wasDeleted && info.mDeleted;
+ }
+
+ return wasDeleted;
+ }
+
private void updateWithLocked(Collection<DownloadInfo> downloads) {
final Resources res = mContext.getResources();
@@ -139,6 +148,11 @@ public class DownloadNotifier {
final int type = getNotificationTagType(tag);
final Collection<DownloadInfo> cluster = clustered.get(tag);
+ // If each of the downloads was canceled, don't show notification for the cluster
+ if (isClusterDeleted(cluster)) {
+ continue;
+ }
+
final Notification.Builder builder = new Notification.Builder(mContext);
builder.setColor(res.getColor(
com.android.internal.R.color.system_notification_accent_color));
@@ -164,16 +178,31 @@ public class DownloadNotifier {
// Build action intents
if (type == TYPE_ACTIVE || type == TYPE_WAITING) {
+ long[] downloadIds = getDownloadIds(cluster);
+
// build a synthetic uri for intent identification purposes
final Uri uri = new Uri.Builder().scheme("active-dl").appendPath(tag).build();
final Intent intent = new Intent(Constants.ACTION_LIST,
uri, mContext, DownloadReceiver.class);
intent.putExtra(DownloadManager.EXTRA_NOTIFICATION_CLICK_DOWNLOAD_IDS,
- getDownloadIds(cluster));
+ downloadIds);
builder.setContentIntent(PendingIntent.getBroadcast(mContext,
0, intent, PendingIntent.FLAG_UPDATE_CURRENT));
builder.setOngoing(true);
+ // Add a Cancel action
+ final Uri cancelUri = new Uri.Builder().scheme("cancel-dl").appendPath(tag).build();
+ final Intent cancelIntent = new Intent(Constants.ACTION_CANCEL,
+ cancelUri, mContext, DownloadReceiver.class);
+ cancelIntent.putExtra(DownloadReceiver.EXTRA_CANCELED_DOWNLOAD_IDS, downloadIds);
+ cancelIntent.putExtra(DownloadReceiver.EXTRA_CANCELED_DOWNLOAD_NOTIFICATION_TAG, tag);
+
+ builder.addAction(
+ android.R.drawable.ic_menu_close_clear_cancel,
+ res.getString(R.string.button_cancel_download),
+ PendingIntent.getBroadcast(mContext,
+ 0, cancelIntent, PendingIntent.FLAG_UPDATE_CURRENT));
+
} else if (type == TYPE_COMPLETE) {
final DownloadInfo info = cluster.iterator().next();
final Uri uri = ContentUris.withAppendedId(
diff --git a/src/com/android/providers/downloads/DownloadReceiver.java b/src/com/android/providers/downloads/DownloadReceiver.java
index 28e2a673..2f50dcf6 100644
--- a/src/com/android/providers/downloads/DownloadReceiver.java
+++ b/src/com/android/providers/downloads/DownloadReceiver.java
@@ -21,6 +21,7 @@ import static android.app.DownloadManager.Request.VISIBILITY_VISIBLE_NOTIFY_ONLY
import static com.android.providers.downloads.Constants.TAG;
import android.app.DownloadManager;
+import android.app.NotificationManager;
import android.content.BroadcastReceiver;
import android.content.ContentResolver;
import android.content.ContentUris;
@@ -45,6 +46,21 @@ import com.google.common.annotations.VisibleForTesting;
* Receives system broadcasts (boot, network connectivity)
*/
public class DownloadReceiver extends BroadcastReceiver {
+ /**
+ * Intent extra included with {@link #ACTION_CANCEL} intents, indicating the IDs (as array of
+ * long) of the downloads that were canceled.
+ */
+ public static final String EXTRA_CANCELED_DOWNLOAD_IDS =
+ "com.android.providers.downloads.extra.CANCELED_DOWNLOAD_IDS";
+
+ /**
+ * Intent extra included with {@link #ACTION_CANCEL} intents, indicating the tag of the
+ * notification corresponding to the download(s) that were canceled; this notification must be
+ * canceled.
+ */
+ public static final String EXTRA_CANCELED_DOWNLOAD_NOTIFICATION_TAG =
+ "com.android.providers.downloads.extra.CANCELED_DOWNLOAD_NOTIFICATION_TAG";
+
private static Handler sAsyncHandler;
static {
@@ -107,6 +123,18 @@ public class DownloadReceiver extends BroadcastReceiver {
}
});
}
+ } else if (Constants.ACTION_CANCEL.equals(action)) {
+ long[] downloadIds = intent.getLongArrayExtra(
+ DownloadReceiver.EXTRA_CANCELED_DOWNLOAD_IDS);
+ DownloadManager manager = (DownloadManager) context.getSystemService(
+ Context.DOWNLOAD_SERVICE);
+ manager.remove(downloadIds);
+
+ String notifTag = intent.getStringExtra(
+ DownloadReceiver.EXTRA_CANCELED_DOWNLOAD_NOTIFICATION_TAG);
+ NotificationManager notifManager = (NotificationManager) context.getSystemService(
+ Context.NOTIFICATION_SERVICE);
+ notifManager.cancel(notifTag, 0);
}
}
diff --git a/src/com/android/providers/downloads/DownloadService.java b/src/com/android/providers/downloads/DownloadService.java
index b0b73297..7845ce0e 100644
--- a/src/com/android/providers/downloads/DownloadService.java
+++ b/src/com/android/providers/downloads/DownloadService.java
@@ -33,11 +33,15 @@ import android.content.res.Resources;
import android.database.ContentObserver;
import android.database.Cursor;
import android.net.Uri;
+import android.os.Binder;
import android.os.Handler;
import android.os.HandlerThread;
import android.os.IBinder;
+import android.os.IDeviceIdleController;
import android.os.Message;
import android.os.Process;
+import android.os.RemoteException;
+import android.os.ServiceManager;
import android.provider.Downloads;
import android.text.TextUtils;
import android.util.Log;
@@ -84,6 +88,7 @@ public class DownloadService extends Service {
SystemFacade mSystemFacade;
private AlarmManager mAlarmManager;
+ private IDeviceIdleController mDeviceIdleController;
/** Observer to get notified when the content observer's data changes */
private DownloadManagerContentObserver mObserver;
@@ -192,6 +197,12 @@ public class DownloadService extends Service {
}
mAlarmManager = (AlarmManager) getSystemService(Context.ALARM_SERVICE);
+ mDeviceIdleController = IDeviceIdleController.Stub.asInterface(
+ ServiceManager.getService(Context.DEVICE_IDLE_CONTROLLER));
+ try {
+ mDeviceIdleController.downloadServiceActive(new Binder());
+ } catch (RemoteException e) {
+ }
mUpdateThread = new HandlerThread(TAG + "-UpdateThread");
mUpdateThread.start();
@@ -330,6 +341,10 @@ public class DownloadService extends Service {
if (DEBUG_LIFECYCLE) Log.v(TAG, "Nothing left; stopped");
getContentResolver().unregisterContentObserver(mObserver);
mScanner.shutdown();
+ try {
+ mDeviceIdleController.downloadServiceInactive();
+ } catch (RemoteException e) {
+ }
mUpdateThread.quit();
}
}
diff --git a/src/com/android/providers/downloads/DownloadStorageProvider.java b/src/com/android/providers/downloads/DownloadStorageProvider.java
index 1b5dc844..77b8fe49 100644
--- a/src/com/android/providers/downloads/DownloadStorageProvider.java
+++ b/src/com/android/providers/downloads/DownloadStorageProvider.java
@@ -35,6 +35,7 @@ import android.provider.DocumentsContract;
import android.provider.DocumentsContract.Document;
import android.provider.DocumentsContract.Root;
import android.provider.DocumentsProvider;
+import android.support.provider.DocumentArchiveHelper;
import android.text.TextUtils;
import android.webkit.MimeTypeMap;
@@ -65,11 +66,14 @@ public class DownloadStorageProvider extends DocumentsProvider {
};
private DownloadManager mDm;
+ private DocumentArchiveHelper mArchiveHelper;
@Override
public boolean onCreate() {
mDm = (DownloadManager) getContext().getSystemService(Context.DOWNLOAD_SERVICE);
mDm.setAccessAllDownloads(true);
+ mDm.setAccessFilename(true);
+ mArchiveHelper = new DocumentArchiveHelper(this, ':');
return true;
}
@@ -152,6 +156,10 @@ public class DownloadStorageProvider extends DocumentsProvider {
@Override
public Cursor queryDocument(String docId, String[] projection) throws FileNotFoundException {
+ if (mArchiveHelper.isArchivedDocument(docId)) {
+ return mArchiveHelper.queryDocument(docId, projection);
+ }
+
final MatrixCursor result = new MatrixCursor(resolveDocumentProjection(projection));
if (DOC_ID_ROOT.equals(docId)) {
@@ -164,7 +172,9 @@ public class DownloadStorageProvider extends DocumentsProvider {
cursor = mDm.query(new Query().setFilterById(Long.parseLong(docId)));
copyNotificationUri(result, cursor);
if (cursor.moveToFirst()) {
- includeDownloadFromCursor(result, cursor);
+ // We don't know if this queryDocument() call is from Downloads (manage)
+ // or Files. Safely assume it's Files.
+ includeDownloadFromCursor(result, cursor, false /* forManage */);
}
} finally {
IoUtils.closeQuietly(cursor);
@@ -177,6 +187,11 @@ public class DownloadStorageProvider extends DocumentsProvider {
@Override
public Cursor queryChildDocuments(String docId, String[] projection, String sortOrder)
throws FileNotFoundException {
+ if (mArchiveHelper.isArchivedDocument(docId) ||
+ mArchiveHelper.isSupportedArchiveType(getDocumentType(docId))) {
+ return mArchiveHelper.queryChildDocuments(docId, projection, sortOrder);
+ }
+
final MatrixCursor result = new MatrixCursor(resolveDocumentProjection(projection));
// Delegate to real provider
@@ -187,7 +202,7 @@ public class DownloadStorageProvider extends DocumentsProvider {
.setFilterByStatus(DownloadManager.STATUS_SUCCESSFUL));
copyNotificationUri(result, cursor);
while (cursor.moveToNext()) {
- includeDownloadFromCursor(result, cursor);
+ includeDownloadFromCursor(result, cursor, false /* forManage */);
}
} finally {
IoUtils.closeQuietly(cursor);
@@ -200,6 +215,10 @@ public class DownloadStorageProvider extends DocumentsProvider {
public Cursor queryChildDocumentsForManage(
String parentDocumentId, String[] projection, String sortOrder)
throws FileNotFoundException {
+ if (mArchiveHelper.isArchivedDocument(parentDocumentId)) {
+ return mArchiveHelper.queryDocument(parentDocumentId, projection);
+ }
+
final MatrixCursor result = new MatrixCursor(resolveDocumentProjection(projection));
// Delegate to real provider
@@ -210,7 +229,7 @@ public class DownloadStorageProvider extends DocumentsProvider {
new DownloadManager.Query().setOnlyIncludeVisibleInDownloadsUi(true));
copyNotificationUri(result, cursor);
while (cursor.moveToNext()) {
- includeDownloadFromCursor(result, cursor);
+ includeDownloadFromCursor(result, cursor, true /* forManage */);
}
} finally {
IoUtils.closeQuietly(cursor);
@@ -244,7 +263,7 @@ public class DownloadStorageProvider extends DocumentsProvider {
continue;
}
- includeDownloadFromCursor(result, cursor);
+ includeDownloadFromCursor(result, cursor, false /* forManage */);
}
} finally {
IoUtils.closeQuietly(cursor);
@@ -256,6 +275,10 @@ public class DownloadStorageProvider extends DocumentsProvider {
@Override
public ParcelFileDescriptor openDocument(String docId, String mode, CancellationSignal signal)
throws FileNotFoundException {
+ if (mArchiveHelper.isArchivedDocument(docId)) {
+ return mArchiveHelper.openDocument(docId, mode, signal);
+ }
+
// Delegate to real provider
final long token = Binder.clearCallingIdentity();
try {
@@ -283,7 +306,7 @@ public class DownloadStorageProvider extends DocumentsProvider {
Document.FLAG_DIR_PREFERS_LAST_MODIFIED | Document.FLAG_DIR_SUPPORTS_CREATE);
}
- private void includeDownloadFromCursor(MatrixCursor result, Cursor cursor) {
+ private void includeDownloadFromCursor(MatrixCursor result, Cursor cursor, boolean forManage) {
final long id = cursor.getLong(cursor.getColumnIndexOrThrow(DownloadManager.COLUMN_ID));
final String docId = String.valueOf(id);
@@ -332,10 +355,15 @@ public class DownloadStorageProvider extends DocumentsProvider {
}
int flags = Document.FLAG_SUPPORTS_DELETE | Document.FLAG_SUPPORTS_WRITE;
- if (mimeType != null && mimeType.startsWith("image/")) {
+ if (mimeType.startsWith("image/")) {
flags |= Document.FLAG_SUPPORTS_THUMBNAIL;
}
+ // TODO: Remove forManage and move the logic to DocumentsUI. b/26321218.
+ if (!forManage && mArchiveHelper.isSupportedArchiveType(mimeType)) {
+ flags |= Document.FLAG_ARCHIVE;
+ }
+
final long lastModified = cursor.getLong(
cursor.getColumnIndexOrThrow(DownloadManager.COLUMN_LAST_MODIFIED_TIMESTAMP));
@@ -345,8 +373,18 @@ public class DownloadStorageProvider extends DocumentsProvider {
row.add(Document.COLUMN_SUMMARY, summary);
row.add(Document.COLUMN_SIZE, size);
row.add(Document.COLUMN_MIME_TYPE, mimeType);
- row.add(Document.COLUMN_LAST_MODIFIED, lastModified);
row.add(Document.COLUMN_FLAGS, flags);
+ // Incomplete downloads get a null timestamp. This prevents thrashy UI when a bunch of
+ // active downloads get sorted by mod time.
+ if (status != DownloadManager.STATUS_RUNNING) {
+ row.add(Document.COLUMN_LAST_MODIFIED, lastModified);
+ }
+
+ final String localFilePath = cursor.getString(
+ cursor.getColumnIndexOrThrow(DownloadManager.COLUMN_LOCAL_FILENAME));
+ if (localFilePath != null) {
+ row.add(DocumentArchiveHelper.COLUMN_LOCAL_FILE_PATH, localFilePath);
+ }
}
/**
diff --git a/src/com/android/providers/downloads/OpenHelper.java b/src/com/android/providers/downloads/OpenHelper.java
index 4eb319c4..4b051be5 100644
--- a/src/com/android/providers/downloads/OpenHelper.java
+++ b/src/com/android/providers/downloads/OpenHelper.java
@@ -65,6 +65,7 @@ public class OpenHelper {
final DownloadManager downManager = (DownloadManager) context.getSystemService(
Context.DOWNLOAD_SERVICE);
downManager.setAccessAllDownloads(true);
+ downManager.setAccessFilename(true);
final Cursor cursor = downManager.query(new DownloadManager.Query().setFilterById(id));
try {