Home | History | Annotate | Download | only in default
      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(), &parameter[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(), &parameter[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