• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 use crate::battery_provider_manager::BatteryProviderManager;
2 use crate::callbacks::Callbacks;
3 use crate::uuid;
4 use crate::Message;
5 use crate::RPCProxy;
6 use bt_topshim::btif::RawAddress;
7 use itertools::Itertools;
8 use std::sync::{Arc, Mutex};
9 use tokio::sync::mpsc::Sender;
10 
11 /// The primary representation of battery information for internal passing and external calls.
12 #[derive(Debug, Clone)]
13 pub struct BatterySet {
14     /// Address of the remote device.
15     pub address: RawAddress,
16     /// UUID of where the battery info is decoded from as found in BT Spec.
17     pub source_uuid: String,
18     /// Information about the battery source, e.g. "BAS" or "HFP 1.8".
19     pub source_info: String,
20     /// Collection of batteries from this source.
21     pub batteries: Vec<Battery>,
22 }
23 
24 /// Describes an individual battery measurement, possibly one of many for a given device.
25 #[derive(Debug, Clone)]
26 pub struct Battery {
27     /// Battery charge percentage between 0 and 100. For protocols that use 0-5 this will be that
28     /// number multiplied by 20.
29     pub percentage: u32,
30     /// Description of this battery, such as Left, Right, or Case. Only present if the source has
31     /// this level of detail.
32     pub variant: String,
33 }
34 
35 /// Helper representation of a collection of BatterySet to simplify passing around data internally.
36 #[derive(Default)]
37 pub struct Batteries(Vec<BatterySet>);
38 
39 /// Callback for interacting with the BatteryManager.
40 pub trait IBatteryManagerCallback: RPCProxy {
41     /// Invoked whenever battery information associated with the given remote changes.
on_battery_info_updated(&mut self, remote_address: RawAddress, battery_set: BatterySet)42     fn on_battery_info_updated(&mut self, remote_address: RawAddress, battery_set: BatterySet);
43 }
44 
45 /// Central point for getting battery information that might be sourced from numerous systems.
46 pub trait IBatteryManager {
47     /// Registers a callback for interfacing with the BatteryManager and returns a unique
48     /// callback_id for future calls.
register_battery_callback( &mut self, battery_manager_callback: Box<dyn IBatteryManagerCallback + Send>, ) -> u3249     fn register_battery_callback(
50         &mut self,
51         battery_manager_callback: Box<dyn IBatteryManagerCallback + Send>,
52     ) -> u32;
53 
54     /// Unregister a callback.
unregister_battery_callback(&mut self, callback_id: u32) -> bool55     fn unregister_battery_callback(&mut self, callback_id: u32) -> bool;
56 
57     /// Returns battery information for the remote, sourced from the highest priority origin.
get_battery_information(&self, remote_address: RawAddress) -> Option<BatterySet>58     fn get_battery_information(&self, remote_address: RawAddress) -> Option<BatterySet>;
59 }
60 
61 /// Repesentation of the BatteryManager.
62 pub struct BatteryManager {
63     battery_provider_manager: Arc<Mutex<Box<BatteryProviderManager>>>,
64     callbacks: Callbacks<dyn IBatteryManagerCallback + Send>,
65 }
66 
67 impl BatteryManager {
68     /// Construct a new BatteryManager with callbacks communicating on tx.
new( battery_provider_manager: Arc<Mutex<Box<BatteryProviderManager>>>, tx: Sender<Message>, ) -> BatteryManager69     pub fn new(
70         battery_provider_manager: Arc<Mutex<Box<BatteryProviderManager>>>,
71         tx: Sender<Message>,
72     ) -> BatteryManager {
73         let callbacks = Callbacks::new(tx.clone(), Message::BatteryManagerCallbackDisconnected);
74         Self { battery_provider_manager, callbacks }
75     }
76 
77     /// Remove a callback due to disconnection or unregistration.
remove_callback(&mut self, callback_id: u32) -> bool78     pub fn remove_callback(&mut self, callback_id: u32) -> bool {
79         self.callbacks.remove_callback(callback_id)
80     }
81 
82     /// Handles a BatterySet update.
handle_battery_updated(&mut self, remote_address: RawAddress, battery_set: BatterySet)83     pub fn handle_battery_updated(&mut self, remote_address: RawAddress, battery_set: BatterySet) {
84         self.callbacks.for_all_callbacks(|callback| {
85             callback.on_battery_info_updated(remote_address, battery_set.clone())
86         });
87     }
88 }
89 
90 impl IBatteryManager for BatteryManager {
register_battery_callback( &mut self, battery_manager_callback: Box<dyn IBatteryManagerCallback + Send>, ) -> u3291     fn register_battery_callback(
92         &mut self,
93         battery_manager_callback: Box<dyn IBatteryManagerCallback + Send>,
94     ) -> u32 {
95         self.callbacks.add_callback(battery_manager_callback)
96     }
97 
unregister_battery_callback(&mut self, callback_id: u32) -> bool98     fn unregister_battery_callback(&mut self, callback_id: u32) -> bool {
99         self.remove_callback(callback_id)
100     }
101 
get_battery_information(&self, remote_address: RawAddress) -> Option<BatterySet>102     fn get_battery_information(&self, remote_address: RawAddress) -> Option<BatterySet> {
103         self.battery_provider_manager.lock().unwrap().get_battery_info(remote_address)
104     }
105 }
106 
107 impl BatterySet {
new( address: RawAddress, source_uuid: String, source_info: String, batteries: Vec<Battery>, ) -> Self108     pub fn new(
109         address: RawAddress,
110         source_uuid: String,
111         source_info: String,
112         batteries: Vec<Battery>,
113     ) -> Self {
114         Self { address, source_uuid, source_info, batteries }
115     }
116 
add_or_update_battery(&mut self, new_battery: Battery)117     pub fn add_or_update_battery(&mut self, new_battery: Battery) {
118         match self.batteries.iter_mut().find(|battery| battery.variant == new_battery.variant) {
119             Some(battery) => *battery = new_battery,
120             None => self.batteries.push(new_battery),
121         }
122     }
123 }
124 
125 impl Batteries {
new() -> Self126     pub fn new() -> Self {
127         Default::default()
128     }
129 
130     /// Updates a battery matching all non-battery-level fields if found, otherwise adds new_battery
131     /// verbatim.
add_or_update_battery_set(&mut self, new_battery_set: BatterySet)132     pub fn add_or_update_battery_set(&mut self, new_battery_set: BatterySet) {
133         match self
134             .0
135             .iter_mut()
136             .find(|battery_set| battery_set.source_uuid == new_battery_set.source_uuid)
137         {
138             Some(battery_set) => *battery_set = new_battery_set,
139             None => self.0.push(new_battery_set),
140         }
141     }
142 
remove_battery_set(&mut self, uuid: &String)143     pub fn remove_battery_set(&mut self, uuid: &String) {
144         self.0.retain(|battery_set| &battery_set.source_uuid != uuid);
145     }
146 
is_empty(&self) -> bool147     pub fn is_empty(&self) -> bool {
148         self.0.is_empty()
149     }
150 
151     /// Returns the best BatterySet from among reported battery data.
pick_best(&self) -> Option<BatterySet>152     pub fn pick_best(&self) -> Option<BatterySet> {
153         self.0
154             .iter()
155             .filter(|battery_set| !battery_set.batteries.is_empty())
156             // Now we prefer BAS, but we might need to prioritize other sources first
157             // TODO (b/295577710): Make a preference list
158             .find_or_first(|battery_set| battery_set.source_uuid == uuid::BAS)
159             .or_else(|| self.0.first())
160             .cloned()
161     }
162 }
163