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