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