// Copyright 2018 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 "shill/power_manager.h"

#include <string>

#include <base/bind.h>
#include <base/logging.h>
#include <base/time/time.h>
#include <chromeos/dbus/service_constants.h>
#include <linux/nl80211.h>

#include "shill/control_interface.h"
#include "shill/logging.h"
#include "shill/power_manager_proxy_interface.h"

namespace shill {

// static
const int PowerManager::kInvalidSuspendId = -1;
const char PowerManager::kSuspendDelayDescription[] = "shill";
const char PowerManager::kDarkSuspendDelayDescription[] = "shill";
const int PowerManager::kSuspendTimeoutMilliseconds = 15 * 1000;

PowerManager::PowerManager(ControlInterface* control_interface)
    : control_interface_(control_interface),
      suspend_delay_registered_(false),
      suspend_delay_id_(0),
      dark_suspend_delay_registered_(false),
      dark_suspend_delay_id_(0),
      suspending_(false),
      suspend_ready_(false),
      suspend_done_deferred_(false),
      in_dark_resume_(false),
      current_suspend_id_(0),
      current_dark_suspend_id_(0),
      suspend_duration_us_(0),
      wifi_reg_domain_is_set(false) {}

PowerManager::~PowerManager() = default;

void PowerManager::Start(
    base::TimeDelta suspend_delay,
    const SuspendImminentCallback& suspend_imminent_callback,
    const SuspendDoneCallback& suspend_done_callback,
    const DarkSuspendImminentCallback& dark_suspend_imminent_callback) {
  power_manager_proxy_ = control_interface_->CreatePowerManagerProxy(
      this,
      base::Bind(&PowerManager::OnPowerManagerAppeared, base::Unretained(this)),
      base::Bind(&PowerManager::OnPowerManagerVanished,
                 base::Unretained(this)));
  suspend_delay_ = suspend_delay;
  suspend_imminent_callback_ = suspend_imminent_callback;
  suspend_done_callback_ = suspend_done_callback;
  dark_suspend_imminent_callback_ = dark_suspend_imminent_callback;
}

void PowerManager::Stop() {
  LOG(INFO) << __func__;
  // We may attempt to unregister with a stale |suspend_delay_id_| if powerd
  // reappeared behind our back. It is safe to do so.
  if (suspend_delay_registered_)
    power_manager_proxy_->UnregisterSuspendDelay(suspend_delay_id_);
  if (dark_suspend_delay_registered_)
    power_manager_proxy_->UnregisterDarkSuspendDelay(dark_suspend_delay_id_);

  suspend_delay_registered_ = false;
  dark_suspend_delay_registered_ = false;
  power_manager_proxy_.reset();
}

bool PowerManager::ReportSuspendReadiness() {
  // If |suspend_done_deferred_| is true, a SuspendDone notification was
  // observed before SuspendReadiness was reported and no further
  // SuspendImminent notification was observed after the SuspendDone
  // notification. We don't need to report SuspendReadiness, but instead notify
  // the deferred SuspendDone.
  if (suspend_done_deferred_) {
    LOG(INFO) << __func__ << ": Notifying deferred SuspendDone.";
    NotifySuspendDone();
    return false;
  }

  suspend_ready_ = true;
  if (!suspending_) {
    LOG(INFO) << __func__ << ": Suspend attempt (" << current_suspend_id_
              << ") not active. Ignoring signal.";
    return false;
  }
  return power_manager_proxy_->ReportSuspendReadiness(suspend_delay_id_,
                                                      current_suspend_id_);
}

bool PowerManager::ReportDarkSuspendReadiness() {
  return power_manager_proxy_->ReportDarkSuspendReadiness(
      dark_suspend_delay_id_, current_dark_suspend_id_);
}

bool PowerManager::RecordDarkResumeWakeReason(const std::string& wake_reason) {
  return power_manager_proxy_->RecordDarkResumeWakeReason(wake_reason);
}

bool PowerManager::ChangeRegDomain(nl80211_dfs_regions domain) {
  auto new_domain = power_manager::WIFI_REG_DOMAIN_NONE;
  switch (domain) {
    case NL80211_DFS_FCC:
      new_domain = power_manager::WIFI_REG_DOMAIN_FCC;
      break;
    case NL80211_DFS_ETSI:
      new_domain = power_manager::WIFI_REG_DOMAIN_EU;
      break;
    case NL80211_DFS_JP:
      new_domain = power_manager::WIFI_REG_DOMAIN_REST_OF_WORLD;
      break;
    case NL80211_DFS_UNSET:
      new_domain = power_manager::WIFI_REG_DOMAIN_NONE;
      break;
    default:
      LOG(WARNING) << "Unrecognized WiFi reg domain: "
                   << std::to_string(domain);
      return false;
  }
  wifi_reg_domain_is_set = true;

  if (new_domain != wifi_reg_domain_) {
    wifi_reg_domain_ = new_domain;
    return power_manager_proxy_->ChangeRegDomain(wifi_reg_domain_);
  }
  return false;
}

void PowerManager::OnSuspendImminent(int suspend_id) {
  LOG(INFO) << __func__ << "(" << suspend_id << ")";
  current_suspend_id_ = suspend_id;

  // Ignore any previously deferred SuspendDone notification as we're going to
  // suspend again and expect a new SuspendDone notification later.
  suspend_done_deferred_ = false;

  // If we're already suspending, don't call the |suspend_imminent_callback_|
  // again.
  if (!suspending_) {
    // Change the power state to suspending as soon as this signal is received
    // so that the manager can suppress auto-connect, for example.
    // Also, we must set this before running the callback below, because the
    // callback may synchronously report suspend readiness.
    suspending_ = true;
    suspend_duration_us_ = 0;
    suspend_imminent_callback_.Run();
  }
}

void PowerManager::OnSuspendDone(int suspend_id, int64_t suspend_duration_us) {
  // NB: |suspend_id| could be -1. See OnPowerManagerVanished.
  LOG(INFO) << __func__ << "(" << suspend_id << ")";
  if (!suspending_) {
    LOG(WARNING) << "Received unexpected SuspendDone (" << suspend_id
                 << "). Ignoring.";
    return;
  }

  suspend_duration_us_ = suspend_duration_us;

  if (!suspend_ready_) {
    LOG(INFO) << "Received SuspendDone (" << suspend_id
              << ") before SuspendReadiness is reported. "
              << "Defer SuspendDone notification.";
    suspend_done_deferred_ = true;
    return;
  }

  NotifySuspendDone();
}

void PowerManager::NotifySuspendDone() {
  suspending_ = false;
  suspend_ready_ = false;
  suspend_done_deferred_ = false;
  in_dark_resume_ = false;
  suspend_done_callback_.Run();
}

void PowerManager::OnDarkSuspendImminent(int suspend_id) {
  LOG(INFO) << __func__ << "(" << suspend_id << ")";
  if (!dark_suspend_delay_registered_) {
    LOG(WARNING) << "Ignoring DarkSuspendImminent signal from powerd. shill "
                 << "does not have a dark suspend delay registered. This "
                 << "means that shill is not guaranteed any time before a "
                 << "resuspend.";
    return;
  }
  in_dark_resume_ = true;
  current_dark_suspend_id_ = suspend_id;
  dark_suspend_imminent_callback_.Run();
}

void PowerManager::OnPowerManagerAppeared() {
  LOG(INFO) << __func__;

  // This function could get called twice in a row due to races in
  // ObjectProxy.
  if (suspend_delay_registered_) {
    return;
  }

  if (power_manager_proxy_->RegisterSuspendDelay(
          suspend_delay_, kSuspendDelayDescription, &suspend_delay_id_))
    suspend_delay_registered_ = true;

  if (power_manager_proxy_->RegisterDarkSuspendDelay(
          suspend_delay_, kDarkSuspendDelayDescription,
          &dark_suspend_delay_id_))
    dark_suspend_delay_registered_ = true;
  if (wifi_reg_domain_is_set) {
    power_manager_proxy_->ChangeRegDomain(wifi_reg_domain_);
  }
}

void PowerManager::OnPowerManagerVanished() {
  LOG(INFO) << __func__;
  // If powerd vanished during a suspend, we need to wake ourselves up.
  if (suspending_) {
    suspend_ready_ = true;
    OnSuspendDone(kInvalidSuspendId, 0);
  }
  suspend_delay_registered_ = false;
  dark_suspend_delay_registered_ = false;
}

}  // namespace shill
