Loading system/gd/rust/linux/mgmt/src/powerd_suspend_manager.rs +4 −3 Original line number Diff line number Diff line Loading @@ -226,7 +226,8 @@ impl PowerdSuspendManager { .await; // Watch events of btadapterd appearing or disappearing. let adapter_watcher = ServiceWatcher::new(self.conn.clone(), String::from(ADAPTER_SERVICE)); let mut adapter_watcher = ServiceWatcher::new(self.conn.clone(), String::from(ADAPTER_SERVICE)); let tx1 = self.tx.clone(); let tx2 = self.tx.clone(); adapter_watcher Loading Loading @@ -470,7 +471,7 @@ impl PowerdSuspendManager { } fn on_adapter_found(&mut self, path: dbus::Path<'static>) { log::debug!("Found adapter {:?}", path); log::debug!("Found adapter suspend {:?}", path); let conn = self.conn.clone(); self.context.lock().unwrap().adapter_suspend_dbus = Loading @@ -491,7 +492,7 @@ impl PowerdSuspendManager { } fn on_adapter_removed(&mut self) { log::debug!("Adapter removed"); log::debug!("Adapter suspend removed"); self.context.lock().unwrap().adapter_suspend_dbus = None; } } system/gd/rust/linux/mgmt/src/service_watcher.rs +69 −13 Original line number Diff line number Diff line Loading @@ -3,7 +3,7 @@ use dbus::channel::MatchingReceiver; use dbus::message::MatchRule; use dbus::nonblock::stdintf::org_freedesktop_dbus::ObjectManager; use dbus::nonblock::SyncConnection; use std::sync::Arc; use std::sync::{Arc, Mutex}; use std::time::Duration; const DBUS_SERVICE: &str = "org.freedesktop.DBus"; Loading @@ -15,18 +15,46 @@ const DBUS_INTERFACES_ADDED: &str = "InterfacesAdded"; const DBUS_PATH: &str = "/org/freedesktop/DBus"; const DBUS_TIMEOUT: Duration = Duration::from_secs(2); struct ServiceWatcherContext { // The service name to watch. service_name: String, // The owner D-Bus address if exists. service_owner: Option<String>, } impl ServiceWatcherContext { fn new(service_name: String) -> Self { Self { service_name, service_owner: None } } fn set_owner(&mut self, owner: String) { log::debug!("setting owner of {} to {}", self.service_name, owner); self.service_owner = Some(owner); } fn unset_owner(&mut self) { log::debug!("unsetting owner of {}", self.service_name); self.service_owner = None; } } pub struct ServiceWatcher { conn: Arc<SyncConnection>, service_name: String, context: Arc<Mutex<ServiceWatcherContext>>, } impl ServiceWatcher { pub fn new(conn: Arc<SyncConnection>, service_name: String) -> Self { ServiceWatcher { conn, service_name } ServiceWatcher { conn, service_name: service_name.clone(), context: Arc::new(Mutex::new(ServiceWatcherContext::new(service_name))), } } // Returns true if the named D-Bus service is available. async fn is_service_available(&self) -> bool { // Returns the owner D-Bus address of the named service. async fn get_dbus_owner_of_service(&self) -> Option<String> { let dbus_proxy = dbus::nonblock::Proxy::new(DBUS_SERVICE, DBUS_PATH, DBUS_TIMEOUT, self.conn.clone()); Loading @@ -37,11 +65,11 @@ impl ServiceWatcher { match service_owner { Err(e) => { log::debug!("Getting service owner failed: {}", e); false None } Ok((owner,)) => { log::debug!("{} service owner = {}", self.service_name, owner); true log::debug!("Got service owner {} = {}", self.service_name, owner); Some(owner) } } } Loading Loading @@ -69,6 +97,7 @@ impl ServiceWatcher { } } // Monitors the service appearance or disappearance and keeps the owner address updated. async fn monitor_name_owner_changed( &self, on_available: Box<dyn Fn() + Send>, Loading @@ -77,9 +106,14 @@ impl ServiceWatcher { let mr = MatchRule::new_signal(DBUS_INTERFACE, DBUS_NAME_OWNER_CHANGED); self.conn.add_match_no_cb(&mr.match_str()).await.unwrap(); let service_name = self.service_name.clone(); let context = self.context.clone(); self.conn.start_receive( mr, Box::new(move |msg, _conn| { // We use [`dbus::nonblock::SyncConnection::set_signal_match_mode`] with // `match_all` = true, so we should always return true from this closure to // indicate that we have handled the message and not let other handlers handle this // signal. if let (Some(name), Some(old_owner), Some(new_owner)) = msg.get3::<String, String, String>() { Loading @@ -90,8 +124,10 @@ impl ServiceWatcher { } if old_owner == "" && new_owner != "" { context.lock().unwrap().set_owner(new_owner.clone()); on_available(); } else if old_owner != "" && new_owner == "" { context.lock().unwrap().unset_owner(); on_unavailable(); } else { log::warn!( Loading @@ -112,8 +148,8 @@ impl ServiceWatcher { on_available: Box<dyn Fn() + Send>, on_unavailable: Box<dyn Fn() + Send>, ) { if self.is_service_available().await { // If service is already available at the start, just call the hook immediately. if let Some(owner) = self.get_dbus_owner_of_service().await { self.context.lock().unwrap().set_owner(owner.clone()); on_available(); } Loading @@ -134,12 +170,13 @@ impl ServiceWatcher { /// Doesn't take into account the disappearance of the interface itself. At the moment assuming /// interfaces do not disappear as long as the service is alive. pub async fn start_watch_interface( &self, &mut self, interface: String, on_available: Box<dyn Fn(dbus::Path<'static>) + Send>, on_unavailable: Box<dyn Fn() + Send>, ) { if self.is_service_available().await { if let Some(owner) = self.get_dbus_owner_of_service().await { self.context.lock().unwrap().set_owner(owner.clone()); if let Some(path) = self.get_path_of_interface(interface.clone()).await { on_available(path); } Loading @@ -148,7 +185,7 @@ impl ServiceWatcher { // Monitor service disappearing. self.monitor_name_owner_changed( Box::new(move || { // Ignore service appearing because we rely on interface added. // Don't trigger on_available() yet because we rely on interface added. }), Box::new(move || { on_unavailable(); Loading @@ -159,15 +196,34 @@ impl ServiceWatcher { // Monitor interface appearing. let mr = MatchRule::new_signal(DBUS_OBJMGR_INTERFACE, DBUS_INTERFACES_ADDED); self.conn.add_match_no_cb(&mr.match_str()).await.unwrap(); let context = self.context.clone(); self.conn.start_receive( mr, Box::new(move |msg, _conn| { // We use [`dbus::nonblock::SyncConnection::set_signal_match_mode`] with // `match_all` = true, so we should always return true from this closure to // indicate that we have handled the message and not let other handlers handle this // signal. let (object_path, interfaces) = msg.get2::<dbus::Path, dbus::arg::Dict<String, dbus::arg::PropMap, _>>(); let interfaces: Vec<String> = interfaces.unwrap().map(|e| e.0).collect(); if interfaces.contains(&interface) { if let (Some(sender), Some(owner)) = (msg.sender(), context.lock().unwrap().service_owner.as_ref()) { // The signal does not come from the service we are watching, ignore. if &sender.to_string() != owner { log::debug!( "Detected interface {} added but sender is {}, expected {}.", interface, sender, owner ); return true; } on_available(object_path.unwrap().into_static()); } } true }), Loading Loading
system/gd/rust/linux/mgmt/src/powerd_suspend_manager.rs +4 −3 Original line number Diff line number Diff line Loading @@ -226,7 +226,8 @@ impl PowerdSuspendManager { .await; // Watch events of btadapterd appearing or disappearing. let adapter_watcher = ServiceWatcher::new(self.conn.clone(), String::from(ADAPTER_SERVICE)); let mut adapter_watcher = ServiceWatcher::new(self.conn.clone(), String::from(ADAPTER_SERVICE)); let tx1 = self.tx.clone(); let tx2 = self.tx.clone(); adapter_watcher Loading Loading @@ -470,7 +471,7 @@ impl PowerdSuspendManager { } fn on_adapter_found(&mut self, path: dbus::Path<'static>) { log::debug!("Found adapter {:?}", path); log::debug!("Found adapter suspend {:?}", path); let conn = self.conn.clone(); self.context.lock().unwrap().adapter_suspend_dbus = Loading @@ -491,7 +492,7 @@ impl PowerdSuspendManager { } fn on_adapter_removed(&mut self) { log::debug!("Adapter removed"); log::debug!("Adapter suspend removed"); self.context.lock().unwrap().adapter_suspend_dbus = None; } }
system/gd/rust/linux/mgmt/src/service_watcher.rs +69 −13 Original line number Diff line number Diff line Loading @@ -3,7 +3,7 @@ use dbus::channel::MatchingReceiver; use dbus::message::MatchRule; use dbus::nonblock::stdintf::org_freedesktop_dbus::ObjectManager; use dbus::nonblock::SyncConnection; use std::sync::Arc; use std::sync::{Arc, Mutex}; use std::time::Duration; const DBUS_SERVICE: &str = "org.freedesktop.DBus"; Loading @@ -15,18 +15,46 @@ const DBUS_INTERFACES_ADDED: &str = "InterfacesAdded"; const DBUS_PATH: &str = "/org/freedesktop/DBus"; const DBUS_TIMEOUT: Duration = Duration::from_secs(2); struct ServiceWatcherContext { // The service name to watch. service_name: String, // The owner D-Bus address if exists. service_owner: Option<String>, } impl ServiceWatcherContext { fn new(service_name: String) -> Self { Self { service_name, service_owner: None } } fn set_owner(&mut self, owner: String) { log::debug!("setting owner of {} to {}", self.service_name, owner); self.service_owner = Some(owner); } fn unset_owner(&mut self) { log::debug!("unsetting owner of {}", self.service_name); self.service_owner = None; } } pub struct ServiceWatcher { conn: Arc<SyncConnection>, service_name: String, context: Arc<Mutex<ServiceWatcherContext>>, } impl ServiceWatcher { pub fn new(conn: Arc<SyncConnection>, service_name: String) -> Self { ServiceWatcher { conn, service_name } ServiceWatcher { conn, service_name: service_name.clone(), context: Arc::new(Mutex::new(ServiceWatcherContext::new(service_name))), } } // Returns true if the named D-Bus service is available. async fn is_service_available(&self) -> bool { // Returns the owner D-Bus address of the named service. async fn get_dbus_owner_of_service(&self) -> Option<String> { let dbus_proxy = dbus::nonblock::Proxy::new(DBUS_SERVICE, DBUS_PATH, DBUS_TIMEOUT, self.conn.clone()); Loading @@ -37,11 +65,11 @@ impl ServiceWatcher { match service_owner { Err(e) => { log::debug!("Getting service owner failed: {}", e); false None } Ok((owner,)) => { log::debug!("{} service owner = {}", self.service_name, owner); true log::debug!("Got service owner {} = {}", self.service_name, owner); Some(owner) } } } Loading Loading @@ -69,6 +97,7 @@ impl ServiceWatcher { } } // Monitors the service appearance or disappearance and keeps the owner address updated. async fn monitor_name_owner_changed( &self, on_available: Box<dyn Fn() + Send>, Loading @@ -77,9 +106,14 @@ impl ServiceWatcher { let mr = MatchRule::new_signal(DBUS_INTERFACE, DBUS_NAME_OWNER_CHANGED); self.conn.add_match_no_cb(&mr.match_str()).await.unwrap(); let service_name = self.service_name.clone(); let context = self.context.clone(); self.conn.start_receive( mr, Box::new(move |msg, _conn| { // We use [`dbus::nonblock::SyncConnection::set_signal_match_mode`] with // `match_all` = true, so we should always return true from this closure to // indicate that we have handled the message and not let other handlers handle this // signal. if let (Some(name), Some(old_owner), Some(new_owner)) = msg.get3::<String, String, String>() { Loading @@ -90,8 +124,10 @@ impl ServiceWatcher { } if old_owner == "" && new_owner != "" { context.lock().unwrap().set_owner(new_owner.clone()); on_available(); } else if old_owner != "" && new_owner == "" { context.lock().unwrap().unset_owner(); on_unavailable(); } else { log::warn!( Loading @@ -112,8 +148,8 @@ impl ServiceWatcher { on_available: Box<dyn Fn() + Send>, on_unavailable: Box<dyn Fn() + Send>, ) { if self.is_service_available().await { // If service is already available at the start, just call the hook immediately. if let Some(owner) = self.get_dbus_owner_of_service().await { self.context.lock().unwrap().set_owner(owner.clone()); on_available(); } Loading @@ -134,12 +170,13 @@ impl ServiceWatcher { /// Doesn't take into account the disappearance of the interface itself. At the moment assuming /// interfaces do not disappear as long as the service is alive. pub async fn start_watch_interface( &self, &mut self, interface: String, on_available: Box<dyn Fn(dbus::Path<'static>) + Send>, on_unavailable: Box<dyn Fn() + Send>, ) { if self.is_service_available().await { if let Some(owner) = self.get_dbus_owner_of_service().await { self.context.lock().unwrap().set_owner(owner.clone()); if let Some(path) = self.get_path_of_interface(interface.clone()).await { on_available(path); } Loading @@ -148,7 +185,7 @@ impl ServiceWatcher { // Monitor service disappearing. self.monitor_name_owner_changed( Box::new(move || { // Ignore service appearing because we rely on interface added. // Don't trigger on_available() yet because we rely on interface added. }), Box::new(move || { on_unavailable(); Loading @@ -159,15 +196,34 @@ impl ServiceWatcher { // Monitor interface appearing. let mr = MatchRule::new_signal(DBUS_OBJMGR_INTERFACE, DBUS_INTERFACES_ADDED); self.conn.add_match_no_cb(&mr.match_str()).await.unwrap(); let context = self.context.clone(); self.conn.start_receive( mr, Box::new(move |msg, _conn| { // We use [`dbus::nonblock::SyncConnection::set_signal_match_mode`] with // `match_all` = true, so we should always return true from this closure to // indicate that we have handled the message and not let other handlers handle this // signal. let (object_path, interfaces) = msg.get2::<dbus::Path, dbus::arg::Dict<String, dbus::arg::PropMap, _>>(); let interfaces: Vec<String> = interfaces.unwrap().map(|e| e.0).collect(); if interfaces.contains(&interface) { if let (Some(sender), Some(owner)) = (msg.sender(), context.lock().unwrap().service_owner.as_ref()) { // The signal does not come from the service we are watching, ignore. if &sender.to_string() != owner { log::debug!( "Detected interface {} added but sender is {}, expected {}.", interface, sender, owner ); return true; } on_available(object_path.unwrap().into_static()); } } true }), Loading