xref: /aosp_15_r20/hardware/interfaces/audio/effect/all-versions/default/Effect.cpp (revision 4d7e907c777eeecc4c5bd7cf640a754fac206ff7)
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, &param) != 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(), &parameter[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(), &parameter[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