| // 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(); |
| } |