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