• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 "Effect.h"
23 #include "common/all-versions/default/EffectMap.h"
24 
25 #define ATRACE_TAG ATRACE_TAG_AUDIO
26 #include <HidlUtils.h>
27 #include <android/log.h>
28 #include <cutils/properties.h>
29 #include <media/EffectsFactoryApi.h>
30 #include <mediautils/ScopedStatistics.h>
31 #include <sys/syscall.h>
32 #include <system/audio_effects/effect_spatializer.h>
33 #include <util/EffectUtils.h>
34 #include <utils/Trace.h>
35 
36 #include "VersionUtils.h"
37 
38 namespace android {
39 namespace hardware {
40 namespace audio {
41 namespace effect {
42 namespace CPP_VERSION {
43 namespace implementation {
44 
45 #if MAJOR_VERSION <= 6
46 using ::android::hardware::audio::common::COMMON_TYPES_CPP_VERSION::implementation::
47         AudioChannelBitfield;
48 #endif
49 using ::android::hardware::audio::common::COMMON_TYPES_CPP_VERSION::implementation::HidlUtils;
50 
51 namespace {
52 
53 /**
54  * Some basic scheduling tools.
55  */
56 namespace scheduler {
57 
getCpu()58 int getCpu() {
59     return sched_getcpu();
60 }
61 
getAffinity(pid_t tid)62 uint64_t getAffinity(pid_t tid) {
63     cpu_set_t set;
64     CPU_ZERO_S(sizeof(set), &set);
65 
66     if (sched_getaffinity(tid, sizeof(set), &set)) {
67         ALOGW("%s: for tid:%d returning 0, failed %s", __func__, tid, strerror(errno));
68         return 0;
69     }
70     const int count = CPU_COUNT_S(sizeof(set), &set);
71     uint64_t mask = 0;
72     for (int i = 0; i < CPU_SETSIZE; ++i) {
73         if (CPU_ISSET_S(i, sizeof(set), &set)) {
74             mask |= 1 << i;
75         }
76     }
77     ALOGV("%s: for tid:%d returning cpu count %d mask %llu", __func__, tid, count,
78           (unsigned long long)mask);
79     return mask;
80 }
81 
setAffinity(pid_t tid,uint64_t mask)82 status_t setAffinity(pid_t tid, uint64_t mask) {
83     cpu_set_t set;
84     CPU_ZERO_S(sizeof(set), &set);
85 
86     for (uint64_t m = mask; m != 0;) {
87         uint64_t tz = __builtin_ctz(m);
88         CPU_SET_S(tz, sizeof(set), &set);
89         m &= ~(1 << tz);
90     }
91     if (sched_setaffinity(tid, sizeof(set), &set)) {
92         ALOGW("%s: for tid:%d setting cpu mask %llu failed %s", __func__, tid,
93               (unsigned long long)mask, strerror(errno));
94         return -errno;
95     }
96     ALOGV("%s: for tid:%d setting cpu mask %llu", __func__, tid, (unsigned long long)mask);
97     return OK;
98 }
99 
setPriority(pid_t tid,int policy,int priority)100 __unused status_t setPriority(pid_t tid, int policy, int priority) {
101     struct sched_param param {
102         .sched_priority = priority,
103     };
104     if (sched_setscheduler(tid, policy, &param) != 0) {
105         ALOGW("%s: Cannot set FIFO priority for tid %d to policy %d priority %d  %s", __func__, tid,
106               policy, priority, strerror(errno));
107         return -errno;
108     }
109     ALOGV("%s: Successfully set priority for tid %d to policy %d priority %d", __func__, tid,
110           policy, priority);
111     return NO_ERROR;
112 }
113 
setUtilMin(pid_t tid,uint32_t utilMin)114 status_t setUtilMin(pid_t tid, uint32_t utilMin) {
115     // Currently, there is no wrapper in bionic: b/183240349.
116     struct {
117         uint32_t size;
118         uint32_t sched_policy;
119         uint64_t sched_flags;
120         int32_t sched_nice;
121         uint32_t sched_priority;
122         uint64_t sched_runtime;
123         uint64_t sched_deadline;
124         uint64_t sched_period;
125         uint32_t sched_util_min;
126         uint32_t sched_util_max;
127     } attr{
128             .size = sizeof(attr),
129             .sched_flags = SCHED_FLAG_KEEP_ALL | SCHED_FLAG_UTIL_CLAMP_MIN,
130             .sched_util_min = utilMin,
131     };
132 
133     if (syscall(__NR_sched_setattr, tid, &attr, 0 /* flags */)) {
134         ALOGW("%s: Cannot set sched_util_min for pid %d to %u  %s", __func__, tid, utilMin,
135               strerror(errno));
136         return -errno;
137     }
138     ALOGV("%s: Successfully set sched_util_min for pid %d to %u", __func__, tid, utilMin);
139     return NO_ERROR;
140 }
141 
142 /*
143    Attempts to raise the priority and usage of tid for spatialization.
144    Returns OK if everything works.
145 */
updateSpatializerPriority(pid_t tid)146 status_t updateSpatializerPriority(pid_t tid) {
147     status_t status = OK;
148 
149     const int cpu = getCpu();
150     ALOGV("%s: current CPU:%d", __func__, cpu);
151 
152     const auto currentAffinity = getAffinity(tid);
153     ALOGV("%s: current Affinity:%llx", __func__, (unsigned long long)currentAffinity);
154 
155     // Set the desired CPU core affinity.
156     // Typically this would be done to move the Spatializer effect off of the little cores.
157     // The mid cores and large cores typically have more FP/NEON units
158     // and will advantageously reduce power and prevent glitches due CPU limitations.
159     //
160     // Since this is SOC dependent, we do not set the core affinity here but
161     // prefer to set the util_clamp_min below.
162     //
163     constexpr uint64_t kDefaultAffinity = 0;
164     const int32_t desiredAffinity =
165             property_get_int32("audio.spatializer.effect.affinity", kDefaultAffinity);
166     if (desiredAffinity != 0 && (desiredAffinity & ~currentAffinity) == 0) {
167         const status_t localStatus = setAffinity(tid, desiredAffinity);
168         status = status ? status : localStatus;
169     }
170 
171     // Set the util_clamp_min.
172     // This is beneficial to reduce glitches when starting up, or due to scheduler
173     // thread statistics reset (e.g. core migration), which cause the CPU frequency to drop
174     // to minimum.
175     //
176     // Experimentation has found that moving to a mid core over a little core reduces
177     // power if the mid core (e.g. A76/78) has more (e.g. 2x) FP/NEON units
178     // than the little core (e.g. A55).
179     // A possible value is 300.
180     //
181     constexpr uint32_t kUtilMin = 0;
182     const int32_t utilMin = property_get_int32("audio.spatializer.effect.util_clamp_min", kUtilMin);
183     if (utilMin > 0 && utilMin <= 1024) {
184         const status_t localStatus = setUtilMin(tid, utilMin);
185         status = status ? status : localStatus;
186     }
187 
188 #if 0
189     // Provided for local vendor testing but not enabled as audioserver does this for us.
190     //
191     // Set priority if specified.
192     constexpr int32_t kRTPriorityMin = 1;
193     constexpr int32_t kRTPriorityMax = 3;
194     const int32_t priorityBoost =
195             property_get_int32("audio.spatializer.priority", kRTPriorityMin);
196     if (priorityBoost >= kRTPriorityMin && priorityBoost <= kRTPriorityMax) {
197         const status_t localStatus = scheduler::setPriority(threadId, SCHED_FIFO, priorityBoost);
198         status = status ? status : localStatus;
199     }
200 #endif
201 
202     return status;
203 }
204 
205 }  // namespace scheduler
206 
207 #define SCOPED_STATS()                                                       \
208     ::android::mediautils::ScopedStatistics scopedStatistics {               \
209         std::string("EffectHal::").append(__func__), mEffectHal->mStatistics \
210     }
211 
212 class ProcessThread : public Thread {
213    public:
214     // ProcessThread's lifespan never exceeds Effect's lifespan.
ProcessThread(std::atomic<bool> * stop,effect_handle_t effect,std::atomic<audio_buffer_t * > * inBuffer,std::atomic<audio_buffer_t * > * outBuffer,Effect::StatusMQ * statusMQ,EventFlag * efGroup,Effect * effectHal)215      ProcessThread(std::atomic<bool>* stop, effect_handle_t effect,
216                    std::atomic<audio_buffer_t*>* inBuffer, std::atomic<audio_buffer_t*>* outBuffer,
217                    Effect::StatusMQ* statusMQ, EventFlag* efGroup, Effect* effectHal)
218          : Thread(false /*canCallJava*/),
219            mStop(stop),
220            mEffect(effect),
221            mHasProcessReverse((*mEffect)->process_reverse != NULL),
222            mInBuffer(inBuffer),
223            mOutBuffer(outBuffer),
224            mStatusMQ(statusMQ),
225            mEfGroup(efGroup),
226            mEffectHal(effectHal) {}
~ProcessThread()227      virtual ~ProcessThread() {}
228 
229    private:
230     std::atomic<bool>* mStop;
231     effect_handle_t mEffect;
232     bool mHasProcessReverse;
233     std::atomic<audio_buffer_t*>* mInBuffer;
234     std::atomic<audio_buffer_t*>* mOutBuffer;
235     Effect::StatusMQ* mStatusMQ;
236     EventFlag* mEfGroup;
237     Effect* const mEffectHal;
238 
239     bool threadLoop() override;
240 };
241 
threadLoop()242 bool ProcessThread::threadLoop() {
243     // This implementation doesn't return control back to the Thread until it decides to stop,
244     // as the Thread uses mutexes, and this can lead to priority inversion.
245     while (!std::atomic_load_explicit(mStop, std::memory_order_acquire)) {
246         uint32_t efState = 0;
247         mEfGroup->wait(static_cast<uint32_t>(MessageQueueFlagBits::REQUEST_PROCESS_ALL), &efState);
248         if (!(efState & static_cast<uint32_t>(MessageQueueFlagBits::REQUEST_PROCESS_ALL)) ||
249             (efState & static_cast<uint32_t>(MessageQueueFlagBits::REQUEST_QUIT))) {
250             continue;  // Nothing to do or time to quit.
251         }
252         Result retval = Result::OK;
253         if (efState & static_cast<uint32_t>(MessageQueueFlagBits::REQUEST_PROCESS_REVERSE) &&
254             !mHasProcessReverse) {
255             retval = Result::NOT_SUPPORTED;
256         }
257 
258         if (retval == Result::OK) {
259             // affects both buffer pointers and their contents.
260             std::atomic_thread_fence(std::memory_order_acquire);
261             int32_t processResult;
262             audio_buffer_t* inBuffer =
263                 std::atomic_load_explicit(mInBuffer, std::memory_order_relaxed);
264             audio_buffer_t* outBuffer =
265                 std::atomic_load_explicit(mOutBuffer, std::memory_order_relaxed);
266             if (inBuffer != nullptr && outBuffer != nullptr) {
267                 // Time this effect process
268                 SCOPED_STATS();
269 
270                 if (efState & static_cast<uint32_t>(MessageQueueFlagBits::REQUEST_PROCESS)) {
271                     processResult = (*mEffect)->process(mEffect, inBuffer, outBuffer);
272                 } else {
273                     processResult = (*mEffect)->process_reverse(mEffect, inBuffer, outBuffer);
274                 }
275                 std::atomic_thread_fence(std::memory_order_release);
276             } else {
277                 ALOGE("processing buffers were not set before calling 'process'");
278                 processResult = -ENODEV;
279             }
280             switch (processResult) {
281                 case 0:
282                     retval = Result::OK;
283                     break;
284                 case -ENODATA:
285                     retval = Result::INVALID_STATE;
286                     break;
287                 case -EINVAL:
288                     retval = Result::INVALID_ARGUMENTS;
289                     break;
290                 default:
291                     retval = Result::NOT_INITIALIZED;
292             }
293         }
294         if (!mStatusMQ->write(&retval)) {
295             ALOGW("status message queue write failed");
296         }
297         mEfGroup->wake(static_cast<uint32_t>(MessageQueueFlagBits::DONE_PROCESSING));
298     }
299 
300     return false;
301 }
302 
303 }  // namespace
304 
305 // static
306 const char* Effect::sContextResultOfCommand = "returned status";
307 const char* Effect::sContextCallToCommand = "error";
308 const char* Effect::sContextCallFunction = sContextCallToCommand;
309 const char* Effect::sContextConversion = "conversion";
310 
Effect(bool isInput,effect_handle_t handle)311 Effect::Effect(bool isInput, effect_handle_t handle)
312     : mIsInput(isInput), mHandle(handle), mEfGroup(nullptr), mStopProcessThread(false) {
313     (void)mIsInput;  // prevent 'unused field' warnings in pre-V7 versions.
314 }
315 
~Effect()316 Effect::~Effect() {
317     ATRACE_CALL();
318     auto [_, handle] = closeImpl();
319     if (mProcessThread.get()) {
320         ATRACE_NAME("mProcessThread->join");
321         status_t status = mProcessThread->join();
322         ALOGE_IF(status, "processing thread exit error: %s", strerror(-status));
323     }
324     if (EventFlag* evFlag = mEfGroup.load(std::memory_order_acquire)) {
325         status_t status = EventFlag::deleteEventFlag(&evFlag);
326         ALOGE_IF(status, "processing MQ event flag deletion error: %s", strerror(-status));
327     }
328     mInBuffer.clear();
329     mOutBuffer.clear();
330 #if MAJOR_VERSION <= 5
331     int status = EffectRelease(handle);
332     ALOGW_IF(status, "Error releasing effect %p: %s", handle, strerror(-status));
333 #endif
334     EffectMap::getInstance().remove(handle);
335 }
336 
337 // static
338 template <typename T>
alignedSizeIn(size_t s)339 size_t Effect::alignedSizeIn(size_t s) {
340     return (s + sizeof(T) - 1) / sizeof(T);
341 }
342 
343 // static
344 template <typename T>
hidlVecToHal(const hidl_vec<T> & vec,uint32_t * halDataSize)345 std::unique_ptr<uint8_t[]> Effect::hidlVecToHal(const hidl_vec<T>& vec, uint32_t* halDataSize) {
346     // Due to bugs in HAL, they may attempt to write into the provided
347     // input buffer. The original binder buffer is r/o, thus it is needed
348     // to create a r/w version.
349     *halDataSize = vec.size() * sizeof(T);
350     std::unique_ptr<uint8_t[]> halData(new uint8_t[*halDataSize]);
351     memcpy(&halData[0], &vec[0], *halDataSize);
352     return halData;
353 }
354 
355 #if MAJOR_VERSION <= 6
356 
effectAuxChannelsConfigFromHal(const channel_config_t & halConfig,EffectAuxChannelsConfig * config)357 void Effect::effectAuxChannelsConfigFromHal(const channel_config_t& halConfig,
358                                             EffectAuxChannelsConfig* config) {
359     config->mainChannels = AudioChannelBitfield(halConfig.main_channels);
360     config->auxChannels = AudioChannelBitfield(halConfig.aux_channels);
361 }
362 
363 // static
effectAuxChannelsConfigToHal(const EffectAuxChannelsConfig & config,channel_config_t * halConfig)364 void Effect::effectAuxChannelsConfigToHal(const EffectAuxChannelsConfig& config,
365                                           channel_config_t* halConfig) {
366     halConfig->main_channels = static_cast<audio_channel_mask_t>(config.mainChannels);
367     halConfig->aux_channels = static_cast<audio_channel_mask_t>(config.auxChannels);
368 }
369 
370 #else  // MAJOR_VERSION <= 6
371 
effectAuxChannelsConfigFromHal(const channel_config_t & halConfig,EffectAuxChannelsConfig * config)372 void Effect::effectAuxChannelsConfigFromHal(const channel_config_t& halConfig,
373                                             EffectAuxChannelsConfig* config) {
374     (void)HidlUtils::audioChannelMaskFromHal(halConfig.main_channels, mIsInput,
375                                              &config->mainChannels);
376     (void)HidlUtils::audioChannelMaskFromHal(halConfig.aux_channels, mIsInput,
377                                              &config->auxChannels);
378 }
379 
380 // static
effectAuxChannelsConfigToHal(const EffectAuxChannelsConfig & config,channel_config_t * halConfig)381 void Effect::effectAuxChannelsConfigToHal(const EffectAuxChannelsConfig& config,
382                                           channel_config_t* halConfig) {
383     (void)HidlUtils::audioChannelMaskToHal(config.mainChannels, &halConfig->main_channels);
384     (void)HidlUtils::audioChannelMaskToHal(config.auxChannels, &halConfig->aux_channels);
385 }
386 
387 #endif  // MAJOR_VERSION <= 6
388 
389 // static
effectOffloadParamToHal(const EffectOffloadParameter & offload,effect_offload_param_t * halOffload)390 void Effect::effectOffloadParamToHal(const EffectOffloadParameter& offload,
391                                      effect_offload_param_t* halOffload) {
392     halOffload->isOffload = offload.isOffload;
393     halOffload->ioHandle = offload.ioHandle;
394 }
395 
396 // static
parameterToHal(uint32_t paramSize,const void * paramData,uint32_t valueSize,const void ** valueData,std::vector<uint8_t> * halParamBuffer)397 bool Effect::parameterToHal(uint32_t paramSize, const void* paramData, uint32_t valueSize,
398                             const void** valueData, std::vector<uint8_t>* halParamBuffer) {
399     constexpr size_t kMaxSize = EFFECT_PARAM_SIZE_MAX - sizeof(effect_param_t);
400     if (paramSize > kMaxSize) {
401         ALOGE("%s: Parameter size is too big: %" PRIu32, __func__, paramSize);
402         return false;
403     }
404     size_t valueOffsetFromData = alignedSizeIn<uint32_t>(paramSize) * sizeof(uint32_t);
405     if (valueOffsetFromData > kMaxSize) {
406         ALOGE("%s: Aligned parameter size is too big: %zu", __func__, valueOffsetFromData);
407         return false;
408     }
409     if (valueSize > kMaxSize - valueOffsetFromData) {
410         ALOGE("%s: Value size is too big: %" PRIu32 ", max size is %zu", __func__, valueSize,
411               kMaxSize - valueOffsetFromData);
412         android_errorWriteLog(0x534e4554, "237291425");
413         return false;
414     }
415     size_t halParamBufferSize = sizeof(effect_param_t) + valueOffsetFromData + valueSize;
416     halParamBuffer->resize(halParamBufferSize, 0);
417     effect_param_t* halParam = reinterpret_cast<effect_param_t*>(halParamBuffer->data());
418     halParam->psize = paramSize;
419     halParam->vsize = valueSize;
420     memcpy(halParam->data, paramData, paramSize);
421     if (valueData) {
422         if (*valueData) {
423             // Value data is provided.
424             memcpy(halParam->data + valueOffsetFromData, *valueData, valueSize);
425         } else {
426             // The caller needs the pointer to the value data location.
427             *valueData = halParam->data + valueOffsetFromData;
428         }
429     }
430     return true;
431 }
432 
analyzeCommandStatus(const char * commandName,const char * context,status_t status)433 Result Effect::analyzeCommandStatus(const char* commandName, const char* context, status_t status) {
434     return analyzeStatus("command", commandName, context, status);
435 }
436 
analyzeStatus(const char * funcName,const char * subFuncName,const char * contextDescription,status_t status)437 Result Effect::analyzeStatus(const char* funcName, const char* subFuncName,
438                              const char* contextDescription, status_t status) {
439     if (status != OK) {
440         std::lock_guard<std::mutex> lock(mLock);
441         ALOGW("Effect %p %s %s %s: %s", mHandle, funcName, subFuncName, contextDescription,
442               strerror(-status));
443     }
444     switch (status) {
445         case OK:
446             return Result::OK;
447         case -EINVAL:
448             return Result::INVALID_ARGUMENTS;
449         case -ENODATA:
450             return Result::INVALID_STATE;
451         case -ENODEV:
452             return Result::NOT_INITIALIZED;
453         case -ENOMEM:
454             return Result::RESULT_TOO_BIG;
455         case -ENOSYS:
456             return Result::NOT_SUPPORTED;
457         default:
458             return Result::INVALID_STATE;
459     }
460 }
461 
462 #define RETURN_IF_EFFECT_CLOSED()          \
463     if (mHandle == kInvalidEffectHandle) { \
464         return Result::INVALID_STATE;      \
465     }
466 #define RETURN_RESULT_IF_EFFECT_CLOSED(result)   \
467     if (mHandle == kInvalidEffectHandle) {       \
468         _hidl_cb(Result::INVALID_STATE, result); \
469         return Void();                           \
470     }
471 
getConfigImpl(int commandCode,const char * commandName,GetConfigCallback _hidl_cb)472 Return<void> Effect::getConfigImpl(int commandCode, const char* commandName,
473                                    GetConfigCallback _hidl_cb) {
474     uint32_t halResultSize = sizeof(effect_config_t);
475     effect_config_t halConfig{};
476     status_t status = OK;
477     {
478         std::lock_guard<std::mutex> lock(mLock);
479         RETURN_RESULT_IF_EFFECT_CLOSED(EffectConfig());
480         status = (*mHandle)->command(mHandle, commandCode, 0, NULL, &halResultSize, &halConfig);
481     }
482     EffectConfig config;
483     if (status == OK) {
484         status = EffectUtils::effectConfigFromHal(halConfig, mIsInput, &config);
485     }
486     _hidl_cb(analyzeCommandStatus(commandName, sContextCallToCommand, status), config);
487     return Void();
488 }
489 
getCurrentConfigImpl(uint32_t featureId,uint32_t configSize,GetCurrentConfigSuccessCallback onSuccess)490 Result Effect::getCurrentConfigImpl(uint32_t featureId, uint32_t configSize,
491                                     GetCurrentConfigSuccessCallback onSuccess) {
492     if (configSize > kMaxDataSize - sizeof(uint32_t)) {
493         ALOGE("%s: Config size is too big: %" PRIu32, __func__, configSize);
494         android_errorWriteLog(0x534e4554, "240266798");
495         return Result::INVALID_ARGUMENTS;
496     }
497     uint32_t halCmd = featureId;
498     std::vector<uint32_t> halResult(alignedSizeIn<uint32_t>(sizeof(uint32_t) + configSize), 0);
499     uint32_t halResultSize = 0;
500     return sendCommandReturningStatusAndData(
501             EFFECT_CMD_GET_FEATURE_CONFIG, "GET_FEATURE_CONFIG", sizeof(uint32_t), &halCmd,
502             &halResultSize, &halResult[0], sizeof(uint32_t), [&] { onSuccess(&halResult[1]); });
503 }
504 
getParameterImpl(uint32_t paramSize,const void * paramData,uint32_t requestValueSize,uint32_t replyValueSize,GetParameterSuccessCallback onSuccess)505 Result Effect::getParameterImpl(uint32_t paramSize, const void* paramData,
506                                 uint32_t requestValueSize, uint32_t replyValueSize,
507                                 GetParameterSuccessCallback onSuccess) {
508     // As it is unknown what method HAL uses for copying the provided parameter data,
509     // it is safer to make sure that input and output buffers do not overlap.
510     std::vector<uint8_t> halCmdBuffer;
511     if (!parameterToHal(paramSize, paramData, requestValueSize, nullptr, &halCmdBuffer)) {
512         return Result::INVALID_ARGUMENTS;
513     }
514     const void* valueData = nullptr;
515     std::vector<uint8_t> halParamBuffer;
516     if (!parameterToHal(paramSize, paramData, replyValueSize, &valueData, &halParamBuffer)) {
517         return Result::INVALID_ARGUMENTS;
518     }
519     uint32_t halParamBufferSize = halParamBuffer.size();
520 
521     return sendCommandReturningStatusAndData(
522         EFFECT_CMD_GET_PARAM, "GET_PARAM", halCmdBuffer.size(), &halCmdBuffer[0],
523         &halParamBufferSize, &halParamBuffer[0], sizeof(effect_param_t), [&] {
524             effect_param_t* halParam = reinterpret_cast<effect_param_t*>(&halParamBuffer[0]);
525             onSuccess(halParam->vsize, valueData);
526         });
527 }
528 
getSupportedConfigsImpl(uint32_t featureId,uint32_t maxConfigs,uint32_t configSize,GetSupportedConfigsSuccessCallback onSuccess)529 Result Effect::getSupportedConfigsImpl(uint32_t featureId, uint32_t maxConfigs, uint32_t configSize,
530                                        GetSupportedConfigsSuccessCallback onSuccess) {
531     if (maxConfigs != 0 && configSize > (kMaxDataSize - 2 * sizeof(uint32_t)) / maxConfigs) {
532         ALOGE("%s: Config size is too big: %" PRIu32, __func__, configSize);
533         return Result::INVALID_ARGUMENTS;
534     }
535     uint32_t halCmd[2] = {featureId, maxConfigs};
536     uint32_t halResultSize = 2 * sizeof(uint32_t) + maxConfigs * configSize;
537     std::vector<uint8_t> halResult(static_cast<size_t>(halResultSize), 0);
538     return sendCommandReturningStatusAndData(
539         EFFECT_CMD_GET_FEATURE_SUPPORTED_CONFIGS, "GET_FEATURE_SUPPORTED_CONFIGS", sizeof(halCmd),
540         halCmd, &halResultSize, &halResult[0], 2 * sizeof(uint32_t), [&] {
541             uint32_t* halResult32 = reinterpret_cast<uint32_t*>(&halResult[0]);
542             uint32_t supportedConfigs = *(++halResult32);  // skip status field
543             if (supportedConfigs > maxConfigs) supportedConfigs = maxConfigs;
544             onSuccess(supportedConfigs, ++halResult32);
545         });
546 }
547 
prepareForProcessing(prepareForProcessing_cb _hidl_cb)548 Return<void> Effect::prepareForProcessing(prepareForProcessing_cb _hidl_cb) {
549     {
550         std::lock_guard<std::mutex> lock(mLock);
551         RETURN_RESULT_IF_EFFECT_CLOSED(StatusMQ::Descriptor());
552     }
553     status_t status;
554     // Create message queue.
555     if (mStatusMQ) {
556         ALOGE("the client attempts to call prepareForProcessing_cb twice");
557         _hidl_cb(Result::INVALID_STATE, StatusMQ::Descriptor());
558         return Void();
559     }
560     std::unique_ptr<StatusMQ> tempStatusMQ(new StatusMQ(1, true /*EventFlag*/));
561     if (!tempStatusMQ->isValid()) {
562         ALOGE_IF(!tempStatusMQ->isValid(), "status MQ is invalid");
563         _hidl_cb(Result::INVALID_ARGUMENTS, StatusMQ::Descriptor());
564         return Void();
565     }
566     EventFlag* evFlag = nullptr;
567     status = EventFlag::createEventFlag(tempStatusMQ->getEventFlagWord(), &evFlag);
568     if (status != OK || !evFlag) {
569         ALOGE("failed creating event flag for status MQ: %s", strerror(-status));
570         _hidl_cb(Result::INVALID_ARGUMENTS, StatusMQ::Descriptor());
571         return Void();
572     }
573     mEfGroup.store(evFlag, std::memory_order_release);
574 
575     {
576         std::lock_guard<std::mutex> lock(mLock);
577         // Create and launch the thread.
578         mProcessThread = new ProcessThread(&mStopProcessThread, mHandle, &mHalInBufferPtr,
579                                            &mHalOutBufferPtr, tempStatusMQ.get(), evFlag, this);
580     }
581     status = mProcessThread->run("effect", PRIORITY_URGENT_AUDIO);
582     if (status != OK) {
583         ALOGW("failed to start effect processing thread: %s", strerror(-status));
584         _hidl_cb(Result::INVALID_ARGUMENTS, MQDescriptorSync<Result>());
585         return Void();
586     }
587 
588     // For a spatializer effect, we perform scheduler adjustments to reduce glitches and power.
589     // We do it here instead of the ProcessThread::threadLoop to ensure that mHandle is valid.
590     {
591         std::lock_guard<std::mutex> lock(mLock);
592         RETURN_RESULT_IF_EFFECT_CLOSED(StatusMQ::Descriptor());
593         if (effect_descriptor_t halDescriptor{};
594             (*mHandle)->get_descriptor(mHandle, &halDescriptor) == NO_ERROR &&
595             memcmp(&halDescriptor.type, FX_IID_SPATIALIZER, sizeof(effect_uuid_t)) == 0) {
596             const status_t status = scheduler::updateSpatializerPriority(mProcessThread->getTid());
597             ALOGW_IF(status != OK, "Failed to update Spatializer priority");
598         }
599     }
600 
601     mStatusMQ = std::move(tempStatusMQ);
602     _hidl_cb(Result::OK, *mStatusMQ->getDesc());
603     return Void();
604 }
605 
setProcessBuffers(const AudioBuffer & inBuffer,const AudioBuffer & outBuffer)606 Return<Result> Effect::setProcessBuffers(const AudioBuffer& inBuffer,
607                                          const AudioBuffer& outBuffer) {
608     {
609         std::lock_guard<std::mutex> lock(mLock);
610         RETURN_IF_EFFECT_CLOSED();
611     }
612     AudioBufferManager& manager = AudioBufferManager::getInstance();
613     sp<AudioBufferWrapper> tempInBuffer, tempOutBuffer;
614     if (!manager.wrap(inBuffer, &tempInBuffer)) {
615         ALOGE("Could not map memory of the input buffer");
616         return Result::INVALID_ARGUMENTS;
617     }
618     if (!manager.wrap(outBuffer, &tempOutBuffer)) {
619         ALOGE("Could not map memory of the output buffer");
620         return Result::INVALID_ARGUMENTS;
621     }
622     mInBuffer = tempInBuffer;
623     mOutBuffer = tempOutBuffer;
624     // The processing thread only reads these pointers after waking up by an event flag,
625     // so it's OK to update the pair non-atomically.
626     mHalInBufferPtr.store(mInBuffer->getHalBuffer(), std::memory_order_release);
627     mHalOutBufferPtr.store(mOutBuffer->getHalBuffer(), std::memory_order_release);
628     return Result::OK;
629 }
630 
sendCommand(int commandCode,const char * commandName)631 Result Effect::sendCommand(int commandCode, const char* commandName) {
632     return sendCommand(commandCode, commandName, 0, NULL);
633 }
634 
sendCommand(int commandCode,const char * commandName,uint32_t size,void * data)635 Result Effect::sendCommand(int commandCode, const char* commandName, uint32_t size, void* data) {
636     status_t status = OK;
637     {
638         std::lock_guard<std::mutex> lock(mLock);
639         RETURN_IF_EFFECT_CLOSED();
640         status = (*mHandle)->command(mHandle, commandCode, size, data, 0, NULL);
641     }
642     return analyzeCommandStatus(commandName, sContextCallToCommand, status);
643 }
644 
sendCommandReturningData(int commandCode,const char * commandName,uint32_t * replySize,void * replyData)645 Result Effect::sendCommandReturningData(int commandCode, const char* commandName,
646                                         uint32_t* replySize, void* replyData) {
647     return sendCommandReturningData(commandCode, commandName, 0, NULL, replySize, replyData);
648 }
649 
sendCommandReturningData(int commandCode,const char * commandName,uint32_t size,void * data,uint32_t * replySize,void * replyData)650 Result Effect::sendCommandReturningData(int commandCode, const char* commandName, uint32_t size,
651                                         void* data, uint32_t* replySize, void* replyData) {
652     uint32_t expectedReplySize = *replySize;
653     status_t status = OK;
654     {
655         std::lock_guard<std::mutex> lock(mLock);
656         RETURN_IF_EFFECT_CLOSED();
657         status = (*mHandle)->command(mHandle, commandCode, size, data, replySize, replyData);
658     }
659     if (status == OK && *replySize != expectedReplySize) {
660         status = -ENODATA;
661     }
662     return analyzeCommandStatus(commandName, sContextCallToCommand, status);
663 }
664 
sendCommandReturningStatus(int commandCode,const char * commandName)665 Result Effect::sendCommandReturningStatus(int commandCode, const char* commandName) {
666     return sendCommandReturningStatus(commandCode, commandName, 0, NULL);
667 }
668 
sendCommandReturningStatus(int commandCode,const char * commandName,uint32_t size,void * data)669 Result Effect::sendCommandReturningStatus(int commandCode, const char* commandName, uint32_t size,
670                                           void* data) {
671     uint32_t replyCmdStatus;
672     uint32_t replySize = sizeof(uint32_t);
673     return sendCommandReturningStatusAndData(commandCode, commandName, size, data, &replySize,
674                                              &replyCmdStatus, replySize, [] {});
675 }
676 
sendCommandReturningStatusAndData(int commandCode,const char * commandName,uint32_t size,void * data,uint32_t * replySize,void * replyData,uint32_t minReplySize,CommandSuccessCallback onSuccess)677 Result Effect::sendCommandReturningStatusAndData(int commandCode, const char* commandName,
678                                                  uint32_t size, void* data, uint32_t* replySize,
679                                                  void* replyData, uint32_t minReplySize,
680                                                  CommandSuccessCallback onSuccess) {
681     status_t status = OK;
682     {
683         std::lock_guard<std::mutex> lock(mLock);
684         RETURN_IF_EFFECT_CLOSED();
685         status = (*mHandle)->command(mHandle, commandCode, size, data, replySize, replyData);
686     }
687     Result retval;
688     if (status == OK && minReplySize >= sizeof(uint32_t) && *replySize >= minReplySize) {
689         uint32_t commandStatus = *reinterpret_cast<uint32_t*>(replyData);
690         retval = analyzeCommandStatus(commandName, sContextResultOfCommand, commandStatus);
691         if (commandStatus == OK) {
692             onSuccess();
693         }
694     } else {
695         retval = analyzeCommandStatus(commandName, sContextCallToCommand, status);
696     }
697     return retval;
698 }
699 
setConfigImpl(int commandCode,const char * commandName,const EffectConfig & config,const sp<IEffectBufferProviderCallback> & inputBufferProvider,const sp<IEffectBufferProviderCallback> & outputBufferProvider)700 Result Effect::setConfigImpl(int commandCode, const char* commandName, const EffectConfig& config,
701                              const sp<IEffectBufferProviderCallback>& inputBufferProvider,
702                              const sp<IEffectBufferProviderCallback>& outputBufferProvider) {
703     effect_config_t halConfig;
704     EffectUtils::effectConfigToHal(config, &halConfig);
705     if (inputBufferProvider != 0) {
706         LOG_FATAL("Using input buffer provider is not supported");
707     }
708     if (outputBufferProvider != 0) {
709         LOG_FATAL("Using output buffer provider is not supported");
710     }
711     return sendCommandReturningStatus(commandCode, commandName, sizeof(effect_config_t),
712                                       &halConfig);
713 }
714 
setParameterImpl(uint32_t paramSize,const void * paramData,uint32_t valueSize,const void * valueData)715 Result Effect::setParameterImpl(uint32_t paramSize, const void* paramData, uint32_t valueSize,
716                                 const void* valueData) {
717     std::vector<uint8_t> halParamBuffer;
718     if (!parameterToHal(paramSize, paramData, valueSize, &valueData, &halParamBuffer)) {
719         return Result::INVALID_ARGUMENTS;
720     }
721     return sendCommandReturningStatus(EFFECT_CMD_SET_PARAM, "SET_PARAM", halParamBuffer.size(),
722                                       &halParamBuffer[0]);
723 }
724 
725 // Methods from ::android::hardware::audio::effect::CPP_VERSION::IEffect follow.
init()726 Return<Result> Effect::init() {
727     return sendCommandReturningStatus(EFFECT_CMD_INIT, "INIT");
728 }
729 
setConfig(const EffectConfig & config,const sp<IEffectBufferProviderCallback> & inputBufferProvider,const sp<IEffectBufferProviderCallback> & outputBufferProvider)730 Return<Result> Effect::setConfig(const EffectConfig& config,
731                                  const sp<IEffectBufferProviderCallback>& inputBufferProvider,
732                                  const sp<IEffectBufferProviderCallback>& outputBufferProvider) {
733     return setConfigImpl(EFFECT_CMD_SET_CONFIG, "SET_CONFIG", config, inputBufferProvider,
734                          outputBufferProvider);
735 }
736 
reset()737 Return<Result> Effect::reset() {
738     return sendCommand(EFFECT_CMD_RESET, "RESET");
739 }
740 
enable()741 Return<Result> Effect::enable() {
742     return sendCommandReturningStatus(EFFECT_CMD_ENABLE, "ENABLE");
743 }
744 
disable()745 Return<Result> Effect::disable() {
746     return sendCommandReturningStatus(EFFECT_CMD_DISABLE, "DISABLE");
747 }
748 
setAudioSource(AudioSource source)749 Return<Result> Effect::setAudioSource(
750 #if MAJOR_VERSION <= 6
751         AudioSource source
752 #else
753         const AudioSource& source
754 #endif
755 ) {
756     audio_source_t halSource;
757     if (status_t status = HidlUtils::audioSourceToHal(source, &halSource); status == NO_ERROR) {
758         uint32_t halSourceParam = static_cast<uint32_t>(halSource);
759         return sendCommand(EFFECT_CMD_SET_AUDIO_SOURCE, "SET_AUDIO_SOURCE", sizeof(uint32_t),
760                            &halSourceParam);
761     } else {
762         return analyzeStatus(__func__, "audioSourceToHal", sContextConversion, status);
763     }
764 }
765 
766 #if MAJOR_VERSION <= 6
767 
setDevice(AudioDeviceBitfield device)768 Return<Result> Effect::setDevice(AudioDeviceBitfield device) {
769     uint32_t halDevice = static_cast<uint32_t>(device);
770     return sendCommand(EFFECT_CMD_SET_DEVICE, "SET_DEVICE", sizeof(uint32_t), &halDevice);
771 }
772 
setInputDevice(AudioDeviceBitfield device)773 Return<Result> Effect::setInputDevice(AudioDeviceBitfield device) {
774     uint32_t halDevice = static_cast<uint32_t>(device);
775     return sendCommand(EFFECT_CMD_SET_INPUT_DEVICE, "SET_INPUT_DEVICE", sizeof(uint32_t),
776                        &halDevice);
777 }
778 
779 #else  // MAJOR_VERSION <= 6
780 
setDevice(const DeviceAddress & device)781 Return<Result> Effect::setDevice(const DeviceAddress& device) {
782     audio_devices_t halDevice;
783     char halDeviceAddress[AUDIO_DEVICE_MAX_ADDRESS_LEN];
784     if (status_t status = HidlUtils::deviceAddressToHal(device, &halDevice, halDeviceAddress);
785         status == NO_ERROR) {
786         uint32_t halDeviceParam = static_cast<uint32_t>(halDevice);
787         return sendCommand(EFFECT_CMD_SET_DEVICE, "SET_DEVICE", sizeof(uint32_t), &halDeviceParam);
788     } else {
789         return analyzeStatus(__func__, "deviceAddressToHal", sContextConversion, status);
790     }
791 }
792 
setInputDevice(const DeviceAddress & device)793 Return<Result> Effect::setInputDevice(const DeviceAddress& device) {
794     audio_devices_t halDevice;
795     char halDeviceAddress[AUDIO_DEVICE_MAX_ADDRESS_LEN];
796     if (status_t status = HidlUtils::deviceAddressToHal(device, &halDevice, halDeviceAddress);
797         status == NO_ERROR) {
798         uint32_t halDeviceParam = static_cast<uint32_t>(halDevice);
799         return sendCommand(EFFECT_CMD_SET_INPUT_DEVICE, "SET_INPUT_DEVICE", sizeof(uint32_t),
800                            &halDeviceParam);
801     } else {
802         return analyzeStatus(__func__, "deviceAddressToHal", sContextConversion, status);
803     }
804 }
805 
806 #endif  // MAJOR_VERSION <= 6
807 
setAndGetVolume(const hidl_vec<uint32_t> & volumes,setAndGetVolume_cb _hidl_cb)808 Return<void> Effect::setAndGetVolume(const hidl_vec<uint32_t>& volumes,
809                                      setAndGetVolume_cb _hidl_cb) {
810     uint32_t halDataSize;
811     std::unique_ptr<uint8_t[]> halData = hidlVecToHal(volumes, &halDataSize);
812     uint32_t halResultSize = halDataSize;
813     std::vector<uint32_t> halResult(volumes.size(), 0);
814     Result retval = sendCommandReturningData(EFFECT_CMD_SET_VOLUME, "SET_VOLUME", halDataSize,
815                                              &halData[0], &halResultSize, &halResult[0]);
816     hidl_vec<uint32_t> result;
817     if (retval == Result::OK) {
818         result.setToExternal(&halResult[0], halResultSize);
819     }
820     _hidl_cb(retval, result);
821     return Void();
822 }
823 
volumeChangeNotification(const hidl_vec<uint32_t> & volumes)824 Return<Result> Effect::volumeChangeNotification(const hidl_vec<uint32_t>& volumes) {
825     uint32_t halDataSize;
826     std::unique_ptr<uint8_t[]> halData = hidlVecToHal(volumes, &halDataSize);
827     return sendCommand(EFFECT_CMD_SET_VOLUME, "SET_VOLUME", halDataSize, &halData[0]);
828 }
829 
setAudioMode(AudioMode mode)830 Return<Result> Effect::setAudioMode(AudioMode mode) {
831     uint32_t halMode = static_cast<uint32_t>(mode);
832     return sendCommand(EFFECT_CMD_SET_AUDIO_MODE, "SET_AUDIO_MODE", sizeof(uint32_t), &halMode);
833 }
834 
setConfigReverse(const EffectConfig & config,const sp<IEffectBufferProviderCallback> & inputBufferProvider,const sp<IEffectBufferProviderCallback> & outputBufferProvider)835 Return<Result> Effect::setConfigReverse(
836     const EffectConfig& config, const sp<IEffectBufferProviderCallback>& inputBufferProvider,
837     const sp<IEffectBufferProviderCallback>& outputBufferProvider) {
838     return setConfigImpl(EFFECT_CMD_SET_CONFIG_REVERSE, "SET_CONFIG_REVERSE", config,
839                          inputBufferProvider, outputBufferProvider);
840 }
841 
getConfig(getConfig_cb _hidl_cb)842 Return<void> Effect::getConfig(getConfig_cb _hidl_cb) {
843     return getConfigImpl(EFFECT_CMD_GET_CONFIG, "GET_CONFIG", _hidl_cb);
844 }
845 
getConfigReverse(getConfigReverse_cb _hidl_cb)846 Return<void> Effect::getConfigReverse(getConfigReverse_cb _hidl_cb) {
847     return getConfigImpl(EFFECT_CMD_GET_CONFIG_REVERSE, "GET_CONFIG_REVERSE", _hidl_cb);
848 }
849 
getSupportedAuxChannelsConfigs(uint32_t maxConfigs,getSupportedAuxChannelsConfigs_cb _hidl_cb)850 Return<void> Effect::getSupportedAuxChannelsConfigs(uint32_t maxConfigs,
851                                                     getSupportedAuxChannelsConfigs_cb _hidl_cb) {
852     hidl_vec<EffectAuxChannelsConfig> result;
853     Result retval = getSupportedConfigsImpl(
854         EFFECT_FEATURE_AUX_CHANNELS, maxConfigs, sizeof(channel_config_t),
855         [&](uint32_t supportedConfigs, void* configsData) {
856             result.resize(supportedConfigs);
857             channel_config_t* config = reinterpret_cast<channel_config_t*>(configsData);
858             for (size_t i = 0; i < result.size(); ++i) {
859                 effectAuxChannelsConfigFromHal(*config++, &result[i]);
860             }
861         });
862     _hidl_cb(retval, result);
863     return Void();
864 }
865 
getAuxChannelsConfig(getAuxChannelsConfig_cb _hidl_cb)866 Return<void> Effect::getAuxChannelsConfig(getAuxChannelsConfig_cb _hidl_cb) {
867     EffectAuxChannelsConfig result;
868     Result retval = getCurrentConfigImpl(
869         EFFECT_FEATURE_AUX_CHANNELS, sizeof(channel_config_t), [&](void* configData) {
870             effectAuxChannelsConfigFromHal(*reinterpret_cast<channel_config_t*>(configData),
871                                            &result);
872         });
873     _hidl_cb(retval, result);
874     return Void();
875 }
876 
setAuxChannelsConfig(const EffectAuxChannelsConfig & config)877 Return<Result> Effect::setAuxChannelsConfig(const EffectAuxChannelsConfig& config) {
878     std::vector<uint32_t> halCmd(
879             alignedSizeIn<uint32_t>(sizeof(uint32_t) + sizeof(channel_config_t)), 0);
880     halCmd[0] = EFFECT_FEATURE_AUX_CHANNELS;
881     effectAuxChannelsConfigToHal(config, reinterpret_cast<channel_config_t*>(&halCmd[1]));
882     return sendCommandReturningStatus(EFFECT_CMD_SET_FEATURE_CONFIG,
883                                       "SET_FEATURE_CONFIG AUX_CHANNELS", halCmd.size(), &halCmd[0]);
884 }
885 
offload(const EffectOffloadParameter & param)886 Return<Result> Effect::offload(const EffectOffloadParameter& param) {
887     effect_offload_param_t halParam;
888     effectOffloadParamToHal(param, &halParam);
889     return sendCommandReturningStatus(EFFECT_CMD_OFFLOAD, "OFFLOAD", sizeof(effect_offload_param_t),
890                                       &halParam);
891 }
892 
getDescriptor(getDescriptor_cb _hidl_cb)893 Return<void> Effect::getDescriptor(getDescriptor_cb _hidl_cb) {
894     effect_descriptor_t halDescriptor;
895     memset(&halDescriptor, 0, sizeof(effect_descriptor_t));
896     status_t status = OK;
897     {
898         std::lock_guard<std::mutex> lock(mLock);
899         RETURN_RESULT_IF_EFFECT_CLOSED(EffectDescriptor());
900         status = (*mHandle)->get_descriptor(mHandle, &halDescriptor);
901     }
902     EffectDescriptor descriptor;
903     if (status == OK) {
904         status = EffectUtils::effectDescriptorFromHal(halDescriptor, &descriptor);
905     }
906     _hidl_cb(analyzeStatus("get_descriptor", "", sContextCallFunction, status), descriptor);
907     return Void();
908 }
909 
command(uint32_t commandId,const hidl_vec<uint8_t> & data,uint32_t resultMaxSize,command_cb _hidl_cb)910 Return<void> Effect::command(uint32_t commandId, const hidl_vec<uint8_t>& data,
911                              uint32_t resultMaxSize, command_cb _hidl_cb) {
912     uint32_t halDataSize;
913     std::unique_ptr<uint8_t[]> halData = hidlVecToHal(data, &halDataSize);
914     uint32_t halResultSize = resultMaxSize;
915     std::unique_ptr<uint8_t[]> halResult(new uint8_t[halResultSize]);
916     memset(&halResult[0], 0, halResultSize);
917 
918     void* dataPtr = halDataSize > 0 ? &halData[0] : NULL;
919     void* resultPtr = halResultSize > 0 ? &halResult[0] : NULL;
920     status_t status = BAD_VALUE;
921     switch (commandId) {
922         case 'gtid':  // retrieve the tid, used for spatializer priority boost
923             if (halDataSize == 0 && resultMaxSize == sizeof(int32_t)) {
924                 auto ptid = (int32_t*)resultPtr;
925                 ptid[0] = mProcessThread ? mProcessThread->getTid() : -1;
926                 status = OK;
927                 break;  // we have handled 'gtid' here.
928             }
929             [[fallthrough]];  // allow 'gtid' overload (checked halDataSize and resultMaxSize).
930         default:
931             {
932                 std::lock_guard<std::mutex> lock(mLock);
933                 if (mHandle == kInvalidEffectHandle) {
934                     _hidl_cb(-ENODATA, hidl_vec<uint8_t>());
935                     return Void();
936                 }
937                 status = (*mHandle)->command(mHandle, commandId, halDataSize, dataPtr,
938                                             &halResultSize, resultPtr);
939             }
940             break;
941     }
942     hidl_vec<uint8_t> result;
943     if (status == OK && resultPtr != NULL) {
944         result.setToExternal(&halResult[0], halResultSize);
945     }
946     _hidl_cb(status, result);
947     return Void();
948 }
949 
setParameter(const hidl_vec<uint8_t> & parameter,const hidl_vec<uint8_t> & value)950 Return<Result> Effect::setParameter(const hidl_vec<uint8_t>& parameter,
951                                     const hidl_vec<uint8_t>& value) {
952     return setParameterImpl(parameter.size(), &parameter[0], value.size(), &value[0]);
953 }
954 
getParameter(const hidl_vec<uint8_t> & parameter,uint32_t valueMaxSize,getParameter_cb _hidl_cb)955 Return<void> Effect::getParameter(const hidl_vec<uint8_t>& parameter, uint32_t valueMaxSize,
956                                   getParameter_cb _hidl_cb) {
957     hidl_vec<uint8_t> value;
958     Result retval = getParameterImpl(
959         parameter.size(), &parameter[0], valueMaxSize,
960         [&](uint32_t valueSize, const void* valueData) {
961             value.setToExternal(reinterpret_cast<uint8_t*>(const_cast<void*>(valueData)),
962                                 valueSize);
963         });
964     _hidl_cb(retval, value);
965     return Void();
966 }
967 
getSupportedConfigsForFeature(uint32_t featureId,uint32_t maxConfigs,uint32_t configSize,getSupportedConfigsForFeature_cb _hidl_cb)968 Return<void> Effect::getSupportedConfigsForFeature(uint32_t featureId, uint32_t maxConfigs,
969                                                    uint32_t configSize,
970                                                    getSupportedConfigsForFeature_cb _hidl_cb) {
971     uint32_t configCount = 0;
972     hidl_vec<uint8_t> result;
973     Result retval = getSupportedConfigsImpl(featureId, maxConfigs, configSize,
974                                             [&](uint32_t supportedConfigs, void* configsData) {
975                                                 configCount = supportedConfigs;
976                                                 result.resize(configCount * configSize);
977                                                 memcpy(&result[0], configsData, result.size());
978                                             });
979     _hidl_cb(retval, configCount, result);
980     return Void();
981 }
982 
getCurrentConfigForFeature(uint32_t featureId,uint32_t configSize,getCurrentConfigForFeature_cb _hidl_cb)983 Return<void> Effect::getCurrentConfigForFeature(uint32_t featureId, uint32_t configSize,
984                                                 getCurrentConfigForFeature_cb _hidl_cb) {
985     hidl_vec<uint8_t> result;
986     Result retval = getCurrentConfigImpl(featureId, configSize, [&](void* configData) {
987         result.resize(configSize);
988         memcpy(&result[0], configData, result.size());
989     });
990     _hidl_cb(retval, result);
991     return Void();
992 }
993 
setCurrentConfigForFeature(uint32_t featureId,const hidl_vec<uint8_t> & configData)994 Return<Result> Effect::setCurrentConfigForFeature(uint32_t featureId,
995                                                   const hidl_vec<uint8_t>& configData) {
996     std::vector<uint32_t> halCmd(alignedSizeIn<uint32_t>(sizeof(uint32_t) + configData.size()), 0);
997     halCmd[0] = featureId;
998     memcpy(&halCmd[1], &configData[0], configData.size());
999     return sendCommandReturningStatus(EFFECT_CMD_SET_FEATURE_CONFIG, "SET_FEATURE_CONFIG",
1000                                       halCmd.size(), &halCmd[0]);
1001 }
1002 
closeImpl()1003 std::tuple<Result, effect_handle_t> Effect::closeImpl() {
1004     if (mStopProcessThread.load(std::memory_order_relaxed)) {  // only this thread modifies
1005         return {Result::INVALID_STATE, kInvalidEffectHandle};
1006     }
1007     mStopProcessThread.store(true, std::memory_order_release);
1008     EventFlag* evFlag = mEfGroup.load(std::memory_order_acquire);
1009     if (evFlag) {
1010         evFlag->wake(static_cast<uint32_t>(
1011             MessageQueueFlagBits::REQUEST_QUIT));
1012     }
1013     effect_handle_t handle;
1014     {
1015         std::lock_guard<std::mutex> lock(mLock);
1016         handle = mHandle;
1017         mHandle = kInvalidEffectHandle;
1018     }
1019 #if MAJOR_VERSION <= 5
1020     return {Result::OK, handle};
1021 #elif MAJOR_VERSION >= 6
1022     // No need to join the processing thread, it is part of the API contract that the client
1023     // must finish processing before closing the effect.
1024     Result retval = analyzeStatus("EffectRelease", "", sContextCallFunction, EffectRelease(handle));
1025     EffectMap::getInstance().remove(handle);
1026     return {retval, handle};
1027 #endif
1028 }
1029 
close()1030 Return<Result> Effect::close() {
1031     {
1032         std::lock_guard<std::mutex> lock(mLock);
1033         RETURN_IF_EFFECT_CLOSED();
1034     }
1035     auto [result, _] = closeImpl();
1036     return result;
1037 }
1038 
debug(const hidl_handle & fd,const hidl_vec<hidl_string> &)1039 Return<void> Effect::debug(const hidl_handle& fd, const hidl_vec<hidl_string>& /* options */) {
1040     if (fd.getNativeHandle() != nullptr && fd->numFds == 1) {
1041         uint32_t cmdData = fd->data[0];
1042         (void)sendCommand(EFFECT_CMD_DUMP, "DUMP", sizeof(cmdData), &cmdData);
1043         const std::string s = mStatistics->dump();
1044         if (s.size() != 0) write(cmdData, s.c_str(), s.size());
1045     }
1046     return Void();
1047 }
1048 
1049 }  // namespace implementation
1050 }  // namespace CPP_VERSION
1051 }  // namespace effect
1052 }  // namespace audio
1053 }  // namespace hardware
1054 }  // namespace android
1055