blob: 28a72879ea76086acd500aaf00238a1a6c380cd5 [file] [log] [blame]
Shunkai Yao05b190a2022-12-22 00:21:31 +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#define LOG_TAG "AHAL_VisualizerLibEffects"
18
19#include <android-base/logging.h>
20#include "Visualizer.h"
21
22using aidl::android::hardware::audio::effect::Descriptor;
23using aidl::android::hardware::audio::effect::IEffect;
24using aidl::android::hardware::audio::effect::VisualizerImpl;
25using aidl::android::hardware::audio::effect::kVisualizerImplUUID;
26using aidl::android::hardware::audio::effect::State;
27using aidl::android::media::audio::common::AudioUuid;
28
29extern "C" binder_exception_t createEffect(const AudioUuid* in_impl_uuid,
30 std::shared_ptr<IEffect>* instanceSpp) {
31 if (!in_impl_uuid || *in_impl_uuid != kVisualizerImplUUID) {
32 LOG(ERROR) << __func__ << "uuid not supported";
33 return EX_ILLEGAL_ARGUMENT;
34 }
35 if (instanceSpp) {
36 *instanceSpp = ndk::SharedRefBase::make<VisualizerImpl>();
37 LOG(DEBUG) << __func__ << " instance " << instanceSpp->get() << " created";
38 return EX_NONE;
39 } else {
40 LOG(ERROR) << __func__ << " invalid input parameter!";
41 return EX_ILLEGAL_ARGUMENT;
42 }
43}
44
45extern "C" binder_exception_t queryEffect(const AudioUuid* in_impl_uuid, Descriptor* _aidl_return) {
46 if (!in_impl_uuid || *in_impl_uuid != kVisualizerImplUUID) {
47 LOG(ERROR) << __func__ << "uuid not supported";
48 return EX_ILLEGAL_ARGUMENT;
49 }
50 *_aidl_return = VisualizerImpl::kDescriptor;
51 return EX_NONE;
52}
53
54namespace aidl::android::hardware::audio::effect {
55
56const std::string VisualizerImpl::kEffectName = "Visualizer";
57const Visualizer::Capability VisualizerImpl::kCapability = {
58 .maxLatencyMs = VisualizerContext::kMaxLatencyMs,
59 .captureSampleRange = {.min = 0, .max = VisualizerContext::kMaxCaptureBufSize}};
60const Descriptor VisualizerImpl::kDescriptor = {
61 .common = {.id = {.type = kVisualizerTypeUUID,
62 .uuid = kVisualizerImplUUID,
63 .proxy = std::nullopt},
64 .flags = {.type = Flags::Type::INSERT,
65 .insert = Flags::Insert::LAST,
66 .volume = Flags::Volume::CTRL},
67 .name = VisualizerImpl::kEffectName,
68 .implementor = "The Android Open Source Project"},
69 .capability = Capability::make<Capability::visualizer>(VisualizerImpl::kCapability)};
70
71ndk::ScopedAStatus VisualizerImpl::getDescriptor(Descriptor* _aidl_return) {
72 RETURN_IF(!_aidl_return, EX_ILLEGAL_ARGUMENT, "Parameter:nullptr");
73 LOG(DEBUG) << __func__ << kDescriptor.toString();
74 *_aidl_return = kDescriptor;
75 return ndk::ScopedAStatus::ok();
76}
77
78ndk::ScopedAStatus VisualizerImpl::commandImpl(CommandId command) {
79 RETURN_IF(!mContext, EX_NULL_POINTER, "nullContext");
80 switch (command) {
81 case CommandId::START:
82 mContext->enable();
83 break;
84 case CommandId::STOP:
85 mContext->disable();
86 break;
87 case CommandId::RESET:
88 mContext->disable();
89 mContext->resetBuffer();
90 break;
91 default:
92 LOG(ERROR) << __func__ << " commandId " << toString(command) << " not supported";
93 return ndk::ScopedAStatus::fromExceptionCodeWithMessage(EX_ILLEGAL_ARGUMENT,
94 "commandIdNotSupported");
95 }
96 return ndk::ScopedAStatus::ok();
97}
98
99ndk::ScopedAStatus VisualizerImpl::setOnlyParameter(
100 const Visualizer::SetOnlyParameters& param) {
101 auto tag = param.getTag();
102 switch (tag) {
103 case Visualizer::SetOnlyParameters::latencyMs: {
Shunkai Yaoc045a032022-12-27 21:33:17 +0000104 RETURN_IF(mContext->setDownstreamLatency(
105 param.get<Visualizer::SetOnlyParameters::latencyMs>()) !=
106 RetCode::SUCCESS,
107 EX_ILLEGAL_ARGUMENT, "setLatencyFailed");
Shunkai Yao05b190a2022-12-22 00:21:31 +0000108 break;
109 }
110 default: {
111 LOG(ERROR) << __func__ << " unsupported tag: " << toString(tag);
112 return ndk::ScopedAStatus::fromExceptionCodeWithMessage(
113 EX_ILLEGAL_ARGUMENT, "setOnlyParameterTagNotSupported");
114 }
115 }
116 return ndk::ScopedAStatus::ok();
117}
118
119ndk::ScopedAStatus VisualizerImpl::setParameterSpecific(const Parameter::Specific& specific) {
120 RETURN_IF(Parameter::Specific::visualizer != specific.getTag(), EX_ILLEGAL_ARGUMENT,
121 "EffectNotSupported");
122 RETURN_IF(!mContext, EX_NULL_POINTER, "nullContext");
123
124 auto& param = specific.get<Parameter::Specific::visualizer>();
125 const auto tag = param.getTag();
126 switch (tag) {
127 case Visualizer::captureSamples: {
128 RETURN_IF(mContext->setCaptureSamples(param.get<Visualizer::captureSamples>()) !=
129 RetCode::SUCCESS,
130 EX_ILLEGAL_ARGUMENT, "setCaptureSizeFailed");
131 return ndk::ScopedAStatus::ok();
132 }
133 case Visualizer::scalingMode: {
134 RETURN_IF(mContext->setScalingMode(param.get<Visualizer::scalingMode>()) !=
135 RetCode::SUCCESS,
136 EX_ILLEGAL_ARGUMENT, "setScalingModeFailed");
137 return ndk::ScopedAStatus::ok();
138 }
139 case Visualizer::measurementMode: {
140 RETURN_IF(mContext->setMeasurementMode(param.get<Visualizer::measurementMode>()) !=
141 RetCode::SUCCESS,
142 EX_ILLEGAL_ARGUMENT, "setMeasurementModeFailed");
143 return ndk::ScopedAStatus::ok();
144 }
145 case Visualizer::setOnlyParameters: {
146 return setOnlyParameter(param.get<Visualizer::setOnlyParameters>());
147 }
148 default: {
149 LOG(ERROR) << __func__ << " unsupported tag: " << toString(tag);
150 return ndk::ScopedAStatus::fromExceptionCodeWithMessage(
151 EX_ILLEGAL_ARGUMENT, "VisualizerTagNotSupported");
152 }
153 }
154}
155
156ndk::ScopedAStatus VisualizerImpl::getOnlyParameter(const Visualizer::GetOnlyParameters::Tag tag,
157 Parameter::Specific* specific) {
158 Visualizer visualizer;
159 Visualizer::GetOnlyParameters param;
160 switch (tag) {
161 case Visualizer::GetOnlyParameters::measurement: {
162 param.set<Visualizer::GetOnlyParameters::measurement>(mContext->getMeasure());
163 break;
164 }
165 case Visualizer::GetOnlyParameters::captureSampleBuffer: {
166 param.set<Visualizer::GetOnlyParameters::captureSampleBuffer>(mContext->capture());
167 break;
168 }
169 default: {
170 LOG(ERROR) << __func__ << " unsupported tag: " << toString(tag);
171 return ndk::ScopedAStatus::fromExceptionCodeWithMessage(
172 EX_ILLEGAL_ARGUMENT, "setOnlyParameterTagNotSupported");
173 }
174 }
175 visualizer.set<Visualizer::getOnlyParameters>(param);
176 specific->set<Parameter::Specific::visualizer>(visualizer);
177 return ndk::ScopedAStatus::ok();
178}
179
180ndk::ScopedAStatus VisualizerImpl::getParameterSpecific(const Parameter::Id& id,
181 Parameter::Specific* specific) {
182 RETURN_IF(!specific, EX_NULL_POINTER, "nullPtr");
183 auto tag = id.getTag();
184 RETURN_IF(Parameter::Id::visualizerTag != tag, EX_ILLEGAL_ARGUMENT, "wrongIdTag");
185 auto specificId = id.get<Parameter::Id::visualizerTag>();
186 auto specificTag = specificId.getTag();
187 switch (specificTag) {
188 case Visualizer::Id::commonTag: {
189 return getParameterVisualizer(specificId.get<Visualizer::Id::commonTag>(), specific);
190 }
191 case Visualizer::Id::getOnlyParamTag: {
192 return getOnlyParameter(specificId.get<Visualizer::Id::getOnlyParamTag>(), specific);
193 }
194 default: {
195 LOG(ERROR) << __func__ << " unsupported tag: " << toString(specificTag);
196 return ndk::ScopedAStatus::fromExceptionCodeWithMessage(EX_ILLEGAL_ARGUMENT,
197 "VisualizerTagNotSupported");
198 }
199 }
200 return ndk::ScopedAStatus::ok();
201}
202
203ndk::ScopedAStatus VisualizerImpl::getParameterVisualizer(const Visualizer::Tag& tag,
204 Parameter::Specific* specific) {
205 RETURN_IF(!mContext, EX_NULL_POINTER, "nullContext");
206
207 Visualizer param;
208 switch (tag) {
209 case Visualizer::captureSamples: {
210 param.set<Visualizer::captureSamples>(mContext->getCaptureSamples());
211 break;
212 }
213 case Visualizer::scalingMode: {
214 param.set<Visualizer::scalingMode>(mContext->getScalingMode());
215 break;
216 }
217 case Visualizer::measurementMode: {
218 param.set<Visualizer::measurementMode>(mContext->getMeasurementMode());
219 break;
220 }
221 default: {
222 LOG(ERROR) << __func__ << " unsupported tag: " << toString(tag);
223 return ndk::ScopedAStatus::fromExceptionCodeWithMessage(
224 EX_ILLEGAL_ARGUMENT, "VisualizerTagNotSupported");
225 }
226 }
227
228 specific->set<Parameter::Specific::visualizer>(param);
229 return ndk::ScopedAStatus::ok();
230}
231
232std::shared_ptr<EffectContext> VisualizerImpl::createContext(const Parameter::Common& common) {
233 if (mContext) {
234 LOG(DEBUG) << __func__ << " context already exist";
235 return mContext;
236 }
237
238 mContext = std::make_shared<VisualizerContext>(1 /* statusFmqDepth */, common);
239 mContext->initParams(common);
240 return mContext;
241}
242
243RetCode VisualizerImpl::releaseContext() {
244 if (mContext) {
245 mContext->disable();
246 mContext->resetBuffer();
247 }
248 return RetCode::SUCCESS;
249}
250
251// Processing method running in EffectWorker thread.
252IEffect::Status VisualizerImpl::effectProcessImpl(float* in, float* out, int samples) {
253 IEffect::Status status = {EX_NULL_POINTER, 0, 0};
254 RETURN_VALUE_IF(!mContext, status, "nullContext");
255 return mContext->process(in, out, samples);
256}
257
258} // namespace aidl::android::hardware::audio::effect