1 /*
2 * Copyright (C) 2021 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17 #include <memory>
18 #include <string>
19 #include <vector>
20
21 #include <android-base/macros.h>
22 #include <gtest/gtest.h>
23 #define LOG_TAG "Generators_Test"
24 #include <log/log.h>
25
26 #if MAJOR_VERSION == 6
27 #include <system/audio.h>
28 #include "6.0/Generators.h"
29 #include "PolicyConfig.h"
30 #elif MAJOR_VERSION == 7
31 #include "7.0/Generators.h"
32 #include "7.0/PolicyConfig.h"
33 #endif
34
35 using namespace android;
36 using namespace ::android::hardware::audio::common::CPP_VERSION;
37 #if MAJOR_VERSION == 7
38 namespace xsd {
39 using namespace ::android::audio::policy::configuration::CPP_VERSION;
40 }
41 #endif
42
43 // Stringify the argument.
44 #define QUOTE(x) #x
45 #define STRINGIFY(x) QUOTE(x)
46
47 struct PolicyConfigManager {
getInstancePolicyConfigManager48 static PolicyConfigManager& getInstance() {
49 static PolicyConfigManager instance;
50 return instance;
51 }
initPolicyConfigManager52 bool init(const std::string& filePath, const std::string& fileName) {
53 mConfig = std::make_unique<PolicyConfig>(filePath, fileName);
54 mDeviceParameters.clear();
55 if (mConfig->getStatus() == OK) {
56 const auto devices = mConfig->getModulesWithDevicesNames();
57 mDeviceParameters.reserve(devices.size());
58 for (const auto& deviceName : devices) {
59 mDeviceParameters.emplace_back(
60 "android.hardware.audio.IDevicesFactory@" STRINGIFY(FILE_VERSION),
61 deviceName);
62 }
63 return true;
64 } else {
65 ALOGE("%s", mConfig->getError().c_str());
66 return false;
67 }
68 }
getConfigPolicyConfigManager69 const PolicyConfig& getConfig() { return *mConfig; }
getDeviceParametersPolicyConfigManager70 const std::vector<DeviceParameter>& getDeviceParameters() { return mDeviceParameters; }
71
72 private:
73 std::unique_ptr<PolicyConfig> mConfig;
74 std::vector<DeviceParameter> mDeviceParameters;
75 };
76
77 // Test implementations
getCachedPolicyConfig()78 const PolicyConfig& getCachedPolicyConfig() {
79 return PolicyConfigManager::getInstance().getConfig();
80 }
81
getDeviceParameters()82 const std::vector<DeviceParameter>& getDeviceParameters() {
83 return PolicyConfigManager::getInstance().getDeviceParameters();
84 }
85
86 static const std::string kDataDir = "/data/local/tmp";
87
88 class GeneratorsTest : public ::testing::TestWithParam<std::string> {
89 public:
validateConfig(const AudioConfig & config)90 static void validateConfig(const AudioConfig& config) {
91 #if MAJOR_VERSION == 6
92 ASSERT_TRUE(audio_is_valid_format(static_cast<audio_format_t>(config.format)))
93 << "Audio format is invalid " << ::testing::PrintToString(config.format);
94 ASSERT_TRUE(
95 audio_channel_mask_is_valid(static_cast<audio_channel_mask_t>(config.channelMask)))
96 << "Audio channel mask is invalid " << ::testing::PrintToString(config.channelMask);
97 #elif MAJOR_VERSION == 7
98 ASSERT_FALSE(xsd::isUnknownAudioFormat(config.base.format))
99 << "Audio format is invalid " << ::testing::PrintToString(config.base.format);
100 ASSERT_FALSE(xsd::isUnknownAudioChannelMask(config.base.channelMask))
101 << "Audio channel mask is invalid "
102 << ::testing::PrintToString(config.base.channelMask);
103 #endif
104 }
validateDeviceConfigs(const std::vector<DeviceConfigParameter> & params)105 static void validateDeviceConfigs(const std::vector<DeviceConfigParameter>& params) {
106 for (const auto& param : params) {
107 ASSERT_NO_FATAL_FAILURE(validateConfig(std::get<PARAM_CONFIG>(param)));
108 }
109 }
110 };
111
TEST_P(GeneratorsTest,ValidateConfigs)112 TEST_P(GeneratorsTest, ValidateConfigs) {
113 ASSERT_TRUE(PolicyConfigManager::getInstance().init(kDataDir, GetParam()));
114 EXPECT_NE(nullptr, getCachedPolicyConfig().getPrimaryModule());
115 EXPECT_FALSE(getCachedPolicyConfig().getModulesWithDevicesNames().empty());
116 const auto allOutConfigs = generateOutputDeviceConfigParameters(false /*oneProfilePerDevice*/);
117 EXPECT_FALSE(allOutConfigs.empty());
118 EXPECT_NO_FATAL_FAILURE(validateDeviceConfigs(allOutConfigs));
119 const auto singleOutConfig = generateOutputDeviceConfigParameters(true /*oneProfilePerDevice*/);
120 EXPECT_FALSE(singleOutConfig.empty());
121 EXPECT_NO_FATAL_FAILURE(validateDeviceConfigs(singleOutConfig));
122 const auto allInConfigs = generateInputDeviceConfigParameters(false /*oneProfilePerDevice*/);
123 EXPECT_FALSE(allInConfigs.empty());
124 EXPECT_NO_FATAL_FAILURE(validateDeviceConfigs(allInConfigs));
125 const auto singleInConfig = generateInputDeviceConfigParameters(true /*oneProfilePerDevice*/);
126 EXPECT_FALSE(singleInConfig.empty());
127 EXPECT_NO_FATAL_FAILURE(validateDeviceConfigs(singleInConfig));
128 }
129
130 // Target file names are the same for all versions, see 'HalAudioVx_0GeneratorTest.xml' test configs
131 // clang-format off
132 INSTANTIATE_TEST_SUITE_P(Generators, GeneratorsTest,
133 ::testing::Values("apm_config_no_vx.xml", "apm_config_with_vx.xml"
134 #if MAJOR_VERSION == 6
135 , "apm_config_b_205808571_6_0.xml"
136 #elif MAJOR_VERSION == 7
137 , "apm_config_b_204314749_7_0.xml"
138 , "apm_config_b_205808571_7_0.xml"
139 #endif
140 ));
141 // clang-format on
142
TEST(GeneratorsDeviceTest,AttachedDevicesOnly)143 TEST(GeneratorsDeviceTest, AttachedDevicesOnly) {
144 static const std::string kTestFile =
145 "apm_config_b_205808571_" STRINGIFY(MAJOR_VERSION) "_0.xml";
146 ASSERT_TRUE(PolicyConfigManager::getInstance().init(kDataDir, kTestFile));
147 EXPECT_NE(nullptr, getCachedPolicyConfig().getPrimaryModule());
148 const auto allInConfigs = generateInputDeviceConfigParameters(false /*oneProfilePerDevice*/);
149 EXPECT_FALSE(allInConfigs.empty());
150 for (const auto& configParam : allInConfigs) {
151 const AudioConfig& config = std::get<PARAM_CONFIG>(configParam);
152 // The config contains multichannel masks for mixPort connected to
153 // input devicePorts that are not attached. These multichannel masks must
154 // not appear among generated masks.
155 const uint32_t channelCount =
156 #if MAJOR_VERSION == 6
157 audio_channel_count_from_in_mask(
158 static_cast<audio_channel_mask_t>(config.channelMask));
159 #elif MAJOR_VERSION == 7
160 xsd::getChannelCount(config.base.channelMask);
161 #endif
162 EXPECT_TRUE(channelCount <= 4) << "Unexpected channel count: " << channelCount << " " <<
163 #if MAJOR_VERSION == 6
164 ::testing::PrintToString(config.format) << ", "
165 << ::testing::PrintToString(config.sampleRateHz) << ", "
166 << ::testing::PrintToString(config.channelMask);
167 #elif MAJOR_VERSION == 7
168 ::testing::PrintToString(config.base.format) << ", "
169 << ::testing::PrintToString(config.base.sampleRateHz) << ", "
170 << ::testing::PrintToString(config.base.channelMask);
171 #endif
172 }
173 }
174