| Index: chrome/browser/chromeos/login/update_screen.cc
|
| diff --git a/chrome/browser/chromeos/login/update_screen.cc b/chrome/browser/chromeos/login/update_screen.cc
|
| index 4f3d7b4afc0babbdd2c6bd7cdc8b1d65ec794fd5..39dbb3fd44cd21b959b01c9b7e5af7539fd7f810 100644
|
| --- a/chrome/browser/chromeos/login/update_screen.cc
|
| +++ b/chrome/browser/chromeos/login/update_screen.cc
|
| @@ -4,6 +4,8 @@
|
|
|
| #include "chrome/browser/chromeos/login/update_screen.h"
|
|
|
| +#include <algorithm>
|
| +
|
| #include "base/bind.h"
|
| #include "base/file_util.h"
|
| #include "base/logging.h"
|
| @@ -39,6 +41,23 @@ const int kUpdateScreenHeight = 305;
|
|
|
| const char kUpdateDeadlineFile[] = "/tmp/update-check-response-deadline";
|
|
|
| +// Minimum timestep between two consecutive measurements for the
|
| +// download rate.
|
| +const base::TimeDelta kMinTimeStep = base::TimeDelta::FromSeconds(1);
|
| +
|
| +// Minimum allowed progress between two consecutive ETAs.
|
| +const double kMinProgressStep = 1e-3;
|
| +
|
| +// Smooth factor that is used for the average downloading speed
|
| +// estimation.
|
| +const double kDownloadSpeedSmoothFactor = 0.005;
|
| +
|
| +// Minumum allowed value for the average downloading speed.
|
| +const double kDownloadAverageSpeedDropBound = 1e-8;
|
| +
|
| +// An upper bound for possible downloading time left estimations.
|
| +const double kMaxTimeLeft = 24 * 60 * 60;
|
| +
|
| // Invoked from call to RequestUpdateCheck upon completion of the DBus call.
|
| void StartUpdateCallback(UpdateScreen* screen,
|
| UpdateEngineClient::UpdateCheckResult result) {
|
| @@ -107,6 +126,7 @@ void UpdateScreen::UpdateStatusChanged(
|
| case UpdateEngineClient::UPDATE_STATUS_UPDATE_AVAILABLE:
|
| MakeSureScreenIsShown();
|
| actor_->SetProgress(kBeforeDownloadProgress);
|
| + actor_->ShowEstimatedTimeLeft(false);
|
| if (!HasCriticalUpdate()) {
|
| LOG(INFO) << "Noncritical update available: "
|
| << status.new_version;
|
| @@ -125,6 +145,11 @@ void UpdateScreen::UpdateStatusChanged(
|
| // Because update engine doesn't send UPDATE_STATUS_UPDATE_AVAILABLE
|
| // we need to is update critical on first downloading notification.
|
| is_downloading_update_ = true;
|
| + download_start_time_ = download_last_time_ = base::Time::Now();
|
| + download_start_progress_ = status.download_progress;
|
| + download_last_progress_ = status.download_progress;
|
| + is_download_average_speed_computed_ = false;
|
| + download_average_speed_ = 0.0;
|
| if (!HasCriticalUpdate()) {
|
| LOG(INFO) << "Non-critical update available: "
|
| << status.new_version;
|
| @@ -136,24 +161,25 @@ void UpdateScreen::UpdateStatusChanged(
|
| actor_->ShowCurtain(false);
|
| }
|
| }
|
| - int download_progress = static_cast<int>(
|
| - status.download_progress * kDownloadProgressIncrement);
|
| - actor_->SetProgress(kBeforeDownloadProgress + download_progress);
|
| + UpdateDownloadingStats(status);
|
| }
|
| break;
|
| case UpdateEngineClient::UPDATE_STATUS_VERIFYING:
|
| MakeSureScreenIsShown();
|
| actor_->SetProgress(kBeforeVerifyingProgress);
|
| + actor_->ShowEstimatedTimeLeft(false);
|
| break;
|
| case UpdateEngineClient::UPDATE_STATUS_FINALIZING:
|
| MakeSureScreenIsShown();
|
| actor_->SetProgress(kBeforeFinalizingProgress);
|
| + actor_->ShowEstimatedTimeLeft(false);
|
| break;
|
| case UpdateEngineClient::UPDATE_STATUS_UPDATED_NEED_REBOOT:
|
| MakeSureScreenIsShown();
|
| // Make sure that first OOBE stage won't be shown after reboot.
|
| WizardController::MarkOobeCompleted();
|
| actor_->SetProgress(kProgressComplete);
|
| + actor_->ShowEstimatedTimeLeft(false);
|
| if (HasCriticalUpdate()) {
|
| actor_->ShowCurtain(false);
|
| VLOG(1) << "Initiate reboot after update";
|
| @@ -276,6 +302,55 @@ void UpdateScreen::SetIgnoreIdleStatus(bool ignore_idle_status) {
|
| ignore_idle_status_ = ignore_idle_status;
|
| }
|
|
|
| +void UpdateScreen::UpdateDownloadingStats(
|
| + const UpdateEngineClient::Status& status) {
|
| + base::Time download_current_time = base::Time::Now();
|
| + if (download_current_time >= download_last_time_ + kMinTimeStep &&
|
| + status.download_progress >=
|
| + download_last_progress_ + kMinProgressStep) {
|
| + // Estimate downloading rate.
|
| + double progress_delta =
|
| + std::max(status.download_progress - download_last_progress_, 0.0);
|
| + double time_delta =
|
| + (download_current_time - download_last_time_).InSecondsF();
|
| + double download_rate = status.new_size * progress_delta / time_delta;
|
| +
|
| + download_last_time_ = download_current_time;
|
| + download_last_progress_ = status.download_progress;
|
| +
|
| + // Estimate time left.
|
| + double progress_left = std::max(1.0 - status.download_progress, 0.0);
|
| + if (!is_download_average_speed_computed_) {
|
| + download_average_speed_ = download_rate;
|
| + is_download_average_speed_computed_ = true;
|
| + }
|
| + download_average_speed_ =
|
| + kDownloadSpeedSmoothFactor * download_rate +
|
| + (1.0 - kDownloadSpeedSmoothFactor) * download_average_speed_;
|
| + if (download_average_speed_ < kDownloadAverageSpeedDropBound) {
|
| + time_delta =
|
| + (download_current_time - download_start_time_).InSecondsF();
|
| + download_average_speed_ =
|
| + status.new_size *
|
| + (status.download_progress - download_start_progress_) /
|
| + time_delta;
|
| + }
|
| + double work_left = progress_left * status.new_size;
|
| + double time_left = work_left / download_average_speed_;
|
| + // |time_left| may be large enough or even +infinity. So we must
|
| + // |bound possible estimations.
|
| + time_left = std::min(time_left, kMaxTimeLeft);
|
| +
|
| + actor_->ShowEstimatedTimeLeft(true);
|
| + actor_->SetEstimatedTimeLeft(
|
| + base::TimeDelta::FromSeconds(static_cast<int64>(time_left)));
|
| + }
|
| +
|
| + int download_progress = static_cast<int>(
|
| + status.download_progress * kDownloadProgressIncrement);
|
| + actor_->SetProgress(kBeforeDownloadProgress + download_progress);
|
| +}
|
| +
|
| bool UpdateScreen::HasCriticalUpdate() {
|
| if (is_ignore_update_deadlines_)
|
| return true;
|
|
|