blob: 0babfdad351fd4ebed8cc1043b934b1c0d760576 [file] [log] [blame]
Mikhail Naganovf558e022016-11-14 17:45:17 -08001/*
2 * Copyright (C) 2016 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 "EffectHalHidl"
18//#define LOG_NDEBUG 0
19
Mikhail Naganov23feba22017-02-23 11:00:55 -080020#include <hwbinder/IPCThreadState.h>
Mikhail Naganovf558e022016-11-14 17:45:17 -080021#include <media/EffectsFactoryApi.h>
22#include <utils/Log.h>
23
Mikhail Naganov9f57e3c2016-12-05 12:54:36 -080024#include "ConversionHelperHidl.h"
Mikhail Naganov022b9952017-01-04 16:36:51 -080025#include "EffectBufferHalHidl.h"
Mikhail Naganovf558e022016-11-14 17:45:17 -080026#include "EffectHalHidl.h"
27#include "HidlUtils.h"
28
Mikhail Naganov022b9952017-01-04 16:36:51 -080029using ::android::hardware::audio::effect::V2_0::AudioBuffer;
Mikhail Naganovf508bd42017-02-16 13:51:20 -080030using ::android::hardware::audio::effect::V2_0::EffectBufferAccess;
31using ::android::hardware::audio::effect::V2_0::EffectConfigParameters;
Mikhail Naganov022b9952017-01-04 16:36:51 -080032using ::android::hardware::audio::effect::V2_0::MessageQueueFlagBits;
Mikhail Naganovf558e022016-11-14 17:45:17 -080033using ::android::hardware::audio::effect::V2_0::Result;
Mikhail Naganovf508bd42017-02-16 13:51:20 -080034using ::android::hardware::audio::common::V2_0::AudioChannelMask;
35using ::android::hardware::audio::common::V2_0::AudioFormat;
Mikhail Naganovf558e022016-11-14 17:45:17 -080036using ::android::hardware::hidl_vec;
Mikhail Naganov022b9952017-01-04 16:36:51 -080037using ::android::hardware::MQDescriptorSync;
Mikhail Naganovf558e022016-11-14 17:45:17 -080038using ::android::hardware::Return;
Mikhail Naganovf558e022016-11-14 17:45:17 -080039
40namespace android {
41
42EffectHalHidl::EffectHalHidl(const sp<IEffect>& effect, uint64_t effectId)
Mikhail Naganov022b9952017-01-04 16:36:51 -080043 : mEffect(effect), mEffectId(effectId), mBuffersChanged(true) {
Mikhail Naganovf558e022016-11-14 17:45:17 -080044}
45
46EffectHalHidl::~EffectHalHidl() {
Mikhail Naganov23feba22017-02-23 11:00:55 -080047 if (mEffect != 0) {
48 close();
49 mEffect.clear();
50 hardware::IPCThreadState::self()->flushCommands();
51 }
Mikhail Naganovf558e022016-11-14 17:45:17 -080052}
53
54// static
55void EffectHalHidl::effectDescriptorToHal(
56 const EffectDescriptor& descriptor, effect_descriptor_t* halDescriptor) {
57 HidlUtils::uuidToHal(descriptor.type, &halDescriptor->type);
58 HidlUtils::uuidToHal(descriptor.uuid, &halDescriptor->uuid);
59 halDescriptor->flags = static_cast<uint32_t>(descriptor.flags);
60 halDescriptor->cpuLoad = descriptor.cpuLoad;
61 halDescriptor->memoryUsage = descriptor.memoryUsage;
62 memcpy(halDescriptor->name, descriptor.name.data(), descriptor.name.size());
63 memcpy(halDescriptor->implementor,
64 descriptor.implementor.data(), descriptor.implementor.size());
65}
66
Mikhail Naganovf508bd42017-02-16 13:51:20 -080067// TODO(mnaganov): These buffer conversion functions should be shared with Effect wrapper
68// via HidlUtils. Move them there when hardware/interfaces will get un-frozen again.
69
70// static
71void EffectHalHidl::effectBufferConfigFromHal(
72 const buffer_config_t& halConfig, EffectBufferConfig* config) {
73 config->samplingRateHz = halConfig.samplingRate;
74 config->channels = AudioChannelMask(halConfig.channels);
75 config->format = AudioFormat(halConfig.format);
76 config->accessMode = EffectBufferAccess(halConfig.accessMode);
77 config->mask = EffectConfigParameters(halConfig.mask);
78}
79
80// static
Mikhail Naganoved01be52017-02-16 15:57:07 -080081void EffectHalHidl::effectBufferConfigToHal(
82 const EffectBufferConfig& config, buffer_config_t* halConfig) {
83 halConfig->buffer.frameCount = 0;
84 halConfig->buffer.raw = NULL;
85 halConfig->samplingRate = config.samplingRateHz;
86 halConfig->channels = static_cast<uint32_t>(config.channels);
87 halConfig->bufferProvider.cookie = NULL;
88 halConfig->bufferProvider.getBuffer = NULL;
89 halConfig->bufferProvider.releaseBuffer = NULL;
90 halConfig->format = static_cast<uint8_t>(config.format);
91 halConfig->accessMode = static_cast<uint8_t>(config.accessMode);
92 halConfig->mask = static_cast<uint8_t>(config.mask);
93}
94
95// static
Mikhail Naganovf508bd42017-02-16 13:51:20 -080096void EffectHalHidl::effectConfigFromHal(const effect_config_t& halConfig, EffectConfig* config) {
97 effectBufferConfigFromHal(halConfig.inputCfg, &config->inputCfg);
98 effectBufferConfigFromHal(halConfig.outputCfg, &config->outputCfg);
99}
100
Mikhail Naganovf558e022016-11-14 17:45:17 -0800101// static
Mikhail Naganoved01be52017-02-16 15:57:07 -0800102void EffectHalHidl::effectConfigToHal(const EffectConfig& config, effect_config_t* halConfig) {
103 effectBufferConfigToHal(config.inputCfg, &halConfig->inputCfg);
104 effectBufferConfigToHal(config.outputCfg, &halConfig->outputCfg);
105}
106
107// static
Mikhail Naganovf558e022016-11-14 17:45:17 -0800108status_t EffectHalHidl::analyzeResult(const Result& result) {
109 switch (result) {
110 case Result::OK: return OK;
111 case Result::INVALID_ARGUMENTS: return BAD_VALUE;
112 case Result::INVALID_STATE: return NOT_ENOUGH_DATA;
113 case Result::NOT_INITIALIZED: return NO_INIT;
114 case Result::NOT_SUPPORTED: return INVALID_OPERATION;
115 case Result::RESULT_TOO_BIG: return NO_MEMORY;
116 default: return NO_INIT;
117 }
118}
119
Mikhail Naganov022b9952017-01-04 16:36:51 -0800120status_t EffectHalHidl::setInBuffer(const sp<EffectBufferHalInterface>& buffer) {
121 if (mInBuffer == 0 || buffer->audioBuffer() != mInBuffer->audioBuffer()) {
122 mBuffersChanged = true;
123 }
124 mInBuffer = buffer;
Mikhail Naganovf558e022016-11-14 17:45:17 -0800125 return OK;
126}
127
Mikhail Naganov022b9952017-01-04 16:36:51 -0800128status_t EffectHalHidl::setOutBuffer(const sp<EffectBufferHalInterface>& buffer) {
129 if (mOutBuffer == 0 || buffer->audioBuffer() != mOutBuffer->audioBuffer()) {
130 mBuffersChanged = true;
131 }
132 mOutBuffer = buffer;
Mikhail Naganovf558e022016-11-14 17:45:17 -0800133 return OK;
134}
135
Mikhail Naganov022b9952017-01-04 16:36:51 -0800136status_t EffectHalHidl::process() {
137 return processImpl(static_cast<uint32_t>(MessageQueueFlagBits::REQUEST_PROCESS));
138}
139
140status_t EffectHalHidl::processReverse() {
141 return processImpl(static_cast<uint32_t>(MessageQueueFlagBits::REQUEST_PROCESS_REVERSE));
142}
143
144status_t EffectHalHidl::prepareForProcessing() {
145 std::unique_ptr<StatusMQ> tempStatusMQ;
146 Result retval;
147 Return<void> ret = mEffect->prepareForProcessing(
148 [&](Result r, const MQDescriptorSync<Result>& statusMQ) {
149 retval = r;
150 if (retval == Result::OK) {
151 tempStatusMQ.reset(new StatusMQ(statusMQ));
152 if (tempStatusMQ->isValid() && tempStatusMQ->getEventFlagWord()) {
153 EventFlag::createEventFlag(tempStatusMQ->getEventFlagWord(), &mEfGroup);
154 }
155 }
156 });
Martijn Coenen67d0d7e2017-01-11 14:51:39 +0100157 if (!ret.isOk() || retval != Result::OK) {
158 return ret.isOk() ? analyzeResult(retval) : FAILED_TRANSACTION;
Mikhail Naganov022b9952017-01-04 16:36:51 -0800159 }
160 if (!tempStatusMQ || !tempStatusMQ->isValid() || !mEfGroup) {
161 ALOGE_IF(!tempStatusMQ, "Failed to obtain status message queue for effects");
162 ALOGE_IF(tempStatusMQ && !tempStatusMQ->isValid(),
163 "Status message queue for effects is invalid");
164 ALOGE_IF(!mEfGroup, "Event flag creation for effects failed");
165 return NO_INIT;
166 }
167 mStatusMQ = std::move(tempStatusMQ);
168 return OK;
169}
170
171status_t EffectHalHidl::processImpl(uint32_t mqFlag) {
172 if (mEffect == 0 || mInBuffer == 0 || mOutBuffer == 0) return NO_INIT;
173 status_t status;
174 if (!mStatusMQ && (status = prepareForProcessing()) != OK) {
175 return status;
176 }
177 if (mBuffersChanged && (status = setProcessBuffers()) != OK) {
178 return status;
179 }
180 // The data is already in the buffers, just need to flush it and wake up the server side.
181 std::atomic_thread_fence(std::memory_order_release);
182 mEfGroup->wake(mqFlag);
183 uint32_t efState = 0;
184retry:
185 status_t ret = mEfGroup->wait(
Mikhail Naganovb4e77912017-02-15 10:23:09 -0800186 static_cast<uint32_t>(MessageQueueFlagBits::DONE_PROCESSING), &efState);
Mikhail Naganov022b9952017-01-04 16:36:51 -0800187 if (efState & static_cast<uint32_t>(MessageQueueFlagBits::DONE_PROCESSING)) {
188 Result retval = Result::NOT_INITIALIZED;
189 mStatusMQ->read(&retval);
190 if (retval == Result::OK || retval == Result::INVALID_STATE) {
191 // Sync back the changed contents of the buffer.
192 std::atomic_thread_fence(std::memory_order_acquire);
193 }
194 return analyzeResult(retval);
195 }
Mikhail Naganovd2ae9cd2017-03-03 09:15:01 -0800196 if (ret == -EAGAIN || ret == -EINTR) {
197 // Spurious wakeup. This normally retries no more than once.
Mikhail Naganov022b9952017-01-04 16:36:51 -0800198 goto retry;
199 }
200 return ret;
201}
202
203status_t EffectHalHidl::setProcessBuffers() {
204 Return<Result> ret = mEffect->setProcessBuffers(
205 reinterpret_cast<EffectBufferHalHidl*>(mInBuffer.get())->hidlBuffer(),
206 reinterpret_cast<EffectBufferHalHidl*>(mOutBuffer.get())->hidlBuffer());
Martijn Coenen67d0d7e2017-01-11 14:51:39 +0100207 if (ret.isOk() && ret == Result::OK) {
Mikhail Naganov022b9952017-01-04 16:36:51 -0800208 mBuffersChanged = false;
209 return OK;
210 }
Mikhail Naganovd621ac82017-01-12 17:17:45 -0800211 return ret.isOk() ? analyzeResult(ret) : FAILED_TRANSACTION;
Mikhail Naganov022b9952017-01-04 16:36:51 -0800212}
213
Mikhail Naganovf558e022016-11-14 17:45:17 -0800214status_t EffectHalHidl::command(uint32_t cmdCode, uint32_t cmdSize, void *pCmdData,
215 uint32_t *replySize, void *pReplyData) {
216 if (mEffect == 0) return NO_INIT;
Mikhail Naganovf508bd42017-02-16 13:51:20 -0800217
218 // Special cases.
219 if (cmdCode == EFFECT_CMD_SET_CONFIG || cmdCode == EFFECT_CMD_SET_CONFIG_REVERSE) {
220 return setConfigImpl(cmdCode, cmdSize, pCmdData, replySize, pReplyData);
Mikhail Naganoved01be52017-02-16 15:57:07 -0800221 } else if (cmdCode == EFFECT_CMD_GET_CONFIG || cmdCode == EFFECT_CMD_GET_CONFIG_REVERSE) {
222 return getConfigImpl(cmdCode, replySize, pReplyData);
Mikhail Naganovf508bd42017-02-16 13:51:20 -0800223 }
224
225 // Common case.
Mikhail Naganovf558e022016-11-14 17:45:17 -0800226 hidl_vec<uint8_t> hidlData;
Mikhail Naganov9dc17472017-01-11 11:15:28 -0800227 if (pCmdData != nullptr && cmdSize > 0) {
228 hidlData.setToExternal(reinterpret_cast<uint8_t*>(pCmdData), cmdSize);
229 }
Mikhail Naganovf558e022016-11-14 17:45:17 -0800230 status_t status;
Mikhail Naganovbcd0a042017-01-17 09:45:19 -0800231 uint32_t replySizeStub = 0;
Mikhail Naganov06888802017-01-19 12:47:55 -0800232 if (replySize == nullptr || pReplyData == nullptr) replySize = &replySizeStub;
Mikhail Naganovf558e022016-11-14 17:45:17 -0800233 Return<void> ret = mEffect->command(cmdCode, hidlData, *replySize,
234 [&](int32_t s, const hidl_vec<uint8_t>& result) {
235 status = s;
236 if (status == 0) {
237 if (*replySize > result.size()) *replySize = result.size();
Mikhail Naganov9dc17472017-01-11 11:15:28 -0800238 if (pReplyData != nullptr && *replySize > 0) {
Mikhail Naganovf558e022016-11-14 17:45:17 -0800239 memcpy(pReplyData, &result[0], *replySize);
240 }
241 }
242 });
Mikhail Naganovd621ac82017-01-12 17:17:45 -0800243 return ret.isOk() ? status : FAILED_TRANSACTION;
Mikhail Naganovf558e022016-11-14 17:45:17 -0800244}
245
246status_t EffectHalHidl::getDescriptor(effect_descriptor_t *pDescriptor) {
247 if (mEffect == 0) return NO_INIT;
248 Result retval = Result::NOT_INITIALIZED;
249 Return<void> ret = mEffect->getDescriptor(
250 [&](Result r, const EffectDescriptor& result) {
251 retval = r;
252 if (retval == Result::OK) {
253 effectDescriptorToHal(result, pDescriptor);
254 }
255 });
Mikhail Naganovd621ac82017-01-12 17:17:45 -0800256 return ret.isOk() ? analyzeResult(retval) : FAILED_TRANSACTION;
Mikhail Naganovf558e022016-11-14 17:45:17 -0800257}
258
Mikhail Naganov022b9952017-01-04 16:36:51 -0800259status_t EffectHalHidl::close() {
260 if (mEffect == 0) return NO_INIT;
261 Return<Result> ret = mEffect->close();
Mikhail Naganovd621ac82017-01-12 17:17:45 -0800262 return ret.isOk() ? analyzeResult(ret) : FAILED_TRANSACTION;
Mikhail Naganov022b9952017-01-04 16:36:51 -0800263}
264
Mikhail Naganoved01be52017-02-16 15:57:07 -0800265status_t EffectHalHidl::getConfigImpl(
266 uint32_t cmdCode, uint32_t *replySize, void *pReplyData) {
267 if (replySize == NULL || *replySize != sizeof(effect_config_t) || pReplyData == NULL) {
268 return BAD_VALUE;
269 }
270 status_t result = FAILED_TRANSACTION;
271 Return<void> ret;
272 if (cmdCode == EFFECT_CMD_GET_CONFIG) {
273 ret = mEffect->getConfig([&] (Result r, const EffectConfig &hidlConfig) {
274 result = analyzeResult(r);
275 if (r == Result::OK) {
276 effectConfigToHal(hidlConfig, static_cast<effect_config_t*>(pReplyData));
277 }
278 });
279 } else {
280 ret = mEffect->getConfigReverse([&] (Result r, const EffectConfig &hidlConfig) {
281 result = analyzeResult(r);
282 if (r == Result::OK) {
283 effectConfigToHal(hidlConfig, static_cast<effect_config_t*>(pReplyData));
284 }
285 });
286 }
287 if (!ret.isOk()) {
288 result = FAILED_TRANSACTION;
289 }
290 return result;
291}
292
Mikhail Naganovf508bd42017-02-16 13:51:20 -0800293status_t EffectHalHidl::setConfigImpl(
294 uint32_t cmdCode, uint32_t cmdSize, void *pCmdData, uint32_t *replySize, void *pReplyData) {
295 if (pCmdData == NULL || cmdSize != sizeof(effect_config_t) ||
296 replySize == NULL || *replySize != sizeof(int32_t) || pReplyData == NULL) {
297 return BAD_VALUE;
298 }
299 const effect_config_t *halConfig = static_cast<effect_config_t*>(pCmdData);
300 if (halConfig->inputCfg.bufferProvider.getBuffer != NULL ||
301 halConfig->inputCfg.bufferProvider.releaseBuffer != NULL ||
302 halConfig->outputCfg.bufferProvider.getBuffer != NULL ||
303 halConfig->outputCfg.bufferProvider.releaseBuffer != NULL) {
304 ALOGE("Buffer provider callbacks are not supported");
305 }
306 EffectConfig hidlConfig;
307 effectConfigFromHal(*halConfig, &hidlConfig);
308 Return<Result> ret = cmdCode == EFFECT_CMD_SET_CONFIG ?
309 mEffect->setConfig(hidlConfig, nullptr, nullptr) :
310 mEffect->setConfigReverse(hidlConfig, nullptr, nullptr);
311 status_t result = FAILED_TRANSACTION;
312 if (ret.isOk()) {
313 result = analyzeResult(ret);
314 *static_cast<int32_t*>(pReplyData) = result;
315 }
316 return result;
317}
318
Mikhail Naganovf558e022016-11-14 17:45:17 -0800319} // namespace android