blob: 8668e85bcf9120074c36d474c9bda3b4a9a346f9 [file] [log] [blame]
Shunkai Yao5c718342023-02-23 23:49:51 +00001/*
2 * Copyright 2023 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 <cstddef>
19#include <cstdint>
20#include <memory>
21#include <utility>
22#define LOG_TAG "EffectProxyTest"
23
24#include <aidl/android/media/audio/common/AudioUuid.h>
25#include <aidl/Vintf.h>
26#include <android/binder_manager.h>
27#include <gtest/gtest.h>
28#include <utils/RefBase.h>
29
30#include "EffectProxy.h"
31
32/**
33 * This test suite is depending on audio effect AIDL service.
34 */
35namespace android {
36
37using ::aidl::android::hardware::audio::effect::CommandId;
38using ::aidl::android::hardware::audio::effect::Descriptor;
39using ::aidl::android::hardware::audio::effect::Flags;
40using ::aidl::android::hardware::audio::effect::IEffect;
41using ::aidl::android::hardware::audio::effect::IFactory;
42using ::aidl::android::hardware::audio::effect::Parameter;
43using ::aidl::android::hardware::audio::effect::State;
44using ::aidl::android::media::audio::common::AudioChannelLayout;
45using ::aidl::android::media::audio::common::AudioFormatDescription;
46using ::aidl::android::media::audio::common::AudioFormatType;
47using ::aidl::android::media::audio::common::AudioUuid;
48using ::aidl::android::media::audio::common::PcmType;
49using ::android::effect::EffectProxy;
50
51class EffectProxyTest : public testing::Test {
52 public:
53 void SetUp() override {
54 auto serviceName = android::getAidlHalInstanceNames(IFactory::descriptor);
55 // only unit test with the first one in case more than one EffectFactory service exist
56 ASSERT_NE(0ul, serviceName.size());
57 mFactory = IFactory::fromBinder(
58 ndk::SpAIBinder(AServiceManager_waitForService(serviceName[0].c_str())));
59 ASSERT_NE(nullptr, mFactory);
60 mFactory->queryEffects(std::nullopt, std::nullopt, std::nullopt, &mDescs);
61 for (const auto& desc : mDescs) {
62 if (desc.common.id.proxy.has_value()) {
Shunkai Yao79f98742023-05-03 23:54:43 +000063 mProxyDescs[desc.common.id.proxy.value()].emplace_back(desc);
Shunkai Yao5c718342023-02-23 23:49:51 +000064 }
65 }
66 }
67
68 void TearDown() override {}
69
70 const AudioFormatDescription kDefaultFormatDescription = {
71 .type = AudioFormatType::PCM, .pcm = PcmType::FLOAT_32_BIT, .encoding = ""};
72
73 Parameter::Common createParamCommon(
74 int session = 0, int ioHandle = -1, int iSampleRate = 48000, int oSampleRate = 48000,
75 long iFrameCount = 0x100, long oFrameCount = 0x100,
76 AudioChannelLayout inputChannelLayout =
77 AudioChannelLayout::make<AudioChannelLayout::layoutMask>(
78 AudioChannelLayout::LAYOUT_STEREO),
79 AudioChannelLayout outputChannelLayout =
80 AudioChannelLayout::make<AudioChannelLayout::layoutMask>(
81 AudioChannelLayout::LAYOUT_STEREO)) {
82 Parameter::Common common;
83 common.session = session;
84 common.ioHandle = ioHandle;
85
86 auto& input = common.input;
87 auto& output = common.output;
88 input.base.sampleRate = iSampleRate;
89 input.base.channelMask = inputChannelLayout;
90 input.base.format = kDefaultFormatDescription;
91 input.frameCount = iFrameCount;
92 output.base.sampleRate = oSampleRate;
93 output.base.channelMask = outputChannelLayout;
94 output.base.format = kDefaultFormatDescription;
95 output.frameCount = oFrameCount;
96 return common;
97 }
98
Shunkai Yao5c718342023-02-23 23:49:51 +000099 enum TupleIndex { HANDLE, DESCRIPTOR };
100 using EffectProxyTuple = std::tuple<std::shared_ptr<EffectProxy>, std::vector<Descriptor>>;
101
102 std::map<AudioUuid, EffectProxyTuple> createAllProxies() {
103 std::map<AudioUuid, EffectProxyTuple> proxyMap;
104 for (const auto& itor : mProxyDescs) {
Shunkai Yao79f98742023-05-03 23:54:43 +0000105 const auto& uuid = itor.first;
Shunkai Yao5c718342023-02-23 23:49:51 +0000106 if (proxyMap.end() == proxyMap.find(uuid)) {
107 std::get<TupleIndex::HANDLE>(proxyMap[uuid]) =
Shunkai Yao79f98742023-05-03 23:54:43 +0000108 ndk::SharedRefBase::make<EffectProxy>(itor.first, itor.second, mFactory);
Shunkai Yao5c718342023-02-23 23:49:51 +0000109 }
110 }
111 return proxyMap;
112 }
113
Shunkai Yao5c718342023-02-23 23:49:51 +0000114 std::shared_ptr<IFactory> mFactory;
115 std::vector<Descriptor> mDescs;
Shunkai Yao79f98742023-05-03 23:54:43 +0000116 std::map<const AudioUuid, std::vector<Descriptor>> mProxyDescs;
Shunkai Yao5c718342023-02-23 23:49:51 +0000117};
118
119TEST_F(EffectProxyTest, createProxy) {
120 auto proxyMap = createAllProxies();
121 // if there are some descriptor defined with proxy, then proxyMap can not be empty
122 EXPECT_EQ(mProxyDescs.size() == 0, proxyMap.size() == 0);
123}
124
125TEST_F(EffectProxyTest, addSubEffectsCreateAndDestroy) {
126 auto proxyMap = createAllProxies();
Shunkai Yao5c718342023-02-23 23:49:51 +0000127
128 for (const auto& itor : proxyMap) {
129 auto& proxy = std::get<TupleIndex::HANDLE>(itor.second);
Shunkai Yao5c718342023-02-23 23:49:51 +0000130 EXPECT_TRUE(proxy->destroy().isOk());
131 }
132}
133
134TEST_F(EffectProxyTest, addSubEffectsCreateOpenCloseDestroy) {
135 auto proxyMap = createAllProxies();
Shunkai Yao5c718342023-02-23 23:49:51 +0000136
137 Parameter::Common common = createParamCommon();
138 IEffect::OpenEffectReturn ret;
139 for (const auto& itor : proxyMap) {
140 auto& proxy = std::get<TupleIndex::HANDLE>(itor.second);
Shunkai Yao5c718342023-02-23 23:49:51 +0000141 EXPECT_TRUE(proxy->open(common, std::nullopt, &ret).isOk());
142 EXPECT_TRUE(proxy->close().isOk());
143 EXPECT_TRUE(proxy->destroy().isOk());
144 }
145}
146
147// Add sub-effects, set active sub-effect with different checkers
148TEST_F(EffectProxyTest, setOffloadParam) {
149 auto proxyMap = createAllProxies();
Shunkai Yao5c718342023-02-23 23:49:51 +0000150
151 // Any flag exist should be able to set successfully
Shunkai Yao5c718342023-02-23 23:49:51 +0000152 Parameter::Common common = createParamCommon();
153 IEffect::OpenEffectReturn ret;
154 for (const auto& itor : proxyMap) {
155 auto& proxy = std::get<TupleIndex::HANDLE>(itor.second);
Shunkai Yao5c718342023-02-23 23:49:51 +0000156 EXPECT_TRUE(proxy->open(common, std::nullopt, &ret).isOk());
157 effect_offload_param_t offloadParam{false, 0};
Shunkai Yao79f98742023-05-03 23:54:43 +0000158 EXPECT_TRUE(proxy->setOffloadParam(&offloadParam).isOk());
Shunkai Yao5c718342023-02-23 23:49:51 +0000159 offloadParam.isOffload = true;
Shunkai Yao79f98742023-05-03 23:54:43 +0000160 EXPECT_TRUE(proxy->setOffloadParam(&offloadParam).isOk());
Shunkai Yao5c718342023-02-23 23:49:51 +0000161 EXPECT_TRUE(proxy->close().isOk());
162 EXPECT_TRUE(proxy->destroy().isOk());
163 }
164}
165TEST_F(EffectProxyTest, destroyWithoutCreate) {
166 auto proxyMap = createAllProxies();
Shunkai Yao5c718342023-02-23 23:49:51 +0000167
168 for (const auto& itor : proxyMap) {
169 auto& proxy = std::get<TupleIndex::HANDLE>(itor.second);
170 EXPECT_TRUE(proxy->destroy().isOk());
171 }
172}
173
174TEST_F(EffectProxyTest, closeWithoutOpen) {
175 auto proxyMap = createAllProxies();
Shunkai Yao5c718342023-02-23 23:49:51 +0000176
177 for (const auto& itor : proxyMap) {
178 auto& proxy = std::get<TupleIndex::HANDLE>(itor.second);
Shunkai Yao5c718342023-02-23 23:49:51 +0000179
180 EXPECT_TRUE(proxy->close().isOk());
181 EXPECT_TRUE(proxy->destroy().isOk());
182 }
183}
184
185// Add sub-effects, set active sub-effect, create, open, and send command, expect success handling
186TEST_F(EffectProxyTest, normalSequency) {
187 auto proxyMap = createAllProxies();
Shunkai Yao5c718342023-02-23 23:49:51 +0000188
189 Parameter::Common common = createParamCommon();
190 IEffect::OpenEffectReturn ret;
191 Parameter::VolumeStereo volumeStereo({.left = .1f, .right = -0.8f});
192 Parameter param = Parameter::make<Parameter::volumeStereo>(volumeStereo);
193 Parameter::Id id = Parameter::Id::make<Parameter::Id::commonTag>(Parameter::volumeStereo);
194 State state;
195 for (const auto& itor : proxyMap) {
196 Parameter expect;
197 auto& proxy = std::get<TupleIndex::HANDLE>(itor.second);
198 effect_offload_param_t offloadParam{true, 0};
Shunkai Yao79f98742023-05-03 23:54:43 +0000199 EXPECT_TRUE(proxy->setOffloadParam(&offloadParam).isOk());
Shunkai Yao5c718342023-02-23 23:49:51 +0000200
Shunkai Yao5c718342023-02-23 23:49:51 +0000201 EXPECT_TRUE(proxy->open(common, std::nullopt, &ret).isOk());
202
203 EXPECT_TRUE(proxy->setParameter(param).isOk());
204 EXPECT_TRUE(proxy->getParameter(id, &expect).isOk());
Shunkai Yao79f98742023-05-03 23:54:43 +0000205 EXPECT_EQ(expect, param) << " EXPECTED: " << expect.toString()
206 << "\nACTUAL: " << param.toString();
Shunkai Yao5c718342023-02-23 23:49:51 +0000207
208 EXPECT_TRUE(proxy->command(CommandId::START).isOk());
209 EXPECT_TRUE(proxy->getState(&state).isOk());
210 EXPECT_EQ(State::PROCESSING, state);
211
212 EXPECT_TRUE(proxy->command(CommandId::STOP).isOk());
213 EXPECT_TRUE(proxy->getState(&state).isOk());
214 EXPECT_EQ(State::IDLE, state);
215
216 EXPECT_TRUE(proxy->close().isOk());
217 EXPECT_TRUE(proxy->destroy().isOk());
218 }
219}
220
221// setParameter, change active sub-effect, verify with getParameter
222TEST_F(EffectProxyTest, changeActiveSubAndVerifyParameter) {
223 auto proxyMap = createAllProxies();
Shunkai Yao5c718342023-02-23 23:49:51 +0000224
225 Parameter::Common common = createParamCommon();
226 IEffect::OpenEffectReturn ret;
227 Parameter::VolumeStereo volumeStereo({.left = .5f, .right = .8f});
228 Parameter param = Parameter::make<Parameter::volumeStereo>(volumeStereo);
229 Parameter::Id id = Parameter::Id::make<Parameter::Id::commonTag>(Parameter::volumeStereo);
230 for (const auto& itor : proxyMap) {
231 Parameter expect;
232 auto& proxy = std::get<TupleIndex::HANDLE>(itor.second);
Shunkai Yao5c718342023-02-23 23:49:51 +0000233 EXPECT_TRUE(proxy->open(common, std::nullopt, &ret).isOk());
234 EXPECT_TRUE(proxy->setParameter(param).isOk());
235 EXPECT_TRUE(proxy->getParameter(id, &expect).isOk());
236 EXPECT_EQ(expect, param);
237
238 effect_offload_param_t offloadParam{false, 0};
Shunkai Yao79f98742023-05-03 23:54:43 +0000239 EXPECT_TRUE(proxy->setOffloadParam(&offloadParam).isOk());
Shunkai Yao5c718342023-02-23 23:49:51 +0000240 EXPECT_TRUE(proxy->getParameter(id, &expect).isOk());
241 EXPECT_EQ(expect, param);
242
243 offloadParam.isOffload = true;
Shunkai Yao79f98742023-05-03 23:54:43 +0000244 EXPECT_TRUE(proxy->setOffloadParam(&offloadParam).isOk());
Shunkai Yao5c718342023-02-23 23:49:51 +0000245 EXPECT_TRUE(proxy->getParameter(id, &expect).isOk());
246 EXPECT_EQ(expect, param);
247
248 EXPECT_TRUE(proxy->close().isOk());
249 EXPECT_TRUE(proxy->destroy().isOk());
250 }
251}
252
253// send command, change active sub-effect, then verify the state with getState
254TEST_F(EffectProxyTest, changeActiveSubAndVerifyState) {
255 auto proxyMap = createAllProxies();
Shunkai Yao5c718342023-02-23 23:49:51 +0000256
257 Parameter::Common common = createParamCommon();
258 IEffect::OpenEffectReturn ret;
259 State state;
260 for (const auto& itor : proxyMap) {
261 Parameter expect;
262 auto& proxy = std::get<TupleIndex::HANDLE>(itor.second);
Shunkai Yao5c718342023-02-23 23:49:51 +0000263 EXPECT_TRUE(proxy->getState(&state).isOk());
264 EXPECT_EQ(State::INIT, state);
265 EXPECT_TRUE(proxy->open(common, std::nullopt, &ret).isOk());
266 EXPECT_TRUE(proxy->getState(&state).isOk());
267 EXPECT_EQ(State::IDLE, state);
268 EXPECT_TRUE(proxy->command(CommandId::START).isOk());
269 EXPECT_TRUE(proxy->getState(&state).isOk());
270 EXPECT_EQ(State::PROCESSING, state);
271
272 effect_offload_param_t offloadParam{false, 0};
Shunkai Yao79f98742023-05-03 23:54:43 +0000273 EXPECT_TRUE(proxy->setOffloadParam(&offloadParam).isOk());
Shunkai Yao5c718342023-02-23 23:49:51 +0000274 EXPECT_TRUE(proxy->getState(&state).isOk());
275 EXPECT_EQ(State::PROCESSING, state);
276
277 offloadParam.isOffload = true;
Shunkai Yao79f98742023-05-03 23:54:43 +0000278 EXPECT_TRUE(proxy->setOffloadParam(&offloadParam).isOk());
Shunkai Yao5c718342023-02-23 23:49:51 +0000279 EXPECT_TRUE(proxy->getState(&state).isOk());
280 EXPECT_EQ(State::PROCESSING, state);
281
282 EXPECT_TRUE(proxy->command(CommandId::STOP).isOk());
283 EXPECT_TRUE(proxy->getState(&state).isOk());
284 EXPECT_EQ(State::IDLE, state);
285
286 EXPECT_TRUE(proxy->close().isOk());
287 EXPECT_TRUE(proxy->getState(&state).isOk());
288 EXPECT_EQ(State::INIT, state);
289 EXPECT_TRUE(proxy->destroy().isOk());
290 }
291}
292
293} // namespace android