//
// Copyright (C) 2012 The Android Open Source Project
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//      http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//

#include "update_engine/update_attempter.h"

#include <stdint.h>

#include <algorithm>
#include <memory>
#include <set>
#include <string>
#include <utility>
#include <vector>

#include <base/bind.h>
#include <base/files/file_util.h>
#include <base/logging.h>
#include <base/rand_util.h>
#include <base/strings/string_util.h>
#include <base/strings/stringprintf.h>
#include <brillo/bind_lambda.h>
#include <brillo/data_encoding.h>
#include <brillo/errors/error_codes.h>
#include <brillo/make_unique_ptr.h>
#include <brillo/message_loops/message_loop.h>
#include <policy/device_policy.h>
#include <policy/libpolicy.h>
#include <update_engine/dbus-constants.h>

#include "update_engine/certificate_checker.h"
#include "update_engine/common/boot_control_interface.h"
#include "update_engine/common/clock_interface.h"
#include "update_engine/common/constants.h"
#include "update_engine/common/hardware_interface.h"
#include "update_engine/common/platform_constants.h"
#include "update_engine/common/prefs_interface.h"
#include "update_engine/common/subprocess.h"
#include "update_engine/common/utils.h"
#include "update_engine/libcurl_http_fetcher.h"
#include "update_engine/metrics_reporter_interface.h"
#include "update_engine/omaha_request_action.h"
#include "update_engine/omaha_request_params.h"
#include "update_engine/omaha_response_handler_action.h"
#include "update_engine/p2p_manager.h"
#include "update_engine/payload_consumer/download_action.h"
#include "update_engine/payload_consumer/filesystem_verifier_action.h"
#include "update_engine/payload_consumer/postinstall_runner_action.h"
#include "update_engine/payload_state_interface.h"
#include "update_engine/power_manager_interface.h"
#include "update_engine/system_state.h"
#include "update_engine/update_manager/policy.h"
#include "update_engine/update_manager/update_manager.h"
#include "update_engine/update_status_utils.h"

using base::Bind;
using base::Callback;
using base::Time;
using base::TimeDelta;
using base::TimeTicks;
using brillo::MessageLoop;
using chromeos_update_manager::EvalStatus;
using chromeos_update_manager::Policy;
using chromeos_update_manager::UpdateCheckParams;
using std::set;
using std::shared_ptr;
using std::string;
using std::vector;
using update_engine::UpdateAttemptFlags;
using update_engine::UpdateEngineStatus;

namespace chromeos_update_engine {

const int UpdateAttempter::kMaxDeltaUpdateFailures = 3;

namespace {
const int kMaxConsecutiveObeyProxyRequests = 20;

// Minimum threshold to broadcast an status update in progress and time.
const double kBroadcastThresholdProgress = 0.01;  // 1%
const int kBroadcastThresholdSeconds = 10;

// By default autest bypasses scattering. If we want to test scattering,
// use kScheduledAUTestURLRequest. The URL used is same in both cases, but
// different params are passed to CheckForUpdate().
const char kAUTestURLRequest[] = "autest";
const char kScheduledAUTestURLRequest[] = "autest-scheduled";
}  // namespace

// Turns a generic ErrorCode::kError to a generic error code specific
// to |action| (e.g., ErrorCode::kFilesystemVerifierError). If |code| is
// not ErrorCode::kError, or the action is not matched, returns |code|
// unchanged.
ErrorCode GetErrorCodeForAction(AbstractAction* action,
                                     ErrorCode code) {
  if (code != ErrorCode::kError)
    return code;

  const string type = action->Type();
  if (type == OmahaRequestAction::StaticType())
    return ErrorCode::kOmahaRequestError;
  if (type == OmahaResponseHandlerAction::StaticType())
    return ErrorCode::kOmahaResponseHandlerError;
  if (type == FilesystemVerifierAction::StaticType())
    return ErrorCode::kFilesystemVerifierError;
  if (type == PostinstallRunnerAction::StaticType())
    return ErrorCode::kPostinstallRunnerError;

  return code;
}

UpdateAttempter::UpdateAttempter(
    SystemState* system_state,
    CertificateChecker* cert_checker,
    org::chromium::NetworkProxyServiceInterfaceProxyInterface*
        network_proxy_service_proxy)
    : processor_(new ActionProcessor()),
      system_state_(system_state),
#if USE_CHROME_NETWORK_PROXY
      cert_checker_(cert_checker),
      chrome_proxy_resolver_(network_proxy_service_proxy) {
#else
      cert_checker_(cert_checker) {
#endif  // USE_CHROME_NETWORK_PROXY
}

UpdateAttempter::~UpdateAttempter() {
  // CertificateChecker might not be initialized in unittests.
  if (cert_checker_)
    cert_checker_->SetObserver(nullptr);
  // Release ourselves as the ActionProcessor's delegate to prevent
  // re-scheduling the updates due to the processing stopped.
  processor_->set_delegate(nullptr);
}

void UpdateAttempter::Init() {
  // Pulling from the SystemState can only be done after construction, since
  // this is an aggregate of various objects (such as the UpdateAttempter),
  // which requires them all to be constructed prior to it being used.
  prefs_ = system_state_->prefs();
  omaha_request_params_ = system_state_->request_params();

  if (cert_checker_)
    cert_checker_->SetObserver(this);

  // In case of update_engine restart without a reboot we need to restore the
  // reboot needed state.
  if (GetBootTimeAtUpdate(nullptr))
    status_ = UpdateStatus::UPDATED_NEED_REBOOT;
  else
    status_ = UpdateStatus::IDLE;
}

void UpdateAttempter::ScheduleUpdates() {
  if (IsUpdateRunningOrScheduled())
    return;

  chromeos_update_manager::UpdateManager* const update_manager =
      system_state_->update_manager();
  CHECK(update_manager);
  Callback<void(EvalStatus, const UpdateCheckParams&)> callback = Bind(
      &UpdateAttempter::OnUpdateScheduled, base::Unretained(this));
  // We limit the async policy request to a reasonably short time, to avoid a
  // starvation due to a transient bug.
  update_manager->AsyncPolicyRequest(callback, &Policy::UpdateCheckAllowed);
  waiting_for_scheduled_check_ = true;
}

void UpdateAttempter::CertificateChecked(ServerToCheck server_to_check,
                                         CertificateCheckResult result) {
  system_state_->metrics_reporter()->ReportCertificateCheckMetrics(
      server_to_check, result);
}

bool UpdateAttempter::CheckAndReportDailyMetrics() {
  int64_t stored_value;
  Time now = system_state_->clock()->GetWallclockTime();
  if (system_state_->prefs()->Exists(kPrefsDailyMetricsLastReportedAt) &&
      system_state_->prefs()->GetInt64(kPrefsDailyMetricsLastReportedAt,
                                       &stored_value)) {
    Time last_reported_at = Time::FromInternalValue(stored_value);
    TimeDelta time_reported_since = now - last_reported_at;
    if (time_reported_since.InSeconds() < 0) {
      LOG(WARNING) << "Last reported daily metrics "
                   << utils::FormatTimeDelta(time_reported_since) << " ago "
                   << "which is negative. Either the system clock is wrong or "
                   << "the kPrefsDailyMetricsLastReportedAt state variable "
                   << "is wrong.";
      // In this case, report daily metrics to reset.
    } else {
      if (time_reported_since.InSeconds() < 24*60*60) {
        LOG(INFO) << "Last reported daily metrics "
                  << utils::FormatTimeDelta(time_reported_since) << " ago.";
        return false;
      }
      LOG(INFO) << "Last reported daily metrics "
                << utils::FormatTimeDelta(time_reported_since) << " ago, "
                << "which is more than 24 hours ago.";
    }
  }

  LOG(INFO) << "Reporting daily metrics.";
  system_state_->prefs()->SetInt64(kPrefsDailyMetricsLastReportedAt,
                                   now.ToInternalValue());

  ReportOSAge();

  return true;
}

void UpdateAttempter::ReportOSAge() {
  struct stat sb;

  if (system_state_ == nullptr)
    return;

  if (stat("/etc/lsb-release", &sb) != 0) {
    PLOG(ERROR) << "Error getting file status for /etc/lsb-release "
                << "(Note: this may happen in some unit tests)";
    return;
  }

  Time lsb_release_timestamp = utils::TimeFromStructTimespec(&sb.st_ctim);
  Time now = system_state_->clock()->GetWallclockTime();
  TimeDelta age = now - lsb_release_timestamp;
  if (age.InSeconds() < 0) {
    LOG(ERROR) << "The OS age (" << utils::FormatTimeDelta(age)
               << ") is negative. Maybe the clock is wrong? "
               << "(Note: this may happen in some unit tests.)";
    return;
  }

  system_state_->metrics_reporter()->ReportDailyMetrics(age);
}

void UpdateAttempter::Update(const string& app_version,
                             const string& omaha_url,
                             const string& target_channel,
                             const string& target_version_prefix,
                             bool obey_proxies,
                             bool interactive) {
  // This is normally called frequently enough so it's appropriate to use as a
  // hook for reporting daily metrics.
  // TODO(garnold) This should be hooked to a separate (reliable and consistent)
  // timeout event.
  CheckAndReportDailyMetrics();

  // Notify of the new update attempt, clearing prior interactive requests.
  if (forced_update_pending_callback_.get())
    forced_update_pending_callback_->Run(false, false);

  fake_update_success_ = false;
  if (status_ == UpdateStatus::UPDATED_NEED_REBOOT) {
    // Although we have applied an update, we still want to ping Omaha
    // to ensure the number of active statistics is accurate.
    //
    // Also convey to the UpdateEngine.Check.Result metric that we're
    // not performing an update check because of this.
    LOG(INFO) << "Not updating b/c we already updated and we're waiting for "
              << "reboot, we'll ping Omaha instead";
    system_state_->metrics_reporter()->ReportUpdateCheckMetrics(
        system_state_,
        metrics::CheckResult::kRebootPending,
        metrics::CheckReaction::kUnset,
        metrics::DownloadErrorCode::kUnset);
    PingOmaha();
    return;
  }
  if (status_ != UpdateStatus::IDLE) {
    // Update in progress. Do nothing
    return;
  }

  if (!CalculateUpdateParams(app_version,
                             omaha_url,
                             target_channel,
                             target_version_prefix,
                             obey_proxies,
                             interactive)) {
    return;
  }

  BuildUpdateActions(interactive);

  SetStatusAndNotify(UpdateStatus::CHECKING_FOR_UPDATE);

  // Update the last check time here; it may be re-updated when an Omaha
  // response is received, but this will prevent us from repeatedly scheduling
  // checks in the case where a response is not received.
  UpdateLastCheckedTime();

  // Just in case we didn't update boot flags yet, make sure they're updated
  // before any update processing starts.
  start_action_processor_ = true;
  UpdateBootFlags();
}

void UpdateAttempter::RefreshDevicePolicy() {
  // Lazy initialize the policy provider, or reload the latest policy data.
  if (!policy_provider_.get())
    policy_provider_.reset(new policy::PolicyProvider());
  policy_provider_->Reload();

  const policy::DevicePolicy* device_policy = nullptr;
  if (policy_provider_->device_policy_is_loaded())
    device_policy = &policy_provider_->GetDevicePolicy();

  if (device_policy)
    LOG(INFO) << "Device policies/settings present";
  else
    LOG(INFO) << "No device policies/settings present.";

  system_state_->set_device_policy(device_policy);
  system_state_->p2p_manager()->SetDevicePolicy(device_policy);
}

void UpdateAttempter::CalculateP2PParams(bool interactive) {
  bool use_p2p_for_downloading = false;
  bool use_p2p_for_sharing = false;

  // Never use p2p for downloading in interactive checks unless the
  // developer has opted in for it via a marker file.
  //
  // (Why would a developer want to opt in? If he's working on the
  // update_engine or p2p codebases so he can actually test his
  // code.).

  if (system_state_ != nullptr) {
    if (!system_state_->p2p_manager()->IsP2PEnabled()) {
      LOG(INFO) << "p2p is not enabled - disallowing p2p for both"
                << " downloading and sharing.";
    } else {
      // Allow p2p for sharing, even in interactive checks.
      use_p2p_for_sharing = true;
      if (!interactive) {
        LOG(INFO) << "Non-interactive check - allowing p2p for downloading";
        use_p2p_for_downloading = true;
      } else {
        LOG(INFO) << "Forcibly disabling use of p2p for downloading "
                  << "since this update attempt is interactive.";
      }
    }
  }

  PayloadStateInterface* const payload_state = system_state_->payload_state();
  payload_state->SetUsingP2PForDownloading(use_p2p_for_downloading);
  payload_state->SetUsingP2PForSharing(use_p2p_for_sharing);
}

bool UpdateAttempter::CalculateUpdateParams(const string& app_version,
                                            const string& omaha_url,
                                            const string& target_channel,
                                            const string& target_version_prefix,
                                            bool obey_proxies,
                                            bool interactive) {
  http_response_code_ = 0;
  PayloadStateInterface* const payload_state = system_state_->payload_state();

  // Refresh the policy before computing all the update parameters.
  RefreshDevicePolicy();

  // Update the target version prefix.
  omaha_request_params_->set_target_version_prefix(target_version_prefix);

  CalculateScatteringParams(interactive);

  CalculateP2PParams(interactive);
  if (payload_state->GetUsingP2PForDownloading() ||
      payload_state->GetUsingP2PForSharing()) {
    // OK, p2p is to be used - start it and perform housekeeping.
    if (!StartP2PAndPerformHousekeeping()) {
      // If this fails, disable p2p for this attempt
      LOG(INFO) << "Forcibly disabling use of p2p since starting p2p or "
                << "performing housekeeping failed.";
      payload_state->SetUsingP2PForDownloading(false);
      payload_state->SetUsingP2PForSharing(false);
    }
  }

  if (!omaha_request_params_->Init(app_version,
                                   omaha_url,
                                   interactive)) {
    LOG(ERROR) << "Unable to initialize Omaha request params.";
    return false;
  }

  // Set the target channel, if one was provided.
  if (target_channel.empty()) {
    LOG(INFO) << "No target channel mandated by policy.";
  } else {
    LOG(INFO) << "Setting target channel as mandated: " << target_channel;
    // Pass in false for powerwash_allowed until we add it to the policy
    // protobuf.
    string error_message;
    if (!omaha_request_params_->SetTargetChannel(target_channel, false,
                                                 &error_message)) {
      LOG(ERROR) << "Setting the channel failed: " << error_message;
    }

    // Since this is the beginning of a new attempt, update the download
    // channel. The download channel won't be updated until the next attempt,
    // even if target channel changes meanwhile, so that how we'll know if we
    // should cancel the current download attempt if there's such a change in
    // target channel.
    omaha_request_params_->UpdateDownloadChannel();
  }

  LOG(INFO) << "target_version_prefix = "
            << omaha_request_params_->target_version_prefix()
            << ", scatter_factor_in_seconds = "
            << utils::FormatSecs(scatter_factor_.InSeconds());

  LOG(INFO) << "Wall Clock Based Wait Enabled = "
            << omaha_request_params_->wall_clock_based_wait_enabled()
            << ", Update Check Count Wait Enabled = "
            << omaha_request_params_->update_check_count_wait_enabled()
            << ", Waiting Period = " << utils::FormatSecs(
               omaha_request_params_->waiting_period().InSeconds());

  LOG(INFO) << "Use p2p For Downloading = "
            << payload_state->GetUsingP2PForDownloading()
            << ", Use p2p For Sharing = "
            << payload_state->GetUsingP2PForSharing();

  obeying_proxies_ = true;
  if (obey_proxies || proxy_manual_checks_ == 0) {
    LOG(INFO) << "forced to obey proxies";
    // If forced to obey proxies, every 20th request will not use proxies
    proxy_manual_checks_++;
    LOG(INFO) << "proxy manual checks: " << proxy_manual_checks_;
    if (proxy_manual_checks_ >= kMaxConsecutiveObeyProxyRequests) {
      proxy_manual_checks_ = 0;
      obeying_proxies_ = false;
    }
  } else if (base::RandInt(0, 4) == 0) {
    obeying_proxies_ = false;
  }
  LOG_IF(INFO, !obeying_proxies_) << "To help ensure updates work, this update "
      "check we are ignoring the proxy settings and using "
      "direct connections.";

  DisableDeltaUpdateIfNeeded();
  return true;
}

void UpdateAttempter::CalculateScatteringParams(bool interactive) {
  // Take a copy of the old scatter value before we update it, as
  // we need to update the waiting period if this value changes.
  TimeDelta old_scatter_factor = scatter_factor_;
  const policy::DevicePolicy* device_policy = system_state_->device_policy();
  if (device_policy) {
    int64_t new_scatter_factor_in_secs = 0;
    device_policy->GetScatterFactorInSeconds(&new_scatter_factor_in_secs);
    if (new_scatter_factor_in_secs < 0)  // sanitize input, just in case.
      new_scatter_factor_in_secs  = 0;
    scatter_factor_ = TimeDelta::FromSeconds(new_scatter_factor_in_secs);
  }

  bool is_scatter_enabled = false;
  if (scatter_factor_.InSeconds() == 0) {
    LOG(INFO) << "Scattering disabled since scatter factor is set to 0";
  } else if (interactive) {
    LOG(INFO) << "Scattering disabled as this is an interactive update check";
  } else if (system_state_->hardware()->IsOOBEEnabled() &&
             !system_state_->hardware()->IsOOBEComplete(nullptr)) {
    LOG(INFO) << "Scattering disabled since OOBE is enabled but not complete "
                 "yet";
  } else {
    is_scatter_enabled = true;
    LOG(INFO) << "Scattering is enabled";
  }

  if (is_scatter_enabled) {
    // This means the scattering policy is turned on.
    // Now check if we need to update the waiting period. The two cases
    // in which we'd need to update the waiting period are:
    // 1. First time in process or a scheduled check after a user-initiated one.
    //    (omaha_request_params_->waiting_period will be zero in this case).
    // 2. Admin has changed the scattering policy value.
    //    (new scattering value will be different from old one in this case).
    int64_t wait_period_in_secs = 0;
    if (omaha_request_params_->waiting_period().InSeconds() == 0) {
      // First case. Check if we have a suitable value to set for
      // the waiting period.
      if (prefs_->GetInt64(kPrefsWallClockWaitPeriod, &wait_period_in_secs) &&
          wait_period_in_secs > 0 &&
          wait_period_in_secs <= scatter_factor_.InSeconds()) {
        // This means:
        // 1. There's a persisted value for the waiting period available.
        // 2. And that persisted value is still valid.
        // So, in this case, we should reuse the persisted value instead of
        // generating a new random value to improve the chances of a good
        // distribution for scattering.
        omaha_request_params_->set_waiting_period(
          TimeDelta::FromSeconds(wait_period_in_secs));
        LOG(INFO) << "Using persisted wall-clock waiting period: " <<
            utils::FormatSecs(
                omaha_request_params_->waiting_period().InSeconds());
      } else {
        // This means there's no persisted value for the waiting period
        // available or its value is invalid given the new scatter_factor value.
        // So, we should go ahead and regenerate a new value for the
        // waiting period.
        LOG(INFO) << "Persisted value not present or not valid ("
                  << utils::FormatSecs(wait_period_in_secs)
                  << ") for wall-clock waiting period.";
        GenerateNewWaitingPeriod();
      }
    } else if (scatter_factor_ != old_scatter_factor) {
      // This means there's already a waiting period value, but we detected
      // a change in the scattering policy value. So, we should regenerate the
      // waiting period to make sure it's within the bounds of the new scatter
      // factor value.
      GenerateNewWaitingPeriod();
    } else {
      // Neither the first time scattering is enabled nor the scattering value
      // changed. Nothing to do.
      LOG(INFO) << "Keeping current wall-clock waiting period: " <<
          utils::FormatSecs(
              omaha_request_params_->waiting_period().InSeconds());
    }

    // The invariant at this point is that omaha_request_params_->waiting_period
    // is non-zero no matter which path we took above.
    LOG_IF(ERROR, omaha_request_params_->waiting_period().InSeconds() == 0)
        << "Waiting Period should NOT be zero at this point!!!";

    // Since scattering is enabled, wall clock based wait will always be
    // enabled.
    omaha_request_params_->set_wall_clock_based_wait_enabled(true);

    // If we don't have any issues in accessing the file system to update
    // the update check count value, we'll turn that on as well.
    bool decrement_succeeded = DecrementUpdateCheckCount();
    omaha_request_params_->set_update_check_count_wait_enabled(
      decrement_succeeded);
  } else {
    // This means the scattering feature is turned off or disabled for
    // this particular update check. Make sure to disable
    // all the knobs and artifacts so that we don't invoke any scattering
    // related code.
    omaha_request_params_->set_wall_clock_based_wait_enabled(false);
    omaha_request_params_->set_update_check_count_wait_enabled(false);
    omaha_request_params_->set_waiting_period(TimeDelta::FromSeconds(0));
    prefs_->Delete(kPrefsWallClockWaitPeriod);
    prefs_->Delete(kPrefsUpdateCheckCount);
    // Don't delete the UpdateFirstSeenAt file as we don't want manual checks
    // that result in no-updates (e.g. due to server side throttling) to
    // cause update starvation by having the client generate a new
    // UpdateFirstSeenAt for each scheduled check that follows a manual check.
  }
}

void UpdateAttempter::GenerateNewWaitingPeriod() {
  omaha_request_params_->set_waiting_period(TimeDelta::FromSeconds(
      base::RandInt(1, scatter_factor_.InSeconds())));

  LOG(INFO) << "Generated new wall-clock waiting period: " << utils::FormatSecs(
                omaha_request_params_->waiting_period().InSeconds());

  // Do a best-effort to persist this in all cases. Even if the persistence
  // fails, we'll still be able to scatter based on our in-memory value.
  // The persistence only helps in ensuring a good overall distribution
  // across multiple devices if they tend to reboot too often.
  system_state_->payload_state()->SetScatteringWaitPeriod(
      omaha_request_params_->waiting_period());
}

void UpdateAttempter::BuildPostInstallActions(
    InstallPlanAction* previous_action) {
  shared_ptr<PostinstallRunnerAction> postinstall_runner_action(
      new PostinstallRunnerAction(system_state_->boot_control(),
                                  system_state_->hardware()));
  postinstall_runner_action->set_delegate(this);
  actions_.push_back(shared_ptr<AbstractAction>(postinstall_runner_action));
  BondActions(previous_action,
              postinstall_runner_action.get());
}

void UpdateAttempter::BuildUpdateActions(bool interactive) {
  CHECK(!processor_->IsRunning());
  processor_->set_delegate(this);

  // Actions:
  std::unique_ptr<LibcurlHttpFetcher> update_check_fetcher(
      new LibcurlHttpFetcher(GetProxyResolver(), system_state_->hardware()));
  update_check_fetcher->set_server_to_check(ServerToCheck::kUpdate);
  // Try harder to connect to the network, esp when not interactive.
  // See comment in libcurl_http_fetcher.cc.
  update_check_fetcher->set_no_network_max_retries(interactive ? 1 : 3);
  shared_ptr<OmahaRequestAction> update_check_action(
      new OmahaRequestAction(system_state_,
                             nullptr,
                             std::move(update_check_fetcher),
                             false));
  shared_ptr<OmahaResponseHandlerAction> response_handler_action(
      new OmahaResponseHandlerAction(system_state_));

  shared_ptr<OmahaRequestAction> download_started_action(
      new OmahaRequestAction(system_state_,
                             new OmahaEvent(
                                 OmahaEvent::kTypeUpdateDownloadStarted),
                             brillo::make_unique_ptr(new LibcurlHttpFetcher(
                                 GetProxyResolver(),
                                 system_state_->hardware())),
                             false));

  LibcurlHttpFetcher* download_fetcher =
      new LibcurlHttpFetcher(GetProxyResolver(), system_state_->hardware());
  download_fetcher->set_server_to_check(ServerToCheck::kDownload);
  shared_ptr<DownloadAction> download_action(
      new DownloadAction(prefs_,
                         system_state_->boot_control(),
                         system_state_->hardware(),
                         system_state_,
                         download_fetcher));  // passes ownership
  shared_ptr<OmahaRequestAction> download_finished_action(
      new OmahaRequestAction(
          system_state_,
          new OmahaEvent(OmahaEvent::kTypeUpdateDownloadFinished),
          brillo::make_unique_ptr(
              new LibcurlHttpFetcher(GetProxyResolver(),
                                     system_state_->hardware())),
          false));
  shared_ptr<FilesystemVerifierAction> filesystem_verifier_action(
      new FilesystemVerifierAction());
  shared_ptr<OmahaRequestAction> update_complete_action(
      new OmahaRequestAction(
          system_state_,
          new OmahaEvent(OmahaEvent::kTypeUpdateComplete),
          brillo::make_unique_ptr(
              new LibcurlHttpFetcher(GetProxyResolver(),
                                     system_state_->hardware())),
          false));

  download_action->set_delegate(this);
  response_handler_action_ = response_handler_action;
  download_action_ = download_action;

  actions_.push_back(shared_ptr<AbstractAction>(update_check_action));
  actions_.push_back(shared_ptr<AbstractAction>(response_handler_action));
  actions_.push_back(shared_ptr<AbstractAction>(download_started_action));
  actions_.push_back(shared_ptr<AbstractAction>(download_action));
  actions_.push_back(shared_ptr<AbstractAction>(download_finished_action));
  actions_.push_back(shared_ptr<AbstractAction>(filesystem_verifier_action));

  // Bond them together. We have to use the leaf-types when calling
  // BondActions().
  BondActions(update_check_action.get(),
              response_handler_action.get());
  BondActions(response_handler_action.get(),
              download_action.get());
  BondActions(download_action.get(),
              filesystem_verifier_action.get());
  BuildPostInstallActions(filesystem_verifier_action.get());

  actions_.push_back(shared_ptr<AbstractAction>(update_complete_action));

  // Enqueue the actions
  for (const shared_ptr<AbstractAction>& action : actions_) {
    processor_->EnqueueAction(action.get());
  }
}

bool UpdateAttempter::Rollback(bool powerwash) {
  if (!CanRollback()) {
    return false;
  }

  // Extra check for enterprise-enrolled devices since they don't support
  // powerwash.
  if (powerwash) {
    // Enterprise-enrolled devices have an empty owner in their device policy.
    string owner;
    RefreshDevicePolicy();
    const policy::DevicePolicy* device_policy = system_state_->device_policy();
    if (device_policy && (!device_policy->GetOwner(&owner) || owner.empty())) {
      LOG(ERROR) << "Enterprise device detected. "
                 << "Cannot perform a powerwash for enterprise devices.";
      return false;
    }
  }

  processor_->set_delegate(this);

  // Initialize the default request params.
  if (!omaha_request_params_->Init("", "", true)) {
    LOG(ERROR) << "Unable to initialize Omaha request params.";
    return false;
  }

  LOG(INFO) << "Setting rollback options.";
  InstallPlan install_plan;

  install_plan.target_slot = GetRollbackSlot();
  install_plan.source_slot = system_state_->boot_control()->GetCurrentSlot();

  TEST_AND_RETURN_FALSE(
      install_plan.LoadPartitionsFromSlots(system_state_->boot_control()));
  install_plan.powerwash_required = powerwash;

  LOG(INFO) << "Using this install plan:";
  install_plan.Dump();

  shared_ptr<InstallPlanAction> install_plan_action(
      new InstallPlanAction(install_plan));
  actions_.push_back(shared_ptr<AbstractAction>(install_plan_action));

  BuildPostInstallActions(install_plan_action.get());

  // Enqueue the actions
  for (const shared_ptr<AbstractAction>& action : actions_) {
    processor_->EnqueueAction(action.get());
  }

  // Update the payload state for Rollback.
  system_state_->payload_state()->Rollback();

  SetStatusAndNotify(UpdateStatus::ATTEMPTING_ROLLBACK);

  // Just in case we didn't update boot flags yet, make sure they're updated
  // before any update processing starts. This also schedules the start of the
  // actions we just posted.
  start_action_processor_ = true;
  UpdateBootFlags();
  return true;
}

bool UpdateAttempter::CanRollback() const {
  // We can only rollback if the update_engine isn't busy and we have a valid
  // rollback partition.
  return (status_ == UpdateStatus::IDLE &&
          GetRollbackSlot() != BootControlInterface::kInvalidSlot);
}

BootControlInterface::Slot UpdateAttempter::GetRollbackSlot() const {
  LOG(INFO) << "UpdateAttempter::GetRollbackSlot";
  const unsigned int num_slots = system_state_->boot_control()->GetNumSlots();
  const BootControlInterface::Slot current_slot =
      system_state_->boot_control()->GetCurrentSlot();

  LOG(INFO) << "  Installed slots: " << num_slots;
  LOG(INFO) << "  Booted from slot: "
            << BootControlInterface::SlotName(current_slot);

  if (current_slot == BootControlInterface::kInvalidSlot || num_slots < 2) {
    LOG(INFO) << "Device is not updateable.";
    return BootControlInterface::kInvalidSlot;
  }

  vector<BootControlInterface::Slot> bootable_slots;
  for (BootControlInterface::Slot slot = 0; slot < num_slots; slot++) {
    if (slot != current_slot &&
        system_state_->boot_control()->IsSlotBootable(slot)) {
      LOG(INFO) << "Found bootable slot "
                << BootControlInterface::SlotName(slot);
      return slot;
    }
  }
  LOG(INFO) << "No other bootable slot found.";
  return BootControlInterface::kInvalidSlot;
}

bool UpdateAttempter::CheckForUpdate(const string& app_version,
                                     const string& omaha_url,
                                     UpdateAttemptFlags flags) {
  bool interactive = !(flags & UpdateAttemptFlags::kFlagNonInteractive);

  if (interactive && status_ != UpdateStatus::IDLE) {
    // An update check is either in-progress, or an update has completed and the
    // system is in UPDATED_NEED_REBOOT.  Either way, don't do an interactive
    // update at this time
    LOG(INFO) << "Refusing to do an interactive update with an update already "
                 "in progress";
    return false;
  }

  LOG(INFO) << "Forced update check requested.";
  forced_app_version_.clear();
  forced_omaha_url_.clear();

  // Certain conditions must be met to allow setting custom version and update
  // server URLs. However, kScheduledAUTestURLRequest and kAUTestURLRequest are
  // always allowed regardless of device state.
  if (IsAnyUpdateSourceAllowed()) {
    forced_app_version_ = app_version;
    forced_omaha_url_ = omaha_url;
  }
  if (omaha_url == kScheduledAUTestURLRequest) {
    forced_omaha_url_ = constants::kOmahaDefaultAUTestURL;
    // Pretend that it's not user-initiated even though it is,
    // so as to test scattering logic, etc. which get kicked off
    // only in scheduled update checks.
    interactive = false;
  } else if (omaha_url == kAUTestURLRequest) {
    forced_omaha_url_ = constants::kOmahaDefaultAUTestURL;
  }

  if (interactive) {
    // Use the passed-in update attempt flags for this update attempt instead
    // of the previously set ones.
    current_update_attempt_flags_ = flags;
    // Note: The caching for non-interactive update checks happens in
    // OnUpdateScheduled().
  }

  if (forced_update_pending_callback_.get()) {
    // Make sure that a scheduling request is made prior to calling the forced
    // update pending callback.
    ScheduleUpdates();
    forced_update_pending_callback_->Run(true, interactive);
  }

  return true;
}

bool UpdateAttempter::RebootIfNeeded() {
  if (status_ != UpdateStatus::UPDATED_NEED_REBOOT) {
    LOG(INFO) << "Reboot requested, but status is "
              << UpdateStatusToString(status_) << ", so not rebooting.";
    return false;
  }

  if (system_state_->power_manager()->RequestReboot())
    return true;

  return RebootDirectly();
}

void UpdateAttempter::WriteUpdateCompletedMarker() {
  string boot_id;
  if (!utils::GetBootId(&boot_id))
    return;
  prefs_->SetString(kPrefsUpdateCompletedOnBootId, boot_id);

  int64_t value = system_state_->clock()->GetBootTime().ToInternalValue();
  prefs_->SetInt64(kPrefsUpdateCompletedBootTime, value);
}

bool UpdateAttempter::RebootDirectly() {
  vector<string> command;
  command.push_back("/sbin/shutdown");
  command.push_back("-r");
  command.push_back("now");
  LOG(INFO) << "Running \"" << base::JoinString(command, " ") << "\"";
  int rc = 0;
  Subprocess::SynchronousExec(command, &rc, nullptr);
  return rc == 0;
}

void UpdateAttempter::OnUpdateScheduled(EvalStatus status,
                                        const UpdateCheckParams& params) {
  waiting_for_scheduled_check_ = false;

  if (status == EvalStatus::kSucceeded) {
    if (!params.updates_enabled) {
      LOG(WARNING) << "Updates permanently disabled.";
      // Signal disabled status, then switch right back to idle. This is
      // necessary for ensuring that observers waiting for a signal change will
      // actually notice one on subsequent calls. Note that we don't need to
      // re-schedule a check in this case as updates are permanently disabled;
      // further (forced) checks may still initiate a scheduling call.
      SetStatusAndNotify(UpdateStatus::DISABLED);
      SetStatusAndNotify(UpdateStatus::IDLE);
      return;
    }

    LOG(INFO) << "Running "
              << (params.is_interactive ? "interactive" : "periodic")
              << " update.";

    if (!params.is_interactive) {
      // Cache the update attempt flags that will be used by this update attempt
      // so that they can't be changed mid-way through.
      current_update_attempt_flags_ = update_attempt_flags_;
    }

    LOG(INFO) << "Update attempt flags in use = 0x" << std::hex
              << current_update_attempt_flags_;

    Update(forced_app_version_, forced_omaha_url_, params.target_channel,
           params.target_version_prefix, false, params.is_interactive);
    // Always clear the forced app_version and omaha_url after an update attempt
    // so the next update uses the defaults.
    forced_app_version_.clear();
    forced_omaha_url_.clear();
  } else {
    LOG(WARNING)
        << "Update check scheduling failed (possibly timed out); retrying.";
    ScheduleUpdates();
  }

  // This check ensures that future update checks will be or are already
  // scheduled. The check should never fail. A check failure means that there's
  // a bug that will most likely prevent further automatic update checks. It
  // seems better to crash in such cases and restart the update_engine daemon
  // into, hopefully, a known good state.
  CHECK(IsUpdateRunningOrScheduled());
}

void UpdateAttempter::UpdateLastCheckedTime() {
  last_checked_time_ = system_state_->clock()->GetWallclockTime().ToTimeT();
}

// Delegate methods:
void UpdateAttempter::ProcessingDone(const ActionProcessor* processor,
                                     ErrorCode code) {
  LOG(INFO) << "Processing Done.";
  actions_.clear();

  // Reset cpu shares back to normal.
  cpu_limiter_.StopLimiter();

  // reset the state that's only valid for a single update pass
  current_update_attempt_flags_ = UpdateAttemptFlags::kNone;

  if (status_ == UpdateStatus::REPORTING_ERROR_EVENT) {
    LOG(INFO) << "Error event sent.";

    // Inform scheduler of new status;
    SetStatusAndNotify(UpdateStatus::IDLE);
    ScheduleUpdates();

    if (!fake_update_success_) {
      return;
    }
    LOG(INFO) << "Booted from FW B and tried to install new firmware, "
        "so requesting reboot from user.";
  }

  if (code == ErrorCode::kSuccess) {
    WriteUpdateCompletedMarker();
    prefs_->SetInt64(kPrefsDeltaUpdateFailures, 0);
    prefs_->SetString(kPrefsPreviousVersion,
                      omaha_request_params_->app_version());
    DeltaPerformer::ResetUpdateProgress(prefs_, false);

    system_state_->payload_state()->UpdateSucceeded();

    // Since we're done with scattering fully at this point, this is the
    // safest point delete the state files, as we're sure that the status is
    // set to reboot (which means no more updates will be applied until reboot)
    // This deletion is required for correctness as we want the next update
    // check to re-create a new random number for the update check count.
    // Similarly, we also delete the wall-clock-wait period that was persisted
    // so that we start with a new random value for the next update check
    // after reboot so that the same device is not favored or punished in any
    // way.
    prefs_->Delete(kPrefsUpdateCheckCount);
    system_state_->payload_state()->SetScatteringWaitPeriod(TimeDelta());
    prefs_->Delete(kPrefsUpdateFirstSeenAt);

    SetStatusAndNotify(UpdateStatus::UPDATED_NEED_REBOOT);
    ScheduleUpdates();
    LOG(INFO) << "Update successfully applied, waiting to reboot.";

    // This pointer is null during rollback operations, and the stats
    // don't make much sense then anyway.
    if (response_handler_action_) {
      const InstallPlan& install_plan =
          response_handler_action_->install_plan();

      // Generate an unique payload identifier.
      string target_version_uid;
      for (const auto& payload : install_plan.payloads) {
        target_version_uid +=
            brillo::data_encoding::Base64Encode(payload.hash) + ":" +
            payload.metadata_signature + ":";
      }

      // Expect to reboot into the new version to send the proper metric during
      // next boot.
      system_state_->payload_state()->ExpectRebootInNewVersion(
          target_version_uid);
    } else {
      // If we just finished a rollback, then we expect to have no Omaha
      // response. Otherwise, it's an error.
      if (system_state_->payload_state()->GetRollbackVersion().empty()) {
        LOG(ERROR) << "Can't send metrics because expected "
            "response_handler_action_ missing.";
      }
    }
    return;
  }

  if (ScheduleErrorEventAction()) {
    return;
  }
  LOG(INFO) << "No update.";
  SetStatusAndNotify(UpdateStatus::IDLE);
  ScheduleUpdates();
}

void UpdateAttempter::ProcessingStopped(const ActionProcessor* processor) {
  // Reset cpu shares back to normal.
  cpu_limiter_.StopLimiter();
  download_progress_ = 0.0;
  SetStatusAndNotify(UpdateStatus::IDLE);
  ScheduleUpdates();
  actions_.clear();
  error_event_.reset(nullptr);
}

// Called whenever an action has finished processing, either successfully
// or otherwise.
void UpdateAttempter::ActionCompleted(ActionProcessor* processor,
                                      AbstractAction* action,
                                      ErrorCode code) {
  // Reset download progress regardless of whether or not the download
  // action succeeded. Also, get the response code from HTTP request
  // actions (update download as well as the initial update check
  // actions).
  const string type = action->Type();
  if (type == DownloadAction::StaticType()) {
    download_progress_ = 0.0;
    DownloadAction* download_action = static_cast<DownloadAction*>(action);
    http_response_code_ = download_action->GetHTTPResponseCode();
  } else if (type == OmahaRequestAction::StaticType()) {
    OmahaRequestAction* omaha_request_action =
        static_cast<OmahaRequestAction*>(action);
    // If the request is not an event, then it's the update-check.
    if (!omaha_request_action->IsEvent()) {
      http_response_code_ = omaha_request_action->GetHTTPResponseCode();

      // Record the number of consecutive failed update checks.
      if (http_response_code_ == kHttpResponseInternalServerError ||
          http_response_code_ == kHttpResponseServiceUnavailable) {
        consecutive_failed_update_checks_++;
      } else {
        consecutive_failed_update_checks_ = 0;
      }

      // Store the server-dictated poll interval, if any.
      server_dictated_poll_interval_ =
          std::max(0, omaha_request_action->GetOutputObject().poll_interval);
    }
  } else if (type == OmahaResponseHandlerAction::StaticType()) {
    // Depending on the returned error code, note that an update is available.
    if (code == ErrorCode::kOmahaUpdateDeferredPerPolicy ||
        code == ErrorCode::kSuccess) {
      // Note that the status will be updated to DOWNLOADING when some bytes
      // get actually downloaded from the server and the BytesReceived
      // callback is invoked. This avoids notifying the user that a download
      // has started in cases when the server and the client are unable to
      // initiate the download.
      CHECK(action == response_handler_action_.get());
      auto plan = response_handler_action_->install_plan();
      UpdateLastCheckedTime();
      new_version_ = plan.version;
      new_system_version_ = plan.system_version;
      new_payload_size_ = 0;
      for (const auto& payload : plan.payloads)
        new_payload_size_ += payload.size;
      cpu_limiter_.StartLimiter();
      SetStatusAndNotify(UpdateStatus::UPDATE_AVAILABLE);
    }
  }
  // General failure cases.
  if (code != ErrorCode::kSuccess) {
    // If the current state is at or past the download phase, count the failure
    // in case a switch to full update becomes necessary. Ignore network
    // transfer timeouts and failures.
    if (status_ >= UpdateStatus::DOWNLOADING &&
        code != ErrorCode::kDownloadTransferError) {
      MarkDeltaUpdateFailure();
    }
    // On failure, schedule an error event to be sent to Omaha.
    CreatePendingErrorEvent(action, code);
    return;
  }
  // Find out which action completed (successfully).
  if (type == DownloadAction::StaticType()) {
    SetStatusAndNotify(UpdateStatus::FINALIZING);
  }
}

void UpdateAttempter::BytesReceived(uint64_t bytes_progressed,
                                    uint64_t bytes_received,
                                    uint64_t total) {
  // The PayloadState keeps track of how many bytes were actually downloaded
  // from a given URL for the URL skipping logic.
  system_state_->payload_state()->DownloadProgress(bytes_progressed);

  double progress = 0;
  if (total)
    progress = static_cast<double>(bytes_received) / static_cast<double>(total);
  if (status_ != UpdateStatus::DOWNLOADING || bytes_received == total) {
    download_progress_ = progress;
    SetStatusAndNotify(UpdateStatus::DOWNLOADING);
  } else {
    ProgressUpdate(progress);
  }
}

void UpdateAttempter::DownloadComplete() {
  system_state_->payload_state()->DownloadComplete();
}

void UpdateAttempter::ProgressUpdate(double progress) {
  // Self throttle based on progress. Also send notifications if progress is
  // too slow.
  if (progress == 1.0 ||
      progress - download_progress_ >= kBroadcastThresholdProgress ||
      TimeTicks::Now() - last_notify_time_ >=
          TimeDelta::FromSeconds(kBroadcastThresholdSeconds)) {
    download_progress_ = progress;
    BroadcastStatus();
  }
}

bool UpdateAttempter::ResetStatus() {
  LOG(INFO) << "Attempting to reset state from "
            << UpdateStatusToString(status_) << " to UpdateStatus::IDLE";

  switch (status_) {
    case UpdateStatus::IDLE:
      // no-op.
      return true;

    case UpdateStatus::UPDATED_NEED_REBOOT:  {
      bool ret_value = true;
      status_ = UpdateStatus::IDLE;

      // Remove the reboot marker so that if the machine is rebooted
      // after resetting to idle state, it doesn't go back to
      // UpdateStatus::UPDATED_NEED_REBOOT state.
      ret_value = prefs_->Delete(kPrefsUpdateCompletedOnBootId) && ret_value;
      ret_value = prefs_->Delete(kPrefsUpdateCompletedBootTime) && ret_value;

      // Update the boot flags so the current slot has higher priority.
      BootControlInterface* boot_control = system_state_->boot_control();
      if (!boot_control->SetActiveBootSlot(boot_control->GetCurrentSlot()))
        ret_value = false;

      // Mark the current slot as successful again, since marking it as active
      // may reset the successful bit. We ignore the result of whether marking
      // the current slot as successful worked.
      if (!boot_control->MarkBootSuccessfulAsync(Bind([](bool successful){})))
        ret_value = false;

      // Notify the PayloadState that the successful payload was canceled.
      system_state_->payload_state()->ResetUpdateStatus();

      // The previous version is used to report back to omaha after reboot that
      // we actually rebooted into the new version from this "prev-version". We
      // need to clear out this value now to prevent it being sent on the next
      // updatecheck request.
      ret_value = prefs_->SetString(kPrefsPreviousVersion, "") && ret_value;

      LOG(INFO) << "Reset status " << (ret_value ? "successful" : "failed");
      return ret_value;
    }

    default:
      LOG(ERROR) << "Reset not allowed in this state.";
      return false;
  }
}

bool UpdateAttempter::GetStatus(UpdateEngineStatus* out_status) {
  out_status->last_checked_time = last_checked_time_;
  out_status->status = status_;
  out_status->current_version = omaha_request_params_->app_version();
  out_status->current_system_version = omaha_request_params_->system_version();
  out_status->progress = download_progress_;
  out_status->new_size_bytes = new_payload_size_;
  out_status->new_version = new_version_;
  out_status->new_system_version = new_system_version_;
  return true;
}

void UpdateAttempter::UpdateBootFlags() {
  if (update_boot_flags_running_) {
    LOG(INFO) << "Update boot flags running, nothing to do.";
    return;
  }
  if (updated_boot_flags_) {
    LOG(INFO) << "Already updated boot flags. Skipping.";
    if (start_action_processor_) {
      ScheduleProcessingStart();
    }
    return;
  }
  // This is purely best effort. Failures should be logged by Subprocess. Run
  // the script asynchronously to avoid blocking the event loop regardless of
  // the script runtime.
  update_boot_flags_running_ = true;
  LOG(INFO) << "Marking booted slot as good.";
  if (!system_state_->boot_control()->MarkBootSuccessfulAsync(Bind(
          &UpdateAttempter::CompleteUpdateBootFlags, base::Unretained(this)))) {
    LOG(ERROR) << "Failed to mark current boot as successful.";
    CompleteUpdateBootFlags(false);
  }
}

void UpdateAttempter::CompleteUpdateBootFlags(bool successful) {
  update_boot_flags_running_ = false;
  updated_boot_flags_ = true;
  if (start_action_processor_) {
    ScheduleProcessingStart();
  }
}

void UpdateAttempter::BroadcastStatus() {
  UpdateEngineStatus broadcast_status;
  // Use common method for generating the current status.
  GetStatus(&broadcast_status);

  for (const auto& observer : service_observers_) {
    observer->SendStatusUpdate(broadcast_status);
  }
  last_notify_time_ = TimeTicks::Now();
}

uint32_t UpdateAttempter::GetErrorCodeFlags()  {
  uint32_t flags = 0;

  if (!system_state_->hardware()->IsNormalBootMode())
    flags |= static_cast<uint32_t>(ErrorCode::kDevModeFlag);

  if (response_handler_action_.get() &&
      response_handler_action_->install_plan().is_resume)
    flags |= static_cast<uint32_t>(ErrorCode::kResumedFlag);

  if (!system_state_->hardware()->IsOfficialBuild())
    flags |= static_cast<uint32_t>(ErrorCode::kTestImageFlag);

  if (omaha_request_params_->update_url() !=
      constants::kOmahaDefaultProductionURL) {
    flags |= static_cast<uint32_t>(ErrorCode::kTestOmahaUrlFlag);
  }

  return flags;
}

bool UpdateAttempter::ShouldCancel(ErrorCode* cancel_reason) {
  // Check if the channel we're attempting to update to is the same as the
  // target channel currently chosen by the user.
  OmahaRequestParams* params = system_state_->request_params();
  if (params->download_channel() != params->target_channel()) {
    LOG(ERROR) << "Aborting download as target channel: "
               << params->target_channel()
               << " is different from the download channel: "
               << params->download_channel();
    *cancel_reason = ErrorCode::kUpdateCanceledByChannelChange;
    return true;
  }

  return false;
}

void UpdateAttempter::SetStatusAndNotify(UpdateStatus status) {
  status_ = status;
  BroadcastStatus();
}

void UpdateAttempter::CreatePendingErrorEvent(AbstractAction* action,
                                              ErrorCode code) {
  if (error_event_.get()) {
    // This shouldn't really happen.
    LOG(WARNING) << "There's already an existing pending error event.";
    return;
  }

  // For now assume that a generic Omaha response action failure means that
  // there's no update so don't send an event. Also, double check that the
  // failure has not occurred while sending an error event -- in which case
  // don't schedule another. This shouldn't really happen but just in case...
  if ((action->Type() == OmahaResponseHandlerAction::StaticType() &&
       code == ErrorCode::kError) ||
      status_ == UpdateStatus::REPORTING_ERROR_EVENT) {
    return;
  }

  // Classify the code to generate the appropriate result so that
  // the Borgmon charts show up the results correctly.
  // Do this before calling GetErrorCodeForAction which could potentially
  // augment the bit representation of code and thus cause no matches for
  // the switch cases below.
  OmahaEvent::Result event_result;
  switch (code) {
    case ErrorCode::kOmahaUpdateIgnoredPerPolicy:
    case ErrorCode::kOmahaUpdateDeferredPerPolicy:
    case ErrorCode::kOmahaUpdateDeferredForBackoff:
      event_result = OmahaEvent::kResultUpdateDeferred;
      break;
    default:
      event_result = OmahaEvent::kResultError;
      break;
  }

  code = GetErrorCodeForAction(action, code);
  fake_update_success_ = code == ErrorCode::kPostinstallBootedFromFirmwareB;

  // Compute the final error code with all the bit flags to be sent to Omaha.
  code = static_cast<ErrorCode>(
      static_cast<uint32_t>(code) | GetErrorCodeFlags());
  error_event_.reset(new OmahaEvent(OmahaEvent::kTypeUpdateComplete,
                                    event_result,
                                    code));
}

bool UpdateAttempter::ScheduleErrorEventAction() {
  if (error_event_.get() == nullptr)
    return false;

  LOG(ERROR) << "Update failed.";
  system_state_->payload_state()->UpdateFailed(error_event_->error_code);

  // Send it to Omaha.
  LOG(INFO) << "Reporting the error event";
  shared_ptr<OmahaRequestAction> error_event_action(
      new OmahaRequestAction(system_state_,
                             error_event_.release(),  // Pass ownership.
                             brillo::make_unique_ptr(new LibcurlHttpFetcher(
                                 GetProxyResolver(),
                                 system_state_->hardware())),
                             false));
  actions_.push_back(shared_ptr<AbstractAction>(error_event_action));
  processor_->EnqueueAction(error_event_action.get());
  SetStatusAndNotify(UpdateStatus::REPORTING_ERROR_EVENT);
  processor_->StartProcessing();
  return true;
}

void UpdateAttempter::ScheduleProcessingStart() {
  LOG(INFO) << "Scheduling an action processor start.";
  start_action_processor_ = false;
  MessageLoop::current()->PostTask(
      FROM_HERE,
      Bind([](ActionProcessor* processor) { processor->StartProcessing(); },
           base::Unretained(processor_.get())));
}

void UpdateAttempter::DisableDeltaUpdateIfNeeded() {
  int64_t delta_failures;
  if (omaha_request_params_->delta_okay() &&
      prefs_->GetInt64(kPrefsDeltaUpdateFailures, &delta_failures) &&
      delta_failures >= kMaxDeltaUpdateFailures) {
    LOG(WARNING) << "Too many delta update failures, forcing full update.";
    omaha_request_params_->set_delta_okay(false);
  }
}

void UpdateAttempter::MarkDeltaUpdateFailure() {
  // Don't try to resume a failed delta update.
  DeltaPerformer::ResetUpdateProgress(prefs_, false);
  int64_t delta_failures;
  if (!prefs_->GetInt64(kPrefsDeltaUpdateFailures, &delta_failures) ||
      delta_failures < 0) {
    delta_failures = 0;
  }
  prefs_->SetInt64(kPrefsDeltaUpdateFailures, ++delta_failures);
}

void UpdateAttempter::PingOmaha() {
  if (!processor_->IsRunning()) {
    shared_ptr<OmahaRequestAction> ping_action(new OmahaRequestAction(
        system_state_,
        nullptr,
        brillo::make_unique_ptr(new LibcurlHttpFetcher(
            GetProxyResolver(),
            system_state_->hardware())),
        true));
    actions_.push_back(shared_ptr<OmahaRequestAction>(ping_action));
    processor_->set_delegate(nullptr);
    processor_->EnqueueAction(ping_action.get());
    // Call StartProcessing() synchronously here to avoid any race conditions
    // caused by multiple outstanding ping Omaha requests.  If we call
    // StartProcessing() asynchronously, the device can be suspended before we
    // get a chance to callback to StartProcessing().  When the device resumes
    // (assuming the device sleeps longer than the next update check period),
    // StartProcessing() is called back and at the same time, the next update
    // check is fired which eventually invokes StartProcessing().  A crash
    // can occur because StartProcessing() checks to make sure that the
    // processor is idle which it isn't due to the two concurrent ping Omaha
    // requests.
    processor_->StartProcessing();
  } else {
    LOG(WARNING) << "Action processor running, Omaha ping suppressed.";
  }

  // Update the last check time here; it may be re-updated when an Omaha
  // response is received, but this will prevent us from repeatedly scheduling
  // checks in the case where a response is not received.
  UpdateLastCheckedTime();

  // Update the status which will schedule the next update check
  SetStatusAndNotify(UpdateStatus::UPDATED_NEED_REBOOT);
  ScheduleUpdates();
}


bool UpdateAttempter::DecrementUpdateCheckCount() {
  int64_t update_check_count_value;

  if (!prefs_->Exists(kPrefsUpdateCheckCount)) {
    // This file does not exist. This means we haven't started our update
    // check count down yet, so nothing more to do. This file will be created
    // later when we first satisfy the wall-clock-based-wait period.
    LOG(INFO) << "No existing update check count. That's normal.";
    return true;
  }

  if (prefs_->GetInt64(kPrefsUpdateCheckCount, &update_check_count_value)) {
    // Only if we're able to read a proper integer value, then go ahead
    // and decrement and write back the result in the same file, if needed.
    LOG(INFO) << "Update check count = " << update_check_count_value;

    if (update_check_count_value == 0) {
      // It could be 0, if, for some reason, the file didn't get deleted
      // when we set our status to waiting for reboot. so we just leave it
      // as is so that we can prevent another update_check wait for this client.
      LOG(INFO) << "Not decrementing update check count as it's already 0.";
      return true;
    }

    if (update_check_count_value > 0)
      update_check_count_value--;
    else
      update_check_count_value = 0;

    // Write out the new value of update_check_count_value.
    if (prefs_->SetInt64(kPrefsUpdateCheckCount, update_check_count_value)) {
      // We successfully wrote out te new value, so enable the
      // update check based wait.
      LOG(INFO) << "New update check count = " << update_check_count_value;
      return true;
    }
  }

  LOG(INFO) << "Deleting update check count state due to read/write errors.";

  // We cannot read/write to the file, so disable the update check based wait
  // so that we don't get stuck in this OS version by any chance (which could
  // happen if there's some bug that causes to read/write incorrectly).
  // Also attempt to delete the file to do our best effort to cleanup.
  prefs_->Delete(kPrefsUpdateCheckCount);
  return false;
}


void UpdateAttempter::UpdateEngineStarted() {
  // If we just booted into a new update, keep the previous OS version
  // in case we rebooted because of a crash of the old version, so we
  // can do a proper crash report with correct information.
  // This must be done before calling
  // system_state_->payload_state()->UpdateEngineStarted() since it will
  // delete SystemUpdated marker file.
  if (system_state_->system_rebooted() &&
      prefs_->Exists(kPrefsSystemUpdatedMarker)) {
    if (!prefs_->GetString(kPrefsPreviousVersion, &prev_version_)) {
      // If we fail to get the version string, make sure it stays empty.
      prev_version_.clear();
    }
  }

  system_state_->payload_state()->UpdateEngineStarted();
  StartP2PAtStartup();
}

bool UpdateAttempter::StartP2PAtStartup() {
  if (system_state_ == nullptr ||
      !system_state_->p2p_manager()->IsP2PEnabled()) {
    LOG(INFO) << "Not starting p2p at startup since it's not enabled.";
    return false;
  }

  if (system_state_->p2p_manager()->CountSharedFiles() < 1) {
    LOG(INFO) << "Not starting p2p at startup since our application "
              << "is not sharing any files.";
    return false;
  }

  return StartP2PAndPerformHousekeeping();
}

bool UpdateAttempter::StartP2PAndPerformHousekeeping() {
  if (system_state_ == nullptr)
    return false;

  if (!system_state_->p2p_manager()->IsP2PEnabled()) {
    LOG(INFO) << "Not starting p2p since it's not enabled.";
    return false;
  }

  LOG(INFO) << "Ensuring that p2p is running.";
  if (!system_state_->p2p_manager()->EnsureP2PRunning()) {
    LOG(ERROR) << "Error starting p2p.";
    return false;
  }

  LOG(INFO) << "Performing p2p housekeeping.";
  if (!system_state_->p2p_manager()->PerformHousekeeping()) {
    LOG(ERROR) << "Error performing housekeeping for p2p.";
    return false;
  }

  LOG(INFO) << "Done performing p2p housekeeping.";
  return true;
}

bool UpdateAttempter::GetBootTimeAtUpdate(Time *out_boot_time) {
  // In case of an update_engine restart without a reboot, we stored the boot_id
  // when the update was completed by setting a pref, so we can check whether
  // the last update was on this boot or a previous one.
  string boot_id;
  TEST_AND_RETURN_FALSE(utils::GetBootId(&boot_id));

  string update_completed_on_boot_id;
  if (!prefs_->Exists(kPrefsUpdateCompletedOnBootId) ||
      !prefs_->GetString(kPrefsUpdateCompletedOnBootId,
                         &update_completed_on_boot_id) ||
      update_completed_on_boot_id != boot_id)
    return false;

  // Short-circuit avoiding the read in case out_boot_time is nullptr.
  if (out_boot_time) {
    int64_t boot_time = 0;
    // Since the kPrefsUpdateCompletedOnBootId was correctly set, this pref
    // should not fail.
    TEST_AND_RETURN_FALSE(
        prefs_->GetInt64(kPrefsUpdateCompletedBootTime, &boot_time));
    *out_boot_time = Time::FromInternalValue(boot_time);
  }
  return true;
}

bool UpdateAttempter::IsUpdateRunningOrScheduled() {
  return ((status_ != UpdateStatus::IDLE &&
           status_ != UpdateStatus::UPDATED_NEED_REBOOT) ||
          waiting_for_scheduled_check_);
}

bool UpdateAttempter::IsAnyUpdateSourceAllowed() {
  // We allow updates from any source if either of these are true:
  //  * The device is running an unofficial (dev/test) image.
  //  * The debugd dev features are accessible (i.e. in devmode with no owner).
  // This protects users running a base image, while still allowing a specific
  // window (gated by the debug dev features) where `cros flash` is usable.
  if (!system_state_->hardware()->IsOfficialBuild()) {
    LOG(INFO) << "Non-official build; allowing any update source.";
    return true;
  }

  if (system_state_->hardware()->AreDevFeaturesEnabled()) {
    LOG(INFO) << "Developer features enabled; allowing custom update sources.";
    return true;
  }

  LOG(INFO)
      << "Developer features disabled; disallowing custom update sources.";
  return false;
}

}  // namespace chromeos_update_engine
