From 037d418553d8f25267b9214e7c070bb7409eb883 Mon Sep 17 00:00:00 2001 From: Vicki Pfau Date: Tue, 11 Jun 2024 17:48:36 -0700 Subject: [PATCH] daemon/root: Allow DsInhibit to be toggled at runtime --- src/daemon/root.rs | 91 +++++++++++++++++++++++++++++++++++++-------- src/manager/root.rs | 37 +++++++++++++++++- 2 files changed, 111 insertions(+), 17 deletions(-) diff --git a/src/daemon/root.rs b/src/daemon/root.rs index b073371..11d78b5 100644 --- a/src/daemon/root.rs +++ b/src/daemon/root.rs @@ -8,13 +8,16 @@ use anyhow::{bail, Result}; use serde::{Deserialize, Serialize}; use std::path::PathBuf; +use tokio::sync::mpsc::Sender; +use tokio::sync::oneshot; +use tokio_util::sync::CancellationToken; use tracing::error; use tracing_subscriber::prelude::*; use tracing_subscriber::{fmt, Registry}; use zbus::connection::Connection; use zbus::ConnectionBuilder; -use crate::daemon::{channel, Daemon, DaemonContext}; +use crate::daemon::{channel, Daemon, DaemonCommand, DaemonContext}; use crate::ds_inhibit::Inhibitor; use crate::manager::root::SteamOSManager; use crate::path; @@ -34,12 +37,61 @@ pub(crate) struct RootState { } #[derive(Copy, Clone, Default, Deserialize, Serialize, Debug)] -pub(crate) struct RootServicesState {} +pub(crate) struct RootServicesState { + pub ds_inhibit: DsInhibit, +} #[derive(Debug)] -pub(crate) enum RootCommand {} +pub(crate) enum RootCommand { + SetDsInhibit(bool), + GetDsInhibit(oneshot::Sender), +} -struct RootContext {} +#[derive(Copy, Clone, Deserialize, Serialize, Debug)] +pub(crate) struct DsInhibit { + pub enabled: bool, +} + +impl Default for DsInhibit { + fn default() -> DsInhibit { + DsInhibit { enabled: true } + } +} + +pub(crate) struct RootContext { + state: RootState, + channel: Sender, + + ds_inhibit: Option, +} + +impl RootContext { + pub(crate) fn new(channel: Sender) -> RootContext { + RootContext { + state: RootState::default(), + channel, + ds_inhibit: None, + } + } + + async fn reload_ds_inhibit(&mut self, daemon: &mut Daemon) -> Result<()> { + match ( + self.state.services.ds_inhibit.enabled, + self.ds_inhibit.as_ref(), + ) { + (false, Some(handle)) => { + handle.cancel(); + self.ds_inhibit = None; + } + (true, None) => { + let inhibitor = Inhibitor::init().await?; + self.ds_inhibit = Some(daemon.add_service(inhibitor)); + } + _ => (), + } + Ok(()) + } +} impl DaemonContext for RootContext { type State = RootState; @@ -79,19 +131,31 @@ impl DaemonContext for RootContext { async fn handle_command( &mut self, - _cmd: RootCommand, - _daemon: &mut Daemon, + cmd: RootCommand, + daemon: &mut Daemon, ) -> Result<()> { + match cmd { + RootCommand::SetDsInhibit(enable) => { + self.state.services.ds_inhibit.enabled = enable; + self.reload_ds_inhibit(daemon).await?; + self.channel.send(DaemonCommand::WriteState).await?; + } + RootCommand::GetDsInhibit(sender) => { + let _ = sender.send(self.ds_inhibit.is_some()); + } + } Ok(()) } } -async fn create_connection() -> Result { +pub(crate) type Command = DaemonCommand; + +async fn create_connection(channel: Sender) -> Result { let connection = ConnectionBuilder::system()? .name("com.steampowered.SteamOSManager1")? .build() .await?; - let manager = SteamOSManager::new(connection.clone()).await?; + let manager = SteamOSManager::new(connection.clone(), channel).await?; connection .object_server() .at("/com/steampowered/SteamOSManager1", manager) @@ -105,9 +169,9 @@ pub async fn daemon() -> Result<()> { let stdout_log = fmt::layer(); let subscriber = Registry::default().with(stdout_log); - let (_tx, rx) = channel::(); + let (tx, rx) = channel::(); - let connection = match create_connection().await { + let connection = match create_connection(tx.clone()).await { Ok(c) => c, Err(e) => { let _guard = tracing::subscriber::set_default(subscriber); @@ -116,14 +180,11 @@ pub async fn daemon() -> Result<()> { } }; - let context = RootContext {}; + let context = RootContext::new(tx); let mut daemon = Daemon::new(subscriber, connection.clone(), rx).await?; - let ftrace = Ftrace::init(connection.clone()).await?; + let ftrace = Ftrace::init(connection).await?; daemon.add_service(ftrace); - let inhibitor = Inhibitor::init().await?; - daemon.add_service(inhibitor); - daemon.run(context).await } diff --git a/src/manager/root.rs b/src/manager/root.rs index 71bc506..c9e7621 100644 --- a/src/manager/root.rs +++ b/src/manager/root.rs @@ -8,10 +8,14 @@ use anyhow::Result; use tokio::fs::File; +use tokio::sync::mpsc::Sender; +use tokio::sync::oneshot; use tracing::error; use zbus::zvariant::Fd; use zbus::{fdo, interface, Connection, SignalContext}; +use crate::daemon::root::{Command, RootCommand}; +use crate::daemon::DaemonCommand; use crate::error::{to_zbus_error, to_zbus_fdo_error}; use crate::hardware::{variant, FanControl, FanControlState, HardwareVariant}; use crate::power::{ @@ -34,6 +38,7 @@ enum PrepareFactoryReset { pub struct SteamOSManager { connection: Connection, + channel: Sender, wifi_debug_mode: WifiDebugMode, fan_control: FanControl, // Whether we should use trace-cmd or not. @@ -43,13 +48,14 @@ pub struct SteamOSManager { } impl SteamOSManager { - pub async fn new(connection: Connection) -> Result { + pub async fn new(connection: Connection, channel: Sender) -> Result { Ok(SteamOSManager { fan_control: FanControl::new(connection.clone()), wifi_debug_mode: WifiDebugMode::Off, should_trace: variant().await? == HardwareVariant::Galileo, process_manager: ProcessManager::new(connection.clone()), connection, + channel, }) } } @@ -260,6 +266,30 @@ impl SteamOSManager { .map_err(to_zbus_fdo_error) } + #[zbus(property)] + async fn inhibit_ds(&self) -> fdo::Result { + let (tx, rx) = oneshot::channel(); + self.channel + .send(DaemonCommand::ContextCommand(RootCommand::GetDsInhibit(tx))) + .await + .inspect_err(|message| error!("Error sending GetDsInhibit command: {message}")) + .map_err(to_zbus_fdo_error)?; + rx.await + .inspect_err(|message| error!("Error receiving GetDsInhibit reply: {message}")) + .map_err(to_zbus_fdo_error) + } + + #[zbus(property)] + async fn set_inhibit_ds(&self, enable: bool) -> zbus::Result<()> { + self.channel + .send(DaemonCommand::ContextCommand(RootCommand::SetDsInhibit( + enable, + ))) + .await + .inspect_err(|message| error!("Error sending SetDsInhibit command: {message}")) + .map_err(to_zbus_error) + } + /// A version property. #[zbus(property(emits_changed_signal = "const"))] async fn version(&self) -> u32 { @@ -270,6 +300,8 @@ impl SteamOSManager { #[cfg(test)] mod test { use super::*; + use crate::daemon::channel; + use crate::daemon::root::RootContext; use crate::power::test::{format_clocks, read_clocks}; use crate::power::{self, get_gpu_performance_level}; use crate::testing; @@ -293,8 +325,9 @@ mod test { ) .await?; + let (tx, _rx) = channel::(); let connection = ConnectionBuilder::session()?.build().await?; - let manager = SteamOSManager::new(connection.clone()).await?; + let manager = SteamOSManager::new(connection.clone(), tx).await?; connection .object_server() .at("/com/steampowered/SteamOSManager1", manager)