Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(237)

Side by Side Diff: chrome/android/java/src/org/chromium/chrome/browser/download/DownloadNotificationService.java

Issue 2861863002: offline_items_collection : Added helper class to determine progress (Closed)
Patch Set: comments Created 3 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 // Copyright 2015 The Chromium Authors. All rights reserved. 1 // Copyright 2015 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 package org.chromium.chrome.browser.download; 5 package org.chromium.chrome.browser.download;
6 6
7 import android.annotation.TargetApi; 7 import android.annotation.TargetApi;
8 import android.app.DownloadManager; 8 import android.app.DownloadManager;
9 import android.app.Notification; 9 import android.app.Notification;
10 import android.app.NotificationManager; 10 import android.app.NotificationManager;
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after
49 import org.chromium.chrome.browser.notifications.ChromeNotificationBuilder; 49 import org.chromium.chrome.browser.notifications.ChromeNotificationBuilder;
50 import org.chromium.chrome.browser.notifications.NotificationBuilderFactory; 50 import org.chromium.chrome.browser.notifications.NotificationBuilderFactory;
51 import org.chromium.chrome.browser.notifications.NotificationConstants; 51 import org.chromium.chrome.browser.notifications.NotificationConstants;
52 import org.chromium.chrome.browser.notifications.NotificationUmaTracker; 52 import org.chromium.chrome.browser.notifications.NotificationUmaTracker;
53 import org.chromium.chrome.browser.notifications.channels.ChannelDefinitions; 53 import org.chromium.chrome.browser.notifications.channels.ChannelDefinitions;
54 import org.chromium.chrome.browser.offlinepages.downloads.OfflinePageDownloadBri dge; 54 import org.chromium.chrome.browser.offlinepages.downloads.OfflinePageDownloadBri dge;
55 import org.chromium.chrome.browser.profiles.Profile; 55 import org.chromium.chrome.browser.profiles.Profile;
56 import org.chromium.chrome.browser.util.IntentUtils; 56 import org.chromium.chrome.browser.util.IntentUtils;
57 import org.chromium.components.offline_items_collection.ContentId; 57 import org.chromium.components.offline_items_collection.ContentId;
58 import org.chromium.components.offline_items_collection.LegacyHelpers; 58 import org.chromium.components.offline_items_collection.LegacyHelpers;
59 import org.chromium.components.offline_items_collection.OfflineItem.Progress;
59 import org.chromium.content.browser.BrowserStartupController; 60 import org.chromium.content.browser.BrowserStartupController;
60 61
61 import java.util.ArrayList; 62 import java.util.ArrayList;
62 import java.util.List; 63 import java.util.List;
63 import java.util.concurrent.TimeUnit;
64 64
65 /** 65 /**
66 * Service responsible for creating and updating download notifications even aft er 66 * Service responsible for creating and updating download notifications even aft er
67 * Chrome gets killed. 67 * Chrome gets killed.
68 * 68 *
69 * On O and above, this service will receive {@link Service#startForeground(int, Notification)} 69 * On O and above, this service will receive {@link Service#startForeground(int, Notification)}
70 * calls when containing active downloads. The foreground notification will be the summary 70 * calls when containing active downloads. The foreground notification will be the summary
71 * notification generated by {@link DownloadNotificationService#buildSummaryNoti fication(Context)}. 71 * notification generated by {@link DownloadNotificationService#buildSummaryNoti fication(Context)}.
72 * The service will receive a {@link Service#stopForeground(boolean)} call when all active downloads 72 * The service will receive a {@link Service#stopForeground(boolean)} call when all active downloads
73 * are paused. The summary notification will be hidden when there are no other notifications in the 73 * are paused. The summary notification will be hidden when there are no other notifications in the
(...skipping 30 matching lines...) Expand all
104 private static final String TAG = "DownloadNotification"; 104 private static final String TAG = "DownloadNotification";
105 // Limit file name to 25 characters. TODO(qinmin): use different limit for d ifferent devices? 105 // Limit file name to 25 characters. TODO(qinmin): use different limit for d ifferent devices?
106 private static final int MAX_FILE_NAME_LENGTH = 25; 106 private static final int MAX_FILE_NAME_LENGTH = 25;
107 107
108 /** Notification Id starting value, to avoid conflicts from IDs used in prio r versions. */ 108 /** Notification Id starting value, to avoid conflicts from IDs used in prio r versions. */
109 109
110 private static final String EXTRA_NOTIFICATION_BUNDLE_ICON_ID = 110 private static final String EXTRA_NOTIFICATION_BUNDLE_ICON_ID =
111 "Chrome.NotificationBundleIconIdExtra"; 111 "Chrome.NotificationBundleIconIdExtra";
112 private static final int STARTING_NOTIFICATION_ID = 1000000; 112 private static final int STARTING_NOTIFICATION_ID = 1000000;
113 private static final int MAX_RESUMPTION_ATTEMPT_LEFT = 5; 113 private static final int MAX_RESUMPTION_ATTEMPT_LEFT = 5;
114 @VisibleForTesting static final long SECONDS_PER_MINUTE = TimeUnit.MINUTES.t oSeconds(1);
115 @VisibleForTesting static final long SECONDS_PER_HOUR = TimeUnit.HOURS.toSec onds(1);
116 @VisibleForTesting static final long SECONDS_PER_DAY = TimeUnit.DAYS.toSecon ds(1);
117 114
118 private static final String KEY_AUTO_RESUMPTION_ATTEMPT_LEFT = "ResumptionAt temptLeft"; 115 private static final String KEY_AUTO_RESUMPTION_ATTEMPT_LEFT = "ResumptionAt temptLeft";
119 private static final String KEY_NEXT_DOWNLOAD_NOTIFICATION_ID = "NextDownloa dNotificationId"; 116 private static final String KEY_NEXT_DOWNLOAD_NOTIFICATION_ID = "NextDownloa dNotificationId";
120 117
121 /** 118 /**
122 * An Observer interface that allows other classes to know when this class i s canceling 119 * An Observer interface that allows other classes to know when this class i s canceling
123 * downloads. 120 * downloads.
124 */ 121 */
125 public interface Observer { 122 public interface Observer {
126 /** 123 /**
(...skipping 604 matching lines...) Expand 10 before | Expand all | Expand 10 after
731 SharedPreferences SharedPrefs = ContextUtils.getAppSharedPreferences(); 728 SharedPreferences SharedPrefs = ContextUtils.getAppSharedPreferences();
732 SharedPreferences.Editor editor = SharedPrefs.edit(); 729 SharedPreferences.Editor editor = SharedPrefs.edit();
733 editor.remove(KEY_AUTO_RESUMPTION_ATTEMPT_LEFT); 730 editor.remove(KEY_AUTO_RESUMPTION_ATTEMPT_LEFT);
734 editor.apply(); 731 editor.apply();
735 } 732 }
736 733
737 /** 734 /**
738 * Adds or updates an in-progress download notification. 735 * Adds or updates an in-progress download notification.
739 * @param id The {@link ContentId} of the download. 736 * @param id The {@link ContentId} of the download.
740 * @param fileName File name of the download. 737 * @param fileName File name of the download.
741 * @param percentage Percentage completed. Value should be betw een 0 to 100 if the 738 * @param progress The current download progress.
742 * percentage can be determined, or -1 if it is unknown.
743 * @param bytesReceived Total number of bytes received. 739 * @param bytesReceived Total number of bytes received.
744 * @param timeRemainingInMillis Remaining download time in milliseconds. 740 * @param timeRemainingInMillis Remaining download time in milliseconds.
745 * @param startTime Time when download started. 741 * @param startTime Time when download started.
746 * @param isOffTheRecord Whether the download is off the record. 742 * @param isOffTheRecord Whether the download is off the record.
747 * @param canDownloadWhileMetered Whether the download can happen in metered network. 743 * @param canDownloadWhileMetered Whether the download can happen in metered network.
748 * @param isTransient Whether or not clicking on the download sh ould launch 744 * @param isTransient Whether or not clicking on the download sh ould launch
749 * downloads home. 745 * downloads home.
750 * @param icon A {@link Bitmap} to be used as the large i con for display. 746 * @param icon A {@link Bitmap} to be used as the large i con for display.
751 */ 747 */
752 @VisibleForTesting 748 @VisibleForTesting
753 public void notifyDownloadProgress(ContentId id, String fileName, int percen tage, 749 public void notifyDownloadProgress(ContentId id, String fileName, Progress p rogress,
754 long bytesReceived, long timeRemainingInMillis, long startTime, bool ean isOffTheRecord, 750 long bytesReceived, long timeRemainingInMillis, long startTime, bool ean isOffTheRecord,
755 boolean canDownloadWhileMetered, boolean isTransient, Bitmap icon) { 751 boolean canDownloadWhileMetered, boolean isTransient, Bitmap icon) {
756 updateActiveDownloadNotification(id, fileName, percentage, bytesReceived , 752 updateActiveDownloadNotification(id, fileName, progress, bytesReceived,
757 timeRemainingInMillis, startTime, isOffTheRecord, canDownloadWhi leMetered, false, 753 timeRemainingInMillis, startTime, isOffTheRecord, canDownloadWhi leMetered, false,
758 isTransient, icon); 754 isTransient, icon);
759 } 755 }
760 756
761 /** 757 /**
762 * Adds or updates a pending download notification. 758 * Adds or updates a pending download notification.
763 * @param id The {@link ContentId} of the download. 759 * @param id The {@link ContentId} of the download.
764 * @param fileName File name of the download. 760 * @param fileName File name of the download.
765 * @param isOffTheRecord Whether the download is off the record. 761 * @param isOffTheRecord Whether the download is off the record.
766 * @param canDownloadWhileMetered Whether the download can happen in metered network. 762 * @param canDownloadWhileMetered Whether the download can happen in metered network.
767 * @param isTransient Whether or not clicking on the download sh ould launch 763 * @param isTransient Whether or not clicking on the download sh ould launch
768 * downloads home. 764 * downloads home.
769 * @param icon A {@link Bitmap} to be used as the large i con for display. 765 * @param icon A {@link Bitmap} to be used as the large i con for display.
770 */ 766 */
771 private void notifyDownloadPending(ContentId id, String fileName, boolean is OffTheRecord, 767 private void notifyDownloadPending(ContentId id, String fileName, boolean is OffTheRecord,
772 boolean canDownloadWhileMetered, boolean isTransient, Bitmap icon) { 768 boolean canDownloadWhileMetered, boolean isTransient, Bitmap icon) {
773 updateActiveDownloadNotification(id, fileName, 769 updateActiveDownloadNotification(id, fileName, Progress.createIndetermin ateProgress(), 0, 0,
774 DownloadItem.INDETERMINATE_DOWNLOAD_PERCENTAGE, 0, 0, 0, isOffTh eRecord, 770 0, isOffTheRecord, canDownloadWhileMetered, true, isTransient, i con);
775 canDownloadWhileMetered, true, isTransient, icon);
776 } 771 }
777 772
778 /** 773 /**
779 * Helper method to update the notification for an active download, the down load is either in 774 * Helper method to update the notification for an active download, the down load is either in
780 * progress or pending. 775 * progress or pending.
781 * @param id The {@link ContentId} of the download. 776 * @param id The {@link ContentId} of the download.
782 * @param fileName File name of the download. 777 * @param fileName File name of the download.
783 * @param percentage Percentage completed. Value should be betw een 0 to 100 if the 778 * @param progress The current download progress.
784 * percentage can be determined, or -1 if it is unknown.
785 * @param bytesReceived Total number of bytes received. 779 * @param bytesReceived Total number of bytes received.
786 * @param timeRemainingInMillis Remaining download time in milliseconds or -1 if it is 780 * @param timeRemainingInMillis Remaining download time in milliseconds or -1 if it is
787 * unknown. 781 * unknown.
788 * @param startTime Time when download started. 782 * @param startTime Time when download started.
789 * @param isOffTheRecord Whether the download is off the record. 783 * @param isOffTheRecord Whether the download is off the record.
790 * @param canDownloadWhileMetered Whether the download can happen in metered network. 784 * @param canDownloadWhileMetered Whether the download can happen in metered network.
791 * @param isDownloadPending Whether the download is pending. 785 * @param isDownloadPending Whether the download is pending.
792 * @param isTransient Whether or not clicking on the download sh ould launch 786 * @param isTransient Whether or not clicking on the download sh ould launch
793 * downloads home. 787 * downloads home.
794 * @param icon A {@link Bitmap} to be used as the large i con for display. 788 * @param icon A {@link Bitmap} to be used as the large i con for display.
795 */ 789 */
796 private void updateActiveDownloadNotification(ContentId id, String fileName, int percentage, 790 private void updateActiveDownloadNotification(ContentId id, String fileName, Progress progress,
797 long bytesReceived, long timeRemainingInMillis, long startTime, bool ean isOffTheRecord, 791 long bytesReceived, long timeRemainingInMillis, long startTime, bool ean isOffTheRecord,
798 boolean canDownloadWhileMetered, boolean isDownloadPending, boolean isTransient, 792 boolean canDownloadWhileMetered, boolean isDownloadPending, boolean isTransient,
799 Bitmap icon) { 793 Bitmap icon) {
800 boolean indeterminate = 794 boolean indeterminate = (progress.isIndeterminate() || isDownloadPending );
801 (percentage == DownloadItem.INDETERMINATE_DOWNLOAD_PERCENTAGE) | | isDownloadPending;
802 String contentText = null; 795 String contentText = null;
803 if (isDownloadPending) { 796 if (isDownloadPending) {
804 contentText = mContext.getResources().getString(R.string.download_no tification_pending); 797 contentText = mContext.getResources().getString(R.string.download_no tification_pending);
805 } else if (indeterminate) { 798 } else if (indeterminate || timeRemainingInMillis < 0) {
806 // TODO(dimich): Enable the byte count back in M59. See bug 704049 f or more info and 799 // TODO(dimich): Enable the byte count back in M59. See bug 704049 f or more info and
807 // details of what was temporarily reverted (for M58). 800 // details of what was temporarily reverted (for M58).
808 contentText = mContext.getResources().getString(R.string.download_st arted); 801 contentText = mContext.getResources().getString(R.string.download_st arted);
809 } else { 802 } else {
810 contentText = timeRemainingInMillis < 0 803 contentText = DownloadUtils.getTimeOrFilesLeftString(
811 ? mContext.getResources().getString(R.string.download_starte d) 804 mContext, progress, timeRemainingInMillis);
812 : formatRemainingTime(mContext, timeRemainingInMillis);
813 } 805 }
814 int resId = isDownloadPending ? R.drawable.ic_download_pending 806 int resId = isDownloadPending ? R.drawable.ic_download_pending
815 : android.R.drawable.stat_sys_download; 807 : android.R.drawable.stat_sys_download;
816 ChromeNotificationBuilder builder = buildNotification(resId, fileName, c ontentText); 808 ChromeNotificationBuilder builder = buildNotification(resId, fileName, c ontentText);
817 builder.setOngoing(true); 809 builder.setOngoing(true);
818 builder.setPriority(Notification.PRIORITY_HIGH); 810 builder.setPriority(Notification.PRIORITY_HIGH);
819 811
820 // Avoid animations while the download isn't progressing. 812 // Avoid animations while the download isn't progressing.
821 if (!isDownloadPending) { 813 if (!isDownloadPending) {
822 builder.setProgress(100, percentage, indeterminate); 814 builder.setProgress(100, indeterminate ? -1 : progress.getPercentage (), indeterminate);
823 } 815 }
824 816
825 if (!indeterminate && !LegacyHelpers.isLegacyOfflinePage(id)) { 817 if (!indeterminate && !LegacyHelpers.isLegacyOfflinePage(id)) {
826 String percentText = DownloadUtils.getPercentageString(percentage); 818 String percentText = DownloadUtils.getPercentageString(progress.getP ercentage());
827 if (Build.VERSION.CODENAME.equals("N") 819 if (Build.VERSION.CODENAME.equals("N")
828 || Build.VERSION.SDK_INT > Build.VERSION_CODES.M) { 820 || Build.VERSION.SDK_INT > Build.VERSION_CODES.M) {
829 builder.setSubText(percentText); 821 builder.setSubText(percentText);
830 } else { 822 } else {
831 builder.setContentInfo(percentText); 823 builder.setContentInfo(percentText);
832 } 824 }
833 } 825 }
834 int notificationId = getNotificationId(id); 826 int notificationId = getNotificationId(id);
835 if (startTime > 0) builder.setWhen(startTime); 827 if (startTime > 0) builder.setWhen(startTime);
836 828
(...skipping 579 matching lines...) Expand 10 before | Expand all | Expand 10 after
1416 mDownloadSharedPreferenceHelper.getDownloadSharedPreferenceEntry (id); 1408 mDownloadSharedPreferenceHelper.getDownloadSharedPreferenceEntry (id);
1417 if (entry != null) return entry.notificationId; 1409 if (entry != null) return entry.notificationId;
1418 int notificationId = mNextNotificationId; 1410 int notificationId = mNextNotificationId;
1419 mNextNotificationId = mNextNotificationId == Integer.MAX_VALUE 1411 mNextNotificationId = mNextNotificationId == Integer.MAX_VALUE
1420 ? STARTING_NOTIFICATION_ID : mNextNotificationId + 1; 1412 ? STARTING_NOTIFICATION_ID : mNextNotificationId + 1;
1421 SharedPreferences.Editor editor = mSharedPrefs.edit(); 1413 SharedPreferences.Editor editor = mSharedPrefs.edit();
1422 editor.putInt(KEY_NEXT_DOWNLOAD_NOTIFICATION_ID, mNextNotificationId); 1414 editor.putInt(KEY_NEXT_DOWNLOAD_NOTIFICATION_ID, mNextNotificationId);
1423 editor.apply(); 1415 editor.apply();
1424 return notificationId; 1416 return notificationId;
1425 } 1417 }
1426
1427 /**
1428 * Format remaining time for the given millis, in the following format:
1429 * 5 hours; will include 1 unit, can go down to seconds precision.
1430 * This is similar to what android.java.text.Formatter.formatShortElapsedTim e() does. Don't use
1431 * ui::TimeFormat::Simple() as it is very expensive.
1432 *
1433 * @param context the application context.
1434 * @param millis the remaining time in milli seconds.
1435 * @return the formatted remaining time.
1436 */
1437 public static String formatRemainingTime(Context context, long millis) {
1438 long secondsLong = millis / 1000;
1439
1440 int days = 0;
1441 int hours = 0;
1442 int minutes = 0;
1443 if (secondsLong >= SECONDS_PER_DAY) {
1444 days = (int) (secondsLong / SECONDS_PER_DAY);
1445 secondsLong -= days * SECONDS_PER_DAY;
1446 }
1447 if (secondsLong >= SECONDS_PER_HOUR) {
1448 hours = (int) (secondsLong / SECONDS_PER_HOUR);
1449 secondsLong -= hours * SECONDS_PER_HOUR;
1450 }
1451 if (secondsLong >= SECONDS_PER_MINUTE) {
1452 minutes = (int) (secondsLong / SECONDS_PER_MINUTE);
1453 secondsLong -= minutes * SECONDS_PER_MINUTE;
1454 }
1455 int seconds = (int) secondsLong;
1456
1457 if (days >= 2) {
1458 days += (hours + 12) / 24;
1459 return context.getString(R.string.remaining_duration_days, days);
1460 } else if (days > 0) {
1461 return context.getString(R.string.remaining_duration_one_day);
1462 } else if (hours >= 2) {
1463 hours += (minutes + 30) / 60;
1464 return context.getString(R.string.remaining_duration_hours, hours);
1465 } else if (hours > 0) {
1466 return context.getString(R.string.remaining_duration_one_hour);
1467 } else if (minutes >= 2) {
1468 minutes += (seconds + 30) / 60;
1469 return context.getString(R.string.remaining_duration_minutes, minute s);
1470 } else if (minutes > 0) {
1471 return context.getString(R.string.remaining_duration_one_minute);
1472 } else if (seconds == 1) {
1473 return context.getString(R.string.remaining_duration_one_second);
1474 } else {
1475 return context.getString(R.string.remaining_duration_seconds, second s);
1476 }
1477 }
1478 } 1418 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698