Loading system/gd/rust/linux/service/src/main.rs +86 −78 Original line number Diff line number Diff line Loading @@ -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. Loading Loading @@ -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())))); Loading Loading @@ -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( Loading Loading @@ -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!() Loading system/gd/rust/linux/stack/src/socket_manager.rs +33 −49 Original line number Diff line number Diff line Loading @@ -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; Loading Loading @@ -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`. Loading @@ -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()) Loading Loading @@ -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, Loading Loading @@ -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, Loading Loading @@ -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); } } } Loading Loading @@ -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"); } } Loading system/gd/rust/topshim/src/profiles/socket.rs +3 −0 Original line number Diff line number Diff line Loading @@ -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 } } } Loading Loading
system/gd/rust/linux/service/src/main.rs +86 −78 Original line number Diff line number Diff line Loading @@ -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. Loading Loading @@ -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())))); Loading Loading @@ -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( Loading Loading @@ -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!() Loading
system/gd/rust/linux/stack/src/socket_manager.rs +33 −49 Original line number Diff line number Diff line Loading @@ -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; Loading Loading @@ -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`. Loading @@ -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()) Loading Loading @@ -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, Loading Loading @@ -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, Loading Loading @@ -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); } } } Loading Loading @@ -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"); } } Loading
system/gd/rust/topshim/src/profiles/socket.rs +3 −0 Original line number Diff line number Diff line Loading @@ -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 } } } Loading