summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
author Katherine Lai <laikatherine@google.com> 2024-06-10 21:44:22 +0000
committer Katherine Lai <laikatherine@google.com> 2024-06-13 18:20:45 +0000
commitd454b17727f977f96691556e445dbf40f9754919 (patch)
tree53cd12c6149bfd056f506d0edc894c2644f7aff0
parente4ba9f2c87787337a78189bd6443bb5731ae8d37 (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.rs4
-rw-r--r--system/gd/rust/linux/client/src/dbus_iface.rs5
-rw-r--r--system/gd/rust/linux/service/src/iface_bluetooth.rs5
-rw-r--r--system/gd/rust/linux/stack/src/bluetooth.rs19
-rw-r--r--system/gd/rust/topshim/src/btif.rs11
-rw-r--r--system/gd/rust/topshim/src/sysprop.rs49
-rw-r--r--system/gd/sysprops/sysprops_module.cc1
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",