1 use crate::bluetooth_manager::BluetoothManager;
2 use crate::config_util;
3 use crate::time::Alarm;
4 use bt_utils::socket::{
5     BtSocket, HciChannels, MgmtCommand, MgmtCommandResponse, MgmtEvent, HCI_DEV_NONE,
6 };
7 
8 use libc;
9 use log::{debug, error, info, warn};
10 use nix::sys::signal::{self, Signal};
11 use nix::unistd::Pid;
12 use regex::Regex;
13 use std::collections::{BTreeMap, HashMap};
14 use std::convert::TryFrom;
15 use std::fmt::{Display, Formatter};
16 use std::process::{Child, Command, Stdio};
17 use std::sync::atomic::{AtomicBool, AtomicI32, Ordering};
18 use std::sync::{Arc, Mutex};
19 use tokio::io::unix::AsyncFd;
20 use tokio::sync::mpsc;
21 use tokio::time::{Duration, Instant};
22 
23 /// Directory for Bluetooth pid file
24 pub const PID_DIR: &str = "/var/run/bluetooth";
25 
26 /// Number of times to try restarting before resetting the adapter.
27 pub const RESET_ON_RESTART_COUNT: i32 = 2;
28 
29 /// Time to wait from when IndexRemoved is sent to mgmt socket to when we send
30 /// it to the state machine. This debounce exists because when the Index is
31 /// removed due to adapter lost, userspace requires some time to actually close
32 /// the socket.
33 pub const INDEX_REMOVED_DEBOUNCE_TIME: Duration = Duration::from_millis(150);
34 
35 /// Period to check the PID existence. Ideally adapter should clean up the PID
36 /// file by itself and uses it as the stopped signal. This is a backup mechanism
37 /// to avoid dead process + PID not cleaned up from happening.
38 pub const PID_RUNNING_CHECK_PERIOD: Duration = Duration::from_secs(60);
39 
40 const HCI_BIND_MAX_RETRY: i32 = 2;
41 
42 const HCI_BIND_RETRY_INTERVAL: Duration = Duration::from_millis(10);
43 
44 #[derive(Debug, PartialEq, Copy, Clone)]
45 #[repr(u32)]
46 pub enum ProcessState {
47     Off = 0,            // Bluetooth is not running or is not available.
48     TurningOn = 1,      // We are not notified that the Bluetooth is running
49     On = 2,             // Bluetooth is running
50     TurningOff = 3,     // We are not notified that the Bluetooth is stopped
51     PendingRestart = 4, // Bluetooth is turning on and will be restarted after started
52     Restarting = 5,     // Bluetooth is turning off and will be started after stopped
53 }
54 
55 /// Check whether adapter is enabled by checking internal state.
state_to_enabled(state: ProcessState) -> bool56 pub fn state_to_enabled(state: ProcessState) -> bool {
57     match state {
58         ProcessState::On | ProcessState::TurningOff => true,
59         _ => false,
60     }
61 }
62 
63 /// Device path of hci device in sysfs. This will uniquely identify a Bluetooth
64 /// host controller even when the hci index changes.
65 pub type DevPath = String;
66 
67 /// An invalid hci index.
68 pub const INVALID_HCI_INDEX: i32 = -1;
69 
70 /// Hci index that doesn't necessarily map to the physical hciN value. Make sure
71 /// that |VirtualHciIndex| and |RealHciIndex| don't easily convert to each other
72 /// to protect from logical errors.
73 #[derive(Clone, Copy, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
74 pub struct VirtualHciIndex(pub i32);
75 impl VirtualHciIndex {
to_i32(&self) -> i3276     pub(crate) fn to_i32(&self) -> i32 {
77         self.0
78     }
79 }
80 impl Display for VirtualHciIndex {
fmt(&self, f: &mut Formatter) -> std::fmt::Result81     fn fmt(&self, f: &mut Formatter) -> std::fmt::Result {
82         write!(f, "VirtHci{}", self.0)
83     }
84 }
85 
86 /// Hci index that maps to real system index.
87 #[derive(Clone, Copy, Debug, PartialEq, PartialOrd)]
88 pub struct RealHciIndex(pub i32);
89 impl RealHciIndex {
to_i32(&self) -> i3290     pub(crate) fn to_i32(&self) -> i32 {
91         self.0
92     }
93 }
94 impl Display for RealHciIndex {
fmt(&self, f: &mut Formatter) -> std::fmt::Result95     fn fmt(&self, f: &mut Formatter) -> std::fmt::Result {
96         write!(f, "RealHci{}", self.0)
97     }
98 }
99 
100 /// Adapter state actions
101 #[derive(Debug)]
102 pub enum AdapterStateActions {
103     StartBluetooth(VirtualHciIndex),
104     StopBluetooth(VirtualHciIndex),
105     RestartBluetooth(VirtualHciIndex),
106     BluetoothStarted(i32, VirtualHciIndex), // PID and HCI
107     BluetoothStopped(VirtualHciIndex),
108     HciDevicePresence(DevPath, RealHciIndex, bool),
109 }
110 
111 /// Enum of all the messages that state machine handles.
112 #[derive(Debug)]
113 pub enum Message {
114     AdapterStateChange(AdapterStateActions),
115     PidChange(inotify::EventMask, Option<String>),
116     CallbackDisconnected(u32),
117     CommandTimeout(VirtualHciIndex),
118     SetDesiredDefaultAdapter(VirtualHciIndex),
119 }
120 
121 pub struct StateMachineContext {
122     tx: mpsc::Sender<Message>,
123     rx: mpsc::Receiver<Message>,
124     state_machine: StateMachineInternal,
125 }
126 
127 impl StateMachineContext {
new(state_machine: StateMachineInternal) -> StateMachineContext128     fn new(state_machine: StateMachineInternal) -> StateMachineContext {
129         let (tx, rx) = mpsc::channel::<Message>(10);
130         StateMachineContext { tx: tx, rx: rx, state_machine: state_machine }
131     }
132 
get_proxy(&self) -> StateMachineProxy133     pub fn get_proxy(&self) -> StateMachineProxy {
134         StateMachineProxy {
135             floss_enabled: self.state_machine.floss_enabled.clone(),
136             default_adapter: self.state_machine.default_adapter.clone(),
137             state: self.state_machine.state.clone(),
138             tx: self.tx.clone(),
139         }
140     }
141 }
142 
143 /// Creates a new state machine.
144 ///
145 /// # Arguments
146 /// `invoker` - What type of process manager to use.
create_new_state_machine_context(invoker: Invoker) -> StateMachineContext147 pub fn create_new_state_machine_context(invoker: Invoker) -> StateMachineContext {
148     let floss_enabled = config_util::is_floss_enabled();
149     let desired_adapter = config_util::get_default_adapter();
150     let process_manager = StateMachineInternal::make_process_manager(invoker);
151 
152     StateMachineContext::new(StateMachineInternal::new(
153         process_manager,
154         floss_enabled,
155         desired_adapter,
156     ))
157 }
158 
159 #[derive(Clone)]
160 /// Proxy object to give access to certain internals of the state machine. For more detailed
161 /// documentation, see |StateMachineInternal|.
162 ///
163 /// Always construct this using |StateMachineContext::get_proxy(&self)|.
164 pub struct StateMachineProxy {
165     /// Shared state about whether floss is enabled.
166     floss_enabled: Arc<AtomicBool>,
167 
168     /// Shared state about what the default adapter should be.
169     default_adapter: Arc<AtomicI32>,
170 
171     /// Shared internal state about each adapter's state.
172     state: Arc<Mutex<BTreeMap<VirtualHciIndex, AdapterState>>>,
173 
174     /// Sender to future that mutates |StateMachineInternal| states.
175     tx: mpsc::Sender<Message>,
176 }
177 
178 const TX_SEND_TIMEOUT_DURATION: Duration = Duration::from_secs(3);
179 
180 /// Duration to use for timeouts when starting/stopping adapters.
181 /// Some adapters take a while to load firmware so use a sufficiently long timeout here.
182 const COMMAND_TIMEOUT_DURATION: Duration = Duration::from_secs(7);
183 
184 impl StateMachineProxy {
start_bluetooth(&self, hci: VirtualHciIndex)185     pub fn start_bluetooth(&self, hci: VirtualHciIndex) {
186         let tx = self.tx.clone();
187         tokio::spawn(async move {
188             let _ = tx
189                 .send(Message::AdapterStateChange(AdapterStateActions::StartBluetooth(hci)))
190                 .await;
191         });
192     }
193 
stop_bluetooth(&self, hci: VirtualHciIndex)194     pub fn stop_bluetooth(&self, hci: VirtualHciIndex) {
195         let tx = self.tx.clone();
196         tokio::spawn(async move {
197             let _ =
198                 tx.send(Message::AdapterStateChange(AdapterStateActions::StopBluetooth(hci))).await;
199         });
200     }
201 
restart_bluetooth(&self, hci: VirtualHciIndex)202     pub fn restart_bluetooth(&self, hci: VirtualHciIndex) {
203         let tx = self.tx.clone();
204         tokio::spawn(async move {
205             let _ = tx
206                 .send(Message::AdapterStateChange(AdapterStateActions::RestartBluetooth(hci)))
207                 .await;
208         });
209     }
210 
211     /// Read state for an hci device.
get_state<T, F>(&self, hci: VirtualHciIndex, call: F) -> Option<T> where F: Fn(&AdapterState) -> Option<T>,212     pub fn get_state<T, F>(&self, hci: VirtualHciIndex, call: F) -> Option<T>
213     where
214         F: Fn(&AdapterState) -> Option<T>,
215     {
216         match self.state.lock().unwrap().get(&hci) {
217             Some(a) => call(&a),
218             None => None,
219         }
220     }
221 
get_process_state(&self, hci: VirtualHciIndex) -> ProcessState222     pub fn get_process_state(&self, hci: VirtualHciIndex) -> ProcessState {
223         self.get_state(hci, move |a: &AdapterState| Some(a.state)).unwrap_or(ProcessState::Off)
224     }
225 
modify_state<F>(&mut self, hci: VirtualHciIndex, call: F) where F: Fn(&mut AdapterState),226     pub fn modify_state<F>(&mut self, hci: VirtualHciIndex, call: F)
227     where
228         F: Fn(&mut AdapterState),
229     {
230         call(&mut *self.state.lock().unwrap().entry(hci).or_insert(AdapterState::new(
231             String::new(),
232             RealHciIndex(hci.to_i32()),
233             hci,
234         )))
235     }
236 
get_tx(&self) -> mpsc::Sender<Message>237     pub fn get_tx(&self) -> mpsc::Sender<Message> {
238         self.tx.clone()
239     }
240 
get_floss_enabled(&self) -> bool241     pub fn get_floss_enabled(&self) -> bool {
242         self.floss_enabled.load(Ordering::Relaxed)
243     }
244 
245     /// Sets the |floss_enabled| atomic variable.
246     ///
247     /// # Returns
248     /// Previous value of |floss_enabled|
set_floss_enabled(&mut self, enabled: bool) -> bool249     pub fn set_floss_enabled(&mut self, enabled: bool) -> bool {
250         self.floss_enabled.swap(enabled, Ordering::Relaxed)
251     }
252 
get_adapters(&self) -> Vec<AdapterState>253     pub fn get_adapters(&self) -> Vec<AdapterState> {
254         self.state.lock().unwrap().iter().map(|(_, a)| a.clone()).collect::<Vec<AdapterState>>()
255     }
256 
get_valid_adapters(&self) -> Vec<AdapterState>257     pub fn get_valid_adapters(&self) -> Vec<AdapterState> {
258         self.state
259             .lock()
260             .unwrap()
261             .iter()
262             // Filter to adapters that are present or enabled.
263             .filter(|&(_, a)| a.present || state_to_enabled(a.state))
264             .map(|(_, a)| a.clone())
265             .collect::<Vec<AdapterState>>()
266     }
267 
268     /// Get the default adapter.
get_default_adapter(&mut self) -> VirtualHciIndex269     pub fn get_default_adapter(&mut self) -> VirtualHciIndex {
270         VirtualHciIndex(self.default_adapter.load(Ordering::Relaxed))
271     }
272 
273     /// Set the desired default adapter.
set_desired_default_adapter(&mut self, adapter: VirtualHciIndex)274     pub fn set_desired_default_adapter(&mut self, adapter: VirtualHciIndex) {
275         let tx = self.tx.clone();
276         tokio::spawn(async move {
277             let _ = tx.send(Message::SetDesiredDefaultAdapter(adapter)).await;
278         });
279     }
280 }
281 
pid_inotify_async_fd() -> AsyncFd<inotify::Inotify>282 fn pid_inotify_async_fd() -> AsyncFd<inotify::Inotify> {
283     let mut pid_detector = inotify::Inotify::init().expect("cannot use inotify");
284     pid_detector
285         .add_watch(PID_DIR, inotify::WatchMask::CREATE | inotify::WatchMask::DELETE)
286         .expect("failed to add watch on pid directory");
287     AsyncFd::new(pid_detector).expect("failed to add async fd for pid detector")
288 }
289 
290 /// Given an pid path, returns the adapter index for that pid path.
get_hci_index_from_pid_path(path: &str) -> Option<VirtualHciIndex>291 fn get_hci_index_from_pid_path(path: &str) -> Option<VirtualHciIndex> {
292     let re = Regex::new(r"bluetooth([0-9]+).pid").unwrap();
293     re.captures(path)?.get(1)?.as_str().parse().ok().map(|v| VirtualHciIndex(v))
294 }
295 
event_name_to_string(name: Option<&std::ffi::OsStr>) -> Option<String>296 fn event_name_to_string(name: Option<&std::ffi::OsStr>) -> Option<String> {
297     if let Some(val) = &name {
298         if let Some(strval) = val.to_str() {
299             return Some(strval.to_string());
300         }
301     }
302 
303     return None;
304 }
305 
306 // List existing pids and then configure inotify on pid dir.
configure_pid(pid_tx: mpsc::Sender<Message>)307 fn configure_pid(pid_tx: mpsc::Sender<Message>) {
308     // Configure PID listener.
309     tokio::spawn(async move {
310         debug!("Spawned pid notify task");
311 
312         // Get a list of active pid files to determine initial adapter status
313         let files = config_util::list_pid_files(PID_DIR);
314         for file in files {
315             let _ = pid_tx
316                 .send_timeout(
317                     Message::PidChange(inotify::EventMask::CREATE, Some(file)),
318                     TX_SEND_TIMEOUT_DURATION,
319                 )
320                 .await
321                 .unwrap();
322         }
323 
324         // Set up a PID file listener to emit PID inotify messages
325         let mut pid_async_fd = pid_inotify_async_fd();
326 
327         loop {
328             let r = pid_async_fd.readable_mut();
329             let mut fd_ready = r.await.unwrap();
330             let mut buffer: [u8; 1024] = [0; 1024];
331             debug!("Found new pid inotify entries. Reading them");
332             match fd_ready.try_io(|inner| inner.get_mut().read_events(&mut buffer)) {
333                 Ok(Ok(events)) => {
334                     for event in events {
335                         debug!("got some events from pid {:?}", event.mask);
336                         let _ = pid_tx
337                             .send_timeout(
338                                 Message::PidChange(event.mask, event_name_to_string(event.name)),
339                                 TX_SEND_TIMEOUT_DURATION,
340                             )
341                             .await
342                             .unwrap();
343                     }
344                 }
345                 Err(_) | Ok(Err(_)) => panic!("Inotify watcher on {} failed.", PID_DIR),
346             }
347             fd_ready.clear_ready();
348             drop(fd_ready);
349         }
350     });
351 }
352 
353 // Configure the HCI socket listener and prepare the system to receive mgmt events for index added
354 // and index removed.
configure_hci(hci_tx: mpsc::Sender<Message>)355 fn configure_hci(hci_tx: mpsc::Sender<Message>) {
356     let mut btsock = BtSocket::new();
357 
358     // If the bluetooth socket isn't available, the kernel module is not loaded and we can't
359     // actually listen to it for index added/removed events.
360     match btsock.open() {
361         -1 => {
362             panic!(
363                 "Bluetooth socket unavailable (errno {}). Try loading the kernel module first.",
364                 std::io::Error::last_os_error().raw_os_error().unwrap_or(0)
365             );
366         }
367         x => debug!("Socket open at fd: {}", x),
368     }
369 
370     tokio::spawn(async move {
371         // Bind to control channel (which is used for mgmt commands). We provide
372         // HCI_DEV_NONE because we don't actually need a valid HCI dev for some MGMT commands.
373         let mut bind_succ = false;
374         for _i in 0..HCI_BIND_MAX_RETRY {
375             match btsock.bind_channel(HciChannels::Control, HCI_DEV_NONE) {
376                 -1 => {
377                     match std::io::Error::last_os_error().raw_os_error().unwrap_or(0) {
378                         libc::EINVAL => {
379                             // If MGMT hasn't been initialized EINVAL will be returned.
380                             // Just wait for a short time and try again.
381                             debug!("Got EINVAL in bind. Wait and try again");
382                             tokio::time::sleep(HCI_BIND_RETRY_INTERVAL).await;
383                             continue;
384                         }
385                         others => {
386                             panic!("Failed to bind control channel with errno={}", others);
387                         }
388                     }
389                 }
390                 _ => {
391                     bind_succ = true;
392                     break;
393                 }
394             };
395         }
396 
397         if !bind_succ {
398             panic!("bind failed too many times!!");
399         }
400 
401         debug!("Spawned hci notify task");
402 
403         // Make this into an AsyncFD and start using it for IO
404         let mut hci_afd = AsyncFd::new(btsock).expect("Failed to add async fd for BT socket.");
405 
406         // Start by first reading the index list
407         match hci_afd.writable_mut().await {
408             Ok(mut guard) => {
409                 let _ = guard.try_io(|sock| {
410                     let command = MgmtCommand::ReadIndexList;
411                     sock.get_mut().write_mgmt_packet(command.into());
412                     Ok(())
413                 });
414             }
415             Err(e) => debug!("Failed to write to hci socket: {:?}", e),
416         };
417 
418         // Now listen only for devices that are newly added or removed.
419         loop {
420             if let Ok(mut guard) = hci_afd.readable_mut().await {
421                 let result = guard.try_io(|sock| Ok(sock.get_mut().read_mgmt_packet()));
422                 let packet = match result {
423                     Ok(v) => v.unwrap_or(None),
424                     Err(_) => None,
425                 };
426 
427                 if let Some(p) = packet {
428                     debug!("Got a valid packet from btsocket: {:?}", p);
429 
430                     if let Ok(ev) = MgmtEvent::try_from(p) {
431                         debug!("Got a valid mgmt event: {:?}", ev);
432 
433                         match ev {
434                             MgmtEvent::CommandComplete { opcode: _, status: _, response } => {
435                                 if let MgmtCommandResponse::ReadIndexList {
436                                     num_intf: _,
437                                     interfaces,
438                                 } = response
439                                 {
440                                     for hci in interfaces {
441                                         let hci = RealHciIndex(hci.into());
442                                         debug!("IndexList response: {}", hci);
443                                         // We need devpath for an index or we don't use it.
444                                         if let Some(d) = config_util::get_devpath_for_hci(hci) {
445                                             let _ = hci_tx
446                                                 .send_timeout(
447                                                     Message::AdapterStateChange(
448                                                         AdapterStateActions::HciDevicePresence(
449                                                             d, hci, true,
450                                                         ),
451                                                     ),
452                                                     TX_SEND_TIMEOUT_DURATION,
453                                                 )
454                                                 .await
455                                                 .unwrap();
456                                         } else {
457                                             error!("IndexList: Could not get devpath for {}", hci);
458                                         }
459                                     }
460                                 }
461                             }
462                             MgmtEvent::IndexAdded(hci) => {
463                                 let hci = RealHciIndex(hci.into());
464                                 debug!("IndexAdded: {}", hci);
465                                 // We need devpath for an index or we don't use it.
466                                 if let Some(d) = config_util::get_devpath_for_hci(hci) {
467                                     let _ = hci_tx
468                                         .send_timeout(
469                                             Message::AdapterStateChange(
470                                                 AdapterStateActions::HciDevicePresence(
471                                                     d, hci, true,
472                                                 ),
473                                             ),
474                                             TX_SEND_TIMEOUT_DURATION,
475                                         )
476                                         .await
477                                         .unwrap();
478                                 } else {
479                                     error!("IndexAdded: Could not get devpath for {}", hci);
480                                 }
481                             }
482                             MgmtEvent::IndexRemoved(hci) => {
483                                 let hci = RealHciIndex(hci.into());
484                                 debug!("IndexRemoved: {}", hci);
485                                 let devpath =
486                                     config_util::get_devpath_for_hci(hci).unwrap_or(String::new());
487                                 // Only send presence removed if the device is removed
488                                 // and not when userchannel takes exclusive access. This needs to
489                                 // be delayed a bit for when the socket legitimately disappears as
490                                 // it takes some time for userspace to close the socket.
491                                 //
492                                 // It's possible for devpath to be empty in this case because the
493                                 // index is being removed. Handlers of HciDevicePresence need to
494                                 // be aware of this case.
495                                 let txl = hci_tx.clone();
496                                 tokio::spawn(async move {
497                                     tokio::time::sleep(INDEX_REMOVED_DEBOUNCE_TIME).await;
498                                     if !config_util::check_hci_device_exists(hci) {
499                                         let _ = txl
500                                             .send_timeout(
501                                                 Message::AdapterStateChange(
502                                                     AdapterStateActions::HciDevicePresence(
503                                                         devpath, hci, false,
504                                                     ),
505                                                 ),
506                                                 TX_SEND_TIMEOUT_DURATION,
507                                             )
508                                             .await
509                                             .unwrap();
510                                     }
511                                 });
512                             }
513                         }
514                     }
515                 } else {
516                     // Got nothing from the previous read so clear the ready bit.
517                     guard.clear_ready();
518                 }
519             }
520         }
521     });
522 }
523 
524 /// Handle command timeouts per hci interface.
525 struct CommandTimeout {
526     pub waker: Arc<Alarm>,
527     expired: bool,
528     per_hci_timeout: HashMap<VirtualHciIndex, Instant>,
529     duration: Duration,
530 }
531 
532 impl CommandTimeout {
new() -> Self533     pub fn new() -> Self {
534         CommandTimeout {
535             waker: Arc::new(Alarm::new()),
536             per_hci_timeout: HashMap::new(),
537             expired: true,
538             duration: COMMAND_TIMEOUT_DURATION,
539         }
540     }
541 
542     /// Set next command timeout. If no waker is active, reset to duration.
set_next(&mut self, hci: VirtualHciIndex)543     fn set_next(&mut self, hci: VirtualHciIndex) {
544         let wake = Instant::now() + self.duration;
545         self.per_hci_timeout.entry(hci).and_modify(|v| *v = wake).or_insert(wake);
546 
547         if self.expired {
548             self.waker.reset(self.duration);
549             self.expired = false;
550         }
551     }
552 
553     /// Remove command timeout for hci interface.
cancel(&mut self, hci: VirtualHciIndex)554     fn cancel(&mut self, hci: VirtualHciIndex) {
555         self.per_hci_timeout.remove(&hci);
556     }
557 
558     /// Expire entries that are older than now and set next wake.
559     /// Returns list of expired hci entries.
expire(&mut self) -> Vec<VirtualHciIndex>560     fn expire(&mut self) -> Vec<VirtualHciIndex> {
561         let now = Instant::now();
562 
563         let mut completed: Vec<VirtualHciIndex> = Vec::new();
564         let mut next_expiry = now + self.duration;
565 
566         for (hci, expiry) in &self.per_hci_timeout {
567             if *expiry < now {
568                 completed.push(*hci);
569             } else if *expiry < next_expiry {
570                 next_expiry = *expiry;
571             }
572         }
573 
574         for hci in &completed {
575             self.per_hci_timeout.remove(hci);
576         }
577 
578         // If there are any remaining wakeups, reset the wake.
579         if !self.per_hci_timeout.is_empty() {
580             let duration: Duration = next_expiry - now;
581             self.waker.reset(duration);
582             self.expired = false;
583         } else {
584             self.expired = true;
585         }
586 
587         completed
588     }
589 
590     /// Handles a specific timeout action.
handle_timeout_action(&mut self, hci: VirtualHciIndex, action: CommandTimeoutAction)591     fn handle_timeout_action(&mut self, hci: VirtualHciIndex, action: CommandTimeoutAction) {
592         match action {
593             CommandTimeoutAction::ResetTimer => self.set_next(hci),
594             CommandTimeoutAction::CancelTimer => self.cancel(hci),
595             CommandTimeoutAction::DoNothing => (),
596         }
597     }
598 }
599 
mainloop( mut context: StateMachineContext, bluetooth_manager: Arc<Mutex<Box<BluetoothManager>>>, )600 pub async fn mainloop(
601     mut context: StateMachineContext,
602     bluetooth_manager: Arc<Mutex<Box<BluetoothManager>>>,
603 ) {
604     // Set up a command timeout listener to emit timeout messages
605     let cmd_timeout = Arc::new(Mutex::new(CommandTimeout::new()));
606 
607     let ct = cmd_timeout.clone();
608     let timeout_tx = context.tx.clone();
609 
610     tokio::spawn(async move {
611         let timer = ct.lock().unwrap().waker.clone();
612         loop {
613             let _expired = timer.expired().await;
614             let completed = ct.lock().unwrap().expire();
615             for hci in completed {
616                 let _ = timeout_tx
617                     .send_timeout(Message::CommandTimeout(hci), TX_SEND_TIMEOUT_DURATION)
618                     .await
619                     .unwrap();
620             }
621         }
622     });
623 
624     // Set up an HCI device listener to emit HCI device inotify messages.
625     // This is also responsible for configuring the initial list of HCI devices available on the
626     // system.
627     configure_hci(context.tx.clone());
628     configure_pid(context.tx.clone());
629 
630     // Listen for all messages and act on them
631     loop {
632         let m = context.rx.recv().await;
633 
634         if m.is_none() {
635             warn!("Exiting manager mainloop");
636             break;
637         }
638 
639         debug!("Message handler: {:?}", m);
640 
641         match m.unwrap() {
642             // Adapter action has changed
643             Message::AdapterStateChange(adapter_action) => {
644                 // Grab previous state from lock and release
645                 let hci: VirtualHciIndex;
646                 let next_state;
647                 let prev_state;
648 
649                 match &adapter_action {
650                     AdapterStateActions::StartBluetooth(i) => {
651                         hci = *i;
652                         prev_state = context.state_machine.get_process_state(hci);
653 
654                         let action;
655                         (next_state, action) = context.state_machine.action_start_bluetooth(hci);
656                         cmd_timeout.lock().unwrap().handle_timeout_action(hci, action);
657                     }
658                     AdapterStateActions::StopBluetooth(i) => {
659                         hci = *i;
660                         prev_state = context.state_machine.get_process_state(hci);
661 
662                         let action;
663                         (next_state, action) = context.state_machine.action_stop_bluetooth(hci);
664                         cmd_timeout.lock().unwrap().handle_timeout_action(hci, action);
665                     }
666                     AdapterStateActions::RestartBluetooth(i) => {
667                         hci = *i;
668                         prev_state = context.state_machine.get_process_state(hci);
669 
670                         let action;
671                         (next_state, action) = context.state_machine.action_restart_bluetooth(hci);
672                         cmd_timeout.lock().unwrap().handle_timeout_action(hci, action);
673                     }
674                     AdapterStateActions::BluetoothStarted(pid, i) => {
675                         hci = *i;
676                         prev_state = context.state_machine.get_process_state(hci);
677 
678                         let action;
679                         (next_state, action) =
680                             context.state_machine.action_on_bluetooth_started(*pid, hci);
681                         cmd_timeout.lock().unwrap().handle_timeout_action(hci, action);
682 
683                         if context.state_machine.has_queued_present(hci) {
684                             context.state_machine.modify_state(hci, |a: &mut AdapterState| {
685                                 a.has_queued_present = false;
686                             });
687                             bluetooth_manager.lock().unwrap().callback_hci_device_change(hci, true);
688                         }
689                     }
690                     AdapterStateActions::BluetoothStopped(i) => {
691                         hci = *i;
692                         prev_state = context.state_machine.get_process_state(hci);
693 
694                         let action;
695                         (next_state, action) =
696                             context.state_machine.action_on_bluetooth_stopped(hci);
697                         cmd_timeout.lock().unwrap().handle_timeout_action(hci, action);
698                     }
699 
700                     AdapterStateActions::HciDevicePresence(devpath, i, present) => {
701                         let previous_real_hci = match context
702                             .state_machine
703                             .get_virtual_id_by_devpath(devpath.clone())
704                         {
705                             Some(v) => context
706                                 .state_machine
707                                 .get_state(v, |a: &AdapterState| Some(a.real_hci)),
708                             None => None,
709                         };
710                         hci = context.state_machine.get_updated_virtual_id(devpath.clone(), *i);
711 
712                         // If this is really a new hci device, load the enabled state from the disk.
713                         if previous_real_hci.is_none() {
714                             context.state_machine.modify_state(hci, |a: &mut AdapterState| {
715                                 a.config_enabled = config_util::is_hci_n_enabled(hci);
716                             });
717                         }
718 
719                         // If the real hci changed, we need to set the previous present to the
720                         // opposite of the current present so that we don't no-op the action.
721                         if previous_real_hci.is_some()
722                             && previous_real_hci
723                                 != context
724                                     .state_machine
725                                     .get_state(hci, |a: &AdapterState| Some(a.real_hci))
726                         {
727                             context.state_machine.modify_state(hci, |a: &mut AdapterState| {
728                                 a.present = !present;
729                             });
730                         }
731 
732                         prev_state = context.state_machine.get_process_state(hci);
733 
734                         // Don't bother the clients if presence is unchanged. But still execute the
735                         // state machine here in case there is anything else to be done (e.g.,
736                         // verify the next state).
737                         let presence_changed = *present
738                             != context
739                                 .state_machine
740                                 .get_state(hci, |a: &AdapterState| Some(a.present))
741                                 .unwrap_or(false);
742 
743                         let adapter_change_action;
744                         let timeout_action;
745                         (next_state, adapter_change_action, timeout_action) =
746                             context.state_machine.action_on_hci_presence_changed(hci, *present);
747 
748                         cmd_timeout.lock().unwrap().handle_timeout_action(hci, timeout_action);
749 
750                         match adapter_change_action {
751                             AdapterChangeAction::NewDefaultAdapter(new_hci) => {
752                                 context
753                                     .state_machine
754                                     .default_adapter
755                                     .store(new_hci.to_i32(), Ordering::Relaxed);
756                                 bluetooth_manager
757                                     .lock()
758                                     .unwrap()
759                                     .callback_default_adapter_change(new_hci);
760                             }
761 
762                             AdapterChangeAction::DoNothing => (),
763                         };
764 
765                         if presence_changed {
766                             // If present switched to true and we're turning on the adapter,
767                             // defer the callback until the next BluetoothStarted or CommandTimeout
768                             // so the clients won't get an unexpected state change after present.
769                             let queue_present = *present && next_state == ProcessState::TurningOn;
770 
771                             // Always modify_state to make sure it's reset on queue_present=false,
772                             // e.g., when a hci is removed while its presence is still queued.
773                             context.state_machine.modify_state(hci, |a: &mut AdapterState| {
774                                 a.has_queued_present = queue_present;
775                             });
776 
777                             if !queue_present {
778                                 bluetooth_manager
779                                     .lock()
780                                     .unwrap()
781                                     .callback_hci_device_change(hci, *present);
782                             }
783                         }
784                     }
785                 };
786 
787                 // All actions and the resulting state changes should be logged for debugging.
788                 info!(
789                     "{}: Action={:?}, Previous State({:?}), Next State({:?})",
790                     hci, adapter_action, prev_state, next_state
791                 );
792 
793                 // Only emit enabled event for certain transitions
794                 let prev_enabled = state_to_enabled(prev_state);
795                 let next_enabled = state_to_enabled(next_state);
796                 if prev_enabled != next_enabled {
797                     bluetooth_manager
798                         .lock()
799                         .unwrap()
800                         .callback_hci_enabled_change(hci, next_enabled);
801                 }
802             }
803 
804             // Monitored pid directory has a change
805             Message::PidChange(mask, filename) => match (mask, &filename) {
806                 (inotify::EventMask::CREATE, Some(fname)) => {
807                     let path = std::path::Path::new(PID_DIR).join(&fname);
808                     match (
809                         get_hci_index_from_pid_path(&fname),
810                         tokio::fs::read(path.clone()).await.ok(),
811                     ) {
812                         (Some(hci), Some(s)) => {
813                             let pid = String::from_utf8(s)
814                                 .expect("invalid pid file")
815                                 .parse::<i32>()
816                                 .unwrap_or(0);
817                             debug!("Sending bluetooth started action for {}, pid={}", hci, pid);
818                             let _ = context
819                                 .tx
820                                 .send_timeout(
821                                     Message::AdapterStateChange(
822                                         AdapterStateActions::BluetoothStarted(pid, hci),
823                                     ),
824                                     TX_SEND_TIMEOUT_DURATION,
825                                 )
826                                 .await
827                                 .unwrap();
828                             let handle = tokio::spawn(async move {
829                                 debug!("{}: Spawned process monitor", hci);
830                                 loop {
831                                     tokio::time::sleep(PID_RUNNING_CHECK_PERIOD).await;
832                                     // Check if process exists by sending kill -0.
833                                     match nix::sys::signal::kill(Pid::from_raw(pid), None) {
834                                         Err(nix::errno::Errno::ESRCH) => {
835                                             warn!("{}: Process died; Removing PID file", hci);
836                                             if let Err(e) = std::fs::remove_file(path) {
837                                                 warn!("{}: Failed to remove: {}", hci, e);
838                                             }
839                                             break;
840                                         }
841                                         Err(e) => {
842                                             // Other errno should rarely happen:
843                                             //   EINVAL: The value of the sig argument is an invalid
844                                             //           or unsupported signal number.
845                                             //   EPERM: The process does not have permission to send
846                                             //          the signal to any receiving process.
847                                             error!("{}: Failed to send signal: {}", hci, e);
848                                             break;
849                                         }
850                                         _ => {}
851                                     }
852                                 }
853                             });
854                             match context
855                                 .state_machine
856                                 .process_monitor
857                                 .lock()
858                                 .unwrap()
859                                 .insert(fname.clone(), handle)
860                             {
861                                 Some(handle) => {
862                                     warn!("{}: Aborting old handler", hci);
863                                     handle.abort();
864                                 }
865                                 None => {}
866                             }
867                         }
868                         _ => debug!("Invalid pid path: {}", fname),
869                     }
870                 }
871                 (inotify::EventMask::DELETE, Some(fname)) => {
872                     if let Some(hci) = get_hci_index_from_pid_path(&fname) {
873                         debug!("Sending bluetooth stopped action for {}", hci);
874                         context
875                             .tx
876                             .send_timeout(
877                                 Message::AdapterStateChange(AdapterStateActions::BluetoothStopped(
878                                     hci,
879                                 )),
880                                 TX_SEND_TIMEOUT_DURATION,
881                             )
882                             .await
883                             .unwrap();
884                         match context.state_machine.process_monitor.lock().unwrap().remove(fname) {
885                             Some(handle) => handle.abort(),
886                             None => {
887                                 warn!("{}: Process exited but process monitor not found", hci)
888                             }
889                         }
890                     }
891                 }
892                 _ => debug!("Ignored event {:?} - {:?}", mask, &filename),
893             },
894 
895             // Callback client has disconnected
896             Message::CallbackDisconnected(id) => {
897                 bluetooth_manager.lock().unwrap().callback_disconnected(id);
898             }
899 
900             // Handle command timeouts
901             Message::CommandTimeout(hci) => {
902                 debug!(
903                     "{}: Expired action, state={:?}",
904                     hci,
905                     context.state_machine.get_process_state(hci)
906                 );
907                 let timeout_action = context.state_machine.action_on_command_timeout(hci);
908                 match timeout_action {
909                     StateMachineTimeoutActions::Noop => (),
910                     _ => cmd_timeout.lock().unwrap().set_next(hci),
911                 }
912 
913                 if context.state_machine.has_queued_present(hci) {
914                     context.state_machine.modify_state(hci, |a: &mut AdapterState| {
915                         a.has_queued_present = false;
916                     });
917                     bluetooth_manager.lock().unwrap().callback_hci_device_change(hci, true);
918                 }
919             }
920 
921             Message::SetDesiredDefaultAdapter(hci) => {
922                 debug!("Changing desired default adapter to {}", hci);
923                 match context.state_machine.set_desired_default_adapter(hci) {
924                     AdapterChangeAction::NewDefaultAdapter(new_hci) => {
925                         context
926                             .state_machine
927                             .default_adapter
928                             .store(new_hci.to_i32(), Ordering::Relaxed);
929                         bluetooth_manager.lock().unwrap().callback_default_adapter_change(new_hci);
930                     }
931                     AdapterChangeAction::DoNothing => (),
932                 }
933             }
934         }
935     }
936 }
937 
938 /// Trait that needs to be implemented by the native process manager for the
939 /// targeted system. This is used to manage adapter processes.
940 pub trait ProcessManager {
941     /// Start the adapter process.
942     ///
943     /// # Args
944     /// * `virtual_hci` - Virtual index of adapter used for apis.
945     /// * `real_hci` - Real index of the adapter on the system. This can
946     ///                  change during a single boot.
start(&mut self, virtual_hci: VirtualHciIndex, real_hci: RealHciIndex)947     fn start(&mut self, virtual_hci: VirtualHciIndex, real_hci: RealHciIndex);
948 
949     /// Stop the adapter process.
950     ///
951     /// # Args
952     /// * `virtual_hci` - Virtual index of adapter used for apis.
953     /// * `real_hci` - Real index of the adapter on the system.
stop(&mut self, virtual_hci: VirtualHciIndex, real_hci: RealHciIndex)954     fn stop(&mut self, virtual_hci: VirtualHciIndex, real_hci: RealHciIndex);
955 }
956 
957 pub enum Invoker {
958     #[allow(dead_code)]
959     NativeInvoker,
960     SystemdInvoker,
961     UpstartInvoker,
962 }
963 
964 pub struct NativeInvoker {
965     process_container: Option<Child>,
966     bluetooth_pid: u32,
967 }
968 
969 impl NativeInvoker {
new() -> NativeInvoker970     pub fn new() -> NativeInvoker {
971         NativeInvoker { process_container: None, bluetooth_pid: 0 }
972     }
973 }
974 
975 impl ProcessManager for NativeInvoker {
start(&mut self, virtual_hci: VirtualHciIndex, real_hci: RealHciIndex)976     fn start(&mut self, virtual_hci: VirtualHciIndex, real_hci: RealHciIndex) {
977         let new_process = Command::new("/usr/bin/btadapterd")
978             .arg(format!("INDEX={} HCI={}", virtual_hci.to_i32(), real_hci.to_i32()))
979             .stdout(Stdio::piped())
980             .spawn()
981             .expect("cannot open");
982         self.bluetooth_pid = new_process.id();
983         self.process_container = Some(new_process);
984     }
stop(&mut self, _virtual_hci: VirtualHciIndex, _real_hci: RealHciIndex)985     fn stop(&mut self, _virtual_hci: VirtualHciIndex, _real_hci: RealHciIndex) {
986         match self.process_container {
987             Some(ref mut _p) => {
988                 signal::kill(Pid::from_raw(self.bluetooth_pid as i32), Signal::SIGTERM).unwrap();
989                 self.process_container = None;
990             }
991             None => {
992                 warn!("Process doesn't exist");
993             }
994         }
995     }
996 }
997 
998 pub struct UpstartInvoker {}
999 
1000 impl UpstartInvoker {
new() -> UpstartInvoker1001     pub fn new() -> UpstartInvoker {
1002         UpstartInvoker {}
1003     }
1004 }
1005 
1006 impl ProcessManager for UpstartInvoker {
start(&mut self, virtual_hci: VirtualHciIndex, real_hci: RealHciIndex)1007     fn start(&mut self, virtual_hci: VirtualHciIndex, real_hci: RealHciIndex) {
1008         if let Err(e) = Command::new("initctl")
1009             .args(&[
1010                 "start",
1011                 "btadapterd",
1012                 format!("INDEX={}", virtual_hci.to_i32()).as_str(),
1013                 format!("HCI={}", real_hci.to_i32()).as_str(),
1014             ])
1015             .output()
1016         {
1017             error!("Failed to start btadapterd: {}", e);
1018         }
1019     }
1020 
stop(&mut self, virtual_hci: VirtualHciIndex, real_hci: RealHciIndex)1021     fn stop(&mut self, virtual_hci: VirtualHciIndex, real_hci: RealHciIndex) {
1022         if let Err(e) = Command::new("initctl")
1023             .args(&[
1024                 "stop",
1025                 "btadapterd",
1026                 format!("INDEX={}", virtual_hci.to_i32()).as_str(),
1027                 format!("HCI={}", real_hci.to_i32()).as_str(),
1028             ])
1029             .output()
1030         {
1031             error!("Failed to stop btadapterd: {}", e);
1032         }
1033     }
1034 }
1035 
1036 pub struct SystemdInvoker {}
1037 
1038 impl SystemdInvoker {
new() -> SystemdInvoker1039     pub fn new() -> SystemdInvoker {
1040         SystemdInvoker {}
1041     }
1042 }
1043 
1044 impl ProcessManager for SystemdInvoker {
start(&mut self, virtual_hci: VirtualHciIndex, real_hci: RealHciIndex)1045     fn start(&mut self, virtual_hci: VirtualHciIndex, real_hci: RealHciIndex) {
1046         Command::new("systemctl")
1047             .args(&[
1048                 "restart",
1049                 format!("btadapterd@{}_{}.service", virtual_hci.to_i32(), real_hci.to_i32())
1050                     .as_str(),
1051             ])
1052             .output()
1053             .expect("failed to start bluetooth");
1054     }
1055 
stop(&mut self, virtual_hci: VirtualHciIndex, real_hci: RealHciIndex)1056     fn stop(&mut self, virtual_hci: VirtualHciIndex, real_hci: RealHciIndex) {
1057         Command::new("systemctl")
1058             .args(&[
1059                 "stop",
1060                 format!("btadapterd@{}_{}.service", virtual_hci.to_i32(), real_hci.to_i32())
1061                     .as_str(),
1062             ])
1063             .output()
1064             .expect("failed to stop bluetooth");
1065     }
1066 }
1067 
1068 /// Stored state of each adapter in the state machine.
1069 #[derive(Clone, Debug)]
1070 pub struct AdapterState {
1071     /// Current adapter process state.
1072     pub state: ProcessState,
1073 
1074     /// Device path for this adapter. This should be consistent across removal
1075     /// and addition of devices.
1076     pub devpath: DevPath,
1077 
1078     /// Real hci index for this adapter. This can change after boot as adapters are
1079     /// removed and re-added. Use the devpath for a more consistent look-up.
1080     pub real_hci: RealHciIndex,
1081 
1082     /// Virtual hci index for this adapter. This can be decoupled from the real
1083     /// hci index and is usually the first |real_hci| value that it shows up as.
1084     pub virt_hci: VirtualHciIndex,
1085 
1086     /// PID for process using this adapter.
1087     pub pid: i32,
1088 
1089     /// Whether this hci device is listed as present.
1090     pub present: bool,
1091 
1092     /// Whether the 'present' notification is being deferred until adapter is ready.
1093     pub has_queued_present: bool,
1094 
1095     /// Whether this hci device is configured to be enabled.
1096     pub config_enabled: bool,
1097 
1098     /// How many times this adapter has attempted to restart without success.
1099     pub restart_count: i32,
1100 }
1101 
1102 impl AdapterState {
new(devpath: DevPath, real_hci: RealHciIndex, virt_hci: VirtualHciIndex) -> Self1103     pub fn new(devpath: DevPath, real_hci: RealHciIndex, virt_hci: VirtualHciIndex) -> Self {
1104         AdapterState {
1105             state: ProcessState::Off,
1106             devpath,
1107             real_hci,
1108             virt_hci,
1109             present: false,
1110             has_queued_present: false,
1111             config_enabled: false,
1112             pid: 0,
1113             restart_count: 0,
1114         }
1115     }
1116 }
1117 
1118 /// Internal and core implementation of the state machine.
1119 struct StateMachineInternal {
1120     /// Is Floss currently enabled?
1121     floss_enabled: Arc<AtomicBool>,
1122 
1123     /// Current default adapter.
1124     default_adapter: Arc<AtomicI32>,
1125 
1126     /// Desired default adapter.
1127     desired_adapter: VirtualHciIndex,
1128 
1129     /// Keep track of per hci state. Key = hci id, Value = State. This must be a BTreeMap because
1130     /// we depend on ordering for |get_lowest_available_adapter|.
1131     state: Arc<Mutex<BTreeMap<VirtualHciIndex, AdapterState>>>,
1132 
1133     /// Trace the process existence for each pid file and clean it up if needed.
1134     process_monitor: Arc<Mutex<HashMap<String, tokio::task::JoinHandle<()>>>>,
1135 
1136     /// Process manager implementation.
1137     process_manager: Box<dyn ProcessManager + Send>,
1138 }
1139 
1140 #[derive(Debug, PartialEq)]
1141 enum StateMachineTimeoutActions {
1142     RetryStart,
1143     RetryStop,
1144     Noop,
1145 }
1146 
1147 #[derive(Debug, PartialEq)]
1148 enum CommandTimeoutAction {
1149     CancelTimer,
1150     DoNothing,
1151     ResetTimer,
1152 }
1153 
1154 /// Actions to take when the default adapter may have changed.
1155 #[derive(Debug, PartialEq)]
1156 enum AdapterChangeAction {
1157     DoNothing,
1158     NewDefaultAdapter(VirtualHciIndex),
1159 }
1160 
1161 // Core state machine implementations.
1162 impl StateMachineInternal {
new( process_manager: Box<dyn ProcessManager + Send>, floss_enabled: bool, desired_adapter: VirtualHciIndex, ) -> StateMachineInternal1163     pub fn new(
1164         process_manager: Box<dyn ProcessManager + Send>,
1165         floss_enabled: bool,
1166         desired_adapter: VirtualHciIndex,
1167     ) -> StateMachineInternal {
1168         StateMachineInternal {
1169             floss_enabled: Arc::new(AtomicBool::new(floss_enabled)),
1170             default_adapter: Arc::new(AtomicI32::new(desired_adapter.to_i32())),
1171             desired_adapter,
1172             state: Arc::new(Mutex::new(BTreeMap::new())),
1173             process_monitor: Arc::new(Mutex::new(HashMap::new())),
1174             process_manager: process_manager,
1175         }
1176     }
1177 
make_process_manager(invoker: Invoker) -> Box<dyn ProcessManager + Send>1178     pub(crate) fn make_process_manager(invoker: Invoker) -> Box<dyn ProcessManager + Send> {
1179         match invoker {
1180             Invoker::NativeInvoker => Box::new(NativeInvoker::new()),
1181             Invoker::SystemdInvoker => Box::new(SystemdInvoker::new()),
1182             Invoker::UpstartInvoker => Box::new(UpstartInvoker::new()),
1183         }
1184     }
1185 
get_real_hci_by_virtual_id(&self, hci_id: VirtualHciIndex) -> RealHciIndex1186     pub(crate) fn get_real_hci_by_virtual_id(&self, hci_id: VirtualHciIndex) -> RealHciIndex {
1187         self.state
1188             .lock()
1189             .unwrap()
1190             .get(&hci_id)
1191             .and_then(|a: &AdapterState| Some(a.real_hci))
1192             .unwrap_or(RealHciIndex(hci_id.to_i32()))
1193     }
1194 
1195     /// Find the virtual id of an hci device using a devpath.
get_virtual_id_by_devpath(&self, devpath: DevPath) -> Option<VirtualHciIndex>1196     pub(crate) fn get_virtual_id_by_devpath(&self, devpath: DevPath) -> Option<VirtualHciIndex> {
1197         if devpath.is_empty() {
1198             return None;
1199         }
1200 
1201         for (k, v) in self.state.lock().unwrap().iter() {
1202             if v.devpath == devpath {
1203                 return Some(k.clone());
1204             }
1205         }
1206 
1207         None
1208     }
1209 
1210     /// Find the virtual id of an hci device using a real hci id.
get_virtual_id_by_real_id(&self, hci: RealHciIndex) -> Option<VirtualHciIndex>1211     pub(crate) fn get_virtual_id_by_real_id(&self, hci: RealHciIndex) -> Option<VirtualHciIndex> {
1212         for (k, v) in self.state.lock().unwrap().iter() {
1213             if v.real_hci == hci {
1214                 return Some(k.clone());
1215             }
1216         }
1217 
1218         None
1219     }
1220 
get_next_virtual_id( &mut self, real_hci: RealHciIndex, devpath: Option<DevPath>, ) -> VirtualHciIndex1221     pub(crate) fn get_next_virtual_id(
1222         &mut self,
1223         real_hci: RealHciIndex,
1224         devpath: Option<DevPath>,
1225     ) -> VirtualHciIndex {
1226         let new_virt = match self.state.lock().unwrap().keys().next_back() {
1227             Some(v) => VirtualHciIndex(v.to_i32() + 1),
1228             None => VirtualHciIndex(0),
1229         };
1230         self.modify_state(new_virt, |a: &mut AdapterState| {
1231             a.real_hci = real_hci;
1232             if let Some(d) = devpath.as_ref() {
1233                 a.devpath = d.clone();
1234             }
1235         });
1236 
1237         return new_virt;
1238     }
1239 
1240     /// Identify the virtual hci for the given real hci. We need to match both
1241     /// the RealHci and devpath for it to be considered a match. Update the
1242     /// real_hci and devpath entries for the virtual adapter where it makes sense.
get_updated_virtual_id( &mut self, devpath: DevPath, real_hci: RealHciIndex, ) -> VirtualHciIndex1243     pub(crate) fn get_updated_virtual_id(
1244         &mut self,
1245         devpath: DevPath,
1246         real_hci: RealHciIndex,
1247     ) -> VirtualHciIndex {
1248         let by_devpath = self.get_virtual_id_by_devpath(devpath.clone());
1249         let by_real = self.get_virtual_id_by_real_id(real_hci);
1250 
1251         match (by_devpath, by_real) {
1252             (Some(dev), Some(real)) => {
1253                 // Devpath matches expectations of real hci index.
1254                 if dev == real {
1255                     return real;
1256                 }
1257 
1258                 // If dev device doesn't match real device, replace the real id
1259                 // in non-matching entry with fake value and update devpath matching
1260                 // one with new real hci.
1261                 self.modify_state(dev, |a: &mut AdapterState| {
1262                     a.real_hci = real_hci;
1263                 });
1264                 self.modify_state(real, |a: &mut AdapterState| {
1265                     a.real_hci = RealHciIndex(INVALID_HCI_INDEX);
1266                 });
1267 
1268                 return dev;
1269             }
1270             (Some(dev), None) => {
1271                 // Device found by path and needs real_hci to be updated.
1272                 self.modify_state(dev, |a: &mut AdapterState| {
1273                     a.real_hci = real_hci;
1274                 });
1275 
1276                 return dev;
1277             }
1278             (None, Some(real)) => {
1279                 // If the real index is found but no entry exists with that devpath,
1280                 // this is likely because the entry was added before the devpath became known.
1281                 if !devpath.is_empty() {
1282                     self.modify_state(real, |a: &mut AdapterState| {
1283                         a.devpath = devpath.clone();
1284                     });
1285                 }
1286 
1287                 return real;
1288             }
1289             (None, None) => {
1290                 // This is a brand new device. Add a new virtual device with this
1291                 // real id and devpath.
1292                 return self.get_next_virtual_id(real_hci, Some(devpath));
1293             }
1294         };
1295 
1296         // match should return on all branches above.
1297     }
1298 
is_known(&self, hci: VirtualHciIndex) -> bool1299     fn is_known(&self, hci: VirtualHciIndex) -> bool {
1300         self.state.lock().unwrap().contains_key(&hci)
1301     }
1302 
get_floss_enabled(&self) -> bool1303     fn get_floss_enabled(&self) -> bool {
1304         self.floss_enabled.load(Ordering::Relaxed)
1305     }
1306 
1307     #[cfg(test)]
set_floss_enabled(&mut self, enabled: bool) -> bool1308     fn set_floss_enabled(&mut self, enabled: bool) -> bool {
1309         self.floss_enabled.swap(enabled, Ordering::Relaxed)
1310     }
1311 
1312     #[cfg(test)]
set_config_enabled(&mut self, hci: VirtualHciIndex, enabled: bool)1313     fn set_config_enabled(&mut self, hci: VirtualHciIndex, enabled: bool) {
1314         self.modify_state(hci, move |a: &mut AdapterState| {
1315             a.config_enabled = enabled;
1316         });
1317     }
1318 
has_queued_present(&self, hci: VirtualHciIndex) -> bool1319     fn has_queued_present(&self, hci: VirtualHciIndex) -> bool {
1320         self.get_state(hci, |a: &AdapterState| Some(a.has_queued_present)).unwrap_or(false)
1321     }
1322 
get_process_state(&self, hci: VirtualHciIndex) -> ProcessState1323     fn get_process_state(&self, hci: VirtualHciIndex) -> ProcessState {
1324         self.get_state(hci, move |a: &AdapterState| Some(a.state)).unwrap_or(ProcessState::Off)
1325     }
1326 
get_state<T, F>(&self, hci: VirtualHciIndex, call: F) -> Option<T> where F: Fn(&AdapterState) -> Option<T>,1327     fn get_state<T, F>(&self, hci: VirtualHciIndex, call: F) -> Option<T>
1328     where
1329         F: Fn(&AdapterState) -> Option<T>,
1330     {
1331         match self.state.lock().unwrap().get(&hci) {
1332             Some(a) => call(a),
1333             None => None,
1334         }
1335     }
1336 
modify_state<F>(&mut self, hci: VirtualHciIndex, call: F) where F: Fn(&mut AdapterState),1337     fn modify_state<F>(&mut self, hci: VirtualHciIndex, call: F)
1338     where
1339         F: Fn(&mut AdapterState),
1340     {
1341         call(&mut *self.state.lock().unwrap().entry(hci).or_insert(AdapterState::new(
1342             String::new(),
1343             RealHciIndex(hci.to_i32()),
1344             hci,
1345         )))
1346     }
1347 
1348     /// Attempt to reset an hci device. Always set the state to ProcessState::Stopped
1349     /// as we expect this device to disappear and reappear.
reset_hci(&mut self, hci: RealHciIndex)1350     fn reset_hci(&mut self, hci: RealHciIndex) {
1351         if !config_util::reset_hci_device(hci) {
1352             error!("Attempted reset recovery of {} and failed.", hci);
1353         }
1354     }
1355 
1356     /// Gets the lowest present or enabled adapter.
get_lowest_available_adapter(&self) -> Option<VirtualHciIndex>1357     fn get_lowest_available_adapter(&self) -> Option<VirtualHciIndex> {
1358         self.state
1359             .lock()
1360             .unwrap()
1361             .iter()
1362             // Filter to adapters that are present or enabled.
1363             .filter(|&(_, a)| a.present)
1364             .map(|(_, a)| a.virt_hci)
1365             .next()
1366     }
1367 
1368     /// Set the desired default adapter. Returns a NewDefaultAdapter action if the default
1369     /// adapter was changed as a result (meaning the newly desired adapter is either present or
1370     /// enabled).
set_desired_default_adapter(&mut self, adapter: VirtualHciIndex) -> AdapterChangeAction1371     pub fn set_desired_default_adapter(&mut self, adapter: VirtualHciIndex) -> AdapterChangeAction {
1372         self.desired_adapter = adapter;
1373 
1374         // Desired adapter isn't current and it is present. It becomes the new default adapter.
1375         if self.default_adapter.load(Ordering::Relaxed) != adapter.to_i32()
1376             && self.get_state(adapter, move |a: &AdapterState| Some(a.present)).unwrap_or(false)
1377         {
1378             self.default_adapter.store(adapter.to_i32(), Ordering::Relaxed);
1379             return AdapterChangeAction::NewDefaultAdapter(adapter);
1380         }
1381 
1382         // Desired adapter is either current or not present|enabled so leave the previous default
1383         // adapter.
1384         return AdapterChangeAction::DoNothing;
1385     }
1386 
1387     /// Returns the next state and an action to reset timer if we are starting bluetooth process.
action_start_bluetooth( &mut self, hci: VirtualHciIndex, ) -> (ProcessState, CommandTimeoutAction)1388     pub fn action_start_bluetooth(
1389         &mut self,
1390         hci: VirtualHciIndex,
1391     ) -> (ProcessState, CommandTimeoutAction) {
1392         let state = self.get_process_state(hci);
1393         let present = self.get_state(hci, move |a: &AdapterState| Some(a.present)).unwrap_or(false);
1394         let floss_enabled = self.get_floss_enabled();
1395 
1396         match state {
1397             // If adapter is off, we should turn it on when present and floss is enabled.
1398             // If adapter is turning on and we get another start request, we should just
1399             // repeat the same action which resets the timeout mechanism.
1400             ProcessState::Off | ProcessState::TurningOn if present && floss_enabled => {
1401                 self.modify_state(hci, move |s: &mut AdapterState| {
1402                     s.state = ProcessState::TurningOn
1403                 });
1404                 self.process_manager.start(hci, self.get_real_hci_by_virtual_id(hci));
1405                 (ProcessState::TurningOn, CommandTimeoutAction::ResetTimer)
1406             }
1407             // Otherwise (enabled states) no op
1408             _ => (state, CommandTimeoutAction::DoNothing),
1409         }
1410     }
1411 
1412     /// Returns the next state and an action to reset or cancel timer if we are stopping bluetooth
1413     /// process.
action_stop_bluetooth( &mut self, hci: VirtualHciIndex, ) -> (ProcessState, CommandTimeoutAction)1414     pub fn action_stop_bluetooth(
1415         &mut self,
1416         hci: VirtualHciIndex,
1417     ) -> (ProcessState, CommandTimeoutAction) {
1418         if !self.is_known(hci) {
1419             warn!("Attempting to stop unknown device {}", hci);
1420             return (ProcessState::Off, CommandTimeoutAction::DoNothing);
1421         }
1422 
1423         let state = self.get_process_state(hci);
1424         match state {
1425             // If adapter is turning off and we get another stop request, we should just
1426             // repeat the same action which resets the timeout mechanism.
1427             ProcessState::On | ProcessState::TurningOff => {
1428                 self.modify_state(hci, |s: &mut AdapterState| s.state = ProcessState::TurningOff);
1429                 self.process_manager.stop(hci, self.get_real_hci_by_virtual_id(hci));
1430                 (ProcessState::TurningOff, CommandTimeoutAction::ResetTimer)
1431             }
1432             // Otherwise (disabled states) no op
1433             _ => (state, CommandTimeoutAction::DoNothing),
1434         }
1435     }
1436 
1437     /// Returns the next state and an action to reset timer if we are restarting bluetooth process.
1438     /// This action aims to make sure the configuration is reloaded. Only TurningOn/On states are
1439     /// affected.
action_restart_bluetooth( &mut self, hci: VirtualHciIndex, ) -> (ProcessState, CommandTimeoutAction)1440     pub fn action_restart_bluetooth(
1441         &mut self,
1442         hci: VirtualHciIndex,
1443     ) -> (ProcessState, CommandTimeoutAction) {
1444         if !self.is_known(hci) {
1445             warn!("Attempting to restart unknown device {}", hci);
1446             return (ProcessState::Off, CommandTimeoutAction::DoNothing);
1447         }
1448 
1449         let state = self.get_process_state(hci);
1450         let present = self.get_state(hci, move |a: &AdapterState| Some(a.present)).unwrap_or(false);
1451         let floss_enabled = self.get_floss_enabled();
1452 
1453         match state {
1454             ProcessState::On if present && floss_enabled => {
1455                 self.modify_state(hci, |s: &mut AdapterState| s.state = ProcessState::Restarting);
1456                 self.process_manager.stop(hci, self.get_real_hci_by_virtual_id(hci));
1457                 (ProcessState::Restarting, CommandTimeoutAction::ResetTimer)
1458             }
1459             ProcessState::TurningOn if present && floss_enabled => {
1460                 self.modify_state(hci, |s: &mut AdapterState| {
1461                     s.state = ProcessState::PendingRestart
1462                 });
1463                 (ProcessState::PendingRestart, CommandTimeoutAction::DoNothing)
1464             }
1465             _ => (state, CommandTimeoutAction::DoNothing),
1466         }
1467     }
1468 
1469     /// Returns the next state and an action. Except a restart is pending,
1470     /// always return the action to cancel timer even with unknown interfaces.
action_on_bluetooth_started( &mut self, pid: i32, hci: VirtualHciIndex, ) -> (ProcessState, CommandTimeoutAction)1471     pub fn action_on_bluetooth_started(
1472         &mut self,
1473         pid: i32,
1474         hci: VirtualHciIndex,
1475     ) -> (ProcessState, CommandTimeoutAction) {
1476         if !self.is_known(hci) {
1477             warn!("Unknown device {} is started; capturing that process", hci);
1478             self.modify_state(hci, |s: &mut AdapterState| s.state = ProcessState::Off);
1479         }
1480 
1481         let state = self.get_process_state(hci);
1482         let present = self.get_state(hci, move |a: &AdapterState| Some(a.present)).unwrap_or(false);
1483         let floss_enabled = self.get_floss_enabled();
1484 
1485         if state == ProcessState::PendingRestart && present && floss_enabled {
1486             self.modify_state(hci, |s: &mut AdapterState| {
1487                 s.state = ProcessState::Restarting;
1488                 s.restart_count = 0;
1489                 s.pid = pid;
1490             });
1491             self.process_manager.stop(hci, self.get_real_hci_by_virtual_id(hci));
1492             return (ProcessState::Restarting, CommandTimeoutAction::ResetTimer);
1493         }
1494 
1495         self.modify_state(hci, |s: &mut AdapterState| {
1496             s.state = ProcessState::On;
1497             s.restart_count = 0;
1498             s.pid = pid;
1499         });
1500         (ProcessState::On, CommandTimeoutAction::CancelTimer)
1501     }
1502 
1503     /// Returns the next state and an action to cancel (turned off) or reset timer (restarting).
1504     /// If unexpected, Bluetooth probably crashed, returns an action to reset the timer to restart
1505     /// timeout.
action_on_bluetooth_stopped( &mut self, hci: VirtualHciIndex, ) -> (ProcessState, CommandTimeoutAction)1506     pub fn action_on_bluetooth_stopped(
1507         &mut self,
1508         hci: VirtualHciIndex,
1509     ) -> (ProcessState, CommandTimeoutAction) {
1510         let state = self.get_process_state(hci);
1511         let (present, config_enabled) = self
1512             .get_state(hci, move |a: &AdapterState| Some((a.present, a.config_enabled)))
1513             .unwrap_or((false, false));
1514         let floss_enabled = self.get_floss_enabled();
1515 
1516         match state {
1517             // Normal shut down behavior.
1518             ProcessState::TurningOff => {
1519                 self.modify_state(hci, |s: &mut AdapterState| s.state = ProcessState::Off);
1520                 (ProcessState::Off, CommandTimeoutAction::CancelTimer)
1521             }
1522             ProcessState::Restarting if floss_enabled && config_enabled => {
1523                 self.modify_state(hci, |s: &mut AdapterState| s.state = ProcessState::TurningOn);
1524                 self.process_manager.start(hci, self.get_real_hci_by_virtual_id(hci));
1525                 (ProcessState::TurningOn, CommandTimeoutAction::ResetTimer)
1526             }
1527             // Running bluetooth stopped unexpectedly.
1528             ProcessState::On if floss_enabled && config_enabled => {
1529                 let restart_count =
1530                     self.get_state(hci, |a: &AdapterState| Some(a.restart_count)).unwrap_or(0);
1531 
1532                 // If we've restarted a number of times, attempt to use the reset mechanism instead
1533                 // of retrying a start.
1534                 if restart_count >= RESET_ON_RESTART_COUNT {
1535                     warn!(
1536                         "{} stopped unexpectedly. After {} restarts, trying a reset recovery.",
1537                         hci, restart_count
1538                     );
1539                     // Reset the restart count since we're attempting a reset now.
1540                     self.modify_state(hci, |s: &mut AdapterState| {
1541                         s.state = ProcessState::Off;
1542                         s.restart_count = 0;
1543                     });
1544                     let real_hci = self
1545                         .get_state(hci, |a: &AdapterState| Some(a.real_hci))
1546                         .unwrap_or(RealHciIndex(hci.to_i32()));
1547                     self.reset_hci(real_hci);
1548                     (ProcessState::Off, CommandTimeoutAction::CancelTimer)
1549                 } else {
1550                     warn!(
1551                         "{} stopped unexpectedly, try restarting (attempt #{})",
1552                         hci,
1553                         restart_count + 1
1554                     );
1555                     self.modify_state(hci, |s: &mut AdapterState| {
1556                         s.state = ProcessState::TurningOn;
1557                         s.restart_count = s.restart_count + 1;
1558                     });
1559                     self.process_manager.start(hci, self.get_real_hci_by_virtual_id(hci));
1560                     (ProcessState::TurningOn, CommandTimeoutAction::ResetTimer)
1561                 }
1562             }
1563             _ => {
1564                 warn!(
1565                     "{} stopped unexpectedly from {:?}. Adapter present={}, Floss enabled={}",
1566                     hci, state, present, floss_enabled
1567                 );
1568                 self.modify_state(hci, |s: &mut AdapterState| s.state = ProcessState::Off);
1569                 (ProcessState::Off, CommandTimeoutAction::CancelTimer)
1570             }
1571         }
1572     }
1573 
1574     /// Triggered on Bluetooth start/stop timeout. Return the actions that the
1575     /// state machine has taken, for the external context to reset the timer.
action_on_command_timeout( &mut self, hci: VirtualHciIndex, ) -> StateMachineTimeoutActions1576     pub fn action_on_command_timeout(
1577         &mut self,
1578         hci: VirtualHciIndex,
1579     ) -> StateMachineTimeoutActions {
1580         let state = self.get_process_state(hci);
1581         let floss_enabled = self.get_floss_enabled();
1582         let (present, config_enabled) = self
1583             .get_state(hci, |a: &AdapterState| Some((a.present, a.config_enabled)))
1584             .unwrap_or((false, false));
1585 
1586         match state {
1587             // If Floss is not enabled, just send |Stop| to process manager and end the state
1588             // machine actions.
1589             ProcessState::TurningOn | ProcessState::PendingRestart if !floss_enabled => {
1590                 warn!("{}: Timed out turning on but floss is disabled", hci);
1591                 self.modify_state(hci, |s: &mut AdapterState| s.state = ProcessState::Off);
1592                 self.process_manager.stop(hci, self.get_real_hci_by_virtual_id(hci));
1593                 StateMachineTimeoutActions::Noop
1594             }
1595             // If turning on and hci is enabled, restart the process if we are below
1596             // the restart count. Otherwise, reset and mark turned off.
1597             ProcessState::TurningOn | ProcessState::PendingRestart if config_enabled => {
1598                 let restart_count =
1599                     self.get_state(hci, |a: &AdapterState| Some(a.restart_count)).unwrap_or(0);
1600 
1601                 // If we've restarted a number of times, attempt to use the reset mechanism instead
1602                 // of retrying a start.
1603                 if restart_count >= RESET_ON_RESTART_COUNT {
1604                     warn!(
1605                         "{} timed out while starting (present={}). After {} restarts, trying a reset recovery.",
1606                         hci, present, restart_count
1607                     );
1608                     // Reset the restart count since we're attempting a reset now.
1609                     self.modify_state(hci, |s: &mut AdapterState| {
1610                         s.state = ProcessState::Off;
1611                         s.restart_count = 0;
1612                     });
1613                     let real_hci = self
1614                         .get_state(hci, |s: &AdapterState| Some(s.real_hci))
1615                         .unwrap_or(RealHciIndex(hci.to_i32()));
1616                     self.reset_hci(real_hci);
1617                     StateMachineTimeoutActions::Noop
1618                 } else {
1619                     warn!(
1620                         "{} timed out while starting (present={}), try restarting (attempt #{})",
1621                         hci,
1622                         present,
1623                         restart_count + 1
1624                     );
1625                     self.modify_state(hci, |s: &mut AdapterState| {
1626                         s.state = ProcessState::TurningOn;
1627                         s.restart_count = s.restart_count + 1;
1628                     });
1629                     self.process_manager.stop(hci, self.get_real_hci_by_virtual_id(hci));
1630                     self.process_manager.start(hci, self.get_real_hci_by_virtual_id(hci));
1631                     StateMachineTimeoutActions::RetryStart
1632                 }
1633             }
1634             ProcessState::TurningOff | ProcessState::Restarting => {
1635                 info!("Killing bluetooth {}", hci);
1636                 self.process_manager.stop(hci, self.get_real_hci_by_virtual_id(hci));
1637                 StateMachineTimeoutActions::RetryStop
1638             }
1639             _ => StateMachineTimeoutActions::Noop,
1640         }
1641     }
1642 
1643     /// Handle when an hci device presence has changed.
1644     ///
1645     /// This will start adapters that are configured to be enabled if the presence is newly added.
1646     ///
1647     /// # Return
1648     /// Target process state.
action_on_hci_presence_changed( &mut self, hci: VirtualHciIndex, present: bool, ) -> (ProcessState, AdapterChangeAction, CommandTimeoutAction)1649     pub fn action_on_hci_presence_changed(
1650         &mut self,
1651         hci: VirtualHciIndex,
1652         present: bool,
1653     ) -> (ProcessState, AdapterChangeAction, CommandTimeoutAction) {
1654         let prev_present = self.get_state(hci, |a: &AdapterState| Some(a.present)).unwrap_or(false);
1655         let prev_state = self.get_process_state(hci);
1656 
1657         // No-op if same as previous present.
1658         if prev_present == present {
1659             return (prev_state, AdapterChangeAction::DoNothing, CommandTimeoutAction::DoNothing);
1660         }
1661 
1662         self.modify_state(hci, |a: &mut AdapterState| a.present = present);
1663         let floss_enabled = self.get_floss_enabled();
1664 
1665         let (next_state, timeout_action) =
1666             match self.get_state(hci, |a: &AdapterState| Some((a.state, a.config_enabled))) {
1667                 // Start the adapter if present, config is enabled and floss is enabled.
1668                 Some((ProcessState::Off, true)) if floss_enabled && present => {
1669                     // Restart count will increment for each time a Start doesn't succeed.
1670                     // Going from `off` -> `turning on` here usually means either
1671                     // a) Recovery from a previously unstartable state.
1672                     // b) Fresh device.
1673                     // Both should reset the restart count.
1674                     self.modify_state(hci, |a: &mut AdapterState| a.restart_count = 0);
1675 
1676                     self.action_start_bluetooth(hci)
1677                 }
1678                 _ => (prev_state, CommandTimeoutAction::DoNothing),
1679             };
1680 
1681         let default_adapter = VirtualHciIndex(self.default_adapter.load(Ordering::Relaxed));
1682         let desired_adapter = self.desired_adapter;
1683 
1684         // Two scenarios here:
1685         //   1) The newly present adapter is the desired adapter.
1686         //      * Switch to it immediately as the default adapter.
1687         //   2) The current default adapter is no longer present or enabled.
1688         //      * Switch to the lowest numbered adapter present or do nothing.
1689         //
1690         let adapter_change_action = if present && hci == desired_adapter && hci != default_adapter {
1691             AdapterChangeAction::NewDefaultAdapter(desired_adapter)
1692         } else if !present && hci == default_adapter {
1693             match self.get_lowest_available_adapter() {
1694                 Some(v) => AdapterChangeAction::NewDefaultAdapter(v),
1695                 None => AdapterChangeAction::DoNothing,
1696             }
1697         } else {
1698             AdapterChangeAction::DoNothing
1699         };
1700 
1701         (next_state, adapter_change_action, timeout_action)
1702     }
1703 }
1704 
1705 #[cfg(test)]
1706 mod tests {
1707     use super::*;
1708     use std::collections::VecDeque;
1709 
1710     #[derive(Debug, PartialEq)]
1711     enum ExecutedCommand {
1712         Start,
1713         Stop,
1714     }
1715 
1716     struct MockProcessManager {
1717         last_command: VecDeque<ExecutedCommand>,
1718         expectations: Vec<Option<String>>,
1719     }
1720 
1721     impl MockProcessManager {
new() -> MockProcessManager1722         fn new() -> MockProcessManager {
1723             MockProcessManager { last_command: VecDeque::new(), expectations: Vec::new() }
1724         }
1725 
expect_start(&mut self)1726         fn expect_start(&mut self) {
1727             self.last_command.push_back(ExecutedCommand::Start);
1728         }
1729 
expect_stop(&mut self)1730         fn expect_stop(&mut self) {
1731             self.last_command.push_back(ExecutedCommand::Stop);
1732         }
1733     }
1734 
1735     impl ProcessManager for MockProcessManager {
start(&mut self, _virt: VirtualHciIndex, _real: RealHciIndex)1736         fn start(&mut self, _virt: VirtualHciIndex, _real: RealHciIndex) {
1737             self.expectations.push(match self.last_command.pop_front() {
1738                 Some(x) => {
1739                     if x == ExecutedCommand::Start {
1740                         None
1741                     } else {
1742                         Some(format!("Got [Start], Expected: [{:?}]", x))
1743                     }
1744                 }
1745                 None => Some(format!("Got [Start], Expected: None")),
1746             });
1747         }
1748 
stop(&mut self, _virt: VirtualHciIndex, _real: RealHciIndex)1749         fn stop(&mut self, _virt: VirtualHciIndex, _real: RealHciIndex) {
1750             self.expectations.push(match self.last_command.pop_front() {
1751                 Some(x) => {
1752                     if x == ExecutedCommand::Stop {
1753                         None
1754                     } else {
1755                         Some(format!("Got [Stop], Expected: [{:?}]", x))
1756                     }
1757                 }
1758                 None => Some(format!("Got [Stop], Expected: None")),
1759             });
1760         }
1761     }
1762 
1763     impl Drop for MockProcessManager {
drop(&mut self)1764         fn drop(&mut self) {
1765             assert_eq!(self.last_command.len(), 0);
1766             let exp: &[String] = &[];
1767             // Check that we had 0 false expectations.
1768             assert_eq!(
1769                 self.expectations
1770                     .iter()
1771                     .filter(|&v| !v.is_none())
1772                     .map(|v| v.as_ref().unwrap().clone())
1773                     .collect::<Vec<String>>()
1774                     .as_slice(),
1775                 exp
1776             );
1777         }
1778     }
1779 
1780     // For tests, this is the default adapter we want
1781     const DEFAULT_ADAPTER: VirtualHciIndex = VirtualHciIndex(0);
1782     const ALT_ADAPTER: VirtualHciIndex = VirtualHciIndex(1);
1783 
make_state_machine(process_manager: MockProcessManager) -> StateMachineInternal1784     fn make_state_machine(process_manager: MockProcessManager) -> StateMachineInternal {
1785         let state_machine =
1786             StateMachineInternal::new(Box::new(process_manager), true, DEFAULT_ADAPTER);
1787         state_machine
1788     }
1789 
1790     #[test]
initial_state_is_off()1791     fn initial_state_is_off() {
1792         tokio::runtime::Runtime::new().unwrap().block_on(async {
1793             let process_manager = MockProcessManager::new();
1794             let state_machine = make_state_machine(process_manager);
1795             assert_eq!(state_machine.get_process_state(DEFAULT_ADAPTER), ProcessState::Off);
1796         })
1797     }
1798 
1799     #[test]
off_turnoff_should_noop()1800     fn off_turnoff_should_noop() {
1801         tokio::runtime::Runtime::new().unwrap().block_on(async {
1802             let process_manager = MockProcessManager::new();
1803             let mut state_machine = make_state_machine(process_manager);
1804             state_machine.action_stop_bluetooth(DEFAULT_ADAPTER);
1805             assert_eq!(state_machine.get_process_state(DEFAULT_ADAPTER), ProcessState::Off);
1806         })
1807     }
1808 
1809     #[test]
off_turnon_should_turningon()1810     fn off_turnon_should_turningon() {
1811         tokio::runtime::Runtime::new().unwrap().block_on(async {
1812             let mut process_manager = MockProcessManager::new();
1813             // Expect to send start command
1814             process_manager.expect_start();
1815             let mut state_machine = make_state_machine(process_manager);
1816             state_machine.action_on_hci_presence_changed(DEFAULT_ADAPTER, true);
1817             state_machine.set_config_enabled(DEFAULT_ADAPTER, true);
1818             state_machine.action_start_bluetooth(DEFAULT_ADAPTER);
1819             assert_eq!(state_machine.get_process_state(DEFAULT_ADAPTER), ProcessState::TurningOn);
1820         })
1821     }
1822 
1823     #[test]
turningon_turnon_again_resends_start()1824     fn turningon_turnon_again_resends_start() {
1825         tokio::runtime::Runtime::new().unwrap().block_on(async {
1826             let mut process_manager = MockProcessManager::new();
1827             // Expect to send start command just once
1828             process_manager.expect_start();
1829             process_manager.expect_start();
1830             let mut state_machine = make_state_machine(process_manager);
1831             state_machine.action_on_hci_presence_changed(DEFAULT_ADAPTER, true);
1832             state_machine.set_config_enabled(DEFAULT_ADAPTER, true);
1833             state_machine.action_start_bluetooth(DEFAULT_ADAPTER);
1834             assert_eq!(
1835                 state_machine.action_start_bluetooth(DEFAULT_ADAPTER),
1836                 (ProcessState::TurningOn, CommandTimeoutAction::ResetTimer)
1837             );
1838         })
1839     }
1840 
1841     #[test]
turningon_bluetooth_started()1842     fn turningon_bluetooth_started() {
1843         tokio::runtime::Runtime::new().unwrap().block_on(async {
1844             let mut process_manager = MockProcessManager::new();
1845             process_manager.expect_start();
1846             let mut state_machine = make_state_machine(process_manager);
1847             state_machine.action_on_hci_presence_changed(DEFAULT_ADAPTER, true);
1848             state_machine.action_start_bluetooth(DEFAULT_ADAPTER);
1849             state_machine.action_on_bluetooth_started(0, DEFAULT_ADAPTER);
1850             assert_eq!(state_machine.get_process_state(DEFAULT_ADAPTER), ProcessState::On);
1851         })
1852     }
1853 
1854     #[test]
turningon_bluetooth_different_hci_started()1855     fn turningon_bluetooth_different_hci_started() {
1856         tokio::runtime::Runtime::new().unwrap().block_on(async {
1857             let mut process_manager = MockProcessManager::new();
1858             process_manager.expect_start();
1859             let mut state_machine = make_state_machine(process_manager);
1860             state_machine.action_on_hci_presence_changed(ALT_ADAPTER, true);
1861             state_machine.set_config_enabled(DEFAULT_ADAPTER, true);
1862             state_machine.action_start_bluetooth(ALT_ADAPTER);
1863             state_machine.action_on_bluetooth_started(1, ALT_ADAPTER);
1864             assert_eq!(state_machine.get_process_state(ALT_ADAPTER), ProcessState::On);
1865             assert_eq!(state_machine.get_process_state(DEFAULT_ADAPTER), ProcessState::Off);
1866         })
1867     }
1868 
1869     #[test]
turningon_timeout()1870     fn turningon_timeout() {
1871         tokio::runtime::Runtime::new().unwrap().block_on(async {
1872             let mut process_manager = MockProcessManager::new();
1873             process_manager.expect_start();
1874             process_manager.expect_stop();
1875             process_manager.expect_start(); // start bluetooth again
1876             let mut state_machine = make_state_machine(process_manager);
1877             state_machine.action_on_hci_presence_changed(DEFAULT_ADAPTER, true);
1878             state_machine.set_config_enabled(DEFAULT_ADAPTER, true);
1879             state_machine.action_start_bluetooth(DEFAULT_ADAPTER);
1880             assert_eq!(
1881                 state_machine.action_on_command_timeout(DEFAULT_ADAPTER),
1882                 StateMachineTimeoutActions::RetryStart
1883             );
1884             assert_eq!(state_machine.get_process_state(DEFAULT_ADAPTER), ProcessState::TurningOn);
1885         })
1886     }
1887 
1888     #[test]
turningon_turnoff_should_noop()1889     fn turningon_turnoff_should_noop() {
1890         tokio::runtime::Runtime::new().unwrap().block_on(async {
1891             let mut process_manager = MockProcessManager::new();
1892             process_manager.expect_start();
1893             let mut state_machine = make_state_machine(process_manager);
1894             state_machine.action_on_hci_presence_changed(DEFAULT_ADAPTER, true);
1895             state_machine.action_start_bluetooth(DEFAULT_ADAPTER);
1896             state_machine.action_stop_bluetooth(DEFAULT_ADAPTER);
1897             assert_eq!(state_machine.get_process_state(DEFAULT_ADAPTER), ProcessState::TurningOn);
1898         })
1899     }
1900 
1901     #[test]
on_turnoff_should_turningoff_and_send_command()1902     fn on_turnoff_should_turningoff_and_send_command() {
1903         tokio::runtime::Runtime::new().unwrap().block_on(async {
1904             let mut process_manager = MockProcessManager::new();
1905             process_manager.expect_start();
1906             // Expect to send stop command
1907             process_manager.expect_stop();
1908             let mut state_machine = make_state_machine(process_manager);
1909             state_machine.action_on_hci_presence_changed(DEFAULT_ADAPTER, true);
1910             state_machine.set_config_enabled(DEFAULT_ADAPTER, true);
1911             state_machine.action_start_bluetooth(DEFAULT_ADAPTER);
1912             state_machine.action_on_bluetooth_started(0, DEFAULT_ADAPTER);
1913             state_machine.action_stop_bluetooth(DEFAULT_ADAPTER);
1914             assert_eq!(state_machine.get_process_state(DEFAULT_ADAPTER), ProcessState::TurningOff);
1915         })
1916     }
1917 
1918     #[test]
on_bluetooth_stopped_multicase()1919     fn on_bluetooth_stopped_multicase() {
1920         // Normal bluetooth stopped should restart.
1921         tokio::runtime::Runtime::new().unwrap().block_on(async {
1922             let mut process_manager = MockProcessManager::new();
1923             process_manager.expect_start();
1924             // Expect to start again
1925             process_manager.expect_start();
1926             let mut state_machine = make_state_machine(process_manager);
1927             state_machine.action_on_hci_presence_changed(DEFAULT_ADAPTER, true);
1928             state_machine.set_config_enabled(DEFAULT_ADAPTER, true);
1929             state_machine.action_start_bluetooth(DEFAULT_ADAPTER);
1930             state_machine.action_on_bluetooth_started(0, DEFAULT_ADAPTER);
1931             assert_eq!(
1932                 state_machine.action_on_bluetooth_stopped(DEFAULT_ADAPTER),
1933                 (ProcessState::TurningOn, CommandTimeoutAction::ResetTimer)
1934             );
1935             assert_eq!(state_machine.get_process_state(DEFAULT_ADAPTER), ProcessState::TurningOn);
1936         });
1937 
1938         // Stopped with no presence should restart if config enabled.
1939         tokio::runtime::Runtime::new().unwrap().block_on(async {
1940             let mut process_manager = MockProcessManager::new();
1941             process_manager.expect_start();
1942             // Expect to start again.
1943             process_manager.expect_start();
1944             let mut state_machine = make_state_machine(process_manager);
1945             state_machine.action_on_hci_presence_changed(DEFAULT_ADAPTER, true);
1946             state_machine.set_config_enabled(DEFAULT_ADAPTER, true);
1947             state_machine.action_start_bluetooth(DEFAULT_ADAPTER);
1948             state_machine.action_on_bluetooth_started(0, DEFAULT_ADAPTER);
1949             state_machine.action_on_hci_presence_changed(DEFAULT_ADAPTER, false);
1950             assert_eq!(
1951                 state_machine.action_on_bluetooth_stopped(DEFAULT_ADAPTER),
1952                 (ProcessState::TurningOn, CommandTimeoutAction::ResetTimer)
1953             );
1954             assert_eq!(state_machine.get_process_state(DEFAULT_ADAPTER), ProcessState::TurningOn);
1955         });
1956 
1957         // If floss was disabled and we see stopped, we shouldn't restart.
1958         tokio::runtime::Runtime::new().unwrap().block_on(async {
1959             let mut process_manager = MockProcessManager::new();
1960             process_manager.expect_start();
1961             let mut state_machine = make_state_machine(process_manager);
1962             state_machine.action_on_hci_presence_changed(DEFAULT_ADAPTER, true);
1963             state_machine.action_start_bluetooth(DEFAULT_ADAPTER);
1964             state_machine.action_on_bluetooth_started(0, DEFAULT_ADAPTER);
1965             state_machine.set_floss_enabled(false);
1966             assert_eq!(
1967                 state_machine.action_on_bluetooth_stopped(DEFAULT_ADAPTER),
1968                 (ProcessState::Off, CommandTimeoutAction::CancelTimer)
1969             );
1970             assert_eq!(state_machine.get_process_state(DEFAULT_ADAPTER), ProcessState::Off);
1971         });
1972     }
1973 
1974     #[test]
turningoff_bluetooth_down_should_off()1975     fn turningoff_bluetooth_down_should_off() {
1976         tokio::runtime::Runtime::new().unwrap().block_on(async {
1977             let mut process_manager = MockProcessManager::new();
1978             process_manager.expect_start();
1979             process_manager.expect_stop();
1980             let mut state_machine = make_state_machine(process_manager);
1981             state_machine.action_on_hci_presence_changed(DEFAULT_ADAPTER, true);
1982             state_machine.set_config_enabled(DEFAULT_ADAPTER, true);
1983             state_machine.action_start_bluetooth(DEFAULT_ADAPTER);
1984             state_machine.action_on_bluetooth_started(0, DEFAULT_ADAPTER);
1985             state_machine.action_stop_bluetooth(DEFAULT_ADAPTER);
1986             state_machine.action_on_bluetooth_stopped(DEFAULT_ADAPTER);
1987             assert_eq!(state_machine.get_process_state(DEFAULT_ADAPTER), ProcessState::Off);
1988         })
1989     }
1990 
1991     #[test]
restart_bluetooth()1992     fn restart_bluetooth() {
1993         tokio::runtime::Runtime::new().unwrap().block_on(async {
1994             let mut process_manager = MockProcessManager::new();
1995             process_manager.expect_start();
1996             process_manager.expect_stop();
1997             process_manager.expect_start();
1998             let mut state_machine = make_state_machine(process_manager);
1999             state_machine.action_on_hci_presence_changed(DEFAULT_ADAPTER, true);
2000             state_machine.action_start_bluetooth(DEFAULT_ADAPTER);
2001             state_machine.action_on_bluetooth_started(0, DEFAULT_ADAPTER);
2002             state_machine.action_stop_bluetooth(DEFAULT_ADAPTER);
2003             state_machine.action_on_bluetooth_stopped(DEFAULT_ADAPTER);
2004             state_machine.action_start_bluetooth(DEFAULT_ADAPTER);
2005             state_machine.action_on_bluetooth_started(0, DEFAULT_ADAPTER);
2006             assert_eq!(state_machine.get_process_state(DEFAULT_ADAPTER), ProcessState::On);
2007         })
2008     }
2009 
2010     #[test]
start_bluetooth_without_device_fails()2011     fn start_bluetooth_without_device_fails() {
2012         tokio::runtime::Runtime::new().unwrap().block_on(async {
2013             let process_manager = MockProcessManager::new();
2014             let mut state_machine = make_state_machine(process_manager);
2015             state_machine.action_start_bluetooth(DEFAULT_ADAPTER);
2016             assert_eq!(state_machine.get_process_state(DEFAULT_ADAPTER), ProcessState::Off);
2017         });
2018     }
2019 
2020     #[test]
start_bluetooth_without_floss_fails()2021     fn start_bluetooth_without_floss_fails() {
2022         tokio::runtime::Runtime::new().unwrap().block_on(async {
2023             let process_manager = MockProcessManager::new();
2024             let mut state_machine = make_state_machine(process_manager);
2025             state_machine.set_floss_enabled(false);
2026             state_machine.action_on_hci_presence_changed(DEFAULT_ADAPTER, true);
2027             state_machine.set_config_enabled(DEFAULT_ADAPTER, true);
2028             state_machine.action_start_bluetooth(DEFAULT_ADAPTER);
2029             assert_eq!(state_machine.get_process_state(DEFAULT_ADAPTER), ProcessState::Off);
2030         });
2031     }
2032 
2033     #[test]
on_timeout_multicase()2034     fn on_timeout_multicase() {
2035         // If a timeout occurs while turning on or off with floss enabled..
2036         tokio::runtime::Runtime::new().unwrap().block_on(async {
2037             let mut process_manager = MockProcessManager::new();
2038             process_manager.expect_start();
2039             // Expect a stop and start for timeout.
2040             process_manager.expect_stop();
2041             process_manager.expect_start();
2042             // Expect another stop for stop timeout.
2043             process_manager.expect_stop();
2044             process_manager.expect_stop();
2045             let mut state_machine = make_state_machine(process_manager);
2046             state_machine.action_on_hci_presence_changed(DEFAULT_ADAPTER, true);
2047             state_machine.set_config_enabled(DEFAULT_ADAPTER, true);
2048             state_machine.action_start_bluetooth(DEFAULT_ADAPTER);
2049             assert_eq!(state_machine.get_process_state(DEFAULT_ADAPTER), ProcessState::TurningOn);
2050             assert_eq!(
2051                 state_machine.action_on_command_timeout(DEFAULT_ADAPTER),
2052                 StateMachineTimeoutActions::RetryStart
2053             );
2054             assert_eq!(state_machine.get_process_state(DEFAULT_ADAPTER), ProcessState::TurningOn);
2055             state_machine.action_on_bluetooth_started(0, DEFAULT_ADAPTER);
2056             state_machine.action_stop_bluetooth(DEFAULT_ADAPTER);
2057             assert_eq!(
2058                 state_machine.action_on_command_timeout(DEFAULT_ADAPTER),
2059                 StateMachineTimeoutActions::RetryStop
2060             );
2061             assert_eq!(state_machine.get_process_state(DEFAULT_ADAPTER), ProcessState::TurningOff);
2062         });
2063 
2064         // If a timeout occurs during turning on and floss is disabled, stop the adapter.
2065         tokio::runtime::Runtime::new().unwrap().block_on(async {
2066             let mut process_manager = MockProcessManager::new();
2067             process_manager.expect_start();
2068             // Expect a stop for timeout since floss is disabled.
2069             process_manager.expect_stop();
2070             let mut state_machine = make_state_machine(process_manager);
2071             state_machine.action_on_hci_presence_changed(DEFAULT_ADAPTER, true);
2072             state_machine.set_config_enabled(DEFAULT_ADAPTER, true);
2073             state_machine.action_start_bluetooth(DEFAULT_ADAPTER);
2074             assert_eq!(state_machine.get_process_state(DEFAULT_ADAPTER), ProcessState::TurningOn);
2075             state_machine.set_floss_enabled(false);
2076             assert_eq!(
2077                 state_machine.action_on_command_timeout(DEFAULT_ADAPTER),
2078                 StateMachineTimeoutActions::Noop
2079             );
2080             assert_eq!(state_machine.get_process_state(DEFAULT_ADAPTER), ProcessState::Off);
2081         });
2082 
2083         // If a timeout occurs during TurningOn phase, use config_enabled to decide eventual state.
2084         tokio::runtime::Runtime::new().unwrap().block_on(async {
2085             let mut process_manager = MockProcessManager::new();
2086             process_manager.expect_start();
2087             process_manager.expect_stop();
2088             process_manager.expect_start();
2089             let mut state_machine = make_state_machine(process_manager);
2090             state_machine.action_on_hci_presence_changed(DEFAULT_ADAPTER, true);
2091             state_machine.set_config_enabled(DEFAULT_ADAPTER, true);
2092             state_machine.action_start_bluetooth(DEFAULT_ADAPTER);
2093             assert_eq!(state_machine.get_process_state(DEFAULT_ADAPTER), ProcessState::TurningOn);
2094             state_machine.action_on_hci_presence_changed(DEFAULT_ADAPTER, false);
2095             assert_eq!(
2096                 state_machine.action_on_command_timeout(DEFAULT_ADAPTER),
2097                 StateMachineTimeoutActions::RetryStart
2098             );
2099             assert_eq!(state_machine.get_process_state(DEFAULT_ADAPTER), ProcessState::TurningOn);
2100         });
2101     }
2102 
2103     #[test]
test_updated_virtual_id()2104     fn test_updated_virtual_id() {
2105         let process_manager = MockProcessManager::new();
2106         let mut state_machine = make_state_machine(process_manager);
2107 
2108         // Note: Test ordering matters here. When re-ordering, keep track of what
2109         // the previous and next states are expected to be. Cases below will also
2110         // denote which match arm it's trying to test.
2111 
2112         // Case #1: (None, None)
2113         // Insert a devpath + real index at 0. Expect virtual index of 0.
2114         assert_eq!(
2115             state_machine.get_updated_virtual_id("/fake/bt0".into(), RealHciIndex(0)),
2116             VirtualHciIndex(0)
2117         );
2118 
2119         // Case #2: (None, None)
2120         // Inserting a real index of 2 will still get you a virtual index of 1.
2121         // We insert in increasing order.
2122         assert_eq!(
2123             state_machine.get_updated_virtual_id("/fake/bt1".into(), RealHciIndex(2)),
2124             VirtualHciIndex(1)
2125         );
2126 
2127         // Case #3: (Some(dev), None)
2128         // Inserting a new real hci for an existing devpath should return the same virtual index.
2129         assert_eq!(
2130             state_machine.get_updated_virtual_id("/fake/bt0".into(), RealHciIndex(12)),
2131             VirtualHciIndex(0)
2132         );
2133         assert_eq!(
2134             Some(RealHciIndex(12)),
2135             state_machine.get_state(VirtualHciIndex(0), |a: &AdapterState| Some(a.real_hci))
2136         );
2137 
2138         // Case #4: (Some(dev), Some(real)) if dev == real
2139         // When devpath and real hci match, expect a stable virtual index.
2140         assert_eq!(
2141             state_machine.get_updated_virtual_id("/fake/bt0".into(), RealHciIndex(12)),
2142             VirtualHciIndex(0)
2143         );
2144 
2145         // Case #5: (None, None) and (None, Some(real))
2146         // If we inserted previously without a devpath, assign this devpath to the index.
2147         assert_eq!(
2148             state_machine.get_updated_virtual_id(String::new(), RealHciIndex(0)),
2149             VirtualHciIndex(2)
2150         );
2151         assert_eq!(
2152             Some(String::new()),
2153             state_machine.get_state(VirtualHciIndex(2), |a: &AdapterState| Some(a.devpath.clone()))
2154         );
2155         assert_eq!(
2156             state_machine.get_updated_virtual_id("/fake/bt2".into(), RealHciIndex(0)),
2157             VirtualHciIndex(2)
2158         );
2159         assert_eq!(
2160             Some("/fake/bt2".into()),
2161             state_machine.get_state(VirtualHciIndex(2), |a: &AdapterState| Some(a.devpath.clone()))
2162         );
2163 
2164         // Case #6: (Some(dev), Some(real)) if dev != real
2165         // We always prefer the virtual index pointed to by the devpath.
2166         assert_eq!(
2167             state_machine.get_updated_virtual_id("/fake/bt0".into(), RealHciIndex(0)),
2168             VirtualHciIndex(0)
2169         );
2170         assert_eq!(
2171             Some("/fake/bt0".to_string()),
2172             state_machine.get_state(VirtualHciIndex(0), |a: &AdapterState| Some(a.devpath.clone()))
2173         );
2174         assert_eq!(
2175             Some(RealHciIndex(0)),
2176             state_machine.get_state(VirtualHciIndex(0), |a: &AdapterState| Some(a.real_hci))
2177         );
2178         assert_eq!(
2179             Some(RealHciIndex(INVALID_HCI_INDEX)),
2180             state_machine.get_state(VirtualHciIndex(2), |a: &AdapterState| Some(a.real_hci))
2181         );
2182     }
2183 
2184     #[test]
path_to_pid()2185     fn path_to_pid() {
2186         assert_eq!(
2187             get_hci_index_from_pid_path("/var/run/bluetooth/bluetooth0.pid"),
2188             Some(VirtualHciIndex(0))
2189         );
2190         assert_eq!(
2191             get_hci_index_from_pid_path("/var/run/bluetooth/bluetooth1.pid"),
2192             Some(VirtualHciIndex(1))
2193         );
2194         assert_eq!(
2195             get_hci_index_from_pid_path("/var/run/bluetooth/bluetooth10.pid"),
2196             Some(VirtualHciIndex(10))
2197         );
2198         assert_eq!(get_hci_index_from_pid_path("/var/run/bluetooth/garbage"), None);
2199     }
2200 }
2201