diff options
8 files changed, 109 insertions, 11 deletions
diff --git a/res/drawable/download_pause.xml b/res/drawable/download_pause.xml new file mode 100644 index 00000000..3a862d22 --- /dev/null +++ b/res/drawable/download_pause.xml @@ -0,0 +1,15 @@ +<?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 fb6f06c3..b850b25e 100644 --- a/res/values/cm_strings.xml +++ b/res/values/cm_strings.xml @@ -16,4 +16,12 @@ --> <resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> <string name="download_speed_text"><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, <xliff:g id="number">%d</xliff:g><xliff:g id="percent">%%</xliff:g></string> + <!-- Representation of download progress percentage when queued. [CHAR LIMIT=24] --> + <string name="download_queued_percent">Queued, <xliff:g id="number">%d</xliff:g><xliff:g id="percent">%%</xliff:g></string> </resources> diff --git a/src/com/android/providers/downloads/Constants.java b/src/com/android/providers/downloads/Constants.java index 7b8fcd24..a10cb514 100644 --- a/src/com/android/providers/downloads/Constants.java +++ b/src/com/android/providers/downloads/Constants.java @@ -57,6 +57,9 @@ 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 choosing to resume the paused download */ + public static final String ACTION_RESUME = "android.intent.action.DOWNLOAD_RESUME"; + /** 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 3af97463..5e1b9de2 100644 --- a/src/com/android/providers/downloads/DownloadNotifier.java +++ b/src/com/android/providers/downloads/DownloadNotifier.java @@ -154,9 +154,25 @@ public class DownloadNotifier { } builder.setWhen(firstShown); + // Check paused status about these downloads. If exists, will + // update icon and content title/content text in notification. + boolean hasPausedStatus = false; + int pausedStatus = -1; + for (DownloadInfo info : cluster) { + if (isPausedStatus(info.mStatus)) { + hasPausedStatus = true; + pausedStatus = info.mStatus; + break; + } + } + // Show relevant icon if (type == TYPE_ACTIVE) { - builder.setSmallIcon(android.R.drawable.stat_sys_download); + if (hasPausedStatus) { + 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) { @@ -264,7 +280,13 @@ public class DownloadNotifier { builder.setContentTitle(getDownloadTitle(res, info)); if (type == TYPE_ACTIVE) { - if (speedAsSizeText != null) { + if (hasPausedStatus) { + if (pausedStatus == Downloads.Impl.STATUS_PAUSED_BY_MANUAL) { + builder.setContentText(res.getText(R.string.download_paused)); + } else { + builder.setContentText(res.getText(R.string.download_queued)); + } + } else if (speedAsSizeText != null) { builder.setContentText(res.getString(R.string.download_speed_text, remainingText, speedAsSizeText)); } @@ -293,8 +315,12 @@ public class DownloadNotifier { } if (type == TYPE_ACTIVE) { - builder.setContentTitle(res.getQuantityString( - R.plurals.notif_summary_active, cluster.size(), cluster.size())); + if (hasPausedStatus) { + builder.setContentTitle(res.getString(R.string.download_queued)); + } else { + builder.setContentTitle(res.getQuantityString( + R.plurals.notif_summary_active, cluster.size(), cluster.size())); + } builder.setContentText(remainingText); builder.setContentInfo(res.getString(R.string.download_speed_text, percentText, speedAsSizeText)); @@ -380,7 +406,7 @@ public class DownloadNotifier { } private static boolean isActiveAndVisible(DownloadInfo download) { - return download.mStatus == STATUS_RUNNING && + return Downloads.Impl.isStatusInformational(download.mStatus) && (download.mVisibility == VISIBILITY_VISIBLE || download.mVisibility == VISIBILITY_VISIBLE_NOTIFY_COMPLETED); } @@ -390,4 +416,9 @@ public class DownloadNotifier { (download.mVisibility == VISIBILITY_VISIBLE_NOTIFY_COMPLETED || download.mVisibility == VISIBILITY_VISIBLE_NOTIFY_ONLY_COMPLETION); } + + private static boolean isPausedStatus(int status) { + return status == Downloads.Impl.STATUS_WAITING_FOR_NETWORK || + status == Downloads.Impl.STATUS_PAUSED_BY_MANUAL; + } } diff --git a/src/com/android/providers/downloads/DownloadReceiver.java b/src/com/android/providers/downloads/DownloadReceiver.java index 28e2a673..d2872356 100644 --- a/src/com/android/providers/downloads/DownloadReceiver.java +++ b/src/com/android/providers/downloads/DownloadReceiver.java @@ -87,7 +87,8 @@ public class DownloadReceiver extends BroadcastReceiver { } }); - } else if (Constants.ACTION_RETRY.equals(action)) { + } else if (Constants.ACTION_RETRY.equals(action) || + Constants.ACTION_RESUME.equals(action)) { startService(context); } else if (Constants.ACTION_OPEN.equals(action) diff --git a/src/com/android/providers/downloads/DownloadStorageProvider.java b/src/com/android/providers/downloads/DownloadStorageProvider.java index 1b5dc844..69efab31 100644 --- a/src/com/android/providers/downloads/DownloadStorageProvider.java +++ b/src/com/android/providers/downloads/DownloadStorageProvider.java @@ -303,20 +303,31 @@ public class DownloadStorageProvider extends DocumentsProvider { size = null; } + final long progress = cursor.getLong(cursor.getColumnIndexOrThrow( + DownloadManager.COLUMN_BYTES_DOWNLOADED_SO_FAR)); final int status = cursor.getInt( cursor.getColumnIndexOrThrow(DownloadManager.COLUMN_STATUS)); + final int reason = cursor.getInt( + cursor.getColumnIndexOrThrow(DownloadManager.COLUMN_REASON)); switch (status) { case DownloadManager.STATUS_SUCCESSFUL: break; case DownloadManager.STATUS_PAUSED: - summary = getContext().getString(R.string.download_queued); + if (size != null) { + final long percent = progress * 100 / size; + summary = (reason == DownloadManager.PAUSED_BY_MANUAL) ? + getContext().getString(R.string.download_paused_percent, percent) : + getContext().getString(R.string.download_queued_percent, percent); + } else { + summary = (reason == DownloadManager.PAUSED_BY_MANUAL) ? + getContext().getString(R.string.download_paused) : + 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 325b4eee..c905e25a 100644 --- a/src/com/android/providers/downloads/DownloadThread.java +++ b/src/com/android/providers/downloads/DownloadThread.java @@ -116,6 +116,11 @@ public class DownloadThread implements Runnable { private volatile boolean mPolicyDirty; + // Add for carrier feature - download breakpoint continuing. + // Support continuing download after the download is broken + // although HTTP Server doesn't contain etag in its response. + private final static String QRD_ETAG = "qrd_magic_etag"; + /** * Local changes to {@link DownloadInfo}. These are kept local to avoid * racing with the thread that updates based on change notifications. @@ -686,6 +691,11 @@ public class DownloadThread implements Runnable { if (mInfo.mStatus == Downloads.Impl.STATUS_CANCELED || mInfo.mDeleted) { throw new StopRequestException(Downloads.Impl.STATUS_CANCELED, "download canceled"); } + if (mInfo.mStatus == Downloads.Impl.STATUS_PAUSED_BY_MANUAL) { + // user pauses the download by manual, here send exception and stop data transfer. + throw new StopRequestException(Downloads.Impl.STATUS_PAUSED_BY_MANUAL, + "download paused by manual"); + } } // if policy has been changed, trigger connectivity check @@ -767,6 +777,10 @@ public class DownloadThread implements Runnable { mInfoDelta.mETag = conn.getHeaderField("ETag"); + if (mInfoDelta.mETag == null) { + mInfoDelta.mETag = QRD_ETAG; + } + mInfoDelta.writeToDatabaseOrThrow(); // Check connectivity again now that we know the total size @@ -812,7 +826,9 @@ public class DownloadThread implements Runnable { if (resuming) { if (mInfoDelta.mETag != null) { - conn.addRequestProperty("If-Match", mInfoDelta.mETag); + if (!mInfoDelta.mETag.equals(QRD_ETAG)) { + conn.addRequestProperty("If-Match", mInfoDelta.mETag); + } } conn.addRequestProperty("Range", "bytes=" + mInfoDelta.mCurrentBytes + "-"); } diff --git a/ui/src/com/android/providers/downloads/ui/TrampolineActivity.java b/ui/src/com/android/providers/downloads/ui/TrampolineActivity.java index 6bcff73b..8ada01b0 100644 --- a/ui/src/com/android/providers/downloads/ui/TrampolineActivity.java +++ b/ui/src/com/android/providers/downloads/ui/TrampolineActivity.java @@ -77,14 +77,27 @@ 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: + // Add for carrier feature - pause and resume download by manual. + dm.pauseDownload(id); + finish(); + break; + case DownloadManager.STATUS_PAUSED: if (reason == DownloadManager.PAUSED_QUEUED_FOR_WIFI) { PausedDialogFragment.show(getFragmentManager(), id); + } else if (reason == DownloadManager.PAUSED_BY_MANUAL) { + // Add for carrier feature - pause and resume download by manual. + dm.resumeDownload(id); + Intent intent = new Intent(Constants.ACTION_RESUME); + intent.setClassName("com.android.providers.downloads", + "com.android.providers.downloads.DownloadReceiver"); + sendBroadcast(intent); + finish(); } else { sendRunningDownloadClickedBroadcast(id); finish(); |