1 //! Anything related to the adapter API (IBluetooth).
2 
3 use bt_topshim::btif::ffi;
4 use bt_topshim::btif::{BluetoothCallbacks, BluetoothInterface, BtState};
5 use bt_topshim::topstack;
6 
7 use btif_macros::btif_callbacks_generator;
8 use btif_macros::stack_message;
9 
10 use num_traits::cast::ToPrimitive;
11 use num_traits::FromPrimitive;
12 
13 use std::fmt::Debug;
14 use std::sync::Arc;
15 use std::sync::Mutex;
16 
17 use tokio::sync::mpsc::Sender;
18 
19 use crate::{BDAddr, Message, RPCProxy};
20 
21 /// Defines the adapter API.
22 pub trait IBluetooth {
23     /// Adds a callback from a client who wishes to observe adapter events.
register_callback(&mut self, callback: Box<dyn IBluetoothCallback + Send>)24     fn register_callback(&mut self, callback: Box<dyn IBluetoothCallback + Send>);
25 
26     /// Enables the adapter.
27     ///
28     /// Returns true if the request is accepted.
enable(&mut self) -> bool29     fn enable(&mut self) -> bool;
30 
31     /// Disables the adapter.
32     ///
33     /// Returns true if the request is accepted.
disable(&mut self) -> bool34     fn disable(&mut self) -> bool;
35 
36     /// Returns the Bluetooth address of the local adapter.
get_address(&self) -> String37     fn get_address(&self) -> String;
38 }
39 
40 /// The interface for adapter callbacks registered through `IBluetooth::register_callback`.
41 pub trait IBluetoothCallback: RPCProxy {
42     /// When any of the adapter states is changed.
on_bluetooth_state_changed(&self, prev_state: u32, new_state: u32)43     fn on_bluetooth_state_changed(&self, prev_state: u32, new_state: u32);
44 
45     /// When any of the adapter local address is changed.
on_bluetooth_address_changed(&self, addr: String)46     fn on_bluetooth_address_changed(&self, addr: String);
47 }
48 
49 /// Implementation of the adapter API.
50 pub struct Bluetooth {
51     intf: Arc<Mutex<BluetoothInterface>>,
52     state: BtState,
53     callbacks: Vec<(u32, Box<dyn IBluetoothCallback + Send>)>,
54     callbacks_last_id: u32,
55     tx: Sender<Message>,
56     local_address: Option<BDAddr>,
57 }
58 
59 impl Bluetooth {
60     /// Constructs the IBluetooth implementation.
new(tx: Sender<Message>, intf: Arc<Mutex<BluetoothInterface>>) -> Bluetooth61     pub fn new(tx: Sender<Message>, intf: Arc<Mutex<BluetoothInterface>>) -> Bluetooth {
62         Bluetooth {
63             tx,
64             intf,
65             state: BtState::Off,
66             callbacks: vec![],
67             callbacks_last_id: 0,
68             local_address: None,
69         }
70     }
71 
update_local_address(&mut self, raw: &Vec<u8>)72     fn update_local_address(&mut self, raw: &Vec<u8>) {
73         self.local_address = Some(BDAddr::from_byte_vec(raw));
74 
75         for callback in &self.callbacks {
76             callback.1.on_bluetooth_address_changed(self.local_address.unwrap().to_string());
77         }
78     }
79 
callback_disconnected(&mut self, id: u32)80     pub(crate) fn callback_disconnected(&mut self, id: u32) {
81         self.callbacks.retain(|x| x.0 != id);
82     }
83 }
84 
85 #[btif_callbacks_generator(btif_bluetooth_callbacks, BluetoothCallbacks)]
86 pub(crate) trait BtifBluetoothCallbacks {
87     #[stack_message(BluetoothAdapterStateChanged)]
adapter_state_changed(&mut self, state: BtState)88     fn adapter_state_changed(&mut self, state: BtState);
89 
90     #[stack_message(BluetoothAdapterPropertiesChanged)]
adapter_properties_changed( &mut self, status: i32, num_properties: i32, properties: Vec<ffi::BtProperty>, )91     fn adapter_properties_changed(
92         &mut self,
93         status: i32,
94         num_properties: i32,
95         properties: Vec<ffi::BtProperty>,
96     );
97 }
98 
99 #[derive(FromPrimitive, ToPrimitive, PartialEq, PartialOrd)]
100 #[repr(i32)]
101 #[derive(Debug)]
102 enum PropertyType {
103     BDName = 0x01,
104     BDAddr,
105     Uuids,
106     ClassOfDevice,
107     TypeOfDevice,
108     ServiceRecord,
109     AdapterScanMode,
110     AdapterBondedDevices,
111     AdapterDiscoverableTimeout,
112     RemoteFriendlyName,
113     RemoteRssi,
114     RemoteVersionInfo,
115     RemoteLocalLeFeatures,
116     RemoteDynamicAudioBuffer = 0x10,
117     Unknown = 0x100,
118 }
119 
120 impl BtifBluetoothCallbacks for Bluetooth {
adapter_state_changed(&mut self, state: BtState)121     fn adapter_state_changed(&mut self, state: BtState) {
122         for callback in &self.callbacks {
123             callback
124                 .1
125                 .on_bluetooth_state_changed(self.state.to_u32().unwrap(), state.to_u32().unwrap());
126         }
127 
128         self.state = state;
129     }
130 
131     #[allow(unused_variables)]
adapter_properties_changed( &mut self, status: i32, num_properties: i32, properties: Vec<ffi::BtProperty>, )132     fn adapter_properties_changed(
133         &mut self,
134         status: i32,
135         num_properties: i32,
136         properties: Vec<ffi::BtProperty>,
137     ) {
138         if status != 0 {
139             return;
140         }
141 
142         for prop in properties {
143             let prop_type = PropertyType::from_i32(prop.prop_type);
144 
145             if prop_type.is_none() {
146                 continue;
147             }
148 
149             match prop_type.unwrap() {
150                 PropertyType::BDAddr => {
151                     self.update_local_address(&prop.val);
152                 }
153                 _ => {}
154             }
155         }
156     }
157 }
158 
159 // TODO: Add unit tests for this implementation
160 impl IBluetooth for Bluetooth {
register_callback(&mut self, mut callback: Box<dyn IBluetoothCallback + Send>)161     fn register_callback(&mut self, mut callback: Box<dyn IBluetoothCallback + Send>) {
162         let tx = self.tx.clone();
163 
164         // TODO: Refactor into a separate wrap-around id generator.
165         self.callbacks_last_id += 1;
166         let id = self.callbacks_last_id;
167 
168         callback.register_disconnect(Box::new(move || {
169             let tx = tx.clone();
170             topstack::get_runtime().spawn(async move {
171                 let _result = tx.send(Message::BluetoothCallbackDisconnected(id)).await;
172             });
173         }));
174 
175         self.callbacks.push((id, callback))
176     }
177 
enable(&mut self) -> bool178     fn enable(&mut self) -> bool {
179         self.intf.lock().unwrap().enable() == 0
180     }
181 
disable(&mut self) -> bool182     fn disable(&mut self) -> bool {
183         self.intf.lock().unwrap().disable() == 0
184     }
185 
get_address(&self) -> String186     fn get_address(&self) -> String {
187         match self.local_address {
188             None => String::from(""),
189             Some(addr) => addr.to_string(),
190         }
191     }
192 }
193