Parse broadcast offload capabilities
1. Parse the broadcast capability from capability file 2. Convert broadcast HAL format to stack format 3. Update test to validate broadcast capability parsing 4. Correct the map size before accessing in VTS test Tag: #feature Bug: 242472419 Test: atest BluetoothLeAudioCodecsProviderTest Test: atest VtsHalBluetoothAudioTargetTest Change-Id: I8ac88c1e9024ca03757620bf48eacdd60ada7eb4
This commit is contained in:
parent
558762c14d
commit
ac077efa16
7 changed files with 101 additions and 14 deletions
|
@ -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<LeAudioCodecConfiguration::lc3Config>(
|
||||
lc3_config);
|
||||
|
|
|
@ -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<std::optional<Lc3Capabilities>> 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 <class T>
|
||||
BroadcastCapability BluetoothLeAudioCodecsProvider::ComposeBroadcastCapability(
|
||||
const CodecType& codec_type, const AudioLocation& audio_location,
|
||||
const uint8_t& channel_count, const std::vector<T>& capability) {
|
||||
return {.codecType = codec_type,
|
||||
.supportedChannel = audio_location,
|
||||
.channelCountPerStream = channel_count,
|
||||
.leAudioCodecCapabilities = std::optional(capability)};
|
||||
}
|
||||
|
||||
template <class T>
|
||||
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) {
|
||||
|
|
|
@ -20,6 +20,7 @@
|
|||
#include <android-base/logging.h>
|
||||
|
||||
#include <unordered_map>
|
||||
#include <vector>
|
||||
|
||||
#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 <class T>
|
||||
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 <class T>
|
||||
static inline BroadcastCapability ComposeBroadcastCapability(
|
||||
const CodecType& codec_type, const AudioLocation& audio_location,
|
||||
const uint8_t& channel_count, const std::vector<T>& capability);
|
||||
|
||||
static inline Lc3Capabilities ComposeLc3Capability(
|
||||
const setting::CodecConfiguration& codec_configuration);
|
||||
|
||||
|
|
|
@ -46,7 +46,11 @@ typedef std::tuple<std::vector<ScenarioList>, std::vector<ConfigurationList>,
|
|||
// 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<ScenarioList> kValidScenarioList = {
|
||||
ScenarioList(std::vector<Scenario>{kValidScenario})};
|
||||
static const std::vector<ScenarioList> kValidScenarioList = {ScenarioList(
|
||||
std::vector<Scenario>{kValidScenario, kValidBroadcastScenario})};
|
||||
static const std::vector<ConfigurationList> kValidConfigurationList = {
|
||||
ConfigurationList(
|
||||
std::vector<Configuration>{kValidConfigOneChanStereo_16_1})};
|
||||
|
@ -84,7 +92,7 @@ static const std::vector<StrategyConfigurationList>
|
|||
kValidStrategyConfigurationList = {
|
||||
StrategyConfigurationList(std::vector<StrategyConfiguration>{
|
||||
kValidStrategyStereoOneCis, kValidStrategyStereoTwoCis,
|
||||
kValidStrategyMonoOneCis})};
|
||||
kValidStrategyMonoOneCis, kValidStrategyBroadcastStereo})};
|
||||
|
||||
class BluetoothLeAudioCodecsProviderTest
|
||||
: public ::testing::TestWithParam<OffloadSetting> {
|
||||
|
@ -151,13 +159,15 @@ class GetScenariosTest : public BluetoothLeAudioCodecsProviderTest {
|
|||
static std::vector<ScenarioList> CreateInvalidScenarios() {
|
||||
std::vector<ScenarioList> invalid_scenario_test_cases;
|
||||
invalid_scenario_test_cases.push_back(ScenarioList(std::vector<Scenario>{
|
||||
Scenario(std::nullopt, std::make_optional("OneChanStereo_16_1"))}));
|
||||
|
||||
invalid_scenario_test_cases.push_back(ScenarioList(std::vector<Scenario>{
|
||||
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>{Scenario(std::nullopt, std::nullopt)}));
|
||||
std::vector<Scenario>{Scenario(std::make_optional("OneChanStereo_16_1"),
|
||||
std::nullopt, std::nullopt)}));
|
||||
|
||||
invalid_scenario_test_cases.push_back(ScenarioList(std::vector<Scenario>{
|
||||
Scenario(std::nullopt, std::nullopt, std::nullopt)}));
|
||||
|
||||
invalid_scenario_test_cases.push_back(
|
||||
ScenarioList(std::vector<Scenario>{}));
|
||||
|
|
|
@ -40,6 +40,8 @@
|
|||
<scenario encode="OneChanStereo_16_2" decode="OneChanMono_16_2"/>
|
||||
<scenario encode="TwoChanStereo_16_2" decode="OneChanMono_16_2"/>
|
||||
<scenario encode="OneChanMono_16_2" decode="OneChanMono_16_2"/>
|
||||
<!-- broadcast -->
|
||||
<scenario encode="invalid" decode="invalid" broadcast="BcastStereo_16_2"/>
|
||||
</scenarioList>
|
||||
<configurationList>
|
||||
<configuration name="OneChanMono_16_1" codecConfiguration="LC3_16k_1" strategyConfiguration="MONO_ONE_CIS_PER_DEVICE"/>
|
||||
|
@ -48,6 +50,7 @@
|
|||
<configuration name="OneChanMono_16_2" codecConfiguration="LC3_16k_2" strategyConfiguration="MONO_ONE_CIS_PER_DEVICE"/>
|
||||
<configuration name="TwoChanStereo_16_2" codecConfiguration="LC3_16k_2" strategyConfiguration="STEREO_TWO_CISES_PER_DEVICE"/>
|
||||
<configuration name="OneChanStereo_16_2" codecConfiguration="LC3_16k_2" strategyConfiguration="STEREO_ONE_CIS_PER_DEVICE"/>
|
||||
<configuration name="BcastStereo_16_2" codecConfiguration="LC3_16k_2" strategyConfiguration="BROADCAST_STEREO"/>
|
||||
</configurationList>
|
||||
<codecConfigurationList>
|
||||
<codecConfiguration name="LC3_16k_1" codec="LC3" samplingFrequency="16000" frameDurationUs="7500" octetsPerCodecFrame="30"/>
|
||||
|
@ -57,5 +60,6 @@
|
|||
<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"/>
|
||||
</strategyConfigurationList>
|
||||
</leAudioOffloadSetting>
|
||||
|
|
|
@ -32,6 +32,7 @@
|
|||
<xs:complexType>
|
||||
<xs:attribute name="encode" type="xs:string"/>
|
||||
<xs:attribute name="decode" type="xs:string"/>
|
||||
<xs:attribute name="broadcast" type="xs:string"/>
|
||||
</xs:complexType>
|
||||
</xs:element>
|
||||
<xs:element name="configuration">
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue