1 /* 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.h> 18 19 #define LOG_TAG "EffectHAL" 20 #define ATRACE_TAG ATRACE_TAG_AUDIO 21 22 #include <android/log.h> 23 #include <media/EffectsFactoryApi.h> 24 #include <utils/Trace.h> 25 26 #include "Conversions.h" 27 #include "Effect.h" 28 #include "EffectMap.h" 29 30 namespace android { 31 namespace hardware { 32 namespace audio { 33 namespace effect { 34 namespace V2_0 { 35 namespace implementation { 36 37 using ::android::hardware::audio::common::V2_0::AudioChannelMask; 38 using ::android::hardware::audio::common::V2_0::AudioFormat; 39 using ::android::hardware::audio::effect::V2_0::MessageQueueFlagBits; 40 41 namespace { 42 43 class ProcessThread : public Thread { 44 public: 45 // ProcessThread's lifespan never exceeds Effect's lifespan. 46 ProcessThread(std::atomic<bool>* stop, 47 effect_handle_t effect, 48 std::atomic<audio_buffer_t*>* inBuffer, 49 std::atomic<audio_buffer_t*>* outBuffer, 50 Effect::StatusMQ* statusMQ, 51 EventFlag* efGroup) 52 : Thread(false /*canCallJava*/), 53 mStop(stop), 54 mEffect(effect), 55 mHasProcessReverse((*mEffect)->process_reverse != NULL), 56 mInBuffer(inBuffer), 57 mOutBuffer(outBuffer), 58 mStatusMQ(statusMQ), 59 mEfGroup(efGroup) { 60 } 61 virtual ~ProcessThread() {} 62 63 private: 64 std::atomic<bool>* mStop; 65 effect_handle_t mEffect; 66 bool mHasProcessReverse; 67 std::atomic<audio_buffer_t*>* mInBuffer; 68 std::atomic<audio_buffer_t*>* mOutBuffer; 69 Effect::StatusMQ* mStatusMQ; 70 EventFlag* mEfGroup; 71 72 bool threadLoop() override; 73 }; 74 75 bool ProcessThread::threadLoop() { 76 // This implementation doesn't return control back to the Thread until it decides to stop, 77 // as the Thread uses mutexes, and this can lead to priority inversion. 78 while(!std::atomic_load_explicit(mStop, std::memory_order_acquire)) { 79 uint32_t efState = 0; 80 mEfGroup->wait(static_cast<uint32_t>(MessageQueueFlagBits::REQUEST_PROCESS_ALL), &efState); 81 if (!(efState & static_cast<uint32_t>(MessageQueueFlagBits::REQUEST_PROCESS_ALL)) 82 || (efState & static_cast<uint32_t>(MessageQueueFlagBits::REQUEST_QUIT))) { 83 continue; // Nothing to do or time to quit. 84 } 85 Result retval = Result::OK; 86 if (efState & static_cast<uint32_t>(MessageQueueFlagBits::REQUEST_PROCESS_REVERSE) 87 && !mHasProcessReverse) { 88 retval = Result::NOT_SUPPORTED; 89 } 90 91 if (retval == Result::OK) { 92 // affects both buffer pointers and their contents. 93 std::atomic_thread_fence(std::memory_order_acquire); 94 int32_t processResult; 95 audio_buffer_t* inBuffer = 96 std::atomic_load_explicit(mInBuffer, std::memory_order_relaxed); 97 audio_buffer_t* outBuffer = 98 std::atomic_load_explicit(mOutBuffer, std::memory_order_relaxed); 99 if (inBuffer != nullptr && outBuffer != nullptr) { 100 if (efState & static_cast<uint32_t>(MessageQueueFlagBits::REQUEST_PROCESS)) { 101 processResult = (*mEffect)->process(mEffect, inBuffer, outBuffer); 102 } else { 103 processResult = (*mEffect)->process_reverse(mEffect, inBuffer, outBuffer); 104 } 105 std::atomic_thread_fence(std::memory_order_release); 106 } else { 107 ALOGE("processing buffers were not set before calling 'process'"); 108 processResult = -ENODEV; 109 } 110 switch(processResult) { 111 case 0: retval = Result::OK; break; 112 case -ENODATA: retval = Result::INVALID_STATE; break; 113 case -EINVAL: retval = Result::INVALID_ARGUMENTS; break; 114 default: retval = Result::NOT_INITIALIZED; 115 } 116 } 117 if (!mStatusMQ->write(&retval)) { 118 ALOGW("status message queue write failed"); 119 } 120 mEfGroup->wake(static_cast<uint32_t>(MessageQueueFlagBits::DONE_PROCESSING)); 121 } 122 123 return false; 124 } 125 126 } // namespace 127 128 // static 129 const char *Effect::sContextResultOfCommand = "returned status"; 130 const char *Effect::sContextCallToCommand = "error"; 131 const char *Effect::sContextCallFunction = sContextCallToCommand; 132 133 Effect::Effect(effect_handle_t handle) 134 : mIsClosed(false), mHandle(handle), mEfGroup(nullptr), mStopProcessThread(false) { 135 } 136 137 Effect::~Effect() { 138 ATRACE_CALL(); 139 close(); 140 if (mProcessThread.get()) { 141 ATRACE_NAME("mProcessThread->join"); 142 status_t status = mProcessThread->join(); 143 ALOGE_IF(status, "processing thread exit error: %s", strerror(-status)); 144 } 145 if (mEfGroup) { 146 status_t status = EventFlag::deleteEventFlag(&mEfGroup); 147 ALOGE_IF(status, "processing MQ event flag deletion error: %s", strerror(-status)); 148 } 149 mInBuffer.clear(); 150 mOutBuffer.clear(); 151 int status = EffectRelease(mHandle); 152 ALOGW_IF(status, "Error releasing effect %p: %s", mHandle, strerror(-status)); 153 EffectMap::getInstance().remove(mHandle); 154 mHandle = 0; 155 } 156 157 // static 158 template<typename T> size_t Effect::alignedSizeIn(size_t s) { 159 return (s + sizeof(T) - 1) / sizeof(T); 160 } 161 162 // static 163 template<typename T> std::unique_ptr<uint8_t[]> Effect::hidlVecToHal( 164 const hidl_vec<T>& vec, uint32_t* halDataSize) { 165 // Due to bugs in HAL, they may attempt to write into the provided 166 // input buffer. The original binder buffer is r/o, thus it is needed 167 // to create a r/w version. 168 *halDataSize = vec.size() * sizeof(T); 169 std::unique_ptr<uint8_t[]> halData(new uint8_t[*halDataSize]); 170 memcpy(&halData[0], &vec[0], *halDataSize); 171 return halData; 172 } 173 174 // static 175 void Effect::effectAuxChannelsConfigFromHal( 176 const channel_config_t& halConfig, EffectAuxChannelsConfig* config) { 177 config->mainChannels = AudioChannelMask(halConfig.main_channels); 178 config->auxChannels = AudioChannelMask(halConfig.aux_channels); 179 } 180 181 // static 182 void Effect::effectAuxChannelsConfigToHal( 183 const EffectAuxChannelsConfig& config, channel_config_t* halConfig) { 184 halConfig->main_channels = static_cast<audio_channel_mask_t>(config.mainChannels); 185 halConfig->aux_channels = static_cast<audio_channel_mask_t>(config.auxChannels); 186 } 187 188 // static 189 void Effect::effectBufferConfigFromHal( 190 const buffer_config_t& halConfig, EffectBufferConfig* config) { 191 config->buffer.id = 0; 192 config->buffer.frameCount = 0; 193 config->samplingRateHz = halConfig.samplingRate; 194 config->channels = AudioChannelMask(halConfig.channels); 195 config->format = AudioFormat(halConfig.format); 196 config->accessMode = EffectBufferAccess(halConfig.accessMode); 197 config->mask = EffectConfigParameters(halConfig.mask); 198 } 199 200 // static 201 void Effect::effectBufferConfigToHal(const EffectBufferConfig& config, buffer_config_t* halConfig) { 202 // Note: setting the buffers directly is considered obsolete. They need to be set 203 // using 'setProcessBuffers'. 204 halConfig->buffer.frameCount = 0; 205 halConfig->buffer.raw = NULL; 206 halConfig->samplingRate = config.samplingRateHz; 207 halConfig->channels = static_cast<uint32_t>(config.channels); 208 // Note: The framework code does not use BP. 209 halConfig->bufferProvider.cookie = NULL; 210 halConfig->bufferProvider.getBuffer = NULL; 211 halConfig->bufferProvider.releaseBuffer = NULL; 212 halConfig->format = static_cast<uint8_t>(config.format); 213 halConfig->accessMode = static_cast<uint8_t>(config.accessMode); 214 halConfig->mask = static_cast<uint8_t>(config.mask); 215 } 216 217 // static 218 void Effect::effectConfigFromHal(const effect_config_t& halConfig, EffectConfig* config) { 219 effectBufferConfigFromHal(halConfig.inputCfg, &config->inputCfg); 220 effectBufferConfigFromHal(halConfig.outputCfg, &config->outputCfg); 221 } 222 223 // static 224 void Effect::effectConfigToHal(const EffectConfig& config, effect_config_t* halConfig) { 225 effectBufferConfigToHal(config.inputCfg, &halConfig->inputCfg); 226 effectBufferConfigToHal(config.outputCfg, &halConfig->outputCfg); 227 } 228 229 // static 230 void Effect::effectOffloadParamToHal( 231 const EffectOffloadParameter& offload, effect_offload_param_t* halOffload) { 232 halOffload->isOffload = offload.isOffload; 233 halOffload->ioHandle = offload.ioHandle; 234 } 235 236 // static 237 std::vector<uint8_t> Effect::parameterToHal( 238 uint32_t paramSize, 239 const void* paramData, 240 uint32_t valueSize, 241 const void** valueData) { 242 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); 245 effect_param_t *halParam = reinterpret_cast<effect_param_t*>(&halParamBuffer[0]); 246 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 261 Result Effect::analyzeCommandStatus(const char* commandName, const char* context, status_t status) { 262 return analyzeStatus("command", commandName, context, status); 263 } 264 265 Result Effect::analyzeStatus( 266 const char* funcName, 267 const char* subFuncName, 268 const char* contextDescription, 269 status_t status) { 270 if (status != OK) { 271 ALOGW("Effect %p %s %s %s: %s", 272 mHandle, funcName, subFuncName, contextDescription, strerror(-status)); 273 } 274 switch (status) { 275 case OK: return Result::OK; 276 case -EINVAL: return Result::INVALID_ARGUMENTS; 277 case -ENODATA: return Result::INVALID_STATE; 278 case -ENODEV: return Result::NOT_INITIALIZED; 279 case -ENOMEM: return Result::RESULT_TOO_BIG; 280 case -ENOSYS: return Result::NOT_SUPPORTED; 281 default: return Result::INVALID_STATE; 282 } 283 } 284 285 void Effect::getConfigImpl(int commandCode, const char* commandName, GetConfigCallback cb) { 286 uint32_t halResultSize = sizeof(effect_config_t); 287 effect_config_t halConfig{}; 288 status_t status = (*mHandle)->command( 289 mHandle, commandCode, 0, NULL, &halResultSize, &halConfig); 290 EffectConfig config; 291 if (status == OK) { 292 effectConfigFromHal(halConfig, &config); 293 } 294 cb(analyzeCommandStatus(commandName, sContextCallToCommand, status), config); 295 } 296 297 Result Effect::getCurrentConfigImpl( 298 uint32_t featureId, uint32_t configSize, GetCurrentConfigSuccessCallback onSuccess) { 299 uint32_t halCmd = featureId; 300 uint32_t halResult[alignedSizeIn<uint32_t>(sizeof(uint32_t) + configSize)]; 301 memset(halResult, 0, sizeof(halResult)); 302 uint32_t halResultSize = 0; 303 return sendCommandReturningStatusAndData( 304 EFFECT_CMD_GET_FEATURE_CONFIG, "GET_FEATURE_CONFIG", 305 sizeof(uint32_t), &halCmd, 306 &halResultSize, halResult, 307 sizeof(uint32_t), 308 [&]{ onSuccess(&halResult[1]); }); 309 } 310 311 Result Effect::getParameterImpl( 312 uint32_t paramSize, 313 const void* paramData, 314 uint32_t requestValueSize, 315 uint32_t replyValueSize, 316 GetParameterSuccessCallback onSuccess) { 317 // As it is unknown what method HAL uses for copying the provided parameter data, 318 // it is safer to make sure that input and output buffers do not overlap. 319 std::vector<uint8_t> halCmdBuffer = 320 parameterToHal(paramSize, paramData, requestValueSize, nullptr); 321 const void *valueData = nullptr; 322 std::vector<uint8_t> halParamBuffer = 323 parameterToHal(paramSize, paramData, replyValueSize, &valueData); 324 uint32_t halParamBufferSize = halParamBuffer.size(); 325 326 return sendCommandReturningStatusAndData( 327 EFFECT_CMD_GET_PARAM, "GET_PARAM", 328 halCmdBuffer.size(), &halCmdBuffer[0], 329 &halParamBufferSize, &halParamBuffer[0], 330 sizeof(effect_param_t), 331 [&]{ 332 effect_param_t *halParam = reinterpret_cast<effect_param_t*>(&halParamBuffer[0]); 333 onSuccess(halParam->vsize, valueData); 334 }); 335 } 336 337 Result Effect::getSupportedConfigsImpl( 338 uint32_t featureId, 339 uint32_t maxConfigs, 340 uint32_t configSize, 341 GetSupportedConfigsSuccessCallback onSuccess) { 342 uint32_t halCmd[2] = { featureId, maxConfigs }; 343 uint32_t halResultSize = 2 * sizeof(uint32_t) + maxConfigs * sizeof(configSize); 344 uint8_t halResult[halResultSize]; 345 memset(&halResult[0], 0, halResultSize); 346 return sendCommandReturningStatusAndData( 347 EFFECT_CMD_GET_FEATURE_SUPPORTED_CONFIGS, "GET_FEATURE_SUPPORTED_CONFIGS", 348 sizeof(halCmd), halCmd, 349 &halResultSize, &halResult[0], 350 2 * sizeof(uint32_t), 351 [&]{ 352 uint32_t *halResult32 = reinterpret_cast<uint32_t*>(&halResult[0]); 353 uint32_t supportedConfigs = *(++halResult32); // skip status field 354 if (supportedConfigs > maxConfigs) supportedConfigs = maxConfigs; 355 onSuccess(supportedConfigs, ++halResult32); 356 }); 357 } 358 359 Return<void> Effect::prepareForProcessing(prepareForProcessing_cb _hidl_cb) { 360 status_t status; 361 // Create message queue. 362 if (mStatusMQ) { 363 ALOGE("the client attempts to call prepareForProcessing_cb twice"); 364 _hidl_cb(Result::INVALID_STATE, StatusMQ::Descriptor()); 365 return Void(); 366 } 367 std::unique_ptr<StatusMQ> tempStatusMQ(new StatusMQ(1, true /*EventFlag*/)); 368 if (!tempStatusMQ->isValid()) { 369 ALOGE_IF(!tempStatusMQ->isValid(), "status MQ is invalid"); 370 _hidl_cb(Result::INVALID_ARGUMENTS, StatusMQ::Descriptor()); 371 return Void(); 372 } 373 status = EventFlag::createEventFlag(tempStatusMQ->getEventFlagWord(), &mEfGroup); 374 if (status != OK || !mEfGroup) { 375 ALOGE("failed creating event flag for status MQ: %s", strerror(-status)); 376 _hidl_cb(Result::INVALID_ARGUMENTS, StatusMQ::Descriptor()); 377 return Void(); 378 } 379 380 // Create and launch the thread. 381 mProcessThread = new ProcessThread( 382 &mStopProcessThread, 383 mHandle, 384 &mHalInBufferPtr, 385 &mHalOutBufferPtr, 386 tempStatusMQ.get(), 387 mEfGroup); 388 status = mProcessThread->run("effect", PRIORITY_URGENT_AUDIO); 389 if (status != OK) { 390 ALOGW("failed to start effect processing thread: %s", strerror(-status)); 391 _hidl_cb(Result::INVALID_ARGUMENTS, MQDescriptorSync<Result>()); 392 return Void(); 393 } 394 395 mStatusMQ = std::move(tempStatusMQ); 396 _hidl_cb(Result::OK, *mStatusMQ->getDesc()); 397 return Void(); 398 } 399 400 Return<Result> Effect::setProcessBuffers( 401 const AudioBuffer& inBuffer, const AudioBuffer& outBuffer) { 402 AudioBufferManager& manager = AudioBufferManager::getInstance(); 403 sp<AudioBufferWrapper> tempInBuffer, tempOutBuffer; 404 if (!manager.wrap(inBuffer, &tempInBuffer)) { 405 ALOGE("Could not map memory of the input buffer"); 406 return Result::INVALID_ARGUMENTS; 407 } 408 if (!manager.wrap(outBuffer, &tempOutBuffer)) { 409 ALOGE("Could not map memory of the output buffer"); 410 return Result::INVALID_ARGUMENTS; 411 } 412 mInBuffer = tempInBuffer; 413 mOutBuffer = tempOutBuffer; 414 // The processing thread only reads these pointers after waking up by an event flag, 415 // so it's OK to update the pair non-atomically. 416 mHalInBufferPtr.store(mInBuffer->getHalBuffer(), std::memory_order_release); 417 mHalOutBufferPtr.store(mOutBuffer->getHalBuffer(), std::memory_order_release); 418 return Result::OK; 419 } 420 421 Result Effect::sendCommand(int commandCode, const char* commandName) { 422 return sendCommand(commandCode, commandName, 0, NULL); 423 } 424 425 Result Effect::sendCommand( 426 int commandCode, const char* commandName, uint32_t size, void* data) { 427 status_t status = (*mHandle)->command(mHandle, commandCode, size, data, 0, NULL); 428 return analyzeCommandStatus(commandName, sContextCallToCommand, status); 429 } 430 431 Result Effect::sendCommandReturningData( 432 int commandCode, const char* commandName, 433 uint32_t* replySize, void* replyData) { 434 return sendCommandReturningData(commandCode, commandName, 0, NULL, replySize, replyData); 435 } 436 437 Result Effect::sendCommandReturningData( 438 int commandCode, const char* commandName, 439 uint32_t size, void* data, 440 uint32_t* replySize, void* replyData) { 441 uint32_t expectedReplySize = *replySize; 442 status_t status = (*mHandle)->command(mHandle, commandCode, size, data, replySize, replyData); 443 if (status == OK && *replySize != expectedReplySize) { 444 status = -ENODATA; 445 } 446 return analyzeCommandStatus(commandName, sContextCallToCommand, status); 447 } 448 449 Result Effect::sendCommandReturningStatus(int commandCode, const char* commandName) { 450 return sendCommandReturningStatus(commandCode, commandName, 0, NULL); 451 } 452 453 Result Effect::sendCommandReturningStatus( 454 int commandCode, const char* commandName, uint32_t size, void* data) { 455 uint32_t replyCmdStatus; 456 uint32_t replySize = sizeof(uint32_t); 457 return sendCommandReturningStatusAndData( 458 commandCode, commandName, size, data, &replySize, &replyCmdStatus, replySize, []{}); 459 } 460 461 Result Effect::sendCommandReturningStatusAndData( 462 int commandCode, const char* commandName, 463 uint32_t size, void* data, 464 uint32_t* replySize, void* replyData, 465 uint32_t minReplySize, 466 CommandSuccessCallback onSuccess) { 467 status_t status = 468 (*mHandle)->command(mHandle, commandCode, size, data, replySize, replyData); 469 Result retval; 470 if (status == OK && minReplySize >= sizeof(uint32_t) && *replySize >= minReplySize) { 471 uint32_t commandStatus = *reinterpret_cast<uint32_t*>(replyData); 472 retval = analyzeCommandStatus(commandName, sContextResultOfCommand, commandStatus); 473 if (commandStatus == OK) { 474 onSuccess(); 475 } 476 } else { 477 retval = analyzeCommandStatus(commandName, sContextCallToCommand, status); 478 } 479 return retval; 480 } 481 482 Result Effect::setConfigImpl( 483 int commandCode, const char* commandName, 484 const EffectConfig& config, 485 const sp<IEffectBufferProviderCallback>& inputBufferProvider, 486 const sp<IEffectBufferProviderCallback>& outputBufferProvider) { 487 effect_config_t halConfig; 488 effectConfigToHal(config, &halConfig); 489 if (inputBufferProvider != 0) { 490 LOG_FATAL("Using input buffer provider is not supported"); 491 } 492 if (outputBufferProvider != 0) { 493 LOG_FATAL("Using output buffer provider is not supported"); 494 } 495 return sendCommandReturningStatus( 496 commandCode, commandName, sizeof(effect_config_t), &halConfig); 497 } 498 499 500 Result Effect::setParameterImpl( 501 uint32_t paramSize, const void* paramData, uint32_t valueSize, const void* valueData) { 502 std::vector<uint8_t> halParamBuffer = parameterToHal( 503 paramSize, paramData, valueSize, &valueData); 504 return sendCommandReturningStatus( 505 EFFECT_CMD_SET_PARAM, "SET_PARAM", halParamBuffer.size(), &halParamBuffer[0]); 506 } 507 508 // Methods from ::android::hardware::audio::effect::V2_0::IEffect follow. 509 Return<Result> Effect::init() { 510 return sendCommandReturningStatus(EFFECT_CMD_INIT, "INIT"); 511 } 512 513 Return<Result> Effect::setConfig( 514 const EffectConfig& config, 515 const sp<IEffectBufferProviderCallback>& inputBufferProvider, 516 const sp<IEffectBufferProviderCallback>& outputBufferProvider) { 517 return setConfigImpl( 518 EFFECT_CMD_SET_CONFIG, "SET_CONFIG", config, inputBufferProvider, outputBufferProvider); 519 } 520 521 Return<Result> Effect::reset() { 522 return sendCommand(EFFECT_CMD_RESET, "RESET"); 523 } 524 525 Return<Result> Effect::enable() { 526 return sendCommandReturningStatus(EFFECT_CMD_ENABLE, "ENABLE"); 527 } 528 529 Return<Result> Effect::disable() { 530 return sendCommandReturningStatus(EFFECT_CMD_DISABLE, "DISABLE"); 531 } 532 533 Return<Result> Effect::setDevice(AudioDevice device) { 534 uint32_t halDevice = static_cast<uint32_t>(device); 535 return sendCommand(EFFECT_CMD_SET_DEVICE, "SET_DEVICE", sizeof(uint32_t), &halDevice); 536 } 537 538 Return<void> Effect::setAndGetVolume( 539 const hidl_vec<uint32_t>& volumes, setAndGetVolume_cb _hidl_cb) { 540 uint32_t halDataSize; 541 std::unique_ptr<uint8_t[]> halData = hidlVecToHal(volumes, &halDataSize); 542 uint32_t halResultSize = halDataSize; 543 uint32_t halResult[volumes.size()]; 544 Result retval = sendCommandReturningData( 545 EFFECT_CMD_SET_VOLUME, "SET_VOLUME", 546 halDataSize, &halData[0], 547 &halResultSize, halResult); 548 hidl_vec<uint32_t> result; 549 if (retval == Result::OK) { 550 result.setToExternal(&halResult[0], halResultSize); 551 } 552 _hidl_cb(retval, result); 553 return Void(); 554 } 555 556 Return<Result> Effect::volumeChangeNotification(const hidl_vec<uint32_t>& volumes) { 557 uint32_t halDataSize; 558 std::unique_ptr<uint8_t[]> halData = hidlVecToHal(volumes, &halDataSize); 559 return sendCommand( 560 EFFECT_CMD_SET_VOLUME, "SET_VOLUME", 561 halDataSize, &halData[0]); 562 } 563 564 Return<Result> Effect::setAudioMode(AudioMode mode) { 565 uint32_t halMode = static_cast<uint32_t>(mode); 566 return sendCommand( 567 EFFECT_CMD_SET_AUDIO_MODE, "SET_AUDIO_MODE", sizeof(uint32_t), &halMode); 568 } 569 570 Return<Result> Effect::setConfigReverse( 571 const EffectConfig& config, 572 const sp<IEffectBufferProviderCallback>& inputBufferProvider, 573 const sp<IEffectBufferProviderCallback>& outputBufferProvider) { 574 return setConfigImpl(EFFECT_CMD_SET_CONFIG_REVERSE, "SET_CONFIG_REVERSE", 575 config, inputBufferProvider, outputBufferProvider); 576 } 577 578 Return<Result> Effect::setInputDevice(AudioDevice device) { 579 uint32_t halDevice = static_cast<uint32_t>(device); 580 return sendCommand( 581 EFFECT_CMD_SET_INPUT_DEVICE, "SET_INPUT_DEVICE", sizeof(uint32_t), &halDevice); 582 } 583 584 Return<void> Effect::getConfig(getConfig_cb _hidl_cb) { 585 getConfigImpl(EFFECT_CMD_GET_CONFIG, "GET_CONFIG", _hidl_cb); 586 return Void(); 587 } 588 589 Return<void> Effect::getConfigReverse(getConfigReverse_cb _hidl_cb) { 590 getConfigImpl(EFFECT_CMD_GET_CONFIG_REVERSE, "GET_CONFIG_REVERSE", _hidl_cb); 591 return Void(); 592 } 593 594 Return<void> Effect::getSupportedAuxChannelsConfigs( 595 uint32_t maxConfigs, getSupportedAuxChannelsConfigs_cb _hidl_cb) { 596 hidl_vec<EffectAuxChannelsConfig> result; 597 Result retval = getSupportedConfigsImpl( 598 EFFECT_FEATURE_AUX_CHANNELS, 599 maxConfigs, 600 sizeof(channel_config_t), 601 [&] (uint32_t supportedConfigs, void* configsData) { 602 result.resize(supportedConfigs); 603 channel_config_t *config = reinterpret_cast<channel_config_t*>(configsData); 604 for (size_t i = 0; i < result.size(); ++i) { 605 effectAuxChannelsConfigFromHal(*config++, &result[i]); 606 } 607 }); 608 _hidl_cb(retval, result); 609 return Void(); 610 } 611 612 Return<void> Effect::getAuxChannelsConfig(getAuxChannelsConfig_cb _hidl_cb) { 613 uint32_t halCmd = EFFECT_FEATURE_AUX_CHANNELS; 614 uint32_t halResult[alignedSizeIn<uint32_t>(sizeof(uint32_t) + sizeof(channel_config_t))]; 615 memset(halResult, 0, sizeof(halResult)); 616 uint32_t halResultSize = 0; 617 EffectAuxChannelsConfig result; 618 Result retval = getCurrentConfigImpl( 619 EFFECT_FEATURE_AUX_CHANNELS, 620 sizeof(channel_config_t), 621 [&] (void* configData) { 622 effectAuxChannelsConfigFromHal( 623 *reinterpret_cast<channel_config_t*>(configData), &result); 624 }); 625 _hidl_cb(retval, result); 626 return Void(); 627 } 628 629 Return<Result> Effect::setAuxChannelsConfig(const EffectAuxChannelsConfig& config) { 630 uint32_t halCmd[alignedSizeIn<uint32_t>(sizeof(uint32_t) + sizeof(channel_config_t))]; 631 halCmd[0] = EFFECT_FEATURE_AUX_CHANNELS; 632 effectAuxChannelsConfigToHal(config, reinterpret_cast<channel_config_t*>(&halCmd[1])); 633 return sendCommandReturningStatus(EFFECT_CMD_SET_FEATURE_CONFIG, 634 "SET_FEATURE_CONFIG AUX_CHANNELS", sizeof(halCmd), halCmd); 635 } 636 637 Return<Result> Effect::setAudioSource(AudioSource source) { 638 uint32_t halSource = static_cast<uint32_t>(source); 639 return sendCommand( 640 EFFECT_CMD_SET_AUDIO_SOURCE, "SET_AUDIO_SOURCE", sizeof(uint32_t), &halSource); 641 } 642 643 Return<Result> Effect::offload(const EffectOffloadParameter& param) { 644 effect_offload_param_t halParam; 645 effectOffloadParamToHal(param, &halParam); 646 return sendCommandReturningStatus( 647 EFFECT_CMD_OFFLOAD, "OFFLOAD", sizeof(effect_offload_param_t), &halParam); 648 } 649 650 Return<void> Effect::getDescriptor(getDescriptor_cb _hidl_cb) { 651 effect_descriptor_t halDescriptor; 652 memset(&halDescriptor, 0, sizeof(effect_descriptor_t)); 653 status_t status = (*mHandle)->get_descriptor(mHandle, &halDescriptor); 654 EffectDescriptor descriptor; 655 if (status == OK) { 656 effectDescriptorFromHal(halDescriptor, &descriptor); 657 } 658 _hidl_cb(analyzeStatus("get_descriptor", "", sContextCallFunction, status), descriptor); 659 return Void(); 660 } 661 662 Return<void> Effect::command( 663 uint32_t commandId, 664 const hidl_vec<uint8_t>& data, 665 uint32_t resultMaxSize, 666 command_cb _hidl_cb) { 667 uint32_t halDataSize; 668 std::unique_ptr<uint8_t[]> halData = hidlVecToHal(data, &halDataSize); 669 uint32_t halResultSize = resultMaxSize; 670 std::unique_ptr<uint8_t[]> halResult(new uint8_t[halResultSize]); 671 memset(&halResult[0], 0, halResultSize); 672 673 void* dataPtr = halDataSize > 0 ? &halData[0] : NULL; 674 void* resultPtr = halResultSize > 0 ? &halResult[0] : NULL; 675 status_t status = (*mHandle)->command( 676 mHandle, commandId, halDataSize, dataPtr, &halResultSize, resultPtr); 677 hidl_vec<uint8_t> result; 678 if (status == OK && resultPtr != NULL) { 679 result.setToExternal(&halResult[0], halResultSize); 680 } 681 _hidl_cb(status, result); 682 return Void(); 683 } 684 685 Return<Result> Effect::setParameter( 686 const hidl_vec<uint8_t>& parameter, const hidl_vec<uint8_t>& value) { 687 return setParameterImpl(parameter.size(), ¶meter[0], value.size(), &value[0]); 688 } 689 690 Return<void> Effect::getParameter( 691 const hidl_vec<uint8_t>& parameter, uint32_t valueMaxSize, getParameter_cb _hidl_cb) { 692 hidl_vec<uint8_t> value; 693 Result retval = getParameterImpl( 694 parameter.size(), 695 ¶meter[0], 696 valueMaxSize, 697 [&] (uint32_t valueSize, const void* valueData) { 698 value.setToExternal( 699 reinterpret_cast<uint8_t*>(const_cast<void*>(valueData)), valueSize); 700 }); 701 _hidl_cb(retval, value); 702 return Void(); 703 } 704 705 Return<void> Effect::getSupportedConfigsForFeature( 706 uint32_t featureId, 707 uint32_t maxConfigs, 708 uint32_t configSize, 709 getSupportedConfigsForFeature_cb _hidl_cb) { 710 uint32_t configCount = 0; 711 hidl_vec<uint8_t> result; 712 Result retval = getSupportedConfigsImpl( 713 featureId, 714 maxConfigs, 715 configSize, 716 [&] (uint32_t supportedConfigs, void* configsData) { 717 configCount = supportedConfigs; 718 result.resize(configCount * configSize); 719 memcpy(&result[0], configsData, result.size()); 720 }); 721 _hidl_cb(retval, configCount, result); 722 return Void(); 723 } 724 725 Return<void> Effect::getCurrentConfigForFeature( 726 uint32_t featureId, uint32_t configSize, getCurrentConfigForFeature_cb _hidl_cb) { 727 hidl_vec<uint8_t> result; 728 Result retval = getCurrentConfigImpl( 729 featureId, 730 configSize, 731 [&] (void* configData) { 732 result.resize(configSize); 733 memcpy(&result[0], configData, result.size()); 734 }); 735 _hidl_cb(retval, result); 736 return Void(); 737 } 738 739 Return<Result> Effect::setCurrentConfigForFeature( 740 uint32_t featureId, const hidl_vec<uint8_t>& configData) { 741 uint32_t halCmd[alignedSizeIn<uint32_t>(sizeof(uint32_t) + configData.size())]; 742 memset(halCmd, 0, sizeof(halCmd)); 743 halCmd[0] = featureId; 744 memcpy(&halCmd[1], &configData[0], configData.size()); 745 return sendCommandReturningStatus( 746 EFFECT_CMD_SET_FEATURE_CONFIG, "SET_FEATURE_CONFIG", sizeof(halCmd), halCmd); 747 } 748 749 Return<Result> Effect::close() { 750 if (mIsClosed) return Result::INVALID_STATE; 751 mIsClosed = true; 752 if (mProcessThread.get()) { 753 mStopProcessThread.store(true, std::memory_order_release); 754 } 755 if (mEfGroup) { 756 mEfGroup->wake(static_cast<uint32_t>(MessageQueueFlagBits::REQUEST_QUIT)); 757 } 758 return Result::OK; 759 } 760 761 } // namespace implementation 762 } // namespace V2_0 763 } // namespace effect 764 } // namespace audio 765 } // namespace hardware 766 } // namespace android 767