xref: /aosp_15_r20/hardware/interfaces/audio/aidl/default/EffectContext.cpp (revision 4d7e907c777eeecc4c5bd7cf640a754fac206ff7)
1 /*
2  * Copyright (C) 2024 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 <memory>
18 #define LOG_TAG "AHAL_EffectContext"
19 #include "effect-impl/EffectContext.h"
20 #include "include/effect-impl/EffectTypes.h"
21 
22 using aidl::android::hardware::audio::common::getChannelCount;
23 using aidl::android::hardware::audio::common::getFrameSizeInBytes;
24 using aidl::android::hardware::audio::effect::IEffect;
25 using aidl::android::hardware::audio::effect::kReopenSupportedVersion;
26 using aidl::android::media::audio::common::PcmType;
27 using ::android::hardware::EventFlag;
28 
29 namespace aidl::android::hardware::audio::effect {
30 
EffectContext(size_t statusDepth,const Parameter::Common & common)31 EffectContext::EffectContext(size_t statusDepth, const Parameter::Common& common) {
32     LOG_ALWAYS_FATAL_IF(RetCode::SUCCESS != setCommon(common), "illegalCommonParameter");
33 
34     // in/outBuffer size in float (FMQ data format defined for DataMQ)
35     size_t inBufferSizeInFloat = common.input.frameCount * mInputFrameSize / sizeof(float);
36     size_t outBufferSizeInFloat = common.output.frameCount * mOutputFrameSize / sizeof(float);
37 
38     // only status FMQ use the EventFlag
39     mStatusMQ = std::make_shared<StatusMQ>(statusDepth, true /*configureEventFlagWord*/);
40     mInputMQ = std::make_shared<DataMQ>(inBufferSizeInFloat);
41     mOutputMQ = std::make_shared<DataMQ>(outBufferSizeInFloat);
42 
43     if (!mStatusMQ->isValid() || !mInputMQ->isValid() || !mOutputMQ->isValid()) {
44         LOG(ERROR) << __func__ << " created invalid FMQ, statusMQ: " << mStatusMQ->isValid()
45                    << " inputMQ: " << mInputMQ->isValid() << " outputMQ: " << mOutputMQ->isValid();
46     }
47 
48     ::android::status_t status =
49             EventFlag::createEventFlag(mStatusMQ->getEventFlagWord(), &mEfGroup);
50     LOG_ALWAYS_FATAL_IF(status != ::android::OK || !mEfGroup, " create EventFlagGroup failed ");
51     mWorkBuffer.resize(std::max(inBufferSizeInFloat, outBufferSizeInFloat));
52 }
53 
54 // reset buffer status by abandon input data in FMQ
resetBuffer()55 void EffectContext::resetBuffer() {
56     auto buffer = static_cast<float*>(mWorkBuffer.data());
57     if (mStatusMQ) {
58         std::vector<IEffect::Status> status(mStatusMQ->availableToRead());
59     }
60     if (mInputMQ) {
61         mInputMQ->read(buffer, mInputMQ->availableToRead());
62     }
63 }
64 
dupeFmqWithReopen(IEffect::OpenEffectReturn * effectRet)65 void EffectContext::dupeFmqWithReopen(IEffect::OpenEffectReturn* effectRet) {
66     const size_t inBufferSizeInFloat = mCommon.input.frameCount * mInputFrameSize / sizeof(float);
67     const size_t outBufferSizeInFloat =
68             mCommon.output.frameCount * mOutputFrameSize / sizeof(float);
69     const size_t bufferSize = std::max(inBufferSizeInFloat, outBufferSizeInFloat);
70     if (!mInputMQ) {
71         mInputMQ = std::make_shared<DataMQ>(inBufferSizeInFloat);
72     }
73     if (!mOutputMQ) {
74         mOutputMQ = std::make_shared<DataMQ>(outBufferSizeInFloat);
75     }
76     if (mWorkBuffer.size() != bufferSize) {
77         mWorkBuffer.resize(bufferSize);
78     }
79     dupeFmq(effectRet);
80 }
81 
dupeFmq(IEffect::OpenEffectReturn * effectRet)82 void EffectContext::dupeFmq(IEffect::OpenEffectReturn* effectRet) {
83     if (effectRet && mStatusMQ && mInputMQ && mOutputMQ) {
84         effectRet->statusMQ = mStatusMQ->dupeDesc();
85         effectRet->inputDataMQ = mInputMQ->dupeDesc();
86         effectRet->outputDataMQ = mOutputMQ->dupeDesc();
87     }
88 }
89 
getWorkBuffer()90 float* EffectContext::getWorkBuffer() {
91     return static_cast<float*>(mWorkBuffer.data());
92 }
93 
getWorkBufferSize() const94 size_t EffectContext::getWorkBufferSize() const {
95     return mWorkBuffer.size();
96 }
97 
getStatusFmq() const98 std::shared_ptr<EffectContext::StatusMQ> EffectContext::getStatusFmq() const {
99     return mStatusMQ;
100 }
101 
getInputDataFmq() const102 std::shared_ptr<EffectContext::DataMQ> EffectContext::getInputDataFmq() const {
103     return mInputMQ;
104 }
105 
getOutputDataFmq() const106 std::shared_ptr<EffectContext::DataMQ> EffectContext::getOutputDataFmq() const {
107     return mOutputMQ;
108 }
109 
getInputFrameSize() const110 size_t EffectContext::getInputFrameSize() const {
111     return mInputFrameSize;
112 }
113 
getOutputFrameSize() const114 size_t EffectContext::getOutputFrameSize() const {
115     return mOutputFrameSize;
116 }
117 
getSessionId() const118 int EffectContext::getSessionId() const {
119     return mCommon.session;
120 }
121 
getIoHandle() const122 int EffectContext::getIoHandle() const {
123     return mCommon.ioHandle;
124 }
125 
setOutputDevice(const std::vector<aidl::android::media::audio::common::AudioDeviceDescription> & device)126 RetCode EffectContext::setOutputDevice(
127         const std::vector<aidl::android::media::audio::common::AudioDeviceDescription>& device) {
128     mOutputDevice = device;
129     return RetCode::SUCCESS;
130 }
131 
132 std::vector<aidl::android::media::audio::common::AudioDeviceDescription>
getOutputDevice()133 EffectContext::getOutputDevice() {
134     return mOutputDevice;
135 }
136 
setAudioMode(const aidl::android::media::audio::common::AudioMode & mode)137 RetCode EffectContext::setAudioMode(const aidl::android::media::audio::common::AudioMode& mode) {
138     mMode = mode;
139     return RetCode::SUCCESS;
140 }
getAudioMode()141 aidl::android::media::audio::common::AudioMode EffectContext::getAudioMode() {
142     return mMode;
143 }
144 
setAudioSource(const aidl::android::media::audio::common::AudioSource & source)145 RetCode EffectContext::setAudioSource(
146         const aidl::android::media::audio::common::AudioSource& source) {
147     mSource = source;
148     return RetCode::SUCCESS;
149 }
150 
getAudioSource()151 aidl::android::media::audio::common::AudioSource EffectContext::getAudioSource() {
152     return mSource;
153 }
154 
setVolumeStereo(const Parameter::VolumeStereo & volumeStereo)155 RetCode EffectContext::setVolumeStereo(const Parameter::VolumeStereo& volumeStereo) {
156     mVolumeStereo = volumeStereo;
157     return RetCode::SUCCESS;
158 }
159 
getVolumeStereo()160 Parameter::VolumeStereo EffectContext::getVolumeStereo() {
161     return mVolumeStereo;
162 }
163 
setCommon(const Parameter::Common & common)164 RetCode EffectContext::setCommon(const Parameter::Common& common) {
165     auto& input = common.input;
166     auto& output = common.output;
167 
168     if (input.base.format.pcm != aidl::android::media::audio::common::PcmType::FLOAT_32_BIT ||
169         output.base.format.pcm != aidl::android::media::audio::common::PcmType::FLOAT_32_BIT) {
170         LOG(ERROR) << __func__ << " illegal IO, input "
171                    << ::android::internal::ToString(input.base.format) << ", output "
172                    << ::android::internal::ToString(output.base.format);
173         return RetCode::ERROR_ILLEGAL_PARAMETER;
174     }
175 
176     if (auto ret = updateIOFrameSize(common); ret != RetCode::SUCCESS) {
177         return ret;
178     }
179 
180     mInputChannelCount = getChannelCount(input.base.channelMask);
181     mOutputChannelCount = getChannelCount(output.base.channelMask);
182     if (mInputChannelCount == 0 || mOutputChannelCount == 0) {
183         LOG(ERROR) << __func__ << " illegal channel count input " << mInputChannelCount
184                    << ", output " << mOutputChannelCount;
185         return RetCode::ERROR_ILLEGAL_PARAMETER;
186     }
187 
188     mCommon = common;
189     return RetCode::SUCCESS;
190 }
191 
getCommon()192 Parameter::Common EffectContext::getCommon() {
193     return mCommon;
194 }
195 
getStatusEventFlag()196 EventFlag* EffectContext::getStatusEventFlag() {
197     return mEfGroup;
198 }
199 
updateIOFrameSize(const Parameter::Common & common)200 RetCode EffectContext::updateIOFrameSize(const Parameter::Common& common) {
201     const auto prevInputFrameSize = mInputFrameSize;
202     const auto prevOutputFrameSize = mOutputFrameSize;
203     mInputFrameSize = ::aidl::android::hardware::audio::common::getFrameSizeInBytes(
204             common.input.base.format, common.input.base.channelMask);
205     mOutputFrameSize = ::aidl::android::hardware::audio::common::getFrameSizeInBytes(
206             common.output.base.format, common.output.base.channelMask);
207 
208     // workBuffer and data MQ not allocated yet, no need to update
209     if (mWorkBuffer.size() == 0 || !mInputMQ || !mOutputMQ) {
210         return RetCode::SUCCESS;
211     }
212     // IEffect::reopen introduced in android.hardware.audio.effect-V2
213     if (mVersion < kReopenSupportedVersion) {
214         LOG(WARNING) << __func__ << " skipped for HAL version " << mVersion;
215         return RetCode::SUCCESS;
216     }
217     bool needUpdateMq = false;
218     if (mInputFrameSize != prevInputFrameSize ||
219         mCommon.input.frameCount != common.input.frameCount) {
220         mInputMQ.reset();
221         needUpdateMq = true;
222     }
223     if (mOutputFrameSize != prevOutputFrameSize ||
224         mCommon.output.frameCount != common.output.frameCount) {
225         mOutputMQ.reset();
226         needUpdateMq = true;
227     }
228 
229     if (needUpdateMq) {
230         return notifyDataMqUpdate();
231     }
232     return RetCode::SUCCESS;
233 }
234 
notifyDataMqUpdate()235 RetCode EffectContext::notifyDataMqUpdate() {
236     if (!mEfGroup) {
237         LOG(ERROR) << __func__ << ": invalid EventFlag group";
238         return RetCode::ERROR_EVENT_FLAG_ERROR;
239     }
240 
241     if (const auto ret = mEfGroup->wake(kEventFlagDataMqUpdate); ret != ::android::OK) {
242         LOG(ERROR) << __func__ << ": wake failure with ret " << ret;
243         return RetCode::ERROR_EVENT_FLAG_ERROR;
244     }
245     LOG(VERBOSE) << __func__ << " : signal client for reopen";
246     return RetCode::SUCCESS;
247 }
248 
enable()249 RetCode EffectContext::enable() {
250     return RetCode::SUCCESS;
251 }
252 
disable()253 RetCode EffectContext::disable() {
254     return RetCode::SUCCESS;
255 }
256 
reset()257 RetCode EffectContext::reset() {
258     return RetCode::SUCCESS;
259 }
260 
startDraining()261 RetCode EffectContext::startDraining() {
262     mIsDraining = true;
263     return RetCode::SUCCESS;
264 }
265 
finishDraining()266 RetCode EffectContext::finishDraining() {
267     mIsDraining = false;
268     return RetCode::SUCCESS;
269 }
270 
isDraining()271 bool EffectContext::isDraining() {
272     return mIsDraining;
273 }
274 
275 }  // namespace aidl::android::hardware::audio::effect
276