1 use log::{error, info, warn}; 2 3 use std::collections::HashMap; 4 use std::process::Command; 5 6 use crate::iface_bluetooth_experimental::IBluetoothExperimental; 7 use crate::iface_bluetooth_manager::{ 8 AdapterWithEnabled, IBluetoothManager, IBluetoothManagerCallback, 9 }; 10 use crate::state_machine::{ 11 state_to_enabled, AdapterState, Message, StateMachineProxy, VirtualHciIndex, 12 }; 13 use crate::{config_util, migrate}; 14 15 const BLUEZ_INIT_TARGET: &str = "bluetoothd"; 16 17 /// Implementation of IBluetoothManager. 18 pub struct BluetoothManager { 19 proxy: StateMachineProxy, 20 callbacks: HashMap<u32, Box<dyn IBluetoothManagerCallback + Send>>, 21 } 22 23 impl BluetoothManager { new(proxy: StateMachineProxy) -> BluetoothManager24 pub fn new(proxy: StateMachineProxy) -> BluetoothManager { 25 BluetoothManager { proxy, callbacks: HashMap::new() } 26 } 27 is_adapter_enabled(&self, hci_device: VirtualHciIndex) -> bool28 fn is_adapter_enabled(&self, hci_device: VirtualHciIndex) -> bool { 29 state_to_enabled(self.proxy.get_process_state(hci_device)) 30 } 31 is_adapter_present(&self, hci_device: VirtualHciIndex) -> bool32 fn is_adapter_present(&self, hci_device: VirtualHciIndex) -> bool { 33 self.proxy.get_state(hci_device, move |a| Some(a.present)).unwrap_or(false) 34 } 35 callback_hci_device_change(&mut self, hci_device: i32, present: bool)36 pub(crate) fn callback_hci_device_change(&mut self, hci_device: i32, present: bool) { 37 for (_, callback) in &mut self.callbacks { 38 callback.on_hci_device_changed(hci_device, present); 39 } 40 } 41 callback_hci_enabled_change(&mut self, hci_device: i32, enabled: bool)42 pub(crate) fn callback_hci_enabled_change(&mut self, hci_device: i32, enabled: bool) { 43 if enabled { 44 info!("Started {}", hci_device); 45 } else { 46 info!("Stopped {}", hci_device); 47 } 48 49 for (_, callback) in &mut self.callbacks { 50 callback.on_hci_enabled_changed(hci_device, enabled); 51 } 52 } 53 callback_default_adapter_change(&mut self, hci_device: i32)54 pub(crate) fn callback_default_adapter_change(&mut self, hci_device: i32) { 55 for (_, callback) in &mut self.callbacks { 56 callback.on_default_adapter_changed(hci_device); 57 } 58 } 59 callback_disconnected(&mut self, id: u32)60 pub(crate) fn callback_disconnected(&mut self, id: u32) { 61 self.callbacks.remove(&id); 62 } 63 } 64 65 impl IBluetoothManager for BluetoothManager { start(&mut self, hci_interface: i32)66 fn start(&mut self, hci_interface: i32) { 67 info!("Starting {}", hci_interface); 68 69 if !config_util::modify_hci_n_enabled(hci_interface, true) { 70 error!("Config is not successfully modified"); 71 } 72 73 let virt_hci = VirtualHciIndex(hci_interface); 74 75 // Store that this adapter is meant to be started in state machine. 76 self.proxy.modify_state(virt_hci, move |a: &mut AdapterState| a.config_enabled = true); 77 78 // Ignore the request if adapter is already enabled or not present. 79 if self.is_adapter_enabled(virt_hci) || !self.is_adapter_present(virt_hci) { 80 return; 81 } 82 83 self.proxy.start_bluetooth(virt_hci); 84 } 85 stop(&mut self, hci_interface: i32)86 fn stop(&mut self, hci_interface: i32) { 87 info!("Stopping {}", hci_interface); 88 if !config_util::modify_hci_n_enabled(hci_interface, false) { 89 error!("Config is not successfully modified"); 90 } 91 92 let virt_hci = VirtualHciIndex(hci_interface); 93 94 // Store that this adapter is meant to be stopped in state machine. 95 self.proxy.modify_state(virt_hci, move |a: &mut AdapterState| a.config_enabled = false); 96 97 // Ignore the request if adapter is already disabled. 98 if !self.is_adapter_enabled(virt_hci) { 99 return; 100 } 101 102 self.proxy.stop_bluetooth(virt_hci); 103 } 104 get_adapter_enabled(&mut self, hci_interface: i32) -> bool105 fn get_adapter_enabled(&mut self, hci_interface: i32) -> bool { 106 self.is_adapter_enabled(VirtualHciIndex(hci_interface)) 107 } 108 register_callback(&mut self, mut callback: Box<dyn IBluetoothManagerCallback + Send>)109 fn register_callback(&mut self, mut callback: Box<dyn IBluetoothManagerCallback + Send>) { 110 let tx = self.proxy.get_tx(); 111 112 let id = callback.register_disconnect(Box::new(move |cb_id| { 113 let tx = tx.clone(); 114 tokio::spawn(async move { 115 let _result = tx.send(Message::CallbackDisconnected(cb_id)).await; 116 }); 117 })); 118 119 self.callbacks.insert(id, callback); 120 } 121 get_floss_enabled(&mut self) -> bool122 fn get_floss_enabled(&mut self) -> bool { 123 self.proxy.get_floss_enabled() 124 } 125 set_floss_enabled(&mut self, enabled: bool)126 fn set_floss_enabled(&mut self, enabled: bool) { 127 let prev = self.proxy.set_floss_enabled(enabled); 128 config_util::write_floss_enabled(enabled); 129 130 if prev != enabled && enabled { 131 if let Err(e) = Command::new("initctl").args(&["stop", BLUEZ_INIT_TARGET]).output() { 132 warn!("Failed to stop bluetoothd: {}", e); 133 } 134 migrate::migrate_bluez_devices(); 135 for hci in config_util::list_hci_devices() { 136 if config_util::is_hci_n_enabled(hci) { 137 let _ = self.proxy.start_bluetooth(VirtualHciIndex(hci)); 138 } 139 } 140 } else if prev != enabled { 141 for hci in config_util::list_hci_devices() { 142 if config_util::is_hci_n_enabled(hci) { 143 let _ = self.proxy.stop_bluetooth(VirtualHciIndex(hci)); 144 } 145 } 146 migrate::migrate_floss_devices(); 147 if let Err(e) = Command::new("initctl").args(&["start", BLUEZ_INIT_TARGET]).output() { 148 warn!("Failed to start bluetoothd: {}", e); 149 } 150 } 151 } 152 get_available_adapters(&mut self) -> Vec<AdapterWithEnabled>153 fn get_available_adapters(&mut self) -> Vec<AdapterWithEnabled> { 154 self.proxy 155 .get_valid_adapters() 156 .iter() 157 .map(|a| AdapterWithEnabled { 158 hci_interface: a.virt_hci.to_i32(), 159 enabled: state_to_enabled(a.state), 160 }) 161 .collect::<Vec<AdapterWithEnabled>>() 162 } 163 get_default_adapter(&mut self) -> i32164 fn get_default_adapter(&mut self) -> i32 { 165 self.proxy.get_default_adapter().to_i32() 166 } 167 set_desired_default_adapter(&mut self, adapter_index: i32)168 fn set_desired_default_adapter(&mut self, adapter_index: i32) { 169 self.proxy.set_desired_default_adapter(VirtualHciIndex(adapter_index)); 170 } 171 } 172 173 /// Implementation of IBluetoothExperimental 174 impl IBluetoothExperimental for BluetoothManager { set_ll_privacy(&mut self, enabled: bool)175 fn set_ll_privacy(&mut self, enabled: bool) { 176 let current_status = match config_util::read_floss_ll_privacy_enabled() { 177 Ok(true) => true, 178 _ => false, 179 }; 180 181 if current_status == enabled { 182 return; 183 } 184 185 if let Err(e) = config_util::write_floss_ll_privacy_enabled(enabled) { 186 error!("Failed to write ll privacy status: {}", e); 187 return; 188 } 189 } 190 set_devcoredump(&mut self, enabled: bool) -> bool191 fn set_devcoredump(&mut self, enabled: bool) -> bool { 192 info!("Set floss devcoredump to {}", enabled); 193 config_util::write_coredump_state_to_file(enabled) 194 } 195 } 196