mirror of
https://gitlab.steamos.cloud/holo/steamos-manager.git
synced 2025-07-06 06:30:27 -04:00
daemon/root: Allow DsInhibit to be toggled at runtime
This commit is contained in:
parent
cae5a69e6e
commit
037d418553
2 changed files with 111 additions and 17 deletions
|
@ -8,13 +8,16 @@
|
||||||
use anyhow::{bail, Result};
|
use anyhow::{bail, Result};
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
use std::path::PathBuf;
|
use std::path::PathBuf;
|
||||||
|
use tokio::sync::mpsc::Sender;
|
||||||
|
use tokio::sync::oneshot;
|
||||||
|
use tokio_util::sync::CancellationToken;
|
||||||
use tracing::error;
|
use tracing::error;
|
||||||
use tracing_subscriber::prelude::*;
|
use tracing_subscriber::prelude::*;
|
||||||
use tracing_subscriber::{fmt, Registry};
|
use tracing_subscriber::{fmt, Registry};
|
||||||
use zbus::connection::Connection;
|
use zbus::connection::Connection;
|
||||||
use zbus::ConnectionBuilder;
|
use zbus::ConnectionBuilder;
|
||||||
|
|
||||||
use crate::daemon::{channel, Daemon, DaemonContext};
|
use crate::daemon::{channel, Daemon, DaemonCommand, DaemonContext};
|
||||||
use crate::ds_inhibit::Inhibitor;
|
use crate::ds_inhibit::Inhibitor;
|
||||||
use crate::manager::root::SteamOSManager;
|
use crate::manager::root::SteamOSManager;
|
||||||
use crate::path;
|
use crate::path;
|
||||||
|
@ -34,12 +37,61 @@ pub(crate) struct RootState {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Copy, Clone, Default, Deserialize, Serialize, Debug)]
|
#[derive(Copy, Clone, Default, Deserialize, Serialize, Debug)]
|
||||||
pub(crate) struct RootServicesState {}
|
pub(crate) struct RootServicesState {
|
||||||
|
pub ds_inhibit: DsInhibit,
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub(crate) enum RootCommand {}
|
pub(crate) enum RootCommand {
|
||||||
|
SetDsInhibit(bool),
|
||||||
|
GetDsInhibit(oneshot::Sender<bool>),
|
||||||
|
}
|
||||||
|
|
||||||
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<Command>,
|
||||||
|
|
||||||
|
ds_inhibit: Option<CancellationToken>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl RootContext {
|
||||||
|
pub(crate) fn new(channel: Sender<Command>) -> RootContext {
|
||||||
|
RootContext {
|
||||||
|
state: RootState::default(),
|
||||||
|
channel,
|
||||||
|
ds_inhibit: None,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async fn reload_ds_inhibit(&mut self, daemon: &mut Daemon<RootContext>) -> 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 {
|
impl DaemonContext for RootContext {
|
||||||
type State = RootState;
|
type State = RootState;
|
||||||
|
@ -79,19 +131,31 @@ impl DaemonContext for RootContext {
|
||||||
|
|
||||||
async fn handle_command(
|
async fn handle_command(
|
||||||
&mut self,
|
&mut self,
|
||||||
_cmd: RootCommand,
|
cmd: RootCommand,
|
||||||
_daemon: &mut Daemon<RootContext>,
|
daemon: &mut Daemon<RootContext>,
|
||||||
) -> Result<()> {
|
) -> 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(())
|
Ok(())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn create_connection() -> Result<Connection> {
|
pub(crate) type Command = DaemonCommand<RootCommand>;
|
||||||
|
|
||||||
|
async fn create_connection(channel: Sender<Command>) -> Result<Connection> {
|
||||||
let connection = ConnectionBuilder::system()?
|
let connection = ConnectionBuilder::system()?
|
||||||
.name("com.steampowered.SteamOSManager1")?
|
.name("com.steampowered.SteamOSManager1")?
|
||||||
.build()
|
.build()
|
||||||
.await?;
|
.await?;
|
||||||
let manager = SteamOSManager::new(connection.clone()).await?;
|
let manager = SteamOSManager::new(connection.clone(), channel).await?;
|
||||||
connection
|
connection
|
||||||
.object_server()
|
.object_server()
|
||||||
.at("/com/steampowered/SteamOSManager1", manager)
|
.at("/com/steampowered/SteamOSManager1", manager)
|
||||||
|
@ -105,9 +169,9 @@ pub async fn daemon() -> Result<()> {
|
||||||
|
|
||||||
let stdout_log = fmt::layer();
|
let stdout_log = fmt::layer();
|
||||||
let subscriber = Registry::default().with(stdout_log);
|
let subscriber = Registry::default().with(stdout_log);
|
||||||
let (_tx, rx) = channel::<RootContext>();
|
let (tx, rx) = channel::<RootContext>();
|
||||||
|
|
||||||
let connection = match create_connection().await {
|
let connection = match create_connection(tx.clone()).await {
|
||||||
Ok(c) => c,
|
Ok(c) => c,
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
let _guard = tracing::subscriber::set_default(subscriber);
|
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 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);
|
daemon.add_service(ftrace);
|
||||||
|
|
||||||
let inhibitor = Inhibitor::init().await?;
|
|
||||||
daemon.add_service(inhibitor);
|
|
||||||
|
|
||||||
daemon.run(context).await
|
daemon.run(context).await
|
||||||
}
|
}
|
||||||
|
|
|
@ -8,10 +8,14 @@
|
||||||
|
|
||||||
use anyhow::Result;
|
use anyhow::Result;
|
||||||
use tokio::fs::File;
|
use tokio::fs::File;
|
||||||
|
use tokio::sync::mpsc::Sender;
|
||||||
|
use tokio::sync::oneshot;
|
||||||
use tracing::error;
|
use tracing::error;
|
||||||
use zbus::zvariant::Fd;
|
use zbus::zvariant::Fd;
|
||||||
use zbus::{fdo, interface, Connection, SignalContext};
|
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::error::{to_zbus_error, to_zbus_fdo_error};
|
||||||
use crate::hardware::{variant, FanControl, FanControlState, HardwareVariant};
|
use crate::hardware::{variant, FanControl, FanControlState, HardwareVariant};
|
||||||
use crate::power::{
|
use crate::power::{
|
||||||
|
@ -34,6 +38,7 @@ enum PrepareFactoryReset {
|
||||||
|
|
||||||
pub struct SteamOSManager {
|
pub struct SteamOSManager {
|
||||||
connection: Connection,
|
connection: Connection,
|
||||||
|
channel: Sender<Command>,
|
||||||
wifi_debug_mode: WifiDebugMode,
|
wifi_debug_mode: WifiDebugMode,
|
||||||
fan_control: FanControl,
|
fan_control: FanControl,
|
||||||
// Whether we should use trace-cmd or not.
|
// Whether we should use trace-cmd or not.
|
||||||
|
@ -43,13 +48,14 @@ pub struct SteamOSManager {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl SteamOSManager {
|
impl SteamOSManager {
|
||||||
pub async fn new(connection: Connection) -> Result<Self> {
|
pub async fn new(connection: Connection, channel: Sender<Command>) -> Result<Self> {
|
||||||
Ok(SteamOSManager {
|
Ok(SteamOSManager {
|
||||||
fan_control: FanControl::new(connection.clone()),
|
fan_control: FanControl::new(connection.clone()),
|
||||||
wifi_debug_mode: WifiDebugMode::Off,
|
wifi_debug_mode: WifiDebugMode::Off,
|
||||||
should_trace: variant().await? == HardwareVariant::Galileo,
|
should_trace: variant().await? == HardwareVariant::Galileo,
|
||||||
process_manager: ProcessManager::new(connection.clone()),
|
process_manager: ProcessManager::new(connection.clone()),
|
||||||
connection,
|
connection,
|
||||||
|
channel,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -260,6 +266,30 @@ impl SteamOSManager {
|
||||||
.map_err(to_zbus_fdo_error)
|
.map_err(to_zbus_fdo_error)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[zbus(property)]
|
||||||
|
async fn inhibit_ds(&self) -> fdo::Result<bool> {
|
||||||
|
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.
|
/// A version property.
|
||||||
#[zbus(property(emits_changed_signal = "const"))]
|
#[zbus(property(emits_changed_signal = "const"))]
|
||||||
async fn version(&self) -> u32 {
|
async fn version(&self) -> u32 {
|
||||||
|
@ -270,6 +300,8 @@ impl SteamOSManager {
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod test {
|
mod test {
|
||||||
use super::*;
|
use super::*;
|
||||||
|
use crate::daemon::channel;
|
||||||
|
use crate::daemon::root::RootContext;
|
||||||
use crate::power::test::{format_clocks, read_clocks};
|
use crate::power::test::{format_clocks, read_clocks};
|
||||||
use crate::power::{self, get_gpu_performance_level};
|
use crate::power::{self, get_gpu_performance_level};
|
||||||
use crate::testing;
|
use crate::testing;
|
||||||
|
@ -293,8 +325,9 @@ mod test {
|
||||||
)
|
)
|
||||||
.await?;
|
.await?;
|
||||||
|
|
||||||
|
let (tx, _rx) = channel::<RootContext>();
|
||||||
let connection = ConnectionBuilder::session()?.build().await?;
|
let connection = ConnectionBuilder::session()?.build().await?;
|
||||||
let manager = SteamOSManager::new(connection.clone()).await?;
|
let manager = SteamOSManager::new(connection.clone(), tx).await?;
|
||||||
connection
|
connection
|
||||||
.object_server()
|
.object_server()
|
||||||
.at("/com/steampowered/SteamOSManager1", manager)
|
.at("/com/steampowered/SteamOSManager1", manager)
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue