// Copyright 2019 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 "vm_tools/concierge/power_manager_client.h"

#include <utility>

#include <base/bind.h>
#include <base/logging.h>
#include <base/time/time.h>
#include <brillo/dbus/dbus_proxy_util.h>
#include <chromeos/dbus/service_constants.h>
#include <dbus/object_path.h>
#include <power_manager/proto_bindings/suspend.pb.h>

namespace vm_tools {
namespace concierge {
namespace {
// How long powerd should wait for us to report suspend readiness.
constexpr base::TimeDelta kSuspendDelayTimeout =
    base::TimeDelta::FromSeconds(5);

// Used to mark that the device is not currently suspended or about to suspend.
constexpr int32_t kNoSuspendId = -1;

}  // namespace

PowerManagerClient::PowerManagerClient(scoped_refptr<dbus::Bus> bus)
    : bus_(bus),
      power_manager_proxy_(nullptr),
      delay_id_(-1),
      current_suspend_id_(kNoSuspendId) {
  power_manager_proxy_ = bus_->GetObjectProxy(
      power_manager::kPowerManagerServiceName,
      dbus::ObjectPath(power_manager::kPowerManagerServicePath));
}

PowerManagerClient::~PowerManagerClient() {
  if (delay_id_ == -1) {
    return;
  }

  dbus::MethodCall method_call(power_manager::kPowerManagerInterface,
                               power_manager::kUnregisterSuspendDelayMethod);

  power_manager::UnregisterSuspendDelayRequest request;
  request.set_delay_id(delay_id_);

  if (!dbus::MessageWriter(&method_call).AppendProtoAsArrayOfBytes(request)) {
    LOG(ERROR) << "Failed to encode UnregisterSuspendDelayRequest";
    return;
  }

  auto dbus_response = brillo::dbus_utils::CallDBusMethod(
      bus_, power_manager_proxy_, &method_call,
      dbus::ObjectProxy::TIMEOUT_USE_DEFAULT);
  if (!dbus_response) {
    LOG(WARNING) << "Failed to un-register suspend delay with powerd";
  }
}

void PowerManagerClient::RegisterSuspendDelay(base::Closure suspend_imminent_cb,
                                              base::Closure suspend_done_cb) {
  // We don't need to check whether powerd is running because it should start
  // automatically at boot while concierge is not started until the user
  // explicitly tries to start a VM.

  dbus::MethodCall method_call(power_manager::kPowerManagerInterface,
                               power_manager::kRegisterSuspendDelayMethod);

  power_manager::RegisterSuspendDelayRequest request;
  request.set_timeout(kSuspendDelayTimeout.ToInternalValue());
  request.set_description("Pause VMs while suspended");

  if (!dbus::MessageWriter(&method_call).AppendProtoAsArrayOfBytes(request)) {
    LOG(ERROR) << "Failed to encode RegisterSuspendDelayRequest";
    return;
  }

  auto dbus_response = brillo::dbus_utils::CallDBusMethod(
      bus_, power_manager_proxy_, &method_call,
      dbus::ObjectProxy::TIMEOUT_USE_DEFAULT);
  if (!dbus_response) {
    LOG(WARNING) << "Failed to register suspend delay with powerd";
    return;
  }

  power_manager::RegisterSuspendDelayReply response;
  if (!dbus::MessageReader(dbus_response.get())
           .PopArrayOfBytesAsProto(&response)) {
    LOG(ERROR) << "Failed to read RegisterSuspendDelayReply message";
    return;
  }

  delay_id_ = response.delay_id();

  // Now that we've registered with powerd, store the callbacks and start
  // watching the signals.
  suspend_imminent_cb_ = std::move(suspend_imminent_cb);
  suspend_done_cb_ = std::move(suspend_done_cb);

  power_manager_proxy_->ConnectToSignal(
      power_manager::kPowerManagerInterface,
      power_manager::kSuspendImminentSignal,
      base::Bind(&PowerManagerClient::HandleSuspendImminent,
                 weak_factory_.GetWeakPtr()),
      base::Bind(&PowerManagerClient::HandleSignalConnected,
                 weak_factory_.GetWeakPtr()));

  power_manager_proxy_->ConnectToSignal(
      power_manager::kPowerManagerInterface, power_manager::kSuspendDoneSignal,
      base::Bind(&PowerManagerClient::HandleSuspendDone,
                 weak_factory_.GetWeakPtr()),
      base::Bind(&PowerManagerClient::HandleSignalConnected,
                 weak_factory_.GetWeakPtr()));

  power_manager_proxy_->SetNameOwnerChangedCallback(base::Bind(
      &PowerManagerClient::HandleNameOwnerChanged, weak_factory_.GetWeakPtr()));
}

void PowerManagerClient::HandleSuspendImminent(dbus::Signal* signal) {
  power_manager::SuspendImminent message;
  if (!dbus::MessageReader(signal).PopArrayOfBytesAsProto(&message)) {
    LOG(ERROR) << "Failed to decode SuspendImminent message";
    return;
  }

  if (current_suspend_id_ != kNoSuspendId) {
    LOG(WARNING) << "Received new SuspendImminent signal before receiving "
                 << "SuspendDone signal for suspend id " << current_suspend_id_;
  }

  current_suspend_id_ = message.suspend_id();

  suspend_imminent_cb_.Run();

  dbus::MethodCall method_call(power_manager::kPowerManagerInterface,
                               power_manager::kHandleSuspendReadinessMethod);

  power_manager::SuspendReadinessInfo ready;
  ready.set_delay_id(delay_id_);
  ready.set_suspend_id(current_suspend_id_);

  if (!dbus::MessageWriter(&method_call).AppendProtoAsArrayOfBytes(ready)) {
    LOG(ERROR) << "Failed to encode SuspendReadinessInfo";
    return;
  }

  auto dbus_response = brillo::dbus_utils::CallDBusMethod(
      bus_, power_manager_proxy_, &method_call,
      dbus::ObjectProxy::TIMEOUT_USE_DEFAULT);
  if (!dbus_response) {
    LOG(WARNING) << "Failed to notify powerd of suspend readiness for suspend "
                 << "id " << current_suspend_id_;
  }
}

void PowerManagerClient::HandleSuspendDone(dbus::Signal* signal) {
  power_manager::SuspendDone message;
  if (!dbus::MessageReader(signal).PopArrayOfBytesAsProto(&message)) {
    LOG(ERROR) << "Failed to decode SuspendImminent message";
  }

  if (current_suspend_id_ != message.suspend_id()) {
    LOG(WARNING) << "Ignoring SuspendDone signal for suspend id "
                 << message.suspend_id() << " because it does not match the "
                 << "current suspend id (" << current_suspend_id_ << ")";
    return;
  }

  suspend_done_cb_.Run();

  current_suspend_id_ = kNoSuspendId;
}

void PowerManagerClient::HandleNameOwnerChanged(const std::string& old_owner,
                                                const std::string& new_owner) {
  if (!new_owner.empty() && delay_id_ != -1) {
    // We had previously registered a suspend delay so re-register it.
    RegisterSuspendDelay(std::move(suspend_imminent_cb_),
                         std::move(suspend_done_cb_));
  }
}

void PowerManagerClient::HandleSignalConnected(
    const std::string& interface_name,
    const std::string& signal_name,
    bool success) {
  if (!success) {
    LOG(WARNING) << "Failed to connect to " << signal_name << " signal from "
                 << interface_name;
  }
}
}  // namespace concierge
}  // namespace vm_tools
