• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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     if (!mInputMQ) {
67         mInputMQ = std::make_shared<DataMQ>(mCommon.input.frameCount * mInputFrameSize /
68                                             sizeof(float));
69     }
70     if (!mOutputMQ) {
71         mOutputMQ = std::make_shared<DataMQ>(mCommon.output.frameCount * mOutputFrameSize /
72                                              sizeof(float));
73     }
74     dupeFmq(effectRet);
75 }
76 
dupeFmq(IEffect::OpenEffectReturn * effectRet)77 void EffectContext::dupeFmq(IEffect::OpenEffectReturn* effectRet) {
78     if (effectRet && mStatusMQ && mInputMQ && mOutputMQ) {
79         effectRet->statusMQ = mStatusMQ->dupeDesc();
80         effectRet->inputDataMQ = mInputMQ->dupeDesc();
81         effectRet->outputDataMQ = mOutputMQ->dupeDesc();
82     }
83 }
84 
getWorkBuffer()85 float* EffectContext::getWorkBuffer() {
86     return static_cast<float*>(mWorkBuffer.data());
87 }
88 
getWorkBufferSize() const89 size_t EffectContext::getWorkBufferSize() const {
90     return mWorkBuffer.size();
91 }
92 
getStatusFmq() const93 std::shared_ptr<EffectContext::StatusMQ> EffectContext::getStatusFmq() const {
94     return mStatusMQ;
95 }
96 
getInputDataFmq() const97 std::shared_ptr<EffectContext::DataMQ> EffectContext::getInputDataFmq() const {
98     return mInputMQ;
99 }
100 
getOutputDataFmq() const101 std::shared_ptr<EffectContext::DataMQ> EffectContext::getOutputDataFmq() const {
102     return mOutputMQ;
103 }
104 
getInputFrameSize() const105 size_t EffectContext::getInputFrameSize() const {
106     return mInputFrameSize;
107 }
108 
getOutputFrameSize() const109 size_t EffectContext::getOutputFrameSize() const {
110     return mOutputFrameSize;
111 }
112 
getSessionId() const113 int EffectContext::getSessionId() const {
114     return mCommon.session;
115 }
116 
getIoHandle() const117 int EffectContext::getIoHandle() const {
118     return mCommon.ioHandle;
119 }
120 
setOutputDevice(const std::vector<aidl::android::media::audio::common::AudioDeviceDescription> & device)121 RetCode EffectContext::setOutputDevice(
122         const std::vector<aidl::android::media::audio::common::AudioDeviceDescription>& device) {
123     mOutputDevice = device;
124     return RetCode::SUCCESS;
125 }
126 
127 std::vector<aidl::android::media::audio::common::AudioDeviceDescription>
getOutputDevice()128 EffectContext::getOutputDevice() {
129     return mOutputDevice;
130 }
131 
setAudioMode(const aidl::android::media::audio::common::AudioMode & mode)132 RetCode EffectContext::setAudioMode(const aidl::android::media::audio::common::AudioMode& mode) {
133     mMode = mode;
134     return RetCode::SUCCESS;
135 }
getAudioMode()136 aidl::android::media::audio::common::AudioMode EffectContext::getAudioMode() {
137     return mMode;
138 }
139 
setAudioSource(const aidl::android::media::audio::common::AudioSource & source)140 RetCode EffectContext::setAudioSource(
141         const aidl::android::media::audio::common::AudioSource& source) {
142     mSource = source;
143     return RetCode::SUCCESS;
144 }
145 
getAudioSource()146 aidl::android::media::audio::common::AudioSource EffectContext::getAudioSource() {
147     return mSource;
148 }
149 
setVolumeStereo(const Parameter::VolumeStereo & volumeStereo)150 RetCode EffectContext::setVolumeStereo(const Parameter::VolumeStereo& volumeStereo) {
151     mVolumeStereo = volumeStereo;
152     return RetCode::SUCCESS;
153 }
154 
getVolumeStereo()155 Parameter::VolumeStereo EffectContext::getVolumeStereo() {
156     return mVolumeStereo;
157 }
158 
setCommon(const Parameter::Common & common)159 RetCode EffectContext::setCommon(const Parameter::Common& common) {
160     auto& input = common.input;
161     auto& output = common.output;
162 
163     if (input.base.format.pcm != aidl::android::media::audio::common::PcmType::FLOAT_32_BIT ||
164         output.base.format.pcm != aidl::android::media::audio::common::PcmType::FLOAT_32_BIT) {
165         LOG(ERROR) << __func__ << " illegal IO, input "
166                    << ::android::internal::ToString(input.base.format) << ", output "
167                    << ::android::internal::ToString(output.base.format);
168         return RetCode::ERROR_ILLEGAL_PARAMETER;
169     }
170 
171     if (auto ret = updateIOFrameSize(common); ret != RetCode::SUCCESS) {
172         return ret;
173     }
174 
175     mInputChannelCount = getChannelCount(input.base.channelMask);
176     mOutputChannelCount = getChannelCount(output.base.channelMask);
177     if (mInputChannelCount == 0 || mOutputChannelCount == 0) {
178         LOG(ERROR) << __func__ << " illegal channel count input " << mInputChannelCount
179                    << ", output " << mOutputChannelCount;
180         return RetCode::ERROR_ILLEGAL_PARAMETER;
181     }
182 
183     mCommon = common;
184     return RetCode::SUCCESS;
185 }
186 
getCommon()187 Parameter::Common EffectContext::getCommon() {
188     return mCommon;
189 }
190 
getStatusEventFlag()191 EventFlag* EffectContext::getStatusEventFlag() {
192     return mEfGroup;
193 }
194 
updateIOFrameSize(const Parameter::Common & common)195 RetCode EffectContext::updateIOFrameSize(const Parameter::Common& common) {
196     const auto prevInputFrameSize = mInputFrameSize;
197     const auto prevOutputFrameSize = mOutputFrameSize;
198     mInputFrameSize = ::aidl::android::hardware::audio::common::getFrameSizeInBytes(
199             common.input.base.format, common.input.base.channelMask);
200     mOutputFrameSize = ::aidl::android::hardware::audio::common::getFrameSizeInBytes(
201             common.output.base.format, common.output.base.channelMask);
202 
203     // workBuffer and data MQ not allocated yet, no need to update
204     if (mWorkBuffer.size() == 0 || !mInputMQ || !mOutputMQ) {
205         return RetCode::SUCCESS;
206     }
207     // IEffect::reopen introduced in android.hardware.audio.effect-V2
208     if (mVersion < kReopenSupportedVersion) {
209         LOG(WARNING) << __func__ << " skipped for HAL version " << mVersion;
210         return RetCode::SUCCESS;
211     }
212     bool needUpdateMq = false;
213     if (mInputFrameSize != prevInputFrameSize ||
214         mCommon.input.frameCount != common.input.frameCount) {
215         mInputMQ.reset();
216         needUpdateMq = true;
217     }
218     if (mOutputFrameSize != prevOutputFrameSize ||
219         mCommon.output.frameCount != common.output.frameCount) {
220         mOutputMQ.reset();
221         needUpdateMq = true;
222     }
223 
224     if (needUpdateMq) {
225         mWorkBuffer.resize(std::max(common.input.frameCount * mInputFrameSize / sizeof(float),
226                                     common.output.frameCount * mOutputFrameSize / sizeof(float)));
227         return notifyDataMqUpdate();
228     }
229     return RetCode::SUCCESS;
230 }
231 
notifyDataMqUpdate()232 RetCode EffectContext::notifyDataMqUpdate() {
233     if (!mEfGroup) {
234         LOG(ERROR) << __func__ << ": invalid EventFlag group";
235         return RetCode::ERROR_EVENT_FLAG_ERROR;
236     }
237 
238     if (const auto ret = mEfGroup->wake(kEventFlagDataMqUpdate); ret != ::android::OK) {
239         LOG(ERROR) << __func__ << ": wake failure with ret " << ret;
240         return RetCode::ERROR_EVENT_FLAG_ERROR;
241     }
242     LOG(VERBOSE) << __func__ << " : signal client for reopen";
243     return RetCode::SUCCESS;
244 }
245 }  // namespace aidl::android::hardware::audio::effect
246