• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 use log::{error, info, warn};
2 
3 use std::collections::HashMap;
4 use std::process::Command;
5 
6 use crate::iface_bluetooth_experimental::IBluetoothExperimental;
7 use crate::iface_bluetooth_manager::{
8     AdapterWithEnabled, IBluetoothManager, IBluetoothManagerCallback,
9 };
10 use crate::state_machine::{
11     state_to_enabled, AdapterState, Message, StateMachineProxy, VirtualHciIndex,
12 };
13 use crate::{config_util, migrate};
14 
15 const BLUEZ_INIT_TARGET: &str = "bluetoothd";
16 
17 /// Implementation of IBluetoothManager.
18 pub struct BluetoothManager {
19     proxy: StateMachineProxy,
20     callbacks: HashMap<u32, Box<dyn IBluetoothManagerCallback + Send>>,
21 }
22 
23 impl BluetoothManager {
new(proxy: StateMachineProxy) -> BluetoothManager24     pub fn new(proxy: StateMachineProxy) -> BluetoothManager {
25         BluetoothManager { proxy, callbacks: HashMap::new() }
26     }
27 
is_adapter_enabled(&self, hci_device: VirtualHciIndex) -> bool28     fn is_adapter_enabled(&self, hci_device: VirtualHciIndex) -> bool {
29         state_to_enabled(self.proxy.get_process_state(hci_device))
30     }
31 
is_adapter_present(&self, hci_device: VirtualHciIndex) -> bool32     fn is_adapter_present(&self, hci_device: VirtualHciIndex) -> bool {
33         self.proxy.get_state(hci_device, move |a| Some(a.present)).unwrap_or(false)
34     }
35 
callback_hci_device_change(&mut self, hci_device: i32, present: bool)36     pub(crate) fn callback_hci_device_change(&mut self, hci_device: i32, present: bool) {
37         for (_, callback) in &mut self.callbacks {
38             callback.on_hci_device_changed(hci_device, present);
39         }
40     }
41 
callback_hci_enabled_change(&mut self, hci_device: i32, enabled: bool)42     pub(crate) fn callback_hci_enabled_change(&mut self, hci_device: i32, enabled: bool) {
43         if enabled {
44             info!("Started {}", hci_device);
45         } else {
46             info!("Stopped {}", hci_device);
47         }
48 
49         for (_, callback) in &mut self.callbacks {
50             callback.on_hci_enabled_changed(hci_device, enabled);
51         }
52     }
53 
callback_default_adapter_change(&mut self, hci_device: i32)54     pub(crate) fn callback_default_adapter_change(&mut self, hci_device: i32) {
55         for (_, callback) in &mut self.callbacks {
56             callback.on_default_adapter_changed(hci_device);
57         }
58     }
59 
callback_disconnected(&mut self, id: u32)60     pub(crate) fn callback_disconnected(&mut self, id: u32) {
61         self.callbacks.remove(&id);
62     }
63 }
64 
65 impl IBluetoothManager for BluetoothManager {
start(&mut self, hci_interface: i32)66     fn start(&mut self, hci_interface: i32) {
67         info!("Starting {}", hci_interface);
68 
69         if !config_util::modify_hci_n_enabled(hci_interface, true) {
70             error!("Config is not successfully modified");
71         }
72 
73         let virt_hci = VirtualHciIndex(hci_interface);
74 
75         // Store that this adapter is meant to be started in state machine.
76         self.proxy.modify_state(virt_hci, move |a: &mut AdapterState| a.config_enabled = true);
77 
78         // Ignore the request if adapter is already enabled or not present.
79         if self.is_adapter_enabled(virt_hci) || !self.is_adapter_present(virt_hci) {
80             return;
81         }
82 
83         self.proxy.start_bluetooth(virt_hci);
84     }
85 
stop(&mut self, hci_interface: i32)86     fn stop(&mut self, hci_interface: i32) {
87         info!("Stopping {}", hci_interface);
88         if !config_util::modify_hci_n_enabled(hci_interface, false) {
89             error!("Config is not successfully modified");
90         }
91 
92         let virt_hci = VirtualHciIndex(hci_interface);
93 
94         // Store that this adapter is meant to be stopped in state machine.
95         self.proxy.modify_state(virt_hci, move |a: &mut AdapterState| a.config_enabled = false);
96 
97         // Ignore the request if adapter is already disabled.
98         if !self.is_adapter_enabled(virt_hci) {
99             return;
100         }
101 
102         self.proxy.stop_bluetooth(virt_hci);
103     }
104 
get_adapter_enabled(&mut self, hci_interface: i32) -> bool105     fn get_adapter_enabled(&mut self, hci_interface: i32) -> bool {
106         self.is_adapter_enabled(VirtualHciIndex(hci_interface))
107     }
108 
register_callback(&mut self, mut callback: Box<dyn IBluetoothManagerCallback + Send>)109     fn register_callback(&mut self, mut callback: Box<dyn IBluetoothManagerCallback + Send>) {
110         let tx = self.proxy.get_tx();
111 
112         let id = callback.register_disconnect(Box::new(move |cb_id| {
113             let tx = tx.clone();
114             tokio::spawn(async move {
115                 let _result = tx.send(Message::CallbackDisconnected(cb_id)).await;
116             });
117         }));
118 
119         self.callbacks.insert(id, callback);
120     }
121 
get_floss_enabled(&mut self) -> bool122     fn get_floss_enabled(&mut self) -> bool {
123         self.proxy.get_floss_enabled()
124     }
125 
set_floss_enabled(&mut self, enabled: bool)126     fn set_floss_enabled(&mut self, enabled: bool) {
127         let prev = self.proxy.set_floss_enabled(enabled);
128         config_util::write_floss_enabled(enabled);
129 
130         if prev != enabled && enabled {
131             if let Err(e) = Command::new("initctl").args(&["stop", BLUEZ_INIT_TARGET]).output() {
132                 warn!("Failed to stop bluetoothd: {}", e);
133             }
134             migrate::migrate_bluez_devices();
135             for hci in config_util::list_hci_devices() {
136                 if config_util::is_hci_n_enabled(hci) {
137                     let _ = self.proxy.start_bluetooth(VirtualHciIndex(hci));
138                 }
139             }
140         } else if prev != enabled {
141             for hci in config_util::list_hci_devices() {
142                 if config_util::is_hci_n_enabled(hci) {
143                     let _ = self.proxy.stop_bluetooth(VirtualHciIndex(hci));
144                 }
145             }
146             migrate::migrate_floss_devices();
147             if let Err(e) = Command::new("initctl").args(&["start", BLUEZ_INIT_TARGET]).output() {
148                 warn!("Failed to start bluetoothd: {}", e);
149             }
150         }
151     }
152 
get_available_adapters(&mut self) -> Vec<AdapterWithEnabled>153     fn get_available_adapters(&mut self) -> Vec<AdapterWithEnabled> {
154         self.proxy
155             .get_valid_adapters()
156             .iter()
157             .map(|a| AdapterWithEnabled {
158                 hci_interface: a.virt_hci.to_i32(),
159                 enabled: state_to_enabled(a.state),
160             })
161             .collect::<Vec<AdapterWithEnabled>>()
162     }
163 
get_default_adapter(&mut self) -> i32164     fn get_default_adapter(&mut self) -> i32 {
165         self.proxy.get_default_adapter().to_i32()
166     }
167 
set_desired_default_adapter(&mut self, adapter_index: i32)168     fn set_desired_default_adapter(&mut self, adapter_index: i32) {
169         self.proxy.set_desired_default_adapter(VirtualHciIndex(adapter_index));
170     }
171 }
172 
173 /// Implementation of IBluetoothExperimental
174 impl IBluetoothExperimental for BluetoothManager {
set_ll_privacy(&mut self, enabled: bool)175     fn set_ll_privacy(&mut self, enabled: bool) {
176         let current_status = match config_util::read_floss_ll_privacy_enabled() {
177             Ok(true) => true,
178             _ => false,
179         };
180 
181         if current_status == enabled {
182             return;
183         }
184 
185         if let Err(e) = config_util::write_floss_ll_privacy_enabled(enabled) {
186             error!("Failed to write ll privacy status: {}", e);
187             return;
188         }
189     }
190 
set_devcoredump(&mut self, enabled: bool) -> bool191     fn set_devcoredump(&mut self, enabled: bool) -> bool {
192         info!("Set floss devcoredump to {}", enabled);
193         config_util::write_coredump_state_to_file(enabled)
194     }
195 }
196