diff options
author | 2024-06-18 00:41:56 +0000 | |
---|---|---|
committer | 2024-06-18 00:41:56 +0000 | |
commit | 422c21c52dc3a56faaf9416d12e3d0c7e679c577 (patch) | |
tree | c72a7c3da56e6cb5f7f62613ee72513f45d962a5 | |
parent | c35be7ca18d31e93e3b70b1a0e6a3644ae82bb5e (diff) | |
parent | 39bd62f6bb433f6e366fe55d8c4ddfdd539d0d16 (diff) |
Merge "floss: notify hfp/a2dp audio status via forwarded fd" into main
-rw-r--r-- | floss/pandora/floss/media_client.py | 26 | ||||
-rw-r--r-- | system/gd/rust/linux/client/src/dbus_iface.rs | 8 | ||||
-rw-r--r-- | system/gd/rust/linux/service/src/iface_bluetooth_media.rs | 8 | ||||
-rw-r--r-- | system/gd/rust/linux/stack/src/bluetooth_media.rs | 81 |
4 files changed, 102 insertions, 21 deletions
diff --git a/floss/pandora/floss/media_client.py b/floss/pandora/floss/media_client.py index 83dbe1e2c4..fdfa032e56 100644 --- a/floss/pandora/floss/media_client.py +++ b/floss/pandora/floss/media_client.py @@ -410,13 +410,16 @@ class FlossMediaClient(BluetoothMediaCallbacks): return True @utils.glib_call(False) - def start_audio_request(self): + def start_audio_request(self, connection_listener): """Starts audio request. + Args: + connection_listener: The file descriptor to write 1 (u8) on audio connection. + Returns: True on success, False otherwise. """ - self.proxy().StartAudioRequest() + self.proxy().StartAudioRequest(connection_listener) return True @utils.glib_call(None) @@ -432,28 +435,32 @@ class FlossMediaClient(BluetoothMediaCallbacks): return self.proxy().GetA2dpAudioStarted(address) @utils.glib_call(False) - def stop_audio_request(self): + def stop_audio_request(self, connection_listener): """Stops audio request. + Args: + connection_listener: The file descriptor to write 0 (u8) on audio connection. + Returns: True on success, False otherwise. """ - self.proxy().StopAudioRequest() + self.proxy().StopAudioRequest(connection_listener) return True @utils.glib_call(False) - def start_sco_call(self, address, sco_offload, force_cvsd): + def start_sco_call(self, address, sco_offload, disabled_codecs, connection_listener): """Starts the SCO call. Args: address: Device address to make SCO call. sco_offload: Whether SCO offload is enabled. - force_cvsd: True to force the stack to use CVSD even if mSBC is supported. + disabled_codecs: The disabled codecs in bitmask form. CVSD=1, MSBC=2, LC3=4. + connection_listener: The file descriptor to write the codec id on audio connection. Returns: True on success, False otherwise. """ - self.proxy().StartScoCall(address, sco_offload, force_cvsd) + self.proxy().StartScoCall(address, sco_offload, disabled_codecs, connection_listener) return True @utils.glib_call(None) @@ -470,16 +477,17 @@ class FlossMediaClient(BluetoothMediaCallbacks): return self.proxy().GetHfpAudioStarted(address) @utils.glib_call(False) - def stop_sco_call(self, address): + def stop_sco_call(self, address, connection_listener): """Stops the SCO call. Args: address: Device address to stop SCO call. + connection_listener: The file descriptor to write 0 (u8) on audio disconnection. Returns: True on success, False otherwise. """ - self.proxy().StopScoCall(address) + self.proxy().StopScoCall(address, connection_listener) return True @utils.glib_call(None) diff --git a/system/gd/rust/linux/client/src/dbus_iface.rs b/system/gd/rust/linux/client/src/dbus_iface.rs index da5344f136..a75ebc5ca4 100644 --- a/system/gd/rust/linux/client/src/dbus_iface.rs +++ b/system/gd/rust/linux/client/src/dbus_iface.rs @@ -71,6 +71,7 @@ use num_traits::{FromPrimitive, ToPrimitive}; use std::collections::HashMap; use std::convert::{TryFrom, TryInto}; +use std::fs::File; use std::sync::Arc; use btstack::bluetooth_qa::IBluetoothQACallback; @@ -2742,7 +2743,7 @@ impl IBluetoothMedia for BluetoothMediaDBus { } #[dbus_method("StartAudioRequest")] - fn start_audio_request(&mut self) -> bool { + fn start_audio_request(&mut self, connection_listener: File) -> bool { dbus_generated!() } @@ -2752,7 +2753,7 @@ impl IBluetoothMedia for BluetoothMediaDBus { } #[dbus_method("StopAudioRequest")] - fn stop_audio_request(&mut self) { + fn stop_audio_request(&mut self, connection_listener: File) { dbus_generated!() } @@ -2762,6 +2763,7 @@ impl IBluetoothMedia for BluetoothMediaDBus { address: RawAddress, sco_offload: bool, disabled_codecs: HfpCodecBitId, + connection_listener: File, ) -> bool { dbus_generated!() } @@ -2772,7 +2774,7 @@ impl IBluetoothMedia for BluetoothMediaDBus { } #[dbus_method("StopScoCall")] - fn stop_sco_call(&mut self, address: RawAddress) { + fn stop_sco_call(&mut self, address: RawAddress, connection_listener: File) { dbus_generated!() } diff --git a/system/gd/rust/linux/service/src/iface_bluetooth_media.rs b/system/gd/rust/linux/service/src/iface_bluetooth_media.rs index a38e7b07d9..62f9ba36fe 100644 --- a/system/gd/rust/linux/service/src/iface_bluetooth_media.rs +++ b/system/gd/rust/linux/service/src/iface_bluetooth_media.rs @@ -26,6 +26,7 @@ use crate::dbus_arg::{DBusArg, DBusArgError, RefArgToRust}; use num_traits::{FromPrimitive, ToPrimitive}; use std::convert::{TryFrom, TryInto}; +use std::fs::File; use std::sync::Arc; #[allow(dead_code)] @@ -360,7 +361,7 @@ impl IBluetoothMedia for IBluetoothMediaDBus { } #[dbus_method("StartAudioRequest")] - fn start_audio_request(&mut self) -> bool { + fn start_audio_request(&mut self, connection_listener: File) -> bool { dbus_generated!() } @@ -370,7 +371,7 @@ impl IBluetoothMedia for IBluetoothMediaDBus { } #[dbus_method("StopAudioRequest", DBusLog::Disable)] - fn stop_audio_request(&mut self) { + fn stop_audio_request(&mut self, connection_listener: File) { dbus_generated!() } @@ -380,6 +381,7 @@ impl IBluetoothMedia for IBluetoothMediaDBus { address: RawAddress, sco_offload: bool, disabled_codecs: HfpCodecBitId, + connection_listener: File, ) -> bool { dbus_generated!() } @@ -390,7 +392,7 @@ impl IBluetoothMedia for IBluetoothMediaDBus { } #[dbus_method("StopScoCall")] - fn stop_sco_call(&mut self, address: RawAddress) { + fn stop_sco_call(&mut self, address: RawAddress, connection_listener: File) { dbus_generated!() } diff --git a/system/gd/rust/linux/stack/src/bluetooth_media.rs b/system/gd/rust/linux/stack/src/bluetooth_media.rs index 3dc949e892..6275fc5aec 100644 --- a/system/gd/rust/linux/stack/src/bluetooth_media.rs +++ b/system/gd/rust/linux/stack/src/bluetooth_media.rs @@ -46,6 +46,8 @@ use itertools::Itertools; use log::{debug, info, warn}; use std::collections::{HashMap, HashSet}; use std::convert::{TryFrom, TryInto}; +use std::fs::File; +use std::io::Write; use std::sync::Arc; use std::sync::Mutex; @@ -151,8 +153,8 @@ pub trait IBluetoothMedia { // Set the HFP speaker volume. Valid volume specified by the HFP spec should // be in the range of 0-15. fn set_hfp_volume(&mut self, volume: u8, address: RawAddress); - fn start_audio_request(&mut self) -> bool; - fn stop_audio_request(&mut self); + fn start_audio_request(&mut self, connection_listener: File) -> bool; + fn stop_audio_request(&mut self, connection_listener: File); /// Returns true iff A2DP audio has started. fn get_a2dp_audio_started(&mut self, address: RawAddress) -> bool; @@ -169,8 +171,9 @@ pub trait IBluetoothMedia { address: RawAddress, sco_offload: bool, disabled_codecs: HfpCodecBitId, + connection_listener: File, ) -> bool; - fn stop_sco_call(&mut self, address: RawAddress); + fn stop_sco_call(&mut self, address: RawAddress, connection_listener: File); /// Set the current playback status: e.g., playing, paused, stopped, etc. The method is a copy /// of the existing CRAS API, hence not following Floss API conventions. @@ -492,6 +495,8 @@ pub struct BluetoothMedia { csis: Option<CsisClient>, csis_states: HashMap<RawAddress, BtCsisConnectionState>, is_le_audio_only_enabled: bool, // TODO: remove this once there is dual mode. + hfp_audio_connection_listener: Option<File>, + a2dp_audio_connection_listener: Option<File>, } impl BluetoothMedia { @@ -557,6 +562,8 @@ impl BluetoothMedia { csis: None, csis_states: HashMap::new(), is_le_audio_only_enabled: false, + hfp_audio_connection_listener: None, + a2dp_audio_connection_listener: None, } } @@ -638,6 +645,19 @@ impl BluetoothMedia { } } + fn write_data_to_listener(&self, mut listener: File, data: Vec<u8>) { + match listener.write(&data) { + Ok(nwritten) => { + if nwritten != data.len() { + warn!("Did not write full data into the event listener."); + } + } + Err(e) => { + warn!("Cannot write data into the event listener: {}", e); + } + } + } + pub fn set_adapter(&mut self, adapter: Arc<Mutex<Box<Bluetooth>>>) { self.adapter = Some(adapter); } @@ -1227,11 +1247,13 @@ impl BluetoothMedia { match state { BtavConnectionState::Connected => { info!("[{}]: a2dp connected.", DisplayAddress(&addr)); + self.a2dp_states.insert(addr, state); self.add_connected_profile(addr, Profile::A2dpSink); } BtavConnectionState::Disconnected => { info!("[{}]: a2dp disconnected.", DisplayAddress(&addr)); + self.a2dp_states.remove(&addr); self.a2dp_caps.remove(&addr); self.a2dp_audio_state.remove(&addr); @@ -1244,6 +1266,18 @@ impl BluetoothMedia { } A2dpCallbacks::AudioState(addr, state) => { info!("[{}]: a2dp audio state: {:?}", DisplayAddress(&addr), state); + + let started: u8 = match state { + BtavAudioState::Started => 1, + _ => 0, + }; + + if self.a2dp_audio_connection_listener.is_some() { + let listener = self.a2dp_audio_connection_listener.take().unwrap(); + let data: Vec<u8> = vec![started]; + self.write_data_to_listener(listener, data); + } + self.a2dp_audio_state.insert(addr, state); } A2dpCallbacks::AudioConfig(addr, _config, _local_caps, a2dp_caps) => { @@ -1480,6 +1514,13 @@ impl BluetoothMedia { self.hfp_audio_state.insert(addr, state); + if self.hfp_audio_connection_listener.is_some() { + let listener = self.hfp_audio_connection_listener.take().unwrap(); + let codec = self.get_hfp_audio_final_codecs(addr); + let data: Vec<u8> = vec![codec]; + self.write_data_to_listener(listener, data); + } + if self.should_insert_call_when_sco_start(addr) { // This triggers a +CIEV command to set the call status for HFP devices. // It is required for some devices to provide sound. @@ -1490,6 +1531,12 @@ impl BluetoothMedia { BthfAudioState::Disconnected => { info!("[{}]: hfp audio disconnected.", DisplayAddress(&addr)); + if self.hfp_audio_connection_listener.is_some() { + let listener = self.hfp_audio_connection_listener.take().unwrap(); + let data: Vec<u8> = vec![0]; + self.write_data_to_listener(listener, data); + } + // Ignore disconnected -> disconnected if let Some(BthfAudioState::Connected) = self.hfp_audio_state.insert(addr, state) @@ -3822,13 +3869,24 @@ impl IBluetoothMedia for BluetoothMedia { }; } - fn start_audio_request(&mut self) -> bool { + fn start_audio_request(&mut self, connection_listener: File) -> bool { + if self.a2dp_audio_connection_listener.is_some() { + warn!("start_audio_request: replacing an unresolved listener"); + } + + self.a2dp_audio_connection_listener = Some(connection_listener); self.start_audio_request_impl() } - fn stop_audio_request(&mut self) { + fn stop_audio_request(&mut self, connection_listener: File) { debug!("Stop audio request"); + if self.a2dp_audio_connection_listener.is_some() { + warn!("stop_audio_request: replacing an unresolved listener"); + } + + self.a2dp_audio_connection_listener = Some(connection_listener); + match self.a2dp.as_mut() { Some(a2dp) => a2dp.stop_audio_request(), None => warn!("Uninitialized A2DP to stop audio request"), @@ -3840,11 +3898,22 @@ impl IBluetoothMedia for BluetoothMedia { address: RawAddress, sco_offload: bool, disabled_codecs: HfpCodecBitId, + connection_listener: File, ) -> bool { + if self.hfp_audio_connection_listener.is_some() { + warn!("start_sco_call: replacing an unresolved listener"); + } + + self.hfp_audio_connection_listener = Some(connection_listener); self.start_sco_call_impl(address, sco_offload, disabled_codecs) } - fn stop_sco_call(&mut self, address: RawAddress) { + fn stop_sco_call(&mut self, address: RawAddress, listener: File) { + if self.hfp_audio_connection_listener.is_some() { + warn!("stop_sco_call: replacing an unresolved listener"); + } + + self.hfp_audio_connection_listener = Some(listener); self.stop_sco_call_impl(address) } |