//
// 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/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/connection_manager_interface.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/policy_utils.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)
    : processor_(new ActionProcessor()),
      system_state_(system_state),
      cert_checker_(cert_checker) {}

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 rollback_allowed,
                             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,
                             rollback_allowed,
                             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 they are working on the
  // update_engine or p2p codebases so they can actually test their 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 rollback_allowed,
                                            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();

  // Check whether we need to clear the rollback-happened preference after
  // policy is available again.
  UpdateRollbackHappened();

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

  // Set whether rollback is allowed.
  omaha_request_params_->set_rollback_allowed(rollback_allowed);

  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()
            << ", rollback_allowed = "
            << omaha_request_params_->rollback_allowed()
            << ", 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),
      std::make_unique<LibcurlHttpFetcher>(GetProxyResolver(),
                                           system_state_->hardware()),
      false));

  LibcurlHttpFetcher* download_fetcher =
      new LibcurlHttpFetcher(GetProxyResolver(), system_state_->hardware());
  download_fetcher->set_server_to_check(ServerToCheck::kDownload);
  if (interactive)
    download_fetcher->set_max_retry_count(kDownloadMaxRetryCountInteractive);
  shared_ptr<DownloadAction> download_action(
      new DownloadAction(prefs_,
                         system_state_->boot_control(),
                         system_state_->hardware(),
                         system_state_,
                         download_fetcher,  // passes ownership
                         interactive));
  shared_ptr<OmahaRequestAction> download_finished_action(
      new OmahaRequestAction(
          system_state_,
          new OmahaEvent(OmahaEvent::kTypeUpdateDownloadFinished),
          std::make_unique<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),
                             std::make_unique<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() {
#ifdef __ANDROID__
  if (status_ != UpdateStatus::UPDATED_NEED_REBOOT) {
    LOG(INFO) << "Reboot requested, but status is "
              << UpdateStatusToString(status_) << ", so not rebooting.";
    return false;
  }
#endif  // __ANDROID__

  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,
           params.rollback_allowed,
           /*obey_proxies=*/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();
}

void UpdateAttempter::UpdateRollbackHappened() {
  DCHECK(system_state_);
  DCHECK(system_state_->payload_state());
  DCHECK(policy_provider_);
  if (system_state_->payload_state()->GetRollbackHappened() &&
      (policy_provider_->device_policy_is_loaded() ||
       policy_provider_->IsConsumerDevice())) {
    // Rollback happened, but we already went through OOBE and policy is
    // present or it's a consumer device.
    system_state_->payload_state()->SetRollbackHappened(false);
  }
}

// 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.";
  }

  attempt_error_code_ = utils::GetBaseErrorCode(code);

  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 + ":";
      }

      // If we just downloaded a rollback image, we should preserve this fact
      // over the following powerwash.
      if (install_plan.is_rollback) {
        system_state_->payload_state()->SetRollbackHappened(true);
        system_state_->metrics_reporter()->ReportEnterpriseRollbackMetrics(
            /*success=*/true, install_plan.version);
      }

      // 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;
      }

      const OmahaResponse& omaha_response =
          omaha_request_action->GetOutputObject();
      // Store the server-dictated poll interval, if any.
      server_dictated_poll_interval_ =
          std::max(0, omaha_response.poll_interval);

      // This update is ignored by omaha request action because update over
      // cellular connection is not allowed. Needs to ask for user's permissions
      // to update.
      if (code == ErrorCode::kOmahaUpdateIgnoredOverCellular) {
        new_version_ = omaha_response.version;
        new_payload_size_ = 0;
        for (const auto& package : omaha_response.packages) {
          new_payload_size_ += package.size;
        }
        SetStatusAndNotify(UpdateStatus::NEED_PERMISSION_TO_UPDATE);
      }
    }
  } 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 (code != ErrorCode::kDownloadTransferError) {
      switch (status_) {
        case UpdateStatus::IDLE:
        case UpdateStatus::CHECKING_FOR_UPDATE:
        case UpdateStatus::UPDATE_AVAILABLE:
        case UpdateStatus::NEED_PERMISSION_TO_UPDATE:
          break;
        case UpdateStatus::DOWNLOADING:
        case UpdateStatus::VERIFYING:
        case UpdateStatus::FINALIZING:
        case UpdateStatus::UPDATED_NEED_REBOOT:
        case UpdateStatus::REPORTING_ERROR_EVENT:
        case UpdateStatus::ATTEMPTING_ROLLBACK:
        case UpdateStatus::DISABLED:
          MarkDeltaUpdateFailure();
          break;
      }
    }
    if (code != ErrorCode::kNoUpdate) {
      // 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);
  } else if (type == FilesystemVerifierAction::StaticType()) {
    // Log the system properties before the postinst and after the file system
    // is verified. It used to be done in the postinst itself. But postinst
    // cannot do this anymore. On the other hand, these logs are frequently
    // looked at and it is preferable not to scatter them in random location in
    // the log and rather log it right before the postinst. The reason not do
    // this in the |PostinstallRunnerAction| is to prevent dependency from
    // libpayload_consumer to libupdate_engine.
    LogImageProperties();
  }
}

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() || status_ == UpdateStatus::REPORTING_ERROR_EVENT) {
    // This shouldn't really happen.
    LOG(WARNING) << "There's already an existing pending 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 metrics if it was a rollback.
  if (response_handler_action_) {
    const InstallPlan& install_plan = response_handler_action_->install_plan();
    if (install_plan.is_rollback) {
      system_state_->metrics_reporter()->ReportEnterpriseRollbackMetrics(
          /*success=*/false, install_plan.version);
    }
  }

  // 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.
                             std::make_unique<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,
        std::make_unique<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
