Loading floss/pandora/floss/media_client.py +17 −9 Original line number Diff line number Diff line Loading @@ -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) Loading @@ -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) Loading @@ -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) Loading system/gd/rust/linux/client/src/dbus_iface.rs +5 −3 Original line number Diff line number Diff line Loading @@ -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; Loading Loading @@ -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!() } Loading @@ -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!() } Loading @@ -2762,6 +2763,7 @@ impl IBluetoothMedia for BluetoothMediaDBus { address: RawAddress, sco_offload: bool, disabled_codecs: HfpCodecBitId, connection_listener: File, ) -> bool { dbus_generated!() } Loading @@ -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!() } Loading system/gd/rust/linux/service/src/iface_bluetooth_media.rs +5 −3 Original line number Diff line number Diff line Loading @@ -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)] Loading Loading @@ -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!() } Loading @@ -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!() } Loading @@ -380,6 +381,7 @@ impl IBluetoothMedia for IBluetoothMediaDBus { address: RawAddress, sco_offload: bool, disabled_codecs: HfpCodecBitId, connection_listener: File, ) -> bool { dbus_generated!() } Loading @@ -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!() } Loading system/gd/rust/linux/stack/src/bluetooth_media.rs +75 −6 Original line number Diff line number Diff line Loading @@ -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; Loading Loading @@ -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; Loading @@ -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. Loading Loading @@ -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 { Loading Loading @@ -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, } } Loading Loading @@ -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); } Loading Loading @@ -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); Loading @@ -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) => { Loading Loading @@ -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. Loading @@ -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) Loading Loading @@ -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"), Loading @@ -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) } Loading Loading
floss/pandora/floss/media_client.py +17 −9 Original line number Diff line number Diff line Loading @@ -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) Loading @@ -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) Loading @@ -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) Loading
system/gd/rust/linux/client/src/dbus_iface.rs +5 −3 Original line number Diff line number Diff line Loading @@ -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; Loading Loading @@ -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!() } Loading @@ -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!() } Loading @@ -2762,6 +2763,7 @@ impl IBluetoothMedia for BluetoothMediaDBus { address: RawAddress, sco_offload: bool, disabled_codecs: HfpCodecBitId, connection_listener: File, ) -> bool { dbus_generated!() } Loading @@ -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!() } Loading
system/gd/rust/linux/service/src/iface_bluetooth_media.rs +5 −3 Original line number Diff line number Diff line Loading @@ -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)] Loading Loading @@ -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!() } Loading @@ -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!() } Loading @@ -380,6 +381,7 @@ impl IBluetoothMedia for IBluetoothMediaDBus { address: RawAddress, sco_offload: bool, disabled_codecs: HfpCodecBitId, connection_listener: File, ) -> bool { dbus_generated!() } Loading @@ -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!() } Loading
system/gd/rust/linux/stack/src/bluetooth_media.rs +75 −6 Original line number Diff line number Diff line Loading @@ -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; Loading Loading @@ -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; Loading @@ -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. Loading Loading @@ -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 { Loading Loading @@ -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, } } Loading Loading @@ -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); } Loading Loading @@ -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); Loading @@ -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) => { Loading Loading @@ -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. Loading @@ -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) Loading Loading @@ -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"), Loading @@ -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) } Loading