Loading system/gd/rust/linux/stack/src/bluetooth.rs +31 −78 Original line number Original line Diff line number Diff line Loading @@ -25,8 +25,9 @@ use tokio::task::JoinHandle; use tokio::time; use tokio::time; use crate::bluetooth_media::{BluetoothMedia, IBluetoothMedia, MediaActions}; use crate::bluetooth_media::{BluetoothMedia, IBluetoothMedia, MediaActions}; use crate::callbacks::Callbacks; use crate::uuid::{Profile, UuidHelper}; use crate::uuid::{Profile, UuidHelper}; use crate::{BluetoothCallbackType, Message, RPCProxy}; use crate::{Message, RPCProxy}; const DEFAULT_DISCOVERY_TIMEOUT_MS: u64 = 12800; const DEFAULT_DISCOVERY_TIMEOUT_MS: u64 = 12800; const MIN_ADV_INSTANCES_FOR_MULTI_ADV: u8 = 5; const MIN_ADV_INSTANCES_FOR_MULTI_ADV: u8 = 5; Loading Loading @@ -299,8 +300,8 @@ pub struct Bluetooth { bonded_devices: HashMap<String, BluetoothDeviceContext>, bonded_devices: HashMap<String, BluetoothDeviceContext>, bluetooth_media: Arc<Mutex<Box<BluetoothMedia>>>, bluetooth_media: Arc<Mutex<Box<BluetoothMedia>>>, callbacks: HashMap<u32, Box<dyn IBluetoothCallback + Send>>, callbacks: Callbacks<dyn IBluetoothCallback + Send>, connection_callbacks: HashMap<u32, Box<dyn IBluetoothConnectionCallback + Send>>, connection_callbacks: Callbacks<dyn IBluetoothConnectionCallback + Send>, discovering_started: Instant, discovering_started: Instant, hh: Option<HidHost>, hh: Option<HidHost>, is_connectable: bool, is_connectable: bool, Loading @@ -327,8 +328,11 @@ impl Bluetooth { ) -> Bluetooth { ) -> Bluetooth { Bluetooth { Bluetooth { bonded_devices: HashMap::new(), bonded_devices: HashMap::new(), callbacks: HashMap::new(), callbacks: Callbacks::new(tx.clone(), Message::AdapterCallbackDisconnected), connection_callbacks: HashMap::new(), connection_callbacks: Callbacks::new( tx.clone(), Message::ConnectionCallbackDisconnected, ), hh: None, hh: None, bluetooth_media, bluetooth_media, discovering_started: Instant::now(), discovering_started: Instant::now(), Loading Loading @@ -378,26 +382,11 @@ impl Bluetooth { fn update_local_address(&mut self, addr: &RawAddress) { fn update_local_address(&mut self, addr: &RawAddress) { self.local_address = Some(*addr); self.local_address = Some(*addr); self.for_all_callbacks(|callback| { self.callbacks.for_all_callbacks(|callback| { callback.on_address_changed(self.local_address.unwrap().to_string()); callback.on_address_changed(self.local_address.unwrap().to_string()); }); }); } } fn for_all_callbacks<F: Fn(&Box<dyn IBluetoothCallback + Send>)>(&self, f: F) { for (_, callback) in self.callbacks.iter() { f(&callback); } } fn for_all_connection_callbacks<F: Fn(&Box<dyn IBluetoothConnectionCallback + Send>)>( &self, f: F, ) { for (_, callback) in self.connection_callbacks.iter() { f(&callback); } } pub fn get_connectable(&self) -> bool { pub fn get_connectable(&self) -> bool { match self.properties.get(&BtPropertyType::AdapterScanMode) { match self.properties.get(&BtPropertyType::AdapterScanMode) { Some(prop) => match prop { Some(prop) => match prop { Loading @@ -421,15 +410,12 @@ impl Bluetooth { )) == 0 )) == 0 } } pub(crate) fn callback_disconnected(&mut self, id: u32, cb_type: BluetoothCallbackType) { pub(crate) fn adapter_callback_disconnected(&mut self, id: u32) { match cb_type { self.callbacks.remove_callback(id); BluetoothCallbackType::Adapter => { self.callbacks.remove(&id); } } BluetoothCallbackType::Connection => { self.connection_callbacks.remove(&id); pub(crate) fn connection_callback_disconnected(&mut self, id: u32) { } self.connection_callbacks.remove_callback(id); }; } } fn get_remote_device_if_found(&self, address: &str) -> Option<&BluetoothDeviceContext> { fn get_remote_device_if_found(&self, address: &str) -> Option<&BluetoothDeviceContext> { Loading Loading @@ -506,7 +492,7 @@ impl Bluetooth { self.found_devices.retain(|_, d| is_fresh(d, &now)); self.found_devices.retain(|_, d| is_fresh(d, &now)); for d in stale_devices { for d in stale_devices { self.for_all_callbacks(|callback| { self.callbacks.for_all_callbacks(|callback| { callback.on_device_cleared(d.clone()); callback.on_device_cleared(d.clone()); }); }); } } Loading Loading @@ -669,12 +655,12 @@ impl BtifBluetoothCallbacks for Bluetooth { } } } } BluetoothProperty::BdName(bdname) => { BluetoothProperty::BdName(bdname) => { self.for_all_callbacks(|callback| { self.callbacks.for_all_callbacks(|callback| { callback.on_name_changed(bdname.clone()); callback.on_name_changed(bdname.clone()); }); }); } } BluetoothProperty::AdapterScanMode(mode) => { BluetoothProperty::AdapterScanMode(mode) => { self.for_all_callbacks(|callback| { self.callbacks.for_all_callbacks(|callback| { callback callback .on_discoverable_changed(*mode == BtScanMode::ConnectableDiscoverable); .on_discoverable_changed(*mode == BtScanMode::ConnectableDiscoverable); }); }); Loading @@ -684,7 +670,7 @@ impl BtifBluetoothCallbacks for Bluetooth { self.properties.insert(prop.get_type(), prop.clone()); self.properties.insert(prop.get_type(), prop.clone()); self.for_all_callbacks(|callback| { self.callbacks.for_all_callbacks(|callback| { callback.on_adapter_property_changed(prop.get_type()); callback.on_adapter_property_changed(prop.get_type()); }); }); } } Loading @@ -710,7 +696,7 @@ impl BtifBluetoothCallbacks for Bluetooth { let device = self.found_devices.get(&address).unwrap(); let device = self.found_devices.get(&address).unwrap(); self.for_all_callbacks(|callback| { self.callbacks.for_all_callbacks(|callback| { callback.on_device_found(device.info.clone()); callback.on_device_found(device.info.clone()); }); }); } } Loading @@ -729,7 +715,7 @@ impl BtifBluetoothCallbacks for Bluetooth { self.discovering_started = Instant::now(); self.discovering_started = Instant::now(); } } self.for_all_callbacks(|callback| { self.callbacks.for_all_callbacks(|callback| { callback.on_discovering_changed(state == BtDiscoveryState::Started); callback.on_discovering_changed(state == BtDiscoveryState::Started); }); }); Loading @@ -751,7 +737,7 @@ impl BtifBluetoothCallbacks for Bluetooth { ) { ) { // Currently this supports many agent because we accept many callbacks. // Currently this supports many agent because we accept many callbacks. // TODO: We need a way to select the default agent. // TODO: We need a way to select the default agent. self.for_all_callbacks(|callback| { self.callbacks.for_all_callbacks(|callback| { callback.on_ssp_request( callback.on_ssp_request( BluetoothDevice::new(remote_addr.to_string(), remote_name.clone()), BluetoothDevice::new(remote_addr.to_string(), remote_name.clone()), cod, cod, Loading Loading @@ -806,7 +792,7 @@ impl BtifBluetoothCallbacks for Bluetooth { } } // Send bond state changed notifications // Send bond state changed notifications self.for_all_callbacks(|callback| { self.callbacks.for_all_callbacks(|callback| { callback.on_bond_state_changed( callback.on_bond_state_changed( status.to_u32().unwrap(), status.to_u32().unwrap(), address.clone(), address.clone(), Loading Loading @@ -898,12 +884,12 @@ impl BtifBluetoothCallbacks for Bluetooth { match state { match state { BtAclState::Connected => { BtAclState::Connected => { self.for_all_connection_callbacks(|callback| { self.connection_callbacks.for_all_callbacks(|callback| { callback.on_device_connected(device.clone()); callback.on_device_connected(device.clone()); }); }); } } BtAclState::Disconnected => { BtAclState::Disconnected => { self.for_all_connection_callbacks(|callback| { self.connection_callbacks.for_all_callbacks(|callback| { callback.on_device_disconnected(device.clone()); callback.on_device_disconnected(device.clone()); }); }); } } Loading @@ -917,52 +903,19 @@ impl BtifBluetoothCallbacks for Bluetooth { // TODO: Add unit tests for this implementation // TODO: Add unit tests for this implementation impl IBluetooth for Bluetooth { impl IBluetooth for Bluetooth { fn register_callback(&mut self, mut callback: Box<dyn IBluetoothCallback + Send>) { fn register_callback(&mut self, callback: Box<dyn IBluetoothCallback + Send>) { let tx = self.tx.clone(); self.callbacks.add_callback(callback); let id = callback.register_disconnect(Box::new(move |cb_id| { let tx = tx.clone(); tokio::spawn(async move { let _result = tx .send(Message::BluetoothCallbackDisconnected( cb_id, BluetoothCallbackType::Adapter, )) .await; }); })); self.callbacks.insert(id, callback); } } fn register_connection_callback( fn register_connection_callback( &mut self, &mut self, mut callback: Box<dyn IBluetoothConnectionCallback + Send>, callback: Box<dyn IBluetoothConnectionCallback + Send>, ) -> u32 { ) -> u32 { let tx = self.tx.clone(); self.connection_callbacks.add_callback(callback) let id = callback.register_disconnect(Box::new(move |cb_id| { let tx = tx.clone(); tokio::spawn(async move { let _ = tx .send(Message::BluetoothCallbackDisconnected( cb_id, BluetoothCallbackType::Connection, )) .await; }); })); self.connection_callbacks.insert(id, callback); id } } fn unregister_connection_callback(&mut self, callback_id: u32) -> bool { fn unregister_connection_callback(&mut self, callback_id: u32) -> bool { match self.connection_callbacks.get_mut(&callback_id) { self.connection_callbacks.remove_callback(callback_id) Some(cb) => cb.unregister(callback_id), None => false, } } } fn enable(&mut self) -> bool { fn enable(&mut self) -> bool { Loading system/gd/rust/linux/stack/src/bluetooth_media.rs +21 −22 Original line number Original line Diff line number Diff line Loading @@ -25,7 +25,8 @@ use tokio::task::JoinHandle; use tokio::time::{sleep, Duration}; use tokio::time::{sleep, Duration}; use crate::bluetooth::{Bluetooth, BluetoothDevice, IBluetooth}; use crate::bluetooth::{Bluetooth, BluetoothDevice, IBluetooth}; use crate::Message; use crate::callbacks::Callbacks; use crate::{Message, RPCProxy}; const DEFAULT_PROFILE_DISCOVERY_TIMEOUT_SEC: u64 = 5; const DEFAULT_PROFILE_DISCOVERY_TIMEOUT_SEC: u64 = 5; Loading Loading @@ -64,7 +65,7 @@ pub trait IBluetoothMedia { fn stop_sco_call(&mut self, address: String); fn stop_sco_call(&mut self, address: String); } } pub trait IBluetoothMediaCallback { pub trait IBluetoothMediaCallback: RPCProxy { /// Triggered when a Bluetooth audio device is ready to be used. This should /// Triggered when a Bluetooth audio device is ready to be used. This should /// only be triggered once for a device and send an event to clients. If the /// only be triggered once for a device and send an event to clients. If the /// device supports both HFP and A2DP, both should be ready when this is /// device supports both HFP and A2DP, both should be ready when this is Loading Loading @@ -119,8 +120,7 @@ pub enum MediaActions { pub struct BluetoothMedia { pub struct BluetoothMedia { intf: Arc<Mutex<BluetoothInterface>>, intf: Arc<Mutex<BluetoothInterface>>, initialized: bool, initialized: bool, callbacks: Arc<Mutex<Vec<(u32, Box<dyn IBluetoothMediaCallback + Send>)>>>, callbacks: Arc<Mutex<Callbacks<dyn IBluetoothMediaCallback + Send>>>, callback_last_id: u32, tx: Sender<Message>, tx: Sender<Message>, adapter: Option<Arc<Mutex<Box<Bluetooth>>>>, adapter: Option<Arc<Mutex<Box<Bluetooth>>>>, a2dp: Option<A2dp>, a2dp: Option<A2dp>, Loading @@ -139,8 +139,10 @@ impl BluetoothMedia { BluetoothMedia { BluetoothMedia { intf, intf, initialized: false, initialized: false, callbacks: Arc::new(Mutex::new(vec![])), callbacks: Arc::new(Mutex::new(Callbacks::new( callback_last_id: 0, tx.clone(), Message::MediaCallbackDisconnected, ))), tx, tx, adapter: None, adapter: None, a2dp: None, a2dp: None, Loading Loading @@ -196,12 +198,12 @@ impl BluetoothMedia { match cb { match cb { AvrcpCallbacks::AvrcpAbsoluteVolumeEnabled(supported) => { AvrcpCallbacks::AvrcpAbsoluteVolumeEnabled(supported) => { self.absolute_volume = supported; self.absolute_volume = supported; self.for_all_callbacks(|callback| { self.callbacks.lock().unwrap().for_all_callbacks(|callback| { callback.on_absolute_volume_supported_changed(supported); callback.on_absolute_volume_supported_changed(supported); }); }); } } AvrcpCallbacks::AvrcpAbsoluteVolumeUpdate(volume) => { AvrcpCallbacks::AvrcpAbsoluteVolumeUpdate(volume) => { self.for_all_callbacks(|callback| { self.callbacks.lock().unwrap().for_all_callbacks(|callback| { callback.on_absolute_volume_changed(volume); callback.on_absolute_volume_changed(volume); }); }); } } Loading Loading @@ -279,27 +281,31 @@ impl BluetoothMedia { } } } } HfpCallbacks::VolumeUpdate(volume, addr) => { HfpCallbacks::VolumeUpdate(volume, addr) => { self.for_all_callbacks(|callback| { self.callbacks.lock().unwrap().for_all_callbacks(|callback| { callback.on_hfp_volume_changed(volume, addr.to_string()); callback.on_hfp_volume_changed(volume, addr.to_string()); }); }); } } } } } } pub fn remove_callback(&mut self, id: u32) -> bool { self.callbacks.lock().unwrap().remove_callback(id) } fn notify_media_capability_added(&self, addr: RawAddress) { fn notify_media_capability_added(&self, addr: RawAddress) { // Return true if the device added message is sent by the call. // Return true if the device added message is sent by the call. fn dedup_added_cb( fn dedup_added_cb( device_added_tasks: Arc<Mutex<HashMap<RawAddress, Option<JoinHandle<()>>>>>, device_added_tasks: Arc<Mutex<HashMap<RawAddress, Option<JoinHandle<()>>>>>, addr: RawAddress, addr: RawAddress, callbacks: Arc<Mutex<Vec<(u32, Box<dyn IBluetoothMediaCallback + Send>)>>>, callbacks: Arc<Mutex<Callbacks<dyn IBluetoothMediaCallback + Send>>>, device: BluetoothAudioDevice, device: BluetoothAudioDevice, is_delayed: bool, is_delayed: bool, ) -> bool { ) -> bool { // Closure used to lock and trigger the device added callbacks. // Closure used to lock and trigger the device added callbacks. let trigger_device_added = || { let trigger_device_added = || { for callback in &*callbacks.lock().unwrap() { callbacks.lock().unwrap().for_all_callbacks(|callback| { callback.1.on_bluetooth_audio_device_added(device.clone()); callback.on_bluetooth_audio_device_added(device.clone()); } }); }; }; let mut guard = device_added_tasks.lock().unwrap(); let mut guard = device_added_tasks.lock().unwrap(); let task = guard.insert(addr, None); let task = guard.insert(addr, None); Loading Loading @@ -390,7 +396,7 @@ impl BluetoothMedia { // Abort what is pending // Abort what is pending Some(handler) => handler.abort(), Some(handler) => handler.abort(), // This addr has been added so tell audio server to remove it // This addr has been added so tell audio server to remove it None => self.for_all_callbacks(|callback| { None => self.callbacks.lock().unwrap().for_all_callbacks(|callback| { callback.on_bluetooth_audio_device_removed(addr.to_string()); callback.on_bluetooth_audio_device_removed(addr.to_string()); }), }), } } Loading @@ -399,12 +405,6 @@ impl BluetoothMedia { } } } } fn for_all_callbacks<F: Fn(&Box<dyn IBluetoothMediaCallback + Send>)>(&self, f: F) { for callback in &*self.callbacks.lock().unwrap() { f(&callback.1); } } fn adapter_get_remote_name(&self, addr: RawAddress) -> String { fn adapter_get_remote_name(&self, addr: RawAddress) -> String { let device = BluetoothDevice::new( let device = BluetoothDevice::new( addr.to_string(), addr.to_string(), Loading Loading @@ -472,8 +472,7 @@ fn get_hfp_dispatcher(tx: Sender<Message>) -> HfpCallbacksDispatcher { impl IBluetoothMedia for BluetoothMedia { impl IBluetoothMedia for BluetoothMedia { fn register_callback(&mut self, callback: Box<dyn IBluetoothMediaCallback + Send>) -> bool { fn register_callback(&mut self, callback: Box<dyn IBluetoothMediaCallback + Send>) -> bool { self.callback_last_id += 1; let _id = self.callbacks.lock().unwrap().add_callback(callback); self.callbacks.lock().unwrap().push((self.callback_last_id, callback)); true true } } Loading system/gd/rust/linux/stack/src/lib.rs +13 −9 Original line number Original line Diff line number Diff line Loading @@ -31,12 +31,6 @@ use bt_topshim::{ }, }, }; }; #[derive(Clone, Debug)] pub enum BluetoothCallbackType { Adapter, Connection, } /// Message types that are sent to the stack main dispatch loop. /// Message types that are sent to the stack main dispatch loop. pub enum Message { pub enum Message { // Callbacks from libbluetooth // Callbacks from libbluetooth Loading @@ -51,9 +45,11 @@ pub enum Message { // Actions within the stack // Actions within the stack Media(MediaActions), Media(MediaActions), MediaCallbackDisconnected(u32), // Client callback disconnections // Client callback disconnections BluetoothCallbackDisconnected(u32, BluetoothCallbackType), AdapterCallbackDisconnected(u32), ConnectionCallbackDisconnected(u32), // Update list of found devices and remove old instances. // Update list of found devices and remove old instances. DeviceFreshnessCheck, DeviceFreshnessCheck, Loading Loading @@ -130,8 +126,16 @@ impl Stack { bluetooth_media.lock().unwrap().dispatch_media_actions(action); bluetooth_media.lock().unwrap().dispatch_media_actions(action); } } Message::BluetoothCallbackDisconnected(id, cb_type) => { Message::MediaCallbackDisconnected(cb_id) => { bluetooth.lock().unwrap().callback_disconnected(id, cb_type); bluetooth_media.lock().unwrap().remove_callback(cb_id); } Message::AdapterCallbackDisconnected(id) => { bluetooth.lock().unwrap().adapter_callback_disconnected(id); } Message::ConnectionCallbackDisconnected(id) => { bluetooth.lock().unwrap().connection_callback_disconnected(id); } } Message::DeviceFreshnessCheck => { Message::DeviceFreshnessCheck => { Loading system/gd/rust/linux/stack/src/suspend.rs +10 −31 Original line number Original line Diff line number Diff line //! Suspend/Resume API. //! Suspend/Resume API. use crate::callbacks::Callbacks; use crate::{Message, RPCProxy}; use crate::{Message, RPCProxy}; use bt_topshim::btif::BluetoothInterface; use bt_topshim::btif::BluetoothInterface; use log::warn; use log::warn; use std::collections::HashMap; use std::sync::{Arc, Mutex}; use std::sync::{Arc, Mutex}; use tokio::sync::mpsc::Sender; use tokio::sync::mpsc::Sender; Loading Loading @@ -60,7 +60,7 @@ pub enum SuspendType { pub struct Suspend { pub struct Suspend { intf: Arc<Mutex<BluetoothInterface>>, intf: Arc<Mutex<BluetoothInterface>>, tx: Sender<Message>, tx: Sender<Message>, callbacks: HashMap<u32, Box<dyn ISuspendCallback + Send>>, callbacks: Callbacks<dyn ISuspendCallback + Send>, is_connected_suspend: bool, is_connected_suspend: bool, was_a2dp_connected: bool, was_a2dp_connected: bool, } } Loading @@ -69,55 +69,34 @@ impl Suspend { pub fn new(intf: Arc<Mutex<BluetoothInterface>>, tx: Sender<Message>) -> Suspend { pub fn new(intf: Arc<Mutex<BluetoothInterface>>, tx: Sender<Message>) -> Suspend { Self { Self { intf: intf, intf: intf, tx, tx: tx.clone(), callbacks: HashMap::new(), callbacks: Callbacks::new(tx.clone(), Message::SuspendCallbackDisconnected), is_connected_suspend: false, is_connected_suspend: false, was_a2dp_connected: false, was_a2dp_connected: false, } } } } pub(crate) fn callback_registered(&mut self, id: u32) { pub(crate) fn callback_registered(&mut self, id: u32) { match self.callbacks.get(&id) { match self.callbacks.get_by_id(id) { Some(callback) => callback.on_callback_registered(id), Some(callback) => callback.on_callback_registered(id), None => warn!("Suspend callback {} does not exist", id), None => warn!("Suspend callback {} does not exist", id), } } } } pub(crate) fn remove_callback(&mut self, id: u32) -> bool { pub(crate) fn remove_callback(&mut self, id: u32) -> bool { match self.callbacks.get_mut(&id) { self.callbacks.remove_callback(id) Some(callback) => { callback.unregister(id); self.callbacks.remove(&id); true } None => false, } } fn for_all_callbacks<F: Fn(&Box<dyn ISuspendCallback + Send>)>(&self, f: F) { for (_, callback) in self.callbacks.iter() { f(&callback); } } } } } impl ISuspend for Suspend { impl ISuspend for Suspend { fn register_callback(&mut self, mut callback: Box<dyn ISuspendCallback + Send>) -> bool { fn register_callback(&mut self, callback: Box<dyn ISuspendCallback + Send>) -> bool { let tx = self.tx.clone(); let id = self.callbacks.add_callback(callback); let id = callback.register_disconnect(Box::new(move |cb_id| { let tx = tx.clone(); tokio::spawn(async move { let _result = tx.send(Message::SuspendCallbackDisconnected(cb_id)).await; }); })); let tx = self.tx.clone(); let tx = self.tx.clone(); tokio::spawn(async move { tokio::spawn(async move { let _result = tx.send(Message::SuspendCallbackRegistered(id)).await; let _result = tx.send(Message::SuspendCallbackRegistered(id)).await; }); }); self.callbacks.insert(id, callback); true true } } Loading Loading @@ -147,7 +126,7 @@ impl ISuspend for Suspend { self.intf.lock().unwrap().clear_filter_accept_list(); self.intf.lock().unwrap().clear_filter_accept_list(); // TODO(231435700): self.intf.lock().unwrap().disconnect_all_acls(); // TODO(231435700): self.intf.lock().unwrap().disconnect_all_acls(); self.intf.lock().unwrap().le_rand(); self.intf.lock().unwrap().le_rand(); self.for_all_callbacks(|callback| { self.callbacks.for_all_callbacks(|callback| { callback.on_suspend_ready(suspend_id); callback.on_suspend_ready(suspend_id); }); }); return 1; return 1; Loading @@ -165,7 +144,7 @@ impl ISuspend for Suspend { // TODO(224603198): start all advertising again // TODO(224603198): start all advertising again } } self.intf.lock().unwrap().le_rand(); self.intf.lock().unwrap().le_rand(); self.for_all_callbacks(|callback| { self.callbacks.for_all_callbacks(|callback| { callback.on_resumed(suspend_id); callback.on_resumed(suspend_id); }); }); return true; return true; Loading Loading
system/gd/rust/linux/stack/src/bluetooth.rs +31 −78 Original line number Original line Diff line number Diff line Loading @@ -25,8 +25,9 @@ use tokio::task::JoinHandle; use tokio::time; use tokio::time; use crate::bluetooth_media::{BluetoothMedia, IBluetoothMedia, MediaActions}; use crate::bluetooth_media::{BluetoothMedia, IBluetoothMedia, MediaActions}; use crate::callbacks::Callbacks; use crate::uuid::{Profile, UuidHelper}; use crate::uuid::{Profile, UuidHelper}; use crate::{BluetoothCallbackType, Message, RPCProxy}; use crate::{Message, RPCProxy}; const DEFAULT_DISCOVERY_TIMEOUT_MS: u64 = 12800; const DEFAULT_DISCOVERY_TIMEOUT_MS: u64 = 12800; const MIN_ADV_INSTANCES_FOR_MULTI_ADV: u8 = 5; const MIN_ADV_INSTANCES_FOR_MULTI_ADV: u8 = 5; Loading Loading @@ -299,8 +300,8 @@ pub struct Bluetooth { bonded_devices: HashMap<String, BluetoothDeviceContext>, bonded_devices: HashMap<String, BluetoothDeviceContext>, bluetooth_media: Arc<Mutex<Box<BluetoothMedia>>>, bluetooth_media: Arc<Mutex<Box<BluetoothMedia>>>, callbacks: HashMap<u32, Box<dyn IBluetoothCallback + Send>>, callbacks: Callbacks<dyn IBluetoothCallback + Send>, connection_callbacks: HashMap<u32, Box<dyn IBluetoothConnectionCallback + Send>>, connection_callbacks: Callbacks<dyn IBluetoothConnectionCallback + Send>, discovering_started: Instant, discovering_started: Instant, hh: Option<HidHost>, hh: Option<HidHost>, is_connectable: bool, is_connectable: bool, Loading @@ -327,8 +328,11 @@ impl Bluetooth { ) -> Bluetooth { ) -> Bluetooth { Bluetooth { Bluetooth { bonded_devices: HashMap::new(), bonded_devices: HashMap::new(), callbacks: HashMap::new(), callbacks: Callbacks::new(tx.clone(), Message::AdapterCallbackDisconnected), connection_callbacks: HashMap::new(), connection_callbacks: Callbacks::new( tx.clone(), Message::ConnectionCallbackDisconnected, ), hh: None, hh: None, bluetooth_media, bluetooth_media, discovering_started: Instant::now(), discovering_started: Instant::now(), Loading Loading @@ -378,26 +382,11 @@ impl Bluetooth { fn update_local_address(&mut self, addr: &RawAddress) { fn update_local_address(&mut self, addr: &RawAddress) { self.local_address = Some(*addr); self.local_address = Some(*addr); self.for_all_callbacks(|callback| { self.callbacks.for_all_callbacks(|callback| { callback.on_address_changed(self.local_address.unwrap().to_string()); callback.on_address_changed(self.local_address.unwrap().to_string()); }); }); } } fn for_all_callbacks<F: Fn(&Box<dyn IBluetoothCallback + Send>)>(&self, f: F) { for (_, callback) in self.callbacks.iter() { f(&callback); } } fn for_all_connection_callbacks<F: Fn(&Box<dyn IBluetoothConnectionCallback + Send>)>( &self, f: F, ) { for (_, callback) in self.connection_callbacks.iter() { f(&callback); } } pub fn get_connectable(&self) -> bool { pub fn get_connectable(&self) -> bool { match self.properties.get(&BtPropertyType::AdapterScanMode) { match self.properties.get(&BtPropertyType::AdapterScanMode) { Some(prop) => match prop { Some(prop) => match prop { Loading @@ -421,15 +410,12 @@ impl Bluetooth { )) == 0 )) == 0 } } pub(crate) fn callback_disconnected(&mut self, id: u32, cb_type: BluetoothCallbackType) { pub(crate) fn adapter_callback_disconnected(&mut self, id: u32) { match cb_type { self.callbacks.remove_callback(id); BluetoothCallbackType::Adapter => { self.callbacks.remove(&id); } } BluetoothCallbackType::Connection => { self.connection_callbacks.remove(&id); pub(crate) fn connection_callback_disconnected(&mut self, id: u32) { } self.connection_callbacks.remove_callback(id); }; } } fn get_remote_device_if_found(&self, address: &str) -> Option<&BluetoothDeviceContext> { fn get_remote_device_if_found(&self, address: &str) -> Option<&BluetoothDeviceContext> { Loading Loading @@ -506,7 +492,7 @@ impl Bluetooth { self.found_devices.retain(|_, d| is_fresh(d, &now)); self.found_devices.retain(|_, d| is_fresh(d, &now)); for d in stale_devices { for d in stale_devices { self.for_all_callbacks(|callback| { self.callbacks.for_all_callbacks(|callback| { callback.on_device_cleared(d.clone()); callback.on_device_cleared(d.clone()); }); }); } } Loading Loading @@ -669,12 +655,12 @@ impl BtifBluetoothCallbacks for Bluetooth { } } } } BluetoothProperty::BdName(bdname) => { BluetoothProperty::BdName(bdname) => { self.for_all_callbacks(|callback| { self.callbacks.for_all_callbacks(|callback| { callback.on_name_changed(bdname.clone()); callback.on_name_changed(bdname.clone()); }); }); } } BluetoothProperty::AdapterScanMode(mode) => { BluetoothProperty::AdapterScanMode(mode) => { self.for_all_callbacks(|callback| { self.callbacks.for_all_callbacks(|callback| { callback callback .on_discoverable_changed(*mode == BtScanMode::ConnectableDiscoverable); .on_discoverable_changed(*mode == BtScanMode::ConnectableDiscoverable); }); }); Loading @@ -684,7 +670,7 @@ impl BtifBluetoothCallbacks for Bluetooth { self.properties.insert(prop.get_type(), prop.clone()); self.properties.insert(prop.get_type(), prop.clone()); self.for_all_callbacks(|callback| { self.callbacks.for_all_callbacks(|callback| { callback.on_adapter_property_changed(prop.get_type()); callback.on_adapter_property_changed(prop.get_type()); }); }); } } Loading @@ -710,7 +696,7 @@ impl BtifBluetoothCallbacks for Bluetooth { let device = self.found_devices.get(&address).unwrap(); let device = self.found_devices.get(&address).unwrap(); self.for_all_callbacks(|callback| { self.callbacks.for_all_callbacks(|callback| { callback.on_device_found(device.info.clone()); callback.on_device_found(device.info.clone()); }); }); } } Loading @@ -729,7 +715,7 @@ impl BtifBluetoothCallbacks for Bluetooth { self.discovering_started = Instant::now(); self.discovering_started = Instant::now(); } } self.for_all_callbacks(|callback| { self.callbacks.for_all_callbacks(|callback| { callback.on_discovering_changed(state == BtDiscoveryState::Started); callback.on_discovering_changed(state == BtDiscoveryState::Started); }); }); Loading @@ -751,7 +737,7 @@ impl BtifBluetoothCallbacks for Bluetooth { ) { ) { // Currently this supports many agent because we accept many callbacks. // Currently this supports many agent because we accept many callbacks. // TODO: We need a way to select the default agent. // TODO: We need a way to select the default agent. self.for_all_callbacks(|callback| { self.callbacks.for_all_callbacks(|callback| { callback.on_ssp_request( callback.on_ssp_request( BluetoothDevice::new(remote_addr.to_string(), remote_name.clone()), BluetoothDevice::new(remote_addr.to_string(), remote_name.clone()), cod, cod, Loading Loading @@ -806,7 +792,7 @@ impl BtifBluetoothCallbacks for Bluetooth { } } // Send bond state changed notifications // Send bond state changed notifications self.for_all_callbacks(|callback| { self.callbacks.for_all_callbacks(|callback| { callback.on_bond_state_changed( callback.on_bond_state_changed( status.to_u32().unwrap(), status.to_u32().unwrap(), address.clone(), address.clone(), Loading Loading @@ -898,12 +884,12 @@ impl BtifBluetoothCallbacks for Bluetooth { match state { match state { BtAclState::Connected => { BtAclState::Connected => { self.for_all_connection_callbacks(|callback| { self.connection_callbacks.for_all_callbacks(|callback| { callback.on_device_connected(device.clone()); callback.on_device_connected(device.clone()); }); }); } } BtAclState::Disconnected => { BtAclState::Disconnected => { self.for_all_connection_callbacks(|callback| { self.connection_callbacks.for_all_callbacks(|callback| { callback.on_device_disconnected(device.clone()); callback.on_device_disconnected(device.clone()); }); }); } } Loading @@ -917,52 +903,19 @@ impl BtifBluetoothCallbacks for Bluetooth { // TODO: Add unit tests for this implementation // TODO: Add unit tests for this implementation impl IBluetooth for Bluetooth { impl IBluetooth for Bluetooth { fn register_callback(&mut self, mut callback: Box<dyn IBluetoothCallback + Send>) { fn register_callback(&mut self, callback: Box<dyn IBluetoothCallback + Send>) { let tx = self.tx.clone(); self.callbacks.add_callback(callback); let id = callback.register_disconnect(Box::new(move |cb_id| { let tx = tx.clone(); tokio::spawn(async move { let _result = tx .send(Message::BluetoothCallbackDisconnected( cb_id, BluetoothCallbackType::Adapter, )) .await; }); })); self.callbacks.insert(id, callback); } } fn register_connection_callback( fn register_connection_callback( &mut self, &mut self, mut callback: Box<dyn IBluetoothConnectionCallback + Send>, callback: Box<dyn IBluetoothConnectionCallback + Send>, ) -> u32 { ) -> u32 { let tx = self.tx.clone(); self.connection_callbacks.add_callback(callback) let id = callback.register_disconnect(Box::new(move |cb_id| { let tx = tx.clone(); tokio::spawn(async move { let _ = tx .send(Message::BluetoothCallbackDisconnected( cb_id, BluetoothCallbackType::Connection, )) .await; }); })); self.connection_callbacks.insert(id, callback); id } } fn unregister_connection_callback(&mut self, callback_id: u32) -> bool { fn unregister_connection_callback(&mut self, callback_id: u32) -> bool { match self.connection_callbacks.get_mut(&callback_id) { self.connection_callbacks.remove_callback(callback_id) Some(cb) => cb.unregister(callback_id), None => false, } } } fn enable(&mut self) -> bool { fn enable(&mut self) -> bool { Loading
system/gd/rust/linux/stack/src/bluetooth_media.rs +21 −22 Original line number Original line Diff line number Diff line Loading @@ -25,7 +25,8 @@ use tokio::task::JoinHandle; use tokio::time::{sleep, Duration}; use tokio::time::{sleep, Duration}; use crate::bluetooth::{Bluetooth, BluetoothDevice, IBluetooth}; use crate::bluetooth::{Bluetooth, BluetoothDevice, IBluetooth}; use crate::Message; use crate::callbacks::Callbacks; use crate::{Message, RPCProxy}; const DEFAULT_PROFILE_DISCOVERY_TIMEOUT_SEC: u64 = 5; const DEFAULT_PROFILE_DISCOVERY_TIMEOUT_SEC: u64 = 5; Loading Loading @@ -64,7 +65,7 @@ pub trait IBluetoothMedia { fn stop_sco_call(&mut self, address: String); fn stop_sco_call(&mut self, address: String); } } pub trait IBluetoothMediaCallback { pub trait IBluetoothMediaCallback: RPCProxy { /// Triggered when a Bluetooth audio device is ready to be used. This should /// Triggered when a Bluetooth audio device is ready to be used. This should /// only be triggered once for a device and send an event to clients. If the /// only be triggered once for a device and send an event to clients. If the /// device supports both HFP and A2DP, both should be ready when this is /// device supports both HFP and A2DP, both should be ready when this is Loading Loading @@ -119,8 +120,7 @@ pub enum MediaActions { pub struct BluetoothMedia { pub struct BluetoothMedia { intf: Arc<Mutex<BluetoothInterface>>, intf: Arc<Mutex<BluetoothInterface>>, initialized: bool, initialized: bool, callbacks: Arc<Mutex<Vec<(u32, Box<dyn IBluetoothMediaCallback + Send>)>>>, callbacks: Arc<Mutex<Callbacks<dyn IBluetoothMediaCallback + Send>>>, callback_last_id: u32, tx: Sender<Message>, tx: Sender<Message>, adapter: Option<Arc<Mutex<Box<Bluetooth>>>>, adapter: Option<Arc<Mutex<Box<Bluetooth>>>>, a2dp: Option<A2dp>, a2dp: Option<A2dp>, Loading @@ -139,8 +139,10 @@ impl BluetoothMedia { BluetoothMedia { BluetoothMedia { intf, intf, initialized: false, initialized: false, callbacks: Arc::new(Mutex::new(vec![])), callbacks: Arc::new(Mutex::new(Callbacks::new( callback_last_id: 0, tx.clone(), Message::MediaCallbackDisconnected, ))), tx, tx, adapter: None, adapter: None, a2dp: None, a2dp: None, Loading Loading @@ -196,12 +198,12 @@ impl BluetoothMedia { match cb { match cb { AvrcpCallbacks::AvrcpAbsoluteVolumeEnabled(supported) => { AvrcpCallbacks::AvrcpAbsoluteVolumeEnabled(supported) => { self.absolute_volume = supported; self.absolute_volume = supported; self.for_all_callbacks(|callback| { self.callbacks.lock().unwrap().for_all_callbacks(|callback| { callback.on_absolute_volume_supported_changed(supported); callback.on_absolute_volume_supported_changed(supported); }); }); } } AvrcpCallbacks::AvrcpAbsoluteVolumeUpdate(volume) => { AvrcpCallbacks::AvrcpAbsoluteVolumeUpdate(volume) => { self.for_all_callbacks(|callback| { self.callbacks.lock().unwrap().for_all_callbacks(|callback| { callback.on_absolute_volume_changed(volume); callback.on_absolute_volume_changed(volume); }); }); } } Loading Loading @@ -279,27 +281,31 @@ impl BluetoothMedia { } } } } HfpCallbacks::VolumeUpdate(volume, addr) => { HfpCallbacks::VolumeUpdate(volume, addr) => { self.for_all_callbacks(|callback| { self.callbacks.lock().unwrap().for_all_callbacks(|callback| { callback.on_hfp_volume_changed(volume, addr.to_string()); callback.on_hfp_volume_changed(volume, addr.to_string()); }); }); } } } } } } pub fn remove_callback(&mut self, id: u32) -> bool { self.callbacks.lock().unwrap().remove_callback(id) } fn notify_media_capability_added(&self, addr: RawAddress) { fn notify_media_capability_added(&self, addr: RawAddress) { // Return true if the device added message is sent by the call. // Return true if the device added message is sent by the call. fn dedup_added_cb( fn dedup_added_cb( device_added_tasks: Arc<Mutex<HashMap<RawAddress, Option<JoinHandle<()>>>>>, device_added_tasks: Arc<Mutex<HashMap<RawAddress, Option<JoinHandle<()>>>>>, addr: RawAddress, addr: RawAddress, callbacks: Arc<Mutex<Vec<(u32, Box<dyn IBluetoothMediaCallback + Send>)>>>, callbacks: Arc<Mutex<Callbacks<dyn IBluetoothMediaCallback + Send>>>, device: BluetoothAudioDevice, device: BluetoothAudioDevice, is_delayed: bool, is_delayed: bool, ) -> bool { ) -> bool { // Closure used to lock and trigger the device added callbacks. // Closure used to lock and trigger the device added callbacks. let trigger_device_added = || { let trigger_device_added = || { for callback in &*callbacks.lock().unwrap() { callbacks.lock().unwrap().for_all_callbacks(|callback| { callback.1.on_bluetooth_audio_device_added(device.clone()); callback.on_bluetooth_audio_device_added(device.clone()); } }); }; }; let mut guard = device_added_tasks.lock().unwrap(); let mut guard = device_added_tasks.lock().unwrap(); let task = guard.insert(addr, None); let task = guard.insert(addr, None); Loading Loading @@ -390,7 +396,7 @@ impl BluetoothMedia { // Abort what is pending // Abort what is pending Some(handler) => handler.abort(), Some(handler) => handler.abort(), // This addr has been added so tell audio server to remove it // This addr has been added so tell audio server to remove it None => self.for_all_callbacks(|callback| { None => self.callbacks.lock().unwrap().for_all_callbacks(|callback| { callback.on_bluetooth_audio_device_removed(addr.to_string()); callback.on_bluetooth_audio_device_removed(addr.to_string()); }), }), } } Loading @@ -399,12 +405,6 @@ impl BluetoothMedia { } } } } fn for_all_callbacks<F: Fn(&Box<dyn IBluetoothMediaCallback + Send>)>(&self, f: F) { for callback in &*self.callbacks.lock().unwrap() { f(&callback.1); } } fn adapter_get_remote_name(&self, addr: RawAddress) -> String { fn adapter_get_remote_name(&self, addr: RawAddress) -> String { let device = BluetoothDevice::new( let device = BluetoothDevice::new( addr.to_string(), addr.to_string(), Loading Loading @@ -472,8 +472,7 @@ fn get_hfp_dispatcher(tx: Sender<Message>) -> HfpCallbacksDispatcher { impl IBluetoothMedia for BluetoothMedia { impl IBluetoothMedia for BluetoothMedia { fn register_callback(&mut self, callback: Box<dyn IBluetoothMediaCallback + Send>) -> bool { fn register_callback(&mut self, callback: Box<dyn IBluetoothMediaCallback + Send>) -> bool { self.callback_last_id += 1; let _id = self.callbacks.lock().unwrap().add_callback(callback); self.callbacks.lock().unwrap().push((self.callback_last_id, callback)); true true } } Loading
system/gd/rust/linux/stack/src/lib.rs +13 −9 Original line number Original line Diff line number Diff line Loading @@ -31,12 +31,6 @@ use bt_topshim::{ }, }, }; }; #[derive(Clone, Debug)] pub enum BluetoothCallbackType { Adapter, Connection, } /// Message types that are sent to the stack main dispatch loop. /// Message types that are sent to the stack main dispatch loop. pub enum Message { pub enum Message { // Callbacks from libbluetooth // Callbacks from libbluetooth Loading @@ -51,9 +45,11 @@ pub enum Message { // Actions within the stack // Actions within the stack Media(MediaActions), Media(MediaActions), MediaCallbackDisconnected(u32), // Client callback disconnections // Client callback disconnections BluetoothCallbackDisconnected(u32, BluetoothCallbackType), AdapterCallbackDisconnected(u32), ConnectionCallbackDisconnected(u32), // Update list of found devices and remove old instances. // Update list of found devices and remove old instances. DeviceFreshnessCheck, DeviceFreshnessCheck, Loading Loading @@ -130,8 +126,16 @@ impl Stack { bluetooth_media.lock().unwrap().dispatch_media_actions(action); bluetooth_media.lock().unwrap().dispatch_media_actions(action); } } Message::BluetoothCallbackDisconnected(id, cb_type) => { Message::MediaCallbackDisconnected(cb_id) => { bluetooth.lock().unwrap().callback_disconnected(id, cb_type); bluetooth_media.lock().unwrap().remove_callback(cb_id); } Message::AdapterCallbackDisconnected(id) => { bluetooth.lock().unwrap().adapter_callback_disconnected(id); } Message::ConnectionCallbackDisconnected(id) => { bluetooth.lock().unwrap().connection_callback_disconnected(id); } } Message::DeviceFreshnessCheck => { Message::DeviceFreshnessCheck => { Loading
system/gd/rust/linux/stack/src/suspend.rs +10 −31 Original line number Original line Diff line number Diff line //! Suspend/Resume API. //! Suspend/Resume API. use crate::callbacks::Callbacks; use crate::{Message, RPCProxy}; use crate::{Message, RPCProxy}; use bt_topshim::btif::BluetoothInterface; use bt_topshim::btif::BluetoothInterface; use log::warn; use log::warn; use std::collections::HashMap; use std::sync::{Arc, Mutex}; use std::sync::{Arc, Mutex}; use tokio::sync::mpsc::Sender; use tokio::sync::mpsc::Sender; Loading Loading @@ -60,7 +60,7 @@ pub enum SuspendType { pub struct Suspend { pub struct Suspend { intf: Arc<Mutex<BluetoothInterface>>, intf: Arc<Mutex<BluetoothInterface>>, tx: Sender<Message>, tx: Sender<Message>, callbacks: HashMap<u32, Box<dyn ISuspendCallback + Send>>, callbacks: Callbacks<dyn ISuspendCallback + Send>, is_connected_suspend: bool, is_connected_suspend: bool, was_a2dp_connected: bool, was_a2dp_connected: bool, } } Loading @@ -69,55 +69,34 @@ impl Suspend { pub fn new(intf: Arc<Mutex<BluetoothInterface>>, tx: Sender<Message>) -> Suspend { pub fn new(intf: Arc<Mutex<BluetoothInterface>>, tx: Sender<Message>) -> Suspend { Self { Self { intf: intf, intf: intf, tx, tx: tx.clone(), callbacks: HashMap::new(), callbacks: Callbacks::new(tx.clone(), Message::SuspendCallbackDisconnected), is_connected_suspend: false, is_connected_suspend: false, was_a2dp_connected: false, was_a2dp_connected: false, } } } } pub(crate) fn callback_registered(&mut self, id: u32) { pub(crate) fn callback_registered(&mut self, id: u32) { match self.callbacks.get(&id) { match self.callbacks.get_by_id(id) { Some(callback) => callback.on_callback_registered(id), Some(callback) => callback.on_callback_registered(id), None => warn!("Suspend callback {} does not exist", id), None => warn!("Suspend callback {} does not exist", id), } } } } pub(crate) fn remove_callback(&mut self, id: u32) -> bool { pub(crate) fn remove_callback(&mut self, id: u32) -> bool { match self.callbacks.get_mut(&id) { self.callbacks.remove_callback(id) Some(callback) => { callback.unregister(id); self.callbacks.remove(&id); true } None => false, } } fn for_all_callbacks<F: Fn(&Box<dyn ISuspendCallback + Send>)>(&self, f: F) { for (_, callback) in self.callbacks.iter() { f(&callback); } } } } } impl ISuspend for Suspend { impl ISuspend for Suspend { fn register_callback(&mut self, mut callback: Box<dyn ISuspendCallback + Send>) -> bool { fn register_callback(&mut self, callback: Box<dyn ISuspendCallback + Send>) -> bool { let tx = self.tx.clone(); let id = self.callbacks.add_callback(callback); let id = callback.register_disconnect(Box::new(move |cb_id| { let tx = tx.clone(); tokio::spawn(async move { let _result = tx.send(Message::SuspendCallbackDisconnected(cb_id)).await; }); })); let tx = self.tx.clone(); let tx = self.tx.clone(); tokio::spawn(async move { tokio::spawn(async move { let _result = tx.send(Message::SuspendCallbackRegistered(id)).await; let _result = tx.send(Message::SuspendCallbackRegistered(id)).await; }); }); self.callbacks.insert(id, callback); true true } } Loading Loading @@ -147,7 +126,7 @@ impl ISuspend for Suspend { self.intf.lock().unwrap().clear_filter_accept_list(); self.intf.lock().unwrap().clear_filter_accept_list(); // TODO(231435700): self.intf.lock().unwrap().disconnect_all_acls(); // TODO(231435700): self.intf.lock().unwrap().disconnect_all_acls(); self.intf.lock().unwrap().le_rand(); self.intf.lock().unwrap().le_rand(); self.for_all_callbacks(|callback| { self.callbacks.for_all_callbacks(|callback| { callback.on_suspend_ready(suspend_id); callback.on_suspend_ready(suspend_id); }); }); return 1; return 1; Loading @@ -165,7 +144,7 @@ impl ISuspend for Suspend { // TODO(224603198): start all advertising again // TODO(224603198): start all advertising again } } self.intf.lock().unwrap().le_rand(); self.intf.lock().unwrap().le_rand(); self.for_all_callbacks(|callback| { self.callbacks.for_all_callbacks(|callback| { callback.on_resumed(suspend_id); callback.on_resumed(suspend_id); }); }); return true; return true; Loading