summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorZhao Wei Liew <zhaoweiliew@gmail.com>2016-10-01 19:36:07 +0800
committerZhao Wei Liew <zhaoweiliew@gmail.com>2016-10-04 15:24:25 +0800
commit2696562b5a71c9b437e60f574e01aafa677e9333 (patch)
treec6babefb4a33fc872b172013debe33de7647a797
parent383964e4289280610c9e6ff646c453e22bc99d5a (diff)
downloadandroid_packages_providers_DownloadProvider-cm-14.0.tar.gz
android_packages_providers_DownloadProvider-cm-14.0.tar.bz2
android_packages_providers_DownloadProvider-cm-14.0.zip
DownloadProvider: Add support for manual pause/resumecm-14.0
Implement the following features: - Manually pause/resume individual downloads in DownloadManager - Manually pause/resume all downloads in notification Based on commit ecd609e7017b8a69688bbae25c17d878ea305f19. Change-Id: I433cdee2de8b3add0248bbb0a9d02f8da4e5bb38
-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.java72
-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, 163 insertions, 10 deletions
diff --git a/res/drawable/download_pause.xml b/res/drawable/download_pause.xml
new file mode 100644
index 00000000..c82ec923
--- /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 100318a2..3a28aafa 100644
--- a/res/values/cm_strings.xml
+++ b/res/values/cm_strings.xml
@@ -26,4 +26,20 @@
<!-- Phrase describing a time duration using hours [CHAR LIMIT=16] -->
<string name="duration_hours">%d h</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 79daeaed..6633057e 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 e6d898ed..aa0c3d04 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;
@@ -47,6 +48,7 @@ import android.util.LongSparseLongArray;
import com.android.internal.util.ArrayUtils;
+import java.lang.StringBuilder;
import java.text.NumberFormat;
import javax.annotation.concurrent.GuardedBy;
@@ -193,9 +195,30 @@ public class DownloadNotifier {
}
builder.setWhen(firstShown);
+ /**
+ * 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) {
- builder.setSmallIcon(android.R.drawable.stat_sys_download);
+ 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) {
@@ -229,6 +252,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);
@@ -327,7 +376,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 {
@@ -365,8 +416,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) {
@@ -469,7 +531,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 a0dc6947..b61ae5ec 100644
--- a/src/com/android/providers/downloads/DownloadReceiver.java
+++ b/src/com/android/providers/downloads/DownloadReceiver.java
@@ -114,6 +114,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 e0bb7cd1..1c4f903f 100644
--- a/src/com/android/providers/downloads/DownloadStorageProvider.java
+++ b/src/com/android/providers/downloads/DownloadStorageProvider.java
@@ -348,19 +348,30 @@ public class DownloadStorageProvider extends DocumentsProvider {
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:
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 != null) {
+ 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 != null) {
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 40194038..dc09d84c 100644
--- a/src/com/android/providers/downloads/DownloadThread.java
+++ b/src/com/android/providers/downloads/DownloadThread.java
@@ -26,6 +26,7 @@ import static android.provider.Downloads.Impl.STATUS_CANNOT_RESUME;
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_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;
@@ -154,9 +155,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;
@@ -206,6 +209,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 5d4e7a45..98504489 100644
--- a/ui/src/com/android/providers/downloads/ui/TrampolineActivity.java
+++ b/ui/src/com/android/providers/downloads/ui/TrampolineActivity.java
@@ -81,14 +81,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();