1 /*
2 * Copyright 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 //#define LOG_NDEBUG 0
18 #include <algorithm>
19 #include <array>
20 #include <cstddef>
21 #include <cstdint>
22 #include <cstring>
23 #include <memory>
24 #include <utility>
25 #define LOG_TAG "EffectsFactoryHalInterfaceTest"
26
27 #include <aidl/android/media/audio/common/AudioUuid.h>
28 #include <gtest/gtest.h>
29 #include <media/AidlConversionCppNdk.h>
30 #include <media/audiohal/EffectsFactoryHalInterface.h>
31 #include <system/audio_aidl_utils.h>
32 #include <system/audio_effect.h>
33 #include <system/audio_effects/audio_effects_utils.h>
34 #include <system/audio_effects/effect_aec.h>
35 #include <system/audio_effects/effect_agc.h>
36 #include <system/audio_effects/effect_agc2.h>
37 #include <system/audio_effects/effect_bassboost.h>
38 #include <system/audio_effects/effect_downmix.h>
39 #include <system/audio_effects/effect_dynamicsprocessing.h>
40 #include <system/audio_effects/effect_hapticgenerator.h>
41 #include <system/audio_effects/effect_loudnessenhancer.h>
42 #include <system/audio_effects/effect_ns.h>
43 #include <utils/RefBase.h>
44 #include <vibrator/ExternalVibrationUtils.h>
45
46 namespace android {
47
48 using ::aidl::android::media::audio::common::AudioUuid;
49 using ::android::audio::utils::toString;
50 using effect::utils::EffectParamReader;
51 using effect::utils::EffectParamWriter;
52
53 // EffectsFactoryHalInterface
TEST(libAudioHalTest,createEffectsFactoryHalInterface)54 TEST(libAudioHalTest, createEffectsFactoryHalInterface) {
55 ASSERT_NE(nullptr, EffectsFactoryHalInterface::create());
56 }
57
TEST(libAudioHalTest,queryNumberEffects)58 TEST(libAudioHalTest, queryNumberEffects) {
59 auto factory = EffectsFactoryHalInterface::create();
60 ASSERT_NE(nullptr, factory);
61
62 uint32_t numEffects = 0;
63 EXPECT_EQ(OK, factory->queryNumberEffects(&numEffects));
64 EXPECT_NE(0ul, numEffects);
65 }
66
TEST(libAudioHalTest,getDescriptorByNumber)67 TEST(libAudioHalTest, getDescriptorByNumber) {
68 auto factory = EffectsFactoryHalInterface::create();
69 ASSERT_NE(nullptr, factory);
70
71 uint32_t numEffects = 0;
72 EXPECT_EQ(OK, factory->queryNumberEffects(&numEffects));
73 EXPECT_NE(0ul, numEffects);
74
75 effect_descriptor_t desc;
76 for (uint32_t i = 0; i < numEffects; i++) {
77 EXPECT_EQ(OK, factory->getDescriptor(i, &desc));
78 }
79 }
80
TEST(libAudioHalTest,createEffect)81 TEST(libAudioHalTest, createEffect) {
82 auto factory = EffectsFactoryHalInterface::create();
83 ASSERT_NE(nullptr, factory);
84
85 uint32_t numEffects = 0;
86 EXPECT_EQ(OK, factory->queryNumberEffects(&numEffects));
87 EXPECT_NE(0ul, numEffects);
88
89 effect_descriptor_t desc;
90 for (uint32_t i = 0; i < numEffects; i++) {
91 sp<EffectHalInterface> interface;
92 EXPECT_EQ(OK, factory->getDescriptor(i, &desc));
93 EXPECT_EQ(OK, factory->createEffect(&desc.uuid, 1 /* sessionId */, 1 /* ioId */,
94 1 /* deviceId */, &interface));
95 }
96 }
97
TEST(libAudioHalTest,getProcessings)98 TEST(libAudioHalTest, getProcessings) {
99 auto factory = EffectsFactoryHalInterface::create();
100 ASSERT_NE(nullptr, factory);
101
102 const auto &processings = factory->getProcessings();
103 if (processings) {
104 EXPECT_NE(0UL, processings->preprocess.size() + processings->postprocess.size() +
105 processings->deviceprocess.size());
106
107 auto processingChecker = [](const auto& processings) {
108 if (processings.size() != 0) {
109 // any process need at least 1 effect inside
110 std::for_each(processings.begin(), processings.end(), [](const auto& process) {
111 EXPECT_NE(0ul, process.effects.size());
112 // any effect should have a valid name string, and not proxy
113 for (const auto& effect : process.effects) {
114 SCOPED_TRACE("Effect: {" +
115 (effect == nullptr
116 ? "NULL}"
117 : ("{name: " + effect->name + ", isproxy: " +
118 (effect->isProxy ? "true" : "false") + ", sw: " +
119 (effect->libSw ? "non-null" : "null") + ", hw: " +
120 (effect->libHw ? "non-null" : "null") + "}")));
121 EXPECT_NE(nullptr, effect);
122 EXPECT_NE("", effect->name);
123 EXPECT_EQ(false, effect->isProxy);
124 EXPECT_EQ(nullptr, effect->libSw);
125 EXPECT_EQ(nullptr, effect->libHw);
126 }
127 });
128 }
129 };
130
131 processingChecker(processings->preprocess);
132 processingChecker(processings->postprocess);
133 processingChecker(processings->deviceprocess);
134 } else {
135 GTEST_SKIP() << "no processing found, skipping the test";
136 }
137 }
138
TEST(libAudioHalTest,getHalVersion)139 TEST(libAudioHalTest, getHalVersion) {
140 auto factory = EffectsFactoryHalInterface::create();
141 ASSERT_NE(nullptr, factory);
142
143 auto version = factory->getHalVersion();
144 EXPECT_NE(0, version.getMajorVersion());
145 }
146
147 class EffectParamCombination {
148 public:
149 template <typename P, typename V>
init(const P & p,const V & v,size_t len)150 void init(const P& p, const V& v, size_t len) {
151 setBuffer.resize(sizeof(effect_param_t) + sizeof(p) + sizeof(v) + 4);
152 getBuffer.resize(sizeof(effect_param_t) + sizeof(p) + len + 4);
153 expectBuffer.resize(sizeof(effect_param_t) + sizeof(p) + len + 4);
154 parameterSet =
155 std::make_shared<EffectParamReader>(createEffectParam(setBuffer.data(), p, v));
156 parameterGet =
157 std::make_shared<EffectParamReader>(createEffectParam(getBuffer.data(), p, v));
158 parameterExpect =
159 std::make_shared<EffectParamReader>(createEffectParam(expectBuffer.data(), p, v));
160 valueSize = len;
161 }
162
163 std::shared_ptr<EffectParamReader> parameterSet; /* setParameter */
164 std::shared_ptr<EffectParamReader> parameterGet; /* getParameter */
165 std::shared_ptr<EffectParamReader> parameterExpect; /* expected from getParameter */
166 size_t valueSize; /* ValueSize expect to write in reply data buffer */
167
168 private:
169 std::vector<uint8_t> setBuffer;
170 std::vector<uint8_t> getBuffer;
171 std::vector<uint8_t> expectBuffer;
172
173 template <typename P, typename V>
createEffectParam(void * buf,const P & p,const V & v)174 EffectParamReader createEffectParam(void* buf, const P& p, const V& v) {
175 effect_param_t* paramRet = (effect_param_t*)buf;
176 paramRet->psize = sizeof(P);
177 paramRet->vsize = sizeof(V);
178 EffectParamWriter writer(*paramRet);
179 EXPECT_EQ(OK, writer.writeToParameter(&p));
180 EXPECT_EQ(OK, writer.writeToValue(&v));
181 writer.finishValueWrite();
182 return writer;
183 }
184 };
185
186 template <typename P, typename V>
createEffectParamCombination(const P & p,const V & v,size_t len)187 std::shared_ptr<EffectParamCombination> createEffectParamCombination(const P& p, const V& v,
188 size_t len) {
189 auto comb = std::make_shared<EffectParamCombination>();
190 comb->init(p, v, len);
191 return comb;
192 }
193
194 enum ParamName { TUPLE_UUID, TUPLE_PARAM_COMBINATION };
195 using EffectParamTestTuple =
196 std::tuple<const effect_uuid_t* /* type UUID */, std::shared_ptr<EffectParamCombination>>;
197
198 static const effect_uuid_t EXTEND_EFFECT_TYPE_UUID = {
199 0xfa81dbde, 0x588b, 0x11ed, 0x9b6a, {0x02, 0x42, 0xac, 0x12, 0x00, 0x02}};
200 constexpr std::array<uint8_t, 10> kVendorExtensionData({0xff, 0x5, 0x50, 0xab, 0xcd, 0x00, 0xbd,
201 0xdb, 0xee, 0xff});
202 std::vector<EffectParamTestTuple> testPairs = {
203 std::make_tuple(FX_IID_AEC,
204 createEffectParamCombination(AEC_PARAM_ECHO_DELAY, 0xff /* echoDelayMs */,
205 sizeof(int32_t) /* returnValueSize */)),
206 std::make_tuple(FX_IID_AGC,
207 createEffectParamCombination(AGC_PARAM_TARGET_LEVEL, 20 /* targetLevel */,
208 sizeof(int16_t) /* returnValueSize */)),
209 std::make_tuple(SL_IID_BASSBOOST,
210 createEffectParamCombination(BASSBOOST_PARAM_STRENGTH, 20 /* strength */,
211 sizeof(int16_t) /* returnValueSize */)),
212 std::make_tuple(EFFECT_UIID_DOWNMIX,
213 createEffectParamCombination(DOWNMIX_PARAM_TYPE, DOWNMIX_TYPE_FOLD,
214 sizeof(int16_t) /* returnValueSize */)),
215 std::make_tuple(SL_IID_DYNAMICSPROCESSING,
216 createEffectParamCombination(
217 std::array<uint32_t, 2>({DP_PARAM_INPUT_GAIN, 0 /* channel */}),
218 30 /* gainDb */, sizeof(int32_t) /* returnValueSize */)),
219 std::make_tuple(
220 FX_IID_LOUDNESS_ENHANCER,
221 createEffectParamCombination(LOUDNESS_ENHANCER_PARAM_TARGET_GAIN_MB, 5 /* gain */,
222 sizeof(int32_t) /* returnValueSize */)),
223 std::make_tuple(FX_IID_NS,
224 createEffectParamCombination(NS_PARAM_LEVEL, 1 /* level */,
225 sizeof(int32_t) /* returnValueSize */)),
226 std::make_tuple(&EXTEND_EFFECT_TYPE_UUID,
227 createEffectParamCombination(8, kVendorExtensionData,
228 sizeof(kVendorExtensionData)))};
229
230 class libAudioHalEffectParamTest : public ::testing::TestWithParam<EffectParamTestTuple> {
231 public:
libAudioHalEffectParamTest()232 libAudioHalEffectParamTest()
233 : mParamTuple(GetParam()),
234 mFactory(EffectsFactoryHalInterface::create()),
235 mTypeUuid(std::get<TUPLE_UUID>(mParamTuple)),
236 mCombination(std::get<TUPLE_PARAM_COMBINATION>(mParamTuple)),
237 mExpectedValue([&]() {
238 std::vector<uint8_t> expectData(mCombination->valueSize);
239 mCombination->parameterExpect->readFromValue(expectData.data(),
240 mCombination->valueSize);
241 return expectData;
242 }()),
__anon64bcb8460402() 243 mDescs([&]() {
244 std::vector<effect_descriptor_t> descs;
245 if (mFactory && mTypeUuid && OK == mFactory->getDescriptors(mTypeUuid, &descs)) {
246 return descs;
247 }
248 return descs;
249 }()) {}
250
SetUp()251 void SetUp() override {
252 if (0ul == mDescs.size()) {
253 GTEST_SKIP() << "Effect type not available on device, skipping";
254 }
255 for (const auto& desc : mDescs) {
256 sp<EffectHalInterface> interface = createEffectHal(desc);
257 ASSERT_NE(nullptr, interface);
258 mHalInterfaces.push_back(interface);
259 }
260 }
261
initEffect(const sp<EffectHalInterface> & interface)262 void initEffect(const sp<EffectHalInterface>& interface) {
263 uint32_t reply = 0;
264 uint32_t replySize = sizeof(reply);
265 ASSERT_EQ(OK, interface->command(EFFECT_CMD_INIT, 0, nullptr, &replySize, &reply));
266 ASSERT_EQ(OK, interface->command(EFFECT_CMD_SET_CONFIG, sizeof(mEffectConfig),
267 &mEffectConfig, &replySize, &reply));
268 }
269
TearDown()270 void TearDown() override {
271 for (auto& interface : mHalInterfaces) {
272 interface->close();
273 }
274 }
275
createEffectHal(const effect_descriptor_t & desc)276 sp<EffectHalInterface> createEffectHal(const effect_descriptor_t& desc) {
277 sp<EffectHalInterface> interface = nullptr;
278 if (0 == std::memcmp(&desc.type, mTypeUuid, sizeof(effect_uuid_t)) &&
279 OK == mFactory->createEffect(&desc.uuid, 1 /* sessionId */, 1 /* ioId */,
280 1 /* deviceId */, &interface)) {
281 return interface;
282 }
283 return nullptr;
284 }
285
setAndGetParameter(const sp<EffectHalInterface> & interface)286 void setAndGetParameter(const sp<EffectHalInterface>& interface) {
287 uint32_t replySize = sizeof(uint32_t);
288 uint8_t reply[replySize];
289 auto parameterSet = mCombination->parameterSet;
290 ASSERT_EQ(OK,
291 interface->command(EFFECT_CMD_SET_PARAM, (uint32_t)parameterSet->getTotalSize(),
292 const_cast<effect_param_t*>(¶meterSet->getEffectParam()),
293 &replySize, &reply))
294 << parameterSet->toString();
295 ASSERT_EQ(replySize, sizeof(uint32_t));
296
297 effect_param_t* getParam =
298 const_cast<effect_param_t*>(&mCombination->parameterGet->getEffectParam());
299 size_t maxReplySize = mCombination->valueSize + sizeof(effect_param_t) +
300 sizeof(parameterSet->getPaddedParameterSize());
301 replySize = maxReplySize;
302 EXPECT_EQ(OK,
303 interface->command(EFFECT_CMD_GET_PARAM, (uint32_t)parameterSet->getTotalSize(),
304 const_cast<effect_param_t*>(¶meterSet->getEffectParam()),
305 &replySize, getParam));
306 EffectParamReader parameterGet(*getParam);
307 EXPECT_EQ(replySize, parameterGet.getTotalSize()) << parameterGet.toString();
308 if (mCombination->valueSize) {
309 std::vector<uint8_t> response(mCombination->valueSize);
310 EXPECT_EQ(OK, parameterGet.readFromValue(response.data(), mCombination->valueSize))
311 << " try get valueSize " << mCombination->valueSize << " from "
312 << parameterGet.toString() << " set " << parameterSet->toString();
313 EXPECT_EQ(response, mExpectedValue);
314 }
315 }
316
317 const EffectParamTestTuple mParamTuple;
318 const sp<EffectsFactoryHalInterface> mFactory;
319 const effect_uuid_t* mTypeUuid;
320 std::shared_ptr<EffectParamCombination> mCombination;
321 const std::vector<uint8_t> mExpectedValue;
322 const std::vector<effect_descriptor_t> mDescs;
323 std::vector<sp<EffectHalInterface>> mHalInterfaces;
324 effect_config_t mEffectConfig = {.inputCfg = {.accessMode = EFFECT_BUFFER_ACCESS_READ,
325 .format = AUDIO_FORMAT_PCM_FLOAT,
326 .bufferProvider.getBuffer = nullptr,
327 .bufferProvider.releaseBuffer = nullptr,
328 .bufferProvider.cookie = nullptr,
329 .mask = EFFECT_CONFIG_ALL,
330 .samplingRate = 48000,
331 .channels = AUDIO_CHANNEL_IN_STEREO},
332
333 .outputCfg = {.accessMode = EFFECT_BUFFER_ACCESS_WRITE,
334 .format = AUDIO_FORMAT_PCM_FLOAT,
335 .bufferProvider.getBuffer = nullptr,
336 .bufferProvider.releaseBuffer = nullptr,
337 .bufferProvider.cookie = nullptr,
338 .mask = EFFECT_CONFIG_ALL,
339 .samplingRate = 48000,
340 .channels = AUDIO_CHANNEL_OUT_STEREO}};
341 };
342
TEST_P(libAudioHalEffectParamTest,setAndGetParam)343 TEST_P(libAudioHalEffectParamTest, setAndGetParam) {
344 for (auto& interface : mHalInterfaces) {
345 EXPECT_NO_FATAL_FAILURE(initEffect(interface));
346 EXPECT_NO_FATAL_FAILURE(setAndGetParameter(interface));
347 }
348 }
349
TEST_P(libAudioHalEffectParamTest,deviceIndicationUpdate)350 TEST_P(libAudioHalEffectParamTest, deviceIndicationUpdate) {
351 for (auto& interface : mHalInterfaces) {
352 EXPECT_NO_FATAL_FAILURE(initEffect(interface));
353
354 // output device
355 uint32_t deviceTypes = AUDIO_DEVICE_OUT_SPEAKER | AUDIO_DEVICE_OUT_BLE_SPEAKER;
356 status_t cmdStatus;
357 uint32_t replySize = sizeof(cmdStatus);
358 EXPECT_EQ(OK, interface->command(EFFECT_CMD_SET_DEVICE, sizeof(uint32_t), &deviceTypes,
359 &replySize, &cmdStatus));
360 // input device
361 deviceTypes = AUDIO_DEVICE_IN_WIRED_HEADSET | AUDIO_DEVICE_IN_BLUETOOTH_BLE;
362 EXPECT_EQ(OK, interface->command(EFFECT_CMD_SET_DEVICE, sizeof(uint32_t), &deviceTypes,
363 &replySize, &cmdStatus));
364 }
365 }
366
TEST_P(libAudioHalEffectParamTest,audioModeIndicationUpdate)367 TEST_P(libAudioHalEffectParamTest, audioModeIndicationUpdate) {
368 for (auto& interface : mHalInterfaces) {
369 EXPECT_NO_FATAL_FAILURE(initEffect(interface));
370 uint32_t mode = AUDIO_MODE_IN_CALL;
371 status_t cmdStatus;
372 uint32_t replySize = sizeof(cmdStatus);
373 EXPECT_EQ(OK, interface->command(EFFECT_CMD_SET_AUDIO_MODE, sizeof(uint32_t), &mode,
374 &replySize, &cmdStatus));
375 }
376 }
377
TEST_P(libAudioHalEffectParamTest,audioSourceIndicationUpdate)378 TEST_P(libAudioHalEffectParamTest, audioSourceIndicationUpdate) {
379 for (auto& interface : mHalInterfaces) {
380 EXPECT_NO_FATAL_FAILURE(initEffect(interface));
381 uint32_t source = AUDIO_SOURCE_MIC;
382 status_t cmdStatus;
383 uint32_t replySize = sizeof(cmdStatus);
384 EXPECT_EQ(OK, interface->command(EFFECT_CMD_SET_AUDIO_SOURCE, sizeof(uint32_t), &source,
385 &replySize, &cmdStatus));
386 }
387 }
388
389 INSTANTIATE_TEST_SUITE_P(
390 libAudioHalEffectParamTest, libAudioHalEffectParamTest, ::testing::ValuesIn(testPairs),
__anon64bcb8460502(const testing::TestParamInfo<libAudioHalEffectParamTest::ParamType>& info) 391 [](const testing::TestParamInfo<libAudioHalEffectParamTest::ParamType>& info) {
392 AudioUuid uuid = ::aidl::android::legacy2aidl_audio_uuid_t_AudioUuid(
393 *std::get<TUPLE_UUID>(info.param))
394 .value();
395 std::string name = "UUID_" + toString(uuid);
396 std::replace_if(
397 name.begin(), name.end(), [](const char c) { return !std::isalnum(c); }, '_');
398 return name;
399 });
400 GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(libAudioHalEffectParamTest);
401
main(int argc,char ** argv)402 int main(int argc, char** argv) {
403 ::testing::InitGoogleTest(&argc, argv);
404 return RUN_ALL_TESTS();
405 }
406
407 // TODO: b/263986405 Add multi-thread testing
408
409 } // namespace android
410