diff --git a/bluetooth/audio/aidl/vts/VtsHalBluetoothAudioTargetTest.cpp b/bluetooth/audio/aidl/vts/VtsHalBluetoothAudioTargetTest.cpp index e9b74b771c..128ef61403 100644 --- a/bluetooth/audio/aidl/vts/VtsHalBluetoothAudioTargetTest.cpp +++ b/bluetooth/audio/aidl/vts/VtsHalBluetoothAudioTargetTest.cpp @@ -1566,6 +1566,7 @@ TEST_P(BluetoothAudioProviderLeAudioBroadcastHardwareAidl, }; for (auto& lc3_config : lc3_codec_configs) { + le_audio_broadcast_config.streamMap.resize(1); le_audio_broadcast_config.streamMap[0] .leAudioCodecConfig.set( lc3_config); diff --git a/bluetooth/audio/utils/aidl_session/BluetoothLeAudioCodecsProvider.cpp b/bluetooth/audio/utils/aidl_session/BluetoothLeAudioCodecsProvider.cpp index 1dec900aed..0a804bbb41 100644 --- a/bluetooth/audio/utils/aidl_session/BluetoothLeAudioCodecsProvider.cpp +++ b/bluetooth/audio/utils/aidl_session/BluetoothLeAudioCodecsProvider.cpp @@ -200,13 +200,21 @@ BluetoothLeAudioCodecsProvider::ComposeLeAudioCodecCapabilities( GetUnicastCapability(scenario.getEncode()); UnicastCapability unicast_decode_capability = GetUnicastCapability(scenario.getDecode()); - // encode and decode cannot be unknown at the same time - if (unicast_encode_capability.codecType == CodecType::UNKNOWN && - unicast_decode_capability.codecType == CodecType::UNKNOWN) { - continue; - } BroadcastCapability broadcast_capability = {.codecType = CodecType::UNKNOWN}; + + if (scenario.hasBroadcast()) { + broadcast_capability = GetBroadcastCapability(scenario.getBroadcast()); + } + + // At least one capability should be valid + if (unicast_encode_capability.codecType == CodecType::UNKNOWN && + unicast_decode_capability.codecType == CodecType::UNKNOWN && + broadcast_capability.codecType == CodecType::UNKNOWN) { + LOG(ERROR) << __func__ << ": None of the capability is valid."; + continue; + } + le_audio_codec_capabilities.push_back( {.unicastEncodeCapability = unicast_encode_capability, .unicastDecodeCapability = unicast_decode_capability, @@ -252,6 +260,54 @@ UnicastCapability BluetoothLeAudioCodecsProvider::GetUnicastCapability( return {.codecType = CodecType::UNKNOWN}; } +BroadcastCapability BluetoothLeAudioCodecsProvider::GetBroadcastCapability( + const std::string& coding_direction) { + if (coding_direction == "invalid") { + return {.codecType = CodecType::UNKNOWN}; + } + + auto configuration_iter = configuration_map_.find(coding_direction); + if (configuration_iter == configuration_map_.end()) { + return {.codecType = CodecType::UNKNOWN}; + } + + auto codec_configuration_iter = codec_configuration_map_.find( + configuration_iter->second.getCodecConfiguration()); + if (codec_configuration_iter == codec_configuration_map_.end()) { + return {.codecType = CodecType::UNKNOWN}; + } + + auto strategy_configuration_iter = strategy_configuration_map_.find( + configuration_iter->second.getStrategyConfiguration()); + if (strategy_configuration_iter == strategy_configuration_map_.end()) { + return {.codecType = CodecType::UNKNOWN}; + } + + CodecType codec_type = + GetCodecType(codec_configuration_iter->second.getCodec()); + std::vector> bcastLc3Cap( + 1, std::optional(ComposeLc3Capability(codec_configuration_iter->second))); + + if (codec_type == CodecType::LC3) { + return ComposeBroadcastCapability( + codec_type, + GetAudioLocation( + strategy_configuration_iter->second.getAudioLocation()), + strategy_configuration_iter->second.getChannelCount(), bcastLc3Cap); + } + return {.codecType = CodecType::UNKNOWN}; +} + +template +BroadcastCapability BluetoothLeAudioCodecsProvider::ComposeBroadcastCapability( + const CodecType& codec_type, const AudioLocation& audio_location, + const uint8_t& channel_count, const std::vector& capability) { + return {.codecType = codec_type, + .supportedChannel = audio_location, + .channelCountPerStream = channel_count, + .leAudioCodecCapabilities = std::optional(capability)}; +} + template UnicastCapability BluetoothLeAudioCodecsProvider::ComposeUnicastCapability( const CodecType& codec_type, const AudioLocation& audio_location, @@ -322,6 +378,10 @@ bool BluetoothLeAudioCodecsProvider::IsValidStrategyConfiguration( // 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) { diff --git a/bluetooth/audio/utils/aidl_session/BluetoothLeAudioCodecsProvider.h b/bluetooth/audio/utils/aidl_session/BluetoothLeAudioCodecsProvider.h index e8799843ef..06e4595a4f 100644 --- a/bluetooth/audio/utils/aidl_session/BluetoothLeAudioCodecsProvider.h +++ b/bluetooth/audio/utils/aidl_session/BluetoothLeAudioCodecsProvider.h @@ -20,6 +20,7 @@ #include #include +#include #include "aidl_android_hardware_bluetooth_audio_setting.h" @@ -66,12 +67,20 @@ class BluetoothLeAudioCodecsProvider { static UnicastCapability GetUnicastCapability( const std::string& coding_direction); + static BroadcastCapability GetBroadcastCapability( + const std::string& coding_direction); + template static inline UnicastCapability ComposeUnicastCapability( const CodecType& codec_type, const AudioLocation& audio_location, const uint8_t& device_cnt, const uint8_t& channel_count, const T& capability); + template + static inline BroadcastCapability ComposeBroadcastCapability( + const CodecType& codec_type, const AudioLocation& audio_location, + const uint8_t& channel_count, const std::vector& capability); + static inline Lc3Capabilities ComposeLc3Capability( const setting::CodecConfiguration& codec_configuration); diff --git a/bluetooth/audio/utils/aidl_session/BluetoothLeAudioCodecsProviderTest.cpp b/bluetooth/audio/utils/aidl_session/BluetoothLeAudioCodecsProviderTest.cpp index 5393cd70e8..dba2749fde 100644 --- a/bluetooth/audio/utils/aidl_session/BluetoothLeAudioCodecsProviderTest.cpp +++ b/bluetooth/audio/utils/aidl_session/BluetoothLeAudioCodecsProviderTest.cpp @@ -46,7 +46,11 @@ typedef std::tuple, std::vector, // Define valid components for each list // Scenario static const Scenario kValidScenario(std::make_optional("OneChanStereo_16_1"), - std::make_optional("OneChanStereo_16_1")); + std::make_optional("OneChanStereo_16_1"), + std::nullopt); +static const Scenario kValidBroadcastScenario( + std::nullopt, std::nullopt, std::make_optional("BcastStereo_16_2")); + // Configuration static const Configuration kValidConfigOneChanStereo_16_1( std::make_optional("OneChanStereo_16_1"), std::make_optional("LC3_16k_1"), @@ -69,11 +73,15 @@ static const StrategyConfiguration kValidStrategyMonoOneCis( std::make_optional("MONO_ONE_CIS_PER_DEVICE"), std::make_optional(AudioLocation::MONO), std::make_optional(1), std::make_optional(1)); +static const StrategyConfiguration kValidStrategyBroadcastStereo( + std::make_optional("BROADCAST_STEREO"), + std::make_optional(AudioLocation::STEREO), std::make_optional(0), + std::make_optional(2)); // Define valid test list built from above valid components // Scenario, Configuration, CodecConfiguration, StrategyConfiguration -static const std::vector kValidScenarioList = { - ScenarioList(std::vector{kValidScenario})}; +static const std::vector kValidScenarioList = {ScenarioList( + std::vector{kValidScenario, kValidBroadcastScenario})}; static const std::vector kValidConfigurationList = { ConfigurationList( std::vector{kValidConfigOneChanStereo_16_1})}; @@ -84,7 +92,7 @@ static const std::vector kValidStrategyConfigurationList = { StrategyConfigurationList(std::vector{ kValidStrategyStereoOneCis, kValidStrategyStereoTwoCis, - kValidStrategyMonoOneCis})}; + kValidStrategyMonoOneCis, kValidStrategyBroadcastStereo})}; class BluetoothLeAudioCodecsProviderTest : public ::testing::TestWithParam { @@ -151,13 +159,15 @@ class GetScenariosTest : public BluetoothLeAudioCodecsProviderTest { static std::vector CreateInvalidScenarios() { std::vector invalid_scenario_test_cases; invalid_scenario_test_cases.push_back(ScenarioList(std::vector{ - Scenario(std::nullopt, std::make_optional("OneChanStereo_16_1"))})); - - invalid_scenario_test_cases.push_back(ScenarioList(std::vector{ - Scenario(std::make_optional("OneChanStereo_16_1"), std::nullopt)})); + Scenario(std::nullopt, std::make_optional("OneChanStereo_16_1"), + std::nullopt)})); invalid_scenario_test_cases.push_back(ScenarioList( - std::vector{Scenario(std::nullopt, std::nullopt)})); + std::vector{Scenario(std::make_optional("OneChanStereo_16_1"), + std::nullopt, std::nullopt)})); + + invalid_scenario_test_cases.push_back(ScenarioList(std::vector{ + Scenario(std::nullopt, std::nullopt, std::nullopt)})); invalid_scenario_test_cases.push_back( ScenarioList(std::vector{})); 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 c7904b338c..c8d1af097d 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 @@ -40,6 +40,8 @@ + + @@ -48,6 +50,7 @@ + @@ -57,5 +60,6 @@ + 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 213e5974da..8c2d6a11eb 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 @@ -32,6 +32,7 @@ + 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 06aa21a7b3..886350e37d 100644 --- a/bluetooth/audio/utils/le_audio_codec_capabilities/schema/current.txt +++ b/bluetooth/audio/utils/le_audio_codec_capabilities/schema/current.txt @@ -64,8 +64,10 @@ package aidl.android.hardware.bluetooth.audio.setting { public class Scenario { ctor public Scenario(); + method public String getBroadcast(); method public String getDecode(); method public String getEncode(); + method public void setBroadcast(String); method public void setDecode(String); method public void setEncode(String); }