sl4f_lib/hardware_power_statecontrol/
facade.rs

1// Copyright 2020 The Fuchsia Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5use crate::common_utils::common::macros::{fx_err_and_bail, with_line};
6use anyhow::Error;
7use fidl_fuchsia_hardware_power_statecontrol::{
8    AdminMarker, AdminProxy, ShutdownAction, ShutdownOptions, ShutdownReason,
9};
10use fuchsia_component as app;
11use log::info;
12
13/// Perform Fuchsia Device Manager fidl operations.
14///
15/// Note this object is shared among all threads created by server.
16///
17#[derive(Debug)]
18pub struct HardwarePowerStatecontrolFacade {}
19
20impl HardwarePowerStatecontrolFacade {
21    pub fn new() -> HardwarePowerStatecontrolFacade {
22        HardwarePowerStatecontrolFacade {}
23    }
24
25    fn get_admin_proxy(&self) -> Result<AdminProxy, Error> {
26        let tag = "HardwarePowerStatecontrolFacade";
27        match app::client::connect_to_protocol::<AdminMarker>() {
28            Ok(p) => Ok(p),
29            Err(err) => fx_err_and_bail!(
30                &with_line!(tag),
31                format_err!("Failed to create device admin proxy: {:?}", err)
32            ),
33        }
34    }
35
36    /// Reboot the Fuchsia device
37    pub async fn suspend_reboot(&self) -> Result<(), Error> {
38        let tag = "HardwarePowerStatecontrolFacade::suspend_reboot";
39        info!("Executing Suspend: REBOOT");
40        if let Err(err) = self
41            .get_admin_proxy()?
42            .shutdown(&ShutdownOptions {
43                action: Some(ShutdownAction::Reboot),
44                reasons: Some(vec![ShutdownReason::DeveloperRequest]),
45                ..Default::default()
46            })
47            .await?
48        {
49            fx_err_and_bail!(
50                &with_line!(tag),
51                format_err!("Failed to change power control state: {:?}", err)
52            )
53        }
54        Ok(())
55    }
56
57    /// Reboot the Fuchsia device into the bootloader
58    pub async fn suspend_reboot_bootloader(&self) -> Result<(), Error> {
59        let tag = "HardwarePowerStatecontrolFacade::suspend_reboot_bootloader";
60        info!("Executing Suspend: REBOOT_BOOTLOADER");
61
62        if let Err(err) = self
63            .get_admin_proxy()?
64            .shutdown(&ShutdownOptions {
65                action: Some(ShutdownAction::RebootToBootloader),
66                reasons: Some(vec![ShutdownReason::DeveloperRequest]),
67                ..Default::default()
68            })
69            .await?
70        {
71            fx_err_and_bail!(
72                &with_line!(tag),
73                format_err!("Failed to change power control state: {:?}", err)
74            )
75        }
76        Ok(())
77    }
78
79    /// Reboot the Fuchsia device into recovery
80    pub async fn suspend_reboot_recovery(&self) -> Result<(), Error> {
81        let tag = "HardwarePowerStatecontrolFacade::suspend_reboot_recovery";
82        info!("Executing Suspend: REBOOT_RECOVERY");
83        if let Err(err) = self
84            .get_admin_proxy()?
85            .shutdown(&ShutdownOptions {
86                action: Some(ShutdownAction::RebootToRecovery),
87                reasons: Some(vec![ShutdownReason::DeveloperRequest]),
88                ..Default::default()
89            })
90            .await?
91        {
92            fx_err_and_bail!(
93                &with_line!(tag),
94                format_err!("Failed to change power control state: {:?}", err)
95            )
96        }
97        Ok(())
98    }
99
100    /// Power off the Fuchsia device
101    pub async fn suspend_poweroff(&self) -> Result<(), Error> {
102        let tag = "HardwarePowerStatecontrolFacade::suspend_poweroff";
103        info!("Executing Suspend: POWEROFF");
104
105        if let Err(err) = self
106            .get_admin_proxy()?
107            .shutdown(&ShutdownOptions {
108                action: Some(ShutdownAction::Poweroff),
109                reasons: Some(vec![ShutdownReason::DeveloperRequest]),
110                ..Default::default()
111            })
112            .await?
113        {
114            fx_err_and_bail!(
115                &with_line!(tag),
116                format_err!("Failed to change power control state: {:?}", err)
117            )
118        }
119        Ok(())
120    }
121
122    /// Suspend MEXEC the Fuchsia device
123    pub async fn suspend_mexec(&self) -> Result<(), Error> {
124        let tag = "HardwarePowerStatecontrolFacade::suspend_mexec";
125        // We limit mexec access here, as its near-term future is in question.
126        fx_err_and_bail!(&with_line!(tag), format!("Unsupported"))
127    }
128
129    /// RSuspend RAM on the Fuchsia device
130    pub async fn suspend_ram(&self) -> Result<(), Error> {
131        let tag = "HardwarePowerStatecontrolFacade::suspend_ram";
132        info!("Executing Suspend: SUSPEND_RAM");
133        if let Err(err) = self.get_admin_proxy()?.suspend_to_ram().await? {
134            fx_err_and_bail!(
135                &with_line!(tag),
136                format_err!("Failed to change power control state: {:?}", err)
137            )
138        }
139        Ok(())
140    }
141}