// Copyright (c) 2013 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 "power_manager/powerd/policy/state_controller.h"

#include <stdint.h>

#include <algorithm>
#include <cmath>
#include <utility>
#include <vector>

#include <base/bind.h>
#include <base/callback.h>
#include <base/files/file_util.h>
#include <base/logging.h>
#include <base/strings/string_number_conversions.h>
#include <base/strings/string_util.h>
#include <base/strings/stringprintf.h>
#include <chromeos/dbus/service_constants.h>
#include <update_engine/proto_bindings/update_engine.pb.h>

#include "power_manager/common/clock.h"
#include "power_manager/common/power_constants.h"
#include "power_manager/common/prefs.h"
#include "power_manager/common/util.h"
#include "power_manager/powerd/system/dbus_wrapper.h"
#include "power_manager/proto_bindings/idle.pb.h"

namespace power_manager {
namespace policy {

namespace {

// Time to wait for display mode change after resuming with lid still closed
// before triggering idle and lid closed action (crbug.com/786721).
constexpr base::TimeDelta KWaitForExternalDisplayTimeout =
    base::TimeDelta::FromSeconds(25);

// Time to wait for the display mode and policy after Init() is called.
constexpr base::TimeDelta kInitialStateTimeout =
    base::TimeDelta::FromSeconds(10);

// Time to wait for the crash-boot-collect to successfully complete.
constexpr base::TimeDelta kCrashBootCollectTimeout =
    base::TimeDelta::FromMinutes(1);

// Time to wait for responses to D-Bus method calls to update_engine.
constexpr base::TimeDelta kUpdateEngineDBusTimeout =
    base::TimeDelta::FromSeconds(3);

// Interval between logging the list of current wake locks.
constexpr base::TimeDelta kWakeLocksLoggingInterval =
    base::TimeDelta::FromMinutes(5);

// File used by crash_reporter to signal successful collection of per-boot crash
// logs.
constexpr char kCrashBootCollectorDoneFile[] =
    "/run/crash_reporter/boot-collector-done";

// Returns |time_ms|, a time in milliseconds, as a
// util::TimeDeltaToString()-style string.
std::string MsToString(int64_t time_ms) {
  return util::TimeDeltaToString(base::TimeDelta::FromMilliseconds(time_ms));
}

// Returns the minimum positive value after comparing |a| and |b|.  If one
// is zero or negative, the other is returned.  If both are zero or
// negative, an empty base::TimeDelta is returned.
base::TimeDelta GetMinPositiveTimeDelta(base::TimeDelta a, base::TimeDelta b) {
  if (a > base::TimeDelta()) {
    if (b > base::TimeDelta()) {
      return a < b ? a : b;
    } else {
      return a;
    }
  } else {
    return b;
  }
}

// Helper function for ScheduleActionTimeout() to compute how long to sleep
// before calling UpdateState() to perform the next-occurring action. Given
// |now| and an action that should be performed |action_delay| after
// |last_activity_time|, updates |timeout| to be the minimum of its current
// value and the time to wait before performing the action. Does nothing if
// |action_delay| is unset or if the action should've been performed already.
void UpdateActionTimeout(base::TimeTicks now,
                         base::TimeTicks last_activity_time,
                         base::TimeDelta action_delay,
                         base::TimeDelta* timeout) {
  if (action_delay <= base::TimeDelta())
    return;

  const base::TimeTicks action_time = last_activity_time + action_delay;
  if (action_time > now)
    *timeout = GetMinPositiveTimeDelta(*timeout, action_time - now);
}

// Helper function for UpdateState.  The general pattern here is:
// - If |inactivity_duration| has reached |delay| and
//   |action_already_performed| says that the controller hasn't yet
//   performed the corresponding action, then run |callback| and set
//   |action_already_performed| to ensure that the action doesn't get
//   performed again the next time this is called.
// - If |delay| hasn't been reached, then run |undo_callback| if non-null
//   to undo the action if needed and reset |action_already_performed| so
//   that the action can be performed later.
void HandleDelay(base::TimeDelta delay,
                 base::TimeDelta inactivity_duration,
                 base::Closure callback,
                 base::Closure undo_callback,
                 const std::string& description,
                 const std::string& undo_description,
                 bool* action_already_performed) {
  if (delay > base::TimeDelta() && inactivity_duration >= delay) {
    if (!*action_already_performed) {
      LOG(INFO) << description << " after "
                << util::TimeDeltaToString(inactivity_duration);
      callback.Run();
      *action_already_performed = true;
    }
  } else if (*action_already_performed) {
    if (!undo_callback.is_null()) {
      LOG(INFO) << undo_description;
      undo_callback.Run();
    }
    *action_already_performed = false;
  }
}

// Looks up |name|, an int64_t preference representing milliseconds, in
// |prefs|, and returns it as a base::TimeDelta.  Returns true on success.
bool GetMillisecondPref(PrefsInterface* prefs,
                        const std::string& name,
                        base::TimeDelta* out) {
  DCHECK(prefs);
  DCHECK(out);

  int64_t int_value = 0;
  if (!prefs->GetInt64(name, &int_value))
    return false;

  *out = base::TimeDelta::FromMilliseconds(int_value);
  return true;
}

// Returns a string describing |delays| with each field prefixed by
// |prefix|. Helper method for GetPolicyDebugString().
std::string GetPolicyDelaysDebugString(
    const PowerManagementPolicy::Delays& delays, const std::string& prefix) {
  std::string str;
  if (delays.has_screen_dim_ms())
    str += prefix + "_dim=" + MsToString(delays.screen_dim_ms()) + " ";
  if (delays.has_screen_off_ms())
    str += prefix + "_screen_off=" + MsToString(delays.screen_off_ms()) + " ";
  if (delays.has_screen_lock_ms())
    str += prefix + "_lock=" + MsToString(delays.screen_lock_ms()) + " ";
  if (delays.has_idle_warning_ms())
    str += prefix + "_idle_warn=" + MsToString(delays.idle_warning_ms()) + " ";
  if (delays.has_idle_ms())
    str += prefix + "_idle=" + MsToString(delays.idle_ms()) + " ";
  return str;
}

// Returns a string describing the wake locks in |policy|, or an empty string if
// no wake locks are held.
std::string GetWakeLocksLogString(const PowerManagementPolicy& policy) {
  std::string msg;
  if (policy.screen_wake_lock())
    msg += " screen";
  if (policy.dim_wake_lock())
    msg += " dim";
  if (policy.system_wake_lock())
    msg += " system";

  if (msg.empty())
    return std::string();

  msg = "Active wake locks:" + msg;
  if (policy.has_reason())
    msg += " (" + policy.reason() + ")";
  return msg;
}

}  // namespace

StateController::TestApi::TestApi(StateController* controller)
    : controller_(controller) {}

StateController::TestApi::~TestApi() {
  controller_ = nullptr;
}

void StateController::TestApi::TriggerActionTimeout() {
  CHECK(controller_->action_timer_.IsRunning());
  controller_->action_timer_.Stop();
  controller_->HandleActionTimeout();
}

bool StateController::TestApi::TriggerInitialStateTimeout() {
  if (!controller_->initial_state_timer_.IsRunning())
    return false;

  controller_->initial_state_timer_.Stop();
  controller_->HandleInitialStateTimeout();
  return true;
}

bool StateController::TestApi::TriggerWaitForExternalDisplayTimeout() {
  if (!controller_->WaitingForExternalDisplay())
    return false;

  controller_->wait_for_external_display_timer_.Stop();
  controller_->HandleWaitForExternalDisplayTimeout();
  return true;
}

bool StateController::TestApi::TriggerHandleCrashBootCollectTimeout() {
  if (!controller_->WaitingForCrashBootCollect())
    return false;

  controller_->wait_for_crash_boot_collect_timer_.Stop();
  controller_->HandleCrashBootCollectTimeout();
  return true;
}

bool StateController::Delays::operator!=(
    const StateController::Delays& o) const {
  // Don't bother checking screen_dim_imminent; it's a synthetic delay that's
  // based solely on screen_dim.
  return idle != o.idle || idle_warning != o.idle_warning ||
         screen_off != o.screen_off || screen_dim != o.screen_dim ||
         screen_lock != o.screen_lock;
}

class StateController::ActivityInfo {
 public:
  ActivityInfo() = default;
  ~ActivityInfo() = default;

  bool active() const { return active_; }

  // Returns |now| if the activity is currently active or the last time that it
  // was active otherwise (or an unset time if it was never active).
  //
  // This method provides a convenient shorthand for callers that are trying to
  // compute a most-recent-activity timestamp across several different
  // activities. This method's return value should not be compared against the
  // current time to determine if the activity is currently active; call
  // active() instead.
  base::TimeTicks GetLastActiveTime(base::TimeTicks now) const {
    return active_ ? now : last_active_time_;
  }

  // Updates the current state of the activity.
  void SetActive(bool active, base::TimeTicks now) {
    if (active == active_)
      return;

    active_ = active;
    last_active_time_ = active ? base::TimeTicks() : now;
  }

 private:
  // True if the activity is currently active.
  bool active_ = false;

  // If the activity is currently inactive, the time at which it was last
  // active. Unset if it is currently active or was never active.
  base::TimeTicks last_active_time_;

  DISALLOW_COPY_AND_ASSIGN(ActivityInfo);
};

const int StateController::kUserActivityAfterScreenOffIncreaseDelaysMs = 60000;

constexpr base::TimeDelta StateController::kScreenDimImminentInterval;

// static
std::string StateController::GetPolicyDebugString(
    const PowerManagementPolicy& policy) {
  std::string str = GetPolicyDelaysDebugString(policy.ac_delays(), "ac");
  str += GetPolicyDelaysDebugString(policy.battery_delays(), "battery");

  if (policy.has_ac_idle_action()) {
    str += "ac_idle=" +
           ActionToString(ProtoActionToAction(policy.ac_idle_action())) + " ";
  }
  if (policy.has_battery_idle_action()) {
    str += "battery_idle=" +
           ActionToString(ProtoActionToAction(policy.battery_idle_action())) +
           " ";
  }
  if (policy.has_lid_closed_action()) {
    str += "lid_closed=" +
           ActionToString(ProtoActionToAction(policy.lid_closed_action())) +
           " ";
  }
  if (policy.has_screen_wake_lock()) {
    str +=
        "screen_wake_lock=" + base::NumberToString(policy.screen_wake_lock()) +
        " ";
  }
  if (policy.has_dim_wake_lock())
    str +=
        "dim_wake_lock=" + base::NumberToString(policy.dim_wake_lock()) + " ";
  if (policy.has_system_wake_lock()) {
    str +=
        "system_wake_lock=" + base::NumberToString(policy.system_wake_lock()) +
        " ";
  }
  if (policy.has_use_audio_activity())
    str +=
        "use_audio=" + base::NumberToString(policy.use_audio_activity()) + " ";
  if (policy.has_use_video_activity())
    str +=
        "use_video=" + base::NumberToString(policy.use_video_activity()) + " ";
  if (policy.has_presentation_screen_dim_delay_factor()) {
    str += "presentation_factor=" +
           base::NumberToString(policy.presentation_screen_dim_delay_factor()) +
           " ";
  }
  if (policy.has_user_activity_screen_dim_delay_factor()) {
    str +=
        "user_activity_factor=" +
        base::NumberToString(policy.user_activity_screen_dim_delay_factor()) +
        " ";
  }
  if (policy.has_wait_for_initial_user_activity()) {
    str += "wait_for_initial_user_activity=" +
           base::NumberToString(policy.wait_for_initial_user_activity()) + " ";
  }
  if (policy.has_force_nonzero_brightness_for_user_activity()) {
    str += "force_nonzero_brightness_for_user_activity=" +
           base::NumberToString(
               policy.force_nonzero_brightness_for_user_activity()) +
           " ";
  }

  if (policy.has_reason())
    str += "(" + policy.reason() + ")";

  return str.empty() ? "[empty]" : str;
}

StateController::StateController()
    : clock_(std::make_unique<Clock>()),
      audio_activity_(std::make_unique<ActivityInfo>()),
      screen_wake_lock_(std::make_unique<ActivityInfo>()),
      dim_wake_lock_(std::make_unique<ActivityInfo>()),
      system_wake_lock_(std::make_unique<ActivityInfo>()),
      wake_lock_logger_(kWakeLocksLoggingInterval),
      weak_ptr_factory_(this) {}

StateController::~StateController() {
  if (prefs_)
    prefs_->RemoveObserver(this);
}

void StateController::Init(Delegate* delegate,
                           PrefsInterface* prefs,
                           system::DBusWrapperInterface* dbus_wrapper,
                           PowerSource power_source,
                           LidState lid_state) {
  delegate_ = delegate;
  prefs_ = prefs;
  prefs_->AddObserver(this);
  LoadPrefs();

  dbus_wrapper_ = dbus_wrapper;
  dbus_wrapper->ExportMethod(
      kGetInactivityDelaysMethod,
      base::Bind(&StateController::HandleGetInactivityDelaysMethodCall,
                 weak_ptr_factory_.GetWeakPtr()));

  update_engine_dbus_proxy_ =
      dbus_wrapper_->GetObjectProxy(update_engine::kUpdateEngineServiceName,
                                    update_engine::kUpdateEngineServicePath);
  dbus_wrapper_->RegisterForServiceAvailability(
      update_engine_dbus_proxy_,
      base::Bind(&StateController::HandleUpdateEngineAvailable,
                 weak_ptr_factory_.GetWeakPtr()));
  dbus_wrapper_->RegisterForSignal(
      update_engine_dbus_proxy_, update_engine::kUpdateEngineInterface,
      update_engine::kStatusUpdateAdvanced,
      base::Bind(&StateController::HandleUpdateEngineStatusUpdateSignal,
                 weak_ptr_factory_.GetWeakPtr()));

  ml_decision_dbus_proxy_ = dbus_wrapper_->GetObjectProxy(
      chromeos::kMlDecisionServiceName, chromeos::kMlDecisionServicePath);
  dbus_wrapper_->RegisterForServiceAvailability(
      ml_decision_dbus_proxy_,
      base::Bind(&StateController::HandleMlDecisionServiceAvailable,
                 weak_ptr_factory_.GetWeakPtr()));

  last_user_activity_time_ = clock_->GetCurrentTime();
  power_source_ = power_source;
  lid_state_ = lid_state;

  initial_state_timer_.Start(FROM_HERE, kInitialStateTimeout, this,
                             &StateController::HandleInitialStateTimeout);

  crash_boot_collector_watcher_.Watch(
      base::FilePath(kCrashBootCollectorDoneFile), false,
      base::Bind(&StateController::MaybeStopWaitForCrashBootCollectTimer,
                 weak_ptr_factory_.GetWeakPtr()));

  wait_for_crash_boot_collect_timer_.Start(
      FROM_HERE, kCrashBootCollectTimeout, this,
      &StateController::HandleCrashBootCollectTimeout);

  UpdateSettingsAndState();

  // Emit the current screen-idle state in case powerd restarted while the
  // screen was dimmed or turned off.
  EmitScreenIdleStateChanged(screen_dimmed_, screen_turned_off_);

  initialized_ = true;
}

void StateController::HandlePowerSourceChange(PowerSource source) {
  CHECK(initialized_);
  if (source == power_source_)
    return;

  power_source_ = source;
  UpdateLastUserActivityTime();
  UpdateSettingsAndState();
}

void StateController::HandleLidStateChange(LidState state) {
  CHECK(initialized_);
  if (state == lid_state_)
    return;

  lid_state_ = state;

  if (lid_state_ == LidState::OPEN) {
    StopWaitForExternalDisplayTimer();
    UpdateLastUserActivityTime();
  }
  UpdateSettingsAndState();
}

void StateController::HandleTabletModeChange(TabletMode mode) {
  DCHECK(initialized_);

  // We don't care about the mode, but we treat events as user activity.
  UpdateLastUserActivityTime();
  UpdateState();
}

void StateController::HandleSessionStateChange(SessionState state) {
  CHECK(initialized_);
  if (state == session_state_)
    return;

  session_state_ = state;
  saw_user_activity_soon_after_screen_dim_or_off_ = false;
  saw_user_activity_during_current_session_ = false;
  UpdateLastUserActivityTime();
  UpdateSettingsAndState();
}

void StateController::HandleDisplayModeChange(DisplayMode mode) {
  CHECK(initialized_);
  if (mode == display_mode_ && got_initial_display_mode_)
    return;

  display_mode_ = mode;

  if (!got_initial_display_mode_) {
    got_initial_display_mode_ = true;
    MaybeStopInitialStateTimer();
  } else {
    UpdateLastUserActivityTime();
  }

  StopWaitForExternalDisplayTimer();
  UpdateSettingsAndState();
}

void StateController::HandleResume(LidState state) {
  CHECK(initialized_);

  lid_state_ = state;
  // If resumed with closed lid and not in docked mode, let us wait for docked
  // mode before resuspending again.
  if (lid_state_ == LidState::CLOSED && !in_docked_mode()) {
    LOG(INFO) << "Waiting for external display before performing idle or "
                 "lid closed action";
    wait_for_external_display_timer_.Start(
        FROM_HERE, KWaitForExternalDisplayTimeout, this,
        &StateController::HandleWaitForExternalDisplayTimeout);
    lid_closed_action_performed_ = false;
  } else if (lid_state_ == LidState::OPEN ||
             lid_state_ == LidState::NOT_PRESENT || in_docked_mode()) {
    // Treat resume as a user activity if the lid is not closed or if we are in
    // docked mode.
    UpdateLastUserActivityTime();
  }
  UpdateSettingsAndState();
}

void StateController::HandlePolicyChange(const PowerManagementPolicy& policy) {
  CHECK(initialized_);
  policy_ = policy;
  if (!got_initial_policy_) {
    got_initial_policy_ = true;
    MaybeStopInitialStateTimer();
  }

  const base::TimeTicks now = clock_->GetCurrentTime();
  screen_wake_lock_->SetActive(policy.screen_wake_lock(), now);
  dim_wake_lock_->SetActive(policy.dim_wake_lock(), now);
  system_wake_lock_->SetActive(policy.system_wake_lock(), now);

  UpdateSettingsAndState();

  // Update the message that periodically lists active wake locks.
  wake_lock_logger_.OnStateChanged(GetWakeLocksLogString(policy));
}

void StateController::HandleUserActivity() {
  CHECK(initialized_);

  // Ignore user activity reported while the lid is closed unless we're in
  // docked mode.
  if (lid_state_ == LidState::CLOSED && !in_docked_mode()) {
    LOG(WARNING) << "Ignoring user activity received while lid is closed";
    return;
  }

  const bool old_saw_user_activity =
      saw_user_activity_soon_after_screen_dim_or_off_;
  const bool screen_turned_off_recently =
      delays_.screen_off > base::TimeDelta() && screen_turned_off_ &&
      (clock_->GetCurrentTime() - screen_turned_off_time_).InMilliseconds() <=
          kUserActivityAfterScreenOffIncreaseDelaysMs;
  if (!saw_user_activity_soon_after_screen_dim_or_off_ &&
      ((screen_dimmed_ && !screen_turned_off_) || screen_turned_off_recently)) {
    LOG(INFO) << "Scaling delays due to user activity while screen was dimmed "
              << "or soon after it was turned off";
    saw_user_activity_soon_after_screen_dim_or_off_ = true;
  }

  if (session_state_ == SessionState::STARTED)
    saw_user_activity_during_current_session_ = true;

  UpdateLastUserActivityTime();
  if (old_saw_user_activity != saw_user_activity_soon_after_screen_dim_or_off_)
    UpdateSettingsAndState();
  else
    UpdateState();
}

void StateController::HandleVideoActivity() {
  CHECK(initialized_);
  if (screen_dimmed_ || screen_turned_off_) {
    LOG(INFO) << "Ignoring video since screen is dimmed or off";
    return;
  }
  last_video_activity_time_ = clock_->GetCurrentTime();
  UpdateState();
}

void StateController::HandleWakeNotification() {
  CHECK(initialized_);

  // Ignore user activity reported while the lid is closed unless we're in
  // docked mode.
  if (lid_state_ == LidState::CLOSED && !in_docked_mode()) {
    LOG(INFO) << "Ignoring wake notification while lid is closed";
    return;
  }

  last_wake_notification_time_ = clock_->GetCurrentTime();
  UpdateState();
}

void StateController::HandleAudioStateChange(bool active) {
  CHECK(initialized_);
  audio_activity_->SetActive(active, clock_->GetCurrentTime());
  UpdateState();
}

void StateController::HandleTpmStatus(int dictionary_attack_count) {
  if (tpm_dictionary_attack_count_ == dictionary_attack_count)
    return;

  tpm_dictionary_attack_count_ = dictionary_attack_count;
  UpdateSettingsAndState();
}

PowerManagementPolicy::Delays StateController::CreateInactivityDelaysProto()
    const {
  PowerManagementPolicy::Delays proto;
  if (!delays_.idle.is_zero())
    proto.set_idle_ms(delays_.idle.InMilliseconds());
  if (!delays_.idle_warning.is_zero())
    proto.set_idle_warning_ms(delays_.idle_warning.InMilliseconds());
  if (!delays_.screen_off.is_zero())
    proto.set_screen_off_ms(delays_.screen_off.InMilliseconds());
  if (!delays_.screen_dim.is_zero())
    proto.set_screen_dim_ms(delays_.screen_dim.InMilliseconds());
  if (!delays_.screen_lock.is_zero())
    proto.set_screen_lock_ms(delays_.screen_lock.InMilliseconds());
  return proto;
}

void StateController::OnPrefChanged(const std::string& pref_name) {
  CHECK(initialized_);
  if (pref_name == kDisableIdleSuspendPref ||
      pref_name == kIgnoreExternalPolicyPref) {
    LOG(INFO) << "Reloading prefs for " << pref_name << " change";
    LoadPrefs();
    UpdateSettingsAndState();
  }
}

// static
std::string StateController::ActionToString(Action action) {
  switch (action) {
    case Action::SUSPEND:
      return "suspend";
    case Action::STOP_SESSION:
      return "logout";
    case Action::SHUT_DOWN:
      return "shutdown";
    case Action::DO_NOTHING:
      return "no-op";
  }
  NOTREACHED() << "Unhandled action " << static_cast<int>(action);
  return base::StringPrintf("unknown (%d)", static_cast<int>(action));
}

// static
StateController::Action StateController::ProtoActionToAction(
    PowerManagementPolicy_Action proto_action) {
  switch (proto_action) {
    case PowerManagementPolicy_Action_SUSPEND:
      return Action::SUSPEND;
    case PowerManagementPolicy_Action_STOP_SESSION:
      return Action::STOP_SESSION;
    case PowerManagementPolicy_Action_SHUT_DOWN:
      return Action::SHUT_DOWN;
    case PowerManagementPolicy_Action_DO_NOTHING:
      return Action::DO_NOTHING;
    default:
      NOTREACHED() << "Unhandled action " << static_cast<int>(proto_action);
      return Action::DO_NOTHING;
  }
}

// static
void StateController::ScaleDelays(Delays* delays,
                                  double screen_dim_scale_factor) {
  DCHECK(delays);
  if (screen_dim_scale_factor <= 1.0 || delays->screen_dim <= base::TimeDelta())
    return;

  const base::TimeDelta orig_screen_dim = delays->screen_dim;
  delays->screen_dim *= screen_dim_scale_factor;

  const base::TimeDelta diff = delays->screen_dim - orig_screen_dim;
  if (delays->screen_off > base::TimeDelta())
    delays->screen_off += diff;
  if (delays->screen_lock > base::TimeDelta())
    delays->screen_lock += diff;
  if (delays->idle_warning > base::TimeDelta())
    delays->idle_warning += diff;
  if (delays->idle > base::TimeDelta())
    delays->idle += diff;
}

// static
void StateController::SanitizeDelays(Delays* delays) {
  DCHECK(delays);

  // Don't try to turn the screen off after performing the idle action.
  if (delays->screen_off > base::TimeDelta())
    delays->screen_off = std::min(delays->screen_off, delays->idle);
  else
    delays->screen_off = base::TimeDelta();

  // Similarly, don't try to dim the screen after turning it off.
  if (delays->screen_dim > base::TimeDelta()) {
    delays->screen_dim =
        std::min(delays->screen_dim,
                 GetMinPositiveTimeDelta(delays->idle, delays->screen_off));
  } else {
    delays->screen_dim = base::TimeDelta();
  }

  // Cap the idle-warning timeout to the idle-action timeout.
  if (delays->idle_warning > base::TimeDelta())
    delays->idle_warning = std::min(delays->idle_warning, delays->idle);
  else
    delays->idle_warning = base::TimeDelta();

  // If the lock delay matches or exceeds the idle delay, unset it --
  // Chrome's lock-before-suspend setting should be enabled instead.
  if (delays->screen_lock >= delays->idle ||
      delays->screen_lock < base::TimeDelta()) {
    delays->screen_lock = base::TimeDelta();
  }
}

// static
void StateController::MergeDelaysFromPolicy(
    const PowerManagementPolicy::Delays& policy_delays, Delays* delays_out) {
  DCHECK(delays_out);

  if (policy_delays.has_idle_ms() && policy_delays.idle_ms() >= 0) {
    delays_out->idle =
        base::TimeDelta::FromMilliseconds(policy_delays.idle_ms());
  }
  if (policy_delays.has_idle_warning_ms() &&
      policy_delays.idle_warning_ms() >= 0) {
    delays_out->idle_warning =
        base::TimeDelta::FromMilliseconds(policy_delays.idle_warning_ms());
  }
  if (policy_delays.has_screen_dim_ms() && policy_delays.screen_dim_ms() >= 0) {
    delays_out->screen_dim =
        base::TimeDelta::FromMilliseconds(policy_delays.screen_dim_ms());
  }
  if (policy_delays.has_screen_off_ms() && policy_delays.screen_off_ms() >= 0) {
    delays_out->screen_off =
        base::TimeDelta::FromMilliseconds(policy_delays.screen_off_ms());
  }
  if (policy_delays.has_screen_lock_ms() &&
      policy_delays.screen_lock_ms() >= 0) {
    delays_out->screen_lock =
        base::TimeDelta::FromMilliseconds(policy_delays.screen_lock_ms());
  }
}

bool StateController::WaitingForInitialState() const {
  return initial_state_timer_.IsRunning();
}

bool StateController::WaitingForExternalDisplay() const {
  return wait_for_external_display_timer_.IsRunning();
}

bool StateController::WaitingForCrashBootCollect() const {
  return wait_for_crash_boot_collect_timer_.IsRunning();
}

bool StateController::WaitingForInitialUserActivity() const {
  return wait_for_initial_user_activity_ &&
         session_state_ == SessionState::STARTED &&
         !saw_user_activity_during_current_session_;
}

void StateController::MaybeStopInitialStateTimer() {
  if (got_initial_display_mode_ && got_initial_policy_)
    initial_state_timer_.Stop();
}

void StateController::StopWaitForExternalDisplayTimer() {
  wait_for_external_display_timer_.Stop();
}

void StateController::MaybeStopWaitForCrashBootCollectTimer(
    const base::FilePath& path, bool error) {
  if (base::PathExists(base::FilePath(kCrashBootCollectorDoneFile)) &&
      wait_for_crash_boot_collect_timer_.IsRunning()) {
    wait_for_crash_boot_collect_timer_.Stop();
    if (lid_state_ == LidState::CLOSED)
      UpdateState();
  }
}

bool StateController::IsIdleBlocked() const {
  return (use_audio_activity_ && audio_activity_->active()) ||
         screen_wake_lock_->active() || dim_wake_lock_->active() ||
         system_wake_lock_->active();
}

bool StateController::IsScreenDimBlocked() const {
  return screen_wake_lock_->active();
}

bool StateController::IsScreenOffBlocked() const {
  // If HDMI audio is active, the screen needs to be kept on.
  return IsScreenDimBlocked() || dim_wake_lock_->active() ||
         (delegate_->IsHdmiAudioActive() && audio_activity_->active());
}

bool StateController::IsScreenLockBlocked() const {
  return IsScreenDimBlocked() || dim_wake_lock_->active();
}

base::TimeTicks StateController::GetLastActivityTimeForIdle(
    base::TimeTicks now) const {
  base::TimeTicks last_time =
      WaitingForInitialUserActivity() ? now : last_user_activity_time_;
  if (use_audio_activity_)
    last_time = std::max(last_time, audio_activity_->GetLastActiveTime(now));
  if (use_video_activity_)
    last_time = std::max(last_time, last_video_activity_time_);
  last_time = std::max(last_time, last_defer_screen_dim_time_);
  last_time = std::max(last_time, last_wake_notification_time_);

  // All types of wake locks defer the idle action.
  last_time = std::max(last_time, screen_wake_lock_->GetLastActiveTime(now));
  last_time = std::max(last_time, dim_wake_lock_->GetLastActiveTime(now));
  last_time = std::max(last_time, system_wake_lock_->GetLastActiveTime(now));

  return last_time;
}

base::TimeTicks StateController::GetLastActivityTimeForScreenDim(
    base::TimeTicks now) const {
  base::TimeTicks last_time =
      WaitingForInitialUserActivity() ? now : last_user_activity_time_;
  if (use_video_activity_)
    last_time = std::max(last_time, last_video_activity_time_);
  last_time = std::max(last_time, last_defer_screen_dim_time_);
  last_time = std::max(last_time, last_wake_notification_time_);

  // Only full-brightness wake locks keep the screen from dimming.
  last_time = std::max(last_time, screen_wake_lock_->GetLastActiveTime(now));

  return last_time;
}

base::TimeTicks StateController::GetLastActivityTimeForRequestSmartDim(
    base::TimeTicks now) const {
  base::TimeTicks last_time = GetLastActivityTimeForScreenDim(now);
  last_time = std::max(last_time, last_smart_dim_decision_request_time_);
  return last_time;
}

base::TimeTicks StateController::GetLastActivityTimeForScreenOff(
    base::TimeTicks now) const {
  base::TimeTicks last_time = GetLastActivityTimeForScreenDim(now);

  // On-but-dimmed wake locks keep the screen on.
  last_time = std::max(last_time, dim_wake_lock_->GetLastActiveTime(now));

  // If HDMI audio is active, the screen needs to be kept on.
  if (delegate_->IsHdmiAudioActive())
    last_time = std::max(last_time, audio_activity_->GetLastActiveTime(now));

  return last_time;
}

base::TimeTicks StateController::GetLastActivityTimeForScreenLock(
    base::TimeTicks now) const {
  // On-but-dimmed wake locks also keep the screen from locking.
  return std::max(GetLastActivityTimeForScreenDim(now),
                  dim_wake_lock_->GetLastActiveTime(now));
}

void StateController::UpdateLastUserActivityTime() {
  last_user_activity_time_ = clock_->GetCurrentTime();
  delegate_->ReportUserActivityMetrics();
}

void StateController::LoadPrefs() {
  prefs_->GetBool(kRequireUsbInputDeviceToSuspendPref,
                  &require_usb_input_device_to_suspend_);
  prefs_->GetBool(kAvoidSuspendWhenHeadphoneJackPluggedPref,
                  &avoid_suspend_when_headphone_jack_plugged_);
  prefs_->GetBool(kDisableIdleSuspendPref, &disable_idle_suspend_);
  prefs_->GetBool(kFactoryModePref, &factory_mode_);
  prefs_->GetBool(kIgnoreExternalPolicyPref, &ignore_external_policy_);

  int64_t tpm_threshold = 0;
  prefs_->GetInt64(kTpmCounterSuspendThresholdPref, &tpm_threshold);
  tpm_dictionary_attack_suspend_threshold_ = static_cast<int>(tpm_threshold);

  CHECK(
      GetMillisecondPref(prefs_, kPluggedSuspendMsPref, &pref_ac_delays_.idle));
  CHECK(GetMillisecondPref(prefs_, kPluggedOffMsPref,
                           &pref_ac_delays_.screen_off));
  CHECK(GetMillisecondPref(prefs_, kPluggedDimMsPref,
                           &pref_ac_delays_.screen_dim));

  CHECK(GetMillisecondPref(prefs_, kUnpluggedSuspendMsPref,
                           &pref_battery_delays_.idle));
  CHECK(GetMillisecondPref(prefs_, kUnpluggedOffMsPref,
                           &pref_battery_delays_.screen_off));
  CHECK(GetMillisecondPref(prefs_, kUnpluggedDimMsPref,
                           &pref_battery_delays_.screen_dim));

  SanitizeDelays(&pref_ac_delays_);
  SanitizeDelays(&pref_battery_delays_);

  // Don't wait around for the external policy if the controller has been
  // instructed to ignore it.
  if (ignore_external_policy_) {
    got_initial_policy_ = true;
    MaybeStopInitialStateTimer();
  }
}

void StateController::UpdateSettingsAndState() {
  const Action old_idle_action = idle_action_;
  const Action old_lid_closed_action = lid_closed_action_;
  const Delays old_delays = delays_;

  const bool on_ac = power_source_ == PowerSource::AC;
  const bool presenting = display_mode_ == DisplayMode::PRESENTATION;

  // Start out with the defaults loaded from the power manager's prefs.
  idle_action_ = Action::SUSPEND;
  lid_closed_action_ = Action::SUSPEND;
  delays_ = on_ac ? pref_ac_delays_ : pref_battery_delays_;
  use_audio_activity_ = true;
  use_video_activity_ = true;
  wait_for_initial_user_activity_ = false;
  double presentation_factor = 1.0;
  double user_activity_factor = 1.0;
  reason_for_ignoring_idle_action_.clear();

  // Now update them with values that were set in the policy.
  if (!ignore_external_policy_) {
    if (on_ac && policy_.has_ac_idle_action())
      idle_action_ = ProtoActionToAction(policy_.ac_idle_action());
    else if (!on_ac && policy_.has_battery_idle_action())
      idle_action_ = ProtoActionToAction(policy_.battery_idle_action());
    if (policy_.has_lid_closed_action())
      lid_closed_action_ = ProtoActionToAction(policy_.lid_closed_action());

    if (on_ac && policy_.has_ac_delays())
      MergeDelaysFromPolicy(policy_.ac_delays(), &delays_);
    else if (!on_ac && policy_.has_battery_delays())
      MergeDelaysFromPolicy(policy_.battery_delays(), &delays_);

    if (policy_.has_use_audio_activity())
      use_audio_activity_ = policy_.use_audio_activity();
    if (policy_.has_use_video_activity())
      use_video_activity_ = policy_.use_video_activity();
    if (policy_.has_presentation_screen_dim_delay_factor())
      presentation_factor = policy_.presentation_screen_dim_delay_factor();
    if (policy_.has_user_activity_screen_dim_delay_factor())
      user_activity_factor = policy_.user_activity_screen_dim_delay_factor();
    if (policy_.has_wait_for_initial_user_activity()) {
      wait_for_initial_user_activity_ =
          policy_.wait_for_initial_user_activity();
    }
  }

  if (presenting)
    ScaleDelays(&delays_, presentation_factor);
  else if (saw_user_activity_soon_after_screen_dim_or_off_)
    ScaleDelays(&delays_, user_activity_factor);

  if (idle_action_ == Action::SUSPEND || idle_action_ == Action::SHUT_DOWN) {
    // The disable-idle-suspend pref overrides |policy_|. Note that it also
    // prevents the system from shutting down on idle if no session has been
    // started.
    if (disable_idle_suspend_) {
      idle_action_ = Action::DO_NOTHING;
      reason_for_ignoring_idle_action_ =
          "disable_idle_suspend powerd pref is set (done automatically in dev)";
    }

    // Avoid suspending or shutting down due to inactivity while a system
    // update is being applied on AC power so users on slow connections can
    // get updates. Continue suspending on lid-close so users don't get
    // confused, though.
    if (updater_state_ == UpdaterState::UPDATING && on_ac) {
      idle_action_ = Action::DO_NOTHING;
      reason_for_ignoring_idle_action_ = "applying update on AC power";
    }

    // Avoid suspending or shutting down due to inactivity immediately after
    // resume if we are waiting for external display.
    if (WaitingForExternalDisplay()) {
      idle_action_ = Action::DO_NOTHING;
      reason_for_ignoring_idle_action_ =
          "waiting for display mode change on resuming with lid closed";
    }
  }

  // Ignore the lid being closed while presenting to support docked mode.
  if (presenting)
    lid_closed_action_ = Action::DO_NOTHING;

  // Override the idle and lid-closed actions to suspend instead of shutting
  // down if the TPM dictionary-attack counter is high.
  if (tpm_dictionary_attack_suspend_threshold_ > 0 &&
      tpm_dictionary_attack_count_ >=
          tpm_dictionary_attack_suspend_threshold_) {
    LOG(WARNING) << "TPM dictionary attack count is "
                 << tpm_dictionary_attack_count_ << " (threshold is "
                 << tpm_dictionary_attack_suspend_threshold_ << "); "
                 << "overriding actions to suspend instead of shutting down";
    if (idle_action_ == Action::SHUT_DOWN)
      idle_action_ = Action::SUSPEND;
    if (lid_closed_action_ == Action::SHUT_DOWN)
      lid_closed_action_ = Action::SUSPEND;
  }

  // Most functionality is disabled in factory mode.
  if (factory_mode_) {
    delays_.screen_dim = base::TimeDelta();
    delays_.screen_off = base::TimeDelta();
    delays_.screen_lock = base::TimeDelta();
    lid_closed_action_ = Action::DO_NOTHING;
    idle_action_ = Action::DO_NOTHING;
    reason_for_ignoring_idle_action_ = "factory mode is enabled";
  }

  SanitizeDelays(&delays_);

  delays_.screen_dim_imminent = std::max(
      delays_.screen_dim - kScreenDimImminentInterval, base::TimeDelta());

  // If the idle or lid-closed actions changed, make sure that we perform
  // the new actions in the event that the system is already idle or the
  // lid is already closed.
  if (idle_action_ != old_idle_action)
    idle_action_performed_ = false;
  if (lid_closed_action_ != old_lid_closed_action)
    lid_closed_action_performed_ = false;

  // Let UpdateState() know if it may need to re-send the warning with an
  // updated time-until-idle-action.
  resend_idle_warning_ = sent_idle_warning_ &&
                         delays_.idle_warning != base::TimeDelta() &&
                         delays_.idle != old_delays.idle;

  LogSettings();

  if (delays_ != old_delays) {
    dbus_wrapper_->EmitSignalWithProtocolBuffer(kInactivityDelaysChangedSignal,
                                                CreateInactivityDelaysProto());
  }

  UpdateState();
}

void StateController::LogSettings() {
  std::vector<std::string> wake_locks;
  wake_locks.reserve(3);
  if (screen_wake_lock_->active())
    wake_locks.emplace_back("screen");
  if (dim_wake_lock_->active())
    wake_locks.emplace_back("dim");
  if (system_wake_lock_->active())
    wake_locks.emplace_back("system");

  LOG(INFO) << "Updated settings:"
            << " dim=" << util::TimeDeltaToString(delays_.screen_dim)
            << " screen_off=" << util::TimeDeltaToString(delays_.screen_off)
            << " lock=" << util::TimeDeltaToString(delays_.screen_lock)
            << " idle_warn=" << util::TimeDeltaToString(delays_.idle_warning)
            << " idle=" << util::TimeDeltaToString(delays_.idle) << " ("
            << ActionToString(idle_action_) << ")"
            << " lid_closed=" << ActionToString(lid_closed_action_)
            << " use_audio=" << use_audio_activity_
            << " use_video=" << use_video_activity_
            << " wake_locks=" << base::JoinString(wake_locks, ",");

  if (wait_for_initial_user_activity_) {
    LOG(INFO) << "Deferring inactivity-triggered actions until user activity "
              << "is observed each time a session starts";
  }
}

void StateController::PerformAction(Action action, ActionReason reason) {
  switch (action) {
    case Action::SUSPEND:
      delegate_->Suspend(reason);
      break;
    case Action::STOP_SESSION:
      delegate_->StopSession();
      break;
    case Action::SHUT_DOWN:
      delegate_->ShutDown();
      break;
    case Action::DO_NOTHING:
      break;
    default:
      NOTREACHED() << "Unhandled action " << static_cast<int>(action);
  }
}

StateController::Action StateController::GetIdleAction() const {
  if (!delegate_->IsOobeCompleted()) {
    LOG(INFO) << "Not performing idle action without OOBE completed";
    return Action::DO_NOTHING;
  }
  if (idle_action_ == Action::SUSPEND && require_usb_input_device_to_suspend_ &&
      !delegate_->IsUsbInputDeviceConnected()) {
    LOG(INFO) << "Not suspending for idle without USB input device";
    return Action::DO_NOTHING;
  }
  if (idle_action_ == Action::SUSPEND &&
      avoid_suspend_when_headphone_jack_plugged_ &&
      delegate_->IsHeadphoneJackPlugged()) {
    LOG(INFO) << "Not suspending for idle due to headphone jack";
    return Action::DO_NOTHING;
  }
  return idle_action_;
}

void StateController::UpdateState() {
  base::TimeTicks now = clock_->GetCurrentTime();
  base::TimeDelta idle_duration = now - GetLastActivityTimeForIdle(now);
  base::TimeDelta request_smart_dim_decision_duration =
      now - GetLastActivityTimeForRequestSmartDim(now);
  base::TimeDelta screen_dim_duration =
      now - GetLastActivityTimeForScreenDim(now);
  base::TimeDelta screen_off_duration =
      now - GetLastActivityTimeForScreenOff(now);
  base::TimeDelta screen_lock_duration =
      now - GetLastActivityTimeForScreenLock(now);

  if (request_smart_dim_decision_ && ml_decision_service_available_ &&
      delays_.screen_dim_imminent > base::TimeDelta() &&
      request_smart_dim_decision_duration >= delays_.screen_dim_imminent &&
      !waiting_for_smart_dim_decision_ && !screen_dimmed_) {
    RequestSmartDimDecision();
    last_smart_dim_decision_request_time_ = clock_->GetCurrentTime();
    waiting_for_smart_dim_decision_ = true;
  }

  const bool screen_was_dimmed = screen_dimmed_;
  HandleDelay(delays_.screen_dim, screen_dim_duration,
              base::Bind(&Delegate::DimScreen, base::Unretained(delegate_)),
              base::Bind(&Delegate::UndimScreen, base::Unretained(delegate_)),
              "Dimming screen", "Undimming screen", &screen_dimmed_);
  if (screen_dimmed_ && !screen_was_dimmed && audio_activity_->active() &&
      delegate_->IsHdmiAudioActive()) {
    LOG(INFO) << "Audio is currently being sent to display; screen will not be "
              << "turned off for inactivity";
  }

  const bool screen_was_turned_off = screen_turned_off_;
  HandleDelay(delays_.screen_off, screen_off_duration,
              base::Bind(&Delegate::TurnScreenOff, base::Unretained(delegate_)),
              base::Bind(&Delegate::TurnScreenOn, base::Unretained(delegate_)),
              "Turning screen off", "Turning screen on", &screen_turned_off_);
  if (screen_turned_off_ && !screen_was_turned_off)
    screen_turned_off_time_ = now;
  else if (!screen_turned_off_)
    screen_turned_off_time_ = base::TimeTicks();

  HandleDelay(delays_.screen_lock, screen_lock_duration,
              base::Bind(&Delegate::LockScreen, base::Unretained(delegate_)),
              base::Closure(), "Locking screen", "", &requested_screen_lock_);

  if (screen_dimmed_ != screen_was_dimmed ||
      screen_turned_off_ != screen_was_turned_off) {
    EmitScreenIdleStateChanged(screen_dimmed_, screen_turned_off_);
  }

  // The idle-imminent signal is only emitted if an idle action is set.
  if (delays_.idle_warning > base::TimeDelta() &&
      idle_duration >= delays_.idle_warning &&
      idle_action_ != Action::DO_NOTHING) {
    if (!sent_idle_warning_ || resend_idle_warning_) {
      const base::TimeDelta time_until_idle = delays_.idle - idle_duration;
      LOG(INFO) << "Emitting idle-imminent signal with "
                << util::TimeDeltaToString(time_until_idle) << " after "
                << util::TimeDeltaToString(idle_duration);
      IdleActionImminent proto;
      proto.set_time_until_idle_action(time_until_idle.ToInternalValue());
      dbus_wrapper_->EmitSignalWithProtocolBuffer(kIdleActionImminentSignal,
                                                  proto);
      sent_idle_warning_ = true;
    }
  } else if (sent_idle_warning_) {
    sent_idle_warning_ = false;
    // When resetting the idle-warning trigger, only emit the idle-deferred
    // signal if the idle action hasn't been performed yet or if it was a
    // no-op action.
    if (!idle_action_performed_ || idle_action_ == Action::DO_NOTHING) {
      LOG(INFO) << "Emitting idle-deferred signal";
      dbus_wrapper_->EmitBareSignal(kIdleActionDeferredSignal);
    }
  }
  resend_idle_warning_ = false;

  Action idle_action_to_perform = Action::DO_NOTHING;
  if (idle_duration >= delays_.idle) {
    if (!idle_action_performed_) {
      if (!reason_for_ignoring_idle_action_.empty()) {
        LOG(INFO) << "Not performing idle action because "
                  << reason_for_ignoring_idle_action_;
      }
      idle_action_to_perform = GetIdleAction();
      LOG(INFO) << "Ready to perform idle action ("
                << ActionToString(idle_action_to_perform) << ") after "
                << util::TimeDeltaToString(idle_duration);
      idle_action_performed_ = true;
    }
  } else {
    idle_action_performed_ = false;
  }

  Action lid_closed_action_to_perform = Action::DO_NOTHING;
  // Hold off on the lid-closed action if
  //  1. The initial display mode or policy hasn't been received. powerd starts
  //     before Chrome's gotten a chance to configure the displays and send the
  //     policy, and we don't want to shut down immediately if the user rebooted
  //     with the lid closed.
  //  2. Just resumed with lid still closed. Chrome takes a little bit of time
  //     to identify and configure external display and we don't want to suspend
  //     immediately if the device resumes with the lid still closed.
  //  3. Booted with closed lid and crash_reporter has not yet collected
  //     per-boot crash logs. Look at (crbug.com/988831) for more info.

  if (lid_state_ == LidState::CLOSED && !WaitingForInitialState() &&
      !WaitingForExternalDisplay() && !WaitingForCrashBootCollect()) {
    if (!lid_closed_action_performed_) {
      lid_closed_action_to_perform = lid_closed_action_;
      LOG(INFO) << "Ready to perform lid-closed action ("
                << ActionToString(lid_closed_action_to_perform) << ")";
      lid_closed_action_performed_ = true;
    }
  } else {
    lid_closed_action_performed_ = false;
  }

  if (idle_action_to_perform == Action::SHUT_DOWN ||
      lid_closed_action_to_perform == Action::SHUT_DOWN) {
    // If either of the actions is shutting down, don't perform the other.
    PerformAction(Action::SHUT_DOWN, idle_action_to_perform == Action::SHUT_DOWN
                                         ? ActionReason::IDLE
                                         : ActionReason::LID_CLOSED);
  } else if (idle_action_to_perform == lid_closed_action_to_perform) {
    // If both actions are the same, only perform it once.
    PerformAction(idle_action_to_perform, ActionReason::IDLE);
  } else {
    // Otherwise, perform both actions.  Note that one or both may be
    // DO_NOTHING.
    PerformAction(idle_action_to_perform, ActionReason::IDLE);
    PerformAction(lid_closed_action_to_perform, ActionReason::LID_CLOSED);
  }

  ScheduleActionTimeout(now);
}

void StateController::ScheduleActionTimeout(base::TimeTicks now) {
  // Find the minimum of the delays that haven't yet occurred.
  base::TimeDelta timeout_delay;
  if (!IsScreenDimBlocked()) {
    if (request_smart_dim_decision_) {
      UpdateActionTimeout(now, GetLastActivityTimeForScreenDim(now),
                          delays_.screen_dim_imminent, &timeout_delay);
    }
    UpdateActionTimeout(now, GetLastActivityTimeForScreenDim(now),
                        delays_.screen_dim, &timeout_delay);
  }
  if (!IsScreenOffBlocked()) {
    UpdateActionTimeout(now, GetLastActivityTimeForScreenOff(now),
                        delays_.screen_off, &timeout_delay);
  }
  if (!IsScreenLockBlocked()) {
    UpdateActionTimeout(now, GetLastActivityTimeForScreenLock(now),
                        delays_.screen_lock, &timeout_delay);
  }
  if (!IsIdleBlocked()) {
    UpdateActionTimeout(now, GetLastActivityTimeForIdle(now),
                        delays_.idle_warning, &timeout_delay);
    UpdateActionTimeout(now, GetLastActivityTimeForIdle(now), delays_.idle,
                        &timeout_delay);
  }

  if (timeout_delay > base::TimeDelta()) {
    action_timer_.Start(FROM_HERE, timeout_delay, this,
                        &StateController::HandleActionTimeout);
    action_timer_time_for_testing_ = now + timeout_delay;
  } else {
    action_timer_.Stop();
    action_timer_time_for_testing_ = base::TimeTicks();
  }
}

void StateController::HandleActionTimeout() {
  action_timer_time_for_testing_ = base::TimeTicks();
  UpdateState();
}

void StateController::HandleInitialStateTimeout() {
  LOG(INFO) << "Didn't receive initial notification about display mode or "
            << "policy; using " << DisplayModeToString(display_mode_)
            << " display mode";
  UpdateState();
}

void StateController::HandleCrashBootCollectTimeout() {
  LOG(INFO) << "CrashBootCollect did not complete sucessfully in "
            << util::TimeDeltaToString(kCrashBootCollectTimeout);
  if (lid_state_ == LidState::CLOSED)
    UpdateState();
}

void StateController::HandleWaitForExternalDisplayTimeout() {
  LOG(INFO) << "Didn't receive display mode change notification in "
            << util::TimeDeltaToString(KWaitForExternalDisplayTimeout)
            << " on resuming with lid closed";
  UpdateSettingsAndState();
}

void StateController::HandleGetInactivityDelaysMethodCall(
    dbus::MethodCall* method_call,
    dbus::ExportedObject::ResponseSender response_sender) {
  std::unique_ptr<dbus::Response> response(
      dbus::Response::FromMethodCall(method_call));
  dbus::MessageWriter writer(response.get());
  writer.AppendProtoAsArrayOfBytes(CreateInactivityDelaysProto());
  std::move(response_sender).Run(std::move(response));
}

void StateController::HandleUpdateEngineAvailable(bool available) {
  if (!available) {
    LOG(ERROR) << "Failed waiting for update engine to become available";
    return;
  }

  dbus::MethodCall method_call(update_engine::kUpdateEngineInterface,
                               update_engine::kGetStatusAdvanced);
  std::unique_ptr<dbus::Response> response = dbus_wrapper_->CallMethodSync(
      update_engine_dbus_proxy_, &method_call, kUpdateEngineDBusTimeout);
  if (!response)
    return;

  HandleUpdateEngineStatusMessage(response.get());
}

void StateController::HandleUpdateEngineStatusUpdateSignal(
    dbus::Signal* signal) {
  HandleUpdateEngineStatusMessage(signal);
}

void StateController::HandleUpdateEngineStatusMessage(dbus::Message* message) {
  DCHECK(message);
  dbus::MessageReader reader(message);
  update_engine::StatusResult status;
  if (!reader.PopArrayOfBytesAsProto(&status)) {
    LOG(ERROR) << "Unable to read update status args.";
    return;
  }

  update_engine::Operation operation = status.current_operation();
  // TODO(crbug.com/977320): Through the protobuf we don't have access to the
  // string value of the current operation. One way to get around this is to add
  // a new |current_operation_string| value to the protobuf with the current
  // operation's string representation for these logging purposes.
  LOG(INFO) << "Update operation is " << operation;
  UpdaterState state = UpdaterState::IDLE;
  if (operation == update_engine::Operation::DOWNLOADING ||
      operation == update_engine::Operation::VERIFYING ||
      operation == update_engine::Operation::FINALIZING) {
    state = UpdaterState::UPDATING;
  } else if (operation == update_engine::Operation::UPDATED_NEED_REBOOT) {
    state = UpdaterState::UPDATED;
  }

  if (state == updater_state_)
    return;

  updater_state_ = state;
  UpdateSettingsAndState();
}

void StateController::EmitScreenIdleStateChanged(bool dimmed, bool off) {
  ScreenIdleState proto;
  proto.set_dimmed(dimmed);
  proto.set_off(off);
  dbus_wrapper_->EmitSignalWithProtocolBuffer(kScreenIdleStateChangedSignal,
                                              proto);
}

void StateController::HandleMlDecisionServiceAvailable(bool available) {
  ml_decision_service_available_ = available;
  if (!available) {
    LOG(ERROR) << "Failed waiting for ml decision service to become "
                  "available";
    return;
  }
}

void StateController::RequestSmartDimDecision() {
  dbus::MethodCall method_call(
      chromeos::kMlDecisionServiceInterface,
      chromeos::kMlDecisionServiceShouldDeferScreenDimMethod);

  dbus_wrapper_->CallMethodAsync(
      ml_decision_dbus_proxy_, &method_call, kSmartDimDecisionTimeout,
      base::Bind(&StateController::HandleSmartDimResponse,
                 weak_ptr_factory_.GetWeakPtr()));
}

void StateController::HandleSmartDimResponse(dbus::Response* response) {
  screen_dim_deferred_for_testing_ = false;
  if (!waiting_for_smart_dim_decision_) {
    LOG(WARNING) << "Smart dim decision is not being waited for";
    return;
  }

  waiting_for_smart_dim_decision_ = false;

  if (screen_dimmed_) {
    VLOG(1) << "Screen is already dimmed";
    return;
  }

  if (!response) {
    LOG(ERROR) << "D-Bus method call to "
               << chromeos::kMlDecisionServiceInterface << "."
               << chromeos::kMlDecisionServiceShouldDeferScreenDimMethod
               << " failed";
    return;
  }

  dbus::MessageReader reader(response);
  bool should_defer_screen_dim = false;
  if (!reader.PopBool(&should_defer_screen_dim)) {
    LOG(ERROR) << "Unable to read info from "
               << chromeos::kMlDecisionServiceInterface << "."
               << chromeos::kMlDecisionServiceShouldDeferScreenDimMethod
               << " response";
    return;
  }

  if (!should_defer_screen_dim) {
    VLOG(1) << "Smart dim decided not to defer screen dimming";
    return;
  }

  screen_dim_deferred_for_testing_ = true;
  LOG(INFO) << "Smart dim decided to defer screen dimming";
  last_defer_screen_dim_time_ = clock_->GetCurrentTime();
  UpdateState();
}

}  // namespace policy
}  // namespace power_manager
