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

Commit d0ff02b9 authored by Sonny Sasaka's avatar Sonny Sasaka Committed by Automerger Merge Worker
Browse files

Merge "floss: add systemd invoker." am: b94c13ac am: 0a3b9c9a am: 080b3e19

Original change: https://android-review.googlesource.com/c/platform/system/bt/+/1818335

Change-Id: I75720b753d2b8f1a8aa133556c20107528b73716
parents b0bcfef2 080b3e19
Loading
Loading
Loading
Loading
+12 −1
Original line number Original line Diff line number Diff line
@@ -42,7 +42,18 @@ pub async fn main() -> Result<(), Box<dyn std::error::Error>> {
    // Connect to the D-Bus system bus (this is blocking, unfortunately).
    // Connect to the D-Bus system bus (this is blocking, unfortunately).
    let (resource, conn) = connection::new_system_sync()?;
    let (resource, conn) = connection::new_system_sync()?;


    let context = state_machine::start_new_state_machine_context();
    // Determine whether to use upstart or systemd
    let args: Vec<String> = std::env::args().collect();
    let invoker = if args.len() > 1 {
        match &args[1][0..] {
            "--systemd" | "-s" => state_machine::Invoker::SystemdInvoker,
            _ => state_machine::Invoker::UpstartInvoker,
        }
    } else {
        state_machine::Invoker::UpstartInvoker
    };

    let context = state_machine::start_new_state_machine_context(invoker);
    let proxy = context.get_proxy();
    let proxy = context.get_proxy();
    let manager_context = ManagerContext {
    let manager_context = ManagerContext {
        proxy: proxy,
        proxy: proxy,
+84 −47
Original line number Original line Diff line number Diff line
@@ -49,17 +49,14 @@ pub enum Message {
    CommandTimeout(),
    CommandTimeout(),
}
}


pub struct StateMachineContext<PM> {
pub struct StateMachineContext {
    tx: mpsc::Sender<Message>,
    tx: mpsc::Sender<Message>,
    rx: mpsc::Receiver<Message>,
    rx: mpsc::Receiver<Message>,
    state_machine: ManagerStateMachine<PM>,
    state_machine: ManagerStateMachine,
}
}


impl<PM> StateMachineContext<PM> {
impl StateMachineContext {
    fn new(state_machine: ManagerStateMachine<PM>) -> StateMachineContext<PM>
    fn new(state_machine: ManagerStateMachine) -> StateMachineContext {
    where
        PM: ProcessManager + Send,
    {
        let (tx, rx) = mpsc::channel::<Message>(10);
        let (tx, rx) = mpsc::channel::<Message>(10);
        StateMachineContext { tx: tx, rx: rx, state_machine: state_machine }
        StateMachineContext { tx: tx, rx: rx, state_machine: state_machine }
    }
    }
@@ -69,8 +66,12 @@ impl<PM> StateMachineContext<PM> {
    }
    }
}
}


pub fn start_new_state_machine_context() -> StateMachineContext<UpstartInvoker> {
pub fn start_new_state_machine_context(invoker: Invoker) -> StateMachineContext {
    StateMachineContext::new(ManagerStateMachine::new_upstart())
    match invoker {
        Invoker::NativeInvoker => StateMachineContext::new(ManagerStateMachine::new_native()),
        Invoker::SystemdInvoker => StateMachineContext::new(ManagerStateMachine::new_systemd()),
        Invoker::UpstartInvoker => StateMachineContext::new(ManagerStateMachine::new_upstart()),
    }
}
}


#[derive(Clone)]
#[derive(Clone)]
@@ -165,12 +166,10 @@ fn event_name_to_string(name: Option<&std::ffi::OsStr>) -> Option<String> {
    return None;
    return None;
}
}


pub async fn mainloop<PM>(
pub async fn mainloop(
    mut context: StateMachineContext<PM>,
    mut context: StateMachineContext,
    bluetooth_manager: Arc<std::sync::Mutex<Box<BluetoothManager>>>,
    bluetooth_manager: Arc<std::sync::Mutex<Box<BluetoothManager>>>,
) where
) {
    PM: ProcessManager + Send,
{
    // Set up a command timeout listener to emit timeout messages
    // Set up a command timeout listener to emit timeout messages
    let command_timeout = Arc::new(Alarm::new());
    let command_timeout = Arc::new(Alarm::new());
    let timeout_clone = command_timeout.clone();
    let timeout_clone = command_timeout.clone();
@@ -445,18 +444,24 @@ pub trait ProcessManager {
    fn stop(&mut self, hci_interface: String);
    fn stop(&mut self, hci_interface: String);
}
}


pub struct NativeSubprocess {
pub enum Invoker {
    NativeInvoker,
    SystemdInvoker,
    UpstartInvoker,
}

pub struct NativeInvoker {
    process_container: Option<Child>,
    process_container: Option<Child>,
    bluetooth_pid: u32,
    bluetooth_pid: u32,
}
}


impl NativeSubprocess {
impl NativeInvoker {
    pub fn new() -> NativeSubprocess {
    pub fn new() -> NativeInvoker {
        NativeSubprocess { process_container: None, bluetooth_pid: 0 }
        NativeInvoker { process_container: None, bluetooth_pid: 0 }
    }
    }
}
}


impl ProcessManager for NativeSubprocess {
impl ProcessManager for NativeInvoker {
    fn start(&mut self, hci_interface: String) {
    fn start(&mut self, hci_interface: String) {
        let new_process = Command::new("/usr/bin/btadapterd")
        let new_process = Command::new("/usr/bin/btadapterd")
            .arg(format!("HCI={}", hci_interface))
            .arg(format!("HCI={}", hci_interface))
@@ -503,25 +508,48 @@ impl ProcessManager for UpstartInvoker {
    }
    }
}
}


struct ManagerStateMachine<PM> {
pub struct SystemdInvoker {}

impl SystemdInvoker {
    pub fn new() -> SystemdInvoker {
        SystemdInvoker {}
    }
}

impl ProcessManager for SystemdInvoker {
    fn start(&mut self, hci_interface: String) {
        Command::new("systemctl")
            .args(&["restart", format!("btadapterd@{}.service", hci_interface).as_str()])
            .output()
            .expect("failed to start bluetooth");
    }

    fn stop(&mut self, hci_interface: String) {
        Command::new("systemctl")
            .args(&["stop", format!("btadapterd@{}.service", hci_interface).as_str()])
            .output()
            .expect("failed to stop bluetooth");
    }
}

struct ManagerStateMachine {
    state: Arc<std::sync::Mutex<State>>,
    state: Arc<std::sync::Mutex<State>>,
    process_manager: PM,
    process_manager: Box<dyn ProcessManager + Send>,
    hci_interface: i32,
    hci_interface: i32,
    bluetooth_pid: i32,
    bluetooth_pid: i32,
}
}


impl ManagerStateMachine<NativeSubprocess> {
impl ManagerStateMachine {
    // NativeSubprocess is not used but is still useful for testing in Linux without upstart.
    pub fn new_upstart() -> ManagerStateMachine {
    // Don't remove just yet.
        ManagerStateMachine::new(Box::new(UpstartInvoker::new()))
    #[allow(dead_code)]
    pub fn new_native() -> ManagerStateMachine<NativeSubprocess> {
        ManagerStateMachine::new(NativeSubprocess::new())
    }
    }

    pub fn new_systemd() -> ManagerStateMachine {
        ManagerStateMachine::new(Box::new(SystemdInvoker::new()))
    }
    }


impl ManagerStateMachine<UpstartInvoker> {
    pub fn new_native() -> ManagerStateMachine {
    pub fn new_upstart() -> ManagerStateMachine<UpstartInvoker> {
        ManagerStateMachine::new(Box::new(NativeInvoker::new()))
        ManagerStateMachine::new(UpstartInvoker::new())
    }
    }
}
}


@@ -532,11 +560,8 @@ enum StateMachineTimeoutActions {
    Noop,
    Noop,
}
}


impl<PM> ManagerStateMachine<PM>
impl ManagerStateMachine {
where
    pub fn new(process_manager: Box<dyn ProcessManager + Send>) -> ManagerStateMachine {
    PM: ProcessManager + Send,
{
    pub fn new(process_manager: PM) -> ManagerStateMachine<PM> {
        ManagerStateMachine {
        ManagerStateMachine {
            state: Arc::new(std::sync::Mutex::new(State::Off)),
            state: Arc::new(std::sync::Mutex::new(State::Off)),
            process_manager: process_manager,
            process_manager: process_manager,
@@ -702,7 +727,7 @@ mod tests {
    fn initial_state_is_off() {
    fn initial_state_is_off() {
        tokio::runtime::Runtime::new().unwrap().block_on(async {
        tokio::runtime::Runtime::new().unwrap().block_on(async {
            let process_manager = MockProcessManager::new();
            let process_manager = MockProcessManager::new();
            let state_machine = ManagerStateMachine::new(process_manager);
            let state_machine = ManagerStateMachine::new(Box::new(process_manager));
            assert_eq!(*state_machine.state.lock().unwrap(), State::Off);
            assert_eq!(*state_machine.state.lock().unwrap(), State::Off);
        })
        })
    }
    }
@@ -711,7 +736,7 @@ mod tests {
    fn off_turnoff_should_noop() {
    fn off_turnoff_should_noop() {
        tokio::runtime::Runtime::new().unwrap().block_on(async {
        tokio::runtime::Runtime::new().unwrap().block_on(async {
            let process_manager = MockProcessManager::new();
            let process_manager = MockProcessManager::new();
            let mut state_machine = ManagerStateMachine::new(process_manager);
            let mut state_machine = ManagerStateMachine::new(Box::new(process_manager));
            state_machine.action_stop_bluetooth(0);
            state_machine.action_stop_bluetooth(0);
            assert_eq!(*state_machine.state.lock().unwrap(), State::Off);
            assert_eq!(*state_machine.state.lock().unwrap(), State::Off);
        })
        })
@@ -723,7 +748,7 @@ mod tests {
            let mut process_manager = MockProcessManager::new();
            let mut process_manager = MockProcessManager::new();
            // Expect to send start command
            // Expect to send start command
            process_manager.expect_start();
            process_manager.expect_start();
            let mut state_machine = ManagerStateMachine::new(process_manager);
            let mut state_machine = ManagerStateMachine::new(Box::new(process_manager));
            state_machine.action_start_bluetooth(0);
            state_machine.action_start_bluetooth(0);
            assert_eq!(*state_machine.state.lock().unwrap(), State::TurningOn);
            assert_eq!(*state_machine.state.lock().unwrap(), State::TurningOn);
        })
        })
@@ -735,7 +760,7 @@ mod tests {
            let mut process_manager = MockProcessManager::new();
            let mut process_manager = MockProcessManager::new();
            // Expect to send start command just once
            // Expect to send start command just once
            process_manager.expect_start();
            process_manager.expect_start();
            let mut state_machine = ManagerStateMachine::new(process_manager);
            let mut state_machine = ManagerStateMachine::new(Box::new(process_manager));
            state_machine.action_start_bluetooth(0);
            state_machine.action_start_bluetooth(0);
            assert_eq!(state_machine.action_start_bluetooth(0), false);
            assert_eq!(state_machine.action_start_bluetooth(0), false);
        })
        })
@@ -746,13 +771,25 @@ mod tests {
        tokio::runtime::Runtime::new().unwrap().block_on(async {
        tokio::runtime::Runtime::new().unwrap().block_on(async {
            let mut process_manager = MockProcessManager::new();
            let mut process_manager = MockProcessManager::new();
            process_manager.expect_start();
            process_manager.expect_start();
            let mut state_machine = ManagerStateMachine::new(process_manager);
            let mut state_machine = ManagerStateMachine::new(Box::new(process_manager));
            state_machine.action_start_bluetooth(0);
            state_machine.action_start_bluetooth(0);
            state_machine.action_on_bluetooth_started(0, 0);
            state_machine.action_on_bluetooth_started(0, 0);
            assert_eq!(*state_machine.state.lock().unwrap(), State::On);
            assert_eq!(*state_machine.state.lock().unwrap(), State::On);
        })
        })
    }
    }


    #[test]
    fn turningon_bluetooth_different_hci_started() {
        tokio::runtime::Runtime::new().unwrap().block_on(async {
            let mut process_manager = MockProcessManager::new();
            process_manager.expect_start();
            let mut state_machine = ManagerStateMachine::new(Box::new(process_manager));
            state_machine.action_start_bluetooth(1);
            state_machine.action_on_bluetooth_started(1, 1);
            assert_eq!(*state_machine.state.lock().unwrap(), State::On);
        })
    }

    #[test]
    #[test]
    fn turningon_timeout() {
    fn turningon_timeout() {
        tokio::runtime::Runtime::new().unwrap().block_on(async {
        tokio::runtime::Runtime::new().unwrap().block_on(async {
@@ -760,7 +797,7 @@ mod tests {
            process_manager.expect_start();
            process_manager.expect_start();
            process_manager.expect_stop();
            process_manager.expect_stop();
            process_manager.expect_start(); // start bluetooth again
            process_manager.expect_start(); // start bluetooth again
            let mut state_machine = ManagerStateMachine::new(process_manager);
            let mut state_machine = ManagerStateMachine::new(Box::new(process_manager));
            state_machine.action_start_bluetooth(0);
            state_machine.action_start_bluetooth(0);
            assert_eq!(
            assert_eq!(
                state_machine.action_on_command_timeout(),
                state_machine.action_on_command_timeout(),
@@ -777,7 +814,7 @@ mod tests {
            process_manager.expect_start();
            process_manager.expect_start();
            // Expect to send stop command
            // Expect to send stop command
            process_manager.expect_stop();
            process_manager.expect_stop();
            let mut state_machine = ManagerStateMachine::new(process_manager);
            let mut state_machine = ManagerStateMachine::new(Box::new(process_manager));
            state_machine.action_start_bluetooth(0);
            state_machine.action_start_bluetooth(0);
            state_machine.action_stop_bluetooth(0);
            state_machine.action_stop_bluetooth(0);
            assert_eq!(*state_machine.state.lock().unwrap(), State::Off);
            assert_eq!(*state_machine.state.lock().unwrap(), State::Off);
@@ -791,7 +828,7 @@ mod tests {
            process_manager.expect_start();
            process_manager.expect_start();
            // Expect to send stop command
            // Expect to send stop command
            process_manager.expect_stop();
            process_manager.expect_stop();
            let mut state_machine = ManagerStateMachine::new(process_manager);
            let mut state_machine = ManagerStateMachine::new(Box::new(process_manager));
            state_machine.action_start_bluetooth(0);
            state_machine.action_start_bluetooth(0);
            state_machine.action_on_bluetooth_started(0, 0);
            state_machine.action_on_bluetooth_started(0, 0);
            state_machine.action_stop_bluetooth(0);
            state_machine.action_stop_bluetooth(0);
@@ -806,7 +843,7 @@ mod tests {
            process_manager.expect_start();
            process_manager.expect_start();
            // Expect to start again
            // Expect to start again
            process_manager.expect_start();
            process_manager.expect_start();
            let mut state_machine = ManagerStateMachine::new(process_manager);
            let mut state_machine = ManagerStateMachine::new(Box::new(process_manager));
            state_machine.action_start_bluetooth(0);
            state_machine.action_start_bluetooth(0);
            state_machine.action_on_bluetooth_started(0, 0);
            state_machine.action_on_bluetooth_started(0, 0);
            assert_eq!(state_machine.action_on_bluetooth_stopped(), false);
            assert_eq!(state_machine.action_on_bluetooth_stopped(), false);
@@ -820,7 +857,7 @@ mod tests {
            let mut process_manager = MockProcessManager::new();
            let mut process_manager = MockProcessManager::new();
            process_manager.expect_start();
            process_manager.expect_start();
            process_manager.expect_stop();
            process_manager.expect_stop();
            let mut state_machine = ManagerStateMachine::new(process_manager);
            let mut state_machine = ManagerStateMachine::new(Box::new(process_manager));
            state_machine.action_start_bluetooth(0);
            state_machine.action_start_bluetooth(0);
            state_machine.action_on_bluetooth_started(0, 0);
            state_machine.action_on_bluetooth_started(0, 0);
            state_machine.action_stop_bluetooth(0);
            state_machine.action_stop_bluetooth(0);
@@ -836,7 +873,7 @@ mod tests {
            process_manager.expect_start();
            process_manager.expect_start();
            process_manager.expect_stop();
            process_manager.expect_stop();
            process_manager.expect_start();
            process_manager.expect_start();
            let mut state_machine = ManagerStateMachine::new(process_manager);
            let mut state_machine = ManagerStateMachine::new(Box::new(process_manager));
            state_machine.action_start_bluetooth(0);
            state_machine.action_start_bluetooth(0);
            state_machine.action_on_bluetooth_started(0, 0);
            state_machine.action_on_bluetooth_started(0, 0);
            state_machine.action_stop_bluetooth(0);
            state_machine.action_stop_bluetooth(0);