Populate `audioLocation` from XML file for LE Audio codec provider
Bug: 331809026
Test: mmm hardware/interfaces/bluetooth/audio/utils
Change-Id: I480ea5523c8c90f2724179f377c5cfe1a278b0bd
diff --git a/bluetooth/audio/utils/Android.bp b/bluetooth/audio/utils/Android.bp
index d931c4d..8870e95 100644
--- a/bluetooth/audio/utils/Android.bp
+++ b/bluetooth/audio/utils/Android.bp
@@ -90,9 +90,6 @@
cc_test {
name: "BluetoothLeAudioCodecsProviderTest",
- defaults: [
- "latest_android_hardware_bluetooth_audio_ndk_shared",
- ],
srcs: [
"aidl_session/BluetoothLeAudioCodecsProvider.cpp",
"aidl_session/BluetoothLeAudioCodecsProviderTest.cpp",
diff --git a/bluetooth/audio/utils/aidl_session/BluetoothLeAudioCodecsProvider.cpp b/bluetooth/audio/utils/aidl_session/BluetoothLeAudioCodecsProvider.cpp
index 473777c..59c43a4 100644
--- a/bluetooth/audio/utils/aidl_session/BluetoothLeAudioCodecsProvider.cpp
+++ b/bluetooth/audio/utils/aidl_session/BluetoothLeAudioCodecsProvider.cpp
@@ -119,19 +119,36 @@
// Mapping octetsPerCodecFrame to bitdepth for easier comparison.
transport.bitdepth.push_back(codec_config.getOctetsPerCodecFrame());
transport.frameDurationUs.push_back(codec_config.getFrameDurationUs());
- switch (strategy_config.getAudioLocation()) {
- case setting::AudioLocation::MONO:
+ if (strategy_config.hasAudioLocation()) {
+ switch (strategy_config.getAudioLocation()) {
+ case setting::AudioLocation::MONO:
+ if (strategy_config_channel_count == 1)
+ transport.channelMode.push_back(ChannelMode::MONO);
+ else
+ transport.channelMode.push_back(ChannelMode::DUALMONO);
+ break;
+ case setting::AudioLocation::STEREO:
+ transport.channelMode.push_back(ChannelMode::STEREO);
+ break;
+ default:
+ transport.channelMode.push_back(ChannelMode::UNKNOWN);
+ break;
+ }
+ } else if (strategy_config.hasAudioChannelAllocation()) {
+ auto count =
+ std::bitset<32>(strategy_config.getAudioChannelAllocation()).count();
+ if (count <= 1) {
if (strategy_config_channel_count == 1)
transport.channelMode.push_back(ChannelMode::MONO);
else
transport.channelMode.push_back(ChannelMode::DUALMONO);
- break;
- case setting::AudioLocation::STEREO:
+ } else if (count == 2) {
transport.channelMode.push_back(ChannelMode::STEREO);
- break;
- default:
+ } else {
transport.channelMode.push_back(ChannelMode::UNKNOWN);
- break;
+ }
+ } else {
+ transport.channelMode.push_back(ChannelMode::UNKNOWN);
}
}
@@ -336,8 +353,12 @@
for (const auto& scenario : supported_scenarios) {
UnicastCapability unicast_encode_capability =
GetUnicastCapability(scenario.getEncode());
+ LOG(INFO) << __func__ << ": Unicast capability encode = "
+ << unicast_encode_capability.toString();
UnicastCapability unicast_decode_capability =
GetUnicastCapability(scenario.getDecode());
+ LOG(INFO) << __func__ << ": Unicast capability decode = "
+ << unicast_decode_capability.toString();
BroadcastCapability broadcast_capability = {.codecType =
CodecType::UNKNOWN};
@@ -384,22 +405,36 @@
return {.codecType = CodecType::UNKNOWN};
}
+ // Populate audio location
+ AudioLocation audio_location = AudioLocation::UNKNOWN;
+ if (strategy_configuration_iter->second.hasAudioLocation()) {
+ audio_location = GetAudioLocation(
+ strategy_configuration_iter->second.getAudioLocation());
+ }
+
+ // Populate audio channel allocation
+ std::optional<CodecSpecificConfigurationLtv::AudioChannelAllocation>
+ audio_channel_allocation = std::nullopt;
+ if (strategy_configuration_iter->second.hasAudioChannelAllocation()) {
+ LOG(INFO) << __func__ << ": has allocation";
+ CodecSpecificConfigurationLtv::AudioChannelAllocation tmp;
+ tmp.bitmask =
+ strategy_configuration_iter->second.getAudioChannelAllocation();
+ audio_channel_allocation = tmp;
+ }
+
CodecType codec_type =
GetCodecType(codec_configuration_iter->second.getCodec());
if (codec_type == CodecType::LC3) {
return ComposeUnicastCapability(
- codec_type,
- GetAudioLocation(
- strategy_configuration_iter->second.getAudioLocation()),
+ codec_type, audio_location, audio_channel_allocation,
strategy_configuration_iter->second.getConnectedDevice(),
strategy_configuration_iter->second.getChannelCount(),
ComposeLc3Capability(codec_configuration_iter->second));
} else if (codec_type == CodecType::APTX_ADAPTIVE_LE ||
codec_type == CodecType::APTX_ADAPTIVE_LEX) {
return ComposeUnicastCapability(
- codec_type,
- GetAudioLocation(
- strategy_configuration_iter->second.getAudioLocation()),
+ codec_type, audio_location, audio_channel_allocation,
strategy_configuration_iter->second.getConnectedDevice(),
strategy_configuration_iter->second.getChannelCount(),
ComposeAptxAdaptiveLeCapability(codec_configuration_iter->second));
@@ -435,11 +470,27 @@
std::vector<std::optional<Lc3Capabilities>> bcastLc3Cap(
1, std::optional(ComposeLc3Capability(codec_configuration_iter->second)));
+ // Populate audio location
+ AudioLocation audio_location = AudioLocation::UNKNOWN;
+ if (strategy_configuration_iter->second.hasAudioLocation()) {
+ audio_location = GetAudioLocation(
+ strategy_configuration_iter->second.getAudioLocation());
+ }
+
+ // Populate audio channel allocation
+ std::optional<CodecSpecificConfigurationLtv::AudioChannelAllocation>
+ audio_channel_allocation = std::nullopt;
+ if (strategy_configuration_iter->second.hasAudioChannelAllocation()) {
+ LOG(INFO) << __func__ << ": has allocation";
+ CodecSpecificConfigurationLtv::AudioChannelAllocation tmp;
+ tmp.bitmask =
+ strategy_configuration_iter->second.getAudioChannelAllocation();
+ audio_channel_allocation = tmp;
+ }
+
if (codec_type == CodecType::LC3) {
return ComposeBroadcastCapability(
- codec_type,
- GetAudioLocation(
- strategy_configuration_iter->second.getAudioLocation()),
+ codec_type, audio_location, audio_channel_allocation,
strategy_configuration_iter->second.getChannelCount(), bcastLc3Cap);
}
return {.codecType = CodecType::UNKNOWN};
@@ -448,16 +499,21 @@
template <class T>
BroadcastCapability BluetoothLeAudioCodecsProvider::ComposeBroadcastCapability(
const CodecType& codec_type, const AudioLocation& audio_location,
+ const std::optional<CodecSpecificConfigurationLtv::AudioChannelAllocation>&
+ audio_channel_allocation,
const uint8_t& channel_count, const std::vector<T>& capability) {
return {.codecType = codec_type,
.supportedChannel = audio_location,
.channelCountPerStream = channel_count,
- .leAudioCodecCapabilities = std::optional(capability)};
+ .leAudioCodecCapabilities = std::optional(capability),
+ .audioLocation = audio_channel_allocation};
}
template <class T>
UnicastCapability BluetoothLeAudioCodecsProvider::ComposeUnicastCapability(
const CodecType& codec_type, const AudioLocation& audio_location,
+ const std::optional<CodecSpecificConfigurationLtv::AudioChannelAllocation>&
+ audio_channel_allocation,
const uint8_t& device_cnt, const uint8_t& channel_count,
const T& capability) {
return {
@@ -467,6 +523,7 @@
.channelCountPerDevice = channel_count,
.leAudioCodecCapabilities =
UnicastCapability::LeAudioCodecCapabilities(capability),
+ .audioLocation = audio_channel_allocation,
};
}
@@ -519,38 +576,87 @@
codec_configuration.hasOctetsPerCodecFrame();
}
+bool IsValidStereoAudioLocation(
+ const setting::StrategyConfiguration& strategy_configuration) {
+ if ((strategy_configuration.getConnectedDevice() == 2 &&
+ strategy_configuration.getChannelCount() == 1) ||
+ (strategy_configuration.getConnectedDevice() == 1 &&
+ strategy_configuration.getChannelCount() == 2)) {
+ // Stereo
+ // 1. two connected device, one for L one for R
+ // 2. one connected device for both L and R
+ return true;
+ } else if (strategy_configuration.getConnectedDevice() == 0 &&
+ strategy_configuration.getChannelCount() == 2) {
+ // Broadcast
+ return true;
+ }
+ return false;
+}
+
+bool IsValidMonoAudioLocation(
+ const setting::StrategyConfiguration& strategy_configuration) {
+ if (strategy_configuration.getConnectedDevice() == 1 &&
+ strategy_configuration.getChannelCount() == 1) {
+ return true;
+ }
+ return false;
+}
+
+bool IsValidAudioLocation(
+ const setting::StrategyConfiguration& strategy_configuration) {
+ if (strategy_configuration.getAudioLocation() ==
+ setting::AudioLocation::STEREO)
+ return IsValidStereoAudioLocation(strategy_configuration);
+ else if (strategy_configuration.getAudioLocation() ==
+ setting::AudioLocation::MONO)
+ return IsValidMonoAudioLocation(strategy_configuration);
+ return false;
+}
+
+bool IsValidAudioChannelAllocation(
+ const setting::StrategyConfiguration& strategy_configuration) {
+ // First, ensure that there's only 2 bitmask enabled
+ int audio_channel_allocation =
+ strategy_configuration.getAudioChannelAllocation();
+ int count = 0;
+ for (int bit = 0; bit < 32; ++bit)
+ if (audio_channel_allocation & (1 << bit)) ++count;
+ if (count > 2) {
+ LOG(WARNING) << "Cannot parse more than 2 audio location, input is "
+ << audio_channel_allocation;
+ return false;
+ }
+
+ if (count == 2)
+ return IsValidStereoAudioLocation(strategy_configuration);
+ else
+ return IsValidMonoAudioLocation(strategy_configuration);
+}
+
bool BluetoothLeAudioCodecsProvider::IsValidStrategyConfiguration(
const setting::StrategyConfiguration& strategy_configuration) {
if (!strategy_configuration.hasName() ||
- !strategy_configuration.hasAudioLocation() ||
!strategy_configuration.hasConnectedDevice() ||
!strategy_configuration.hasChannelCount()) {
return false;
}
- if (strategy_configuration.getAudioLocation() ==
- setting::AudioLocation::STEREO) {
- if ((strategy_configuration.getConnectedDevice() == 2 &&
- strategy_configuration.getChannelCount() == 1) ||
- (strategy_configuration.getConnectedDevice() == 1 &&
- strategy_configuration.getChannelCount() == 2)) {
- // Stereo
- // 1. two connected device, one for L one for R
- // 2. one connected device for both L and R
- return true;
- } else if (strategy_configuration.getConnectedDevice() == 0 &&
- strategy_configuration.getChannelCount() == 2) {
- // Broadcast
- return true;
- }
- } else if (strategy_configuration.getAudioLocation() ==
- setting::AudioLocation::MONO) {
- if (strategy_configuration.getConnectedDevice() == 1 &&
- strategy_configuration.getChannelCount() == 1) {
- // Mono
- return true;
- }
- }
- return false;
+
+ // Both audio location field cannot be empty
+ if (!strategy_configuration.hasAudioLocation() &&
+ !strategy_configuration.hasAudioChannelAllocation())
+ return false;
+
+ // Any audio location field that presents must be valid
+ if (strategy_configuration.hasAudioLocation() &&
+ !IsValidAudioLocation(strategy_configuration))
+ return false;
+
+ if (strategy_configuration.hasAudioChannelAllocation() &&
+ !IsValidAudioChannelAllocation(strategy_configuration))
+ return false;
+
+ return true;
}
} // namespace audio
diff --git a/bluetooth/audio/utils/aidl_session/BluetoothLeAudioCodecsProvider.h b/bluetooth/audio/utils/aidl_session/BluetoothLeAudioCodecsProvider.h
index 5bf67e2..23b2bb6 100644
--- a/bluetooth/audio/utils/aidl_session/BluetoothLeAudioCodecsProvider.h
+++ b/bluetooth/audio/utils/aidl_session/BluetoothLeAudioCodecsProvider.h
@@ -23,6 +23,7 @@
#include <vector>
#include "aidl/android/hardware/bluetooth/audio/CodecInfo.h"
+#include "aidl/android/hardware/bluetooth/audio/CodecSpecificConfigurationLtv.h"
#include "aidl/android/hardware/bluetooth/audio/SessionType.h"
#include "aidl_android_hardware_bluetooth_audio_setting.h"
@@ -84,12 +85,18 @@
template <class T>
static inline UnicastCapability ComposeUnicastCapability(
const CodecType& codec_type, const AudioLocation& audio_location,
+ const std::optional<
+ CodecSpecificConfigurationLtv::AudioChannelAllocation>&
+ audio_channel_allocation,
const uint8_t& device_cnt, const uint8_t& channel_count,
const T& capability);
template <class T>
static inline BroadcastCapability ComposeBroadcastCapability(
const CodecType& codec_type, const AudioLocation& audio_location,
+ const std::optional<
+ CodecSpecificConfigurationLtv::AudioChannelAllocation>&
+ audio_channel_allocation,
const uint8_t& channel_count, const std::vector<T>& capability);
static inline Lc3Capabilities ComposeLc3Capability(
diff --git a/bluetooth/audio/utils/le_audio_codec_capabilities/le_audio_codec_capabilities.xml b/bluetooth/audio/utils/le_audio_codec_capabilities/le_audio_codec_capabilities.xml
index eaace78..b6ebbd9 100644
--- a/bluetooth/audio/utils/le_audio_codec_capabilities/le_audio_codec_capabilities.xml
+++ b/bluetooth/audio/utils/le_audio_codec_capabilities/le_audio_codec_capabilities.xml
@@ -69,9 +69,9 @@
<codecConfiguration name="APTX_ADAPTIVE_LEX_96k" codec="APTX_ADAPTIVE_LEX" samplingFrequency="96000" frameDurationUs="10000" octetsPerCodecFrame="816"/>
</codecConfigurationList>
<strategyConfigurationList>
- <strategyConfiguration name="STEREO_ONE_CIS_PER_DEVICE" audioLocation="STEREO" connectedDevice="2" channelCount="1"/>
- <strategyConfiguration name="STEREO_TWO_CISES_PER_DEVICE" audioLocation="STEREO" connectedDevice="1" channelCount="2"/>
- <strategyConfiguration name="MONO_ONE_CIS_PER_DEVICE" audioLocation="MONO" connectedDevice="1" channelCount="1"/>
- <strategyConfiguration name="BROADCAST_STEREO" audioLocation="STEREO" connectedDevice="0" channelCount="2"/>
+ <strategyConfiguration name="STEREO_ONE_CIS_PER_DEVICE" audioLocation="STEREO" connectedDevice="2" channelCount="1" audioChannelAllocation="3"/>
+ <strategyConfiguration name="STEREO_TWO_CISES_PER_DEVICE" audioLocation="STEREO" connectedDevice="1" channelCount="2" audioChannelAllocation="3"/>
+ <strategyConfiguration name="MONO_ONE_CIS_PER_DEVICE" audioLocation="MONO" connectedDevice="1" channelCount="1" audioChannelAllocation="4"/>
+ <strategyConfiguration name="BROADCAST_STEREO" audioLocation="STEREO" connectedDevice="0" channelCount="2" audioChannelAllocation="3"/>
</strategyConfigurationList>
</leAudioOffloadSetting>
diff --git a/bluetooth/audio/utils/le_audio_codec_capabilities/le_audio_codec_capabilities.xsd b/bluetooth/audio/utils/le_audio_codec_capabilities/le_audio_codec_capabilities.xsd
index 03c8ade..d9ccab5 100644
--- a/bluetooth/audio/utils/le_audio_codec_capabilities/le_audio_codec_capabilities.xsd
+++ b/bluetooth/audio/utils/le_audio_codec_capabilities/le_audio_codec_capabilities.xsd
@@ -56,9 +56,12 @@
<xs:element name="strategyConfiguration">
<xs:complexType>
<xs:attribute name="name" type="xs:string"/>
+ <!-- Deprecated definition of Audio Location, please use audioLocationInt -->
<xs:attribute name="audioLocation" type="audioLocation"/>
<xs:attribute name="connectedDevice" type="xs:unsignedByte"/>
<xs:attribute name="channelCount" type="xs:unsignedByte"/>
+ <!-- Integer Audio Location to populate to audioLocation if present -->
+ <xs:attribute name="audioChannelAllocation" type="xs:int"/>
</xs:complexType>
</xs:element>
<xs:simpleType name="audioLocation">
diff --git a/bluetooth/audio/utils/le_audio_codec_capabilities/schema/current.txt b/bluetooth/audio/utils/le_audio_codec_capabilities/schema/current.txt
index a882174..b6c2f03 100644
--- a/bluetooth/audio/utils/le_audio_codec_capabilities/schema/current.txt
+++ b/bluetooth/audio/utils/le_audio_codec_capabilities/schema/current.txt
@@ -81,10 +81,12 @@
public class StrategyConfiguration {
ctor public StrategyConfiguration();
+ method public int getAudioChannelAllocation();
method public aidl.android.hardware.bluetooth.audio.setting.AudioLocation getAudioLocation();
method public short getChannelCount();
method public short getConnectedDevice();
method public String getName();
+ method public void setAudioChannelAllocation(int);
method public void setAudioLocation(aidl.android.hardware.bluetooth.audio.setting.AudioLocation);
method public void setChannelCount(short);
method public void setConnectedDevice(short);