• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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*>(&parameterSet->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*>(&parameterSet->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