blob: f5af81e52b05b0fda9b65250cacee2c85ecf7216 [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;
Shunkai Yao87811022023-02-13 17:40:37 +000033using aidl::android::hardware::audio::effect::Range;
Shunkai Yaobd862b82022-12-20 00:11:41 +000034using aidl::android::media::audio::common::AudioUuid;
35
36extern "C" binder_exception_t createEffect(const AudioUuid* in_impl_uuid,
37 std::shared_ptr<IEffect>* instanceSpp) {
38 if (!in_impl_uuid || *in_impl_uuid != kAcousticEchoCancelerSwImplUUID) {
39 LOG(ERROR) << __func__ << "uuid not supported";
40 return EX_ILLEGAL_ARGUMENT;
41 }
42 if (instanceSpp) {
43 *instanceSpp = ndk::SharedRefBase::make<AcousticEchoCancelerSw>();
44 LOG(DEBUG) << __func__ << " instance " << instanceSpp->get() << " created";
45 return EX_NONE;
46 } else {
47 LOG(ERROR) << __func__ << " invalid input parameter!";
48 return EX_ILLEGAL_ARGUMENT;
49 }
50}
51
52extern "C" binder_exception_t queryEffect(const AudioUuid* in_impl_uuid, Descriptor* _aidl_return) {
53 if (!in_impl_uuid || *in_impl_uuid != kAcousticEchoCancelerSwImplUUID) {
54 LOG(ERROR) << __func__ << "uuid not supported";
55 return EX_ILLEGAL_ARGUMENT;
56 }
57 *_aidl_return = AcousticEchoCancelerSw::kDescriptor;
Shunkai Yaobd862b82022-12-20 00:11:41 +000058 return EX_NONE;
59}
60
61namespace aidl::android::hardware::audio::effect {
62
63const std::string AcousticEchoCancelerSw::kEffectName = "AcousticEchoCancelerSw";
Shunkai Yao87811022023-02-13 17:40:37 +000064
65const std::vector<Range::AcousticEchoCancelerRange> AcousticEchoCancelerSw::kRanges = {
66 MAKE_RANGE(AcousticEchoCanceler, echoDelayUs, 0, 500),
67 /* mobile mode not supported, and not settable */
68 MAKE_RANGE(AcousticEchoCanceler, mobileMode, false, false)};
69
70const Capability AcousticEchoCancelerSw::kCapability = {.range = AcousticEchoCancelerSw::kRanges};
71
Shunkai Yaobd862b82022-12-20 00:11:41 +000072const Descriptor AcousticEchoCancelerSw::kDescriptor = {
73 .common = {.id = {.type = kAcousticEchoCancelerTypeUUID,
74 .uuid = kAcousticEchoCancelerSwImplUUID,
75 .proxy = std::nullopt},
76 .flags = {.type = Flags::Type::INSERT,
77 .insert = Flags::Insert::FIRST,
78 .volume = Flags::Volume::CTRL},
79 .name = AcousticEchoCancelerSw::kEffectName,
80 .implementor = "The Android Open Source Project"},
Shunkai Yao87811022023-02-13 17:40:37 +000081 .capability = AcousticEchoCancelerSw::kCapability};
Shunkai Yaobd862b82022-12-20 00:11:41 +000082
83ndk::ScopedAStatus AcousticEchoCancelerSw::getDescriptor(Descriptor* _aidl_return) {
84 LOG(DEBUG) << __func__ << kDescriptor.toString();
85 *_aidl_return = kDescriptor;
86 return ndk::ScopedAStatus::ok();
87}
88
89ndk::ScopedAStatus AcousticEchoCancelerSw::setParameterSpecific(
90 const Parameter::Specific& specific) {
91 RETURN_IF(Parameter::Specific::acousticEchoCanceler != specific.getTag(), EX_ILLEGAL_ARGUMENT,
92 "EffectNotSupported");
93 RETURN_IF(!mContext, EX_NULL_POINTER, "nullContext");
94
95 auto& param = specific.get<Parameter::Specific::acousticEchoCanceler>();
Shunkai Yao87811022023-02-13 17:40:37 +000096 RETURN_IF(!inRange(param, kRanges), EX_ILLEGAL_ARGUMENT, "outOfRange");
Shunkai Yaobd862b82022-12-20 00:11:41 +000097
Shunkai Yao87811022023-02-13 17:40:37 +000098 auto tag = param.getTag();
Shunkai Yaobd862b82022-12-20 00:11:41 +000099 switch (tag) {
100 case AcousticEchoCanceler::echoDelayUs: {
101 RETURN_IF(mContext->setEchoDelay(param.get<AcousticEchoCanceler::echoDelayUs>()) !=
102 RetCode::SUCCESS,
103 EX_ILLEGAL_ARGUMENT, "echoDelayNotSupported");
104 return ndk::ScopedAStatus::ok();
105 }
106 case AcousticEchoCanceler::mobileMode: {
107 RETURN_IF(true == param.get<AcousticEchoCanceler::mobileMode>(), EX_ILLEGAL_ARGUMENT,
108 "SettingmobileModeSupported");
109 return ndk::ScopedAStatus::ok();
110 }
111 default: {
112 LOG(ERROR) << __func__ << " unsupported tag: " << toString(tag);
113 return ndk::ScopedAStatus::fromExceptionCodeWithMessage(
114 EX_ILLEGAL_ARGUMENT, "AcousticEchoCancelerTagNotSupported");
115 }
116 }
117}
118
119ndk::ScopedAStatus AcousticEchoCancelerSw::getParameterSpecific(const Parameter::Id& id,
120 Parameter::Specific* specific) {
121 auto tag = id.getTag();
122 RETURN_IF(Parameter::Id::acousticEchoCancelerTag != tag, EX_ILLEGAL_ARGUMENT, "wrongIdTag");
123 auto specificId = id.get<Parameter::Id::acousticEchoCancelerTag>();
124 auto specificIdTag = specificId.getTag();
125 switch (specificIdTag) {
126 case AcousticEchoCanceler::Id::commonTag:
127 return getParameterAcousticEchoCanceler(
128 specificId.get<AcousticEchoCanceler::Id::commonTag>(), specific);
129 default:
130 LOG(ERROR) << __func__ << " unsupported tag: " << toString(tag);
131 return ndk::ScopedAStatus::fromExceptionCodeWithMessage(
132 EX_ILLEGAL_ARGUMENT, "AcousticEchoCancelerTagNotSupported");
133 }
134}
135
136ndk::ScopedAStatus AcousticEchoCancelerSw::getParameterAcousticEchoCanceler(
137 const AcousticEchoCanceler::Tag& tag, Parameter::Specific* specific) {
138 RETURN_IF(!mContext, EX_NULL_POINTER, "nullContext");
139 AcousticEchoCanceler param;
140 switch (tag) {
141 case AcousticEchoCanceler::echoDelayUs: {
142 param.set<AcousticEchoCanceler::echoDelayUs>(mContext->getEchoDelay());
143 break;
144 }
145 case AcousticEchoCanceler::mobileMode: {
146 param.set<AcousticEchoCanceler::mobileMode>(false);
147 break;
148 }
149 default: {
150 LOG(ERROR) << __func__ << " unsupported tag: " << toString(tag);
151 return ndk::ScopedAStatus::fromExceptionCodeWithMessage(
152 EX_ILLEGAL_ARGUMENT, "AcousticEchoCancelerTagNotSupported");
153 }
154 }
155
156 specific->set<Parameter::Specific::acousticEchoCanceler>(param);
157 return ndk::ScopedAStatus::ok();
158}
159
160std::shared_ptr<EffectContext> AcousticEchoCancelerSw::createContext(
161 const Parameter::Common& common) {
162 if (mContext) {
163 LOG(DEBUG) << __func__ << " context already exist";
164 } else {
165 mContext = std::make_shared<AcousticEchoCancelerSwContext>(1 /* statusFmqDepth */, common);
166 }
167 return mContext;
168}
169
170std::shared_ptr<EffectContext> AcousticEchoCancelerSw::getContext() {
171 return mContext;
172}
173
174RetCode AcousticEchoCancelerSw::releaseContext() {
175 if (mContext) {
176 mContext.reset();
177 }
178 return RetCode::SUCCESS;
179}
180
181// Processing method running in EffectWorker thread.
182IEffect::Status AcousticEchoCancelerSw::effectProcessImpl(float* in, float* out, int samples) {
183 // TODO: get data buffer and process.
184 LOG(DEBUG) << __func__ << " in " << in << " out " << out << " samples " << samples;
185 for (int i = 0; i < samples; i++) {
186 *out++ = *in++;
187 }
188 return {STATUS_OK, samples, samples};
189}
190
191RetCode AcousticEchoCancelerSwContext::setEchoDelay(int echoDelayUs) {
Shunkai Yaobd862b82022-12-20 00:11:41 +0000192 mEchoDelayUs = echoDelayUs;
193 return RetCode::SUCCESS;
194}
195
196} // namespace aidl::android::hardware::audio::effect