1 use crate::battery_manager::{Batteries, BatterySet};
2 use crate::callbacks::Callbacks;
3 use crate::{Message, RPCProxy};
4 use bt_topshim::btif::{DisplayAddress, RawAddress};
5 use log::debug;
6 use std::collections::HashMap;
7 use tokio::sync::mpsc::Sender;
8 
9 /// Callback for BatteryProvider implementers.
10 pub trait IBatteryProviderCallback: RPCProxy {
11     /// Requests that the BatteryProvider send updated battery information.
refresh_battery_info(&mut self)12     fn refresh_battery_info(&mut self);
13 }
14 
15 /// Interface for managing BatteryProvider instances.
16 pub trait IBatteryProviderManager {
17     /// Registers a BatteryProvider and generates a unique batttery provider ID for future calls.
register_battery_provider( &mut self, battery_provider_callback: Box<dyn IBatteryProviderCallback + Send>, ) -> u3218     fn register_battery_provider(
19         &mut self,
20         battery_provider_callback: Box<dyn IBatteryProviderCallback + Send>,
21     ) -> u32;
22 
23     /// Unregisters a BatteryProvider, potentially removes battery information for the remote device
24     /// if there are no other providers.
unregister_battery_provider(&mut self, battery_provider_id: u32)25     fn unregister_battery_provider(&mut self, battery_provider_id: u32);
26 
27     /// Updates the battery information for the battery associated with battery_id.
set_battery_info(&mut self, battery_provider_id: u32, battery_set: BatterySet)28     fn set_battery_info(&mut self, battery_provider_id: u32, battery_set: BatterySet);
29 
30     /// Removes the battery information for the battery associated with battery_id.
remove_battery_info(&mut self, battery_provider_id: u32, address: RawAddress, uuid: String)31     fn remove_battery_info(&mut self, battery_provider_id: u32, address: RawAddress, uuid: String);
32 }
33 
34 /// Represents the BatteryProviderManager, a central point for collecting battery information from
35 /// numerous sources.
36 pub struct BatteryProviderManager {
37     /// Sender for callback communication with the main thread.
38     tx: Sender<Message>,
39     battery_provider_callbacks: Callbacks<dyn IBatteryProviderCallback + Send>,
40     /// Stored information merged from all battery providers.
41     battery_info: HashMap<RawAddress, Batteries>,
42 }
43 
44 impl BatteryProviderManager {
45     /// Constructs a new BatteryProviderManager with callbacks communicating on tx.
new(tx: Sender<Message>) -> BatteryProviderManager46     pub fn new(tx: Sender<Message>) -> BatteryProviderManager {
47         let battery_provider_callbacks =
48             Callbacks::new(tx.clone(), Message::BatteryProviderManagerCallbackDisconnected);
49         let battery_info = HashMap::new();
50         BatteryProviderManager { tx, battery_provider_callbacks, battery_info }
51     }
52 
53     /// Request battery info refresh from all battery providers.
refresh_battery_info(&mut self)54     pub fn refresh_battery_info(&mut self) {
55         self.battery_provider_callbacks
56             .for_all_callbacks(|callback| callback.refresh_battery_info());
57     }
58 
59     /// Get the best battery info available for a given device.
get_battery_info(&self, remote_address: RawAddress) -> Option<BatterySet>60     pub fn get_battery_info(&self, remote_address: RawAddress) -> Option<BatterySet> {
61         self.battery_info.get(&remote_address)?.pick_best()
62     }
63 
64     /// Removes a battery provider callback.
remove_battery_provider_callback(&mut self, battery_provider_id: u32)65     pub fn remove_battery_provider_callback(&mut self, battery_provider_id: u32) {
66         self.battery_provider_callbacks.remove_callback(battery_provider_id);
67     }
68 }
69 
70 impl IBatteryProviderManager for BatteryProviderManager {
register_battery_provider( &mut self, battery_provider_callback: Box<dyn IBatteryProviderCallback + Send>, ) -> u3271     fn register_battery_provider(
72         &mut self,
73         battery_provider_callback: Box<dyn IBatteryProviderCallback + Send>,
74     ) -> u32 {
75         self.battery_provider_callbacks.add_callback(battery_provider_callback)
76     }
77 
unregister_battery_provider(&mut self, battery_provider_id: u32)78     fn unregister_battery_provider(&mut self, battery_provider_id: u32) {
79         self.remove_battery_provider_callback(battery_provider_id);
80     }
81 
remove_battery_info( &mut self, _battery_provider_id: u32, address: RawAddress, uuid: String, )82     fn remove_battery_info(
83         &mut self,
84         _battery_provider_id: u32,
85         address: RawAddress,
86         uuid: String,
87     ) {
88         if let Some(batteries) = self.battery_info.get_mut(&address) {
89             batteries.remove_battery_set(&uuid);
90 
91             if batteries.is_empty() {
92                 self.battery_info.remove(&address);
93             }
94         }
95     }
96 
set_battery_info(&mut self, _battery_provider_id: u32, battery_set: BatterySet)97     fn set_battery_info(&mut self, _battery_provider_id: u32, battery_set: BatterySet) {
98         debug!(
99             "BatteryProviderManager received BatterySet for [{}] from \"{}\": {:?}",
100             DisplayAddress(&battery_set.address),
101             battery_set.source_info.clone(),
102             battery_set.clone()
103         );
104 
105         if battery_set.batteries.is_empty() {
106             return;
107         }
108 
109         let batteries =
110             self.battery_info.entry(battery_set.address).or_insert_with(|| Batteries::new());
111         batteries.add_or_update_battery_set(battery_set);
112 
113         if let Some(best_battery_set) = batteries.pick_best() {
114             let tx = self.tx.clone();
115             tokio::spawn(async move {
116                 let _ = tx
117                     .send(Message::BatteryProviderManagerBatteryUpdated(
118                         best_battery_set.address,
119                         best_battery_set,
120                     ))
121                     .await;
122             });
123         }
124     }
125 }
126