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