blob: 40b46e064251350324556196279f7343fdd1772d [file] [log] [blame]
Shunkai Yaobd862b82022-12-20 00:11:41 +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#include <algorithm>
18#include <cstddef>
19#include <memory>
20#define LOG_TAG "AHAL_AcousticEchoCancelerSw"
21#include <Utils.h>
22#include <unordered_set>
23
24#include <android-base/logging.h>
25#include <fmq/AidlMessageQueue.h>
26
27#include "AcousticEchoCancelerSw.h"
28
29using aidl::android::hardware::audio::effect::AcousticEchoCancelerSw;
30using aidl::android::hardware::audio::effect::Descriptor;
31using aidl::android::hardware::audio::effect::IEffect;
32using aidl::android::hardware::audio::effect::kAcousticEchoCancelerSwImplUUID;
33using aidl::android::media::audio::common::AudioUuid;
34
35extern "C" binder_exception_t createEffect(const AudioUuid* in_impl_uuid,
36 std::shared_ptr<IEffect>* instanceSpp) {
37 if (!in_impl_uuid || *in_impl_uuid != kAcousticEchoCancelerSwImplUUID) {
38 LOG(ERROR) << __func__ << "uuid not supported";
39 return EX_ILLEGAL_ARGUMENT;
40 }
41 if (instanceSpp) {
42 *instanceSpp = ndk::SharedRefBase::make<AcousticEchoCancelerSw>();
43 LOG(DEBUG) << __func__ << " instance " << instanceSpp->get() << " created";
44 return EX_NONE;
45 } else {
46 LOG(ERROR) << __func__ << " invalid input parameter!";
47 return EX_ILLEGAL_ARGUMENT;
48 }
49}
50
51extern "C" binder_exception_t queryEffect(const AudioUuid* in_impl_uuid, Descriptor* _aidl_return) {
52 if (!in_impl_uuid || *in_impl_uuid != kAcousticEchoCancelerSwImplUUID) {
53 LOG(ERROR) << __func__ << "uuid not supported";
54 return EX_ILLEGAL_ARGUMENT;
55 }
56 *_aidl_return = AcousticEchoCancelerSw::kDescriptor;
Shunkai Yaobd862b82022-12-20 00:11:41 +000057 return EX_NONE;
58}
59
60namespace aidl::android::hardware::audio::effect {
61
62const std::string AcousticEchoCancelerSw::kEffectName = "AcousticEchoCancelerSw";
63const AcousticEchoCanceler::Capability AcousticEchoCancelerSw::kCapability = {
64 .maxEchoDelayUs = 500, .supportMobileMode = false};
65const Descriptor AcousticEchoCancelerSw::kDescriptor = {
66 .common = {.id = {.type = kAcousticEchoCancelerTypeUUID,
67 .uuid = kAcousticEchoCancelerSwImplUUID,
68 .proxy = std::nullopt},
69 .flags = {.type = Flags::Type::INSERT,
70 .insert = Flags::Insert::FIRST,
71 .volume = Flags::Volume::CTRL},
72 .name = AcousticEchoCancelerSw::kEffectName,
73 .implementor = "The Android Open Source Project"},
74 .capability = Capability::make<Capability::acousticEchoCanceler>(
75 AcousticEchoCancelerSw::kCapability)};
76
77ndk::ScopedAStatus AcousticEchoCancelerSw::getDescriptor(Descriptor* _aidl_return) {
78 LOG(DEBUG) << __func__ << kDescriptor.toString();
79 *_aidl_return = kDescriptor;
80 return ndk::ScopedAStatus::ok();
81}
82
83ndk::ScopedAStatus AcousticEchoCancelerSw::setParameterSpecific(
84 const Parameter::Specific& specific) {
85 RETURN_IF(Parameter::Specific::acousticEchoCanceler != specific.getTag(), EX_ILLEGAL_ARGUMENT,
86 "EffectNotSupported");
87 RETURN_IF(!mContext, EX_NULL_POINTER, "nullContext");
88
89 auto& param = specific.get<Parameter::Specific::acousticEchoCanceler>();
90 auto tag = param.getTag();
91
92 switch (tag) {
93 case AcousticEchoCanceler::echoDelayUs: {
94 RETURN_IF(mContext->setEchoDelay(param.get<AcousticEchoCanceler::echoDelayUs>()) !=
95 RetCode::SUCCESS,
96 EX_ILLEGAL_ARGUMENT, "echoDelayNotSupported");
97 return ndk::ScopedAStatus::ok();
98 }
99 case AcousticEchoCanceler::mobileMode: {
100 RETURN_IF(true == param.get<AcousticEchoCanceler::mobileMode>(), EX_ILLEGAL_ARGUMENT,
101 "SettingmobileModeSupported");
102 return ndk::ScopedAStatus::ok();
103 }
104 default: {
105 LOG(ERROR) << __func__ << " unsupported tag: " << toString(tag);
106 return ndk::ScopedAStatus::fromExceptionCodeWithMessage(
107 EX_ILLEGAL_ARGUMENT, "AcousticEchoCancelerTagNotSupported");
108 }
109 }
110}
111
112ndk::ScopedAStatus AcousticEchoCancelerSw::getParameterSpecific(const Parameter::Id& id,
113 Parameter::Specific* specific) {
114 auto tag = id.getTag();
115 RETURN_IF(Parameter::Id::acousticEchoCancelerTag != tag, EX_ILLEGAL_ARGUMENT, "wrongIdTag");
116 auto specificId = id.get<Parameter::Id::acousticEchoCancelerTag>();
117 auto specificIdTag = specificId.getTag();
118 switch (specificIdTag) {
119 case AcousticEchoCanceler::Id::commonTag:
120 return getParameterAcousticEchoCanceler(
121 specificId.get<AcousticEchoCanceler::Id::commonTag>(), specific);
122 default:
123 LOG(ERROR) << __func__ << " unsupported tag: " << toString(tag);
124 return ndk::ScopedAStatus::fromExceptionCodeWithMessage(
125 EX_ILLEGAL_ARGUMENT, "AcousticEchoCancelerTagNotSupported");
126 }
127}
128
129ndk::ScopedAStatus AcousticEchoCancelerSw::getParameterAcousticEchoCanceler(
130 const AcousticEchoCanceler::Tag& tag, Parameter::Specific* specific) {
131 RETURN_IF(!mContext, EX_NULL_POINTER, "nullContext");
132 AcousticEchoCanceler param;
133 switch (tag) {
134 case AcousticEchoCanceler::echoDelayUs: {
135 param.set<AcousticEchoCanceler::echoDelayUs>(mContext->getEchoDelay());
136 break;
137 }
138 case AcousticEchoCanceler::mobileMode: {
139 param.set<AcousticEchoCanceler::mobileMode>(false);
140 break;
141 }
142 default: {
143 LOG(ERROR) << __func__ << " unsupported tag: " << toString(tag);
144 return ndk::ScopedAStatus::fromExceptionCodeWithMessage(
145 EX_ILLEGAL_ARGUMENT, "AcousticEchoCancelerTagNotSupported");
146 }
147 }
148
149 specific->set<Parameter::Specific::acousticEchoCanceler>(param);
150 return ndk::ScopedAStatus::ok();
151}
152
153std::shared_ptr<EffectContext> AcousticEchoCancelerSw::createContext(
154 const Parameter::Common& common) {
155 if (mContext) {
156 LOG(DEBUG) << __func__ << " context already exist";
157 } else {
158 mContext = std::make_shared<AcousticEchoCancelerSwContext>(1 /* statusFmqDepth */, common);
159 }
160 return mContext;
161}
162
163std::shared_ptr<EffectContext> AcousticEchoCancelerSw::getContext() {
164 return mContext;
165}
166
167RetCode AcousticEchoCancelerSw::releaseContext() {
168 if (mContext) {
169 mContext.reset();
170 }
171 return RetCode::SUCCESS;
172}
173
174// Processing method running in EffectWorker thread.
175IEffect::Status AcousticEchoCancelerSw::effectProcessImpl(float* in, float* out, int samples) {
176 // TODO: get data buffer and process.
177 LOG(DEBUG) << __func__ << " in " << in << " out " << out << " samples " << samples;
178 for (int i = 0; i < samples; i++) {
179 *out++ = *in++;
180 }
181 return {STATUS_OK, samples, samples};
182}
183
184RetCode AcousticEchoCancelerSwContext::setEchoDelay(int echoDelayUs) {
185 if (echoDelayUs < 0 || echoDelayUs > AcousticEchoCancelerSw::kCapability.maxEchoDelayUs) {
186 LOG(DEBUG) << __func__ << " illegal delay " << echoDelayUs;
187 return RetCode::ERROR_ILLEGAL_PARAMETER;
188 }
189 mEchoDelayUs = echoDelayUs;
190 return RetCode::SUCCESS;
191}
192
193} // namespace aidl::android::hardware::audio::effect