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 #define LOG_TAG "ElementWiseAidlUnionTest"
18
19 #include <aidl/android/hardware/audio/effect/DynamicsProcessing.h>
20 #include <gtest/gtest.h>
21 #include <log/log.h>
22 #include <system/elementwise_op.h>
23
24 using ::aidl::android::hardware::audio::effect::DynamicsProcessing;
25 using ::android::audio_utils::elementwise_clamp;
26 using ::android::audio_utils::elementwise_max;
27 using ::android::audio_utils::elementwise_min;
28
dynamicsProcessing(int v=0)29 static DynamicsProcessing dynamicsProcessing(int v = 0) {
30 const DynamicsProcessing::EngineArchitecture engine{
31 .preferredProcessingDurationMs = static_cast<float>(v),
32 .preEqStage = DynamicsProcessing::StageEnablement{.bandCount = v},
33 .postEqStage = DynamicsProcessing::StageEnablement{.bandCount = v},
34 .mbcStage = DynamicsProcessing::StageEnablement{.bandCount = v},
35 };
36
37 return DynamicsProcessing::make<DynamicsProcessing::engineArchitecture>(engine);
38 }
39
dynamicsProcessing(int v1,int v2)40 static DynamicsProcessing dynamicsProcessing(int v1, int v2) {
41 const DynamicsProcessing::EngineArchitecture engine{
42 .preferredProcessingDurationMs = static_cast<float>(v1),
43 .preEqStage = DynamicsProcessing::StageEnablement{.bandCount = v2},
44 .postEqStage = DynamicsProcessing::StageEnablement{.bandCount = v1},
45 .mbcStage = DynamicsProcessing::StageEnablement{.bandCount = v2},
46 };
47
48 return DynamicsProcessing::make<DynamicsProcessing::engineArchitecture>(engine);
49 }
50
51 static const DynamicsProcessing kDpDifferentTag;
52
53 class ElementWiseAidlUnionTest : public ::testing::TestWithParam<int> {
54 public:
ElementWiseAidlUnionTest()55 ElementWiseAidlUnionTest() : value(GetParam()) {}
56
57 protected:
58 const int value;
59 };
60
61 // min/max/clamp op on same AIDL unions should get same value as result
TEST_P(ElementWiseAidlUnionTest,aidl_union_op_self)62 TEST_P(ElementWiseAidlUnionTest, aidl_union_op_self) {
63 const DynamicsProcessing dp = dynamicsProcessing(value);
64 auto min = elementwise_min(dp, dp);
65 ASSERT_NE(std::nullopt, min);
66 EXPECT_EQ(dp, min.value());
67 auto max = elementwise_max(dp, dp);
68 ASSERT_NE(std::nullopt, max);
69 EXPECT_EQ(dp, max.value());
70 auto clamp = elementwise_clamp(dp, dp, dp);
71 ASSERT_NE(std::nullopt, clamp);
72 EXPECT_EQ(dp, clamp.value());
73 }
74
75 // min/max/clamp op on AIDL unions with ascending order
TEST_P(ElementWiseAidlUnionTest,aidl_union_op_ascending)76 TEST_P(ElementWiseAidlUnionTest, aidl_union_op_ascending) {
77 const DynamicsProcessing dp1 = dynamicsProcessing(value);
78 const DynamicsProcessing dp2 = dynamicsProcessing(value + 1);
79 const DynamicsProcessing dp3 = dynamicsProcessing(value + 2);
80 auto min = elementwise_min(dp1, dp2);
81 ASSERT_NE(std::nullopt, min);
82 EXPECT_EQ(dp1, min.value());
83
84 auto max = elementwise_max(dp1, dp2);
85 ASSERT_NE(std::nullopt, max);
86 EXPECT_EQ(dp2, max.value());
87
88 auto clamped = elementwise_clamp(dp1, dp1, dp3);
89 ASSERT_NE(std::nullopt, clamped);
90 EXPECT_EQ(dp1, clamped.value());
91
92 clamped = elementwise_clamp(dp2, dp1, dp3);
93 ASSERT_NE(std::nullopt, clamped);
94 EXPECT_EQ(dp2, clamped.value());
95
96 clamped = elementwise_clamp(dp3, dp1, dp3);
97 ASSERT_NE(std::nullopt, clamped);
98 EXPECT_EQ(dp3, clamped.value());
99
100 clamped = elementwise_clamp(dp1, dp2, dp3);
101 ASSERT_NE(std::nullopt, clamped);
102 EXPECT_EQ(dp2, clamped.value());
103 }
104
105 // min/max/clamp op on AIDL unions with descending order
TEST_P(ElementWiseAidlUnionTest,aidl_union_op_descending)106 TEST_P(ElementWiseAidlUnionTest, aidl_union_op_descending) {
107 const DynamicsProcessing dp1 = dynamicsProcessing(value);
108 const DynamicsProcessing dp2 = dynamicsProcessing(value + 1);
109 const DynamicsProcessing dp3 = dynamicsProcessing(value + 2);
110 auto min = elementwise_min(dp2, dp1);
111 ASSERT_NE(std::nullopt, min);
112 EXPECT_EQ(dp1, min.value());
113
114 auto max = elementwise_max(dp2, dp1);
115 ASSERT_NE(std::nullopt, max);
116 EXPECT_EQ(dp2, max.value());
117
118 auto clamped = elementwise_clamp(dp3, dp2, dp1);
119 ASSERT_EQ(std::nullopt, clamped);
120
121 clamped = elementwise_clamp(dp1, dp3, dp1);
122 ASSERT_EQ(std::nullopt, clamped);
123
124 clamped = elementwise_clamp(dp2, dp3, dp1);
125 ASSERT_EQ(std::nullopt, clamped);
126
127 clamped = elementwise_clamp(dp3, dp3, dp1);
128 ASSERT_EQ(std::nullopt, clamped);
129
130 clamped = elementwise_clamp(dp1, dp3, dp2);
131 ASSERT_EQ(std::nullopt, clamped);
132 }
133
134 constexpr int kTestParamValues[] = {0, 1, 10};
135
136 INSTANTIATE_TEST_SUITE_P(AidlUtilsTest, ElementWiseAidlUnionTest,
137 testing::ValuesIn(kTestParamValues));
138
139 // expect `std::nullopt` when comparing two AIDL unions with different tags
TEST(ElementWiseAidlUnionTest,aidl_union_op_mismatch_tag)140 TEST(ElementWiseAidlUnionTest, aidl_union_op_mismatch_tag) {
141 const DynamicsProcessing dp = dynamicsProcessing();
142
143 EXPECT_EQ(std::nullopt, elementwise_min(dp, kDpDifferentTag));
144 EXPECT_EQ(std::nullopt, elementwise_min(kDpDifferentTag, dp));
145 EXPECT_EQ(std::nullopt, elementwise_max(dp, kDpDifferentTag));
146 EXPECT_EQ(std::nullopt, elementwise_max(kDpDifferentTag, dp));
147 EXPECT_EQ(std::nullopt, elementwise_clamp(dp, dp, kDpDifferentTag));
148 EXPECT_EQ(std::nullopt, elementwise_clamp(dp, kDpDifferentTag, dp));
149 }
150
151 // min/max op on AIDL unions with mixed parameter values
TEST(ElementWiseAidlUnionTest,aidl_union_op_compare_mix)152 TEST(ElementWiseAidlUnionTest, aidl_union_op_compare_mix) {
153 const auto dp12 = dynamicsProcessing(1, 2);
154 const auto dp21 = dynamicsProcessing(2, 1);
155 const auto dp34 = dynamicsProcessing(3, 4);
156 const auto dp43 = dynamicsProcessing(4, 3);
157
158 auto min = elementwise_min(dp12, dp21);
159 ASSERT_NE(std::nullopt, min);
160 EXPECT_EQ(dynamicsProcessing(1), min.value());
161 auto max = elementwise_max(dp12, dp21);
162 ASSERT_NE(std::nullopt, max);
163 EXPECT_EQ(dynamicsProcessing(2), max.value());
164
165 min = elementwise_min(dp34, dp43);
166 ASSERT_NE(std::nullopt, min);
167 EXPECT_EQ(dynamicsProcessing(3), min.value());
168 max = elementwise_max(dp34, dp43);
169 ASSERT_NE(std::nullopt, max);
170 EXPECT_EQ(dynamicsProcessing(4), max.value());
171 }
172
173 // clamp op on AIDL unions with mixed parameter values
TEST(ElementWiseAidlUnionTest,aidl_union_op_clamp_mix)174 TEST(ElementWiseAidlUnionTest, aidl_union_op_clamp_mix) {
175 const auto dp3 = dynamicsProcessing(3);
176 const auto dp4 = dynamicsProcessing(4);
177 const auto dp34 = dynamicsProcessing(3, 4);
178 const auto dp43 = dynamicsProcessing(4, 3);
179 const auto dp33 = dynamicsProcessing(3, 3);
180 const auto dp44 = dynamicsProcessing(4, 4);
181
182 auto clamped = elementwise_clamp(dp34, dp3, dp4);
183 ASSERT_NE(std::nullopt, clamped);
184 EXPECT_EQ(dp34, clamped.value());
185 clamped = elementwise_clamp(dp43, dp33, dp44);
186 ASSERT_NE(std::nullopt, clamped);
187 EXPECT_EQ(dp43, clamped.value());
188 clamped = elementwise_clamp(dp34, dp3, dp3);
189 ASSERT_NE(std::nullopt, clamped);
190 EXPECT_EQ(dp3, clamped.value());
191 clamped = elementwise_clamp(dp43, dp4, dp4);
192 ASSERT_NE(std::nullopt, clamped);
193 EXPECT_EQ(dp4, clamped.value());
194 }