Merge "Add BluetoothLeAudioCodecsProvider Unit Test"

This commit is contained in:
Treehugger Robot
2022-11-10 05:20:56 +00:00
committed by Gerrit Code Review
5 changed files with 443 additions and 8 deletions

View File

@@ -63,6 +63,31 @@ cc_library_shared {
generated_headers: ["le_audio_codec_capabilities"],
}
cc_test {
name: "BluetoothLeAudioCodecsProviderTest",
srcs: [
"aidl_session/BluetoothLeAudioCodecsProvider.cpp",
"aidl_session/BluetoothLeAudioCodecsProviderTest.cpp",
],
header_libs: [
"libxsdc-utils",
],
shared_libs: [
"libbase",
"libbinder_ndk",
"android.hardware.bluetooth.audio-V2-ndk",
"libxml2",
],
test_suites: [
"general-tests",
],
test_options: {
unit_test: false,
},
generated_sources: ["le_audio_codec_capabilities"],
generated_headers: ["le_audio_codec_capabilities"],
}
xsd_config {
name: "le_audio_codec_capabilities",
srcs: ["le_audio_codec_capabilities/le_audio_codec_capabilities.xsd"],

View File

@@ -398,8 +398,11 @@ BluetoothAudioCodecs::GetLeAudioOffloadCodecCapabilities(
}
if (kDefaultOffloadLeAudioCapabilities.empty()) {
auto le_audio_offload_setting =
BluetoothLeAudioCodecsProvider::ParseFromLeAudioOffloadSettingFile();
kDefaultOffloadLeAudioCapabilities =
BluetoothLeAudioCodecsProvider::GetLeAudioCodecCapabilities();
BluetoothLeAudioCodecsProvider::GetLeAudioCodecCapabilities(
le_audio_offload_setting);
}
return kDefaultOffloadLeAudioCapabilities;

View File

@@ -34,20 +34,40 @@ static const AudioLocation kMonoAudio = AudioLocation::UNKNOWN;
static std::vector<LeAudioCodecCapabilitiesSetting> leAudioCodecCapabilities;
std::vector<LeAudioCodecCapabilitiesSetting>
BluetoothLeAudioCodecsProvider::GetLeAudioCodecCapabilities() {
if (!leAudioCodecCapabilities.empty()) {
return leAudioCodecCapabilities;
}
static bool isInvalidFileContent = false;
const auto le_audio_offload_setting =
std::optional<setting::LeAudioOffloadSetting>
BluetoothLeAudioCodecsProvider::ParseFromLeAudioOffloadSettingFile() {
if (!leAudioCodecCapabilities.empty() || isInvalidFileContent) {
return std::nullopt;
}
auto le_audio_offload_setting =
setting::readLeAudioOffloadSetting(kLeAudioCodecCapabilitiesFile);
if (!le_audio_offload_setting.has_value()) {
LOG(ERROR) << __func__ << ": Failed to read "
<< kLeAudioCodecCapabilitiesFile;
}
return le_audio_offload_setting;
}
std::vector<LeAudioCodecCapabilitiesSetting>
BluetoothLeAudioCodecsProvider::GetLeAudioCodecCapabilities(
const std::optional<setting::LeAudioOffloadSetting>&
le_audio_offload_setting) {
if (!leAudioCodecCapabilities.empty()) {
return leAudioCodecCapabilities;
}
if (!le_audio_offload_setting.has_value()) {
LOG(ERROR)
<< __func__
<< ": input le_audio_offload_setting content need to be non empty";
return {};
}
ClearLeAudioCodecCapabilities();
isInvalidFileContent = true;
std::vector<setting::Scenario> supported_scenarios =
GetScenarios(le_audio_offload_setting);
if (supported_scenarios.empty()) {
@@ -79,9 +99,18 @@ BluetoothLeAudioCodecsProvider::GetLeAudioCodecCapabilities() {
leAudioCodecCapabilities =
ComposeLeAudioCodecCapabilities(supported_scenarios);
isInvalidFileContent = leAudioCodecCapabilities.empty();
return leAudioCodecCapabilities;
}
void BluetoothLeAudioCodecsProvider::ClearLeAudioCodecCapabilities() {
leAudioCodecCapabilities.clear();
configuration_map_.clear();
codec_configuration_map_.clear();
strategy_configuration_map_.clear();
}
std::vector<setting::Scenario> BluetoothLeAudioCodecsProvider::GetScenarios(
const std::optional<setting::LeAudioOffloadSetting>&
le_audio_offload_setting) {

View File

@@ -31,8 +31,13 @@ namespace audio {
class BluetoothLeAudioCodecsProvider {
public:
static std::optional<setting::LeAudioOffloadSetting>
ParseFromLeAudioOffloadSettingFile();
static std::vector<LeAudioCodecCapabilitiesSetting>
GetLeAudioCodecCapabilities();
GetLeAudioCodecCapabilities(
const std::optional<setting::LeAudioOffloadSetting>&
le_audio_offload_setting);
static void ClearLeAudioCodecCapabilities();
private:
static inline std::unordered_map<std::string, setting::Configuration>

View File

@@ -0,0 +1,373 @@
/*
* Copyright (C) 2022 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include <gtest/gtest.h>
#include <optional>
#include <tuple>
#include "BluetoothLeAudioCodecsProvider.h"
using aidl::android::hardware::bluetooth::audio::BluetoothLeAudioCodecsProvider;
using aidl::android::hardware::bluetooth::audio::
LeAudioCodecCapabilitiesSetting;
using aidl::android::hardware::bluetooth::audio::setting::AudioLocation;
using aidl::android::hardware::bluetooth::audio::setting::CodecConfiguration;
using aidl::android::hardware::bluetooth::audio::setting::
CodecConfigurationList;
using aidl::android::hardware::bluetooth::audio::setting::CodecType;
using aidl::android::hardware::bluetooth::audio::setting::Configuration;
using aidl::android::hardware::bluetooth::audio::setting::ConfigurationList;
using aidl::android::hardware::bluetooth::audio::setting::LeAudioOffloadSetting;
using aidl::android::hardware::bluetooth::audio::setting::Scenario;
using aidl::android::hardware::bluetooth::audio::setting::ScenarioList;
using aidl::android::hardware::bluetooth::audio::setting::StrategyConfiguration;
using aidl::android::hardware::bluetooth::audio::setting::
StrategyConfigurationList;
typedef std::tuple<std::vector<ScenarioList>, std::vector<ConfigurationList>,
std::vector<CodecConfigurationList>,
std::vector<StrategyConfigurationList>>
OffloadSetting;
// Define valid components for each list
// Scenario
static const Scenario kValidScenario(std::make_optional("OneChanStereo_16_1"),
std::make_optional("OneChanStereo_16_1"));
// Configuration
static const Configuration kValidConfigOneChanStereo_16_1(
std::make_optional("OneChanStereo_16_1"), std::make_optional("LC3_16k_1"),
std::make_optional("STEREO_ONE_CIS_PER_DEVICE"));
// CodecConfiguration
static const CodecConfiguration kValidCodecLC3_16k_1(
std::make_optional("LC3_16k_1"), std::make_optional(CodecType::LC3),
std::nullopt, std::make_optional(16000), std::make_optional(7500),
std::make_optional(30), std::nullopt);
// StrategyConfiguration
static const StrategyConfiguration kValidStrategyStereoOneCis(
std::make_optional("STEREO_ONE_CIS_PER_DEVICE"),
std::make_optional(AudioLocation::STEREO), std::make_optional(2),
std::make_optional(1));
static const StrategyConfiguration kValidStrategyStereoTwoCis(
std::make_optional("STEREO_TWO_CISES_PER_DEVICE"),
std::make_optional(AudioLocation::STEREO), std::make_optional(1),
std::make_optional(2));
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));
// 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<ConfigurationList> kValidConfigurationList = {
ConfigurationList(
std::vector<Configuration>{kValidConfigOneChanStereo_16_1})};
static const std::vector<CodecConfigurationList> kValidCodecConfigurationList =
{CodecConfigurationList(
std::vector<CodecConfiguration>{kValidCodecLC3_16k_1})};
static const std::vector<StrategyConfigurationList>
kValidStrategyConfigurationList = {
StrategyConfigurationList(std::vector<StrategyConfiguration>{
kValidStrategyStereoOneCis, kValidStrategyStereoTwoCis,
kValidStrategyMonoOneCis})};
class BluetoothLeAudioCodecsProviderTest
: public ::testing::TestWithParam<OffloadSetting> {
public:
static std::vector<OffloadSetting> CreateTestCases(
const std::vector<ScenarioList>& scenario_lists,
const std::vector<ConfigurationList>& configuration_lists,
const std::vector<CodecConfigurationList>& codec_configuration_lists,
const std::vector<StrategyConfigurationList>&
strategy_configuration_lists) {
// make each vector in output test_cases has only one element
// to match the input of test params
// normally only one vector in input has multiple elements
// we just split elements in this vector to several vector
std::vector<OffloadSetting> test_cases;
for (const auto& scenario_list : scenario_lists) {
for (const auto& configuration_list : configuration_lists) {
for (const auto& codec_configuration_list : codec_configuration_lists) {
for (const auto& strategy_configuration_list :
strategy_configuration_lists) {
test_cases.push_back(CreateTestCase(
scenario_list, configuration_list, codec_configuration_list,
strategy_configuration_list));
}
}
}
}
return test_cases;
}
protected:
void Initialize() {
BluetoothLeAudioCodecsProvider::ClearLeAudioCodecCapabilities();
}
std::vector<LeAudioCodecCapabilitiesSetting> RunTestCase() {
auto& [scenario_lists, configuration_lists, codec_configuration_lists,
strategy_configuration_lists] = GetParam();
LeAudioOffloadSetting le_audio_offload_setting(
scenario_lists, configuration_lists, codec_configuration_lists,
strategy_configuration_lists);
auto le_audio_codec_capabilities =
BluetoothLeAudioCodecsProvider::GetLeAudioCodecCapabilities(
std::make_optional(le_audio_offload_setting));
return le_audio_codec_capabilities;
}
private:
static inline OffloadSetting CreateTestCase(
const ScenarioList& scenario_list,
const ConfigurationList& configuration_list,
const CodecConfigurationList& codec_configuration_list,
const StrategyConfigurationList& strategy_configuration_list) {
return std::make_tuple(
std::vector<ScenarioList>{scenario_list},
std::vector<ConfigurationList>{configuration_list},
std::vector<CodecConfigurationList>{codec_configuration_list},
std::vector<StrategyConfigurationList>{strategy_configuration_list});
}
};
class GetScenariosTest : public BluetoothLeAudioCodecsProviderTest {
public:
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)}));
invalid_scenario_test_cases.push_back(ScenarioList(
std::vector<Scenario>{Scenario(std::nullopt, std::nullopt)}));
invalid_scenario_test_cases.push_back(
ScenarioList(std::vector<Scenario>{}));
return invalid_scenario_test_cases;
}
};
TEST_P(GetScenariosTest, InvalidScenarios) {
Initialize();
auto le_audio_codec_capabilities = RunTestCase();
ASSERT_TRUE(le_audio_codec_capabilities.empty());
}
class UpdateConfigurationsToMapTest
: public BluetoothLeAudioCodecsProviderTest {
public:
static std::vector<ConfigurationList> CreateInvalidConfigurations() {
std::vector<ConfigurationList> invalid_configuration_test_cases;
invalid_configuration_test_cases.push_back(
ConfigurationList(std::vector<Configuration>{
Configuration(std::nullopt, std::make_optional("LC3_16k_1"),
std::make_optional("STEREO_ONE_CIS_PER_DEVICE"))}));
invalid_configuration_test_cases.push_back(
ConfigurationList(std::vector<Configuration>{Configuration(
std::make_optional("OneChanStereo_16_1"), std::nullopt,
std::make_optional("STEREO_ONE_CIS_PER_DEVICE"))}));
invalid_configuration_test_cases.push_back(
ConfigurationList(std::vector<Configuration>{
Configuration(std::make_optional("OneChanStereo_16_1"),
std::make_optional("LC3_16k_1"), std::nullopt)}));
invalid_configuration_test_cases.push_back(
ConfigurationList(std::vector<Configuration>{}));
return invalid_configuration_test_cases;
}
};
TEST_P(UpdateConfigurationsToMapTest, InvalidConfigurations) {
Initialize();
auto le_audio_codec_capabilities = RunTestCase();
ASSERT_TRUE(le_audio_codec_capabilities.empty());
}
class UpdateCodecConfigurationsToMapTest
: public BluetoothLeAudioCodecsProviderTest {
public:
static std::vector<CodecConfigurationList>
CreateInvalidCodecConfigurations() {
std::vector<CodecConfigurationList> invalid_codec_configuration_test_cases;
invalid_codec_configuration_test_cases.push_back(CodecConfigurationList(
std::vector<CodecConfiguration>{CodecConfiguration(
std::nullopt, std::make_optional(CodecType::LC3), std::nullopt,
std::make_optional(16000), std::make_optional(7500),
std::make_optional(30), std::nullopt)}));
invalid_codec_configuration_test_cases.push_back(CodecConfigurationList(
std::vector<CodecConfiguration>{CodecConfiguration(
std::make_optional("LC3_16k_1"), std::nullopt, std::nullopt,
std::make_optional(16000), std::make_optional(7500),
std::make_optional(30), std::nullopt)}));
invalid_codec_configuration_test_cases.push_back(CodecConfigurationList(
std::vector<CodecConfiguration>{CodecConfiguration(
std::make_optional("LC3_16k_1"), std::make_optional(CodecType::LC3),
std::nullopt, std::nullopt, std::make_optional(7500),
std::make_optional(30), std::nullopt)}));
invalid_codec_configuration_test_cases.push_back(CodecConfigurationList(
std::vector<CodecConfiguration>{CodecConfiguration(
std::make_optional("LC3_16k_1"), std::make_optional(CodecType::LC3),
std::nullopt, std::make_optional(16000), std::nullopt,
std::make_optional(30), std::nullopt)}));
invalid_codec_configuration_test_cases.push_back(CodecConfigurationList(
std::vector<CodecConfiguration>{CodecConfiguration(
std::make_optional("LC3_16k_1"), std::make_optional(CodecType::LC3),
std::nullopt, std::make_optional(16000), std::make_optional(7500),
std::nullopt, std::nullopt)}));
invalid_codec_configuration_test_cases.push_back(
CodecConfigurationList(std::vector<CodecConfiguration>{}));
return invalid_codec_configuration_test_cases;
}
};
TEST_P(UpdateCodecConfigurationsToMapTest, InvalidCodecConfigurations) {
Initialize();
auto le_audio_codec_capabilities = RunTestCase();
ASSERT_TRUE(le_audio_codec_capabilities.empty());
}
class UpdateStrategyConfigurationsToMapTest
: public BluetoothLeAudioCodecsProviderTest {
public:
static std::vector<StrategyConfigurationList>
CreateInvalidStrategyConfigurations() {
std::vector<StrategyConfigurationList>
invalid_strategy_configuration_test_cases;
invalid_strategy_configuration_test_cases.push_back(
StrategyConfigurationList(
std::vector<StrategyConfiguration>{StrategyConfiguration(
std::make_optional("STEREO_ONE_CIS_PER_DEVICE"),
std::make_optional(AudioLocation::STEREO),
std::make_optional(2), std::make_optional(2))}));
invalid_strategy_configuration_test_cases.push_back(
StrategyConfigurationList(
std::vector<StrategyConfiguration>{StrategyConfiguration(
std::make_optional("MONO_ONE_CIS_PER_DEVICE"),
std::make_optional(AudioLocation::STEREO),
std::make_optional(2), std::make_optional(2))}));
invalid_strategy_configuration_test_cases.push_back(
StrategyConfigurationList(
std::vector<StrategyConfiguration>{StrategyConfiguration(
std::nullopt, std::make_optional(AudioLocation::STEREO),
std::make_optional(2), std::make_optional(1))}));
invalid_strategy_configuration_test_cases.push_back(
StrategyConfigurationList(
std::vector<StrategyConfiguration>{StrategyConfiguration(
std::make_optional("STEREO_ONE_CIS_PER_DEVICE"), std::nullopt,
std::make_optional(2), std::make_optional(1))}));
invalid_strategy_configuration_test_cases.push_back(
StrategyConfigurationList(
std::vector<StrategyConfiguration>{StrategyConfiguration(
std::make_optional("STEREO_ONE_CIS_PER_DEVICE"),
std::make_optional(AudioLocation::STEREO), std::nullopt,
std::make_optional(1))}));
invalid_strategy_configuration_test_cases.push_back(
StrategyConfigurationList(
std::vector<StrategyConfiguration>{StrategyConfiguration(
std::make_optional("STEREO_ONE_CIS_PER_DEVICE"),
std::make_optional(AudioLocation::STEREO),
std::make_optional(2), std::nullopt)}));
invalid_strategy_configuration_test_cases.push_back(
StrategyConfigurationList(std::vector<StrategyConfiguration>{}));
return invalid_strategy_configuration_test_cases;
}
};
TEST_P(UpdateStrategyConfigurationsToMapTest, InvalidStrategyConfigurations) {
Initialize();
auto le_audio_codec_capabilities = RunTestCase();
ASSERT_TRUE(le_audio_codec_capabilities.empty());
}
class ComposeLeAudioCodecCapabilitiesTest
: public BluetoothLeAudioCodecsProviderTest {
public:
};
TEST_P(ComposeLeAudioCodecCapabilitiesTest, CodecCapabilitiesNotEmpty) {
Initialize();
auto le_audio_codec_capabilities = RunTestCase();
ASSERT_TRUE(!le_audio_codec_capabilities.empty());
}
GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(GetScenariosTest);
INSTANTIATE_TEST_SUITE_P(
BluetoothLeAudioCodecsProviderTest, GetScenariosTest,
::testing::ValuesIn(BluetoothLeAudioCodecsProviderTest::CreateTestCases(
GetScenariosTest::CreateInvalidScenarios(), kValidConfigurationList,
kValidCodecConfigurationList, kValidStrategyConfigurationList)));
GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(UpdateConfigurationsToMapTest);
INSTANTIATE_TEST_SUITE_P(
BluetoothLeAudioCodecsProviderTest, UpdateConfigurationsToMapTest,
::testing::ValuesIn(BluetoothLeAudioCodecsProviderTest::CreateTestCases(
kValidScenarioList,
UpdateConfigurationsToMapTest::CreateInvalidConfigurations(),
kValidCodecConfigurationList, kValidStrategyConfigurationList)));
GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(
UpdateCodecConfigurationsToMapTest);
INSTANTIATE_TEST_SUITE_P(
BluetoothLeAudioCodecsProviderTest, UpdateCodecConfigurationsToMapTest,
::testing::ValuesIn(BluetoothLeAudioCodecsProviderTest::CreateTestCases(
kValidScenarioList, kValidConfigurationList,
UpdateCodecConfigurationsToMapTest::CreateInvalidCodecConfigurations(),
kValidStrategyConfigurationList)));
GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(
UpdateStrategyConfigurationsToMapTest);
INSTANTIATE_TEST_SUITE_P(
BluetoothLeAudioCodecsProviderTest, UpdateStrategyConfigurationsToMapTest,
::testing::ValuesIn(BluetoothLeAudioCodecsProviderTest::CreateTestCases(
kValidScenarioList, kValidConfigurationList,
kValidCodecConfigurationList,
UpdateStrategyConfigurationsToMapTest::
CreateInvalidStrategyConfigurations())));
GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(
ComposeLeAudioCodecCapabilitiesTest);
INSTANTIATE_TEST_SUITE_P(
BluetoothLeAudioCodecsProviderTest, ComposeLeAudioCodecCapabilitiesTest,
::testing::ValuesIn(BluetoothLeAudioCodecsProviderTest::CreateTestCases(
kValidScenarioList, kValidConfigurationList,
kValidCodecConfigurationList, kValidStrategyConfigurationList)));
int main(int argc, char** argv) {
::testing::InitGoogleTest(&argc, argv);
return RUN_ALL_TESTS();
}