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

Commit 7962b32d authored by Hsin-chen Chuang's avatar Hsin-chen Chuang
Browse files

floss: btmanagerd: Replace i32 with VirtualHciIndex / RealHciIndex

Some code are still using i32 to indicate HCI devices. Apply the type
to them to avoid passing the index in different meaning.

Bug: 306322786
Tag: #floss
Test: mmm packages/modules/Bluetooth
Test: Toggle BT through ChromeOS UI, verified state machine
      and callbacks work fine
Change-Id: Ic0b73ca45b4b3d13a752f60a27c338eb81621c36
parent 23aa7a93
Loading
Loading
Loading
Loading
+29 −30
Original line number Diff line number Diff line
@@ -42,27 +42,27 @@ impl BluetoothManager {
        self.proxy.get_state(hci_device, move |a| Some(a.present)).unwrap_or(false)
    }

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

    pub(crate) fn callback_hci_enabled_change(&mut self, hci_device: i32, enabled: bool) {
    pub(crate) fn callback_hci_enabled_change(&mut self, hci: VirtualHciIndex, enabled: bool) {
        if enabled {
            warn!("Started {}", hci_device);
            warn!("Started {}", hci);
        } else {
            warn!("Stopped {}", hci_device);
            warn!("Stopped {}", hci);
        }

        for (_, callback) in &mut self.callbacks {
            callback.on_hci_enabled_changed(hci_device, enabled);
            callback.on_hci_enabled_changed(hci.to_i32(), enabled);
        }
    }

    pub(crate) fn callback_default_adapter_change(&mut self, hci_device: i32) {
    pub(crate) fn callback_default_adapter_change(&mut self, hci: VirtualHciIndex) {
        for (_, callback) in &mut self.callbacks {
            callback.on_default_adapter_changed(hci_device);
            callback.on_default_adapter_changed(hci.to_i32());
        }
    }

@@ -80,50 +80,49 @@ impl BluetoothManager {
}

impl IBluetoothManager for BluetoothManager {
    fn start(&mut self, hci_interface: i32) {
        warn!("Starting {}", hci_interface);
    fn start(&mut self, hci: i32) {
        let hci = VirtualHciIndex(hci);
        warn!("Starting {}", hci);

        if !config_util::modify_hci_n_enabled(hci_interface, true) {
        if !config_util::modify_hci_n_enabled(hci, true) {
            error!("Config is not successfully modified");
        }

        let virt_hci = VirtualHciIndex(hci_interface);

        // Store that this adapter is meant to be started in state machine.
        self.proxy.modify_state(virt_hci, move |a: &mut AdapterState| a.config_enabled = true);
        self.proxy.modify_state(hci, move |a: &mut AdapterState| a.config_enabled = true);

        // Ignore the request if adapter is already enabled or not present.
        if self.is_adapter_enabled(virt_hci) {
            warn!("Adapter {} is already enabled.", hci_interface);
        if self.is_adapter_enabled(hci) {
            warn!("Adapter {} is already enabled.", hci);
            return;
        }

        if !self.is_adapter_present(virt_hci) {
            warn!("Adapter {} is not present.", hci_interface);
        if !self.is_adapter_present(hci) {
            warn!("Adapter {} is not present.", hci);
            return;
        }

        self.proxy.start_bluetooth(virt_hci);
        self.proxy.start_bluetooth(hci);
    }

    fn stop(&mut self, hci_interface: i32) {
        warn!("Stopping {}", hci_interface);
        if !config_util::modify_hci_n_enabled(hci_interface, false) {
    fn stop(&mut self, hci: i32) {
        let hci = VirtualHciIndex(hci);
        warn!("Stopping {}", hci);

        if !config_util::modify_hci_n_enabled(hci, false) {
            error!("Config is not successfully modified");
        }

        let virt_hci = VirtualHciIndex(hci_interface);

        // Store that this adapter is meant to be stopped in state machine.
        self.proxy.modify_state(virt_hci, move |a: &mut AdapterState| a.config_enabled = false);
        self.proxy.modify_state(hci, move |a: &mut AdapterState| a.config_enabled = false);

        // Ignore the request if adapter is already disabled.
        if !self.is_adapter_enabled(virt_hci) {
            warn!("Adapter {} is already stopped", hci_interface);
        if !self.is_adapter_enabled(hci) {
            warn!("Adapter {} is already stopped", hci);
            return;
        }

        self.proxy.stop_bluetooth(virt_hci);
        self.proxy.stop_bluetooth(hci);
    }

    fn get_adapter_enabled(&mut self, hci_interface: i32) -> bool {
@@ -157,13 +156,13 @@ impl IBluetoothManager for BluetoothManager {
            }
            migrate::migrate_bluez_devices();
            for hci in self.proxy.get_valid_adapters().iter().map(|a| a.virt_hci) {
                if config_util::is_hci_n_enabled(hci.to_i32()) {
                if config_util::is_hci_n_enabled(hci) {
                    self.proxy.start_bluetooth(hci);
                }
            }
        } else if prev != enabled {
            for hci in self.proxy.get_valid_adapters().iter().map(|a| a.virt_hci) {
                if config_util::is_hci_n_enabled(hci.to_i32()) {
                if config_util::is_hci_n_enabled(hci) {
                    self.proxy.stop_bluetooth(hci);
                }
            }
+49 −39
Original line number Diff line number Diff line
use crate::state_machine::{RealHciIndex, VirtualHciIndex};

use log::LevelFilter;
use serde_json::{Map, Value};
use std::convert::TryInto;
@@ -25,7 +27,7 @@ const FLOSS_COREDUMP_CONF_PATH: &str = "/var/run/bluetooth/coredump_disabled";
const DEFAULT_ADAPTER_KEY: &str = "default_adapter";

/// In the absence of other values, default to hci0.
const DEFAULT_ADAPTER_VALUE: i32 = 0;
const DEFAULT_ADAPTER: VirtualHciIndex = VirtualHciIndex(0);

pub fn is_floss_enabled() -> bool {
    match std::fs::read(BLUETOOTH_DAEMON_CURRENT) {
@@ -69,17 +71,14 @@ fn get_log_level_internal(config: String) -> Option<LevelFilter> {
}

/// Returns whether hci N is enabled in config; defaults to true.
pub fn is_hci_n_enabled(n: i32) -> bool {
    match read_config().ok().and_then(|config| is_hci_n_enabled_internal(config, n)) {
        Some(v) => v,
        _ => true,
    }
pub fn is_hci_n_enabled(hci: VirtualHciIndex) -> bool {
    read_config().ok().and_then(|config| is_hci_n_enabled_internal(config, hci)).unwrap_or(true)
}

fn is_hci_n_enabled_internal(config: String, n: i32) -> Option<bool> {
fn is_hci_n_enabled_internal(config: String, hci: VirtualHciIndex) -> Option<bool> {
    serde_json::from_str::<Value>(config.as_str())
        .ok()?
        .get(format!("hci{}", n))?
        .get(format!("hci{}", hci))?
        .as_object()?
        .get("enabled")?
        .as_bool()
@@ -96,24 +95,25 @@ pub fn fix_config_file_format() -> bool {
    }
}

pub fn modify_hci_n_enabled(n: i32, enabled: bool) -> bool {
pub fn modify_hci_n_enabled(hci: VirtualHciIndex, enabled: bool) -> bool {
    if !fix_config_file_format() {
        false
    } else {
        match read_config()
            .ok()
            .and_then(|config| modify_hci_n_enabled_internal(config, n, enabled))
        return false;
    }
    match read_config().ok().and_then(|config| modify_hci_n_enabled_internal(config, hci, enabled))
    {
        Some(s) => std::fs::write(BTMANAGERD_CONF, s).is_ok(),
        _ => false,
    }
}
}

fn modify_hci_n_enabled_internal(config: String, n: i32, enabled: bool) -> Option<String> {
    let hci_interface = format!("hci{}", n);
fn modify_hci_n_enabled_internal(
    config: String,
    hci: VirtualHciIndex,
    enabled: bool,
) -> Option<String> {
    let hci_str = format!("hci{}", hci);
    let mut o = serde_json::from_str::<Value>(config.as_str()).ok()?;
    match o.get_mut(hci_interface.clone()) {
    match o.get_mut(hci_str.clone()) {
        Some(section) => {
            section.as_object_mut()?.insert("enabled".to_string(), Value::Bool(enabled));
            serde_json::ser::to_string_pretty(&o).ok()
@@ -121,25 +121,31 @@ fn modify_hci_n_enabled_internal(config: String, n: i32, enabled: bool) -> Optio
        _ => {
            let mut entry_map = Map::new();
            entry_map.insert("enabled".to_string(), Value::Bool(enabled));
            o.as_object_mut()?.insert(hci_interface, Value::Object(entry_map));
            o.as_object_mut()?.insert(hci_str, Value::Object(entry_map));
            serde_json::ser::to_string_pretty(&o).ok()
        }
    }
}

pub fn get_default_adapter() -> i32 {
    match read_config().ok().and_then(|config| {
        serde_json::from_str::<Value>(config.as_str()).ok()?.get(DEFAULT_ADAPTER_KEY)?.as_i64()
    }) {
        Some(v) => v.try_into().unwrap_or(DEFAULT_ADAPTER_VALUE),
        None => DEFAULT_ADAPTER_VALUE,
    }
pub fn get_default_adapter() -> VirtualHciIndex {
    read_config()
        .ok()
        .and_then(|config| {
            serde_json::from_str::<Value>(config.as_str())
                .ok()?
                .get(DEFAULT_ADAPTER_KEY)?
                .as_i64()?
                .try_into()
                .ok()
        })
        .map(|i| VirtualHciIndex(i))
        .unwrap_or(DEFAULT_ADAPTER)
}

pub fn set_default_adapter(adapter: i32) -> bool {
pub fn set_default_adapter(hci: VirtualHciIndex) -> bool {
    match read_config().ok().and_then(|config| {
        let mut cfg = serde_json::from_str::<Value>(config.as_str()).ok()?;
        cfg[DEFAULT_ADAPTER_KEY] = serde_json::to_value(adapter).ok().unwrap();
        cfg[DEFAULT_ADAPTER_KEY] = serde_json::to_value(hci.to_i32()).ok().unwrap();
        serde_json::ser::to_string_pretty(&cfg).ok()
    }) {
        Some(s) => std::fs::write(BTMANAGERD_CONF, s).is_ok(),
@@ -157,13 +163,13 @@ fn list_hci_devices_string() -> Vec<String> {
}

/// Check whether a certain hci device exists in sysfs.
pub fn check_hci_device_exists(hci: i32) -> bool {
pub fn check_hci_device_exists(hci: RealHciIndex) -> bool {
    Path::new(format!("{}/hci{}", HCI_DEVICES_DIR, hci).as_str()).exists()
}

/// Get the devpath for a given hci index. This gives a stable path that can be
/// used to identify a device even as the hci index fluctuates.
pub fn get_devpath_for_hci(hci: i32) -> Option<String> {
pub fn get_devpath_for_hci(hci: RealHciIndex) -> Option<String> {
    match std::fs::canonicalize(format!("{}/hci{}/device", HCI_DEVICES_DIR, hci).as_str()) {
        Ok(p) => Some(p.into_os_string().into_string().ok()?),
        Err(e) => {
@@ -183,7 +189,7 @@ pub fn list_pid_files(pid_dir: &str) -> Vec<String> {
}

/// Calls the reset sysfs entry for an hci device. Returns True if the write succeeds.
pub fn reset_hci_device(hci: i32) -> bool {
pub fn reset_hci_device(hci: RealHciIndex) -> bool {
    let path = format!("/sys/class/bluetooth/hci{}/reset", hci);
    std::fs::write(path, "1").is_ok()
}
@@ -248,7 +254,7 @@ mod tests {
    use super::*;

    fn is_hci_n_enabled_internal_wrapper(config: String, n: i32) -> bool {
        is_hci_n_enabled_internal(config, n).or(Some(true)).unwrap()
        is_hci_n_enabled_internal(config, VirtualHciIndex(n)).unwrap_or(true)
    }

    #[test]
@@ -289,15 +295,19 @@ mod tests {

    #[test]
    fn modify_hci0_enabled() {
        let modified_string =
            modify_hci_n_enabled_internal("{\"hci0\":\n{\"enabled\": false}}".to_string(), 0, true)
        let modified_string = modify_hci_n_enabled_internal(
            "{\"hci0\":\n{\"enabled\": false}}".to_string(),
            VirtualHciIndex(0),
            true,
        )
        .unwrap();
        assert_eq!(is_hci_n_enabled_internal_wrapper(modified_string, 0), true);
    }

    #[test]
    fn modify_hci0_enabled_from_empty() {
        let modified_string = modify_hci_n_enabled_internal("{}".to_string(), 0, true).unwrap();
        let modified_string =
            modify_hci_n_enabled_internal("{}".to_string(), VirtualHciIndex(0), true).unwrap();
        assert_eq!(is_hci_n_enabled_internal_wrapper(modified_string, 0), true);
    }

+53 −75

File changed.

Preview size limit exceeded, changes collapsed.