AudioPolicyManager: add support for Bluetooth LE audio codec selection
Add support for Bluetooth LE audio codec reconfiguration similarly to
what is supported for A2DP.
Bug: 309909149
Test: connect BT LE device and check correct codec selection
Change-Id: I1759314fcf0e757db617980aa2129e8bd8af53c5
diff --git a/media/libaudiohal/impl/DeviceHalAidl.cpp b/media/libaudiohal/impl/DeviceHalAidl.cpp
index a58ce1b..6a6557c 100644
--- a/media/libaudiohal/impl/DeviceHalAidl.cpp
+++ b/media/libaudiohal/impl/DeviceHalAidl.cpp
@@ -267,6 +267,9 @@
if (status_t status = filterAndRetrieveBtA2dpParameters(parameterKeys, &result); status != OK) {
ALOGW("%s: filtering or retrieving BT A2DP parameters failed: %d", __func__, status);
}
+ if (status_t status = filterAndRetrieveBtLeParameters(parameterKeys, &result); status != OK) {
+ ALOGW("%s: filtering or retrieving BT LE parameters failed: %d", __func__, status);
+ }
*values = result.toString();
return parseAndGetVendorParameters(mVendorExt, mModule, parameterKeys, values);
}
@@ -988,6 +991,23 @@
return OK;
}
+status_t DeviceHalAidl::filterAndRetrieveBtLeParameters(
+ AudioParameter &keys, AudioParameter *result) {
+ if (String8 key = String8(AudioParameter::keyReconfigLeSupported); keys.containsKey(key)) {
+ keys.remove(key);
+ if (mBluetoothLe != nullptr) {
+ bool supports;
+ RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(
+ mBluetoothLe->supportsOffloadReconfiguration(&supports)));
+ result->addInt(key, supports ? 1 : 0);
+ } else {
+ ALOGI("%s: no mBluetoothLe on %s", __func__, mInstance.c_str());
+ result->addInt(key, 0);
+ }
+ }
+ return OK;
+}
+
status_t DeviceHalAidl::filterAndUpdateBtA2dpParameters(AudioParameter ¶meters) {
std::optional<bool> a2dpEnabled;
std::optional<std::vector<VendorParameter>> reconfigureOffload;
@@ -1069,6 +1089,7 @@
status_t DeviceHalAidl::filterAndUpdateBtLeParameters(AudioParameter ¶meters) {
std::optional<bool> leEnabled;
+ std::optional<std::vector<VendorParameter>> reconfigureOffload;
(void)VALUE_OR_RETURN_STATUS(filterOutAndProcessParameter<String8>(
parameters, String8(AudioParameter::keyBtLeSuspended),
[&leEnabled](const String8& trueOrFalse) {
@@ -1083,9 +1104,27 @@
AudioParameter::keyBtLeSuspended, trueOrFalse.c_str());
return BAD_VALUE;
}));
+ (void)VALUE_OR_RETURN_STATUS(filterOutAndProcessParameter<String8>(
+ parameters, String8(AudioParameter::keyReconfigLe),
+ [&](const String8& value) -> status_t {
+ if (mVendorExt != nullptr) {
+ std::vector<VendorParameter> result;
+ RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(
+ mVendorExt->parseBluetoothLeReconfigureOffload(
+ std::string(value.c_str()), &result)));
+ reconfigureOffload = std::move(result);
+ } else {
+ reconfigureOffload = std::vector<VendorParameter>();
+ }
+ return OK;
+ }));
if (mBluetoothLe != nullptr && leEnabled.has_value()) {
return statusTFromBinderStatus(mBluetoothLe->setEnabled(leEnabled.value()));
}
+ if (mBluetoothLe != nullptr && reconfigureOffload.has_value()) {
+ return statusTFromBinderStatus(mBluetoothLe->reconfigureOffload(
+ reconfigureOffload.value()));
+ }
return OK;
}
diff --git a/media/libaudiohal/impl/DeviceHalAidl.h b/media/libaudiohal/impl/DeviceHalAidl.h
index 9493e47..f705db7 100644
--- a/media/libaudiohal/impl/DeviceHalAidl.h
+++ b/media/libaudiohal/impl/DeviceHalAidl.h
@@ -207,6 +207,7 @@
~DeviceHalAidl() override = default;
status_t filterAndRetrieveBtA2dpParameters(AudioParameter &keys, AudioParameter *result);
+ status_t filterAndRetrieveBtLeParameters(AudioParameter &keys, AudioParameter *result);
status_t filterAndUpdateBtA2dpParameters(AudioParameter ¶meters);
status_t filterAndUpdateBtHfpParameters(AudioParameter ¶meters);
status_t filterAndUpdateBtLeParameters(AudioParameter ¶meters);
diff --git a/media/libmediahelper/AudioParameter.cpp b/media/libmediahelper/AudioParameter.cpp
index f21ea53..e921bd2 100644
--- a/media/libmediahelper/AudioParameter.cpp
+++ b/media/libmediahelper/AudioParameter.cpp
@@ -75,6 +75,8 @@
const char * const AudioParameter::keyReconfigA2dp = AUDIO_PARAMETER_RECONFIG_A2DP;
const char * const AudioParameter::keyReconfigA2dpSupported = AUDIO_PARAMETER_A2DP_RECONFIG_SUPPORTED;
const char * const AudioParameter::keyBtLeSuspended = AUDIO_PARAMETER_KEY_BT_LE_SUSPENDED;
+const char * const AudioParameter::keyReconfigLe = AUDIO_PARAMETER_RECONFIG_LE;
+const char * const AudioParameter::keyReconfigLeSupported = AUDIO_PARAMETER_LE_RECONFIG_SUPPORTED;
// const char * const AudioParameter::keyDeviceSupportedEncapsulationModes =
// AUDIO_PARAMETER_DEVICE_SUP_ENCAPSULATION_MODES;
// const char * const AudioParameter::keyDeviceSupportedEncapsulationMetadataTypes =
diff --git a/media/libmediahelper/include/media/AudioParameter.h b/media/libmediahelper/include/media/AudioParameter.h
index 21d5117..61e6bcc 100644
--- a/media/libmediahelper/include/media/AudioParameter.h
+++ b/media/libmediahelper/include/media/AudioParameter.h
@@ -121,10 +121,14 @@
// keyReconfigA2dp: Ask HwModule to reconfigure A2DP offloaded codec
// keyReconfigA2dpSupported: Query if HwModule supports A2DP offload codec config
// keyBtLeSuspended: 'true' or 'false'
+ // keyReconfigLe: Ask HwModule to reconfigure LE offloaded codec
+ // keyReconfigLeSupported: Query if HwModule supports LE offload codec config
static const char * const keyBtA2dpSuspended;
static const char * const keyReconfigA2dp;
static const char * const keyReconfigA2dpSupported;
static const char * const keyBtLeSuspended;
+ static const char * const keyReconfigLe;
+ static const char * const keyReconfigLeSupported;
// For querying device supported encapsulation capabilities. All returned values are integer,
// which are bit fields composed from using encapsulation capability values as position bits.
diff --git a/services/audiopolicy/common/include/policy.h b/services/audiopolicy/common/include/policy.h
index d266e63..4643bd1 100644
--- a/services/audiopolicy/common/include/policy.h
+++ b/services/audiopolicy/common/include/policy.h
@@ -115,7 +115,7 @@
*/
static inline bool device_has_encoding_capability(audio_devices_t device)
{
- return audio_is_a2dp_out_device(device);
+ return audio_is_a2dp_out_device(device) || audio_is_ble_out_device(device);
}
/**
diff --git a/services/audiopolicy/managerdefault/AudioPolicyManager.cpp b/services/audiopolicy/managerdefault/AudioPolicyManager.cpp
index e8066fb..69d3b5d 100644
--- a/services/audiopolicy/managerdefault/AudioPolicyManager.cpp
+++ b/services/audiopolicy/managerdefault/AudioPolicyManager.cpp
@@ -511,11 +511,6 @@
const char *device_name,
audio_format_t encodedFormat)
{
- status_t status;
- String8 reply;
- AudioParameter param;
- int isReconfigA2dpSupported = 0;
-
ALOGV("handleDeviceConfigChange(() device: 0x%X, address %s name %s encodedFormat: 0x%X",
device, device_address, device_name, encodedFormat);
@@ -537,19 +532,22 @@
// Case 1: A2DP active device switches from primary to primary
// module
// Case 2: A2DP device config changes on primary module.
- if (audio_is_a2dp_out_device(device) && hasPrimaryOutput()) {
+ if (device_has_encoding_capability(device) && hasPrimaryOutput()) {
sp<HwModule> module = mHwModules.getModuleForDeviceType(device, encodedFormat);
audio_module_handle_t primaryHandle = mPrimaryOutput->getModuleHandle();
if (availablePrimaryOutputDevices().contains(devDesc) &&
(module != 0 && module->getHandle() == primaryHandle)) {
- reply = mpClientInterface->getParameters(
- AUDIO_IO_HANDLE_NONE,
- String8(AudioParameter::keyReconfigA2dpSupported));
+ bool isA2dp = audio_is_a2dp_out_device(device);
+ const String8 supportKey = isA2dp ? String8(AudioParameter::keyReconfigA2dpSupported)
+ : String8(AudioParameter::keyReconfigLeSupported);
+ String8 reply = mpClientInterface->getParameters(AUDIO_IO_HANDLE_NONE, supportKey);
AudioParameter repliedParameters(reply);
- repliedParameters.getInt(
- String8(AudioParameter::keyReconfigA2dpSupported), isReconfigA2dpSupported);
- if (isReconfigA2dpSupported) {
- const String8 key(AudioParameter::keyReconfigA2dp);
+ int isReconfigSupported;
+ repliedParameters.getInt(supportKey, isReconfigSupported);
+ if (isReconfigSupported) {
+ const String8 key = isA2dp ? String8(AudioParameter::keyReconfigA2dp)
+ : String8(AudioParameter::keyReconfigLe);
+ AudioParameter param;
param.add(key, String8("true"));
mpClientInterface->setParameters(AUDIO_IO_HANDLE_NONE, param.toString());
devDesc->setEncodedFormat(encodedFormat);
@@ -569,7 +567,7 @@
}
// Toggle the device state: UNAVAILABLE -> AVAILABLE
// This will force reading again the device configuration
- status = setDeviceConnectionState(device,
+ status_t status = setDeviceConnectionState(device,
AUDIO_POLICY_DEVICE_STATE_UNAVAILABLE,
device_address, device_name,
devDesc->getEncodedFormat());