summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--res/drawable/download_pause.xml16
-rw-r--r--res/values/cm_strings.xml16
-rw-r--r--src/com/android/providers/downloads/Constants.java9
-rw-r--r--src/com/android/providers/downloads/DownloadNotifier.java79
-rw-r--r--src/com/android/providers/downloads/DownloadReceiver.java20
-rw-r--r--src/com/android/providers/downloads/DownloadStorageProvider.java17
-rw-r--r--src/com/android/providers/downloads/DownloadThread.java7
-rw-r--r--ui/src/com/android/providers/downloads/ui/TrampolineActivity.java16
8 files changed, 171 insertions, 9 deletions
diff --git a/res/drawable/download_pause.xml b/res/drawable/download_pause.xml
new file mode 100644
index 0000000..c82ec92
--- /dev/null
+++ b/res/drawable/download_pause.xml
@@ -0,0 +1,16 @@
+<?xml version="1.0" encoding="utf-8"?>
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:width="24dp"
+ android:height="24dp"
+ android:viewportWidth="24"
+ android:viewportHeight="24">
+
+ <group>
+ <path
+ android:fillColor="#fafafa"
+ android:pathData="M6 19h4V5H6v14zm8-14v14h4V5h-4z" />
+
+ <path
+ android:pathData="M0 0h24v24H0z" />
+ </group>
+</vector>
diff --git a/res/values/cm_strings.xml b/res/values/cm_strings.xml
index 9fca450..38964af 100644
--- a/res/values/cm_strings.xml
+++ b/res/values/cm_strings.xml
@@ -17,4 +17,20 @@
<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<!-- Notification text containing download duration left and download speed -->
<string name="text_download_speed"><xliff:g id="text">%1$s</xliff:g>, <xliff:g id="size" example="230 kB">%2$s</xliff:g>/s</string>
+
+ <!-- Status indicating that the download has been paused to start in the future. Appears for an
+ individual item in the download list. [CHAR LIMIT=24] -->
+ <string name="download_paused">Paused</string>
+
+ <!-- Representation of download progress percentage when paused. [CHAR LIMIT=24] -->
+ <string name="download_paused_percent">Paused, %d%%</string>
+
+ <!-- Text for button to manually resume all manually paused downloads [CHAR LIMIT=25] -->
+ <string name="button_resume_download">Resume</string>
+
+ <!-- Text for button to manually manually pause all running downloads [CHAR LIMIT=25] -->
+ <string name="button_pause_download">Pause</string>
+
+ <!-- Title summarizing paused downloads. [CHAR LIMIT=32] -->
+ <string name="notif_summary_paused">%d paused</string>
</resources>
diff --git a/src/com/android/providers/downloads/Constants.java b/src/com/android/providers/downloads/Constants.java
index c822c7c..f2cf5a9 100644
--- a/src/com/android/providers/downloads/Constants.java
+++ b/src/com/android/providers/downloads/Constants.java
@@ -57,6 +57,15 @@ public class Constants {
/** the intent that gets sent when deleting the notification of a completed download */
public static final String ACTION_HIDE = "android.intent.action.DOWNLOAD_HIDE";
+ /** the intent that gets sent when manually resuming a manually paused download queue */
+ public static final String ACTION_RESUME_QUEUE = "android.intent.action.DOWNLOAD_RESUME_QUEUE";
+
+ /** the intent that gets sent when manually resuming a manually paused download */
+ public static final String ACTION_RESUME = "android.intent.action.DOWNLOAD_RESUME";
+
+ /** the intent that gets sent when manually pausing a running download */
+ public static final String ACTION_PAUSE = "android.intent.action.DOWNLOAD_PAUSE";
+
/** The default base name for downloaded files if we can't get one at the HTTP level */
public static final String DEFAULT_DL_FILENAME = "downloadfile";
diff --git a/src/com/android/providers/downloads/DownloadNotifier.java b/src/com/android/providers/downloads/DownloadNotifier.java
index e6a9864..db24db6 100644
--- a/src/com/android/providers/downloads/DownloadNotifier.java
+++ b/src/com/android/providers/downloads/DownloadNotifier.java
@@ -19,6 +19,7 @@ package com.android.providers.downloads;
import static android.app.DownloadManager.Request.VISIBILITY_VISIBLE;
import static android.app.DownloadManager.Request.VISIBILITY_VISIBLE_NOTIFY_COMPLETED;
import static android.app.DownloadManager.Request.VISIBILITY_VISIBLE_NOTIFY_ONLY_COMPLETION;
+import static android.provider.Downloads.Impl.STATUS_PAUSED_MANUAL;
import static android.provider.Downloads.Impl.STATUS_QUEUED_FOR_WIFI;
import static android.provider.Downloads.Impl.STATUS_RUNNING;
@@ -48,6 +49,7 @@ import android.util.LongSparseLongArray;
import com.android.internal.util.ArrayUtils;
+import java.lang.StringBuilder;
import java.text.NumberFormat;
import javax.annotation.concurrent.GuardedBy;
@@ -222,6 +224,36 @@ public class DownloadNotifier {
builder.setWhen(firstShown);
builder.setOnlyAlertOnce(true);
+ /**
+ * If *all* current downloads in the cluster are manually paused,
+ * display the appropriate notification icon and content.
+ *
+ * Also keep track of the number of paused downloads so as to
+ * display the current number of downloading files correctly.
+ */
+ int numPaused = 0;
+ for (int j = 0; j < cluster.size(); j++) {
+ cursor.moveToPosition(cluster.get(j));
+ int status = cursor.getInt(UpdateQuery.STATUS);
+ if (status == Downloads.Impl.STATUS_PAUSED_MANUAL) {
+ numPaused++;
+ }
+ }
+ boolean isClusterPaused = numPaused == cluster.size();
+
+ // Show relevant icon
+ if (type == TYPE_ACTIVE) {
+ if (isClusterPaused) {
+ builder.setSmallIcon(R.drawable.download_pause);
+ } else {
+ builder.setSmallIcon(android.R.drawable.stat_sys_download);
+ }
+ } else if (type == TYPE_WAITING) {
+ builder.setSmallIcon(android.R.drawable.stat_sys_warning);
+ } else if (type == TYPE_COMPLETE) {
+ builder.setSmallIcon(android.R.drawable.stat_sys_download_done);
+ }
+
// Build action intents
if (type == TYPE_ACTIVE || type == TYPE_WAITING) {
final long[] downloadIds = getDownloadIds(cursor, cluster);
@@ -253,6 +285,32 @@ public class DownloadNotifier {
PendingIntent.getBroadcast(mContext,
0, cancelIntent, PendingIntent.FLAG_UPDATE_CURRENT));
+ if (isClusterPaused) {
+ // Add a Resume action
+ final Intent resumeIntent = new Intent(Constants.ACTION_RESUME_QUEUE,
+ uri, mContext, DownloadReceiver.class);
+ resumeIntent.putExtra(DownloadManager.EXTRA_NOTIFICATION_CLICK_DOWNLOAD_IDS,
+ downloadIds);
+
+ builder.addAction(
+ com.android.internal.R.drawable.ic_media_play,
+ res.getString(R.string.button_resume_download),
+ PendingIntent.getBroadcast(mContext,
+ 0, resumeIntent, PendingIntent.FLAG_UPDATE_CURRENT));
+ } else {
+ // Add a Pause action
+ final Intent pauseIntent = new Intent(Constants.ACTION_PAUSE,
+ uri, mContext, DownloadReceiver.class);
+ pauseIntent.putExtra(DownloadManager.EXTRA_NOTIFICATION_CLICK_DOWNLOAD_IDS,
+ downloadIds);
+
+ builder.addAction(
+ com.android.internal.R.drawable.ic_media_pause,
+ res.getString(R.string.button_pause_download),
+ PendingIntent.getBroadcast(mContext,
+ 0, pauseIntent, PendingIntent.FLAG_UPDATE_CURRENT));
+ }
+
} else if (type == TYPE_COMPLETE) {
cursor.moveToPosition(cluster.get(0));
final long id = cursor.getLong(UpdateQuery._ID);
@@ -349,7 +407,9 @@ public class DownloadNotifier {
builder.setContentTitle(getDownloadTitle(res, cursor));
if (type == TYPE_ACTIVE) {
- if (speedAsSizeText != null) {
+ if (isClusterPaused) {
+ builder.setContentText(res.getText(R.string.download_paused));
+ } else if (speedAsSizeText != null) {
builder.setContentText(res.getString(R.string.text_download_speed,
remainingText, speedAsSizeText));
} else {
@@ -387,8 +447,19 @@ public class DownloadNotifier {
}
if (type == TYPE_ACTIVE) {
- builder.setContentTitle(res.getQuantityString(
- R.plurals.notif_summary_active, cluster.size(), cluster.size()));
+ if (isClusterPaused) {
+ builder.setContentTitle(res.getString(R.string.download_paused));
+ } else if (numPaused > 0) {
+ StringBuilder sb = new StringBuilder(res.getQuantityString(
+ R.plurals.notif_summary_active,
+ cluster.size() - numPaused, cluster.size()));
+ sb.append(", ");
+ sb.append(res.getString(R.string.notif_summary_paused, numPaused));
+ builder.setContentTitle(sb.toString());
+ } else {
+ builder.setContentTitle(res.getQuantityString(
+ R.plurals.notif_summary_active, cluster.size(), cluster.size()));
+ }
builder.setContentText(remainingText);
builder.setContentInfo(percentText);
if (speedAsSizeText != null) {
@@ -491,7 +562,7 @@ public class DownloadNotifier {
}
private static boolean isActiveAndVisible(int status, int visibility) {
- return status == STATUS_RUNNING &&
+ return (status == STATUS_RUNNING || status == STATUS_PAUSED_MANUAL) &&
(visibility == VISIBILITY_VISIBLE
|| visibility == VISIBILITY_VISIBLE_NOTIFY_COMPLETED);
}
diff --git a/src/com/android/providers/downloads/DownloadReceiver.java b/src/com/android/providers/downloads/DownloadReceiver.java
index 40b5e09..acd7070 100644
--- a/src/com/android/providers/downloads/DownloadReceiver.java
+++ b/src/com/android/providers/downloads/DownloadReceiver.java
@@ -122,6 +122,26 @@ public class DownloadReceiver extends BroadcastReceiver {
NotificationManager notifManager = (NotificationManager) context.getSystemService(
Context.NOTIFICATION_SERVICE);
notifManager.cancel(notifTag, 0);
+ } else if (Constants.ACTION_PAUSE.equals(action)) {
+ long[] downloadIds = intent.getLongArrayExtra(
+ DownloadManager.EXTRA_NOTIFICATION_CLICK_DOWNLOAD_IDS);
+ DownloadManager manager = (DownloadManager) context.getSystemService(
+ Context.DOWNLOAD_SERVICE);
+ for (long id : downloadIds) {
+ manager.pauseDownload(id);
+ }
+ } else if (Constants.ACTION_RESUME_QUEUE.equals(action)) {
+ long[] downloadIds = intent.getLongArrayExtra(
+ DownloadManager.EXTRA_NOTIFICATION_CLICK_DOWNLOAD_IDS);
+ DownloadManager manager = (DownloadManager) context.getSystemService(
+ Context.DOWNLOAD_SERVICE);
+ for (long id : downloadIds) {
+ manager.resumeDownload(id);
+ Helpers.scheduleJob(context, DownloadInfo.queryDownloadInfo(context, id));
+ }
+ } else if (Constants.ACTION_RESUME.equals(action)) {
+ long id = intent.getLongExtra(DownloadManager.EXTRA_DOWNLOAD_ID, -1);
+ Helpers.scheduleJob(context, DownloadInfo.queryDownloadInfo(context, id));
}
}
diff --git a/src/com/android/providers/downloads/DownloadStorageProvider.java b/src/com/android/providers/downloads/DownloadStorageProvider.java
index fc7dd5e..051cf35 100644
--- a/src/com/android/providers/downloads/DownloadStorageProvider.java
+++ b/src/com/android/providers/downloads/DownloadStorageProvider.java
@@ -649,6 +649,10 @@ public class DownloadStorageProvider extends FileSystemProvider {
int extraFlags = Document.FLAG_PARTIAL;
final int status = cursor.getInt(
cursor.getColumnIndexOrThrow(DownloadManager.COLUMN_STATUS));
+ final long progress = cursor.getLong(cursor.getColumnIndexOrThrow(
+ DownloadManager.COLUMN_BYTES_DOWNLOADED_SO_FAR));
+ final int reason = cursor.getInt(
+ cursor.getColumnIndexOrThrow(DownloadManager.COLUMN_REASON));
switch (status) {
case DownloadManager.STATUS_SUCCESSFUL:
// Verify that the document still exists in external storage. This is necessary
@@ -660,14 +664,21 @@ public class DownloadStorageProvider extends FileSystemProvider {
extraFlags = Document.FLAG_SUPPORTS_RENAME; // only successful is non-partial
break;
case DownloadManager.STATUS_PAUSED:
- summary = getContext().getString(R.string.download_queued);
+ if (reason == DownloadManager.PAUSED_MANUAL) {
+ if (size > 0) {
+ long percent = progress * 100 / size;
+ summary = getContext().getString(R.string.download_paused_percent, percent);
+ } else {
+ summary = getContext().getString(R.string.download_paused);
+ }
+ } else {
+ summary = getContext().getString(R.string.download_queued);
+ }
break;
case DownloadManager.STATUS_PENDING:
summary = getContext().getString(R.string.download_queued);
break;
case DownloadManager.STATUS_RUNNING:
- final long progress = cursor.getLong(cursor.getColumnIndexOrThrow(
- DownloadManager.COLUMN_BYTES_DOWNLOADED_SO_FAR));
if (size > 0) {
String percent =
NumberFormat.getPercentInstance().format((double) progress / size);
diff --git a/src/com/android/providers/downloads/DownloadThread.java b/src/com/android/providers/downloads/DownloadThread.java
index bc7997f..15b1729 100644
--- a/src/com/android/providers/downloads/DownloadThread.java
+++ b/src/com/android/providers/downloads/DownloadThread.java
@@ -29,6 +29,7 @@ import static android.provider.Downloads.Impl.STATUS_FILE_ERROR;
import static android.provider.Downloads.Impl.STATUS_HTTP_DATA_ERROR;
import static android.provider.Downloads.Impl.STATUS_INSUFFICIENT_SPACE_ERROR;
import static android.provider.Downloads.Impl.STATUS_PAUSED_BY_APP;
+import static android.provider.Downloads.Impl.STATUS_PAUSED_MANUAL;
import static android.provider.Downloads.Impl.STATUS_QUEUED_FOR_WIFI;
import static android.provider.Downloads.Impl.STATUS_RUNNING;
import static android.provider.Downloads.Impl.STATUS_SUCCESS;
@@ -159,9 +160,11 @@ public class DownloadThread extends Thread {
private static final String NOT_DELETED = COLUMN_DELETED + " == '0'";
private static final String NOT_PAUSED = "(" + COLUMN_CONTROL + " IS NULL OR "
+ COLUMN_CONTROL + " != '" + CONTROL_PAUSED + "')";
+ private static final String NOT_PAUSED_MANUAL = COLUMN_STATUS + " != '"
+ + STATUS_PAUSED_MANUAL + "'";
private static final String SELECTION_VALID = NOT_CANCELED + " AND " + NOT_DELETED + " AND "
- + NOT_PAUSED;
+ + NOT_PAUSED + " AND " + NOT_PAUSED_MANUAL;
public DownloadInfoDelta(DownloadInfo info) {
mUri = info.mUri;
@@ -211,6 +214,8 @@ public class DownloadThread extends Thread {
buildContentValues(), SELECTION_VALID, null) == 0) {
if (mInfo.queryDownloadControl() == CONTROL_PAUSED) {
throw new StopRequestException(STATUS_PAUSED_BY_APP, "Download paused!");
+ } else if (mInfo.queryDownloadStatus() == STATUS_PAUSED_MANUAL) {
+ throw new StopRequestException(STATUS_PAUSED_MANUAL, "Download paused manually!");
} else {
throw new StopRequestException(STATUS_CANCELED, "Download deleted or missing!");
}
diff --git a/ui/src/com/android/providers/downloads/ui/TrampolineActivity.java b/ui/src/com/android/providers/downloads/ui/TrampolineActivity.java
index b3c0813..bc4a3c7 100644
--- a/ui/src/com/android/providers/downloads/ui/TrampolineActivity.java
+++ b/ui/src/com/android/providers/downloads/ui/TrampolineActivity.java
@@ -106,14 +106,28 @@ public class TrampolineActivity extends Activity {
Log.d(Constants.TAG, "Found " + id + " with status " + status + ", reason " + reason);
switch (status) {
case DownloadManager.STATUS_PENDING:
- case DownloadManager.STATUS_RUNNING:
sendRunningDownloadClickedBroadcast(id);
finish();
break;
+ case DownloadManager.STATUS_RUNNING:
+ // Pause and resume download manually
+ dm.pauseDownload(id);
+ finish();
+ break;
+
case DownloadManager.STATUS_PAUSED:
if (reason == DownloadManager.PAUSED_QUEUED_FOR_WIFI) {
PausedDialogFragment.show(getFragmentManager(), id, size);
+ } else if (reason == DownloadManager.PAUSED_MANUAL) {
+ // Pause and resume download manually
+ dm.resumeDownload(id);
+ Intent intent = new Intent(Constants.ACTION_RESUME);
+ intent.setClassName("com.android.providers.downloads",
+ "com.android.providers.downloads.DownloadReceiver");
+ intent.putExtra(DownloadManager.EXTRA_DOWNLOAD_ID, id);
+ sendBroadcast(intent);
+ finish();
} else {
sendRunningDownloadClickedBroadcast(id);
finish();