blob: 1d81758d5ff0c8d930216c3880a69613bb5464cf [file] [log] [blame]
use log::{error, info};
use manager_service::iface_bluetooth_manager::{
AdapterWithEnabled, IBluetoothManager, IBluetoothManagerCallback,
};
use std::collections::HashMap;
use std::process::Command;
use std::sync::atomic::Ordering;
use crate::{config_util, state_machine, ManagerContext};
const BLUEZ_INIT_TARGET: &str = "bluetoothd";
/// Implementation of IBluetoothManager.
pub struct BluetoothManager {
manager_context: ManagerContext,
callbacks: HashMap<u32, Box<dyn IBluetoothManagerCallback + Send>>,
cached_devices: HashMap<i32, bool>,
}
impl BluetoothManager {
pub(crate) fn new(manager_context: ManagerContext) -> BluetoothManager {
BluetoothManager {
manager_context,
callbacks: HashMap::new(),
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);
}
for (_, callback) in &self.callbacks {
callback.on_hci_device_changed(hci_device, present);
}
}
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);
}
}
pub(crate) fn callback_disconnected(&mut self, id: u32) {
self.callbacks.remove(&id);
}
}
impl IBluetoothManager for BluetoothManager {
fn start(&mut self, hci_interface: i32) {
info!("Starting {}", hci_interface);
if !config_util::modify_hci_n_enabled(hci_interface, true) {
error!("Config is not successfully modified");
}
// Ignore the request if adapter is already enabled.
if *self.cached_devices.get(&hci_interface).unwrap_or(&false) {
return;
}
self.manager_context.proxy.start_bluetooth(hci_interface);
}
fn stop(&mut self, hci_interface: i32) {
info!("Stopping {}", hci_interface);
if !config_util::modify_hci_n_enabled(hci_interface, false) {
error!("Config is not successfully modified");
}
// Ignore the request if adapter is already disabled.
if !*self.cached_devices.get(&hci_interface).unwrap_or(&false) {
return;
}
self.manager_context.proxy.stop_bluetooth(hci_interface);
}
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_enabled(state);
result
}
fn register_callback(&mut self, mut callback: Box<dyn IBluetoothManagerCallback + Send>) {
let tx = self.manager_context.proxy.get_tx();
let id = callback.register_disconnect(Box::new(move |cb_id| {
let tx = tx.clone();
tokio::spawn(async move {
let _result = tx.send(state_machine::Message::CallbackDisconnected(cb_id)).await;
});
}));
self.callbacks.insert(id, callback);
}
fn get_floss_enabled(&mut self) -> bool {
let enabled = self.manager_context.floss_enabled.load(Ordering::Relaxed);
enabled
}
fn set_floss_enabled(&mut self, enabled: bool) {
let prev = self.manager_context.floss_enabled.swap(enabled, Ordering::Relaxed);
config_util::write_floss_enabled(enabled);
if prev != enabled && enabled {
Command::new("initctl")
.args(&["stop", BLUEZ_INIT_TARGET])
.output()
.expect("failed to stop bluetoothd");
// TODO: Implement multi-hci case
let default_device = config_util::list_hci_devices()[0];
if config_util::is_hci_n_enabled(default_device) {
let _ = self.manager_context.proxy.start_bluetooth(default_device);
}
} else if prev != enabled {
// TODO: Implement multi-hci case
let default_device = config_util::list_hci_devices()[0];
self.manager_context.proxy.stop_bluetooth(default_device);
Command::new("initctl")
.args(&["start", BLUEZ_INIT_TARGET])
.output()
.expect("failed to start bluetoothd");
}
}
fn get_available_adapters(&mut self) -> Vec<AdapterWithEnabled> {
let adapters = config_util::list_hci_devices()
.iter()
.map(|hci_interface| {
let enabled: bool = *self.cached_devices.get(&hci_interface).unwrap_or(&false);
AdapterWithEnabled { hci_interface: *hci_interface, enabled }
})
.collect::<Vec<AdapterWithEnabled>>();
adapters
}
}