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