diff --git a/system/gd/rust/linux/mgmt/src/bluetooth_manager.rs b/system/gd/rust/linux/mgmt/src/bluetooth_manager.rs index 535423a97b2c12bd9e4ce520790a2a7042645e1c..c534145ecf023e4a084f75132c95af868d747583 100644 --- a/system/gd/rust/linux/mgmt/src/bluetooth_manager.rs +++ b/system/gd/rust/linux/mgmt/src/bluetooth_manager.rs @@ -60,6 +60,14 @@ impl BluetoothManager { pub(crate) fn callback_disconnected(&mut self, id: u32) { self.callbacks.remove(&id); } + + pub(crate) fn restart_available_adapters(&mut self) { + self.get_available_adapters() + .into_iter() + .filter(|adapter| adapter.enabled) + .map(|adapter| VirtualHciIndex(adapter.hci_interface)) + .for_each(|virt_hci| self.proxy.restart_bluetooth(virt_hci)); + } } impl IBluetoothManager for BluetoothManager { @@ -182,10 +190,13 @@ impl IBluetoothExperimental for BluetoothManager { return; } + info!("Set floss ll privacy to {}", enabled); if let Err(e) = config_util::write_floss_ll_privacy_enabled(enabled) { error!("Failed to write ll privacy status: {}", e); return; } + + self.restart_available_adapters(); } fn set_devcoredump(&mut self, enabled: bool) -> bool { diff --git a/system/gd/rust/linux/mgmt/src/state_machine.rs b/system/gd/rust/linux/mgmt/src/state_machine.rs index d1365753702ac1be42a1ec9083b2e527ecda80a6..d7c80e851d7e7b49aaa6a46aedafc1b478043ce8 100644 --- a/system/gd/rust/linux/mgmt/src/state_machine.rs +++ b/system/gd/rust/linux/mgmt/src/state_machine.rs @@ -38,6 +38,7 @@ pub enum ProcessState { TurningOn = 1, // We are not notified that the Bluetooth is running On = 2, // Bluetooth is running TurningOff = 3, // We are not notified that the Bluetooth is stopped + Restarting = 4, // Pending restart and not notified that the Bluetooth is stopped } /// Check whether adapter is enabled by checking internal state. @@ -90,6 +91,7 @@ impl Display for RealHciIndex { pub enum AdapterStateActions { StartBluetooth(VirtualHciIndex), StopBluetooth(VirtualHciIndex), + RestartBluetooth(VirtualHciIndex), BluetoothStarted(i32, RealHciIndex), // PID and HCI BluetoothStopped(RealHciIndex), HciDevicePresence(DevPath, RealHciIndex, bool), @@ -186,6 +188,15 @@ impl StateMachineProxy { }); } + pub fn restart_bluetooth(&self, hci: VirtualHciIndex) { + let tx = self.tx.clone(); + tokio::spawn(async move { + let _ = tx + .send(Message::AdapterStateChange(AdapterStateActions::RestartBluetooth(hci))) + .await; + }); + } + /// Read state for an hci device. pub fn get_state<T, F>(&self, hci: VirtualHciIndex, call: F) -> Option<T> where @@ -654,6 +665,14 @@ pub async fn mainloop( let action = context.state_machine.action_stop_bluetooth(hci); cmd_timeout.lock().unwrap().handle_timeout_action(hci, action); } + AdapterStateActions::RestartBluetooth(i) => { + hci = *i; + prev_state = context.state_machine.get_process_state(hci); + next_state = ProcessState::Restarting; + + let action = context.state_machine.action_restart_bluetooth(hci); + cmd_timeout.lock().unwrap().handle_timeout_action(hci, action); + } AdapterStateActions::BluetoothStarted(pid, real_hci) => { hci = match context.state_machine.get_virtual_id_by_real_id(*real_hci) { Some(v) => v, @@ -1310,6 +1329,32 @@ impl StateMachineInternal { } } + /// Returns true if we are restarting bluetooth process + pub fn action_restart_bluetooth(&mut self, hci: VirtualHciIndex) -> CommandTimeoutAction { + if !self.is_known(hci) { + warn!("Attempting to restart unknown hci{}", hci); + return CommandTimeoutAction::DoNothing; + } + + let state = self.get_process_state(hci); + let present = self.get_state(hci, move |a: &AdapterState| Some(a.present)).unwrap_or(false); + let floss_enabled = self.get_floss_enabled(); + + match state { + ProcessState::On if present && floss_enabled => { + self.modify_state(hci, |s: &mut AdapterState| s.state = ProcessState::Restarting); + self.process_manager + .stop(hci.to_string(), self.get_real_hci_by_virtual_id(hci).to_string()); + CommandTimeoutAction::ResetTimer + } + ProcessState::TurningOn => { + debug!("hci{} is already starting.", hci); + CommandTimeoutAction::DoNothing + } + _ => CommandTimeoutAction::DoNothing, + } + } + /// Handles a bluetooth started event. Always returns true even with unknown interfaces. pub fn action_on_bluetooth_started( &mut self, @@ -1345,6 +1390,13 @@ impl StateMachineInternal { self.modify_state(hci, |s: &mut AdapterState| s.state = ProcessState::Off); CommandTimeoutAction::CancelTimer } + ProcessState::Restarting => { + debug!("hci{} restarting", hci.to_i32()); + self.modify_state(hci, |s: &mut AdapterState| s.state = ProcessState::TurningOn); + self.process_manager + .start(hci.to_string(), self.get_real_hci_by_virtual_id(hci).to_string()); + CommandTimeoutAction::ResetTimer + } // Running bluetooth stopped unexpectedly. ProcessState::On if floss_enabled && config_enabled => { let restart_count =