xref: /aosp_15_r20/system/media/tests/aidl_effects_utils_test.cpp (revision b9df5ad1c9ac98a7fefaac271a55f7ae3db05414)
1 /*
2  * Copyright (C) 2024 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 <array>
18 
19 #define LOG_TAG "AidlEffectsUtilsTest"
20 
21 #include <aidl/android/hardware/audio/effect/IEffect.h>
22 #include <gtest/gtest.h>
23 #include <log/log.h>
24 #include <system/audio_effects/aidl_effects_utils.h>
25 
26 using ::aidl::android::hardware::audio::effect::Capability;
27 using ::aidl::android::hardware::audio::effect::Downmix;
28 using ::aidl::android::hardware::audio::effect::DynamicsProcessing;
29 using ::aidl::android::hardware::audio::effect::Parameter;
30 using ::aidl::android::hardware::audio::effect::Range;
31 
32 // Helper function to create a DynamicsProcessing parameter with custom tag
33 template <typename DynamicsProcessing::Tag TAG = DynamicsProcessing::engineArchitecture>
dynamicsProcessing(int v,int n=0)34 static DynamicsProcessing dynamicsProcessing(int v, int n = 0) {
35   if constexpr (TAG == DynamicsProcessing::engineArchitecture) {
36     const DynamicsProcessing::EngineArchitecture engine{
37         .preferredProcessingDurationMs = static_cast<float>(v),
38         .preEqStage = DynamicsProcessing::StageEnablement{.bandCount = v},
39         .postEqStage = DynamicsProcessing::StageEnablement{.bandCount = v},
40         .mbcStage = DynamicsProcessing::StageEnablement{.bandCount = v},
41     };
42     return DynamicsProcessing::make<DynamicsProcessing::engineArchitecture>(engine);
43   } else if constexpr (TAG == DynamicsProcessing::inputGain) {
44     std::vector<DynamicsProcessing::InputGain> gain;
45     for (int i = 0; i < n; i++) {
46       gain.emplace_back(DynamicsProcessing::InputGain{
47           .channel = i, .gainDb = static_cast<float>(v)});
48     }
49     return DynamicsProcessing::make<DynamicsProcessing::inputGain>(gain);
50   } else {
51     static_assert(false, "tag not supported");
52   }
53 }
54 
parameter(int v)55 static Parameter parameter(int v) {
56   return Parameter::make<Parameter::specific>(
57       Parameter::Specific::make<Parameter::Specific::dynamicsProcessing>(dynamicsProcessing(v)));
58 }
59 
capability(int min,int max)60 static Capability capability(int min, int max) {
61   return Capability{
62       .range =
63           Range::make<Range::dynamicsProcessing>({Range::DynamicsProcessingRange{
64               .min = dynamicsProcessing(min), .max = dynamicsProcessing(max),
65           }}),
66   };
67 }
68 
multiCapability(int min,int max)69 static Capability multiCapability(int min, int max) {
70   return Capability{
71       .range = Range::make<Range::dynamicsProcessing>({
72           Range::DynamicsProcessingRange{
73               .min = dynamicsProcessing(min), .max = dynamicsProcessing(max),
74           },
75           Range::DynamicsProcessingRange{
76               .min = dynamicsProcessing<DynamicsProcessing::inputGain>(min),
77               .max = dynamicsProcessing<DynamicsProcessing::inputGain>(max),
78           },
79       }),
80   };
81 }
82 
83 // construct an invalid capability with different vector size
capabilityWithDifferentVecSize(int min,int minVecSize,int max,int maxVecSize)84 static Capability capabilityWithDifferentVecSize(int min, int minVecSize, int max, int maxVecSize) {
85   return Capability{
86       .range = Range::make<Range::dynamicsProcessing>({
87           Range::DynamicsProcessingRange{
88               .min = dynamicsProcessing<DynamicsProcessing::inputGain>(min, minVecSize),
89               .max = dynamicsProcessing<DynamicsProcessing::inputGain>(max, maxVecSize),
90           },
91       }),
92   };
93 }
94 
downmixCapability()95 static Capability downmixCapability() {
96   return Capability{.range = Range::make<Range::downmix>({Range::DownmixRange{}})};
97 }
98 
99 // static Range::DynamicsProcessingRange createMultiRange(int min, int max) {
100 //   return Range::DynamicsProcessingRange{.min = min, .max = max};
101 // }
102 
103 using FindSharedCapabilityTestParam =
104     std::tuple<int /* a_min */, int /* a_max */, int /*b_min*/, int /*b_max*/>;
105 class FindSharedCapabilityTest
106     : public ::testing::TestWithParam<FindSharedCapabilityTestParam> {
107  public:
FindSharedCapabilityTest()108   FindSharedCapabilityTest()
109       : a_min(std::get<0>(GetParam())),
110         a_max(std::get<1>(GetParam())),
111         b_min(std::get<2>(GetParam())),
112         b_max(std::get<3>(GetParam())) {}
113 
114  protected:
115   const int a_min, a_max, b_min, b_max;
116 };
117 
118 /**
119  * Find shared capability with all elements in the predefined capability array `kCapArray`.
120  */
TEST_P(FindSharedCapabilityTest,basic)121 TEST_P(FindSharedCapabilityTest, basic) {
122   std::optional<Capability> cap =
123       findSharedCapability(capability(a_min, a_max), capability(b_min, b_max));
124   ASSERT_NE(std::nullopt, cap);
125   EXPECT_EQ(capability(std::max(a_min, b_min), std::min(a_max, b_max)).range, cap->range);
126 }
127 
TEST_P(FindSharedCapabilityTest,multi_tags)128 TEST_P(FindSharedCapabilityTest, multi_tags) {
129   std::optional<Capability> cap = findSharedCapability(
130       multiCapability(a_min, a_max), multiCapability(b_min, b_max));
131   ASSERT_NE(std::nullopt, cap);
132   EXPECT_EQ(multiCapability(std::max(a_min, b_min), std::min(a_max, b_max)).range, cap->range);
133 }
134 
TEST(FindSharedCapabilityTest,diff_effects)135 TEST(FindSharedCapabilityTest, diff_effects) {
136   EXPECT_EQ(std::nullopt, findSharedCapability(capability(0, 1), downmixCapability()));
137 }
138 
TEST(FindSharedCapabilityTest,capability_with_diff_vec)139 TEST(FindSharedCapabilityTest, capability_with_diff_vec) {
140   auto target = capabilityWithDifferentVecSize(1, 5, 2, 6);
141   auto shared = findSharedCapability(
142       capabilityWithDifferentVecSize(0 /*min*/, 5 /*minVacSize*/, 3 /*max*/, 6 /*maxVacSize*/),
143       capabilityWithDifferentVecSize(1 /*min*/, 5 /*minVacSize*/, 2 /*max*/, 6 /*maxVacSize*/));
144   ASSERT_NE(std::nullopt, shared);
145   EXPECT_EQ(target.range, shared->range);
146 
147   // the shared min is invalid because the vector size is different
148   target = capabilityWithDifferentVecSize(0, 0, 1, 3);
149   shared = findSharedCapability(
150       capabilityWithDifferentVecSize(0 /*min*/, 2 /*minVacSize*/, 1 /*max*/, 3 /*maxVacSize*/),
151       capabilityWithDifferentVecSize(0 /*min*/, 3 /*minVacSize*/, 1 /*max*/, 3 /*maxVacSize*/));
152   ASSERT_NE(std::nullopt, shared);
153   ASSERT_EQ(Range::dynamicsProcessing, shared->range.getTag());
154   auto dpRanges = shared->range.get<Range::dynamicsProcessing>();
155   ASSERT_EQ(1ul, dpRanges.size());
156   EXPECT_EQ(DynamicsProcessing::vendor, dpRanges[0].min.getTag());
157   const auto targetRanges = target.range.get<Range::dynamicsProcessing>();
158   EXPECT_EQ(targetRanges[0].max, dpRanges[0].max);
159 
160   // the shared min and max both invalid because the vector size is different
161   target = capabilityWithDifferentVecSize(0, 0, 1, 3);
162   shared = findSharedCapability(
163       capabilityWithDifferentVecSize(0 /*min*/, 2 /*minVacSize*/, 1 /*max*/, 5 /*maxVacSize*/),
164       capabilityWithDifferentVecSize(0 /*min*/, 3 /*minVacSize*/, 1 /*max*/, 3 /*maxVacSize*/));
165   EXPECT_EQ(std::nullopt, shared);
166 }
167 
168 using ClampParameterTestParam = std::tuple<int /* a */, int /* b */>;
169 class ClampParameterTest
170     : public ::testing::TestWithParam<ClampParameterTestParam> {
171  public:
ClampParameterTest()172   ClampParameterTest()
173       : a(std::get<0>(GetParam())), b(std::get<1>(GetParam())) {}
174 
175  protected:
176   const int a, b;
177 };
178 
TEST_P(ClampParameterTest,basic)179 TEST_P(ClampParameterTest, basic) {
180   const std::optional<Parameter> clamped =
181       clampParameter<Range::dynamicsProcessing, Parameter::Specific::dynamicsProcessing>(
182           parameter(a), capability(a, b));
183   if (a <= b) {
184     ASSERT_NE(std::nullopt, clamped);
185     EXPECT_EQ(parameter(a), clamped.value());
186   } else {
187     EXPECT_EQ(std::nullopt, clamped);
188   }
189 }
190 
TEST_P(ClampParameterTest,clamp_to_min)191 TEST_P(ClampParameterTest, clamp_to_min) {
192   const std::optional<Parameter> clamped =
193       clampParameter<Range::dynamicsProcessing, Parameter::Specific::dynamicsProcessing>(
194           parameter(a - 1), capability(a, b));
195   if (a <= b) {
196     ASSERT_NE(std::nullopt, clamped);
197     EXPECT_EQ(parameter(a), clamped.value());
198   } else {
199     EXPECT_EQ(std::nullopt, clamped);
200   }
201 }
202 
TEST_P(ClampParameterTest,clamp_to_max)203 TEST_P(ClampParameterTest, clamp_to_max) {
204   const std::optional<Parameter> clamped =
205       clampParameter<Range::dynamicsProcessing, Parameter::Specific::dynamicsProcessing>(
206           parameter(b + 1), capability(a, b));
207   if (a <= b) {
208     ASSERT_NE(std::nullopt, clamped);
209     EXPECT_EQ(parameter(b), clamped.value());
210   } else {
211     EXPECT_EQ(std::nullopt, clamped);
212   }
213 }
214 
215 // minimum and maximum value used to initialize effect parameters for comparison
216 static constexpr int kParameterStartValue = 1;
217 static constexpr int kParameterEndValue = 4; // end will not included in the generated values
218 
219 INSTANTIATE_TEST_SUITE_P(
220     AidlEffectsUtilsTest, FindSharedCapabilityTest,
221     ::testing::Combine(testing::Range(kParameterStartValue, kParameterEndValue),
222                        testing::Range(kParameterStartValue, kParameterEndValue),
223                        testing::Range(kParameterStartValue, kParameterEndValue),
224                        testing::Range(kParameterStartValue, kParameterEndValue)),
__anon30a6e0730102(const testing::TestParamInfo<FindSharedCapabilityTest::ParamType>& info) 225     [](const testing::TestParamInfo<FindSharedCapabilityTest::ParamType>& info) {
226       return std::to_string(std::get<0>(info.param)) + "_" +
227              std::to_string(std::get<1>(info.param)) + "_" +
228              std::to_string(std::get<2>(info.param)) + "_" +
229              std::to_string(std::get<3>(info.param));
230     });
231 
232 INSTANTIATE_TEST_SUITE_P(
233     AidlEffectsUtilsTest, ClampParameterTest,
234     ::testing::Combine(testing::Range(kParameterStartValue, kParameterEndValue),
235                        testing::Range(kParameterStartValue, kParameterEndValue)),
__anon30a6e0730202(const testing::TestParamInfo<ClampParameterTest::ParamType>& info) 236     [](const testing::TestParamInfo<ClampParameterTest::ParamType>& info) {
237       return std::to_string(std::get<0>(info.param)) + "_" +
238              std::to_string(std::get<1>(info.param));
239     });