// 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 "power_manager/powerd/daemon.h"

#include <inttypes.h>

#include <algorithm>
#include <cmath>
#include <map>
#include <utility>

#include <base/bind.h>
#include <base/files/file_util.h>
#include <base/format_macros.h>
#include <base/logging.h>
#include <base/strings/string_number_conversions.h>
#include <base/strings/string_split.h>
#include <base/strings/string_util.h>
#include <base/strings/stringprintf.h>
#include <base/threading/platform_thread.h>
#include <chromeos/dbus/service_constants.h>
#include <dbus/message.h>

#include "cryptohome/proto_bindings/rpc.pb.h"
#include "power_manager/common/activity_logger.h"
#include "power_manager/common/battery_percentage_converter.h"
#include "power_manager/common/metrics_sender.h"
#include "power_manager/common/power_constants.h"
#include "power_manager/common/prefs.h"
#include "power_manager/common/util.h"
#if USE_BUFFET
#include "power_manager/powerd/buffet/command_handlers.h"
#endif
#include "power_manager/powerd/daemon_delegate.h"
#include "power_manager/powerd/metrics_collector.h"
#include "power_manager/powerd/policy/backlight_controller.h"
#include "power_manager/powerd/policy/input_device_controller.h"
#include "power_manager/powerd/policy/keyboard_backlight_controller.h"
#include "power_manager/powerd/policy/shutdown_from_suspend.h"
#include "power_manager/powerd/policy/state_controller.h"
#include "power_manager/powerd/system/acpi_wakeup_helper_interface.h"
#include "power_manager/powerd/system/ambient_light_sensor_manager.h"
#include "power_manager/powerd/system/arc_timer_manager.h"
#include "power_manager/powerd/system/audio_client_interface.h"
#include "power_manager/powerd/system/backlight_interface.h"
#include "power_manager/powerd/system/charge_controller_helper_interface.h"
#include "power_manager/powerd/system/cros_ec_helper_interface.h"
#include "power_manager/powerd/system/dark_resume_interface.h"
#include "power_manager/powerd/system/dbus_wrapper.h"
#include "power_manager/powerd/system/display/display_power_setter.h"
#include "power_manager/powerd/system/display/display_watcher.h"
#include "power_manager/powerd/system/event_device_interface.h"
#include "power_manager/powerd/system/input_watcher_interface.h"
#include "power_manager/powerd/system/lockfile_checker.h"
#include "power_manager/powerd/system/peripheral_battery_watcher.h"
#include "power_manager/powerd/system/power_supply.h"
#include "power_manager/powerd/system/smart_discharge_configurator.h"
#include "power_manager/powerd/system/suspend_configurator.h"
#include "power_manager/powerd/system/udev.h"
#include "power_manager/powerd/system/user_proximity_watcher_interface.h"
#include "power_manager/powerd/system/wake_on_dp_configurator.h"
#include "power_manager/powerd/system/wakeup_source_identifier.h"
#include "power_manager/powerd/system/wilco_charge_controller_helper.h"
#include "power_manager/proto_bindings/idle.pb.h"
#include "power_manager/proto_bindings/policy.pb.h"

#if USE_BUFFET
namespace dbus {
class Bus;
}  // namespace dbus
#endif  // USE_BUFFET

namespace power_manager {
namespace {

// Default values for |*_path_| members (which can be overridden for tests).
const char kDefaultSuspendedStatePath[] =
    "/var/lib/power_manager/powerd_suspended";
const char kDefaultWakeupCountPath[] = "/sys/power/wakeup_count";
const char kDefaultOobeCompletedPath[] = "/home/chronos/.oobe_completed";

// Directory checked for lockfiles indicating that powerd shouldn't suspend or
// shut down the system (typically due to a firmware update).
const char kPowerOverrideLockfileDir[] = "/run/lock/power_override";

// Basename appended to |run_dir| (see Daemon's c'tor) to produce
// |suspend_announced_path_|.
const char kSuspendAnnouncedFile[] = "suspend_announced";

// Strings for states that powerd cares about from the session manager's
// SessionStateChanged signal. This value is defined in the session_manager
// codebase.
const char kSessionStarted[] = "started";

// After noticing that power management is overridden while suspending, wait up
// to this long for the lockfile(s) to be removed before reporting a suspend
// failure. The event loop is blocked during this period.
constexpr base::TimeDelta kSuspendLockfileTimeout =
    base::TimeDelta::FromMilliseconds(500);

// Interval between successive polls during kSuspendLockfileTimeout.
constexpr base::TimeDelta kSuspendLockfilePollInterval =
    base::TimeDelta::FromMilliseconds(100);

// Interval between attempts to retry shutting the system down while power
// management is overridden, in seconds.
constexpr base::TimeDelta kShutdownLockfileRetryInterval =
    base::TimeDelta::FromSeconds(5);

// Maximum amount of time to wait for responses to D-Bus method calls to other
// processes.
const int kSessionManagerDBusTimeoutMs = 3000;
const int kCryptohomedDBusTimeoutMs = 2 * 60 * 1000;  // Two minutes.

// Interval between log messages while user, audio, or video activity is
// ongoing, in seconds.
const int kLogOngoingActivitySec = 180;

// Time after the last report from Chrome of video or user activity at which
// point a message is logged about the activity having stopped. Chrome reports
// these every five seconds, but longer delays here reduce the amount of log
// spam due to sporadic activity.
const int kLogVideoActivityStoppedDelaySec = 20;
const int kLogUserActivityStoppedDelaySec = 20;

// Delay to wait before logging that hovering has stopped. This is ideally
// smaller than kKeyboardBacklightKeepOnMsPref; otherwise the backlight can be
// turned off before the hover-off event that triggered it is logged.
const int64_t kLogHoveringStoppedDelaySec = 20;

// Passes |method_call| to |handler| and passes the response to
// |response_sender|. If |handler| returns NULL, an empty response is
// created and sent.
void HandleSynchronousDBusMethodCall(
    base::Callback<std::unique_ptr<dbus::Response>(dbus::MethodCall*)> handler,
    dbus::MethodCall* method_call,
    dbus::ExportedObject::ResponseSender response_sender) {
  std::unique_ptr<dbus::Response> response = handler.Run(method_call);
  if (!response)
    response = dbus::Response::FromMethodCall(method_call);
  response_sender.Run(std::move(response));
}

// Creates a new "invalid args" reply to |method_call|.
std::unique_ptr<dbus::Response> CreateInvalidArgsError(
    dbus::MethodCall* method_call, std::string message) {
  return std::unique_ptr<dbus::Response>(dbus::ErrorResponse::FromMethodCall(
      method_call, DBUS_ERROR_INVALID_ARGS, message));
}

}  // namespace

// static
constexpr char Daemon::kAlreadyRanFileName[];

// Performs actions requested by |state_controller_|.  The reason that
// this is a nested class of Daemon rather than just being implemented as
// part of Daemon is to avoid method naming conflicts.
class Daemon::StateControllerDelegate
    : public policy::StateController::Delegate {
 public:
  explicit StateControllerDelegate(Daemon* daemon) : daemon_(daemon) {}
  ~StateControllerDelegate() override { daemon_ = nullptr; }

  // Overridden from policy::StateController::Delegate:
  bool IsUsbInputDeviceConnected() override {
    return daemon_->input_watcher_->IsUSBInputDeviceConnected();
  }

  bool IsOobeCompleted() override {
    return base::PathExists(base::FilePath(daemon_->oobe_completed_path_));
  }

  bool IsHdmiAudioActive() override {
    return daemon_->audio_client_ ? daemon_->audio_client_->GetHdmiActive()
                                  : false;
  }

  bool IsHeadphoneJackPlugged() override {
    return daemon_->audio_client_
               ? daemon_->audio_client_->GetHeadphoneJackPlugged()
               : false;
  }

  void DimScreen() override { daemon_->SetBacklightsDimmedForInactivity(true); }

  void UndimScreen() override {
    daemon_->SetBacklightsDimmedForInactivity(false);
  }

  void TurnScreenOff() override {
    daemon_->SetBacklightsOffForInactivity(true);
  }

  void TurnScreenOn() override {
    daemon_->SetBacklightsOffForInactivity(false);
  }

  void LockScreen() override {
    dbus::MethodCall method_call(login_manager::kSessionManagerInterface,
                                 login_manager::kSessionManagerLockScreen);
    daemon_->dbus_wrapper_->CallMethodSync(
        daemon_->session_manager_dbus_proxy_, &method_call,
        base::TimeDelta::FromMilliseconds(kSessionManagerDBusTimeoutMs));
  }

  void Suspend(policy::StateController::ActionReason reason) override {
    SuspendImminent::Reason suspend_reason = SuspendImminent_Reason_OTHER;
    switch (reason) {
      case policy::StateController::ActionReason::IDLE:
        suspend_reason = SuspendImminent_Reason_IDLE;
        break;
      case policy::StateController::ActionReason::LID_CLOSED:
        suspend_reason = SuspendImminent_Reason_LID_CLOSED;
        break;
    }
    daemon_->Suspend(suspend_reason, false, 0, base::TimeDelta());
  }

  void StopSession() override {
    // This session manager method takes a string argument, although it
    // doesn't currently do anything with it.
    dbus::MethodCall method_call(login_manager::kSessionManagerInterface,
                                 login_manager::kSessionManagerStopSession);
    dbus::MessageWriter writer(&method_call);
    writer.AppendString("");
    daemon_->dbus_wrapper_->CallMethodSync(
        daemon_->session_manager_dbus_proxy_, &method_call,
        base::TimeDelta::FromMilliseconds(kSessionManagerDBusTimeoutMs));
  }

  void ShutDown() override {
    daemon_->ShutDown(ShutdownMode::POWER_OFF,
                      ShutdownReason::STATE_TRANSITION);
  }

  void ReportUserActivityMetrics() override {
    daemon_->metrics_collector_->GenerateUserActivityMetrics();
  }

 private:
  Daemon* daemon_;  // weak

  DISALLOW_COPY_AND_ASSIGN(StateControllerDelegate);
};

Daemon::Daemon(DaemonDelegate* delegate, const base::FilePath& run_dir)
    : delegate_(delegate),
      state_controller_delegate_(new StateControllerDelegate(this)),
      state_controller_(new policy::StateController),
      input_event_handler_(new policy::InputEventHandler),
      input_device_controller_(new policy::InputDeviceController),
      shutdown_from_suspend_(std::make_unique<policy::ShutdownFromSuspend>()),
      suspender_(new policy::Suspender),
      wifi_controller_(std::make_unique<policy::WifiController>()),
      cellular_controller_(std::make_unique<policy::CellularController>()),
      metrics_collector_(new metrics::MetricsCollector),
      arc_timer_manager_(std::make_unique<system::ArcTimerManager>()),
      retry_shutdown_for_lockfile_timer_(),
      wakeup_count_path_(kDefaultWakeupCountPath),
      oobe_completed_path_(kDefaultOobeCompletedPath),
      run_dir_(run_dir),
      suspended_state_path_(kDefaultSuspendedStatePath),
      suspend_announced_path_(run_dir.Append(kSuspendAnnouncedFile)),
      already_ran_path_(run_dir.Append(Daemon::kAlreadyRanFileName)),
      video_activity_logger_(new PeriodicActivityLogger(
          "Video activity",
          base::TimeDelta::FromSeconds(kLogVideoActivityStoppedDelaySec),
          base::TimeDelta::FromSeconds(kLogOngoingActivitySec))),
      user_activity_logger_(new PeriodicActivityLogger(
          "User activity",
          base::TimeDelta::FromSeconds(kLogUserActivityStoppedDelaySec),
          base::TimeDelta::FromSeconds(kLogOngoingActivitySec))),
      audio_activity_logger_(new StartStopActivityLogger(
          "Audio activity",
          base::TimeDelta(),
          base::TimeDelta::FromSeconds(kLogOngoingActivitySec))),
      hovering_logger_(new StartStopActivityLogger(
          "Hovering",
          base::TimeDelta::FromSeconds(kLogHoveringStoppedDelaySec),
          base::TimeDelta())),
      weak_ptr_factory_(this) {}

Daemon::~Daemon() {
  if (dbus_wrapper_)
    dbus_wrapper_->RemoveObserver(this);
  if (audio_client_)
    audio_client_->RemoveObserver(this);
  if (power_supply_)
    power_supply_->RemoveObserver(this);
}

void Daemon::Init() {
  // Check if this is the first run of powerd after boot.
  first_run_after_boot_ = !base::PathExists(already_ran_path_);
  if (first_run_after_boot_) {
    if (base::WriteFile(already_ran_path_, "", 0) != 0)
      PLOG(ERROR) << "Couldn't create " << already_ran_path_.value();
  }

  prefs_ = delegate_->CreatePrefs();
  InitDBus();

  factory_mode_ = BoolPrefIsTrue(kFactoryModePref);
  if (factory_mode_)
    LOG(INFO) << "Factory mode enabled; most functionality will be disabled";

  metrics_sender_ = delegate_->CreateMetricsSender();
  udev_ = delegate_->CreateUdev();
  input_watcher_ = delegate_->CreateInputWatcher(prefs_.get(), udev_.get());
  suspend_configurator_ = delegate_->CreateSuspendConfigurator(prefs_.get());
  wakeup_source_identifier_ =
      std::make_unique<system::WakeupSourceIdentifier>(udev_.get());

  const TabletMode tablet_mode = input_watcher_->GetTabletMode();
  if (tablet_mode == TabletMode::ON)
    LOG(INFO) << "Tablet mode enabled at startup";
  const LidState lid_state = input_watcher_->QueryLidState();
  if (lid_state == LidState::CLOSED)
    LOG(INFO) << "Lid closed at startup";

  display_watcher_ = delegate_->CreateDisplayWatcher(udev_.get());
  display_power_setter_ =
      delegate_->CreateDisplayPowerSetter(dbus_wrapper_.get());

  // Ignore the ALS and backlights in factory mode.
  if (!factory_mode_) {
    light_sensor_manager_ =
        delegate_->CreateAmbientLightSensorManager(prefs_.get());

    if (BoolPrefIsTrue(kExternalDisplayOnlyPref)) {
      display_backlight_controller_ =
          delegate_->CreateExternalBacklightController(
              display_watcher_.get(), display_power_setter_.get(),
              dbus_wrapper_.get());
    } else {
      display_backlight_ = delegate_->CreateInternalBacklight(
          base::FilePath(kInternalBacklightPath), kInternalBacklightPattern);
      if (!display_backlight_) {
        LOG(ERROR) << "Failed to initialize display backlight under "
                   << kInternalBacklightPath << " using pattern "
                   << kInternalBacklightPattern;
      } else {
        display_backlight_controller_ =
            delegate_->CreateInternalBacklightController(
                display_backlight_.get(), prefs_.get(),
                light_sensor_manager_->GetSensorForInternalBacklight(),
                display_power_setter_.get(), dbus_wrapper_.get(), lid_state);
      }
    }
    if (display_backlight_controller_)
      all_backlight_controllers_.push_back(display_backlight_controller_.get());

    if (BoolPrefIsTrue(kHasKeyboardBacklightPref)) {
      keyboard_backlight_ = delegate_->CreatePluggableInternalBacklight(
          udev_.get(), kKeyboardBacklightUdevSubsystem,
          base::FilePath(kKeyboardBacklightPath), kKeyboardBacklightPattern);
      keyboard_backlight_controller_ =
          delegate_->CreateKeyboardBacklightController(
              keyboard_backlight_.get(), prefs_.get(),
              light_sensor_manager_->GetSensorForKeyboardBacklight(),
              dbus_wrapper_.get(), display_backlight_controller_.get(),
              lid_state, tablet_mode);
      all_backlight_controllers_.push_back(
          keyboard_backlight_controller_.get());
    }
  }

  prefs_->GetBool(kMosysEventlogPref, &log_suspend_with_mosys_eventlog_);
  prefs_->GetBool(kSuspendToIdlePref, &suspend_to_idle_);

  battery_percentage_converter_ =
      BatteryPercentageConverter::CreateFromPrefs(prefs_.get());

  power_supply_ = delegate_->CreatePowerSupply(
      base::FilePath(kPowerStatusPath), prefs_.get(), udev_.get(),
      dbus_wrapper_.get(), battery_percentage_converter_.get());
  power_supply_->AddObserver(this);
  if (!power_supply_->RefreshImmediately())
    LOG(ERROR) << "Initial power supply refresh failed; brace for weirdness";
  const system::PowerStatus power_status = power_supply_->GetPowerStatus();

  metrics_collector_->Init(prefs_.get(), display_backlight_controller_.get(),
                           keyboard_backlight_controller_.get(), power_status,
                           first_run_after_boot_);

  dark_resume_ = delegate_->CreateDarkResume(prefs_.get(),
                                             wakeup_source_identifier_.get());

  shutdown_from_suspend_->Init(prefs_.get(), power_supply_.get());

  suspender_->Init(this, dbus_wrapper_.get(), dark_resume_.get(),
                   display_watcher_.get(), wakeup_source_identifier_.get(),
                   shutdown_from_suspend_.get(), prefs_.get());

  input_event_handler_->Init(input_watcher_.get(), this, display_watcher_.get(),
                             dbus_wrapper_.get(), prefs_.get());

  acpi_wakeup_helper_ = delegate_->CreateAcpiWakeupHelper();
  ec_helper_ = delegate_->CreateCrosEcHelper();
  input_device_controller_->Init(display_backlight_controller_.get(),
                                 udev_.get(), acpi_wakeup_helper_.get(),
                                 ec_helper_.get(), lid_state, tablet_mode,
                                 DisplayMode::NORMAL, prefs_.get());

  const PowerSource power_source =
      power_status.line_power_on ? PowerSource::AC : PowerSource::BATTERY;
  state_controller_->Init(state_controller_delegate_.get(), prefs_.get(),
                          dbus_wrapper_.get(), power_source, lid_state);

  if (BoolPrefIsTrue(kUseCrasPref)) {
    audio_client_ = delegate_->CreateAudioClient(dbus_wrapper_.get(), run_dir_);
    audio_client_->AddObserver(this);
  }

  wifi_controller_->Init(this, prefs_.get(), udev_.get(), tablet_mode);
  cellular_controller_->Init(this, prefs_.get());

  peripheral_battery_watcher_ =
      delegate_->CreatePeripheralBatteryWatcher(dbus_wrapper_.get());
  power_override_lockfile_checker_ = delegate_->CreateLockfileChecker(
      base::FilePath(kPowerOverrideLockfileDir), {});

  user_proximity_watcher_ =
      delegate_->CreateUserProximityWatcher(prefs_.get(), udev_.get());
  user_proximity_handler_ = std::make_unique<policy::UserProximityHandler>();
  user_proximity_handler_->Init(user_proximity_watcher_.get(),
                                wifi_controller_.get(),
                                cellular_controller_.get());

  arc_timer_manager_->Init(dbus_wrapper_.get());

  if (BoolPrefIsTrue(kHasChargeControllerPref)) {
    charge_controller_helper_ = delegate_->CreateChargeControllerHelper();
    charge_controller_ = std::make_unique<policy::ChargeController>(),
    charge_controller_->Init(charge_controller_helper_.get(),
                             battery_percentage_converter_.get());
  }

  // Asynchronously undo the previous force-lid-open request to the EC (if there
  // was one).
  if (!factory_mode_ && BoolPrefIsTrue(kUseLidPref))
    RunSetuidHelper("set_force_lid_open", "--noforce_lid_open", false);

  // This needs to happen *after* all D-Bus methods are exported:
  // https://crbug.com/331431
  CHECK(dbus_wrapper_->PublishService()) << "Failed to publish D-Bus service";

  // configure wake on dp only if the preference is set.
  bool wake_on_dp = false;
  if (prefs_->GetBool(kWakeOnDpPref, &wake_on_dp))
    system::ConfigureWakeOnDp(wake_on_dp);

  // Configure wake for the EC.
  if (acpi_wakeup_helper_->IsSupported()) {
    acpi_wakeup_helper_->SetWakeupEnabled("CREC", true);
  }

  // Configure Smart Discharge in EC.
  int64_t to_zero_hr = -1, cutoff_ua = -1, hibernate_ua = -1;
  prefs_->GetInt64(kSmartDischargeToZeroHrPref, &to_zero_hr);
  prefs_->GetInt64(kCutoffPowerUaPref, &cutoff_ua);
  prefs_->GetInt64(kHibernatePowerUaPref, &hibernate_ua);
  system::ConfigureSmartDischarge(to_zero_hr, cutoff_ua, hibernate_ua);

  // Call this last to ensure that all of our members are already initialized.
  OnPowerStatusUpdate();
}

bool Daemon::TriggerRetryShutdownTimerForTesting() {
  if (!retry_shutdown_for_lockfile_timer_.IsRunning())
    return false;

  retry_shutdown_for_lockfile_timer_.user_task().Run();
  return true;
}

bool Daemon::BoolPrefIsTrue(const std::string& name) const {
  bool value = false;
  return prefs_->GetBool(name, &value) && value;
}

bool Daemon::SuspendAndShutdownAreBlocked(std::string* details_out) {
  const std::vector<base::FilePath> paths =
      power_override_lockfile_checker_->GetValidLockfiles();
  *details_out = util::JoinPaths(paths, ", ");
  return !paths.empty();
}

int Daemon::RunSetuidHelper(const std::string& action,
                            const std::string& additional_args,
                            bool wait_for_completion) {
  std::string command = kSetuidHelperPath + std::string(" --action=" + action);
  if (!additional_args.empty())
    command += " " + additional_args;
  if (wait_for_completion) {
    return delegate_->Run(command.c_str());
  } else {
    delegate_->Launch(command.c_str());
    return 0;
  }
}

void Daemon::HandleLidClosed() {
  LOG(INFO) << "Lid closed";
  // It is important that we notify InputDeviceController first so that it can
  // inhibit input devices quickly. StateController will issue a blocking call
  // to Chrome which can take longer than a second.
  input_device_controller_->SetLidState(LidState::CLOSED);
  state_controller_->HandleLidStateChange(LidState::CLOSED);
  for (auto controller : all_backlight_controllers_)
    controller->HandleLidStateChange(LidState::CLOSED);

  dbus_wrapper_->EmitBareSignal(kLidClosedSignal);
}

void Daemon::HandleLidOpened() {
  LOG(INFO) << "Lid opened";
  suspender_->HandleLidOpened();
  state_controller_->HandleLidStateChange(LidState::OPEN);
  input_device_controller_->SetLidState(LidState::OPEN);
  for (auto controller : all_backlight_controllers_)
    controller->HandleLidStateChange(LidState::OPEN);

  dbus_wrapper_->EmitBareSignal(kLidOpenedSignal);
}

void Daemon::HandlePowerButtonEvent(ButtonState state) {
  // Don't log spammy repeat events if we see them.
  if (state != ButtonState::REPEAT)
    LOG(INFO) << "Power button " << ButtonStateToString(state);
  metrics_collector_->HandlePowerButtonEvent(state);
  if (state == ButtonState::DOWN) {
    delegate_->Launch("sync");
    for (auto controller : all_backlight_controllers_)
      controller->HandlePowerButtonPress();
  }
}

void Daemon::HandleHoverStateChange(bool hovering) {
  if (hovering)
    hovering_logger_->OnActivityStarted();
  else
    hovering_logger_->OnActivityStopped();

  for (auto controller : all_backlight_controllers_)
    controller->HandleHoverStateChange(hovering);
}

void Daemon::HandleTabletModeChange(TabletMode mode) {
  DCHECK_NE(mode, TabletMode::UNSUPPORTED);
  LOG(INFO) << "Tablet mode " << TabletModeToString(mode);
  state_controller_->HandleTabletModeChange(mode);
  input_device_controller_->SetTabletMode(mode);
  for (auto controller : all_backlight_controllers_)
    controller->HandleTabletModeChange(mode);
  wifi_controller_->HandleTabletModeChange(mode);
  cellular_controller_->HandleTabletModeChange(mode);
}

void Daemon::ShutDownForPowerButtonWithNoDisplay() {
  LOG(INFO) << "Shutting down due to power button press while no display is "
            << "connected";
  metrics_collector_->HandlePowerButtonEvent(ButtonState::DOWN);
  ShutDown(ShutdownMode::POWER_OFF, ShutdownReason::USER_REQUEST);
}

void Daemon::HandleMissingPowerButtonAcknowledgment() {
  LOG(INFO) << "Didn't receive power button acknowledgment from Chrome";
}

void Daemon::ReportPowerButtonAcknowledgmentDelay(base::TimeDelta delay) {
  metrics_collector_->SendPowerButtonAcknowledgmentDelayMetric(delay);
}

int Daemon::GetInitialSuspendId() {
  // Take powerd's PID modulo 2**15 (/proc/sys/kernel/pid_max is currently
  // 2**15, but just in case...) and multiply it by 2**16, leaving it able to
  // fit in a signed 32-bit int. This allows for 2**16 suspend attempts and
  // suspend delays per powerd run before wrapping or intruding on another
  // run's ID range (neither of which should be particularly problematic, but
  // doing this reduces the chances of a confused client that's using stale
  // IDs from a previous powerd run being able to conflict with the new run's
  // IDs).
  return (delegate_->GetPid() % 32768) * 65536 + 1;
}

int Daemon::GetInitialDarkSuspendId() {
  // We use the upper half of the suspend ID space for dark suspend attempts.
  // Assuming that we will go through dark suspend IDs faster than the regular
  // suspend IDs, we should never have a collision between the suspend ID and
  // the dark suspend ID until the dark suspend IDs wrap around.
  return GetInitialSuspendId() + 32768;
}

bool Daemon::IsLidClosedForSuspend() {
  return input_watcher_->QueryLidState() == LidState::CLOSED;
}

bool Daemon::ReadSuspendWakeupCount(uint64_t* wakeup_count) {
  DCHECK(wakeup_count);
  std::string buf;
  LOG(INFO) << "Reading wakeup count from " << wakeup_count_path_.value();
  if (base::ReadFileToString(wakeup_count_path_, &buf)) {
    base::TrimWhitespaceASCII(buf, base::TRIM_TRAILING, &buf);
    if (base::StringToUint64(buf, wakeup_count)) {
      LOG(INFO) << "Read wakeup count " << *wakeup_count;
      return true;
    }
    LOG(ERROR) << "Could not parse wakeup count from \"" << buf << "\"";
  } else {
    PLOG(ERROR) << "Could not read " << wakeup_count_path_.value();
  }
  return false;
}

void Daemon::SetSuspendAnnounced(bool announced) {
  if (announced) {
    if (base::WriteFile(suspend_announced_path_, nullptr, 0) < 0)
      PLOG(ERROR) << "Couldn't create " << suspend_announced_path_.value();
  } else {
    if (!base::DeleteFile(suspend_announced_path_, false))
      PLOG(ERROR) << "Couldn't delete " << suspend_announced_path_.value();
  }
}

bool Daemon::GetSuspendAnnounced() {
  return base::PathExists(suspend_announced_path_);
}

void Daemon::PrepareToSuspend() {
  // Before announcing the suspend request, notify the backlight controller so
  // it can turn the backlight off and tell the kernel to resume the current
  // level after resuming.  This must occur before Chrome is told that the
  // system is going to suspend (Chrome turns the display back on while leaving
  // the backlight off).
  SetBacklightsSuspended(true);

  power_supply_->SetSuspended(true);
  if (audio_client_)
    audio_client_->SetSuspended(true);
  metrics_collector_->PrepareForSuspend();
}

policy::Suspender::Delegate::SuspendResult Daemon::DoSuspend(
    uint64_t wakeup_count, bool wakeup_count_valid, base::TimeDelta duration) {
  // If power management is overridden by a lockfile, spin for a bit to wait for
  // the process to finish: http://crosbug.com/p/38947
  base::TimeDelta elapsed;
  std::string details;
  while (SuspendAndShutdownAreBlocked(&details)) {
    if (elapsed >= kSuspendLockfileTimeout) {
      LOG(INFO) << "Aborting suspend attempt for lockfile(s): " << details;
      return policy::Suspender::Delegate::SuspendResult::FAILURE;
    }
    elapsed += kSuspendLockfilePollInterval;
    base::PlatformThread::Sleep(kSuspendLockfilePollInterval);
  }

  // Touch a file that crash-reporter can inspect later to determine
  // whether the system was suspended while an unclean shutdown occurred.
  // If the file already exists, assume that crash-reporter hasn't seen it
  // yet and avoid unlinking it after resume.
  created_suspended_state_file_ = false;
  if (!base::PathExists(suspended_state_path_)) {
    if (base::WriteFile(suspended_state_path_, nullptr, 0) == 0)
      created_suspended_state_file_ = true;
    else
      PLOG(ERROR) << "Unable to create " << suspended_state_path_.value();
  }

  // This command is run synchronously to ensure that it finishes before the
  // system is suspended.
  if (log_suspend_with_mosys_eventlog_) {
    RunSetuidHelper("mosys_eventlog", "--mosys_eventlog_code=0xa7", true);
  }

  std::vector<std::string> args;
  if (wakeup_count_valid) {
    args.push_back("--suspend_wakeup_count_valid");
    args.push_back(
        base::StringPrintf("--suspend_wakeup_count=%" PRIu64, wakeup_count));
  }

  if (suspend_to_idle_)
    args.push_back("--suspend_to_idle");

  suspend_configurator_->PrepareForSuspend(duration);
  const int exit_code =
      RunSetuidHelper("suspend", base::JoinString(args, " "), true);
  LOG(INFO) << "powerd_suspend returned " << exit_code;

  if (log_suspend_with_mosys_eventlog_)
    RunSetuidHelper("mosys_eventlog", "--mosys_eventlog_code=0xa8", false);

  if (created_suspended_state_file_) {
    if (!base::DeleteFile(base::FilePath(suspended_state_path_), false))
      PLOG(ERROR) << "Failed to delete " << suspended_state_path_.value();
  }

  if (!suspend_configurator_->UndoPrepareForSuspend())
    return policy::Suspender::Delegate::SuspendResult::FAILURE;

  // These exit codes are defined in powerd/powerd_suspend.
  switch (exit_code) {
    case 0:
      return policy::Suspender::Delegate::SuspendResult::SUCCESS;
    case 1:
      return policy::Suspender::Delegate::SuspendResult::FAILURE;
    case 2:  // Wakeup event received before write to wakeup_count.
    case 3:  // Wakeup event received after write to wakeup_count.
      return policy::Suspender::Delegate::SuspendResult::CANCELED;
    default:
      LOG(ERROR) << "Treating unexpected exit code " << exit_code
                 << " as suspend failure";
      return policy::Suspender::Delegate::SuspendResult::FAILURE;
  }
}

void Daemon::UndoPrepareToSuspend(bool success, int num_suspend_attempts) {
  LidState lid_state = input_watcher_->QueryLidState();

  // Update the lid state first so that resume does not turn the internal
  // backlight on if the lid is still closed on resume.
  for (auto controller : all_backlight_controllers_)
    controller->HandleLidStateChange(lid_state);

  // Let State controller know about resume with the latest lid state.
  state_controller_->HandleResume(lid_state);

  // Resume the backlight right after announcing resume. This might be where we
  // turn on the display, so we want to do this as early as possible. This
  // happens when we idle suspend (and the requested power state in Chrome is
  // off for the displays).
  SetBacklightsSuspended(false);

  if (audio_client_)
    audio_client_->SetSuspended(false);
  power_supply_->SetSuspended(false);

  if (success)
    metrics_collector_->HandleResume(num_suspend_attempts);
  else if (num_suspend_attempts > 0)
    metrics_collector_->HandleCanceledSuspendRequest(num_suspend_attempts);
}

void Daemon::GenerateDarkResumeMetrics(
    const std::vector<policy::Suspender::DarkResumeInfo>&
        dark_resume_wake_durations,
    base::TimeDelta suspend_duration) {
  metrics_collector_->GenerateDarkResumeMetrics(dark_resume_wake_durations,
                                                suspend_duration);
}

void Daemon::ShutDownForFailedSuspend() {
  ShutDown(ShutdownMode::POWER_OFF, ShutdownReason::SUSPEND_FAILED);
}

void Daemon::ShutDownFromSuspend() {
  ShutDown(ShutdownMode::POWER_OFF, ShutdownReason::SHUTDOWN_FROM_SUSPEND);
}

void Daemon::SetWifiTransmitPower(RadioTransmitPower power,
                                  WifiRegDomain domain) {
  const std::string power_arg = (power == RadioTransmitPower::LOW)
                                    ? "--wifi_transmit_power_tablet"
                                    : "--nowifi_transmit_power_tablet";
  std::string domain_arg = "--wifi_transmit_power_domain=none";
  switch (domain) {
    case WifiRegDomain::FCC:
      domain_arg = "--wifi_transmit_power_domain=fcc";
      break;
    case WifiRegDomain::EU:
      domain_arg = "--wifi_transmit_power_domain=eu";
      break;
    case WifiRegDomain::REST_OF_WORLD:
      domain_arg = "--wifi_transmit_power_domain=rest-of-world";
      break;
    default:
      break;
  }
  const std::string args =
      base::StringPrintf("%s %s", power_arg.c_str(), domain_arg.c_str());
  LOG(INFO) << ((power == RadioTransmitPower::LOW) ? "Enabling" : "Disabling")
            << " tablet mode wifi transmit power";
  RunSetuidHelper("set_wifi_transmit_power", args, false);
}

void Daemon::SetCellularTransmitPower(RadioTransmitPower power,
                                      int64_t dpr_gpio_number) {
  const bool is_power_low = (power == RadioTransmitPower::LOW);
  const std::string args = base::StringPrintf(
      "--cellular_transmit_power_low=%s "
      "--cellular_transmit_power_gpio=%" PRId64,
      is_power_low ? "true" : "false", dpr_gpio_number);
  LOG(INFO) << "Setting cellular transmit power "
            << (is_power_low ? "low" : "high");
  RunSetuidHelper("set_cellular_transmit_power", args, false);
}

void Daemon::OnAudioStateChange(bool active) {
  if (active)
    audio_activity_logger_->OnActivityStarted();
  else
    audio_activity_logger_->OnActivityStopped();
  state_controller_->HandleAudioStateChange(active);
}

void Daemon::OnDBusNameOwnerChanged(const std::string& name,
                                    const std::string& old_owner,
                                    const std::string& new_owner) {
  if (name == login_manager::kSessionManagerServiceName && !new_owner.empty()) {
    LOG(INFO) << "D-Bus " << name << " ownership changed to " << new_owner;
    HandleSessionManagerAvailableOrRestarted(true);
  } else if (name == chromeos::kDisplayServiceName && !new_owner.empty()) {
    LOG(INFO) << "D-Bus " << name << " ownership changed to " << new_owner;
    HandleDisplayServiceAvailableOrRestarted(true);
  }
  suspender_->HandleDBusNameOwnerChanged(name, old_owner, new_owner);
}

void Daemon::OnPowerStatusUpdate() {
  const system::PowerStatus status = power_supply_->GetPowerStatus();
  if (status.battery_is_present)
    LOG(INFO) << system::GetPowerStatusBatteryDebugString(status);

  metrics_collector_->HandlePowerStatusUpdate(status);

  const PowerSource power_source =
      status.line_power_on ? PowerSource::AC : PowerSource::BATTERY;
  for (auto controller : all_backlight_controllers_)
    controller->HandlePowerSourceChange(power_source);
  state_controller_->HandlePowerSourceChange(power_source);

  if (status.battery_is_present && status.battery_below_shutdown_threshold) {
    if (factory_mode_) {
      LOG(INFO) << "Battery is low, but not shutting down in factory mode";
    } else {
      LOG(INFO) << "Shutting down due to low battery ("
                << base::StringPrintf("%0.2f", status.battery_percentage)
                << "%, "
                << util::TimeDeltaToString(status.battery_time_to_empty)
                << " until empty, "
                << base::StringPrintf("%0.3f",
                                      status.observed_battery_charge_rate)
                << "A observed charge rate)";
      ShutDown(ShutdownMode::POWER_OFF, ShutdownReason::LOW_BATTERY);
    }
  }
}

void Daemon::InitDBus() {
  dbus_wrapper_ = delegate_->CreateDBusWrapper();
  dbus_wrapper_->AddObserver(this);

  dbus::ObjectProxy* display_service_proxy = dbus_wrapper_->GetObjectProxy(
      chromeos::kDisplayServiceName, chromeos::kDisplayServicePath);
  dbus_wrapper_->RegisterForServiceAvailability(
      display_service_proxy,
      base::Bind(&Daemon::HandleDisplayServiceAvailableOrRestarted,
                 weak_ptr_factory_.GetWeakPtr()));

  session_manager_dbus_proxy_ =
      dbus_wrapper_->GetObjectProxy(login_manager::kSessionManagerServiceName,
                                    login_manager::kSessionManagerServicePath);
  dbus_wrapper_->RegisterForServiceAvailability(
      session_manager_dbus_proxy_,
      base::Bind(&Daemon::HandleSessionManagerAvailableOrRestarted,
                 weak_ptr_factory_.GetWeakPtr()));
  dbus_wrapper_->RegisterForSignal(
      session_manager_dbus_proxy_, login_manager::kSessionManagerInterface,
      login_manager::kSessionStateChangedSignal,
      base::Bind(&Daemon::HandleSessionStateChangedSignal,
                 weak_ptr_factory_.GetWeakPtr()));

  int64_t tpm_threshold = 0;
  prefs_->GetInt64(kTpmCounterSuspendThresholdPref, &tpm_threshold);
  if (tpm_threshold > 0) {
    cryptohomed_dbus_proxy_ = dbus_wrapper_->GetObjectProxy(
        cryptohome::kCryptohomeServiceName, cryptohome::kCryptohomeServicePath);
    dbus_wrapper_->RegisterForServiceAvailability(
        cryptohomed_dbus_proxy_, base::Bind(&Daemon::HandleCryptohomedAvailable,
                                            weak_ptr_factory_.GetWeakPtr()));

    int64_t tpm_status_sec = 0;
    prefs_->GetInt64(kTpmStatusIntervalSecPref, &tpm_status_sec);
    tpm_status_interval_ = base::TimeDelta::FromSeconds(tpm_status_sec);
  }

  // Export Daemon's D-Bus method calls.
  typedef std::unique_ptr<dbus::Response> (Daemon::*DaemonMethod)(
      dbus::MethodCall*);
  const std::map<const char*, DaemonMethod> kDaemonMethods = {
      {kRequestShutdownMethod, &Daemon::HandleRequestShutdownMethod},
      {kRequestRestartMethod, &Daemon::HandleRequestRestartMethod},
      {kRequestSuspendMethod, &Daemon::HandleRequestSuspendMethod},
      {kHandleVideoActivityMethod, &Daemon::HandleVideoActivityMethod},
      {kHandleUserActivityMethod, &Daemon::HandleUserActivityMethod},
      {kHandleWakeNotificationMethod, &Daemon::HandleWakeNotificationMethod},
      {kSetIsProjectingMethod, &Daemon::HandleSetIsProjectingMethod},
      {kSetPolicyMethod, &Daemon::HandleSetPolicyMethod},
      {kSetBacklightsForcedOffMethod,
       &Daemon::HandleSetBacklightsForcedOffMethod},
      {kGetBacklightsForcedOffMethod,
       &Daemon::HandleGetBacklightsForcedOffMethod},
      {kHasAmbientColorDeviceMethod,
       &Daemon::HandleHasAmbientColorDeviceMethod},
      {kChangeWifiRegDomainMethod, &Daemon::HandleChangeWifiRegDomainMethod},
  };
  for (const auto& it : kDaemonMethods) {
    dbus_wrapper_->ExportMethod(
        it.first, base::Bind(&HandleSynchronousDBusMethodCall,
                             base::Bind(it.second, base::Unretained(this))));
  }

#if USE_BUFFET
  // There's no underlying dbus::Bus object when we're being tested.
  dbus::Bus* bus = dbus_wrapper_->GetBus();
  if (bus) {
    buffet::InitCommandHandlers(
        bus, base::Bind(&Daemon::ShutDown, weak_ptr_factory_.GetWeakPtr(),
                        ShutdownMode::REBOOT, ShutdownReason::USER_REQUEST));
  }
#endif  // USE_BUFFET
}

void Daemon::HandleDisplayServiceAvailableOrRestarted(bool available) {
  if (!available) {
    LOG(ERROR) << "Failed waiting for DisplayService to become available";
    return;
  }
  for (auto controller : all_backlight_controllers_)
    controller->HandleDisplayServiceStart();

  // When running in the factory, we avoid initializing any backlight
  // controllers, but we need to still tell Chrome to initially turn displays on
  // so it will restore the correct display power state when returning from VT2:
  // http://b/78436034
  if (factory_mode_) {
    DCHECK(all_backlight_controllers_.empty());
    display_power_setter_->SetDisplayPower(chromeos::DISPLAY_POWER_ALL_ON,
                                           base::TimeDelta());
  }
}

void Daemon::HandleSessionManagerAvailableOrRestarted(bool available) {
  if (!available) {
    LOG(ERROR) << "Failed waiting for session manager to become available";
    return;
  }

  dbus::MethodCall method_call(
      login_manager::kSessionManagerInterface,
      login_manager::kSessionManagerRetrieveSessionState);
  std::unique_ptr<dbus::Response> response = dbus_wrapper_->CallMethodSync(
      session_manager_dbus_proxy_, &method_call,
      base::TimeDelta::FromMilliseconds(kSessionManagerDBusTimeoutMs));
  if (!response)
    return;

  std::string state;
  dbus::MessageReader reader(response.get());
  if (!reader.PopString(&state)) {
    LOG(ERROR) << "Unable to read "
               << login_manager::kSessionManagerRetrieveSessionState << " args";
    return;
  }
  OnSessionStateChange(state);
}

void Daemon::HandleCryptohomedAvailable(bool available) {
  if (!available) {
    LOG(ERROR) << "Failed waiting for cryptohomed to become available";
    return;
  }
  if (!cryptohomed_dbus_proxy_)
    return;

  RequestTpmStatus();
  if (tpm_status_interval_ > base::TimeDelta::FromSeconds(0)) {
    tpm_status_timer_.Start(FROM_HERE, tpm_status_interval_, this,
                            &Daemon::RequestTpmStatus);
  }
}

void Daemon::HandleSessionStateChangedSignal(dbus::Signal* signal) {
  dbus::MessageReader reader(signal);
  std::string state;
  if (reader.PopString(&state)) {
    OnSessionStateChange(state);
  } else {
    LOG(ERROR) << "Unable to read " << login_manager::kSessionStateChangedSignal
               << " args";
  }
}

void Daemon::HandleGetTpmStatusResponse(dbus::Response* response) {
  if (!response) {
    LOG(ERROR) << cryptohome::kCryptohomeGetTpmStatus << " call failed";
    return;
  }

  cryptohome::BaseReply base_reply;
  dbus::MessageReader reader(response);
  if (!reader.PopArrayOfBytesAsProto(&base_reply)) {
    LOG(ERROR) << "Unable to parse " << cryptohome::kCryptohomeGetTpmStatus
               << "response";
    return;
  }
  if (base_reply.has_error()) {
    LOG(ERROR) << cryptohome::kCryptohomeGetTpmStatus << " response contains "
               << "error code " << base_reply.error();
    return;
  }
  if (!base_reply.HasExtension(cryptohome::GetTpmStatusReply::reply)) {
    LOG(ERROR) << cryptohome::kCryptohomeGetTpmStatus << " response doesn't "
               << "contain nested reply";
    return;
  }

  cryptohome::GetTpmStatusReply tpm_reply =
      base_reply.GetExtension(cryptohome::GetTpmStatusReply::reply);
  LOG(INFO) << "Received " << cryptohome::kCryptohomeGetTpmStatus
            << " response with dictionary attack count "
            << tpm_reply.dictionary_attack_counter();
  state_controller_->HandleTpmStatus(tpm_reply.dictionary_attack_counter());
}

std::unique_ptr<dbus::Response> Daemon::HandleRequestShutdownMethod(
    dbus::MethodCall* method_call) {
  // Both arguments are optional.
  dbus::MessageReader reader(method_call);
  int32_t arg = 0;
  ShutdownReason reason = ShutdownReason::OTHER_REQUEST_TO_POWERD;
  if (reader.PopInt32(&arg)) {
    switch (static_cast<RequestShutdownReason>(arg)) {
      case REQUEST_SHUTDOWN_FOR_USER:
        reason = ShutdownReason::USER_REQUEST;
        break;
      case REQUEST_SHUTDOWN_OTHER:
        reason = ShutdownReason::OTHER_REQUEST_TO_POWERD;
        break;
      default:
        LOG(WARNING) << "Got unknown shutdown reason " << arg;
    }
  }

  std::string description;
  reader.PopString(&description);

  LOG(INFO) << "Got " << kRequestShutdownMethod << " message from "
            << method_call->GetSender() << " with reason "
            << ShutdownReasonToString(reason) << " (" << description << ")";

  ShutDown(ShutdownMode::POWER_OFF, reason);
  return nullptr;
}

std::unique_ptr<dbus::Response> Daemon::HandleRequestRestartMethod(
    dbus::MethodCall* method_call) {
  // Both arguments are optional.
  dbus::MessageReader reader(method_call);
  int32_t arg = 0;
  ShutdownReason reason = ShutdownReason::OTHER_REQUEST_TO_POWERD;
  if (reader.PopInt32(&arg)) {
    switch (static_cast<RequestRestartReason>(arg)) {
      case REQUEST_RESTART_FOR_USER:
        reason = ShutdownReason::USER_REQUEST;
        break;
      case REQUEST_RESTART_FOR_UPDATE:
        reason = ShutdownReason::SYSTEM_UPDATE;
        break;
      case REQUEST_RESTART_OTHER:
        reason = ShutdownReason::OTHER_REQUEST_TO_POWERD;
        break;
      default:
        LOG(WARNING) << "Got unknown restart reason " << arg;
    }
  }

  std::string description;
  reader.PopString(&description);

  LOG(INFO) << "Got " << kRequestRestartMethod << " message from "
            << method_call->GetSender() << " with reason "
            << ShutdownReasonToString(reason) << " (" << description << ")";

  ShutDown(ShutdownMode::REBOOT, reason);
  return nullptr;
}

std::unique_ptr<dbus::Response> Daemon::HandleRequestSuspendMethod(
    dbus::MethodCall* method_call) {
  // Read an optional uint64_t argument specifying the wakeup count that is
  // expected.
  dbus::MessageReader reader(method_call);
  uint64_t external_wakeup_count = 0;
  const bool got_external_wakeup_count =
      reader.PopUint64(&external_wakeup_count);
  LOG(INFO) << "Got " << kRequestSuspendMethod << " message"
            << (got_external_wakeup_count
                    ? base::StringPrintf(" with external wakeup count %" PRIu64,
                                         external_wakeup_count)
                          .c_str()
                    : "")
            << " from " << method_call->GetSender();
  // Read an optional int32_t argument specifying the wakeup timeout for a
  // suspend request.
  int32_t wakeup_timeout = 0;
  reader.PopInt32(&wakeup_timeout);
  base::TimeDelta duration = base::TimeDelta::FromSeconds(wakeup_timeout);
  Suspend(SuspendImminent_Reason_OTHER, got_external_wakeup_count,
          external_wakeup_count, duration);
  return nullptr;
}

std::unique_ptr<dbus::Response> Daemon::HandleVideoActivityMethod(
    dbus::MethodCall* method_call) {
  bool fullscreen = false;
  dbus::MessageReader reader(method_call);
  if (!reader.PopBool(&fullscreen))
    LOG(ERROR) << "Unable to read " << kHandleVideoActivityMethod << " args";

  video_activity_logger_->OnActivityReported();

  for (auto controller : all_backlight_controllers_)
    controller->HandleVideoActivity(fullscreen);
  state_controller_->HandleVideoActivity();
  return nullptr;
}

std::unique_ptr<dbus::Response> Daemon::HandleUserActivityMethod(
    dbus::MethodCall* method_call) {
  user_activity_logger_->OnActivityReported();

  int type_int = USER_ACTIVITY_OTHER;
  dbus::MessageReader reader(method_call);
  if (!reader.PopInt32(&type_int))
    LOG(ERROR) << "Unable to read " << kHandleUserActivityMethod << " args";
  UserActivityType type = static_cast<UserActivityType>(type_int);

  suspender_->HandleUserActivity();
  state_controller_->HandleUserActivity();
  for (auto controller : all_backlight_controllers_)
    controller->HandleUserActivity(type);
  return nullptr;
}

std::unique_ptr<dbus::Response> Daemon::HandleWakeNotificationMethod(
    dbus::MethodCall* method_call) {
  suspender_->HandleWakeNotification();
  state_controller_->HandleWakeNotification();
  for (auto controller : all_backlight_controllers_)
    controller->HandleWakeNotification();
  return nullptr;
}

std::unique_ptr<dbus::Response> Daemon::HandleSetIsProjectingMethod(
    dbus::MethodCall* method_call) {
  bool is_projecting = false;
  dbus::MessageReader reader(method_call);
  if (!reader.PopBool(&is_projecting)) {
    LOG(ERROR) << "Unable to read " << kSetIsProjectingMethod << " args";
    return CreateInvalidArgsError(method_call, "Expected boolean state");
  }

  DisplayMode mode =
      is_projecting ? DisplayMode::PRESENTATION : DisplayMode::NORMAL;
  LOG(INFO) << "Chrome is using " << DisplayModeToString(mode)
            << " display mode";
  state_controller_->HandleDisplayModeChange(mode);
  suspender_->HandleDisplayModeChange(mode);
  input_device_controller_->SetDisplayMode(mode);
  for (auto controller : all_backlight_controllers_)
    controller->HandleDisplayModeChange(mode);
  return nullptr;
}

std::unique_ptr<dbus::Response> Daemon::HandleSetPolicyMethod(
    dbus::MethodCall* method_call) {
  PowerManagementPolicy policy;
  dbus::MessageReader reader(method_call);
  if (!reader.PopArrayOfBytesAsProto(&policy)) {
    LOG(ERROR) << "Unable to parse " << kSetPolicyMethod << " request";
    return CreateInvalidArgsError(method_call, "Expected protobuf");
  }

  LOG(INFO) << "Received updated external policy: "
            << policy::StateController::GetPolicyDebugString(policy);
  state_controller_->HandlePolicyChange(policy);

  if (charge_controller_) {
    charge_controller_->HandlePolicyChange(policy);
  }

  for (auto controller : all_backlight_controllers_)
    controller->HandlePolicyChange(policy);
  return nullptr;
}

std::unique_ptr<dbus::Response> Daemon::HandleSetBacklightsForcedOffMethod(
    dbus::MethodCall* method_call) {
  bool force_off = false;
  if (!dbus::MessageReader(method_call).PopBool(&force_off)) {
    LOG(ERROR) << "Unable to read " << kSetBacklightsForcedOffMethod << " args";
    return CreateInvalidArgsError(method_call, "Expected bool");
  }
  LOG(INFO) << "Received request to " << (force_off ? "start" : "stop")
            << " forcing backlights off";
  for (auto controller : all_backlight_controllers_)
    controller->SetForcedOff(force_off);
  return nullptr;
}

std::unique_ptr<dbus::Response> Daemon::HandleGetBacklightsForcedOffMethod(
    dbus::MethodCall* method_call) {
  std::unique_ptr<dbus::Response> response(
      dbus::Response::FromMethodCall(method_call));

  // We can get the current state from any backlight controller.
  bool forced_off = all_backlight_controllers_.empty()
                        ? false
                        : all_backlight_controllers_.front()->GetForcedOff();
  dbus::MessageWriter(response.get()).AppendBool(forced_off);
  return response;
}

std::unique_ptr<dbus::Response> Daemon::HandleHasAmbientColorDeviceMethod(
    dbus::MethodCall* method_call) {
  std::unique_ptr<dbus::Response> response(
      dbus::Response::FromMethodCall(method_call));
  bool has_color_device = false;
  if (light_sensor_manager_)
    has_color_device = light_sensor_manager_->HasColorSensor();

  dbus::MessageWriter(response.get()).AppendBool(has_color_device);
  return response;
}

std::unique_ptr<dbus::Response> Daemon::HandleChangeWifiRegDomainMethod(
    dbus::MethodCall* method_call) {
  int32_t arg = 0;
  dbus::MessageReader reader(method_call);
  WifiRegDomain domain = WifiRegDomain::NONE;
  if (!reader.PopInt32(&arg)) {
    LOG(ERROR) << "Unable to read " << kChangeWifiRegDomainMethod << " args";
    return CreateInvalidArgsError(method_call, "Expected Int32");
  }
  switch (static_cast<WifiRegDomainDbus>(arg)) {
    case WIFI_REG_DOMAIN_FCC:
      domain = WifiRegDomain::FCC;
      break;
    case WIFI_REG_DOMAIN_EU:
      domain = WifiRegDomain::EU;
      break;
    case WIFI_REG_DOMAIN_REST_OF_WORLD:
      domain = WifiRegDomain::REST_OF_WORLD;
      break;
    case WIFI_REG_DOMAIN_NONE:
      break;
    default:
      LOG(WARNING) << "Got unknown WiFi regulatory domain " << arg;
  }

  LOG(INFO) << "Received request to change reg domain to \""
            << WifiRegDomainToString(domain) << "\"";
  wifi_controller_->HandleRegDomainChange(domain);
  return nullptr;
}

void Daemon::OnSessionStateChange(const std::string& state_str) {
  SessionState state = (state_str == kSessionStarted) ? SessionState::STARTED
                                                      : SessionState::STOPPED;
  if (state == session_state_)
    return;

  LOG(INFO) << "Session state changed to " << SessionStateToString(state);
  session_state_ = state;
  metrics_collector_->HandleSessionStateChange(state);
  state_controller_->HandleSessionStateChange(state);
  for (auto controller : all_backlight_controllers_)
    controller->HandleSessionStateChange(state);
}

void Daemon::RequestTpmStatus() {
  DCHECK(cryptohomed_dbus_proxy_);
  dbus::MethodCall method_call(cryptohome::kCryptohomeInterface,
                               cryptohome::kCryptohomeGetTpmStatus);
  dbus::MessageWriter writer(&method_call);
  writer.AppendProtoAsArrayOfBytes(cryptohome::GetTpmStatusRequest());
  dbus_wrapper_->CallMethodAsync(
      cryptohomed_dbus_proxy_, &method_call,
      base::TimeDelta::FromMilliseconds(kCryptohomedDBusTimeoutMs),
      base::Bind(&Daemon::HandleGetTpmStatusResponse,
                 weak_ptr_factory_.GetWeakPtr()));
}

void Daemon::ShutDown(ShutdownMode mode, ShutdownReason reason) {
  if (shutting_down_) {
    LOG(INFO) << "Shutdown already initiated; ignoring additional request";
    return;
  }

  std::string details;
  if (SuspendAndShutdownAreBlocked(&details)) {
    LOG(INFO) << "Postponing shutdown for lockfile(s): " << details;
    if (!retry_shutdown_for_lockfile_timer_.IsRunning()) {
      retry_shutdown_for_lockfile_timer_.Start(
          FROM_HERE, kShutdownLockfileRetryInterval,
          base::Bind(&Daemon::ShutDown, weak_ptr_factory_.GetWeakPtr(), mode,
                     reason));
    }
    return;
  }

  shutting_down_ = true;
  retry_shutdown_for_lockfile_timer_.Stop();
  suspender_->HandleShutdown();
  metrics_collector_->HandleShutdown(reason);

  for (auto controller : all_backlight_controllers_) {
    // If we're going to display a low-battery alert while shutting down, don't
    // turn the screen off immediately.
    if (!(reason == ShutdownReason::LOW_BATTERY &&
          controller == display_backlight_controller_.get()))
      controller->SetShuttingDown(true);
  }

  const std::string reason_str = ShutdownReasonToString(reason);
  switch (mode) {
    case ShutdownMode::POWER_OFF:
      LOG(INFO) << "Shutting down, reason: " << reason_str;
      RunSetuidHelper("shut_down", "--shutdown_reason=" + reason_str, false);
      break;
    case ShutdownMode::REBOOT:
      if (state_controller_->in_docked_mode()) {
        LOG(INFO) << "In docked mode, so telling EC to force lid open to avoid "
                  << "shutting down after reboot";
        RunSetuidHelper("set_force_lid_open", "--force_lid_open", true);
      }
      LOG(INFO) << "Restarting, reason: " << reason_str;
      RunSetuidHelper("reboot", "--shutdown_reason=" + reason_str, false);
      break;
  }
}

void Daemon::Suspend(SuspendImminent::Reason reason,
                     bool use_external_wakeup_count,
                     uint64_t external_wakeup_count,
                     base::TimeDelta duration) {
  if (shutting_down_) {
    LOG(INFO) << "Ignoring request for suspend with outstanding shutdown";
    return;
  }

  if (use_external_wakeup_count) {
    suspender_->RequestSuspendWithExternalWakeupCount(
        reason, external_wakeup_count, duration);
  } else {
    suspender_->RequestSuspend(reason, duration);
  }
}

void Daemon::SetBacklightsDimmedForInactivity(bool dimmed) {
  for (auto controller : all_backlight_controllers_)
    controller->SetDimmedForInactivity(dimmed);
  metrics_collector_->HandleScreenDimmedChange(
      dimmed, state_controller_->last_user_activity_time());
}

void Daemon::SetBacklightsOffForInactivity(bool off) {
  for (auto controller : all_backlight_controllers_)
    controller->SetOffForInactivity(off);
  metrics_collector_->HandleScreenOffChange(
      off, state_controller_->last_user_activity_time());
}

void Daemon::SetBacklightsSuspended(bool suspended) {
  for (auto controller : all_backlight_controllers_)
    controller->SetSuspended(suspended);
}

}  // namespace power_manager
