1 // Copyright 2024 The ChromiumOS Authors 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 //! Dbus client for sending request to powerd to get power properties. 6 7 use std::error::Error; 8 use std::time::Duration; 9 10 use dbus::blocking::Connection; 11 use protobuf::Message; 12 use remain::sorted; 13 use system_api::client::OrgChromiumPowerManager; 14 use thiserror::Error; 15 16 use crate::powerd::POWER_INTERFACE_NAME; 17 use crate::powerd::POWER_OBJECT_PATH; 18 use crate::protos::power_supply_properties::PowerSupplyProperties; 19 use crate::PowerClient; 20 use crate::PowerData; 21 22 // 25 seconds is the default timeout for dbus-send. 23 const DEFAULT_DBUS_TIMEOUT: Duration = Duration::from_secs(25); 24 25 pub struct DBusClient { 26 connection: Connection, 27 } 28 29 #[sorted] 30 #[derive(Error, Debug)] 31 pub enum DBusClientError { 32 #[error("failed to convert protobuf message: {0}")] 33 ConvertProtobuf(protobuf::Error), 34 #[error("failed to connect to D-Bus: {0}")] 35 DBusConnect(dbus::Error), 36 #[error("failed to read D-Bus message: {0}")] 37 DBusRead(dbus::Error), 38 } 39 40 impl DBusClient { 41 /// Creates a new blocking dbus connection to system bus. connect() -> std::result::Result<Box<dyn PowerClient>, Box<dyn Error>>42 pub fn connect() -> std::result::Result<Box<dyn PowerClient>, Box<dyn Error>> { 43 let channel = dbus::channel::Channel::get_private(dbus::channel::BusType::System) 44 .map_err(DBusClientError::DBusConnect)?; 45 46 let connection = dbus::blocking::Connection::from(channel); 47 48 Ok(Box::new(Self { connection })) 49 } 50 } 51 52 // Send GetPowerSupplyProperties dbus request to power_manager(powerd), blocks until it gets 53 // response, and converts the response into PowerData. 54 impl PowerClient for DBusClient { get_power_data(&mut self) -> std::result::Result<PowerData, Box<dyn Error>>55 fn get_power_data(&mut self) -> std::result::Result<PowerData, Box<dyn Error>> { 56 let proxy = self.connection.with_proxy( 57 POWER_INTERFACE_NAME, 58 POWER_OBJECT_PATH, 59 DEFAULT_DBUS_TIMEOUT, 60 ); 61 let data_bytes = proxy 62 .get_power_supply_properties() 63 .map_err(DBusClientError::DBusRead)?; 64 let mut props = PowerSupplyProperties::new(); 65 props 66 .merge_from_bytes(&data_bytes) 67 .map_err(DBusClientError::ConvertProtobuf)?; 68 let data: PowerData = props.into(); 69 Ok(data) 70 } 71 } 72