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