Loading system/gd/rust/linux/client/src/dbus_iface.rs +14 −4 Original line number Diff line number Diff line Loading @@ -4,7 +4,10 @@ use bt_topshim::btif::{ BtBondState, BtConnectionState, BtDeviceType, BtDiscMode, BtPropertyType, BtSspVariant, BtStatus, BtTransport, BtVendorProductInfo, Uuid, Uuid128Bit, }; use bt_topshim::profiles::a2dp::{A2dpCodecConfig, PresentationPosition}; use bt_topshim::profiles::a2dp::{ A2dpCodecBitsPerSample, A2dpCodecChannelMode, A2dpCodecConfig, A2dpCodecIndex, A2dpCodecSampleRate, PresentationPosition, }; use bt_topshim::profiles::avrcp::PlayerMetadata; use bt_topshim::profiles::gatt::{AdvertisingStatus, GattStatus, LePhy}; use bt_topshim::profiles::hfp::HfpCodecCapability; Loading Loading @@ -415,6 +418,11 @@ pub struct A2dpCodecConfigDBus { codec_specific_4: i64, } impl_dbus_arg_enum!(A2dpCodecIndex); impl_dbus_arg_from_into!(A2dpCodecSampleRate, i32); impl_dbus_arg_from_into!(A2dpCodecBitsPerSample, i32); impl_dbus_arg_from_into!(A2dpCodecChannelMode, i32); impl_dbus_arg_from_into!(HfpCodecCapability, i32); #[dbus_propmap(BluetoothAudioDevice)] pub struct BluetoothAudioDeviceDBus { Loading Loading @@ -2524,9 +2532,11 @@ impl IBluetoothMedia for BluetoothMediaDBus { #[dbus_method("SetAudioConfig")] fn set_audio_config( &mut self, sample_rate: i32, bits_per_sample: i32, channel_mode: i32, address: String, codec_type: A2dpCodecIndex, sample_rate: A2dpCodecSampleRate, bits_per_sample: A2dpCodecBitsPerSample, channel_mode: A2dpCodecChannelMode, ) -> bool { dbus_generated!() } Loading system/gd/rust/linux/service/src/iface_bluetooth_media.rs +16 −5 Original line number Diff line number Diff line use bt_topshim::profiles::a2dp::{A2dpCodecConfig, PresentationPosition}; use bt_topshim::profiles::a2dp::{ A2dpCodecBitsPerSample, A2dpCodecChannelMode, A2dpCodecConfig, A2dpCodecIndex, A2dpCodecSampleRate, PresentationPosition, }; use bt_topshim::profiles::avrcp::PlayerMetadata; use bt_topshim::profiles::hfp::HfpCodecCapability; use btstack::bluetooth_media::{BluetoothAudioDevice, IBluetoothMedia, IBluetoothMediaCallback}; Loading @@ -11,10 +14,12 @@ use dbus::strings::Path; use dbus_macros::{dbus_method, dbus_propmap, dbus_proxy_obj, generate_dbus_exporter}; use dbus_projection::DisconnectWatcher; use dbus_projection::{dbus_generated, impl_dbus_arg_from_into}; use dbus_projection::{dbus_generated, impl_dbus_arg_enum, impl_dbus_arg_from_into}; use crate::dbus_arg::{DBusArg, DBusArgError, RefArgToRust}; use num_traits::{FromPrimitive, ToPrimitive}; use std::convert::{TryFrom, TryInto}; use std::sync::Arc; Loading Loading @@ -44,6 +49,10 @@ pub struct BluetoothAudioDeviceDBus { } impl_dbus_arg_from_into!(HfpCodecCapability, i32); impl_dbus_arg_enum!(A2dpCodecIndex); impl_dbus_arg_from_into!(A2dpCodecSampleRate, i32); impl_dbus_arg_from_into!(A2dpCodecBitsPerSample, i32); impl_dbus_arg_from_into!(A2dpCodecChannelMode, i32); #[dbus_proxy_obj(BluetoothMediaCallback, "org.chromium.bluetooth.BluetoothMediaCallback")] impl IBluetoothMediaCallback for BluetoothMediaCallbackDBus { Loading Loading @@ -203,9 +212,11 @@ impl IBluetoothMedia for IBluetoothMediaDBus { #[dbus_method("SetAudioConfig")] fn set_audio_config( &mut self, sample_rate: i32, bits_per_sample: i32, channel_mode: i32, address: String, codec_type: A2dpCodecIndex, sample_rate: A2dpCodecSampleRate, bits_per_sample: A2dpCodecBitsPerSample, channel_mode: A2dpCodecChannelMode, ) -> bool { dbus_generated!() } Loading system/gd/rust/linux/stack/src/bluetooth_media.rs +66 −14 Original line number Diff line number Diff line Loading @@ -6,8 +6,8 @@ use bt_topshim::btif::{ }; use bt_topshim::profiles::a2dp::{ A2dp, A2dpCallbacks, A2dpCallbacksDispatcher, A2dpCodecBitsPerSample, A2dpCodecChannelMode, A2dpCodecConfig, A2dpCodecSampleRate, BtavAudioState, BtavConnectionState, PresentationPosition, A2dpCodecConfig, A2dpCodecIndex, A2dpCodecPriority, A2dpCodecSampleRate, BtavAudioState, BtavConnectionState, PresentationPosition, }; use bt_topshim::profiles::avrcp::{ Avrcp, AvrcpCallbacks, AvrcpCallbacksDispatcher, PlayerMetadata, Loading Loading @@ -90,9 +90,11 @@ pub trait IBluetoothMedia { fn set_audio_config( &mut self, sample_rate: i32, bits_per_sample: i32, channel_mode: i32, address: String, codec_type: A2dpCodecIndex, sample_rate: A2dpCodecSampleRate, bits_per_sample: A2dpCodecBitsPerSample, channel_mode: A2dpCodecChannelMode, ) -> bool; // Set the A2DP/AVRCP volume. Valid volume specified by the spec should be Loading Loading @@ -2164,21 +2166,71 @@ impl IBluetoothMedia for BluetoothMedia { fn set_audio_config( &mut self, sample_rate: i32, bits_per_sample: i32, channel_mode: i32, address: String, codec_type: A2dpCodecIndex, sample_rate: A2dpCodecSampleRate, bits_per_sample: A2dpCodecBitsPerSample, channel_mode: A2dpCodecChannelMode, ) -> bool { if !A2dpCodecSampleRate::validate_bits(sample_rate) || !A2dpCodecBitsPerSample::validate_bits(bits_per_sample) || !A2dpCodecChannelMode::validate_bits(channel_mode) { let addr = match RawAddress::from_string(address.clone()) { None => { warn!("Invalid device address {}", address); return false; } Some(addr) => addr, }; if self.a2dp_states.get(&addr).is_none() { warn!( "[{}]: Ignore set config event for unconnected or disconnected A2DP device", DisplayAddress(&addr) ); return false; } match self.a2dp.as_mut() { Some(a2dp) => { a2dp.set_audio_config(sample_rate, bits_per_sample, channel_mode); true let caps = self.a2dp_caps.get(&addr).unwrap_or(&Vec::new()).to_vec(); for cap in &caps { if A2dpCodecIndex::from(cap.codec_type) == codec_type { if (A2dpCodecSampleRate::from_bits(cap.sample_rate).unwrap() & sample_rate) != sample_rate { warn!("Unsupported sample rate {:?}", sample_rate); return false; } if (A2dpCodecBitsPerSample::from_bits(cap.bits_per_sample).unwrap() & bits_per_sample) != bits_per_sample { warn!("Unsupported bit depth {:?}", bits_per_sample); return false; } if (A2dpCodecChannelMode::from_bits(cap.channel_mode).unwrap() & channel_mode) != channel_mode { warn!("Unsupported channel mode {:?}", channel_mode); return false; } let config = vec![A2dpCodecConfig { codec_type: codec_type as i32, codec_priority: A2dpCodecPriority::Highest as i32, sample_rate: sample_rate.bits() as i32, bits_per_sample: bits_per_sample.bits() as i32, channel_mode: channel_mode.bits() as i32, ..Default::default() }]; a2dp.config_codec(addr, config); return true; } } warn!("Unsupported codec type {:?}", codec_type); false } None => { warn!("Uninitialized A2DP to set audio config"); Loading system/gd/rust/topshim/btav/btav_shim.cc +1 −1 Original line number Diff line number Diff line Loading @@ -246,7 +246,7 @@ static void audio_config_cb( } static bool mandatory_codec_preferred_cb(const RawAddress& addr) { rusty::mandatory_codec_preferred_callback(addr); return true; return false; } btav_source_callbacks_t g_callbacks = { Loading system/gd/rust/topshim/src/profiles/a2dp.rs +48 −7 Original line number Diff line number Diff line Loading @@ -4,6 +4,7 @@ use crate::topstack::get_dispatchers; use bitflags::bitflags; use num_derive::{FromPrimitive, ToPrimitive}; use num_traits::cast::FromPrimitive; use std::convert::{TryFrom, TryInto}; use std::sync::{Arc, Mutex}; use topshim_macros::{cb_variant, profile_enabled_or, profile_enabled_or_default}; Loading Loading @@ -38,8 +39,8 @@ impl From<u32> for BtavAudioState { } } #[derive(Debug, FromPrimitive, PartialEq, PartialOrd)] #[repr(u32)] #[derive(Debug, FromPrimitive, ToPrimitive, PartialEq, PartialOrd)] #[repr(i32)] pub enum A2dpCodecIndex { SrcSbc = 0, SrcAac, Loading Loading @@ -67,7 +68,7 @@ impl From<i32> for A2dpCodecIndex { } } #[derive(Debug, FromPrimitive, PartialEq, PartialOrd)] #[derive(Debug, FromPrimitive, ToPrimitive, PartialEq, PartialOrd)] #[repr(i32)] pub enum A2dpCodecPriority { Disabled = -1, Loading Loading @@ -113,6 +114,20 @@ impl A2dpCodecSampleRate { } } impl TryInto<i32> for A2dpCodecSampleRate { type Error = (); fn try_into(self) -> Result<i32, Self::Error> { Ok(self.bits()) } } impl TryFrom<i32> for A2dpCodecSampleRate { type Error = (); fn try_from(val: i32) -> Result<Self, Self::Error> { Self::from_bits(val).ok_or(()) } } bitflags! { pub struct A2dpCodecBitsPerSample: i32 { const SAMPLE_NONE = 0x0; Loading @@ -128,6 +143,20 @@ impl A2dpCodecBitsPerSample { } } impl TryInto<i32> for A2dpCodecBitsPerSample { type Error = (); fn try_into(self) -> Result<i32, Self::Error> { Ok(self.bits()) } } impl TryFrom<i32> for A2dpCodecBitsPerSample { type Error = (); fn try_from(val: i32) -> Result<Self, Self::Error> { Self::from_bits(val).ok_or(()) } } bitflags! { pub struct A2dpCodecChannelMode: i32 { const MODE_NONE = 0x0; Loading @@ -142,6 +171,20 @@ impl A2dpCodecChannelMode { } } impl TryInto<i32> for A2dpCodecChannelMode { type Error = (); fn try_into(self) -> Result<i32, Self::Error> { Ok(self.bits()) } } impl TryFrom<i32> for A2dpCodecChannelMode { type Error = (); fn try_from(val: i32) -> Result<Self, Self::Error> { Self::from_bits(val).ok_or(()) } } #[cxx::bridge(namespace = bluetooth::topshim::rust)] pub mod ffi { unsafe extern "C++" { Loading Loading @@ -364,10 +407,8 @@ impl A2dp { } #[profile_enabled_or] pub fn set_audio_config(&self, sample_rate: i32, bits_per_sample: i32, channel_mode: i32) { let config = A2dpCodecConfig { sample_rate, bits_per_sample, channel_mode, ..Default::default() }; self.internal.set_audio_config(config); pub fn config_codec(&self, addr: RawAddress, config: Vec<A2dpCodecConfig>) { self.internal.config_codec(addr, config); } #[profile_enabled_or(false)] Loading Loading
system/gd/rust/linux/client/src/dbus_iface.rs +14 −4 Original line number Diff line number Diff line Loading @@ -4,7 +4,10 @@ use bt_topshim::btif::{ BtBondState, BtConnectionState, BtDeviceType, BtDiscMode, BtPropertyType, BtSspVariant, BtStatus, BtTransport, BtVendorProductInfo, Uuid, Uuid128Bit, }; use bt_topshim::profiles::a2dp::{A2dpCodecConfig, PresentationPosition}; use bt_topshim::profiles::a2dp::{ A2dpCodecBitsPerSample, A2dpCodecChannelMode, A2dpCodecConfig, A2dpCodecIndex, A2dpCodecSampleRate, PresentationPosition, }; use bt_topshim::profiles::avrcp::PlayerMetadata; use bt_topshim::profiles::gatt::{AdvertisingStatus, GattStatus, LePhy}; use bt_topshim::profiles::hfp::HfpCodecCapability; Loading Loading @@ -415,6 +418,11 @@ pub struct A2dpCodecConfigDBus { codec_specific_4: i64, } impl_dbus_arg_enum!(A2dpCodecIndex); impl_dbus_arg_from_into!(A2dpCodecSampleRate, i32); impl_dbus_arg_from_into!(A2dpCodecBitsPerSample, i32); impl_dbus_arg_from_into!(A2dpCodecChannelMode, i32); impl_dbus_arg_from_into!(HfpCodecCapability, i32); #[dbus_propmap(BluetoothAudioDevice)] pub struct BluetoothAudioDeviceDBus { Loading Loading @@ -2524,9 +2532,11 @@ impl IBluetoothMedia for BluetoothMediaDBus { #[dbus_method("SetAudioConfig")] fn set_audio_config( &mut self, sample_rate: i32, bits_per_sample: i32, channel_mode: i32, address: String, codec_type: A2dpCodecIndex, sample_rate: A2dpCodecSampleRate, bits_per_sample: A2dpCodecBitsPerSample, channel_mode: A2dpCodecChannelMode, ) -> bool { dbus_generated!() } Loading
system/gd/rust/linux/service/src/iface_bluetooth_media.rs +16 −5 Original line number Diff line number Diff line use bt_topshim::profiles::a2dp::{A2dpCodecConfig, PresentationPosition}; use bt_topshim::profiles::a2dp::{ A2dpCodecBitsPerSample, A2dpCodecChannelMode, A2dpCodecConfig, A2dpCodecIndex, A2dpCodecSampleRate, PresentationPosition, }; use bt_topshim::profiles::avrcp::PlayerMetadata; use bt_topshim::profiles::hfp::HfpCodecCapability; use btstack::bluetooth_media::{BluetoothAudioDevice, IBluetoothMedia, IBluetoothMediaCallback}; Loading @@ -11,10 +14,12 @@ use dbus::strings::Path; use dbus_macros::{dbus_method, dbus_propmap, dbus_proxy_obj, generate_dbus_exporter}; use dbus_projection::DisconnectWatcher; use dbus_projection::{dbus_generated, impl_dbus_arg_from_into}; use dbus_projection::{dbus_generated, impl_dbus_arg_enum, impl_dbus_arg_from_into}; use crate::dbus_arg::{DBusArg, DBusArgError, RefArgToRust}; use num_traits::{FromPrimitive, ToPrimitive}; use std::convert::{TryFrom, TryInto}; use std::sync::Arc; Loading Loading @@ -44,6 +49,10 @@ pub struct BluetoothAudioDeviceDBus { } impl_dbus_arg_from_into!(HfpCodecCapability, i32); impl_dbus_arg_enum!(A2dpCodecIndex); impl_dbus_arg_from_into!(A2dpCodecSampleRate, i32); impl_dbus_arg_from_into!(A2dpCodecBitsPerSample, i32); impl_dbus_arg_from_into!(A2dpCodecChannelMode, i32); #[dbus_proxy_obj(BluetoothMediaCallback, "org.chromium.bluetooth.BluetoothMediaCallback")] impl IBluetoothMediaCallback for BluetoothMediaCallbackDBus { Loading Loading @@ -203,9 +212,11 @@ impl IBluetoothMedia for IBluetoothMediaDBus { #[dbus_method("SetAudioConfig")] fn set_audio_config( &mut self, sample_rate: i32, bits_per_sample: i32, channel_mode: i32, address: String, codec_type: A2dpCodecIndex, sample_rate: A2dpCodecSampleRate, bits_per_sample: A2dpCodecBitsPerSample, channel_mode: A2dpCodecChannelMode, ) -> bool { dbus_generated!() } Loading
system/gd/rust/linux/stack/src/bluetooth_media.rs +66 −14 Original line number Diff line number Diff line Loading @@ -6,8 +6,8 @@ use bt_topshim::btif::{ }; use bt_topshim::profiles::a2dp::{ A2dp, A2dpCallbacks, A2dpCallbacksDispatcher, A2dpCodecBitsPerSample, A2dpCodecChannelMode, A2dpCodecConfig, A2dpCodecSampleRate, BtavAudioState, BtavConnectionState, PresentationPosition, A2dpCodecConfig, A2dpCodecIndex, A2dpCodecPriority, A2dpCodecSampleRate, BtavAudioState, BtavConnectionState, PresentationPosition, }; use bt_topshim::profiles::avrcp::{ Avrcp, AvrcpCallbacks, AvrcpCallbacksDispatcher, PlayerMetadata, Loading Loading @@ -90,9 +90,11 @@ pub trait IBluetoothMedia { fn set_audio_config( &mut self, sample_rate: i32, bits_per_sample: i32, channel_mode: i32, address: String, codec_type: A2dpCodecIndex, sample_rate: A2dpCodecSampleRate, bits_per_sample: A2dpCodecBitsPerSample, channel_mode: A2dpCodecChannelMode, ) -> bool; // Set the A2DP/AVRCP volume. Valid volume specified by the spec should be Loading Loading @@ -2164,21 +2166,71 @@ impl IBluetoothMedia for BluetoothMedia { fn set_audio_config( &mut self, sample_rate: i32, bits_per_sample: i32, channel_mode: i32, address: String, codec_type: A2dpCodecIndex, sample_rate: A2dpCodecSampleRate, bits_per_sample: A2dpCodecBitsPerSample, channel_mode: A2dpCodecChannelMode, ) -> bool { if !A2dpCodecSampleRate::validate_bits(sample_rate) || !A2dpCodecBitsPerSample::validate_bits(bits_per_sample) || !A2dpCodecChannelMode::validate_bits(channel_mode) { let addr = match RawAddress::from_string(address.clone()) { None => { warn!("Invalid device address {}", address); return false; } Some(addr) => addr, }; if self.a2dp_states.get(&addr).is_none() { warn!( "[{}]: Ignore set config event for unconnected or disconnected A2DP device", DisplayAddress(&addr) ); return false; } match self.a2dp.as_mut() { Some(a2dp) => { a2dp.set_audio_config(sample_rate, bits_per_sample, channel_mode); true let caps = self.a2dp_caps.get(&addr).unwrap_or(&Vec::new()).to_vec(); for cap in &caps { if A2dpCodecIndex::from(cap.codec_type) == codec_type { if (A2dpCodecSampleRate::from_bits(cap.sample_rate).unwrap() & sample_rate) != sample_rate { warn!("Unsupported sample rate {:?}", sample_rate); return false; } if (A2dpCodecBitsPerSample::from_bits(cap.bits_per_sample).unwrap() & bits_per_sample) != bits_per_sample { warn!("Unsupported bit depth {:?}", bits_per_sample); return false; } if (A2dpCodecChannelMode::from_bits(cap.channel_mode).unwrap() & channel_mode) != channel_mode { warn!("Unsupported channel mode {:?}", channel_mode); return false; } let config = vec![A2dpCodecConfig { codec_type: codec_type as i32, codec_priority: A2dpCodecPriority::Highest as i32, sample_rate: sample_rate.bits() as i32, bits_per_sample: bits_per_sample.bits() as i32, channel_mode: channel_mode.bits() as i32, ..Default::default() }]; a2dp.config_codec(addr, config); return true; } } warn!("Unsupported codec type {:?}", codec_type); false } None => { warn!("Uninitialized A2DP to set audio config"); Loading
system/gd/rust/topshim/btav/btav_shim.cc +1 −1 Original line number Diff line number Diff line Loading @@ -246,7 +246,7 @@ static void audio_config_cb( } static bool mandatory_codec_preferred_cb(const RawAddress& addr) { rusty::mandatory_codec_preferred_callback(addr); return true; return false; } btav_source_callbacks_t g_callbacks = { Loading
system/gd/rust/topshim/src/profiles/a2dp.rs +48 −7 Original line number Diff line number Diff line Loading @@ -4,6 +4,7 @@ use crate::topstack::get_dispatchers; use bitflags::bitflags; use num_derive::{FromPrimitive, ToPrimitive}; use num_traits::cast::FromPrimitive; use std::convert::{TryFrom, TryInto}; use std::sync::{Arc, Mutex}; use topshim_macros::{cb_variant, profile_enabled_or, profile_enabled_or_default}; Loading Loading @@ -38,8 +39,8 @@ impl From<u32> for BtavAudioState { } } #[derive(Debug, FromPrimitive, PartialEq, PartialOrd)] #[repr(u32)] #[derive(Debug, FromPrimitive, ToPrimitive, PartialEq, PartialOrd)] #[repr(i32)] pub enum A2dpCodecIndex { SrcSbc = 0, SrcAac, Loading Loading @@ -67,7 +68,7 @@ impl From<i32> for A2dpCodecIndex { } } #[derive(Debug, FromPrimitive, PartialEq, PartialOrd)] #[derive(Debug, FromPrimitive, ToPrimitive, PartialEq, PartialOrd)] #[repr(i32)] pub enum A2dpCodecPriority { Disabled = -1, Loading Loading @@ -113,6 +114,20 @@ impl A2dpCodecSampleRate { } } impl TryInto<i32> for A2dpCodecSampleRate { type Error = (); fn try_into(self) -> Result<i32, Self::Error> { Ok(self.bits()) } } impl TryFrom<i32> for A2dpCodecSampleRate { type Error = (); fn try_from(val: i32) -> Result<Self, Self::Error> { Self::from_bits(val).ok_or(()) } } bitflags! { pub struct A2dpCodecBitsPerSample: i32 { const SAMPLE_NONE = 0x0; Loading @@ -128,6 +143,20 @@ impl A2dpCodecBitsPerSample { } } impl TryInto<i32> for A2dpCodecBitsPerSample { type Error = (); fn try_into(self) -> Result<i32, Self::Error> { Ok(self.bits()) } } impl TryFrom<i32> for A2dpCodecBitsPerSample { type Error = (); fn try_from(val: i32) -> Result<Self, Self::Error> { Self::from_bits(val).ok_or(()) } } bitflags! { pub struct A2dpCodecChannelMode: i32 { const MODE_NONE = 0x0; Loading @@ -142,6 +171,20 @@ impl A2dpCodecChannelMode { } } impl TryInto<i32> for A2dpCodecChannelMode { type Error = (); fn try_into(self) -> Result<i32, Self::Error> { Ok(self.bits()) } } impl TryFrom<i32> for A2dpCodecChannelMode { type Error = (); fn try_from(val: i32) -> Result<Self, Self::Error> { Self::from_bits(val).ok_or(()) } } #[cxx::bridge(namespace = bluetooth::topshim::rust)] pub mod ffi { unsafe extern "C++" { Loading Loading @@ -364,10 +407,8 @@ impl A2dp { } #[profile_enabled_or] pub fn set_audio_config(&self, sample_rate: i32, bits_per_sample: i32, channel_mode: i32) { let config = A2dpCodecConfig { sample_rate, bits_per_sample, channel_mode, ..Default::default() }; self.internal.set_audio_config(config); pub fn config_codec(&self, addr: RawAddress, config: Vec<A2dpCodecConfig>) { self.internal.config_codec(addr, config); } #[profile_enabled_or(false)] Loading