• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2022 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 <string>
18 
19 #define LOG_TAG "VtsHalLoudnessEnhancerTest"
20 #include <android-base/logging.h>
21 
22 #include "EffectHelper.h"
23 
24 using namespace android;
25 
26 using aidl::android::hardware::audio::common::getChannelCount;
27 using aidl::android::hardware::audio::effect::Descriptor;
28 using aidl::android::hardware::audio::effect::getEffectTypeUuidLoudnessEnhancer;
29 using aidl::android::hardware::audio::effect::IEffect;
30 using aidl::android::hardware::audio::effect::IFactory;
31 using aidl::android::hardware::audio::effect::LoudnessEnhancer;
32 using aidl::android::hardware::audio::effect::Parameter;
33 using android::hardware::audio::common::testing::detail::TestExecutionTracer;
34 
35 static constexpr int kZeroGain = 0;
36 static constexpr int kMaxGain = std::numeric_limits<int>::max();
37 static constexpr int kMinGain = std::numeric_limits<int>::min();
38 static constexpr float kAbsError = 0.0001;
39 
40 // Every int 32 bit value is a valid gain, so testing the corner cases and one regular value.
41 // TODO : Update the test values once range/capability is updated by implementation.
42 static const std::vector<int> kGainMbValues = {kMinGain, -100, -50, kZeroGain, 50, 100, kMaxGain};
43 
44 class LoudnessEnhancerEffectHelper : public EffectHelper {
45   public:
SetUpLoudnessEnhancer()46     void SetUpLoudnessEnhancer() {
47         ASSERT_NE(nullptr, mFactory);
48         ASSERT_NO_FATAL_FAILURE(create(mFactory, mEffect, mDescriptor));
49 
50         Parameter::Specific specific = getDefaultParamSpecific();
51         Parameter::Common common = createParamCommon(
52                 0 /* session */, 1 /* ioHandle */, 44100 /* iSampleRate */, 44100 /* oSampleRate */,
53                 kFrameCount /* iFrameCount */, kFrameCount /* oFrameCount */);
54         ASSERT_NO_FATAL_FAILURE(open(mEffect, common, specific, &mOpenEffectReturn, EX_NONE));
55         ASSERT_NE(nullptr, mEffect);
56         mVersion = EffectFactoryHelper::getHalVersion(mFactory);
57     }
58 
TearDownLoudnessEnhancer()59     void TearDownLoudnessEnhancer() {
60         ASSERT_NO_FATAL_FAILURE(close(mEffect));
61         ASSERT_NO_FATAL_FAILURE(destroy(mFactory, mEffect));
62         mOpenEffectReturn = IEffect::OpenEffectReturn{};
63     }
64 
getDefaultParamSpecific()65     Parameter::Specific getDefaultParamSpecific() {
66         LoudnessEnhancer le = LoudnessEnhancer::make<LoudnessEnhancer::gainMb>(0);
67         Parameter::Specific specific =
68                 Parameter::Specific::make<Parameter::Specific::loudnessEnhancer>(le);
69         return specific;
70     }
71 
createLoudnessParam(int gainMb)72     Parameter createLoudnessParam(int gainMb) {
73         LoudnessEnhancer le;
74         le.set<LoudnessEnhancer::gainMb>(gainMb);
75         Parameter param;
76         Parameter::Specific specific;
77         specific.set<Parameter::Specific::loudnessEnhancer>(le);
78         param.set<Parameter::specific>(specific);
79         return param;
80     }
81 
isGainValid(int gainMb)82     binder_exception_t isGainValid(int gainMb) {
83         LoudnessEnhancer le;
84         le.set<LoudnessEnhancer::gainMb>(gainMb);
85         if (isParameterValid<LoudnessEnhancer, Range::loudnessEnhancer>(le, mDescriptor)) {
86             return EX_NONE;
87         } else {
88             return EX_ILLEGAL_ARGUMENT;
89         }
90     }
91 
setParameters(int gain,binder_exception_t expected)92     void setParameters(int gain, binder_exception_t expected) {
93         // set parameter
94         auto param = createLoudnessParam(gain);
95         EXPECT_STATUS(expected, mEffect->setParameter(param)) << param.toString();
96     }
97 
reset()98     void reset() { EXPECT_STATUS(EX_NONE, mEffect->command(CommandId::RESET)); }
99 
validateParameters(int gain)100     void validateParameters(int gain) {
101         // get parameter
102         LoudnessEnhancer::Id leId;
103         Parameter getParam;
104         Parameter::Id id;
105 
106         LoudnessEnhancer::Tag tag(LoudnessEnhancer::gainMb);
107         leId.set<LoudnessEnhancer::Id::commonTag>(tag);
108         id.set<Parameter::Id::loudnessEnhancerTag>(leId);
109         EXPECT_STATUS(EX_NONE, mEffect->getParameter(id, &getParam));
110         auto expectedParam = createLoudnessParam(gain);
111         EXPECT_EQ(expectedParam, getParam) << "\nexpectedParam:" << expectedParam.toString()
112                                            << "\ngetParam:" << getParam.toString();
113     }
114 
115     static const long kFrameCount = 256;
116     IEffect::OpenEffectReturn mOpenEffectReturn;
117     std::shared_ptr<IFactory> mFactory;
118     std::shared_ptr<IEffect> mEffect;
119     Descriptor mDescriptor;
120     int mVersion = 0;
121 };
122 
123 /**
124  * Here we focus on specific parameter checking, general IEffect interfaces testing performed in
125  * VtsAudioEffectTargetTest.
126  */
127 enum ParamName { PARAM_INSTANCE_NAME, PARAM_GAIN_MB };
128 using LoudnessEnhancerParamTestParam =
129         std::tuple<std::pair<std::shared_ptr<IFactory>, Descriptor>, int>;
130 
131 class LoudnessEnhancerParamTest : public ::testing::TestWithParam<LoudnessEnhancerParamTestParam>,
132                                   public LoudnessEnhancerEffectHelper {
133   public:
LoudnessEnhancerParamTest()134     LoudnessEnhancerParamTest() : mParamGainMb(std::get<PARAM_GAIN_MB>(GetParam())) {
135         std::tie(mFactory, mDescriptor) = std::get<PARAM_INSTANCE_NAME>(GetParam());
136     }
137 
SetUp()138     void SetUp() override { ASSERT_NO_FATAL_FAILURE(SetUpLoudnessEnhancer()); }
TearDown()139     void TearDown() override { TearDownLoudnessEnhancer(); }
140     int mParamGainMb = 0;
141 };
142 
TEST_P(LoudnessEnhancerParamTest,SetAndGetGainMb)143 TEST_P(LoudnessEnhancerParamTest, SetAndGetGainMb) {
144     binder_exception_t expected = isGainValid(mParamGainMb);
145     setParameters(mParamGainMb, expected);
146     if (expected == EX_NONE) {
147         validateParameters(mParamGainMb);
148     }
149 }
150 
151 using LoudnessEnhancerDataTestParam = std::pair<std::shared_ptr<IFactory>, Descriptor>;
152 
153 class LoudnessEnhancerDataTest : public ::testing::TestWithParam<LoudnessEnhancerDataTestParam>,
154                                  public LoudnessEnhancerEffectHelper {
155   public:
LoudnessEnhancerDataTest()156     LoudnessEnhancerDataTest() {
157         std::tie(mFactory, mDescriptor) = GetParam();
158         size_t channelCount = getChannelCount(
159                 AudioChannelLayout::make<AudioChannelLayout::layoutMask>(kDefaultChannelLayout));
160         mBufferSizeInFrames = kFrameCount * channelCount;
161         mInputBuffer.resize(mBufferSizeInFrames);
162         generateInputBuffer(mInputBuffer, 0, true, channelCount, kMaxAudioSampleValue);
163 
164         mOutputBuffer.resize(mBufferSizeInFrames);
165     }
166 
SetUp()167     void SetUp() override {
168         SKIP_TEST_IF_DATA_UNSUPPORTED(mDescriptor.common.flags);
169         ASSERT_NO_FATAL_FAILURE(SetUpLoudnessEnhancer());
170 
171         // Creating AidlMessageQueues
172         mStatusMQ = std::make_unique<EffectHelper::StatusMQ>(mOpenEffectReturn.statusMQ);
173         mInputMQ = std::make_unique<EffectHelper::DataMQ>(mOpenEffectReturn.inputDataMQ);
174         mOutputMQ = std::make_unique<EffectHelper::DataMQ>(mOpenEffectReturn.outputDataMQ);
175     }
176 
TearDown()177     void TearDown() override {
178         SKIP_TEST_IF_DATA_UNSUPPORTED(mDescriptor.common.flags);
179         TearDownLoudnessEnhancer();
180     }
181 
182     // Add gains to the mInputBuffer and store processed output to mOutputBuffer
processAndWriteToOutput()183     void processAndWriteToOutput() {
184         // Check AidlMessageQueues are not null
185         ASSERT_TRUE(mStatusMQ->isValid());
186         ASSERT_TRUE(mInputMQ->isValid());
187         ASSERT_TRUE(mOutputMQ->isValid());
188 
189         // Enabling the process
190         ASSERT_NO_FATAL_FAILURE(command(mEffect, CommandId::START));
191         ASSERT_NO_FATAL_FAILURE(expectState(mEffect, State::PROCESSING));
192 
193         // Write from buffer to message queues and calling process
194         EXPECT_NO_FATAL_FAILURE(
195                 EffectHelper::writeToFmq(mStatusMQ, mInputMQ, mInputBuffer, mVersion));
196 
197         // Read the updated message queues into buffer
198         EXPECT_NO_FATAL_FAILURE(EffectHelper::readFromFmq(mStatusMQ, 1, mOutputMQ,
199                                                           mOutputBuffer.size(), mOutputBuffer));
200 
201         // Disable the process
202         ASSERT_NO_FATAL_FAILURE(command(mEffect, CommandId::STOP));
203     }
204 
assertGreaterGain(const std::vector<float> & first,const std::vector<float> & second)205     void assertGreaterGain(const std::vector<float>& first, const std::vector<float>& second) {
206         for (size_t i = 0; i < first.size(); i++) {
207             if (first[i] != 0) {
208                 ASSERT_GT(abs(first[i]), abs(second[i]));
209 
210             } else {
211                 ASSERT_EQ(first[i], second[i]);
212             }
213         }
214     }
215 
assertSequentialGains(const std::vector<int> & gainValues,bool isIncreasing)216     void assertSequentialGains(const std::vector<int>& gainValues, bool isIncreasing) {
217         std::vector<float> baseOutput(mBufferSizeInFrames);
218 
219         // Process a reference output buffer with 0 gain which gives compressed input values
220         binder_exception_t expected;
221         expected = isGainValid(kZeroGain);
222         ASSERT_EQ(expected, EX_NONE);
223         // reset state to prevent prior signal history from affecting trial run.
224         ASSERT_NO_FATAL_FAILURE(reset());
225         setParameters(kZeroGain, expected);
226         ASSERT_NO_FATAL_FAILURE(processAndWriteToOutput());
227         baseOutput = mOutputBuffer;
228 
229         // Compare the outputs for increasing gain
230         for (int gain : gainValues) {
231             // Setting the parameters
232             binder_exception_t expected = isGainValid(gain);
233             if (expected != EX_NONE) {
234                 GTEST_SKIP() << "Gains not supported.";
235             }
236             // reset state to prevent prior signal history from affecting trial run.
237             ASSERT_NO_FATAL_FAILURE(reset());
238             setParameters(gain, expected);
239             ASSERT_NO_FATAL_FAILURE(processAndWriteToOutput());
240 
241             // Compare the mOutputBuffer values with baseOutput and update it
242             if (isIncreasing) {
243                 ASSERT_NO_FATAL_FAILURE(assertGreaterGain(mOutputBuffer, baseOutput));
244             } else {
245                 ASSERT_NO_FATAL_FAILURE(assertGreaterGain(baseOutput, mOutputBuffer));
246             }
247 
248             baseOutput = mOutputBuffer;
249         }
250     }
251 
252     std::unique_ptr<StatusMQ> mStatusMQ;
253     std::unique_ptr<DataMQ> mInputMQ;
254     std::unique_ptr<DataMQ> mOutputMQ;
255 
256     std::vector<float> mInputBuffer;
257     std::vector<float> mOutputBuffer;
258     size_t mBufferSizeInFrames;
259 };
260 
TEST_P(LoudnessEnhancerDataTest,IncreasingGains)261 TEST_P(LoudnessEnhancerDataTest, IncreasingGains) {
262     static const std::vector<int> kIncreasingGains = {50, 100};
263 
264     ASSERT_NO_FATAL_FAILURE(assertSequentialGains(kIncreasingGains, true /*isIncreasing*/));
265 }
266 
TEST_P(LoudnessEnhancerDataTest,DecreasingGains)267 TEST_P(LoudnessEnhancerDataTest, DecreasingGains) {
268     static const std::vector<int> kDecreasingGains = {-50, -100};
269 
270     ASSERT_NO_FATAL_FAILURE(assertSequentialGains(kDecreasingGains, false /*isIncreasing*/));
271 }
272 
TEST_P(LoudnessEnhancerDataTest,MinimumGain)273 TEST_P(LoudnessEnhancerDataTest, MinimumGain) {
274     // Setting the parameters
275     binder_exception_t expected = isGainValid(kMinGain);
276     if (expected != EX_NONE) {
277         GTEST_SKIP() << "Minimum integer value not supported";
278     }
279     setParameters(kMinGain, expected);
280     ASSERT_NO_FATAL_FAILURE(processAndWriteToOutput());
281 
282     // Validate that mOutputBuffer has 0 values for INT_MIN gain
283     for (size_t i = 0; i < mOutputBuffer.size(); i++) {
284         ASSERT_FLOAT_EQ(mOutputBuffer[i], 0);
285     }
286 }
287 
TEST_P(LoudnessEnhancerDataTest,MaximumGain)288 TEST_P(LoudnessEnhancerDataTest, MaximumGain) {
289     // Setting the parameters
290     binder_exception_t expected = isGainValid(kMaxGain);
291     if (expected != EX_NONE) {
292         GTEST_SKIP() << "Maximum integer value not supported";
293     }
294     setParameters(kMaxGain, expected);
295     ASSERT_NO_FATAL_FAILURE(processAndWriteToOutput());
296 
297     // Validate that mOutputBuffer reaches to kMaxAudioSampleValue for INT_MAX gain
298     for (size_t i = 0; i < mOutputBuffer.size(); i++) {
299         if (mInputBuffer[i] != 0) {
300             EXPECT_NEAR(kMaxAudioSampleValue, abs(mOutputBuffer[i]), kAbsError);
301         } else {
302             ASSERT_EQ(mOutputBuffer[i], mInputBuffer[i]);
303         }
304     }
305 }
306 
307 INSTANTIATE_TEST_SUITE_P(
308         LoudnessEnhancerTest, LoudnessEnhancerParamTest,
309         ::testing::Combine(testing::ValuesIn(EffectFactoryHelper::getAllEffectDescriptors(
310                                    IFactory::descriptor, getEffectTypeUuidLoudnessEnhancer())),
311                            testing::ValuesIn(kGainMbValues)),
__anon53125b360102(const testing::TestParamInfo<LoudnessEnhancerParamTest::ParamType>& info) 312         [](const testing::TestParamInfo<LoudnessEnhancerParamTest::ParamType>& info) {
313             auto descriptor = std::get<PARAM_INSTANCE_NAME>(info.param).second;
314             std::string gainMb = std::to_string(std::get<PARAM_GAIN_MB>(info.param));
315             std::string name = getPrefix(descriptor) + "_gainMb_" + gainMb;
316             std::replace_if(
317                     name.begin(), name.end(), [](const char c) { return !std::isalnum(c); }, '_');
318             return name;
319         });
320 
321 GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(LoudnessEnhancerParamTest);
322 
323 INSTANTIATE_TEST_SUITE_P(
324         LoudnessEnhancerTest, LoudnessEnhancerDataTest,
325         testing::ValuesIn(EffectFactoryHelper::getAllEffectDescriptors(
326                 IFactory::descriptor, getEffectTypeUuidLoudnessEnhancer())),
__anon53125b360302(const testing::TestParamInfo<LoudnessEnhancerDataTest::ParamType>& info) 327         [](const testing::TestParamInfo<LoudnessEnhancerDataTest::ParamType>& info) {
328             auto descriptor = info.param;
329             std::string name = getPrefix(descriptor.second);
330             std::replace_if(
331                     name.begin(), name.end(), [](const char c) { return !std::isalnum(c); }, '_');
332             return name;
333         });
334 
335 GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(LoudnessEnhancerDataTest);
336 
main(int argc,char ** argv)337 int main(int argc, char** argv) {
338     ::testing::InitGoogleTest(&argc, argv);
339     ::testing::UnitTest::GetInstance()->listeners().Append(new TestExecutionTracer());
340     ABinderProcess_setThreadPoolMaxThreadCount(1);
341     ABinderProcess_startThreadPool();
342     return RUN_ALL_TESTS();
343 }
344