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