blob: 623ac3749daaef18646899e9972dee055df709cd [file] [log] [blame]
Shunkai Yaoa4ab38c2022-10-14 01:07:47 +00001/*
2 * Copyright (C) 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#pragma once
18
19#include <memory>
20#include <string>
21#include <unordered_map>
22#include <vector>
23
24#include <aidl/android/hardware/audio/effect/IEffect.h>
25#include <aidl/android/hardware/audio/effect/IFactory.h>
26#include <aidl/android/media/audio/common/AudioChannelLayout.h>
27#include <aidl/android/media/audio/common/AudioDeviceType.h>
28#include <android/binder_auto_utils.h>
29#include <fmq/AidlMessageQueue.h>
30
31#include "AudioHalBinderServiceUtil.h"
32#include "EffectFactoryHelper.h"
33#include "TestUtils.h"
34
35using namespace android;
36using aidl::android::hardware::audio::effect::CommandId;
37using aidl::android::hardware::audio::effect::Descriptor;
38using aidl::android::hardware::audio::effect::EffectNullUuid;
39using aidl::android::hardware::audio::effect::EffectZeroUuid;
40using aidl::android::hardware::audio::effect::IEffect;
41using aidl::android::hardware::audio::effect::Parameter;
42using aidl::android::hardware::audio::effect::State;
43using aidl::android::hardware::common::fmq::SynchronizedReadWrite;
44using aidl::android::media::audio::common::AudioChannelLayout;
45using aidl::android::media::audio::common::AudioDeviceType;
46using aidl::android::media::audio::common::AudioFormatDescription;
47using aidl::android::media::audio::common::AudioFormatType;
48using aidl::android::media::audio::common::AudioUuid;
49using aidl::android::media::audio::common::PcmType;
50
51const AudioFormatDescription DefaultFormat = {
Shunkai Yao6afc8552022-10-26 22:47:20 +000052 .type = AudioFormatType::PCM, .pcm = PcmType::FLOAT_32_BIT, .encoding = ""};
Shunkai Yaoa4ab38c2022-10-14 01:07:47 +000053
54class EffectHelper {
55 public:
56 explicit EffectHelper(const std::string& name) : mFactoryHelper(EffectFactoryHelper(name)) {
57 mFactoryHelper.ConnectToFactoryService();
58 }
59
60 void OpenEffects(const AudioUuid& type = EffectNullUuid) {
61 auto open = [&](const std::shared_ptr<IEffect>& effect) {
Shunkai Yao6afc8552022-10-26 22:47:20 +000062 ASSERT_NE(effect, nullptr);
Shunkai Yaoa4ab38c2022-10-14 01:07:47 +000063 IEffect::OpenEffectReturn ret;
64 EXPECT_IS_OK(effect->open(mCommon, mSpecific, &ret));
65 EffectParam params;
66 params.statusMQ = std::make_unique<StatusMQ>(ret.statusMQ);
67 params.inputMQ = std::make_unique<DataMQ>(ret.inputDataMQ);
68 params.outputMQ = std::make_unique<DataMQ>(ret.outputDataMQ);
69 mEffectParams.push_back(std::move(params));
70 };
71 EXPECT_NO_FATAL_FAILURE(ForEachEffect(open, type));
72 }
73
74 void CloseEffects(const binder_status_t status = EX_NONE) {
75 auto close = [&](const std::shared_ptr<IEffect>& effect) {
Shunkai Yao6afc8552022-10-26 22:47:20 +000076 ASSERT_NE(effect, nullptr);
Shunkai Yaoa4ab38c2022-10-14 01:07:47 +000077 EXPECT_STATUS(status, effect->close());
78 };
79
80 EXPECT_NO_FATAL_FAILURE(ForEachEffect(close));
81 }
82
83 void CreateEffects(const int n = 1) {
84 for (int i = 0; i < n; i++) {
85 ASSERT_NO_FATAL_FAILURE(mFactoryHelper.QueryAndCreateAllEffects());
86 }
87 }
88
89 void CreateEffectsWithUUID(const AudioUuid& type = EffectNullUuid) {
90 ASSERT_NO_FATAL_FAILURE(mFactoryHelper.QueryAndCreateEffects(type));
91 }
92
93 void QueryEffects() { ASSERT_NO_FATAL_FAILURE(mFactoryHelper.QueryAndCreateAllEffects()); }
94
95 void DestroyEffects(const binder_status_t status = EX_NONE, const int remaining = 0) {
96 ASSERT_NO_FATAL_FAILURE(mFactoryHelper.DestroyEffects(status, remaining));
97 mEffectDescriptors.clear();
98 }
99
100 void GetEffectDescriptors() {
101 auto get = [&](const std::shared_ptr<IEffect>& effect) {
Shunkai Yao6afc8552022-10-26 22:47:20 +0000102 ASSERT_NE(effect, nullptr);
Shunkai Yaoa4ab38c2022-10-14 01:07:47 +0000103 Descriptor desc;
104 EXPECT_IS_OK(effect->getDescriptor(&desc));
105 mEffectDescriptors.push_back(std::move(desc));
106 };
107 EXPECT_NO_FATAL_FAILURE(ForEachEffect(get));
108 }
109
110 void CommandEffects(CommandId command) {
111 auto close = [&](const std::shared_ptr<IEffect>& effect) {
Shunkai Yao6afc8552022-10-26 22:47:20 +0000112 ASSERT_NE(effect, nullptr);
Shunkai Yaoa4ab38c2022-10-14 01:07:47 +0000113 EXPECT_IS_OK(effect->command(command));
114 };
115 EXPECT_NO_FATAL_FAILURE(ForEachEffect(close));
116 }
117
118 void CommandEffectsExpectStatus(CommandId command, const binder_status_t status) {
119 auto func = [&](const std::shared_ptr<IEffect>& effect) {
Shunkai Yao6afc8552022-10-26 22:47:20 +0000120 ASSERT_NE(effect, nullptr);
Shunkai Yaoa4ab38c2022-10-14 01:07:47 +0000121 EXPECT_STATUS(status, effect->command(command));
122 };
123 EXPECT_NO_FATAL_FAILURE(ForEachEffect(func));
124 }
125
126 void ExpectState(State expected) {
127 auto get = [&](const std::shared_ptr<IEffect>& effect) {
Shunkai Yao6afc8552022-10-26 22:47:20 +0000128 ASSERT_NE(effect, nullptr);
Shunkai Yaoa4ab38c2022-10-14 01:07:47 +0000129 State state = State::INIT;
130 EXPECT_IS_OK(effect->getState(&state));
131 EXPECT_EQ(expected, state);
132 };
133 EXPECT_NO_FATAL_FAILURE(ForEachEffect(get));
134 }
135
136 void SetParameter() {
137 auto func = [&](const std::shared_ptr<IEffect>& effect) {
Shunkai Yao6afc8552022-10-26 22:47:20 +0000138 ASSERT_NE(effect, nullptr);
Shunkai Yaoa4ab38c2022-10-14 01:07:47 +0000139 Parameter param;
140 param.set<Parameter::common>(mCommon);
141 EXPECT_IS_OK(effect->setParameter(param));
142 };
143 EXPECT_NO_FATAL_FAILURE(ForEachEffect(func));
144 }
145
146 void VerifyParameters() {
147 auto func = [&](const std::shared_ptr<IEffect>& effect) {
Shunkai Yao6afc8552022-10-26 22:47:20 +0000148 ASSERT_NE(effect, nullptr);
Shunkai Yaoa4ab38c2022-10-14 01:07:47 +0000149 Parameter paramCommonGet = Parameter(), paramCommonExpect = Parameter();
150 Parameter::Id id;
Shunkai Yao6afc8552022-10-26 22:47:20 +0000151 id.set<Parameter::Id::commonTag>(Parameter::common);
Shunkai Yaoa4ab38c2022-10-14 01:07:47 +0000152 paramCommonExpect.set<Parameter::common>(mCommon);
153 EXPECT_IS_OK(effect->getParameter(id, &paramCommonGet));
154 EXPECT_EQ(paramCommonExpect, paramCommonGet)
155 << paramCommonExpect.toString() << " vs " << paramCommonGet.toString();
156 };
157 EXPECT_NO_FATAL_FAILURE(ForEachEffect(func));
158 }
159
160 void QueryEffects(const std::optional<AudioUuid>& in_type,
161 const std::optional<AudioUuid>& in_instance,
Shunkai Yao6afc8552022-10-26 22:47:20 +0000162 const std::optional<AudioUuid>& in_proxy,
Shunkai Yaoa4ab38c2022-10-14 01:07:47 +0000163 std::vector<Descriptor::Identity>* _aidl_return) {
Shunkai Yao6afc8552022-10-26 22:47:20 +0000164 mFactoryHelper.QueryEffects(in_type, in_instance, in_proxy, _aidl_return);
Shunkai Yaoa4ab38c2022-10-14 01:07:47 +0000165 }
166
167 template <typename Functor>
168 void ForEachEffect(Functor functor, const std::optional<AudioUuid>& type = EffectNullUuid) {
169 auto effectMap = mFactoryHelper.GetEffectMap();
170 for (const auto& it : effectMap) {
171 SCOPED_TRACE(it.second.toString());
172 if (type != EffectNullUuid && it.second.type != type) continue;
173 functor(it.first);
174 }
175 }
176
177 template <typename Functor>
178 void ForEachDescriptor(Functor functor) {
179 for (size_t i = 0; i < mEffectDescriptors.size(); i++) {
180 SCOPED_TRACE(mEffectDescriptors[i].toString());
181 functor(i, mEffectDescriptors[i]);
182 }
183 }
184
Shunkai Yao6afc8552022-10-26 22:47:20 +0000185 static const size_t mWriteMQBytes = 0x400;
Shunkai Yaoa4ab38c2022-10-14 01:07:47 +0000186
187 enum class IO : char { INPUT = 0, OUTPUT = 1, INOUT = 2 };
188
189 void initParamCommonFormat(IO io = IO::INOUT,
190 const AudioFormatDescription& format = DefaultFormat) {
191 if (io == IO::INPUT || io == IO::INOUT) {
192 mCommon.input.base.format = format;
193 }
194 if (io == IO::OUTPUT || io == IO::INOUT) {
195 mCommon.output.base.format = format;
196 }
197 }
198
199 void initParamCommonSampleRate(IO io = IO::INOUT, const int& sampleRate = 48000) {
200 if (io == IO::INPUT || io == IO::INOUT) {
201 mCommon.input.base.sampleRate = sampleRate;
202 }
203 if (io == IO::OUTPUT || io == IO::INOUT) {
204 mCommon.output.base.sampleRate = sampleRate;
205 }
206 }
207
208 void initParamCommonFrameCount(IO io = IO::INOUT, const long& frameCount = 48000) {
209 if (io == IO::INPUT || io == IO::INOUT) {
210 mCommon.input.frameCount = frameCount;
211 }
212 if (io == IO::OUTPUT || io == IO::INOUT) {
213 mCommon.output.frameCount = frameCount;
214 }
215 }
Shunkai Yao6afc8552022-10-26 22:47:20 +0000216 void initParamCommon(int session = 0, int ioHandle = -1, int iSampleRate = 48000,
Shunkai Yaoa4ab38c2022-10-14 01:07:47 +0000217 int oSampleRate = 48000, long iFrameCount = 0x100,
218 long oFrameCount = 0x100) {
219 mCommon.session = session;
220 mCommon.ioHandle = ioHandle;
221
222 auto& input = mCommon.input;
223 auto& output = mCommon.output;
224 input.base.sampleRate = iSampleRate;
225 input.base.channelMask = mInputChannelLayout;
226 input.frameCount = iFrameCount;
Shunkai Yao6afc8552022-10-26 22:47:20 +0000227 input.base.format = DefaultFormat;
Shunkai Yaoa4ab38c2022-10-14 01:07:47 +0000228 output.base.sampleRate = oSampleRate;
229 output.base.channelMask = mOutputChannelLayout;
Shunkai Yao464775e2022-10-28 21:42:25 +0000230 output.base.format = DefaultFormat;
Shunkai Yaoa4ab38c2022-10-14 01:07:47 +0000231 output.frameCount = oFrameCount;
Shunkai Yao6afc8552022-10-26 22:47:20 +0000232 output.base.format = DefaultFormat;
Shunkai Yaoa4ab38c2022-10-14 01:07:47 +0000233 inputFrameSize = android::hardware::audio::common::getFrameSizeInBytes(
234 input.base.format, input.base.channelMask);
235 outputFrameSize = android::hardware::audio::common::getFrameSizeInBytes(
236 output.base.format, output.base.channelMask);
237 }
238
239 void setSpecific(Parameter::Specific& specific) { mSpecific = specific; }
240
241 // usually this function only call once.
Shunkai Yao6afc8552022-10-26 22:47:20 +0000242 void PrepareInputData(size_t bytes = mWriteMQBytes) {
243 size_t maxInputBytes = mWriteMQBytes;
Shunkai Yaoa4ab38c2022-10-14 01:07:47 +0000244 for (auto& it : mEffectParams) {
245 auto& mq = it.inputMQ;
246 EXPECT_NE(nullptr, mq);
247 EXPECT_TRUE(mq->isValid());
Shunkai Yao6afc8552022-10-26 22:47:20 +0000248 const size_t bytesToWrite = mq->availableToWrite() * sizeof(float);
Shunkai Yaoa4ab38c2022-10-14 01:07:47 +0000249 EXPECT_EQ(inputFrameSize * mCommon.input.frameCount, bytesToWrite);
250 EXPECT_NE(0UL, bytesToWrite);
Shunkai Yao6afc8552022-10-26 22:47:20 +0000251 EXPECT_TRUE(bytes <= bytesToWrite);
252 maxInputBytes = std::max(maxInputBytes, bytesToWrite);
Shunkai Yaoa4ab38c2022-10-14 01:07:47 +0000253 }
Shunkai Yao6afc8552022-10-26 22:47:20 +0000254 mInputBuffer.resize(maxInputBytes / sizeof(float));
Shunkai Yaoa4ab38c2022-10-14 01:07:47 +0000255 std::fill(mInputBuffer.begin(), mInputBuffer.end(), 0x5a);
256 }
257
Shunkai Yao6afc8552022-10-26 22:47:20 +0000258 void writeToFmq(size_t bytes = mWriteMQBytes) {
Shunkai Yaoa4ab38c2022-10-14 01:07:47 +0000259 for (auto& it : mEffectParams) {
260 auto& mq = it.inputMQ;
261 EXPECT_NE(nullptr, mq);
Shunkai Yao6afc8552022-10-26 22:47:20 +0000262 const size_t bytesToWrite = mq->availableToWrite() * sizeof(float);
Shunkai Yaoa4ab38c2022-10-14 01:07:47 +0000263 EXPECT_NE(0Ul, bytesToWrite);
Shunkai Yao6afc8552022-10-26 22:47:20 +0000264 EXPECT_TRUE(bytes <= bytesToWrite);
265 EXPECT_TRUE(mq->write(mInputBuffer.data(), bytes / sizeof(float)));
Shunkai Yaoa4ab38c2022-10-14 01:07:47 +0000266 }
267 }
268
Shunkai Yao6afc8552022-10-26 22:47:20 +0000269 void readFromFmq(size_t expectBytes = mWriteMQBytes) {
Shunkai Yaoa4ab38c2022-10-14 01:07:47 +0000270 for (auto& it : mEffectParams) {
271 IEffect::Status status{};
272 auto& statusMq = it.statusMQ;
273 EXPECT_NE(nullptr, statusMq);
274 EXPECT_TRUE(statusMq->readBlocking(&status, 1));
275 EXPECT_EQ(STATUS_OK, status.status);
Shunkai Yao6afc8552022-10-26 22:47:20 +0000276 EXPECT_EQ(expectBytes, (unsigned)status.fmqProduced * sizeof(float));
Shunkai Yaoa4ab38c2022-10-14 01:07:47 +0000277
278 auto& outputMq = it.outputMQ;
279 EXPECT_NE(nullptr, outputMq);
Shunkai Yao6afc8552022-10-26 22:47:20 +0000280 EXPECT_EQ(expectBytes, outputMq->availableToRead() * sizeof(float));
Shunkai Yaoa4ab38c2022-10-14 01:07:47 +0000281 }
282 }
283
284 void setInputChannelLayout(AudioChannelLayout input) { mInputChannelLayout = input; }
285 void setOutputChannelLayout(AudioChannelLayout output) { mOutputChannelLayout = output; }
286 const std::vector<Descriptor::Identity>& GetCompleteEffectIdList() const {
287 return mFactoryHelper.GetCompleteEffectIdList();
288 }
289 const std::vector<Descriptor>& getDescriptorVec() const { return mEffectDescriptors; }
290
291 private:
292 EffectFactoryHelper mFactoryHelper;
293
294 AudioChannelLayout mInputChannelLayout =
295 AudioChannelLayout::make<AudioChannelLayout::layoutMask>(
296 AudioChannelLayout::LAYOUT_STEREO);
297 AudioChannelLayout mOutputChannelLayout =
298 AudioChannelLayout::make<AudioChannelLayout::layoutMask>(
299 AudioChannelLayout::LAYOUT_STEREO);
300
301 Parameter::Common mCommon;
Shunkai Yao6afc8552022-10-26 22:47:20 +0000302 std::optional<Parameter::Specific> mSpecific = std::nullopt;
Shunkai Yaoa4ab38c2022-10-14 01:07:47 +0000303
304 size_t inputFrameSize, outputFrameSize;
Shunkai Yao6afc8552022-10-26 22:47:20 +0000305 std::vector<float> mInputBuffer; // reuse same buffer for all effects testing
Shunkai Yaoa4ab38c2022-10-14 01:07:47 +0000306
307 typedef ::android::AidlMessageQueue<
308 IEffect::Status, ::aidl::android::hardware::common::fmq::SynchronizedReadWrite>
309 StatusMQ;
310 typedef ::android::AidlMessageQueue<
Shunkai Yao6afc8552022-10-26 22:47:20 +0000311 float, ::aidl::android::hardware::common::fmq::SynchronizedReadWrite>
Shunkai Yaoa4ab38c2022-10-14 01:07:47 +0000312 DataMQ;
313
314 class EffectParam {
315 public:
316 std::unique_ptr<StatusMQ> statusMQ;
317 std::unique_ptr<DataMQ> inputMQ;
318 std::unique_ptr<DataMQ> outputMQ;
319 };
320 std::vector<EffectParam> mEffectParams;
321 std::vector<Descriptor> mEffectDescriptors;
322};