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

Commit 0bc5444a authored by Treehugger Robot's avatar Treehugger Robot Committed by Gerrit Code Review
Browse files

Merge "floss: Refactor btstack initialization order (1/4 SocketManager)" into main

parents 012702d7 c2920684
Loading
Loading
Loading
Loading
+86 −78
Original line number Diff line number Diff line
@@ -7,6 +7,7 @@ use nix::sys::signal;
use std::error::Error;
use std::sync::{Arc, Condvar, Mutex};
use std::time::Duration;
use tokio::runtime::Builder;
use tokio::sync::mpsc::Sender;

// Necessary to link right entries.
@@ -129,6 +130,42 @@ fn main() -> Result<(), Box<dyn Error>> {
        thread_notify: Condvar::new(),
    });

    // This needs to be built before any |topstack::get_runtime()| call!
    let bt_sock_mgr_runtime = Arc::new(
        Builder::new_multi_thread()
            .worker_threads(1)
            .max_blocking_threads(1)
            .enable_all()
            .build()
            .expect("Failed to make socket runtime."),
    );

    topstack::get_runtime().block_on(async {
        // Connect to D-Bus system bus.
        let (resource, conn) = connection::new_system_sync()?;

        // The `resource` is a task that should be spawned onto a tokio compatible
        // reactor ASAP. If the resource ever finishes, we lost connection to D-Bus.
        let conn_join_handle = tokio::spawn(async {
            let err = resource.await;
            panic!("Lost connection to D-Bus: {}", err);
        });

        // Request a service name and quit if not able to.
        conn.request_name(DBUS_SERVICE_NAME, false, true, false).await?;

        // Install SIGTERM handler so that we can properly shutdown
        *SIG_DATA.lock().unwrap() = Some((tx.clone(), sig_notifier.clone()));
        let sig_action_term = signal::SigAction::new(
            signal::SigHandler::Handler(handle_sigterm),
            signal::SaFlags::empty(),
            signal::SigSet::empty(),
        );
        unsafe {
            signal::sigaction(signal::SIGTERM, &sig_action_term).unwrap();
        }

        // Construct btstack profiles.
        let intf = Arc::new(Mutex::new(get_btinterface().unwrap()));
        let bluetooth_gatt =
            Arc::new(Mutex::new(Box::new(BluetoothGatt::new(intf.clone(), tx.clone()))));
@@ -171,28 +208,27 @@ fn main() -> Result<(), Box<dyn Error>> {
            bluetooth_media.clone(),
            tx.clone(),
        ))));
    let bt_sock_mgr = Arc::new(Mutex::new(Box::new(BluetoothSocketManager::new(
        let bluetooth_qa = Arc::new(Mutex::new(Box::new(BluetoothQA::new(tx.clone()))));
        let dis = Arc::new(Mutex::new(Box::new(DeviceInformation::new(
            bluetooth_gatt.clone(),
            tx.clone(),
        bluetooth_admin.clone(),
        ))));
    let bluetooth_qa = Arc::new(Mutex::new(Box::new(BluetoothQA::new(tx.clone()))));

    let dis =
        Arc::new(Mutex::new(Box::new(DeviceInformation::new(bluetooth_gatt.clone(), tx.clone()))));
        bluetooth_media.lock().unwrap().set_adapter(bluetooth.clone());
        bluetooth_admin.lock().unwrap().set_adapter(bluetooth.clone());

    topstack::get_runtime().block_on(async {
        // Connect to D-Bus system bus.
        let (resource, conn) = connection::new_system_sync()?;
        bluetooth.lock().unwrap().init(init_flags, hci_index);
        bluetooth.lock().unwrap().enable();

        // The `resource` is a task that should be spawned onto a tokio compatible
        // reactor ASAP. If the resource ever finishes, we lost connection to D-Bus.
        let conn_join_handle = tokio::spawn(async {
            let err = resource.await;
            panic!("Lost connection to D-Bus: {}", err);
        });
        bluetooth_gatt.lock().unwrap().init_profiles(tx.clone(), api_tx.clone());

        // Request a service name and quit if not able to.
        conn.request_name(DBUS_SERVICE_NAME, false, true, false).await?;
        // This construction requires |intf| to be already init-ed.
        let bt_sock_mgr = Arc::new(Mutex::new(Box::new(BluetoothSocketManager::new(
            tx.clone(),
            bt_sock_mgr_runtime,
            intf.clone(),
            bluetooth_admin.clone(),
        ))));

        // Run the stack main dispatch loop.
        topstack::get_runtime().spawn(Stack::dispatch(
@@ -237,34 +273,6 @@ fn main() -> Result<(), Box<dyn Error>> {
            logging.clone(),
        ));

        // Hold locks and initialize all interfaces. This must be done AFTER DBus is
        // initialized so DBus can properly enforce user policies.
        {
            let adapter = bluetooth.clone();
            bluetooth_media.lock().unwrap().set_adapter(adapter.clone());
            bluetooth_admin.lock().unwrap().set_adapter(adapter.clone());

            let mut bluetooth = bluetooth.lock().unwrap();
            bluetooth.init(init_flags, hci_index);
            bluetooth.enable();

            bluetooth_gatt.lock().unwrap().init_profiles(tx.clone(), api_tx.clone());
            bt_sock_mgr.lock().unwrap().initialize(intf.clone());

            // Install SIGTERM handler so that we can properly shutdown
            *SIG_DATA.lock().unwrap() = Some((tx.clone(), sig_notifier.clone()));

            let sig_action_term = signal::SigAction::new(
                signal::SigHandler::Handler(handle_sigterm),
                signal::SaFlags::empty(),
                signal::SigSet::empty(),
            );

            unsafe {
                signal::sigaction(signal::SIGTERM, &sig_action_term).unwrap();
            }
        }

        // Serve clients forever.
        future::pending::<()>().await;
        unreachable!()
+33 −49
Original line number Diff line number Diff line
@@ -15,7 +15,7 @@ use std::os::unix::io::{AsRawFd, FromRawFd, IntoRawFd, RawFd};
use std::sync::{Arc, Mutex};
use std::time::Duration;
use tokio::net::UnixStream;
use tokio::runtime::{Builder, Runtime};
use tokio::runtime::Runtime;
use tokio::sync::mpsc::{channel, Receiver, Sender};
use tokio::task::JoinHandle;
use tokio::time;
@@ -507,7 +507,7 @@ pub struct BluetoothSocketManager {
    runtime: Arc<Runtime>,

    /// Topshim interface for socket. Must call initialize for this to be valid.
    sock: Option<socket::BtSocket>,
    sock: socket::BtSocket,

    /// Monotonically increasing counter for socket id. Always access using
    /// `next_socket_id`.
@@ -522,39 +522,29 @@ pub struct BluetoothSocketManager {

impl BluetoothSocketManager {
    /// Constructs the IBluetooth implementation.
    pub fn new(tx: Sender<Message>, admin: Arc<Mutex<Box<BluetoothAdmin>>>) -> Self {
    pub fn new(
        tx: Sender<Message>,
        runtime: Arc<Runtime>,
        intf: Arc<Mutex<BluetoothInterface>>,
        admin: Arc<Mutex<Box<BluetoothAdmin>>>,
    ) -> Self {
        let callbacks = Callbacks::new(tx.clone(), Message::SocketManagerCallbackDisconnected);
        let socket_counter: u64 = 1000;
        let connecting = HashMap::new();
        let listening = HashMap::new();
        let runtime = Arc::new(
            Builder::new_multi_thread()
                .worker_threads(1)
                .max_blocking_threads(1)
                .enable_all()
                .build()
                .expect("Failed to make socket runtime."),
        );

        BluetoothSocketManager {
            callbacks,
            connecting,
            listening,
            runtime,
            sock: None,
            sock: socket::BtSocket::new(&intf.lock().unwrap()),
            socket_counter,
            tx,
            admin,
        }
    }

    /// In order to access the underlying socket apis, we must initialize after
    /// the btif layer has initialized. Thus, this must be called after intf is
    /// init.
    pub fn initialize(&mut self, intf: Arc<Mutex<BluetoothInterface>>) {
        self.sock = Some(socket::BtSocket::new(&intf.lock().unwrap()));
    }

    /// Check if there is any listening socket.
    pub fn is_listening(&self) -> bool {
        self.listening.values().any(|vs| !vs.is_empty())
@@ -605,8 +595,7 @@ impl BluetoothSocketManager {
        }

        // Create listener socket pair
        let (mut status, result) =
            self.sock.as_ref().expect("Socket Manager not initialized").listen(
        let (mut status, result) = self.sock.listen(
            socket_info.sock_type.clone(),
            socket_info.name.as_ref().unwrap_or(&String::new()).clone(),
            socket_info.uuid,
@@ -696,8 +685,7 @@ impl BluetoothSocketManager {
        }

        // Create connecting socket pair.
        let (mut status, result) =
            self.sock.as_ref().expect("Socket manager not initialized").connect(
        let (mut status, result) = self.sock.connect(
            socket_info.remote_device.address,
            socket_info.sock_type.clone(),
            socket_info.uuid,
@@ -1190,7 +1178,7 @@ impl BluetoothSocketManager {
            }

            SocketActions::DisconnectAll(addr) => {
                self.sock.as_ref().expect("Socket Manager not initialized").disconnect_all(addr);
                self.sock.disconnect_all(addr);
            }
        }
    }
@@ -1251,11 +1239,7 @@ impl BluetoothSocketManager {
    // libbluetooth auto starts the control request only when it is the client.
    // This function allows the host to start the control request while as a server.
    pub fn rfcomm_send_msc(&mut self, dlci: u8, addr: RawAddress) {
        let Some(sock) = self.sock.as_ref() else {
            log::warn!("Socket Manager not initialized when starting control request");
            return;
        };
        if sock.send_msc(dlci, addr) != BtStatus::Success {
        if self.sock.send_msc(dlci, addr) != BtStatus::Success {
            log::warn!("Failed to start control request");
        }
    }
+3 −0
Original line number Diff line number Diff line
@@ -140,6 +140,9 @@ pub fn try_from_fd(fd: i32) -> Result<File, FdError> {
impl BtSocket {
    pub fn new(intf: &BluetoothInterface) -> Self {
        let r = intf.get_profile_interface(SupportedProfiles::Socket);
        if r.is_null() {
            panic!("Failed to get Socket interface");
        }
        BtSocket { internal: RawBtSockWrapper { raw: r as *const bindings::btsock_interface_t } }
    }