diff options
author | 2024-06-10 21:44:22 +0000 | |
---|---|---|
committer | 2024-06-13 18:20:45 +0000 | |
commit | d454b17727f977f96691556e445dbf40f9754919 (patch) | |
tree | 53cd12c6149bfd056f506d0edc894c2644f7aff0 | |
parent | e4ba9f2c87787337a78189bd6443bb5731ae8d37 (diff) |
floss: Add IsLEAudioStable API
Add new API that returns true for a remote device if its model
is in the allowlist. The allowlist is stored as sysprop
persist.bluetooth.leaudio.allow_list. Add handling for getting
this sysprop in Rust. Also add RemoteModelName property in
btif to get the remote device's model name.
Bug: 341977695
Tag: #floss
Test: btclient - device info <Samsung Galaxy Pro Buds2>
Test: mmm packages/modules/Bluetooth
Flag: EXEMPT, floss change for ChromeOS only
Change-Id: Iafe55d86a0cd67ad20214b9c534fc4bd2420d0e7
-rw-r--r-- | system/gd/rust/linux/client/src/command_handler.rs | 4 | ||||
-rw-r--r-- | system/gd/rust/linux/client/src/dbus_iface.rs | 5 | ||||
-rw-r--r-- | system/gd/rust/linux/service/src/iface_bluetooth.rs | 5 | ||||
-rw-r--r-- | system/gd/rust/linux/stack/src/bluetooth.rs | 19 | ||||
-rw-r--r-- | system/gd/rust/topshim/src/btif.rs | 11 | ||||
-rw-r--r-- | system/gd/rust/topshim/src/sysprop.rs | 49 | ||||
-rw-r--r-- | system/gd/sysprops/sysprops_module.cc | 1 |
7 files changed, 91 insertions, 3 deletions
diff --git a/system/gd/rust/linux/client/src/command_handler.rs b/system/gd/rust/linux/client/src/command_handler.rs index e586eb5193..25ad024d8a 100644 --- a/system/gd/rust/linux/client/src/command_handler.rs +++ b/system/gd/rust/linux/client/src/command_handler.rs @@ -889,6 +889,7 @@ impl CommandHandler { uuids, wake_allowed, dual_mode_audio, + le_audio_stable, ) = { let ctx = self.lock_context(); let adapter = ctx.adapter_dbus.as_ref().unwrap(); @@ -908,6 +909,7 @@ impl CommandHandler { let uuids = adapter.get_remote_uuids(device.clone()); let wake_allowed = adapter.get_remote_wake_allowed(device.clone()); let dual_mode_audio = adapter.is_dual_mode_audio_sink_device(device.clone()); + let le_audio_stable = adapter.is_le_audio_stable(device.clone()); ( name, @@ -921,6 +923,7 @@ impl CommandHandler { uuids, wake_allowed, dual_mode_audio, + le_audio_stable, ) }; @@ -935,6 +938,7 @@ impl CommandHandler { print_info!("Bond State: {:?}", bonded); print_info!("Connection State: {}", connection_state); print_info!("Dual Mode Audio Device: {}", dual_mode_audio); + print_info!("Is LE Audio Stable: {}", le_audio_stable); print_info!( "Uuids: {}", DisplayList( diff --git a/system/gd/rust/linux/client/src/dbus_iface.rs b/system/gd/rust/linux/client/src/dbus_iface.rs index 6a2fe45b11..e3f070e70a 100644 --- a/system/gd/rust/linux/client/src/dbus_iface.rs +++ b/system/gd/rust/linux/client/src/dbus_iface.rs @@ -1036,6 +1036,11 @@ impl IBluetooth for BluetoothDBus { dbus_generated!() } + #[dbus_method("IsLEAudioStable")] + fn is_le_audio_stable(&self, device: BluetoothDevice) -> bool { + dbus_generated!() + } + #[dbus_method("GetDumpsys")] fn get_dumpsys(&self) -> String { dbus_generated!() diff --git a/system/gd/rust/linux/service/src/iface_bluetooth.rs b/system/gd/rust/linux/service/src/iface_bluetooth.rs index 063b333134..3a1fc6530e 100644 --- a/system/gd/rust/linux/service/src/iface_bluetooth.rs +++ b/system/gd/rust/linux/service/src/iface_bluetooth.rs @@ -771,6 +771,11 @@ impl IBluetooth for IBluetoothDBus { dbus_generated!() } + #[dbus_method("IsLEAudioStable", DBusLog::Disable)] + fn is_le_audio_stable(&self, device: BluetoothDevice) -> bool { + dbus_generated!() + } + #[dbus_method("GetDumpsys", DBusLog::Disable)] fn get_dumpsys(&self) -> String { dbus_generated!() diff --git a/system/gd/rust/linux/stack/src/bluetooth.rs b/system/gd/rust/linux/stack/src/bluetooth.rs index 7898e8b57b..69388bcd8d 100644 --- a/system/gd/rust/linux/stack/src/bluetooth.rs +++ b/system/gd/rust/linux/stack/src/bluetooth.rs @@ -17,7 +17,7 @@ use bt_topshim::{ }, profiles::sdp::{BtSdpRecord, Sdp, SdpCallbacks, SdpCallbacksDispatcher}, profiles::ProfileConnectionState, - topstack, + sysprop, topstack, }; use bt_utils::array_utils; @@ -265,6 +265,9 @@ pub trait IBluetooth { /// LE Audio sink roles). fn is_dual_mode_audio_sink_device(&self, device: BluetoothDevice) -> bool; + /// Returns whether the remote device is LE audio stable. + fn is_le_audio_stable(&self, device: BluetoothDevice) -> bool; + /// Gets diagnostic output. fn get_dumpsys(&self) -> String; } @@ -3004,6 +3007,20 @@ impl IBluetooth for Bluetooth { }) } + fn is_le_audio_stable(&self, device: BluetoothDevice) -> bool { + let model_name = + match self.get_remote_device_property(&device, &BtPropertyType::RemoteModelName) { + Some(BluetoothProperty::RemoteModelName(name)) => name, + _ => { + return false; + } + }; + + sysprop::get_string(sysprop::PropertyString::LeAudioAllowList) + .split(",") + .any(|model| model == model_name) + } + fn get_dumpsys(&self) -> String { NamedTempFile::new() .and_then(|file| { diff --git a/system/gd/rust/topshim/src/btif.rs b/system/gd/rust/topshim/src/btif.rs index 0ce1be07d5..4b9e1b9127 100644 --- a/system/gd/rust/topshim/src/btif.rs +++ b/system/gd/rust/topshim/src/btif.rs @@ -167,7 +167,7 @@ pub enum BtPropertyType { // Unimplemented: // BT_PROPERTY_REMOTE_ASHA_CAPABILITY, // BT_PROPERTY_REMOTE_ASHA_TRUNCATED_HISYNCID, - // BT_PROPERTY_REMOTE_MODEL_NUM, + RemoteModelName = 0x17, RemoteAddrType = 0x18, Unknown = 0xFE, @@ -583,6 +583,7 @@ pub enum BluetoothProperty { RemoteIsCoordinatedSetMember(bool), Appearance(u16), VendorProductInfo(BtVendorProductInfo), + RemoteModelName(String), RemoteAddrType(BtAddrType), RemoteDeviceTimestamp(), @@ -627,6 +628,7 @@ impl BluetoothProperty { BluetoothProperty::Appearance(_) => BtPropertyType::Appearance, BluetoothProperty::VendorProductInfo(_) => BtPropertyType::VendorProductInfo, BluetoothProperty::RemoteDeviceTimestamp() => BtPropertyType::RemoteDeviceTimestamp, + BluetoothProperty::RemoteModelName(_) => BtPropertyType::RemoteModelName, BluetoothProperty::RemoteAddrType(_) => BtPropertyType::RemoteAddrType, BluetoothProperty::Unknown() => BtPropertyType::Unknown, } @@ -658,6 +660,7 @@ impl BluetoothProperty { BluetoothProperty::RemoteIsCoordinatedSetMember(_) => mem::size_of::<bool>(), BluetoothProperty::Appearance(_) => mem::size_of::<u16>(), BluetoothProperty::VendorProductInfo(_) => mem::size_of::<BtVendorProductInfo>(), + BluetoothProperty::RemoteModelName(name) => name.len(), BluetoothProperty::RemoteAddrType(_) => mem::size_of::<BtAddrType>(), // TODO(abps) - Figure out sizes for these @@ -767,6 +770,9 @@ impl BluetoothProperty { }; data.copy_from_slice(&slice); } + BluetoothProperty::RemoteModelName(name) => { + data.copy_from_slice(name.as_bytes()); + } BluetoothProperty::RemoteAddrType(addr_type) => { data.copy_from_slice( &BtAddrType::to_u32(addr_type).unwrap_or_default().to_ne_bytes(), @@ -848,6 +854,9 @@ impl From<bindings::bt_property_t> for BluetoothProperty { let v = unsafe { (prop.val as *const BtVendorProductInfo).read_unaligned() }; BluetoothProperty::VendorProductInfo(BtVendorProductInfo::from(v)) } + BtPropertyType::RemoteModelName => { + BluetoothProperty::RemoteModelName(ascii_to_string(slice, len)) + } BtPropertyType::RemoteAddrType => BluetoothProperty::RemoteAddrType( BtAddrType::from_u32(u32_from_bytes(slice)).unwrap_or(BtAddrType::Unknown), ), diff --git a/system/gd/rust/topshim/src/sysprop.rs b/system/gd/rust/topshim/src/sysprop.rs index 6dd0084567..0020134705 100644 --- a/system/gd/rust/topshim/src/sysprop.rs +++ b/system/gd/rust/topshim/src/sysprop.rs @@ -3,7 +3,9 @@ use std::ffi::CString; use crate::bindings::root as bindings; -use crate::utils::LTCheckedPtr; +use crate::utils::{LTCheckedPtr, LTCheckedPtrMut}; + +const PROPERTY_VALUE_MAX: usize = 92; /// List of properties accessible to Rust. Add new ones here as they become /// necessary. @@ -94,3 +96,48 @@ pub fn get_bool(prop: PropertyBool) -> bool { // SAFETY: Calling C++ function with compatible types (null terminated string and bool) is safe. unsafe { bindings::osi_property_get_bool(key_cptr.into(), default_value) } } + +/// List of string properties accessible to Rust. Add new ones here as they become +/// necessary. +pub enum PropertyString { + // bluetooth.le_audio + LeAudioAllowList, +} + +impl Into<(CString, CString)> for PropertyString { + /// Convert the property into the property key name and a default value. + fn into(self) -> (CString, CString) { + let (key, default_value) = match self { + PropertyString::LeAudioAllowList => ("persist.bluetooth.leaudio.allow_list", ""), + }; + + ( + CString::new(key).expect("CString::new failed on sysprop key"), + CString::new(default_value).expect("CString::new failed on sysprop default_value"), + ) + } +} + +/// Get the string value for a system property. +pub fn get_string(prop: PropertyString) -> String { + let (key, default_value): (CString, CString) = prop.into(); + let key_cptr = LTCheckedPtr::from(&key); + let default_val_cptr = LTCheckedPtr::from(&default_value); + let mut dest = vec![0u8; PROPERTY_VALUE_MAX]; + let dest_cptr = LTCheckedPtrMut::from(&mut dest); + + // SAFETY: Calling C++ function with compatible types (null terminated strings) is safe. + let len = unsafe { + bindings::osi_property_get( + key_cptr.into(), + dest_cptr.cast_into::<std::os::raw::c_char>(), + default_val_cptr.into(), + ) + }; + if len <= 0 { + return "".to_string(); + } + + dest.resize(len as usize, b'\0'); + String::from_utf8(dest).expect("Found invalid UTF-8") +} diff --git a/system/gd/sysprops/sysprops_module.cc b/system/gd/sysprops/sysprops_module.cc index 64b9e19fe0..e0a2923a28 100644 --- a/system/gd/sysprops/sysprops_module.cc +++ b/system/gd/sysprops/sysprops_module.cc @@ -122,6 +122,7 @@ void SyspropsModule::parse_config(std::string file_path) { // LE Audio "bluetooth.le_audio.enable_le_audio_only", "bluetooth.leaudio.dual_bidirection_swb.supported", + "persist.bluetooth.leaudio.allow_list", // SCO "bluetooth.sco.disable_enhanced_connection", "bluetooth.sco.swb_supported", |