blob: 487bbe6a5e5bcb771b603905452ed03b8ff5cb9f [file] [log] [blame]
Mikhail Naganov7cbf2f12016-10-27 20:05:35 -07001/*
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
Mikhail Naganov7cbf2f12016-10-27 20:05:35 -070017#include <memory.h>
18
19#define LOG_TAG "EffectHAL"
Mikhail Naganovb0abafb2017-01-31 17:24:48 -080020#define ATRACE_TAG ATRACE_TAG_AUDIO
21
Yifan Hongf9d30342016-11-30 13:45:34 -080022#include <android/log.h>
Mikhail Naganova331de12017-01-04 16:33:55 -080023#include <media/EffectsFactoryApi.h>
Mikhail Naganovb0abafb2017-01-31 17:24:48 -080024#include <utils/Trace.h>
Mikhail Naganov7cbf2f12016-10-27 20:05:35 -070025
26#include "Conversions.h"
27#include "Effect.h"
Kevin Rocard6891d7e2017-12-14 18:39:39 -080028#include "common/all-versions/default/EffectMap.h"
Mikhail Naganov7cbf2f12016-10-27 20:05:35 -070029
30namespace android {
31namespace hardware {
32namespace audio {
33namespace effect {
34namespace V2_0 {
35namespace implementation {
36
37using ::android::hardware::audio::common::V2_0::AudioChannelMask;
38using ::android::hardware::audio::common::V2_0::AudioFormat;
Mikhail Naganova331de12017-01-04 16:33:55 -080039using ::android::hardware::audio::effect::V2_0::MessageQueueFlagBits;
40
41namespace {
42
43class ProcessThread : public Thread {
Kevin Rocard22505e62017-12-14 18:50:12 -080044 public:
Mikhail Naganova331de12017-01-04 16:33:55 -080045 // ProcessThread's lifespan never exceeds Effect's lifespan.
Kevin Rocard22505e62017-12-14 18:50:12 -080046 ProcessThread(std::atomic<bool>* stop, effect_handle_t effect,
47 std::atomic<audio_buffer_t*>* inBuffer, std::atomic<audio_buffer_t*>* outBuffer,
48 Effect::StatusMQ* statusMQ, EventFlag* efGroup)
49 : Thread(false /*canCallJava*/),
50 mStop(stop),
51 mEffect(effect),
52 mHasProcessReverse((*mEffect)->process_reverse != NULL),
53 mInBuffer(inBuffer),
54 mOutBuffer(outBuffer),
55 mStatusMQ(statusMQ),
56 mEfGroup(efGroup) {}
Mikhail Naganova331de12017-01-04 16:33:55 -080057 virtual ~ProcessThread() {}
58
Kevin Rocard22505e62017-12-14 18:50:12 -080059 private:
Mikhail Naganova331de12017-01-04 16:33:55 -080060 std::atomic<bool>* mStop;
61 effect_handle_t mEffect;
62 bool mHasProcessReverse;
63 std::atomic<audio_buffer_t*>* mInBuffer;
64 std::atomic<audio_buffer_t*>* mOutBuffer;
65 Effect::StatusMQ* mStatusMQ;
66 EventFlag* mEfGroup;
67
68 bool threadLoop() override;
69};
70
71bool ProcessThread::threadLoop() {
72 // This implementation doesn't return control back to the Thread until it decides to stop,
73 // as the Thread uses mutexes, and this can lead to priority inversion.
Kevin Rocard22505e62017-12-14 18:50:12 -080074 while (!std::atomic_load_explicit(mStop, std::memory_order_acquire)) {
Mikhail Naganova331de12017-01-04 16:33:55 -080075 uint32_t efState = 0;
Mikhail Naganove8674562017-02-10 08:37:19 -080076 mEfGroup->wait(static_cast<uint32_t>(MessageQueueFlagBits::REQUEST_PROCESS_ALL), &efState);
Kevin Rocard22505e62017-12-14 18:50:12 -080077 if (!(efState & static_cast<uint32_t>(MessageQueueFlagBits::REQUEST_PROCESS_ALL)) ||
78 (efState & static_cast<uint32_t>(MessageQueueFlagBits::REQUEST_QUIT))) {
Mikhail Naganovb0abafb2017-01-31 17:24:48 -080079 continue; // Nothing to do or time to quit.
Mikhail Naganova331de12017-01-04 16:33:55 -080080 }
81 Result retval = Result::OK;
Kevin Rocard22505e62017-12-14 18:50:12 -080082 if (efState & static_cast<uint32_t>(MessageQueueFlagBits::REQUEST_PROCESS_REVERSE) &&
83 !mHasProcessReverse) {
Mikhail Naganova331de12017-01-04 16:33:55 -080084 retval = Result::NOT_SUPPORTED;
85 }
86
87 if (retval == Result::OK) {
88 // affects both buffer pointers and their contents.
89 std::atomic_thread_fence(std::memory_order_acquire);
90 int32_t processResult;
91 audio_buffer_t* inBuffer =
Kevin Rocard22505e62017-12-14 18:50:12 -080092 std::atomic_load_explicit(mInBuffer, std::memory_order_relaxed);
Mikhail Naganova331de12017-01-04 16:33:55 -080093 audio_buffer_t* outBuffer =
Kevin Rocard22505e62017-12-14 18:50:12 -080094 std::atomic_load_explicit(mOutBuffer, std::memory_order_relaxed);
Mikhail Naganova331de12017-01-04 16:33:55 -080095 if (inBuffer != nullptr && outBuffer != nullptr) {
96 if (efState & static_cast<uint32_t>(MessageQueueFlagBits::REQUEST_PROCESS)) {
97 processResult = (*mEffect)->process(mEffect, inBuffer, outBuffer);
98 } else {
99 processResult = (*mEffect)->process_reverse(mEffect, inBuffer, outBuffer);
100 }
101 std::atomic_thread_fence(std::memory_order_release);
102 } else {
103 ALOGE("processing buffers were not set before calling 'process'");
104 processResult = -ENODEV;
105 }
Kevin Rocard22505e62017-12-14 18:50:12 -0800106 switch (processResult) {
107 case 0:
108 retval = Result::OK;
109 break;
110 case -ENODATA:
111 retval = Result::INVALID_STATE;
112 break;
113 case -EINVAL:
114 retval = Result::INVALID_ARGUMENTS;
115 break;
116 default:
117 retval = Result::NOT_INITIALIZED;
Mikhail Naganova331de12017-01-04 16:33:55 -0800118 }
119 }
120 if (!mStatusMQ->write(&retval)) {
121 ALOGW("status message queue write failed");
122 }
123 mEfGroup->wake(static_cast<uint32_t>(MessageQueueFlagBits::DONE_PROCESSING));
124 }
125
126 return false;
127}
128
129} // namespace
Mikhail Naganov7cbf2f12016-10-27 20:05:35 -0700130
131// static
Kevin Rocard22505e62017-12-14 18:50:12 -0800132const char* Effect::sContextResultOfCommand = "returned status";
133const char* Effect::sContextCallToCommand = "error";
134const char* Effect::sContextCallFunction = sContextCallToCommand;
Mikhail Naganov7cbf2f12016-10-27 20:05:35 -0700135
Mikhail Naganova331de12017-01-04 16:33:55 -0800136Effect::Effect(effect_handle_t handle)
Kevin Rocard22505e62017-12-14 18:50:12 -0800137 : mIsClosed(false), mHandle(handle), mEfGroup(nullptr), mStopProcessThread(false) {}
Mikhail Naganov7cbf2f12016-10-27 20:05:35 -0700138
139Effect::~Effect() {
Mikhail Naganovb0abafb2017-01-31 17:24:48 -0800140 ATRACE_CALL();
Mikhail Naganova331de12017-01-04 16:33:55 -0800141 close();
Mikhail Naganovb0abafb2017-01-31 17:24:48 -0800142 if (mProcessThread.get()) {
143 ATRACE_NAME("mProcessThread->join");
144 status_t status = mProcessThread->join();
145 ALOGE_IF(status, "processing thread exit error: %s", strerror(-status));
146 }
147 if (mEfGroup) {
148 status_t status = EventFlag::deleteEventFlag(&mEfGroup);
149 ALOGE_IF(status, "processing MQ event flag deletion error: %s", strerror(-status));
150 }
151 mInBuffer.clear();
152 mOutBuffer.clear();
153 int status = EffectRelease(mHandle);
154 ALOGW_IF(status, "Error releasing effect %p: %s", mHandle, strerror(-status));
155 EffectMap::getInstance().remove(mHandle);
156 mHandle = 0;
Mikhail Naganov7cbf2f12016-10-27 20:05:35 -0700157}
158
159// static
Kevin Rocard22505e62017-12-14 18:50:12 -0800160template <typename T>
161size_t Effect::alignedSizeIn(size_t s) {
Mikhail Naganov7cbf2f12016-10-27 20:05:35 -0700162 return (s + sizeof(T) - 1) / sizeof(T);
163}
164
165// static
Kevin Rocard22505e62017-12-14 18:50:12 -0800166template <typename T>
167std::unique_ptr<uint8_t[]> Effect::hidlVecToHal(const hidl_vec<T>& vec, uint32_t* halDataSize) {
Mikhail Naganov6e81e9b2016-11-16 16:30:17 -0800168 // Due to bugs in HAL, they may attempt to write into the provided
169 // input buffer. The original binder buffer is r/o, thus it is needed
170 // to create a r/w version.
171 *halDataSize = vec.size() * sizeof(T);
172 std::unique_ptr<uint8_t[]> halData(new uint8_t[*halDataSize]);
173 memcpy(&halData[0], &vec[0], *halDataSize);
174 return halData;
Mikhail Naganov7cbf2f12016-10-27 20:05:35 -0700175}
176
177// static
Kevin Rocard22505e62017-12-14 18:50:12 -0800178void Effect::effectAuxChannelsConfigFromHal(const channel_config_t& halConfig,
179 EffectAuxChannelsConfig* config) {
Mikhail Naganov7cbf2f12016-10-27 20:05:35 -0700180 config->mainChannels = AudioChannelMask(halConfig.main_channels);
181 config->auxChannels = AudioChannelMask(halConfig.aux_channels);
182}
183
184// static
Kevin Rocard22505e62017-12-14 18:50:12 -0800185void Effect::effectAuxChannelsConfigToHal(const EffectAuxChannelsConfig& config,
186 channel_config_t* halConfig) {
Mikhail Naganov7cbf2f12016-10-27 20:05:35 -0700187 halConfig->main_channels = static_cast<audio_channel_mask_t>(config.mainChannels);
188 halConfig->aux_channels = static_cast<audio_channel_mask_t>(config.auxChannels);
189}
190
191// static
Kevin Rocard22505e62017-12-14 18:50:12 -0800192void Effect::effectBufferConfigFromHal(const buffer_config_t& halConfig,
193 EffectBufferConfig* config) {
Mikhail Naganov9f289042017-02-23 08:39:36 -0800194 config->buffer.id = 0;
195 config->buffer.frameCount = 0;
Mikhail Naganov7cbf2f12016-10-27 20:05:35 -0700196 config->samplingRateHz = halConfig.samplingRate;
197 config->channels = AudioChannelMask(halConfig.channels);
198 config->format = AudioFormat(halConfig.format);
199 config->accessMode = EffectBufferAccess(halConfig.accessMode);
200 config->mask = EffectConfigParameters(halConfig.mask);
201}
202
203// static
204void Effect::effectBufferConfigToHal(const EffectBufferConfig& config, buffer_config_t* halConfig) {
Mikhail Naganova331de12017-01-04 16:33:55 -0800205 // Note: setting the buffers directly is considered obsolete. They need to be set
206 // using 'setProcessBuffers'.
Mikhail Naganov7cbf2f12016-10-27 20:05:35 -0700207 halConfig->buffer.frameCount = 0;
208 halConfig->buffer.raw = NULL;
209 halConfig->samplingRate = config.samplingRateHz;
210 halConfig->channels = static_cast<uint32_t>(config.channels);
Mikhail Naganovb0dd0762017-03-22 10:36:14 -0700211 // Note: The framework code does not use BP.
Mikhail Naganov7cbf2f12016-10-27 20:05:35 -0700212 halConfig->bufferProvider.cookie = NULL;
213 halConfig->bufferProvider.getBuffer = NULL;
214 halConfig->bufferProvider.releaseBuffer = NULL;
215 halConfig->format = static_cast<uint8_t>(config.format);
216 halConfig->accessMode = static_cast<uint8_t>(config.accessMode);
217 halConfig->mask = static_cast<uint8_t>(config.mask);
218}
219
220// static
221void Effect::effectConfigFromHal(const effect_config_t& halConfig, EffectConfig* config) {
222 effectBufferConfigFromHal(halConfig.inputCfg, &config->inputCfg);
223 effectBufferConfigFromHal(halConfig.outputCfg, &config->outputCfg);
224}
225
226// static
227void Effect::effectConfigToHal(const EffectConfig& config, effect_config_t* halConfig) {
228 effectBufferConfigToHal(config.inputCfg, &halConfig->inputCfg);
229 effectBufferConfigToHal(config.outputCfg, &halConfig->outputCfg);
230}
231
232// static
Kevin Rocard22505e62017-12-14 18:50:12 -0800233void Effect::effectOffloadParamToHal(const EffectOffloadParameter& offload,
234 effect_offload_param_t* halOffload) {
Mikhail Naganov7cbf2f12016-10-27 20:05:35 -0700235 halOffload->isOffload = offload.isOffload;
236 halOffload->ioHandle = offload.ioHandle;
237}
238
239// static
Kevin Rocard22505e62017-12-14 18:50:12 -0800240std::vector<uint8_t> Effect::parameterToHal(uint32_t paramSize, const void* paramData,
241 uint32_t valueSize, const void** valueData) {
Mikhail Naganov7cbf2f12016-10-27 20:05:35 -0700242 size_t valueOffsetFromData = alignedSizeIn<uint32_t>(paramSize) * sizeof(uint32_t);
243 size_t halParamBufferSize = sizeof(effect_param_t) + valueOffsetFromData + valueSize;
244 std::vector<uint8_t> halParamBuffer(halParamBufferSize, 0);
Kevin Rocard22505e62017-12-14 18:50:12 -0800245 effect_param_t* halParam = reinterpret_cast<effect_param_t*>(&halParamBuffer[0]);
Mikhail Naganov7cbf2f12016-10-27 20:05:35 -0700246 halParam->psize = paramSize;
247 halParam->vsize = valueSize;
248 memcpy(halParam->data, paramData, paramSize);
249 if (valueData) {
250 if (*valueData) {
251 // Value data is provided.
252 memcpy(halParam->data + valueOffsetFromData, *valueData, valueSize);
253 } else {
254 // The caller needs the pointer to the value data location.
255 *valueData = halParam->data + valueOffsetFromData;
256 }
257 }
258 return halParamBuffer;
259}
260
261Result Effect::analyzeCommandStatus(const char* commandName, const char* context, status_t status) {
262 return analyzeStatus("command", commandName, context, status);
263}
264
Kevin Rocard22505e62017-12-14 18:50:12 -0800265Result Effect::analyzeStatus(const char* funcName, const char* subFuncName,
266 const char* contextDescription, status_t status) {
Mikhail Naganov7cbf2f12016-10-27 20:05:35 -0700267 if (status != OK) {
Kevin Rocard22505e62017-12-14 18:50:12 -0800268 ALOGW("Effect %p %s %s %s: %s", mHandle, funcName, subFuncName, contextDescription,
269 strerror(-status));
Mikhail Naganov7cbf2f12016-10-27 20:05:35 -0700270 }
271 switch (status) {
Kevin Rocard22505e62017-12-14 18:50:12 -0800272 case OK:
273 return Result::OK;
274 case -EINVAL:
275 return Result::INVALID_ARGUMENTS;
276 case -ENODATA:
277 return Result::INVALID_STATE;
278 case -ENODEV:
279 return Result::NOT_INITIALIZED;
280 case -ENOMEM:
281 return Result::RESULT_TOO_BIG;
282 case -ENOSYS:
283 return Result::NOT_SUPPORTED;
284 default:
285 return Result::INVALID_STATE;
Mikhail Naganov7cbf2f12016-10-27 20:05:35 -0700286 }
287}
288
289void Effect::getConfigImpl(int commandCode, const char* commandName, GetConfigCallback cb) {
290 uint32_t halResultSize = sizeof(effect_config_t);
Mikhail Naganov9f289042017-02-23 08:39:36 -0800291 effect_config_t halConfig{};
Kevin Rocard22505e62017-12-14 18:50:12 -0800292 status_t status =
293 (*mHandle)->command(mHandle, commandCode, 0, NULL, &halResultSize, &halConfig);
Mikhail Naganov7cbf2f12016-10-27 20:05:35 -0700294 EffectConfig config;
295 if (status == OK) {
296 effectConfigFromHal(halConfig, &config);
297 }
298 cb(analyzeCommandStatus(commandName, sContextCallToCommand, status), config);
299}
300
Kevin Rocard22505e62017-12-14 18:50:12 -0800301Result Effect::getCurrentConfigImpl(uint32_t featureId, uint32_t configSize,
302 GetCurrentConfigSuccessCallback onSuccess) {
Mikhail Naganov7cbf2f12016-10-27 20:05:35 -0700303 uint32_t halCmd = featureId;
304 uint32_t halResult[alignedSizeIn<uint32_t>(sizeof(uint32_t) + configSize)];
305 memset(halResult, 0, sizeof(halResult));
306 uint32_t halResultSize = 0;
Kevin Rocard22505e62017-12-14 18:50:12 -0800307 return sendCommandReturningStatusAndData(EFFECT_CMD_GET_FEATURE_CONFIG, "GET_FEATURE_CONFIG",
308 sizeof(uint32_t), &halCmd, &halResultSize, halResult,
309 sizeof(uint32_t), [&] { onSuccess(&halResult[1]); });
Mikhail Naganov7cbf2f12016-10-27 20:05:35 -0700310}
311
Kevin Rocard22505e62017-12-14 18:50:12 -0800312Result Effect::getParameterImpl(uint32_t paramSize, const void* paramData,
313 uint32_t requestValueSize, uint32_t replyValueSize,
314 GetParameterSuccessCallback onSuccess) {
Mikhail Naganov7cbf2f12016-10-27 20:05:35 -0700315 // As it is unknown what method HAL uses for copying the provided parameter data,
316 // it is safer to make sure that input and output buffers do not overlap.
317 std::vector<uint8_t> halCmdBuffer =
Kevin Rocard22505e62017-12-14 18:50:12 -0800318 parameterToHal(paramSize, paramData, requestValueSize, nullptr);
319 const void* valueData = nullptr;
Mikhail Naganov7cbf2f12016-10-27 20:05:35 -0700320 std::vector<uint8_t> halParamBuffer =
Kevin Rocard22505e62017-12-14 18:50:12 -0800321 parameterToHal(paramSize, paramData, replyValueSize, &valueData);
Mikhail Naganov7cbf2f12016-10-27 20:05:35 -0700322 uint32_t halParamBufferSize = halParamBuffer.size();
323
324 return sendCommandReturningStatusAndData(
Kevin Rocard22505e62017-12-14 18:50:12 -0800325 EFFECT_CMD_GET_PARAM, "GET_PARAM", halCmdBuffer.size(), &halCmdBuffer[0],
326 &halParamBufferSize, &halParamBuffer[0], sizeof(effect_param_t), [&] {
327 effect_param_t* halParam = reinterpret_cast<effect_param_t*>(&halParamBuffer[0]);
328 onSuccess(halParam->vsize, valueData);
329 });
Mikhail Naganov7cbf2f12016-10-27 20:05:35 -0700330}
331
Kevin Rocard22505e62017-12-14 18:50:12 -0800332Result Effect::getSupportedConfigsImpl(uint32_t featureId, uint32_t maxConfigs, uint32_t configSize,
333 GetSupportedConfigsSuccessCallback onSuccess) {
334 uint32_t halCmd[2] = {featureId, maxConfigs};
Mikhail Naganov7cbf2f12016-10-27 20:05:35 -0700335 uint32_t halResultSize = 2 * sizeof(uint32_t) + maxConfigs * sizeof(configSize);
336 uint8_t halResult[halResultSize];
337 memset(&halResult[0], 0, halResultSize);
338 return sendCommandReturningStatusAndData(
Kevin Rocard22505e62017-12-14 18:50:12 -0800339 EFFECT_CMD_GET_FEATURE_SUPPORTED_CONFIGS, "GET_FEATURE_SUPPORTED_CONFIGS", sizeof(halCmd),
340 halCmd, &halResultSize, &halResult[0], 2 * sizeof(uint32_t), [&] {
341 uint32_t* halResult32 = reinterpret_cast<uint32_t*>(&halResult[0]);
342 uint32_t supportedConfigs = *(++halResult32); // skip status field
343 if (supportedConfigs > maxConfigs) supportedConfigs = maxConfigs;
344 onSuccess(supportedConfigs, ++halResult32);
345 });
Mikhail Naganov7cbf2f12016-10-27 20:05:35 -0700346}
347
Mikhail Naganova331de12017-01-04 16:33:55 -0800348Return<void> Effect::prepareForProcessing(prepareForProcessing_cb _hidl_cb) {
349 status_t status;
350 // Create message queue.
351 if (mStatusMQ) {
352 ALOGE("the client attempts to call prepareForProcessing_cb twice");
353 _hidl_cb(Result::INVALID_STATE, StatusMQ::Descriptor());
354 return Void();
Mikhail Naganov7cbf2f12016-10-27 20:05:35 -0700355 }
Mikhail Naganova331de12017-01-04 16:33:55 -0800356 std::unique_ptr<StatusMQ> tempStatusMQ(new StatusMQ(1, true /*EventFlag*/));
357 if (!tempStatusMQ->isValid()) {
358 ALOGE_IF(!tempStatusMQ->isValid(), "status MQ is invalid");
359 _hidl_cb(Result::INVALID_ARGUMENTS, StatusMQ::Descriptor());
360 return Void();
361 }
362 status = EventFlag::createEventFlag(tempStatusMQ->getEventFlagWord(), &mEfGroup);
363 if (status != OK || !mEfGroup) {
364 ALOGE("failed creating event flag for status MQ: %s", strerror(-status));
365 _hidl_cb(Result::INVALID_ARGUMENTS, StatusMQ::Descriptor());
366 return Void();
367 }
368
369 // Create and launch the thread.
Kevin Rocard22505e62017-12-14 18:50:12 -0800370 mProcessThread = new ProcessThread(&mStopProcessThread, mHandle, &mHalInBufferPtr,
371 &mHalOutBufferPtr, tempStatusMQ.get(), mEfGroup);
Mikhail Naganova331de12017-01-04 16:33:55 -0800372 status = mProcessThread->run("effect", PRIORITY_URGENT_AUDIO);
373 if (status != OK) {
374 ALOGW("failed to start effect processing thread: %s", strerror(-status));
375 _hidl_cb(Result::INVALID_ARGUMENTS, MQDescriptorSync<Result>());
376 return Void();
377 }
378
379 mStatusMQ = std::move(tempStatusMQ);
380 _hidl_cb(Result::OK, *mStatusMQ->getDesc());
381 return Void();
382}
383
Kevin Rocard22505e62017-12-14 18:50:12 -0800384Return<Result> Effect::setProcessBuffers(const AudioBuffer& inBuffer,
385 const AudioBuffer& outBuffer) {
Mikhail Naganova331de12017-01-04 16:33:55 -0800386 AudioBufferManager& manager = AudioBufferManager::getInstance();
387 sp<AudioBufferWrapper> tempInBuffer, tempOutBuffer;
388 if (!manager.wrap(inBuffer, &tempInBuffer)) {
389 ALOGE("Could not map memory of the input buffer");
390 return Result::INVALID_ARGUMENTS;
391 }
392 if (!manager.wrap(outBuffer, &tempOutBuffer)) {
393 ALOGE("Could not map memory of the output buffer");
394 return Result::INVALID_ARGUMENTS;
395 }
396 mInBuffer = tempInBuffer;
397 mOutBuffer = tempOutBuffer;
398 // The processing thread only reads these pointers after waking up by an event flag,
399 // so it's OK to update the pair non-atomically.
400 mHalInBufferPtr.store(mInBuffer->getHalBuffer(), std::memory_order_release);
401 mHalOutBufferPtr.store(mOutBuffer->getHalBuffer(), std::memory_order_release);
402 return Result::OK;
Mikhail Naganov7cbf2f12016-10-27 20:05:35 -0700403}
404
405Result Effect::sendCommand(int commandCode, const char* commandName) {
406 return sendCommand(commandCode, commandName, 0, NULL);
407}
408
Kevin Rocard22505e62017-12-14 18:50:12 -0800409Result Effect::sendCommand(int commandCode, const char* commandName, uint32_t size, void* data) {
Mikhail Naganov7cbf2f12016-10-27 20:05:35 -0700410 status_t status = (*mHandle)->command(mHandle, commandCode, size, data, 0, NULL);
411 return analyzeCommandStatus(commandName, sContextCallToCommand, status);
412}
413
Kevin Rocard22505e62017-12-14 18:50:12 -0800414Result Effect::sendCommandReturningData(int commandCode, const char* commandName,
415 uint32_t* replySize, void* replyData) {
Mikhail Naganov7cbf2f12016-10-27 20:05:35 -0700416 return sendCommandReturningData(commandCode, commandName, 0, NULL, replySize, replyData);
417}
418
Kevin Rocard22505e62017-12-14 18:50:12 -0800419Result Effect::sendCommandReturningData(int commandCode, const char* commandName, uint32_t size,
420 void* data, uint32_t* replySize, void* replyData) {
Mikhail Naganov7cbf2f12016-10-27 20:05:35 -0700421 uint32_t expectedReplySize = *replySize;
422 status_t status = (*mHandle)->command(mHandle, commandCode, size, data, replySize, replyData);
423 if (status == OK && *replySize != expectedReplySize) {
424 status = -ENODATA;
425 }
426 return analyzeCommandStatus(commandName, sContextCallToCommand, status);
427}
428
429Result Effect::sendCommandReturningStatus(int commandCode, const char* commandName) {
430 return sendCommandReturningStatus(commandCode, commandName, 0, NULL);
431}
432
Kevin Rocard22505e62017-12-14 18:50:12 -0800433Result Effect::sendCommandReturningStatus(int commandCode, const char* commandName, uint32_t size,
434 void* data) {
Mikhail Naganov7cbf2f12016-10-27 20:05:35 -0700435 uint32_t replyCmdStatus;
436 uint32_t replySize = sizeof(uint32_t);
Kevin Rocard22505e62017-12-14 18:50:12 -0800437 return sendCommandReturningStatusAndData(commandCode, commandName, size, data, &replySize,
438 &replyCmdStatus, replySize, [] {});
Mikhail Naganov7cbf2f12016-10-27 20:05:35 -0700439}
440
Kevin Rocard22505e62017-12-14 18:50:12 -0800441Result Effect::sendCommandReturningStatusAndData(int commandCode, const char* commandName,
442 uint32_t size, void* data, uint32_t* replySize,
443 void* replyData, uint32_t minReplySize,
444 CommandSuccessCallback onSuccess) {
445 status_t status = (*mHandle)->command(mHandle, commandCode, size, data, replySize, replyData);
Mikhail Naganov7cbf2f12016-10-27 20:05:35 -0700446 Result retval;
447 if (status == OK && minReplySize >= sizeof(uint32_t) && *replySize >= minReplySize) {
448 uint32_t commandStatus = *reinterpret_cast<uint32_t*>(replyData);
449 retval = analyzeCommandStatus(commandName, sContextResultOfCommand, commandStatus);
450 if (commandStatus == OK) {
451 onSuccess();
452 }
453 } else {
454 retval = analyzeCommandStatus(commandName, sContextCallToCommand, status);
455 }
456 return retval;
457}
458
Kevin Rocard22505e62017-12-14 18:50:12 -0800459Result Effect::setConfigImpl(int commandCode, const char* commandName, const EffectConfig& config,
460 const sp<IEffectBufferProviderCallback>& inputBufferProvider,
461 const sp<IEffectBufferProviderCallback>& outputBufferProvider) {
Mikhail Naganov7cbf2f12016-10-27 20:05:35 -0700462 effect_config_t halConfig;
463 effectConfigToHal(config, &halConfig);
464 if (inputBufferProvider != 0) {
465 LOG_FATAL("Using input buffer provider is not supported");
466 }
467 if (outputBufferProvider != 0) {
468 LOG_FATAL("Using output buffer provider is not supported");
469 }
Kevin Rocard22505e62017-12-14 18:50:12 -0800470 return sendCommandReturningStatus(commandCode, commandName, sizeof(effect_config_t),
471 &halConfig);
Mikhail Naganov7cbf2f12016-10-27 20:05:35 -0700472}
473
Kevin Rocard22505e62017-12-14 18:50:12 -0800474Result Effect::setParameterImpl(uint32_t paramSize, const void* paramData, uint32_t valueSize,
475 const void* valueData) {
476 std::vector<uint8_t> halParamBuffer =
477 parameterToHal(paramSize, paramData, valueSize, &valueData);
478 return sendCommandReturningStatus(EFFECT_CMD_SET_PARAM, "SET_PARAM", halParamBuffer.size(),
479 &halParamBuffer[0]);
Mikhail Naganov7cbf2f12016-10-27 20:05:35 -0700480}
481
482// Methods from ::android::hardware::audio::effect::V2_0::IEffect follow.
Kevin Rocard22505e62017-12-14 18:50:12 -0800483Return<Result> Effect::init() {
Mikhail Naganov7cbf2f12016-10-27 20:05:35 -0700484 return sendCommandReturningStatus(EFFECT_CMD_INIT, "INIT");
485}
486
Kevin Rocard22505e62017-12-14 18:50:12 -0800487Return<Result> Effect::setConfig(const EffectConfig& config,
488 const sp<IEffectBufferProviderCallback>& inputBufferProvider,
489 const sp<IEffectBufferProviderCallback>& outputBufferProvider) {
490 return setConfigImpl(EFFECT_CMD_SET_CONFIG, "SET_CONFIG", config, inputBufferProvider,
491 outputBufferProvider);
Mikhail Naganov7cbf2f12016-10-27 20:05:35 -0700492}
493
Kevin Rocard22505e62017-12-14 18:50:12 -0800494Return<Result> Effect::reset() {
Mikhail Naganov7cbf2f12016-10-27 20:05:35 -0700495 return sendCommand(EFFECT_CMD_RESET, "RESET");
496}
497
Kevin Rocard22505e62017-12-14 18:50:12 -0800498Return<Result> Effect::enable() {
Mikhail Naganov7cbf2f12016-10-27 20:05:35 -0700499 return sendCommandReturningStatus(EFFECT_CMD_ENABLE, "ENABLE");
500}
501
Kevin Rocard22505e62017-12-14 18:50:12 -0800502Return<Result> Effect::disable() {
Mikhail Naganov7cbf2f12016-10-27 20:05:35 -0700503 return sendCommandReturningStatus(EFFECT_CMD_DISABLE, "DISABLE");
504}
505
Kevin Rocard22505e62017-12-14 18:50:12 -0800506Return<Result> Effect::setDevice(AudioDevice device) {
Mikhail Naganov7cbf2f12016-10-27 20:05:35 -0700507 uint32_t halDevice = static_cast<uint32_t>(device);
508 return sendCommand(EFFECT_CMD_SET_DEVICE, "SET_DEVICE", sizeof(uint32_t), &halDevice);
509}
510
Kevin Rocard22505e62017-12-14 18:50:12 -0800511Return<void> Effect::setAndGetVolume(const hidl_vec<uint32_t>& volumes,
512 setAndGetVolume_cb _hidl_cb) {
Mikhail Naganov7cbf2f12016-10-27 20:05:35 -0700513 uint32_t halDataSize;
Mikhail Naganov6e81e9b2016-11-16 16:30:17 -0800514 std::unique_ptr<uint8_t[]> halData = hidlVecToHal(volumes, &halDataSize);
Mikhail Naganov7cbf2f12016-10-27 20:05:35 -0700515 uint32_t halResultSize = halDataSize;
516 uint32_t halResult[volumes.size()];
Kevin Rocard22505e62017-12-14 18:50:12 -0800517 Result retval = sendCommandReturningData(EFFECT_CMD_SET_VOLUME, "SET_VOLUME", halDataSize,
518 &halData[0], &halResultSize, halResult);
Mikhail Naganov7cbf2f12016-10-27 20:05:35 -0700519 hidl_vec<uint32_t> result;
520 if (retval == Result::OK) {
521 result.setToExternal(&halResult[0], halResultSize);
522 }
523 _hidl_cb(retval, result);
524 return Void();
525}
526
Kevin Rocard22505e62017-12-14 18:50:12 -0800527Return<Result> Effect::volumeChangeNotification(const hidl_vec<uint32_t>& volumes) {
Mikhail Naganovf4f2ff32017-01-19 12:38:39 -0800528 uint32_t halDataSize;
529 std::unique_ptr<uint8_t[]> halData = hidlVecToHal(volumes, &halDataSize);
Kevin Rocard22505e62017-12-14 18:50:12 -0800530 return sendCommand(EFFECT_CMD_SET_VOLUME, "SET_VOLUME", halDataSize, &halData[0]);
Mikhail Naganovf4f2ff32017-01-19 12:38:39 -0800531}
532
Kevin Rocard22505e62017-12-14 18:50:12 -0800533Return<Result> Effect::setAudioMode(AudioMode mode) {
Mikhail Naganov7cbf2f12016-10-27 20:05:35 -0700534 uint32_t halMode = static_cast<uint32_t>(mode);
Kevin Rocard22505e62017-12-14 18:50:12 -0800535 return sendCommand(EFFECT_CMD_SET_AUDIO_MODE, "SET_AUDIO_MODE", sizeof(uint32_t), &halMode);
Mikhail Naganov7cbf2f12016-10-27 20:05:35 -0700536}
537
538Return<Result> Effect::setConfigReverse(
Kevin Rocard22505e62017-12-14 18:50:12 -0800539 const EffectConfig& config, const sp<IEffectBufferProviderCallback>& inputBufferProvider,
540 const sp<IEffectBufferProviderCallback>& outputBufferProvider) {
541 return setConfigImpl(EFFECT_CMD_SET_CONFIG_REVERSE, "SET_CONFIG_REVERSE", config,
542 inputBufferProvider, outputBufferProvider);
Mikhail Naganov7cbf2f12016-10-27 20:05:35 -0700543}
544
Kevin Rocard22505e62017-12-14 18:50:12 -0800545Return<Result> Effect::setInputDevice(AudioDevice device) {
Mikhail Naganov7cbf2f12016-10-27 20:05:35 -0700546 uint32_t halDevice = static_cast<uint32_t>(device);
Kevin Rocard22505e62017-12-14 18:50:12 -0800547 return sendCommand(EFFECT_CMD_SET_INPUT_DEVICE, "SET_INPUT_DEVICE", sizeof(uint32_t),
548 &halDevice);
Mikhail Naganov7cbf2f12016-10-27 20:05:35 -0700549}
550
Kevin Rocard22505e62017-12-14 18:50:12 -0800551Return<void> Effect::getConfig(getConfig_cb _hidl_cb) {
Mikhail Naganov7cbf2f12016-10-27 20:05:35 -0700552 getConfigImpl(EFFECT_CMD_GET_CONFIG, "GET_CONFIG", _hidl_cb);
553 return Void();
554}
555
Kevin Rocard22505e62017-12-14 18:50:12 -0800556Return<void> Effect::getConfigReverse(getConfigReverse_cb _hidl_cb) {
Mikhail Naganov7cbf2f12016-10-27 20:05:35 -0700557 getConfigImpl(EFFECT_CMD_GET_CONFIG_REVERSE, "GET_CONFIG_REVERSE", _hidl_cb);
558 return Void();
559}
560
Kevin Rocard22505e62017-12-14 18:50:12 -0800561Return<void> Effect::getSupportedAuxChannelsConfigs(uint32_t maxConfigs,
562 getSupportedAuxChannelsConfigs_cb _hidl_cb) {
Mikhail Naganov7cbf2f12016-10-27 20:05:35 -0700563 hidl_vec<EffectAuxChannelsConfig> result;
564 Result retval = getSupportedConfigsImpl(
Kevin Rocard22505e62017-12-14 18:50:12 -0800565 EFFECT_FEATURE_AUX_CHANNELS, maxConfigs, sizeof(channel_config_t),
566 [&](uint32_t supportedConfigs, void* configsData) {
567 result.resize(supportedConfigs);
568 channel_config_t* config = reinterpret_cast<channel_config_t*>(configsData);
569 for (size_t i = 0; i < result.size(); ++i) {
570 effectAuxChannelsConfigFromHal(*config++, &result[i]);
571 }
572 });
Mikhail Naganov7cbf2f12016-10-27 20:05:35 -0700573 _hidl_cb(retval, result);
574 return Void();
575}
576
Kevin Rocard22505e62017-12-14 18:50:12 -0800577Return<void> Effect::getAuxChannelsConfig(getAuxChannelsConfig_cb _hidl_cb) {
Mikhail Naganov7cbf2f12016-10-27 20:05:35 -0700578 uint32_t halResult[alignedSizeIn<uint32_t>(sizeof(uint32_t) + sizeof(channel_config_t))];
579 memset(halResult, 0, sizeof(halResult));
Mikhail Naganov7cbf2f12016-10-27 20:05:35 -0700580 EffectAuxChannelsConfig result;
581 Result retval = getCurrentConfigImpl(
Kevin Rocard22505e62017-12-14 18:50:12 -0800582 EFFECT_FEATURE_AUX_CHANNELS, sizeof(channel_config_t), [&](void* configData) {
583 effectAuxChannelsConfigFromHal(*reinterpret_cast<channel_config_t*>(configData),
584 &result);
585 });
Mikhail Naganov7cbf2f12016-10-27 20:05:35 -0700586 _hidl_cb(retval, result);
587 return Void();
588}
589
Kevin Rocard22505e62017-12-14 18:50:12 -0800590Return<Result> Effect::setAuxChannelsConfig(const EffectAuxChannelsConfig& config) {
Mikhail Naganov7cbf2f12016-10-27 20:05:35 -0700591 uint32_t halCmd[alignedSizeIn<uint32_t>(sizeof(uint32_t) + sizeof(channel_config_t))];
592 halCmd[0] = EFFECT_FEATURE_AUX_CHANNELS;
593 effectAuxChannelsConfigToHal(config, reinterpret_cast<channel_config_t*>(&halCmd[1]));
594 return sendCommandReturningStatus(EFFECT_CMD_SET_FEATURE_CONFIG,
Kevin Rocard22505e62017-12-14 18:50:12 -0800595 "SET_FEATURE_CONFIG AUX_CHANNELS", sizeof(halCmd), halCmd);
Mikhail Naganov7cbf2f12016-10-27 20:05:35 -0700596}
597
Kevin Rocard22505e62017-12-14 18:50:12 -0800598Return<Result> Effect::setAudioSource(AudioSource source) {
Mikhail Naganov7cbf2f12016-10-27 20:05:35 -0700599 uint32_t halSource = static_cast<uint32_t>(source);
Kevin Rocard22505e62017-12-14 18:50:12 -0800600 return sendCommand(EFFECT_CMD_SET_AUDIO_SOURCE, "SET_AUDIO_SOURCE", sizeof(uint32_t),
601 &halSource);
Mikhail Naganov7cbf2f12016-10-27 20:05:35 -0700602}
603
Kevin Rocard22505e62017-12-14 18:50:12 -0800604Return<Result> Effect::offload(const EffectOffloadParameter& param) {
Mikhail Naganov7cbf2f12016-10-27 20:05:35 -0700605 effect_offload_param_t halParam;
606 effectOffloadParamToHal(param, &halParam);
Kevin Rocard22505e62017-12-14 18:50:12 -0800607 return sendCommandReturningStatus(EFFECT_CMD_OFFLOAD, "OFFLOAD", sizeof(effect_offload_param_t),
608 &halParam);
Mikhail Naganov7cbf2f12016-10-27 20:05:35 -0700609}
610
Kevin Rocard22505e62017-12-14 18:50:12 -0800611Return<void> Effect::getDescriptor(getDescriptor_cb _hidl_cb) {
Mikhail Naganov7cbf2f12016-10-27 20:05:35 -0700612 effect_descriptor_t halDescriptor;
613 memset(&halDescriptor, 0, sizeof(effect_descriptor_t));
614 status_t status = (*mHandle)->get_descriptor(mHandle, &halDescriptor);
615 EffectDescriptor descriptor;
616 if (status == OK) {
617 effectDescriptorFromHal(halDescriptor, &descriptor);
618 }
619 _hidl_cb(analyzeStatus("get_descriptor", "", sContextCallFunction, status), descriptor);
620 return Void();
621}
622
Kevin Rocard22505e62017-12-14 18:50:12 -0800623Return<void> Effect::command(uint32_t commandId, const hidl_vec<uint8_t>& data,
624 uint32_t resultMaxSize, command_cb _hidl_cb) {
Mikhail Naganov7cbf2f12016-10-27 20:05:35 -0700625 uint32_t halDataSize;
Mikhail Naganov6e81e9b2016-11-16 16:30:17 -0800626 std::unique_ptr<uint8_t[]> halData = hidlVecToHal(data, &halDataSize);
Mikhail Naganov7cbf2f12016-10-27 20:05:35 -0700627 uint32_t halResultSize = resultMaxSize;
628 std::unique_ptr<uint8_t[]> halResult(new uint8_t[halResultSize]);
629 memset(&halResult[0], 0, halResultSize);
Mikhail Naganovf4f2ff32017-01-19 12:38:39 -0800630
631 void* dataPtr = halDataSize > 0 ? &halData[0] : NULL;
632 void* resultPtr = halResultSize > 0 ? &halResult[0] : NULL;
Kevin Rocard22505e62017-12-14 18:50:12 -0800633 status_t status =
634 (*mHandle)->command(mHandle, commandId, halDataSize, dataPtr, &halResultSize, resultPtr);
Mikhail Naganov7cbf2f12016-10-27 20:05:35 -0700635 hidl_vec<uint8_t> result;
Mikhail Naganovf4f2ff32017-01-19 12:38:39 -0800636 if (status == OK && resultPtr != NULL) {
Mikhail Naganov7cbf2f12016-10-27 20:05:35 -0700637 result.setToExternal(&halResult[0], halResultSize);
638 }
639 _hidl_cb(status, result);
640 return Void();
641}
642
Kevin Rocard22505e62017-12-14 18:50:12 -0800643Return<Result> Effect::setParameter(const hidl_vec<uint8_t>& parameter,
644 const hidl_vec<uint8_t>& value) {
Mikhail Naganov7cbf2f12016-10-27 20:05:35 -0700645 return setParameterImpl(parameter.size(), &parameter[0], value.size(), &value[0]);
646}
647
Kevin Rocard22505e62017-12-14 18:50:12 -0800648Return<void> Effect::getParameter(const hidl_vec<uint8_t>& parameter, uint32_t valueMaxSize,
649 getParameter_cb _hidl_cb) {
Mikhail Naganov7cbf2f12016-10-27 20:05:35 -0700650 hidl_vec<uint8_t> value;
651 Result retval = getParameterImpl(
Kevin Rocard22505e62017-12-14 18:50:12 -0800652 parameter.size(), &parameter[0], valueMaxSize,
653 [&](uint32_t valueSize, const void* valueData) {
654 value.setToExternal(reinterpret_cast<uint8_t*>(const_cast<void*>(valueData)),
655 valueSize);
656 });
Mikhail Naganov7cbf2f12016-10-27 20:05:35 -0700657 _hidl_cb(retval, value);
658 return Void();
659}
660
Kevin Rocard22505e62017-12-14 18:50:12 -0800661Return<void> Effect::getSupportedConfigsForFeature(uint32_t featureId, uint32_t maxConfigs,
662 uint32_t configSize,
663 getSupportedConfigsForFeature_cb _hidl_cb) {
Mikhail Naganov7cbf2f12016-10-27 20:05:35 -0700664 uint32_t configCount = 0;
665 hidl_vec<uint8_t> result;
Kevin Rocard22505e62017-12-14 18:50:12 -0800666 Result retval = getSupportedConfigsImpl(featureId, maxConfigs, configSize,
667 [&](uint32_t supportedConfigs, void* configsData) {
668 configCount = supportedConfigs;
669 result.resize(configCount * configSize);
670 memcpy(&result[0], configsData, result.size());
671 });
Mikhail Naganov7cbf2f12016-10-27 20:05:35 -0700672 _hidl_cb(retval, configCount, result);
673 return Void();
674}
675
Kevin Rocard22505e62017-12-14 18:50:12 -0800676Return<void> Effect::getCurrentConfigForFeature(uint32_t featureId, uint32_t configSize,
677 getCurrentConfigForFeature_cb _hidl_cb) {
Mikhail Naganov7cbf2f12016-10-27 20:05:35 -0700678 hidl_vec<uint8_t> result;
Kevin Rocard22505e62017-12-14 18:50:12 -0800679 Result retval = getCurrentConfigImpl(featureId, configSize, [&](void* configData) {
680 result.resize(configSize);
681 memcpy(&result[0], configData, result.size());
682 });
Mikhail Naganov7cbf2f12016-10-27 20:05:35 -0700683 _hidl_cb(retval, result);
684 return Void();
685}
686
Kevin Rocard22505e62017-12-14 18:50:12 -0800687Return<Result> Effect::setCurrentConfigForFeature(uint32_t featureId,
688 const hidl_vec<uint8_t>& configData) {
Mikhail Naganov7cbf2f12016-10-27 20:05:35 -0700689 uint32_t halCmd[alignedSizeIn<uint32_t>(sizeof(uint32_t) + configData.size())];
690 memset(halCmd, 0, sizeof(halCmd));
691 halCmd[0] = featureId;
692 memcpy(&halCmd[1], &configData[0], configData.size());
Kevin Rocard22505e62017-12-14 18:50:12 -0800693 return sendCommandReturningStatus(EFFECT_CMD_SET_FEATURE_CONFIG, "SET_FEATURE_CONFIG",
694 sizeof(halCmd), halCmd);
Mikhail Naganov7cbf2f12016-10-27 20:05:35 -0700695}
696
Mikhail Naganova331de12017-01-04 16:33:55 -0800697Return<Result> Effect::close() {
698 if (mIsClosed) return Result::INVALID_STATE;
699 mIsClosed = true;
700 if (mProcessThread.get()) {
701 mStopProcessThread.store(true, std::memory_order_release);
Mikhail Naganova331de12017-01-04 16:33:55 -0800702 }
703 if (mEfGroup) {
Mikhail Naganovb0abafb2017-01-31 17:24:48 -0800704 mEfGroup->wake(static_cast<uint32_t>(MessageQueueFlagBits::REQUEST_QUIT));
Mikhail Naganova331de12017-01-04 16:33:55 -0800705 }
Mikhail Naganova331de12017-01-04 16:33:55 -0800706 return Result::OK;
707}
708
Kevin Rocard22505e62017-12-14 18:50:12 -0800709} // namespace implementation
Mikhail Naganov7cbf2f12016-10-27 20:05:35 -0700710} // namespace V2_0
711} // namespace effect
712} // namespace audio
713} // namespace hardware
714} // namespace android