blob: cac3593b592705a2218b0b862c59c26cf86e8d96 [file] [log] [blame]
// Copyright 2020 The Fuchsia 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 "system_state_manager.h"
#include <lib/fidl-async/cpp/bind.h>
#include <zircon/status.h>
#include "src/devices/lib/log/log.h"
zx_status_t SystemStateManager::Create(async_dispatcher_t* dispatcher, Coordinator* dev_coord,
zx::channel system_state_transition_server,
std::unique_ptr<SystemStateManager>* state_mgr) {
// Invoked when the channel is closed or on any binding-related error.
// When power manager exists, but closes this channel, it means power manager
// existed but crashed, and we will not have a way to reboot the system.
// We would need to reboot in that case.
fidl::OnUnboundFn<device_manager_fidl::SystemStateTransition::Interface> unbound_fn(
[](device_manager_fidl::SystemStateTransition::Interface* sys_state_manager,
fidl::UnbindInfo info, zx::channel) {
LOGF(ERROR, "system state transition channel with power manager got unbound:%d",
static_cast<uint32_t>(info.reason));
SystemStateManager* system_state_manager =
static_cast<SystemStateManager*>(sys_state_manager);
Coordinator* dev_coord = system_state_manager->dev_coord_;
if (!dev_coord->power_manager_registered()) {
return;
}
dev_coord->set_power_manager_registered(false);
});
auto mgr = std::make_unique<SystemStateManager>(dev_coord);
auto result = fidl::BindServer(
dispatcher, std::move(system_state_transition_server),
static_cast<device_manager_fidl::SystemStateTransition::Interface*>(mgr.get()),
std::move(unbound_fn));
if (!result.is_ok()) {
LOGF(ERROR, "Failed to bind to client channel for '%s': %s",
device_manager_fidl::SystemStateTransition::Name, zx_status_get_string(result.error()));
return result.error();
}
*state_mgr = std::move(mgr);
return ZX_OK;
}
void SystemStateManager::SetTerminationSystemState(
power_fidl::statecontrol::SystemPowerState state,
device_manager_fidl::SystemStateTransition::Interface::SetTerminationSystemStateCompleter::Sync&
completer) {
if (state == power_fidl::statecontrol::SystemPowerState::FULLY_ON) {
LOGF(INFO, "Invalid termination state");
completer.ReplyError(ZX_ERR_INVALID_ARGS);
return;
}
LOGF(INFO, "Setting shutdown system state to %d", state);
dev_coord_->set_shutdown_system_state(state);
completer.ReplySuccess();
}