Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit dc9b4b22 authored by Zhengping Jiang's avatar Zhengping Jiang
Browse files

Floss: Add restart bluetooth and apply ll privacy status

Add restart bluetooth to state machine and restart any enabled adapters
when ll privacy status is changed.

Restarting ProcessState can only transit from On. It will be no op for
other SM states. For example, a disabled adapter will stay disabled
after calling restart_bluetooth.

Bug: 242100561
Tag: #floss
Test: manual run dbus command to enable/disable ll privacy
Test: mma -j32

Change-Id: Ib1cba068aea9da47c1cbe7ce62e524e819f9de8f
parent 8a1048e5
Loading
Loading
Loading
Loading
+11 −0
Original line number Diff line number Diff line
@@ -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 {
+52 −0
Original line number Diff line number Diff line
@@ -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 =