blob: 1a7ea9cb9d5ec6be4a7ee9bea80a0271d5e87c85 [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"
20#include <media/EffectsFactoryApi.h>
Yifan Hongf9d30342016-11-30 13:45:34 -080021#include <android/log.h>
Mikhail Naganov7cbf2f12016-10-27 20:05:35 -070022
23#include "Conversions.h"
24#include "Effect.h"
Mikhail Naganov10548292016-10-31 10:39:47 -070025#include "EffectMap.h"
Mikhail Naganov7cbf2f12016-10-27 20:05:35 -070026
27namespace android {
28namespace hardware {
29namespace audio {
30namespace effect {
31namespace V2_0 {
32namespace implementation {
33
34using ::android::hardware::audio::common::V2_0::AudioChannelMask;
35using ::android::hardware::audio::common::V2_0::AudioFormat;
36
37// static
38const char *Effect::sContextResultOfCommand = "returned status";
39const char *Effect::sContextCallToCommand = "error";
40const char *Effect::sContextCallFunction = sContextCallToCommand;
41
42Effect::Effect(effect_handle_t handle) : mHandle(handle) {
43}
44
45Effect::~Effect() {
46 int status = EffectRelease(mHandle);
47 ALOGW_IF(status, "Error releasing effect %p: %s", mHandle, strerror(-status));
Mikhail Naganov10548292016-10-31 10:39:47 -070048 EffectMap::getInstance().remove(mHandle);
Mikhail Naganov7cbf2f12016-10-27 20:05:35 -070049 mHandle = 0;
50}
51
52// static
53template<typename T> size_t Effect::alignedSizeIn(size_t s) {
54 return (s + sizeof(T) - 1) / sizeof(T);
55}
56
57// static
Mikhail Naganov6e81e9b2016-11-16 16:30:17 -080058template<typename T> std::unique_ptr<uint8_t[]> Effect::hidlVecToHal(
59 const hidl_vec<T>& vec, uint32_t* halDataSize) {
60 // Due to bugs in HAL, they may attempt to write into the provided
61 // input buffer. The original binder buffer is r/o, thus it is needed
62 // to create a r/w version.
63 *halDataSize = vec.size() * sizeof(T);
64 std::unique_ptr<uint8_t[]> halData(new uint8_t[*halDataSize]);
65 memcpy(&halData[0], &vec[0], *halDataSize);
66 return halData;
Mikhail Naganov7cbf2f12016-10-27 20:05:35 -070067}
68
69// static
70void Effect::effectAuxChannelsConfigFromHal(
71 const channel_config_t& halConfig, EffectAuxChannelsConfig* config) {
72 config->mainChannels = AudioChannelMask(halConfig.main_channels);
73 config->auxChannels = AudioChannelMask(halConfig.aux_channels);
74}
75
76// static
77void Effect::effectAuxChannelsConfigToHal(
78 const EffectAuxChannelsConfig& config, channel_config_t* halConfig) {
79 halConfig->main_channels = static_cast<audio_channel_mask_t>(config.mainChannels);
80 halConfig->aux_channels = static_cast<audio_channel_mask_t>(config.auxChannels);
81}
82
83// static
84void Effect::effectBufferConfigFromHal(
85 const buffer_config_t& halConfig, EffectBufferConfig* config) {
86 // TODO(mnaganov): Use FMQ instead of AudioBuffer.
87 (void)halConfig.buffer.frameCount;
88 (void)halConfig.buffer.raw;
89 config->samplingRateHz = halConfig.samplingRate;
90 config->channels = AudioChannelMask(halConfig.channels);
91 config->format = AudioFormat(halConfig.format);
92 config->accessMode = EffectBufferAccess(halConfig.accessMode);
93 config->mask = EffectConfigParameters(halConfig.mask);
94}
95
96// static
97void Effect::effectBufferConfigToHal(const EffectBufferConfig& config, buffer_config_t* halConfig) {
98 // TODO(mnaganov): Use FMQ instead of AudioBuffer.
99 halConfig->buffer.frameCount = 0;
100 halConfig->buffer.raw = NULL;
101 halConfig->samplingRate = config.samplingRateHz;
102 halConfig->channels = static_cast<uint32_t>(config.channels);
103 // TODO(mnaganov): As the calling code does not use BP for now, implement later.
104 halConfig->bufferProvider.cookie = NULL;
105 halConfig->bufferProvider.getBuffer = NULL;
106 halConfig->bufferProvider.releaseBuffer = NULL;
107 halConfig->format = static_cast<uint8_t>(config.format);
108 halConfig->accessMode = static_cast<uint8_t>(config.accessMode);
109 halConfig->mask = static_cast<uint8_t>(config.mask);
110}
111
112// static
113void Effect::effectConfigFromHal(const effect_config_t& halConfig, EffectConfig* config) {
114 effectBufferConfigFromHal(halConfig.inputCfg, &config->inputCfg);
115 effectBufferConfigFromHal(halConfig.outputCfg, &config->outputCfg);
116}
117
118// static
119void Effect::effectConfigToHal(const EffectConfig& config, effect_config_t* halConfig) {
120 effectBufferConfigToHal(config.inputCfg, &halConfig->inputCfg);
121 effectBufferConfigToHal(config.outputCfg, &halConfig->outputCfg);
122}
123
124// static
125void Effect::effectOffloadParamToHal(
126 const EffectOffloadParameter& offload, effect_offload_param_t* halOffload) {
127 halOffload->isOffload = offload.isOffload;
128 halOffload->ioHandle = offload.ioHandle;
129}
130
131// static
132std::vector<uint8_t> Effect::parameterToHal(
133 uint32_t paramSize,
134 const void* paramData,
135 uint32_t valueSize,
136 const void** valueData) {
137 size_t valueOffsetFromData = alignedSizeIn<uint32_t>(paramSize) * sizeof(uint32_t);
138 size_t halParamBufferSize = sizeof(effect_param_t) + valueOffsetFromData + valueSize;
139 std::vector<uint8_t> halParamBuffer(halParamBufferSize, 0);
140 effect_param_t *halParam = reinterpret_cast<effect_param_t*>(&halParamBuffer[0]);
141 halParam->psize = paramSize;
142 halParam->vsize = valueSize;
143 memcpy(halParam->data, paramData, paramSize);
144 if (valueData) {
145 if (*valueData) {
146 // Value data is provided.
147 memcpy(halParam->data + valueOffsetFromData, *valueData, valueSize);
148 } else {
149 // The caller needs the pointer to the value data location.
150 *valueData = halParam->data + valueOffsetFromData;
151 }
152 }
153 return halParamBuffer;
154}
155
156Result Effect::analyzeCommandStatus(const char* commandName, const char* context, status_t status) {
157 return analyzeStatus("command", commandName, context, status);
158}
159
160Result Effect::analyzeStatus(
161 const char* funcName,
162 const char* subFuncName,
163 const char* contextDescription,
164 status_t status) {
165 if (status != OK) {
166 ALOGW("Effect %p %s %s %s: %s",
167 mHandle, funcName, subFuncName, contextDescription, strerror(-status));
168 }
169 switch (status) {
170 case OK: return Result::OK;
171 case -EINVAL: return Result::INVALID_ARGUMENTS;
172 case -ENODATA: return Result::INVALID_STATE;
173 case -ENODEV: return Result::NOT_INITIALIZED;
174 case -ENOMEM: return Result::RESULT_TOO_BIG;
175 case -ENOSYS: return Result::NOT_SUPPORTED;
176 default: return Result::INVALID_STATE;
177 }
178}
179
180void Effect::getConfigImpl(int commandCode, const char* commandName, GetConfigCallback cb) {
181 uint32_t halResultSize = sizeof(effect_config_t);
182 effect_config_t halConfig;
183 status_t status = (*mHandle)->command(
184 mHandle, commandCode, 0, NULL, &halResultSize, &halConfig);
185 EffectConfig config;
186 if (status == OK) {
187 effectConfigFromHal(halConfig, &config);
188 }
189 cb(analyzeCommandStatus(commandName, sContextCallToCommand, status), config);
190}
191
192Result Effect::getCurrentConfigImpl(
193 uint32_t featureId, uint32_t configSize, GetCurrentConfigSuccessCallback onSuccess) {
194 uint32_t halCmd = featureId;
195 uint32_t halResult[alignedSizeIn<uint32_t>(sizeof(uint32_t) + configSize)];
196 memset(halResult, 0, sizeof(halResult));
197 uint32_t halResultSize = 0;
198 return sendCommandReturningStatusAndData(
199 EFFECT_CMD_GET_FEATURE_CONFIG, "GET_FEATURE_CONFIG",
200 sizeof(uint32_t), &halCmd,
201 &halResultSize, halResult,
202 sizeof(uint32_t),
203 [&]{ onSuccess(&halResult[1]); });
204}
205
206Result Effect::getParameterImpl(
207 uint32_t paramSize,
208 const void* paramData,
209 uint32_t valueSize,
210 GetParameterSuccessCallback onSuccess) {
211 // As it is unknown what method HAL uses for copying the provided parameter data,
212 // it is safer to make sure that input and output buffers do not overlap.
213 std::vector<uint8_t> halCmdBuffer =
214 parameterToHal(paramSize, paramData, valueSize, nullptr);
215 const void *valueData = nullptr;
216 std::vector<uint8_t> halParamBuffer =
217 parameterToHal(paramSize, paramData, valueSize, &valueData);
218 uint32_t halParamBufferSize = halParamBuffer.size();
219
220 return sendCommandReturningStatusAndData(
221 EFFECT_CMD_GET_PARAM, "GET_PARAM",
222 halCmdBuffer.size(), &halCmdBuffer[0],
223 &halParamBufferSize, &halParamBuffer[0],
224 sizeof(effect_param_t),
225 [&]{
226 effect_param_t *halParam = reinterpret_cast<effect_param_t*>(&halParamBuffer[0]);
227 onSuccess(halParam->vsize, valueData);
228 });
229}
230
231Result Effect::getSupportedConfigsImpl(
232 uint32_t featureId,
233 uint32_t maxConfigs,
234 uint32_t configSize,
235 GetSupportedConfigsSuccessCallback onSuccess) {
236 uint32_t halCmd[2] = { featureId, maxConfigs };
237 uint32_t halResultSize = 2 * sizeof(uint32_t) + maxConfigs * sizeof(configSize);
238 uint8_t halResult[halResultSize];
239 memset(&halResult[0], 0, halResultSize);
240 return sendCommandReturningStatusAndData(
241 EFFECT_CMD_GET_FEATURE_SUPPORTED_CONFIGS, "GET_FEATURE_SUPPORTED_CONFIGS",
242 sizeof(halCmd), halCmd,
243 &halResultSize, &halResult[0],
244 2 * sizeof(uint32_t),
245 [&]{
246 uint32_t *halResult32 = reinterpret_cast<uint32_t*>(&halResult[0]);
247 uint32_t supportedConfigs = *(++halResult32); // skip status field
248 if (supportedConfigs > maxConfigs) supportedConfigs = maxConfigs;
249 onSuccess(supportedConfigs, ++halResult32);
250 });
251}
252
253void Effect::processImpl(
254 ProcessFunction process,
255 const char* funcName,
256 const AudioBuffer& inBuffer,
257 uint32_t outFrameSize,
258 ProcessCallback cb) {
259 audio_buffer_t halInBuffer;
260 halInBuffer.frameCount = inBuffer.frameCount;
261 halInBuffer.u8 = const_cast<uint8_t*>(&inBuffer.data[0]);
262 audio_buffer_t halOutBuffer;
263 halOutBuffer.frameCount = halInBuffer.frameCount;
264 // TODO(mnaganov): Consider stashing the buffer to avoid reallocating it every time.
265 std::unique_ptr<uint8_t[]> halOutBufferData(
266 new uint8_t[halOutBuffer.frameCount * outFrameSize]);
267 halOutBuffer.u8 = &halOutBufferData[0];
268 status_t status = process(mHandle, &halInBuffer, &halOutBuffer);
269 Result retval = analyzeStatus(funcName, "", sContextCallFunction, status);
270 AudioBuffer outBuffer;
271 if (status == OK) {
272 outBuffer.frameCount = halOutBuffer.frameCount;
273 outBuffer.data.setToExternal(halOutBuffer.u8, halOutBuffer.frameCount * outFrameSize);
274 } else {
275 outBuffer.frameCount = 0;
276 }
277 cb(retval, outBuffer);
278}
279
280Result Effect::sendCommand(int commandCode, const char* commandName) {
281 return sendCommand(commandCode, commandName, 0, NULL);
282}
283
284Result Effect::sendCommand(
285 int commandCode, const char* commandName, uint32_t size, void* data) {
286 status_t status = (*mHandle)->command(mHandle, commandCode, size, data, 0, NULL);
287 return analyzeCommandStatus(commandName, sContextCallToCommand, status);
288}
289
290Result Effect::sendCommandReturningData(
291 int commandCode, const char* commandName,
292 uint32_t* replySize, void* replyData) {
293 return sendCommandReturningData(commandCode, commandName, 0, NULL, replySize, replyData);
294}
295
296Result Effect::sendCommandReturningData(
297 int commandCode, const char* commandName,
298 uint32_t size, void* data,
299 uint32_t* replySize, void* replyData) {
300 uint32_t expectedReplySize = *replySize;
301 status_t status = (*mHandle)->command(mHandle, commandCode, size, data, replySize, replyData);
302 if (status == OK && *replySize != expectedReplySize) {
303 status = -ENODATA;
304 }
305 return analyzeCommandStatus(commandName, sContextCallToCommand, status);
306}
307
308Result Effect::sendCommandReturningStatus(int commandCode, const char* commandName) {
309 return sendCommandReturningStatus(commandCode, commandName, 0, NULL);
310}
311
312Result Effect::sendCommandReturningStatus(
313 int commandCode, const char* commandName, uint32_t size, void* data) {
314 uint32_t replyCmdStatus;
315 uint32_t replySize = sizeof(uint32_t);
316 return sendCommandReturningStatusAndData(
317 commandCode, commandName, size, data, &replySize, &replyCmdStatus, replySize, []{});
318}
319
320Result Effect::sendCommandReturningStatusAndData(
321 int commandCode, const char* commandName,
322 uint32_t size, void* data,
323 uint32_t* replySize, void* replyData,
324 uint32_t minReplySize,
325 CommandSuccessCallback onSuccess) {
326 status_t status =
327 (*mHandle)->command(mHandle, commandCode, size, data, replySize, replyData);
328 Result retval;
329 if (status == OK && minReplySize >= sizeof(uint32_t) && *replySize >= minReplySize) {
330 uint32_t commandStatus = *reinterpret_cast<uint32_t*>(replyData);
331 retval = analyzeCommandStatus(commandName, sContextResultOfCommand, commandStatus);
332 if (commandStatus == OK) {
333 onSuccess();
334 }
335 } else {
336 retval = analyzeCommandStatus(commandName, sContextCallToCommand, status);
337 }
338 return retval;
339}
340
341Result Effect::setConfigImpl(
342 int commandCode, const char* commandName,
343 const EffectConfig& config,
344 const sp<IEffectBufferProviderCallback>& inputBufferProvider,
345 const sp<IEffectBufferProviderCallback>& outputBufferProvider) {
346 effect_config_t halConfig;
347 effectConfigToHal(config, &halConfig);
348 if (inputBufferProvider != 0) {
349 LOG_FATAL("Using input buffer provider is not supported");
350 }
351 if (outputBufferProvider != 0) {
352 LOG_FATAL("Using output buffer provider is not supported");
353 }
354 return sendCommandReturningStatus(
355 commandCode, commandName, sizeof(effect_config_t), &halConfig);
356}
357
358
359Result Effect::setParameterImpl(
360 uint32_t paramSize, const void* paramData, uint32_t valueSize, const void* valueData) {
361 std::vector<uint8_t> halParamBuffer = parameterToHal(
362 paramSize, paramData, valueSize, &valueData);
363 return sendCommandReturningStatus(
364 EFFECT_CMD_SET_PARAM, "SET_PARAM", halParamBuffer.size(), &halParamBuffer[0]);
365}
366
367// Methods from ::android::hardware::audio::effect::V2_0::IEffect follow.
368Return<Result> Effect::init() {
369 return sendCommandReturningStatus(EFFECT_CMD_INIT, "INIT");
370}
371
372Return<Result> Effect::setConfig(
373 const EffectConfig& config,
374 const sp<IEffectBufferProviderCallback>& inputBufferProvider,
375 const sp<IEffectBufferProviderCallback>& outputBufferProvider) {
376 return setConfigImpl(
377 EFFECT_CMD_SET_CONFIG, "SET_CONFIG", config, inputBufferProvider, outputBufferProvider);
378}
379
380Return<Result> Effect::reset() {
381 return sendCommand(EFFECT_CMD_RESET, "RESET");
382}
383
384Return<Result> Effect::enable() {
385 return sendCommandReturningStatus(EFFECT_CMD_ENABLE, "ENABLE");
386}
387
388Return<Result> Effect::disable() {
389 return sendCommandReturningStatus(EFFECT_CMD_DISABLE, "DISABLE");
390}
391
392Return<Result> Effect::setDevice(AudioDevice device) {
393 uint32_t halDevice = static_cast<uint32_t>(device);
394 return sendCommand(EFFECT_CMD_SET_DEVICE, "SET_DEVICE", sizeof(uint32_t), &halDevice);
395}
396
397Return<void> Effect::setAndGetVolume(
398 const hidl_vec<uint32_t>& volumes, setAndGetVolume_cb _hidl_cb) {
399 uint32_t halDataSize;
Mikhail Naganov6e81e9b2016-11-16 16:30:17 -0800400 std::unique_ptr<uint8_t[]> halData = hidlVecToHal(volumes, &halDataSize);
Mikhail Naganov7cbf2f12016-10-27 20:05:35 -0700401 uint32_t halResultSize = halDataSize;
402 uint32_t halResult[volumes.size()];
403 Result retval = sendCommandReturningData(
Mikhail Naganov6e81e9b2016-11-16 16:30:17 -0800404 EFFECT_CMD_SET_VOLUME, "SET_VOLUME",
405 halDataSize, &halData[0],
406 &halResultSize, halResult);
Mikhail Naganov7cbf2f12016-10-27 20:05:35 -0700407 hidl_vec<uint32_t> result;
408 if (retval == Result::OK) {
409 result.setToExternal(&halResult[0], halResultSize);
410 }
411 _hidl_cb(retval, result);
412 return Void();
413}
414
415Return<Result> Effect::setAudioMode(AudioMode mode) {
416 uint32_t halMode = static_cast<uint32_t>(mode);
417 return sendCommand(
418 EFFECT_CMD_SET_AUDIO_MODE, "SET_AUDIO_MODE", sizeof(uint32_t), &halMode);
419}
420
421Return<Result> Effect::setConfigReverse(
422 const EffectConfig& config,
423 const sp<IEffectBufferProviderCallback>& inputBufferProvider,
424 const sp<IEffectBufferProviderCallback>& outputBufferProvider) {
425 return setConfigImpl(EFFECT_CMD_SET_CONFIG_REVERSE, "SET_CONFIG_REVERSE",
426 config, inputBufferProvider, outputBufferProvider);
427}
428
429Return<Result> Effect::setInputDevice(AudioDevice device) {
430 uint32_t halDevice = static_cast<uint32_t>(device);
431 return sendCommand(
432 EFFECT_CMD_SET_INPUT_DEVICE, "SET_INPUT_DEVICE", sizeof(uint32_t), &halDevice);
433}
434
435Return<void> Effect::getConfig(getConfig_cb _hidl_cb) {
436 getConfigImpl(EFFECT_CMD_GET_CONFIG, "GET_CONFIG", _hidl_cb);
437 return Void();
438}
439
440Return<void> Effect::getConfigReverse(getConfigReverse_cb _hidl_cb) {
441 getConfigImpl(EFFECT_CMD_GET_CONFIG_REVERSE, "GET_CONFIG_REVERSE", _hidl_cb);
442 return Void();
443}
444
445Return<void> Effect::getSupportedAuxChannelsConfigs(
446 uint32_t maxConfigs, getSupportedAuxChannelsConfigs_cb _hidl_cb) {
447 hidl_vec<EffectAuxChannelsConfig> result;
448 Result retval = getSupportedConfigsImpl(
449 EFFECT_FEATURE_AUX_CHANNELS,
450 maxConfigs,
451 sizeof(channel_config_t),
452 [&] (uint32_t supportedConfigs, void* configsData) {
453 result.resize(supportedConfigs);
454 channel_config_t *config = reinterpret_cast<channel_config_t*>(configsData);
455 for (size_t i = 0; i < result.size(); ++i) {
456 effectAuxChannelsConfigFromHal(*config++, &result[i]);
457 }
458 });
459 _hidl_cb(retval, result);
460 return Void();
461}
462
463Return<void> Effect::getAuxChannelsConfig(getAuxChannelsConfig_cb _hidl_cb) {
464 uint32_t halCmd = EFFECT_FEATURE_AUX_CHANNELS;
465 uint32_t halResult[alignedSizeIn<uint32_t>(sizeof(uint32_t) + sizeof(channel_config_t))];
466 memset(halResult, 0, sizeof(halResult));
467 uint32_t halResultSize = 0;
468 EffectAuxChannelsConfig result;
469 Result retval = getCurrentConfigImpl(
470 EFFECT_FEATURE_AUX_CHANNELS,
471 sizeof(channel_config_t),
472 [&] (void* configData) {
473 effectAuxChannelsConfigFromHal(
474 *reinterpret_cast<channel_config_t*>(configData), &result);
475 });
476 _hidl_cb(retval, result);
477 return Void();
478}
479
480Return<Result> Effect::setAuxChannelsConfig(const EffectAuxChannelsConfig& config) {
481 uint32_t halCmd[alignedSizeIn<uint32_t>(sizeof(uint32_t) + sizeof(channel_config_t))];
482 halCmd[0] = EFFECT_FEATURE_AUX_CHANNELS;
483 effectAuxChannelsConfigToHal(config, reinterpret_cast<channel_config_t*>(&halCmd[1]));
484 return sendCommandReturningStatus(EFFECT_CMD_SET_FEATURE_CONFIG,
485 "SET_FEATURE_CONFIG AUX_CHANNELS", sizeof(halCmd), halCmd);
486}
487
488Return<Result> Effect::setAudioSource(AudioSource source) {
489 uint32_t halSource = static_cast<uint32_t>(source);
490 return sendCommand(
491 EFFECT_CMD_SET_AUDIO_SOURCE, "SET_AUDIO_SOURCE", sizeof(uint32_t), &halSource);
492}
493
494Return<Result> Effect::offload(const EffectOffloadParameter& param) {
495 effect_offload_param_t halParam;
496 effectOffloadParamToHal(param, &halParam);
497 return sendCommandReturningStatus(
498 EFFECT_CMD_OFFLOAD, "OFFLOAD", sizeof(effect_offload_param_t), &halParam);
499}
500
501Return<void> Effect::getDescriptor(getDescriptor_cb _hidl_cb) {
502 effect_descriptor_t halDescriptor;
503 memset(&halDescriptor, 0, sizeof(effect_descriptor_t));
504 status_t status = (*mHandle)->get_descriptor(mHandle, &halDescriptor);
505 EffectDescriptor descriptor;
506 if (status == OK) {
507 effectDescriptorFromHal(halDescriptor, &descriptor);
508 }
509 _hidl_cb(analyzeStatus("get_descriptor", "", sContextCallFunction, status), descriptor);
510 return Void();
511}
512
513Return<void> Effect::process(
514 const AudioBuffer& inBuffer, uint32_t outFrameSize, process_cb _hidl_cb) {
515 processImpl((*mHandle)->process, "process", inBuffer, outFrameSize, _hidl_cb);
516 return Void();
517}
518
519Return<void> Effect::processReverse(
520 const AudioBuffer& inBuffer, uint32_t outFrameSize, processReverse_cb _hidl_cb) {
521 if ((*mHandle)->process_reverse != NULL) {
522 processImpl(
523 (*mHandle)->process_reverse, "process_reverse", inBuffer, outFrameSize, _hidl_cb);
524 } else {
525 _hidl_cb(Result::NOT_SUPPORTED, AudioBuffer());
526 }
527 return Void();
528}
529
530Return<void> Effect::command(
531 uint32_t commandId,
532 const hidl_vec<uint8_t>& data,
533 uint32_t resultMaxSize,
534 command_cb _hidl_cb) {
535 uint32_t halDataSize;
Mikhail Naganov6e81e9b2016-11-16 16:30:17 -0800536 std::unique_ptr<uint8_t[]> halData = hidlVecToHal(data, &halDataSize);
Mikhail Naganov7cbf2f12016-10-27 20:05:35 -0700537 uint32_t halResultSize = resultMaxSize;
538 std::unique_ptr<uint8_t[]> halResult(new uint8_t[halResultSize]);
539 memset(&halResult[0], 0, halResultSize);
540 status_t status = (*mHandle)->command(
Mikhail Naganov6e81e9b2016-11-16 16:30:17 -0800541 mHandle, commandId, halDataSize, &halData[0], &halResultSize, &halResult[0]);
Mikhail Naganov7cbf2f12016-10-27 20:05:35 -0700542 hidl_vec<uint8_t> result;
543 if (status == OK) {
544 result.setToExternal(&halResult[0], halResultSize);
545 }
546 _hidl_cb(status, result);
547 return Void();
548}
549
550Return<Result> Effect::setParameter(
551 const hidl_vec<uint8_t>& parameter, const hidl_vec<uint8_t>& value) {
552 return setParameterImpl(parameter.size(), &parameter[0], value.size(), &value[0]);
553}
554
555Return<void> Effect::getParameter(
556 const hidl_vec<uint8_t>& parameter, uint32_t valueMaxSize, getParameter_cb _hidl_cb) {
557 hidl_vec<uint8_t> value;
558 Result retval = getParameterImpl(
559 parameter.size(),
560 &parameter[0],
561 valueMaxSize,
562 [&] (uint32_t valueSize, const void* valueData) {
563 value.setToExternal(
564 reinterpret_cast<uint8_t*>(const_cast<void*>(valueData)), valueSize);
565 });
566 _hidl_cb(retval, value);
567 return Void();
568}
569
570Return<void> Effect::getSupportedConfigsForFeature(
571 uint32_t featureId,
572 uint32_t maxConfigs,
573 uint32_t configSize,
574 getSupportedConfigsForFeature_cb _hidl_cb) {
575 uint32_t configCount = 0;
576 hidl_vec<uint8_t> result;
577 Result retval = getSupportedConfigsImpl(
578 featureId,
579 maxConfigs,
580 configSize,
581 [&] (uint32_t supportedConfigs, void* configsData) {
582 configCount = supportedConfigs;
583 result.resize(configCount * configSize);
584 memcpy(&result[0], configsData, result.size());
585 });
586 _hidl_cb(retval, configCount, result);
587 return Void();
588}
589
590Return<void> Effect::getCurrentConfigForFeature(
591 uint32_t featureId, uint32_t configSize, getCurrentConfigForFeature_cb _hidl_cb) {
592 hidl_vec<uint8_t> result;
593 Result retval = getCurrentConfigImpl(
594 featureId,
595 configSize,
596 [&] (void* configData) {
597 result.resize(configSize);
598 memcpy(&result[0], configData, result.size());
599 });
600 _hidl_cb(retval, result);
601 return Void();
602}
603
604Return<Result> Effect::setCurrentConfigForFeature(
605 uint32_t featureId, const hidl_vec<uint8_t>& configData) {
606 uint32_t halCmd[alignedSizeIn<uint32_t>(sizeof(uint32_t) + configData.size())];
607 memset(halCmd, 0, sizeof(halCmd));
608 halCmd[0] = featureId;
609 memcpy(&halCmd[1], &configData[0], configData.size());
610 return sendCommandReturningStatus(
611 EFFECT_CMD_SET_FEATURE_CONFIG, "SET_FEATURE_CONFIG", sizeof(halCmd), halCmd);
612}
613
614} // namespace implementation
615} // namespace V2_0
616} // namespace effect
617} // namespace audio
618} // namespace hardware
619} // namespace android