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

Commit 48382eea authored by Abhishek Pandit-Subedi's avatar Abhishek Pandit-Subedi Committed by Gerrit Code Review
Browse files

Merge changes I098c846d,I69391699

* changes:
  floss: Cache adapter state during startup
  floss: Change manager GetState to GetAdapterEnabled
parents fd170e1c fa50f94b
Loading
Loading
Loading
Loading
+2 −2
Original line number Diff line number Diff line
@@ -216,8 +216,8 @@ impl IBluetoothManager for BluetoothManagerDBus {
        self.client_proxy.method_noreturn("Stop", (hci_interface,))
    }

    fn get_state(&mut self) -> i32 {
        self.client_proxy.method("GetState", ())
    fn get_adapter_enabled(&mut self, hci_interface: i32) -> bool {
        self.client_proxy.method("GetAdapterEnabled", (hci_interface,))
    }

    fn register_callback(&mut self, callback: Box<dyn IBluetoothManagerCallback + Send>) {
+32 −5
Original line number Diff line number Diff line
@@ -2,6 +2,7 @@ use log::{error, info};

use manager_service::iface_bluetooth_manager::{IBluetoothManager, IBluetoothManagerCallback};

use std::collections::HashMap;
use std::process::Command;
use std::sync::atomic::Ordering;

@@ -14,20 +15,44 @@ pub struct BluetoothManager {
    manager_context: ManagerContext,
    callbacks: Vec<(u32, Box<dyn IBluetoothManagerCallback + Send>)>,
    callbacks_last_id: u32,
    cached_devices: HashMap<i32, bool>,
}

impl BluetoothManager {
    pub(crate) fn new(manager_context: ManagerContext) -> BluetoothManager {
        BluetoothManager { manager_context, callbacks: vec![], callbacks_last_id: 0 }
        BluetoothManager {
            manager_context,
            callbacks: vec![],
            callbacks_last_id: 0,
            cached_devices: HashMap::new(),
        }
    }

    pub(crate) fn callback_hci_device_change(&mut self, hci_device: i32, present: bool) {
        if present {
            // Default device to false or whatever was already existing in cache
            self.cached_devices.entry(hci_device).or_insert(false);
        } else {
            // Remove device and ignore if it's not there
            self.cached_devices.remove(&hci_device);
        }

    pub(crate) fn callback_hci_device_change(&self, hci_device: i32, present: bool) {
        for (_, callback) in &self.callbacks {
            callback.on_hci_device_changed(hci_device, present);
        }
    }

    pub(crate) fn callback_hci_enabled_change(&self, hci_device: i32, enabled: bool) {
    pub(crate) fn callback_hci_enabled_change(&mut self, hci_device: i32, enabled: bool) {
        // Update existing entry or insert new one
        match self.cached_devices.get_mut(&hci_device) {
            Some(dev) => {
                *dev = enabled;
            }
            _ => {
                self.cached_devices.insert(hci_device, enabled);
            }
        };

        for (_, callback) in &self.callbacks {
            callback.on_hci_enabled_changed(hci_device, enabled);
        }
@@ -55,10 +80,12 @@ impl IBluetoothManager for BluetoothManager {
        self.manager_context.proxy.stop_bluetooth(hci_interface);
    }

    fn get_state(&mut self) -> i32 {
    fn get_adapter_enabled(&mut self, _hci_interface: i32) -> bool {
        let proxy = self.manager_context.proxy.clone();

        // TODO(b/189501676) - State should depend on given adapter.
        let state = proxy.get_state();
        let result = state_machine::state_to_i32(state);
        let result = state_machine::state_to_enabled(state);
        result
    }

+3 −3
Original line number Diff line number Diff line
@@ -21,9 +21,9 @@ impl IBluetoothManager for BluetoothManagerDBus {
    #[dbus_method("Stop")]
    fn stop(&mut self, _hci_interface: i32) {}

    #[dbus_method("GetState")]
    fn get_state(&mut self) -> i32 {
        0
    #[dbus_method("GetAdapterEnabled")]
    fn get_adapter_enabled(&mut self, _hci_interface: i32) -> bool {
        false
    }

    #[dbus_method("RegisterCallback")]
+9 −0
Original line number Diff line number Diff line
@@ -130,6 +130,15 @@ fn hci_devices_string_to_int(devices: Vec<String>) -> Vec<i32> {
        .collect()
}

pub fn list_pid_files(pid_dir: &str) -> Vec<String> {
    match std::fs::read_dir(pid_dir) {
        Ok(entries) => entries
            .map(|e| e.unwrap().path().file_name().unwrap().to_str().unwrap().to_string())
            .collect::<Vec<_>>(),
        _ => Vec::new(),
    }
}

#[cfg(test)]
mod tests {
    use super::*;
+31 −7
Original line number Diff line number Diff line
@@ -22,14 +22,12 @@ pub enum State {
    TurningOff = 3, // We are not notified that the Bluetooth is stopped
}

impl From<State> for i32 {
    fn from(item: State) -> i32 {
        item as i32
    }
/// Check whether adapter is enabled by checking internal state.
pub fn state_to_enabled(state: State) -> bool {
    match state {
        State::On => true,
        _ => false,
    }

pub fn state_to_i32(state: State) -> i32 {
    i32::from(state)
}

/// Adapter state actions
@@ -143,6 +141,14 @@ fn hci_devices_inotify_async_fd() -> AsyncFd<inotify::Inotify> {
    AsyncFd::new(detector).expect("failed to add async fd")
}

/// On startup, get and cache all hci devices by emitting the callback
fn startup_hci_devices(manager: &Arc<std::sync::Mutex<Box<BluetoothManager>>>) {
    let devices = crate::config_util::list_hci_devices();
    for device in devices {
        manager.lock().unwrap().callback_hci_device_change(device, true);
    }
}

/// Given an hci sysfs path, returns the index of the hci device at the path.
fn get_hci_index_from_device(path: &str) -> Option<i32> {
    let re = Regex::new(r"hci([0-9]+)").unwrap();
@@ -170,6 +176,9 @@ pub async fn mainloop<PM>(
    let timeout_clone = command_timeout.clone();
    let timeout_tx = context.tx.clone();

    // First set up hci states
    startup_hci_devices(&bluetooth_manager);

    tokio::spawn(async move {
        loop {
            let _expired = timeout_clone.expired().await;
@@ -180,6 +189,21 @@ pub async fn mainloop<PM>(
        }
    });

    // Get a list of active pid files to determine initial adapter status
    let init_tx = context.tx.clone();
    tokio::spawn(async move {
        let files = crate::config_util::list_pid_files(PID_DIR);
        for file in files {
            let _ = init_tx
                .send_timeout(
                    Message::PidChange(inotify::EventMask::CREATE, Some(file)),
                    TX_SEND_TIMEOUT_DURATION,
                )
                .await
                .unwrap();
        }
    });

    // Set up a PID file listener to emit PID inotify messages
    let mut pid_async_fd = pid_inotify_async_fd();
    let pid_tx = context.tx.clone();
Loading