// Copyright (c) 2012 The Chromium OS Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "update_engine/update_check_scheduler.h"

#include "update_engine/certificate_checker.h"
#include "update_engine/http_common.h"
#include "update_engine/system_state.h"
#include "update_engine/utils.h"

namespace chromeos_update_engine {

// Default update check timeout interval/fuzz values, in seconds. Note that
// actual fuzz is within +/- half of the indicated value.
const int UpdateCheckScheduler::kTimeoutInitialInterval    =  7 * 60;
const int UpdateCheckScheduler::kTimeoutPeriodicInterval   = 45 * 60;
const int UpdateCheckScheduler::kTimeoutQuickInterval      =  1 * 60;
const int UpdateCheckScheduler::kTimeoutMaxBackoffInterval =  4 * 60 * 60;
const int UpdateCheckScheduler::kTimeoutRegularFuzz        = 10 * 60;

UpdateCheckScheduler::UpdateCheckScheduler(UpdateAttempter* update_attempter,
                                           GpioHandler* gpio_handler,
                                           SystemState* system_state)
    : update_attempter_(update_attempter),
      enabled_(false),
      scheduled_(false),
      last_interval_(0),
      poll_interval_(0),
      is_test_update_attempted_(false),
      gpio_handler_(gpio_handler),
      system_state_(system_state) {}

UpdateCheckScheduler::~UpdateCheckScheduler() {}

void UpdateCheckScheduler::Run() {
  enabled_ = false;
  update_attempter_->set_update_check_scheduler(NULL);

  if (!IsOfficialBuild()) {
    LOG(WARNING) << "Non-official build: periodic update checks disabled.";
    return;
  }
  if (IsBootDeviceRemovable()) {
    LOG(WARNING) << "Removable device boot: periodic update checks disabled.";
    return;
  }
  enabled_ = true;

  // Registers this scheduler with the update attempter so that scheduler can be
  // notified of update status changes.
  update_attempter_->set_update_check_scheduler(this);

  // Kicks off periodic update checks. The first check is scheduled
  // |kTimeoutInitialInterval| seconds from now. Subsequent checks are scheduled
  // by ScheduleNextCheck, normally at |kTimeoutPeriodicInterval|-second
  // intervals.
  ScheduleCheck(kTimeoutInitialInterval, kTimeoutRegularFuzz);
}

bool UpdateCheckScheduler::IsBootDeviceRemovable() {
  return utils::IsRemovableDevice(utils::RootDevice(utils::BootDevice()));
}

bool UpdateCheckScheduler::IsOfficialBuild() {
  return utils::IsOfficialBuild();
}

guint UpdateCheckScheduler::GTimeoutAddSeconds(guint interval,
                                               GSourceFunc function) {
  return g_timeout_add_seconds(interval, function, this);
}

void UpdateCheckScheduler::ScheduleCheck(int interval, int fuzz) {
  if (!CanSchedule()) {
    return;
  }
  last_interval_ = interval;
  interval = utils::FuzzInt(interval, fuzz);
  if (interval < 0) {
    interval = 0;
  }
  GTimeoutAddSeconds(interval, StaticCheck);
  scheduled_ = true;
  LOG(INFO) << "Next update check in " << utils::FormatSecs(interval);
}

gboolean UpdateCheckScheduler::StaticCheck(void* scheduler) {
  UpdateCheckScheduler* me = reinterpret_cast<UpdateCheckScheduler*>(scheduler);
  CHECK(me->scheduled_);
  me->scheduled_ = false;

  bool is_test_mode = false;
  if (me->system_state_->IsOOBEComplete() ||
      (is_test_mode = (!me->is_test_update_attempted_ &&
                       me->gpio_handler_ &&
                       me->gpio_handler_->IsTestModeSignaled()))) {
    if (is_test_mode) {
      LOG(WARNING)
          << "test mode signaled, allowing update check prior to OOBE complete";
      me->is_test_update_attempted_ = true;
    }

    // Before updating, we flush any previously generated UMA reports.
    CertificateChecker::FlushReport();
    me->update_attempter_->Update("", "", false, false, is_test_mode, false);
  } else {
    // Skips all automatic update checks if the OOBE process is not complete and
    // schedules a new check as if it is the first one.
    LOG(WARNING) << "Skipping update check because OOBE is not complete.";
    me->ScheduleCheck(kTimeoutInitialInterval, kTimeoutRegularFuzz);
  }
  // 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(me->update_attempter_->status() != UPDATE_STATUS_IDLE ||
        !me->CanSchedule());
  return FALSE;  // Don't run again.
}

void UpdateCheckScheduler::ComputeNextIntervalAndFuzz(const int forced_interval,
                                                      int* next_interval,
                                                      int* next_fuzz) {
  CHECK(next_interval && next_fuzz);

  int interval = forced_interval;
  int fuzz = 0;  // Use default fuzz value (see below)

  if (interval == 0) {
    int http_response_code;
    if (poll_interval_ > 0) {
      // Server-dictated poll interval.
      interval = poll_interval_;
      LOG(WARNING) << "Using server-dictated poll interval: " << interval;
    } else if ((http_response_code = update_attempter_->http_response_code()) ==
               kHttpResponseInternalServerError ||
               http_response_code == kHttpResponseServiceUnavailable) {
      // Implements exponential back off on 500 (Internal Server Error) and 503
      // (Service Unavailable) HTTP response codes.
      interval = 2 * last_interval_;
      LOG(WARNING) << "Exponential back off due to HTTP response code ("
                   << http_response_code << ")";
    }

    // Backoff cannot exceed a predetermined maximum period.
    if (interval > kTimeoutMaxBackoffInterval)
      interval = kTimeoutMaxBackoffInterval;

    // Ensures that under normal conditions the regular update check interval
    // and fuzz are used. Also covers the case where back off is required based
    // on the initial update check.
    if (interval < kTimeoutPeriodicInterval) {
      interval = kTimeoutPeriodicInterval;
      fuzz = kTimeoutRegularFuzz;
    }
  }

  // Set default fuzz to +/- |interval|/2.
  if (fuzz == 0)
    fuzz = interval;

  *next_interval = interval;
  *next_fuzz = fuzz;
}

void UpdateCheckScheduler::ScheduleNextCheck(bool is_force_quick) {
  int interval, fuzz;
  ComputeNextIntervalAndFuzz(is_force_quick ? kTimeoutQuickInterval : 0,
                             &interval, &fuzz);
  ScheduleCheck(interval, fuzz);
}

void UpdateCheckScheduler::SetUpdateStatus(UpdateStatus status,
                                           UpdateNotice notice) {
  // We want to schedule the update checks for when we're idle as well as
  // after we've successfully applied an update and waiting for the user
  // to reboot to ensure our active count is accurate.
  if (status == UPDATE_STATUS_IDLE ||
      status == UPDATE_STATUS_UPDATED_NEED_REBOOT) {
    ScheduleNextCheck(notice == kUpdateNoticeTestAddrFailed);
  }
}

}  // namespace chromeos_update_engine
