blob: e21aa019002cccec53d7bd6ec83b517ca58b192f [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: {
104 mContext->setDownstreamLatency(param.get<Visualizer::SetOnlyParameters::latencyMs>());
105 break;
106 }
107 default: {
108 LOG(ERROR) << __func__ << " unsupported tag: " << toString(tag);
109 return ndk::ScopedAStatus::fromExceptionCodeWithMessage(
110 EX_ILLEGAL_ARGUMENT, "setOnlyParameterTagNotSupported");
111 }
112 }
113 return ndk::ScopedAStatus::ok();
114}
115
116ndk::ScopedAStatus VisualizerImpl::setParameterSpecific(const Parameter::Specific& specific) {
117 RETURN_IF(Parameter::Specific::visualizer != specific.getTag(), EX_ILLEGAL_ARGUMENT,
118 "EffectNotSupported");
119 RETURN_IF(!mContext, EX_NULL_POINTER, "nullContext");
120
121 auto& param = specific.get<Parameter::Specific::visualizer>();
122 const auto tag = param.getTag();
123 switch (tag) {
124 case Visualizer::captureSamples: {
125 RETURN_IF(mContext->setCaptureSamples(param.get<Visualizer::captureSamples>()) !=
126 RetCode::SUCCESS,
127 EX_ILLEGAL_ARGUMENT, "setCaptureSizeFailed");
128 return ndk::ScopedAStatus::ok();
129 }
130 case Visualizer::scalingMode: {
131 RETURN_IF(mContext->setScalingMode(param.get<Visualizer::scalingMode>()) !=
132 RetCode::SUCCESS,
133 EX_ILLEGAL_ARGUMENT, "setScalingModeFailed");
134 return ndk::ScopedAStatus::ok();
135 }
136 case Visualizer::measurementMode: {
137 RETURN_IF(mContext->setMeasurementMode(param.get<Visualizer::measurementMode>()) !=
138 RetCode::SUCCESS,
139 EX_ILLEGAL_ARGUMENT, "setMeasurementModeFailed");
140 return ndk::ScopedAStatus::ok();
141 }
142 case Visualizer::setOnlyParameters: {
143 return setOnlyParameter(param.get<Visualizer::setOnlyParameters>());
144 }
145 default: {
146 LOG(ERROR) << __func__ << " unsupported tag: " << toString(tag);
147 return ndk::ScopedAStatus::fromExceptionCodeWithMessage(
148 EX_ILLEGAL_ARGUMENT, "VisualizerTagNotSupported");
149 }
150 }
151}
152
153ndk::ScopedAStatus VisualizerImpl::getOnlyParameter(const Visualizer::GetOnlyParameters::Tag tag,
154 Parameter::Specific* specific) {
155 Visualizer visualizer;
156 Visualizer::GetOnlyParameters param;
157 switch (tag) {
158 case Visualizer::GetOnlyParameters::measurement: {
159 param.set<Visualizer::GetOnlyParameters::measurement>(mContext->getMeasure());
160 break;
161 }
162 case Visualizer::GetOnlyParameters::captureSampleBuffer: {
163 param.set<Visualizer::GetOnlyParameters::captureSampleBuffer>(mContext->capture());
164 break;
165 }
166 default: {
167 LOG(ERROR) << __func__ << " unsupported tag: " << toString(tag);
168 return ndk::ScopedAStatus::fromExceptionCodeWithMessage(
169 EX_ILLEGAL_ARGUMENT, "setOnlyParameterTagNotSupported");
170 }
171 }
172 visualizer.set<Visualizer::getOnlyParameters>(param);
173 specific->set<Parameter::Specific::visualizer>(visualizer);
174 return ndk::ScopedAStatus::ok();
175}
176
177ndk::ScopedAStatus VisualizerImpl::getParameterSpecific(const Parameter::Id& id,
178 Parameter::Specific* specific) {
179 RETURN_IF(!specific, EX_NULL_POINTER, "nullPtr");
180 auto tag = id.getTag();
181 RETURN_IF(Parameter::Id::visualizerTag != tag, EX_ILLEGAL_ARGUMENT, "wrongIdTag");
182 auto specificId = id.get<Parameter::Id::visualizerTag>();
183 auto specificTag = specificId.getTag();
184 switch (specificTag) {
185 case Visualizer::Id::commonTag: {
186 return getParameterVisualizer(specificId.get<Visualizer::Id::commonTag>(), specific);
187 }
188 case Visualizer::Id::getOnlyParamTag: {
189 return getOnlyParameter(specificId.get<Visualizer::Id::getOnlyParamTag>(), specific);
190 }
191 default: {
192 LOG(ERROR) << __func__ << " unsupported tag: " << toString(specificTag);
193 return ndk::ScopedAStatus::fromExceptionCodeWithMessage(EX_ILLEGAL_ARGUMENT,
194 "VisualizerTagNotSupported");
195 }
196 }
197 return ndk::ScopedAStatus::ok();
198}
199
200ndk::ScopedAStatus VisualizerImpl::getParameterVisualizer(const Visualizer::Tag& tag,
201 Parameter::Specific* specific) {
202 RETURN_IF(!mContext, EX_NULL_POINTER, "nullContext");
203
204 Visualizer param;
205 switch (tag) {
206 case Visualizer::captureSamples: {
207 param.set<Visualizer::captureSamples>(mContext->getCaptureSamples());
208 break;
209 }
210 case Visualizer::scalingMode: {
211 param.set<Visualizer::scalingMode>(mContext->getScalingMode());
212 break;
213 }
214 case Visualizer::measurementMode: {
215 param.set<Visualizer::measurementMode>(mContext->getMeasurementMode());
216 break;
217 }
218 default: {
219 LOG(ERROR) << __func__ << " unsupported tag: " << toString(tag);
220 return ndk::ScopedAStatus::fromExceptionCodeWithMessage(
221 EX_ILLEGAL_ARGUMENT, "VisualizerTagNotSupported");
222 }
223 }
224
225 specific->set<Parameter::Specific::visualizer>(param);
226 return ndk::ScopedAStatus::ok();
227}
228
229std::shared_ptr<EffectContext> VisualizerImpl::createContext(const Parameter::Common& common) {
230 if (mContext) {
231 LOG(DEBUG) << __func__ << " context already exist";
232 return mContext;
233 }
234
235 mContext = std::make_shared<VisualizerContext>(1 /* statusFmqDepth */, common);
236 mContext->initParams(common);
237 return mContext;
238}
239
240RetCode VisualizerImpl::releaseContext() {
241 if (mContext) {
242 mContext->disable();
243 mContext->resetBuffer();
244 }
245 return RetCode::SUCCESS;
246}
247
248// Processing method running in EffectWorker thread.
249IEffect::Status VisualizerImpl::effectProcessImpl(float* in, float* out, int samples) {
250 IEffect::Status status = {EX_NULL_POINTER, 0, 0};
251 RETURN_VALUE_IF(!mContext, status, "nullContext");
252 return mContext->process(in, out, samples);
253}
254
255} // namespace aidl::android::hardware::audio::effect