Loading system/gd/rust/linux/service/src/iface_battery_manager.rs +11 −9 Original line number Diff line number Diff line use btstack::battery_manager::{Battery, IBatteryManager, IBatteryManagerCallback}; use btstack::battery_manager::{Battery, BatterySet, IBatteryManager, IBatteryManagerCallback}; use btstack::RPCProxy; use dbus::arg::RefArg; use dbus::strings::Path; Loading @@ -7,10 +7,17 @@ use dbus_projection::{dbus_generated, DisconnectWatcher}; use crate::dbus_arg::{DBusArg, DBusArgError, RefArgToRust}; #[dbus_propmap(BatterySet)] pub struct BatterySetDBus { address: String, source_uuid: String, source_info: String, batteries: Vec<Battery>, } #[dbus_propmap(Battery)] pub struct BatteryDBus { percentage: u32, source_info: String, variant: String, } Loading @@ -19,7 +26,7 @@ struct IBatteryManagerCallbackDBus {} #[dbus_proxy_obj(BatteryManagerCallback, "org.chromium.bluetooth.BatteryManagerCallback")] impl IBatteryManagerCallback for IBatteryManagerCallbackDBus { #[dbus_method("OnBatteryInfoUpdated")] fn on_battery_info_updated(&self, remote_address: String, battery: Battery) { fn on_battery_info_updated(&self, remote_address: String, battery_set: BatterySet) { dbus_generated!() } } Loading @@ -41,13 +48,8 @@ impl IBatteryManager for IBatteryManagerDBus { dbus_generated!() } #[dbus_method("EnableNotifications")] fn enable_notifications(&mut self, callback_id: u32, enable: bool) { dbus_generated!() } #[dbus_method("GetBatteryInformation")] fn get_battery_information(&self, remote_address: String) -> Option<Battery> { fn get_battery_information(&self, remote_address: String) -> Option<BatterySet> { dbus_generated!() } } system/gd/rust/linux/service/src/iface_battery_provider_manager.rs +8 −18 Original line number Diff line number Diff line use btstack::battery_manager::Battery; use btstack::battery_provider_manager::{ BatteryProvider, IBatteryProviderCallback, IBatteryProviderManager, }; use btstack::battery_manager::BatterySet; use btstack::battery_provider_manager::{IBatteryProviderCallback, IBatteryProviderManager}; use btstack::RPCProxy; use dbus::arg::RefArg; use dbus::strings::Path; use dbus_macros::{dbus_method, dbus_propmap, dbus_proxy_obj, generate_dbus_exporter}; use dbus_macros::{dbus_method, dbus_proxy_obj, generate_dbus_exporter}; use dbus_projection::{dbus_generated, DisconnectWatcher}; use crate::dbus_arg::{DBusArg, DBusArgError, RefArgToRust}; #[dbus_propmap(BatteryProvider)] pub struct BatteryProviderDBus { source_info: String, remote_address: String, } use crate::dbus_arg::DBusArg; struct IBatteryProviderCallbackDBus {} Loading @@ -36,19 +27,18 @@ impl IBatteryProviderManager for IBatteryProviderManagerDBus { #[dbus_method("RegisterBatteryProvider")] fn register_battery_provider( &mut self, battery_provider: BatteryProvider, battery_provider_callback: Box<dyn IBatteryProviderCallback + Send>, ) -> i32 { ) -> u32 { dbus_generated!() } #[dbus_method("UnregisterBatteryProvider")] fn unregister_battery_provider(&mut self, battery_id: i32) { fn unregister_battery_provider(&mut self, battery_provider_id: u32) { dbus_generated!() } #[dbus_method("SetBatteryPercentage")] fn set_battery_percentage(&mut self, battery_id: i32, battery: Battery) { #[dbus_method("SetBatteryInfo")] fn set_battery_info(&mut self, battery_provider_id: u32, battery_set: BatterySet) { dbus_generated!() } } system/gd/rust/linux/service/src/main.rs +12 −5 Original line number Diff line number Diff line Loading @@ -114,11 +114,17 @@ fn main() -> Result<(), Box<dyn Error>> { Arc::new(Mutex::new(Box::new(BluetoothGatt::new(intf.clone(), tx.clone())))); let bluetooth_media = Arc::new(Mutex::new(Box::new(BluetoothMedia::new(tx.clone(), intf.clone())))); let battery_provider_manager = Arc::new(Mutex::new(Box::new(BatteryProviderManager::new()))); let battery_service = Arc::new(Mutex::new(Box::new(BatteryService::new(bluetooth_gatt.clone(), tx.clone())))); let battery_manager = Arc::new(Mutex::new(Box::new(BatteryManager::new(battery_service.clone(), tx.clone())))); let battery_provider_manager = Arc::new(Mutex::new(Box::new(BatteryProviderManager::new(tx.clone())))); let battery_service = Arc::new(Mutex::new(Box::new(BatteryService::new( bluetooth_gatt.clone(), battery_provider_manager.clone(), tx.clone(), )))); let battery_manager = Arc::new(Mutex::new(Box::new(BatteryManager::new( battery_provider_manager.clone(), tx.clone(), )))); let bluetooth = Arc::new(Mutex::new(Box::new(Bluetooth::new( tx.clone(), intf.clone(), Loading Loading @@ -170,6 +176,7 @@ fn main() -> Result<(), Box<dyn Error>> { bluetooth_gatt.clone(), battery_service.clone(), battery_manager.clone(), battery_provider_manager.clone(), bluetooth_media.clone(), suspend.clone(), bt_sock_mgr.clone(), Loading system/gd/rust/linux/stack/src/battery_manager.rs +75 −68 Original line number Diff line number Diff line use crate::battery_service::{ BatteryService, BatteryServiceStatus, IBatteryService, IBatteryServiceCallback, }; use crate::battery_provider_manager::BatteryProviderManager; use crate::callbacks::Callbacks; use crate::uuid; use crate::Message; use crate::RPCProxy; use std::collections::HashSet; use std::sync::{Arc, Mutex}; use tokio::sync::mpsc::Sender; /// The primary representation of battery information for internal /// passing and external calls. /// The primary representation of battery information for internal passing and external calls. #[derive(Debug, Clone)] pub struct BatterySet { /// Address of the remote device. pub address: String, /// UUID of where the battery info is decoded from as found in BT Spec. pub source_uuid: String, /// Information about the battery source, e.g. "BAS" or "HFP 1.8". pub source_info: String, /// Collection of batteries from this source. pub batteries: Vec<Battery>, } /// Describes an individual battery measurement, possibly one of many for a given device. #[derive(Debug, Clone)] pub struct Battery { /// Battery charge percentage between 0 and 100. For protocols that use 0-5 this will be that /// number multiplied by 20. pub percentage: u32, pub source_info: String, /// Description of this battery, such as Left, Right, or Case. Only present if the source has /// this level of detail. pub variant: String, } /// Helper representation of a collection of BatterySet to simplify passing around data internally. pub struct Batteries(Vec<BatterySet>); /// Callback for interacting with the BatteryManager. pub trait IBatteryManagerCallback: RPCProxy { /// Invoked whenever battery information associated with the given remote changes. fn on_battery_info_updated(&self, remote_address: String, battery: Battery); fn on_battery_info_updated(&self, remote_address: String, battery_set: BatterySet); } /// Central point for getting battery information that might be sourced from numerous systems. Loading @@ -35,69 +51,36 @@ pub trait IBatteryManager { /// Unregister a callback. fn unregister_battery_callback(&mut self, callback_id: u32); /// Enables notifications for a given callback. fn enable_notifications(&mut self, callback_id: u32, enable: bool); /// Returns battery information for the remote, sourced from the highest priority origin. fn get_battery_information(&self, remote_address: String) -> Option<Battery>; fn get_battery_information(&self, remote_address: String) -> Option<BatterySet>; } /// Repesentation of the BatteryManager. pub struct BatteryManager { bas: Arc<Mutex<Box<BatteryService>>>, battery_provider_manager: Arc<Mutex<Box<BatteryProviderManager>>>, callbacks: Callbacks<dyn IBatteryManagerCallback + Send>, /// List of callback IDs that have enabled notifications. notifications_enabled: HashSet<u32>, } impl BatteryManager { /// Construct a new BatteryManager with callbacks communicating on tx. pub fn new(bas: Arc<Mutex<Box<BatteryService>>>, tx: Sender<Message>) -> BatteryManager { pub fn new( battery_provider_manager: Arc<Mutex<Box<BatteryProviderManager>>>, tx: Sender<Message>, ) -> BatteryManager { let callbacks = Callbacks::new(tx.clone(), Message::BatteryManagerCallbackDisconnected); let notifications_enabled = HashSet::new(); Self { bas, callbacks, notifications_enabled } } /// Invoked after BAS has been initialized. pub fn init(&self) { self.bas.lock().unwrap().register_callback(Box::new(BasCallback::new())); Self { battery_provider_manager, callbacks } } /// Remove a callback due to disconnection or unregistration. pub fn remove_callback(&mut self, callback_id: u32) { self.callbacks.remove_callback(callback_id); } } struct BasCallback {} impl BasCallback { pub fn new() -> BasCallback { Self {} } } impl IBatteryServiceCallback for BasCallback { fn on_battery_service_status_updated( &self, _remote_address: String, _status: BatteryServiceStatus, ) { todo!() } fn on_battery_level_updated(&self, _remote_address: String, _battery_level: u32) { todo!() } fn on_battery_level_read(&self, _remote_address: String, _battery_level: u32) { todo!() } } impl RPCProxy for BasCallback { fn get_object_id(&self) -> String { "BAS Callback".to_string() /// Handles a BatterySet update. pub fn handle_battery_updated(&mut self, remote_address: String, battery_set: BatterySet) { self.callbacks.for_all_callbacks(|callback| { callback.on_battery_info_updated(remote_address.clone(), battery_set.clone()) }); } } Loading @@ -113,24 +96,48 @@ impl IBatteryManager for BatteryManager { self.remove_callback(callback_id); } fn enable_notifications(&mut self, callback_id: u32, enable: bool) { if self.callbacks.get_by_id(callback_id).is_none() { return; fn get_battery_information(&self, remote_address: String) -> Option<BatterySet> { self.battery_provider_manager.lock().unwrap().get_battery_info(remote_address) } } impl BatterySet { pub fn new(address: String, source_uuid: String, source_info: String) -> Self { Self { address, source_uuid, source_info, batteries: vec![] } } self.notifications_enabled.remove(&callback_id); if enable { self.notifications_enabled.insert(callback_id); pub fn add_or_update_battery(&mut self, new_battery: Battery) { match self.batteries.iter_mut().find(|battery| battery.variant == new_battery.variant) { Some(battery) => *battery = new_battery, None => self.batteries.push(new_battery), } } } impl Batteries { pub fn new() -> Self { Self(vec![]) } /// Updates a battery matching all non-battery-level fields if found, otherwise adds new_battery /// verbatim. pub fn add_or_update_battery_set(&mut self, new_battery_set: BatterySet) { match self .0 .iter_mut() .find(|battery_set| battery_set.source_uuid == new_battery_set.source_uuid) { Some(battery_set) => *battery_set = new_battery_set, None => self.0.push(new_battery_set), } } // TODO(b/233101174): update to use all available sources once // BatteryProviderManager is implemented. fn get_battery_information(&self, remote_address: String) -> Option<Battery> { let battery_level = self.bas.lock().unwrap().get_battery_level(remote_address)?; Some(Battery { percentage: battery_level, source_info: "BAS".to_string(), variant: "".to_string(), }) /// Returns the best BatterySet from among reported battery data. pub fn pick_best(&self) -> Option<BatterySet> { self.0 .iter() .find(|battery_set| battery_set.source_uuid == uuid::BAS) .or_else(|| self.0.first()) .cloned() } } system/gd/rust/linux/stack/src/battery_provider_manager.rs +65 −26 Original line number Diff line number Diff line use crate::battery_manager::Battery; #[derive(Debug, Clone)] pub struct BatteryProvider { pub source_info: String, pub remote_address: String, } use crate::battery_manager::{Batteries, BatterySet}; use crate::callbacks::Callbacks; use crate::{Message, RPCProxy}; use std::collections::HashMap; use tokio::sync::mpsc::Sender; /// Callback for BatteryProvider implementers. pub trait IBatteryProviderCallback { pub trait IBatteryProviderCallback: RPCProxy { /// Requests that the BatteryProvider send updated battery information. fn refresh_battery_info(&self); } /// Interface for managing BatteryProvider instances. pub trait IBatteryProviderManager { /// Registers a BatteryProvider and generates a unique batttery ID for future calls. /// Registers a BatteryProvider and generates a unique batttery provider ID for future calls. fn register_battery_provider( &mut self, battery_provider: BatteryProvider, battery_provider_callback: Box<dyn IBatteryProviderCallback + Send>, ) -> i32; ) -> u32; /// Unregisters a BatteryProvider, potentially removes battery information for the remote /// device if there are no other providers. fn unregister_battery_provider(&mut self, battery_id: i32); /// Unregisters a BatteryProvider, potentially removes battery information for the remote device /// if there are no other providers. fn unregister_battery_provider(&mut self, battery_provider_id: u32); /// Updates the battery information for the battery associated with battery_id. fn set_battery_percentage(&mut self, battery_id: i32, battery: Battery); fn set_battery_info(&mut self, battery_provider_id: u32, battery_set: BatterySet); } pub struct BatteryProviderManager {} /// Represents the BatteryProviderManager, a central point for collecting battery information from /// numerous sources. pub struct BatteryProviderManager { /// Sender for callback communication with the main thread. tx: Sender<Message>, battery_provider_callbacks: Callbacks<dyn IBatteryProviderCallback + Send>, /// Stored information merged from all battery providers. battery_info: HashMap<String, Batteries>, } impl BatteryProviderManager { pub fn new() -> BatteryProviderManager { BatteryProviderManager {} /// Constructs a new BatteryProviderManager with callbacks communicating on tx. pub fn new(tx: Sender<Message>) -> BatteryProviderManager { let battery_provider_callbacks = Callbacks::new(tx.clone(), Message::BatteryProviderManagerCallbackDisconnected); let battery_info = HashMap::new(); BatteryProviderManager { tx, battery_provider_callbacks, battery_info } } /// Request battery info refresh from all battery providers. pub fn refresh_battery_info(&self) { self.battery_provider_callbacks .for_all_callbacks(|callback| callback.refresh_battery_info()); } /// Get the best battery info available for a given device. pub fn get_battery_info(&self, remote_address: String) -> Option<BatterySet> { self.battery_info.get(&remote_address)?.pick_best() } /// Removes a battery provider callback. pub fn remove_battery_provider_callback(&mut self, battery_provider_id: u32) { self.battery_provider_callbacks.remove_callback(battery_provider_id); } } impl IBatteryProviderManager for BatteryProviderManager { fn register_battery_provider( &mut self, _battery_provider: BatteryProvider, _battery_provider_callback: Box<dyn IBatteryProviderCallback + Send>, ) -> i32 { todo!() battery_provider_callback: Box<dyn IBatteryProviderCallback + Send>, ) -> u32 { self.battery_provider_callbacks.add_callback(battery_provider_callback) } fn unregister_battery_provider(&mut self, _battery_id: i32) { todo!() fn unregister_battery_provider(&mut self, battery_provider_id: u32) { self.remove_battery_provider_callback(battery_provider_id); } fn set_battery_percentage(&mut self, _battery_id: i32, _battery: Battery) { todo!() fn set_battery_info(&mut self, _battery_provider_id: u32, battery_set: BatterySet) { let batteries = self .battery_info .entry(battery_set.address.clone()) .or_insert_with(|| Batteries::new()); batteries.add_or_update_battery_set(battery_set); if let Some(best_battery_set) = batteries.pick_best() { let tx = self.tx.clone(); tokio::spawn(async move { let _ = tx .send(Message::BatteryProviderManagerBatteryUpdated( best_battery_set.address.clone(), best_battery_set, )) .await; }); } } } Loading
system/gd/rust/linux/service/src/iface_battery_manager.rs +11 −9 Original line number Diff line number Diff line use btstack::battery_manager::{Battery, IBatteryManager, IBatteryManagerCallback}; use btstack::battery_manager::{Battery, BatterySet, IBatteryManager, IBatteryManagerCallback}; use btstack::RPCProxy; use dbus::arg::RefArg; use dbus::strings::Path; Loading @@ -7,10 +7,17 @@ use dbus_projection::{dbus_generated, DisconnectWatcher}; use crate::dbus_arg::{DBusArg, DBusArgError, RefArgToRust}; #[dbus_propmap(BatterySet)] pub struct BatterySetDBus { address: String, source_uuid: String, source_info: String, batteries: Vec<Battery>, } #[dbus_propmap(Battery)] pub struct BatteryDBus { percentage: u32, source_info: String, variant: String, } Loading @@ -19,7 +26,7 @@ struct IBatteryManagerCallbackDBus {} #[dbus_proxy_obj(BatteryManagerCallback, "org.chromium.bluetooth.BatteryManagerCallback")] impl IBatteryManagerCallback for IBatteryManagerCallbackDBus { #[dbus_method("OnBatteryInfoUpdated")] fn on_battery_info_updated(&self, remote_address: String, battery: Battery) { fn on_battery_info_updated(&self, remote_address: String, battery_set: BatterySet) { dbus_generated!() } } Loading @@ -41,13 +48,8 @@ impl IBatteryManager for IBatteryManagerDBus { dbus_generated!() } #[dbus_method("EnableNotifications")] fn enable_notifications(&mut self, callback_id: u32, enable: bool) { dbus_generated!() } #[dbus_method("GetBatteryInformation")] fn get_battery_information(&self, remote_address: String) -> Option<Battery> { fn get_battery_information(&self, remote_address: String) -> Option<BatterySet> { dbus_generated!() } }
system/gd/rust/linux/service/src/iface_battery_provider_manager.rs +8 −18 Original line number Diff line number Diff line use btstack::battery_manager::Battery; use btstack::battery_provider_manager::{ BatteryProvider, IBatteryProviderCallback, IBatteryProviderManager, }; use btstack::battery_manager::BatterySet; use btstack::battery_provider_manager::{IBatteryProviderCallback, IBatteryProviderManager}; use btstack::RPCProxy; use dbus::arg::RefArg; use dbus::strings::Path; use dbus_macros::{dbus_method, dbus_propmap, dbus_proxy_obj, generate_dbus_exporter}; use dbus_macros::{dbus_method, dbus_proxy_obj, generate_dbus_exporter}; use dbus_projection::{dbus_generated, DisconnectWatcher}; use crate::dbus_arg::{DBusArg, DBusArgError, RefArgToRust}; #[dbus_propmap(BatteryProvider)] pub struct BatteryProviderDBus { source_info: String, remote_address: String, } use crate::dbus_arg::DBusArg; struct IBatteryProviderCallbackDBus {} Loading @@ -36,19 +27,18 @@ impl IBatteryProviderManager for IBatteryProviderManagerDBus { #[dbus_method("RegisterBatteryProvider")] fn register_battery_provider( &mut self, battery_provider: BatteryProvider, battery_provider_callback: Box<dyn IBatteryProviderCallback + Send>, ) -> i32 { ) -> u32 { dbus_generated!() } #[dbus_method("UnregisterBatteryProvider")] fn unregister_battery_provider(&mut self, battery_id: i32) { fn unregister_battery_provider(&mut self, battery_provider_id: u32) { dbus_generated!() } #[dbus_method("SetBatteryPercentage")] fn set_battery_percentage(&mut self, battery_id: i32, battery: Battery) { #[dbus_method("SetBatteryInfo")] fn set_battery_info(&mut self, battery_provider_id: u32, battery_set: BatterySet) { dbus_generated!() } }
system/gd/rust/linux/service/src/main.rs +12 −5 Original line number Diff line number Diff line Loading @@ -114,11 +114,17 @@ fn main() -> Result<(), Box<dyn Error>> { Arc::new(Mutex::new(Box::new(BluetoothGatt::new(intf.clone(), tx.clone())))); let bluetooth_media = Arc::new(Mutex::new(Box::new(BluetoothMedia::new(tx.clone(), intf.clone())))); let battery_provider_manager = Arc::new(Mutex::new(Box::new(BatteryProviderManager::new()))); let battery_service = Arc::new(Mutex::new(Box::new(BatteryService::new(bluetooth_gatt.clone(), tx.clone())))); let battery_manager = Arc::new(Mutex::new(Box::new(BatteryManager::new(battery_service.clone(), tx.clone())))); let battery_provider_manager = Arc::new(Mutex::new(Box::new(BatteryProviderManager::new(tx.clone())))); let battery_service = Arc::new(Mutex::new(Box::new(BatteryService::new( bluetooth_gatt.clone(), battery_provider_manager.clone(), tx.clone(), )))); let battery_manager = Arc::new(Mutex::new(Box::new(BatteryManager::new( battery_provider_manager.clone(), tx.clone(), )))); let bluetooth = Arc::new(Mutex::new(Box::new(Bluetooth::new( tx.clone(), intf.clone(), Loading Loading @@ -170,6 +176,7 @@ fn main() -> Result<(), Box<dyn Error>> { bluetooth_gatt.clone(), battery_service.clone(), battery_manager.clone(), battery_provider_manager.clone(), bluetooth_media.clone(), suspend.clone(), bt_sock_mgr.clone(), Loading
system/gd/rust/linux/stack/src/battery_manager.rs +75 −68 Original line number Diff line number Diff line use crate::battery_service::{ BatteryService, BatteryServiceStatus, IBatteryService, IBatteryServiceCallback, }; use crate::battery_provider_manager::BatteryProviderManager; use crate::callbacks::Callbacks; use crate::uuid; use crate::Message; use crate::RPCProxy; use std::collections::HashSet; use std::sync::{Arc, Mutex}; use tokio::sync::mpsc::Sender; /// The primary representation of battery information for internal /// passing and external calls. /// The primary representation of battery information for internal passing and external calls. #[derive(Debug, Clone)] pub struct BatterySet { /// Address of the remote device. pub address: String, /// UUID of where the battery info is decoded from as found in BT Spec. pub source_uuid: String, /// Information about the battery source, e.g. "BAS" or "HFP 1.8". pub source_info: String, /// Collection of batteries from this source. pub batteries: Vec<Battery>, } /// Describes an individual battery measurement, possibly one of many for a given device. #[derive(Debug, Clone)] pub struct Battery { /// Battery charge percentage between 0 and 100. For protocols that use 0-5 this will be that /// number multiplied by 20. pub percentage: u32, pub source_info: String, /// Description of this battery, such as Left, Right, or Case. Only present if the source has /// this level of detail. pub variant: String, } /// Helper representation of a collection of BatterySet to simplify passing around data internally. pub struct Batteries(Vec<BatterySet>); /// Callback for interacting with the BatteryManager. pub trait IBatteryManagerCallback: RPCProxy { /// Invoked whenever battery information associated with the given remote changes. fn on_battery_info_updated(&self, remote_address: String, battery: Battery); fn on_battery_info_updated(&self, remote_address: String, battery_set: BatterySet); } /// Central point for getting battery information that might be sourced from numerous systems. Loading @@ -35,69 +51,36 @@ pub trait IBatteryManager { /// Unregister a callback. fn unregister_battery_callback(&mut self, callback_id: u32); /// Enables notifications for a given callback. fn enable_notifications(&mut self, callback_id: u32, enable: bool); /// Returns battery information for the remote, sourced from the highest priority origin. fn get_battery_information(&self, remote_address: String) -> Option<Battery>; fn get_battery_information(&self, remote_address: String) -> Option<BatterySet>; } /// Repesentation of the BatteryManager. pub struct BatteryManager { bas: Arc<Mutex<Box<BatteryService>>>, battery_provider_manager: Arc<Mutex<Box<BatteryProviderManager>>>, callbacks: Callbacks<dyn IBatteryManagerCallback + Send>, /// List of callback IDs that have enabled notifications. notifications_enabled: HashSet<u32>, } impl BatteryManager { /// Construct a new BatteryManager with callbacks communicating on tx. pub fn new(bas: Arc<Mutex<Box<BatteryService>>>, tx: Sender<Message>) -> BatteryManager { pub fn new( battery_provider_manager: Arc<Mutex<Box<BatteryProviderManager>>>, tx: Sender<Message>, ) -> BatteryManager { let callbacks = Callbacks::new(tx.clone(), Message::BatteryManagerCallbackDisconnected); let notifications_enabled = HashSet::new(); Self { bas, callbacks, notifications_enabled } } /// Invoked after BAS has been initialized. pub fn init(&self) { self.bas.lock().unwrap().register_callback(Box::new(BasCallback::new())); Self { battery_provider_manager, callbacks } } /// Remove a callback due to disconnection or unregistration. pub fn remove_callback(&mut self, callback_id: u32) { self.callbacks.remove_callback(callback_id); } } struct BasCallback {} impl BasCallback { pub fn new() -> BasCallback { Self {} } } impl IBatteryServiceCallback for BasCallback { fn on_battery_service_status_updated( &self, _remote_address: String, _status: BatteryServiceStatus, ) { todo!() } fn on_battery_level_updated(&self, _remote_address: String, _battery_level: u32) { todo!() } fn on_battery_level_read(&self, _remote_address: String, _battery_level: u32) { todo!() } } impl RPCProxy for BasCallback { fn get_object_id(&self) -> String { "BAS Callback".to_string() /// Handles a BatterySet update. pub fn handle_battery_updated(&mut self, remote_address: String, battery_set: BatterySet) { self.callbacks.for_all_callbacks(|callback| { callback.on_battery_info_updated(remote_address.clone(), battery_set.clone()) }); } } Loading @@ -113,24 +96,48 @@ impl IBatteryManager for BatteryManager { self.remove_callback(callback_id); } fn enable_notifications(&mut self, callback_id: u32, enable: bool) { if self.callbacks.get_by_id(callback_id).is_none() { return; fn get_battery_information(&self, remote_address: String) -> Option<BatterySet> { self.battery_provider_manager.lock().unwrap().get_battery_info(remote_address) } } impl BatterySet { pub fn new(address: String, source_uuid: String, source_info: String) -> Self { Self { address, source_uuid, source_info, batteries: vec![] } } self.notifications_enabled.remove(&callback_id); if enable { self.notifications_enabled.insert(callback_id); pub fn add_or_update_battery(&mut self, new_battery: Battery) { match self.batteries.iter_mut().find(|battery| battery.variant == new_battery.variant) { Some(battery) => *battery = new_battery, None => self.batteries.push(new_battery), } } } impl Batteries { pub fn new() -> Self { Self(vec![]) } /// Updates a battery matching all non-battery-level fields if found, otherwise adds new_battery /// verbatim. pub fn add_or_update_battery_set(&mut self, new_battery_set: BatterySet) { match self .0 .iter_mut() .find(|battery_set| battery_set.source_uuid == new_battery_set.source_uuid) { Some(battery_set) => *battery_set = new_battery_set, None => self.0.push(new_battery_set), } } // TODO(b/233101174): update to use all available sources once // BatteryProviderManager is implemented. fn get_battery_information(&self, remote_address: String) -> Option<Battery> { let battery_level = self.bas.lock().unwrap().get_battery_level(remote_address)?; Some(Battery { percentage: battery_level, source_info: "BAS".to_string(), variant: "".to_string(), }) /// Returns the best BatterySet from among reported battery data. pub fn pick_best(&self) -> Option<BatterySet> { self.0 .iter() .find(|battery_set| battery_set.source_uuid == uuid::BAS) .or_else(|| self.0.first()) .cloned() } }
system/gd/rust/linux/stack/src/battery_provider_manager.rs +65 −26 Original line number Diff line number Diff line use crate::battery_manager::Battery; #[derive(Debug, Clone)] pub struct BatteryProvider { pub source_info: String, pub remote_address: String, } use crate::battery_manager::{Batteries, BatterySet}; use crate::callbacks::Callbacks; use crate::{Message, RPCProxy}; use std::collections::HashMap; use tokio::sync::mpsc::Sender; /// Callback for BatteryProvider implementers. pub trait IBatteryProviderCallback { pub trait IBatteryProviderCallback: RPCProxy { /// Requests that the BatteryProvider send updated battery information. fn refresh_battery_info(&self); } /// Interface for managing BatteryProvider instances. pub trait IBatteryProviderManager { /// Registers a BatteryProvider and generates a unique batttery ID for future calls. /// Registers a BatteryProvider and generates a unique batttery provider ID for future calls. fn register_battery_provider( &mut self, battery_provider: BatteryProvider, battery_provider_callback: Box<dyn IBatteryProviderCallback + Send>, ) -> i32; ) -> u32; /// Unregisters a BatteryProvider, potentially removes battery information for the remote /// device if there are no other providers. fn unregister_battery_provider(&mut self, battery_id: i32); /// Unregisters a BatteryProvider, potentially removes battery information for the remote device /// if there are no other providers. fn unregister_battery_provider(&mut self, battery_provider_id: u32); /// Updates the battery information for the battery associated with battery_id. fn set_battery_percentage(&mut self, battery_id: i32, battery: Battery); fn set_battery_info(&mut self, battery_provider_id: u32, battery_set: BatterySet); } pub struct BatteryProviderManager {} /// Represents the BatteryProviderManager, a central point for collecting battery information from /// numerous sources. pub struct BatteryProviderManager { /// Sender for callback communication with the main thread. tx: Sender<Message>, battery_provider_callbacks: Callbacks<dyn IBatteryProviderCallback + Send>, /// Stored information merged from all battery providers. battery_info: HashMap<String, Batteries>, } impl BatteryProviderManager { pub fn new() -> BatteryProviderManager { BatteryProviderManager {} /// Constructs a new BatteryProviderManager with callbacks communicating on tx. pub fn new(tx: Sender<Message>) -> BatteryProviderManager { let battery_provider_callbacks = Callbacks::new(tx.clone(), Message::BatteryProviderManagerCallbackDisconnected); let battery_info = HashMap::new(); BatteryProviderManager { tx, battery_provider_callbacks, battery_info } } /// Request battery info refresh from all battery providers. pub fn refresh_battery_info(&self) { self.battery_provider_callbacks .for_all_callbacks(|callback| callback.refresh_battery_info()); } /// Get the best battery info available for a given device. pub fn get_battery_info(&self, remote_address: String) -> Option<BatterySet> { self.battery_info.get(&remote_address)?.pick_best() } /// Removes a battery provider callback. pub fn remove_battery_provider_callback(&mut self, battery_provider_id: u32) { self.battery_provider_callbacks.remove_callback(battery_provider_id); } } impl IBatteryProviderManager for BatteryProviderManager { fn register_battery_provider( &mut self, _battery_provider: BatteryProvider, _battery_provider_callback: Box<dyn IBatteryProviderCallback + Send>, ) -> i32 { todo!() battery_provider_callback: Box<dyn IBatteryProviderCallback + Send>, ) -> u32 { self.battery_provider_callbacks.add_callback(battery_provider_callback) } fn unregister_battery_provider(&mut self, _battery_id: i32) { todo!() fn unregister_battery_provider(&mut self, battery_provider_id: u32) { self.remove_battery_provider_callback(battery_provider_id); } fn set_battery_percentage(&mut self, _battery_id: i32, _battery: Battery) { todo!() fn set_battery_info(&mut self, _battery_provider_id: u32, battery_set: BatterySet) { let batteries = self .battery_info .entry(battery_set.address.clone()) .or_insert_with(|| Batteries::new()); batteries.add_or_update_battery_set(battery_set); if let Some(best_battery_set) = batteries.pick_best() { let tx = self.tx.clone(); tokio::spawn(async move { let _ = tx .send(Message::BatteryProviderManagerBatteryUpdated( best_battery_set.address.clone(), best_battery_set, )) .await; }); } } }