xref: /aosp_15_r20/frameworks/av/media/libaudiohal/impl/EffectHalHidl.cpp (revision ec779b8e0859a360c3d303172224686826e6e0e1)
1*ec779b8eSAndroid Build Coastguard Worker /*
2*ec779b8eSAndroid Build Coastguard Worker  * Copyright (C) 2016 The Android Open Source Project
3*ec779b8eSAndroid Build Coastguard Worker  *
4*ec779b8eSAndroid Build Coastguard Worker  * Licensed under the Apache License, Version 2.0 (the "License");
5*ec779b8eSAndroid Build Coastguard Worker  * you may not use this file except in compliance with the License.
6*ec779b8eSAndroid Build Coastguard Worker  * You may obtain a copy of the License at
7*ec779b8eSAndroid Build Coastguard Worker  *
8*ec779b8eSAndroid Build Coastguard Worker  *      http://www.apache.org/licenses/LICENSE-2.0
9*ec779b8eSAndroid Build Coastguard Worker  *
10*ec779b8eSAndroid Build Coastguard Worker  * Unless required by applicable law or agreed to in writing, software
11*ec779b8eSAndroid Build Coastguard Worker  * distributed under the License is distributed on an "AS IS" BASIS,
12*ec779b8eSAndroid Build Coastguard Worker  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13*ec779b8eSAndroid Build Coastguard Worker  * See the License for the specific language governing permissions and
14*ec779b8eSAndroid Build Coastguard Worker  * limitations under the License.
15*ec779b8eSAndroid Build Coastguard Worker  */
16*ec779b8eSAndroid Build Coastguard Worker 
17*ec779b8eSAndroid Build Coastguard Worker #define LOG_TAG "EffectHalHidl"
18*ec779b8eSAndroid Build Coastguard Worker //#define LOG_NDEBUG 0
19*ec779b8eSAndroid Build Coastguard Worker 
20*ec779b8eSAndroid Build Coastguard Worker #include <android/hidl/manager/1.0/IServiceManager.h>
21*ec779b8eSAndroid Build Coastguard Worker #include <android-base/stringprintf.h>
22*ec779b8eSAndroid Build Coastguard Worker #include <common/all-versions/VersionUtils.h>
23*ec779b8eSAndroid Build Coastguard Worker #include <cutils/native_handle.h>
24*ec779b8eSAndroid Build Coastguard Worker #include <cutils/properties.h>
25*ec779b8eSAndroid Build Coastguard Worker #include <hwbinder/IPCThreadState.h>
26*ec779b8eSAndroid Build Coastguard Worker #include <media/EffectsFactoryApi.h>
27*ec779b8eSAndroid Build Coastguard Worker #include <mediautils/SchedulingPolicyService.h>
28*ec779b8eSAndroid Build Coastguard Worker #include <mediautils/TimeCheck.h>
29*ec779b8eSAndroid Build Coastguard Worker #include <system/audio_effects/effect_spatializer.h>
30*ec779b8eSAndroid Build Coastguard Worker #include <utils/Log.h>
31*ec779b8eSAndroid Build Coastguard Worker 
32*ec779b8eSAndroid Build Coastguard Worker #include <util/EffectUtils.h>
33*ec779b8eSAndroid Build Coastguard Worker 
34*ec779b8eSAndroid Build Coastguard Worker #include "EffectBufferHalHidl.h"
35*ec779b8eSAndroid Build Coastguard Worker #include "EffectHalHidl.h"
36*ec779b8eSAndroid Build Coastguard Worker 
37*ec779b8eSAndroid Build Coastguard Worker using ::android::hardware::audio::common::utils::EnumBitfield;
38*ec779b8eSAndroid Build Coastguard Worker using ::android::hardware::audio::effect::CPP_VERSION::implementation::EffectUtils;
39*ec779b8eSAndroid Build Coastguard Worker using ::android::hardware::hidl_vec;
40*ec779b8eSAndroid Build Coastguard Worker using ::android::hardware::MQDescriptorSync;
41*ec779b8eSAndroid Build Coastguard Worker using ::android::hardware::Return;
42*ec779b8eSAndroid Build Coastguard Worker 
43*ec779b8eSAndroid Build Coastguard Worker namespace android {
44*ec779b8eSAndroid Build Coastguard Worker namespace effect {
45*ec779b8eSAndroid Build Coastguard Worker 
46*ec779b8eSAndroid Build Coastguard Worker using namespace ::android::hardware::audio::common::CPP_VERSION;
47*ec779b8eSAndroid Build Coastguard Worker using namespace ::android::hardware::audio::effect::CPP_VERSION;
48*ec779b8eSAndroid Build Coastguard Worker 
EffectHalHidl(const sp<IEffect> & effect,uint64_t effectId)49*ec779b8eSAndroid Build Coastguard Worker EffectHalHidl::EffectHalHidl(const sp<IEffect>& effect, uint64_t effectId)
50*ec779b8eSAndroid Build Coastguard Worker         : EffectConversionHelperHidl("EffectHalHidl"),
51*ec779b8eSAndroid Build Coastguard Worker           mEffect(effect), mEffectId(effectId), mBuffersChanged(true), mEfGroup(nullptr) {
52*ec779b8eSAndroid Build Coastguard Worker     effect_descriptor_t halDescriptor{};
53*ec779b8eSAndroid Build Coastguard Worker     if (EffectHalHidl::getDescriptor(&halDescriptor) == NO_ERROR) {
54*ec779b8eSAndroid Build Coastguard Worker         mIsInput = (halDescriptor.flags & EFFECT_FLAG_TYPE_PRE_PROC) == EFFECT_FLAG_TYPE_PRE_PROC;
55*ec779b8eSAndroid Build Coastguard Worker         const bool isSpatializer =
56*ec779b8eSAndroid Build Coastguard Worker                 memcmp(&halDescriptor.type, FX_IID_SPATIALIZER, sizeof(effect_uuid_t)) == 0;
57*ec779b8eSAndroid Build Coastguard Worker         if (isSpatializer) {
58*ec779b8eSAndroid Build Coastguard Worker             constexpr int32_t kRTPriorityMin = 1;
59*ec779b8eSAndroid Build Coastguard Worker             constexpr int32_t kRTPriorityMax = 3;
60*ec779b8eSAndroid Build Coastguard Worker             const int32_t priorityBoost = property_get_int32("audio.spatializer.priority", 1);
61*ec779b8eSAndroid Build Coastguard Worker             if (priorityBoost >= kRTPriorityMin && priorityBoost <= kRTPriorityMax) {
62*ec779b8eSAndroid Build Coastguard Worker                 ALOGD("%s: audio.spatializer.priority %d on effect %lld",
63*ec779b8eSAndroid Build Coastguard Worker                          __func__, priorityBoost, (long long)effectId);
64*ec779b8eSAndroid Build Coastguard Worker                 mHalThreadPriority = priorityBoost;
65*ec779b8eSAndroid Build Coastguard Worker             }
66*ec779b8eSAndroid Build Coastguard Worker         }
67*ec779b8eSAndroid Build Coastguard Worker     }
68*ec779b8eSAndroid Build Coastguard Worker }
69*ec779b8eSAndroid Build Coastguard Worker 
~EffectHalHidl()70*ec779b8eSAndroid Build Coastguard Worker EffectHalHidl::~EffectHalHidl() {
71*ec779b8eSAndroid Build Coastguard Worker     if (mEffect != 0) {
72*ec779b8eSAndroid Build Coastguard Worker         close();
73*ec779b8eSAndroid Build Coastguard Worker         mEffect.clear();
74*ec779b8eSAndroid Build Coastguard Worker         hardware::IPCThreadState::self()->flushCommands();
75*ec779b8eSAndroid Build Coastguard Worker     }
76*ec779b8eSAndroid Build Coastguard Worker     if (mEfGroup) {
77*ec779b8eSAndroid Build Coastguard Worker         EventFlag::deleteEventFlag(&mEfGroup);
78*ec779b8eSAndroid Build Coastguard Worker     }
79*ec779b8eSAndroid Build Coastguard Worker }
80*ec779b8eSAndroid Build Coastguard Worker 
setInBuffer(const sp<EffectBufferHalInterface> & buffer)81*ec779b8eSAndroid Build Coastguard Worker status_t EffectHalHidl::setInBuffer(const sp<EffectBufferHalInterface>& buffer) {
82*ec779b8eSAndroid Build Coastguard Worker     TIME_CHECK();
83*ec779b8eSAndroid Build Coastguard Worker 
84*ec779b8eSAndroid Build Coastguard Worker     if (!mBuffersChanged) {
85*ec779b8eSAndroid Build Coastguard Worker         if (buffer.get() == nullptr || mInBuffer.get() == nullptr) {
86*ec779b8eSAndroid Build Coastguard Worker             mBuffersChanged = buffer.get() != mInBuffer.get();
87*ec779b8eSAndroid Build Coastguard Worker         } else {
88*ec779b8eSAndroid Build Coastguard Worker             mBuffersChanged = buffer->audioBuffer() != mInBuffer->audioBuffer();
89*ec779b8eSAndroid Build Coastguard Worker         }
90*ec779b8eSAndroid Build Coastguard Worker     }
91*ec779b8eSAndroid Build Coastguard Worker     mInBuffer = buffer;
92*ec779b8eSAndroid Build Coastguard Worker     return OK;
93*ec779b8eSAndroid Build Coastguard Worker }
94*ec779b8eSAndroid Build Coastguard Worker 
setOutBuffer(const sp<EffectBufferHalInterface> & buffer)95*ec779b8eSAndroid Build Coastguard Worker status_t EffectHalHidl::setOutBuffer(const sp<EffectBufferHalInterface>& buffer) {
96*ec779b8eSAndroid Build Coastguard Worker     TIME_CHECK();
97*ec779b8eSAndroid Build Coastguard Worker 
98*ec779b8eSAndroid Build Coastguard Worker     if (!mBuffersChanged) {
99*ec779b8eSAndroid Build Coastguard Worker         if (buffer.get() == nullptr || mOutBuffer.get() == nullptr) {
100*ec779b8eSAndroid Build Coastguard Worker             mBuffersChanged = buffer.get() != mOutBuffer.get();
101*ec779b8eSAndroid Build Coastguard Worker         } else {
102*ec779b8eSAndroid Build Coastguard Worker             mBuffersChanged = buffer->audioBuffer() != mOutBuffer->audioBuffer();
103*ec779b8eSAndroid Build Coastguard Worker         }
104*ec779b8eSAndroid Build Coastguard Worker     }
105*ec779b8eSAndroid Build Coastguard Worker     mOutBuffer = buffer;
106*ec779b8eSAndroid Build Coastguard Worker     return OK;
107*ec779b8eSAndroid Build Coastguard Worker }
108*ec779b8eSAndroid Build Coastguard Worker 
process()109*ec779b8eSAndroid Build Coastguard Worker status_t EffectHalHidl::process() {
110*ec779b8eSAndroid Build Coastguard Worker     // TIME_CHECK();  // TODO(b/243839867) reenable only when optimized.
111*ec779b8eSAndroid Build Coastguard Worker 
112*ec779b8eSAndroid Build Coastguard Worker     return processImpl(static_cast<uint32_t>(MessageQueueFlagBits::REQUEST_PROCESS));
113*ec779b8eSAndroid Build Coastguard Worker }
114*ec779b8eSAndroid Build Coastguard Worker 
processReverse()115*ec779b8eSAndroid Build Coastguard Worker status_t EffectHalHidl::processReverse() {
116*ec779b8eSAndroid Build Coastguard Worker     // TIME_CHECK();  // TODO(b/243839867) reenable only when optimized.
117*ec779b8eSAndroid Build Coastguard Worker 
118*ec779b8eSAndroid Build Coastguard Worker     return processImpl(static_cast<uint32_t>(MessageQueueFlagBits::REQUEST_PROCESS_REVERSE));
119*ec779b8eSAndroid Build Coastguard Worker }
120*ec779b8eSAndroid Build Coastguard Worker 
prepareForProcessing()121*ec779b8eSAndroid Build Coastguard Worker status_t EffectHalHidl::prepareForProcessing() {
122*ec779b8eSAndroid Build Coastguard Worker     std::unique_ptr<StatusMQ> tempStatusMQ;
123*ec779b8eSAndroid Build Coastguard Worker     Result retval;
124*ec779b8eSAndroid Build Coastguard Worker     Return<void> ret = mEffect->prepareForProcessing(
125*ec779b8eSAndroid Build Coastguard Worker             [&](Result r, const MQDescriptorSync<Result>& statusMQ) {
126*ec779b8eSAndroid Build Coastguard Worker                 retval = r;
127*ec779b8eSAndroid Build Coastguard Worker                 if (retval == Result::OK) {
128*ec779b8eSAndroid Build Coastguard Worker                     tempStatusMQ.reset(new StatusMQ(statusMQ));
129*ec779b8eSAndroid Build Coastguard Worker                     if (tempStatusMQ->isValid() && tempStatusMQ->getEventFlagWord()) {
130*ec779b8eSAndroid Build Coastguard Worker                         EventFlag::createEventFlag(tempStatusMQ->getEventFlagWord(), &mEfGroup);
131*ec779b8eSAndroid Build Coastguard Worker                     }
132*ec779b8eSAndroid Build Coastguard Worker                 }
133*ec779b8eSAndroid Build Coastguard Worker             });
134*ec779b8eSAndroid Build Coastguard Worker     if (!ret.isOk() || retval != Result::OK) {
135*ec779b8eSAndroid Build Coastguard Worker         return ret.isOk() ? analyzeResult(retval) : FAILED_TRANSACTION;
136*ec779b8eSAndroid Build Coastguard Worker     }
137*ec779b8eSAndroid Build Coastguard Worker     if (!tempStatusMQ || !tempStatusMQ->isValid() || !mEfGroup) {
138*ec779b8eSAndroid Build Coastguard Worker         ALOGE_IF(!tempStatusMQ, "Failed to obtain status message queue for effects");
139*ec779b8eSAndroid Build Coastguard Worker         ALOGE_IF(tempStatusMQ && !tempStatusMQ->isValid(),
140*ec779b8eSAndroid Build Coastguard Worker                 "Status message queue for effects is invalid");
141*ec779b8eSAndroid Build Coastguard Worker         ALOGE_IF(!mEfGroup, "Event flag creation for effects failed");
142*ec779b8eSAndroid Build Coastguard Worker         return NO_INIT;
143*ec779b8eSAndroid Build Coastguard Worker     }
144*ec779b8eSAndroid Build Coastguard Worker 
145*ec779b8eSAndroid Build Coastguard Worker     (void)checkHalThreadPriority();
146*ec779b8eSAndroid Build Coastguard Worker     mStatusMQ = std::move(tempStatusMQ);
147*ec779b8eSAndroid Build Coastguard Worker     return OK;
148*ec779b8eSAndroid Build Coastguard Worker }
149*ec779b8eSAndroid Build Coastguard Worker 
needToResetBuffers()150*ec779b8eSAndroid Build Coastguard Worker bool EffectHalHidl::needToResetBuffers() {
151*ec779b8eSAndroid Build Coastguard Worker     if (mBuffersChanged) return true;
152*ec779b8eSAndroid Build Coastguard Worker     bool inBufferFrameCountUpdated = mInBuffer->checkFrameCountChange();
153*ec779b8eSAndroid Build Coastguard Worker     bool outBufferFrameCountUpdated = mOutBuffer->checkFrameCountChange();
154*ec779b8eSAndroid Build Coastguard Worker     return inBufferFrameCountUpdated || outBufferFrameCountUpdated;
155*ec779b8eSAndroid Build Coastguard Worker }
156*ec779b8eSAndroid Build Coastguard Worker 
processImpl(uint32_t mqFlag)157*ec779b8eSAndroid Build Coastguard Worker status_t EffectHalHidl::processImpl(uint32_t mqFlag) {
158*ec779b8eSAndroid Build Coastguard Worker     if (mEffect == 0 || mInBuffer == 0 || mOutBuffer == 0) return NO_INIT;
159*ec779b8eSAndroid Build Coastguard Worker     status_t status;
160*ec779b8eSAndroid Build Coastguard Worker     if (!mStatusMQ && (status = prepareForProcessing()) != OK) {
161*ec779b8eSAndroid Build Coastguard Worker         return status;
162*ec779b8eSAndroid Build Coastguard Worker     }
163*ec779b8eSAndroid Build Coastguard Worker     if (needToResetBuffers() && (status = setProcessBuffers()) != OK) {
164*ec779b8eSAndroid Build Coastguard Worker         return status;
165*ec779b8eSAndroid Build Coastguard Worker     }
166*ec779b8eSAndroid Build Coastguard Worker     // The data is already in the buffers, just need to flush it and wake up the server side.
167*ec779b8eSAndroid Build Coastguard Worker     std::atomic_thread_fence(std::memory_order_release);
168*ec779b8eSAndroid Build Coastguard Worker     mEfGroup->wake(mqFlag);
169*ec779b8eSAndroid Build Coastguard Worker     uint32_t efState = 0;
170*ec779b8eSAndroid Build Coastguard Worker retry:
171*ec779b8eSAndroid Build Coastguard Worker     status_t ret = mEfGroup->wait(
172*ec779b8eSAndroid Build Coastguard Worker             static_cast<uint32_t>(MessageQueueFlagBits::DONE_PROCESSING), &efState);
173*ec779b8eSAndroid Build Coastguard Worker     if (efState & static_cast<uint32_t>(MessageQueueFlagBits::DONE_PROCESSING)) {
174*ec779b8eSAndroid Build Coastguard Worker         Result retval = Result::NOT_INITIALIZED;
175*ec779b8eSAndroid Build Coastguard Worker         mStatusMQ->read(&retval);
176*ec779b8eSAndroid Build Coastguard Worker         if (retval == Result::OK || retval == Result::INVALID_STATE) {
177*ec779b8eSAndroid Build Coastguard Worker             // Sync back the changed contents of the buffer.
178*ec779b8eSAndroid Build Coastguard Worker             std::atomic_thread_fence(std::memory_order_acquire);
179*ec779b8eSAndroid Build Coastguard Worker         }
180*ec779b8eSAndroid Build Coastguard Worker         return analyzeResult(retval);
181*ec779b8eSAndroid Build Coastguard Worker     }
182*ec779b8eSAndroid Build Coastguard Worker     if (ret == -EAGAIN || ret == -EINTR) {
183*ec779b8eSAndroid Build Coastguard Worker         // Spurious wakeup. This normally retries no more than once.
184*ec779b8eSAndroid Build Coastguard Worker         goto retry;
185*ec779b8eSAndroid Build Coastguard Worker     }
186*ec779b8eSAndroid Build Coastguard Worker     return ret;
187*ec779b8eSAndroid Build Coastguard Worker }
188*ec779b8eSAndroid Build Coastguard Worker 
setProcessBuffers()189*ec779b8eSAndroid Build Coastguard Worker status_t EffectHalHidl::setProcessBuffers() {
190*ec779b8eSAndroid Build Coastguard Worker     Return<Result> ret = mEffect->setProcessBuffers(
191*ec779b8eSAndroid Build Coastguard Worker             static_cast<EffectBufferHalHidl*>(mInBuffer.get())->hidlBuffer(),
192*ec779b8eSAndroid Build Coastguard Worker             static_cast<EffectBufferHalHidl*>(mOutBuffer.get())->hidlBuffer());
193*ec779b8eSAndroid Build Coastguard Worker     if (ret.isOk() && ret == Result::OK) {
194*ec779b8eSAndroid Build Coastguard Worker         mBuffersChanged = false;
195*ec779b8eSAndroid Build Coastguard Worker         return OK;
196*ec779b8eSAndroid Build Coastguard Worker     }
197*ec779b8eSAndroid Build Coastguard Worker     return ret.isOk() ? analyzeResult(ret) : FAILED_TRANSACTION;
198*ec779b8eSAndroid Build Coastguard Worker }
199*ec779b8eSAndroid Build Coastguard Worker 
command(uint32_t cmdCode,uint32_t cmdSize,void * pCmdData,uint32_t * replySize,void * pReplyData)200*ec779b8eSAndroid Build Coastguard Worker status_t EffectHalHidl::command(uint32_t cmdCode, uint32_t cmdSize, void *pCmdData,
201*ec779b8eSAndroid Build Coastguard Worker         uint32_t *replySize, void *pReplyData) {
202*ec779b8eSAndroid Build Coastguard Worker     TIME_CHECK();
203*ec779b8eSAndroid Build Coastguard Worker 
204*ec779b8eSAndroid Build Coastguard Worker     if (mEffect == 0) return NO_INIT;
205*ec779b8eSAndroid Build Coastguard Worker 
206*ec779b8eSAndroid Build Coastguard Worker     // Special cases.
207*ec779b8eSAndroid Build Coastguard Worker     if (cmdCode == EFFECT_CMD_SET_CONFIG || cmdCode == EFFECT_CMD_SET_CONFIG_REVERSE) {
208*ec779b8eSAndroid Build Coastguard Worker         return setConfigImpl(cmdCode, cmdSize, pCmdData, replySize, pReplyData);
209*ec779b8eSAndroid Build Coastguard Worker     } else if (cmdCode == EFFECT_CMD_GET_CONFIG || cmdCode == EFFECT_CMD_GET_CONFIG_REVERSE) {
210*ec779b8eSAndroid Build Coastguard Worker         return getConfigImpl(cmdCode, replySize, pReplyData);
211*ec779b8eSAndroid Build Coastguard Worker     }
212*ec779b8eSAndroid Build Coastguard Worker 
213*ec779b8eSAndroid Build Coastguard Worker     // Common case.
214*ec779b8eSAndroid Build Coastguard Worker     hidl_vec<uint8_t> hidlData;
215*ec779b8eSAndroid Build Coastguard Worker     if (pCmdData != nullptr && cmdSize > 0) {
216*ec779b8eSAndroid Build Coastguard Worker         hidlData.setToExternal(reinterpret_cast<uint8_t*>(pCmdData), cmdSize);
217*ec779b8eSAndroid Build Coastguard Worker     }
218*ec779b8eSAndroid Build Coastguard Worker     status_t status;
219*ec779b8eSAndroid Build Coastguard Worker     uint32_t replySizeStub = 0;
220*ec779b8eSAndroid Build Coastguard Worker     if (replySize == nullptr || pReplyData == nullptr) replySize = &replySizeStub;
221*ec779b8eSAndroid Build Coastguard Worker     Return<void> ret = mEffect->command(cmdCode, hidlData, *replySize,
222*ec779b8eSAndroid Build Coastguard Worker             [&](int32_t s, const hidl_vec<uint8_t>& result) {
223*ec779b8eSAndroid Build Coastguard Worker                 status = s;
224*ec779b8eSAndroid Build Coastguard Worker                 if (status == 0) {
225*ec779b8eSAndroid Build Coastguard Worker                     if (*replySize > result.size()) *replySize = result.size();
226*ec779b8eSAndroid Build Coastguard Worker                     if (pReplyData != nullptr && *replySize > 0) {
227*ec779b8eSAndroid Build Coastguard Worker                         memcpy(pReplyData, &result[0], *replySize);
228*ec779b8eSAndroid Build Coastguard Worker                     }
229*ec779b8eSAndroid Build Coastguard Worker                 }
230*ec779b8eSAndroid Build Coastguard Worker             });
231*ec779b8eSAndroid Build Coastguard Worker     return ret.isOk() ? status : FAILED_TRANSACTION;
232*ec779b8eSAndroid Build Coastguard Worker }
233*ec779b8eSAndroid Build Coastguard Worker 
getDescriptor(effect_descriptor_t * pDescriptor)234*ec779b8eSAndroid Build Coastguard Worker status_t EffectHalHidl::getDescriptor(effect_descriptor_t *pDescriptor) {
235*ec779b8eSAndroid Build Coastguard Worker     TIME_CHECK();
236*ec779b8eSAndroid Build Coastguard Worker 
237*ec779b8eSAndroid Build Coastguard Worker     if (mEffect == 0) return NO_INIT;
238*ec779b8eSAndroid Build Coastguard Worker     Result retval = Result::NOT_INITIALIZED;
239*ec779b8eSAndroid Build Coastguard Worker     Return<void> ret = mEffect->getDescriptor(
240*ec779b8eSAndroid Build Coastguard Worker             [&](Result r, const EffectDescriptor& result) {
241*ec779b8eSAndroid Build Coastguard Worker                 retval = r;
242*ec779b8eSAndroid Build Coastguard Worker                 if (retval == Result::OK) {
243*ec779b8eSAndroid Build Coastguard Worker                     EffectUtils::effectDescriptorToHal(result, pDescriptor);
244*ec779b8eSAndroid Build Coastguard Worker                 }
245*ec779b8eSAndroid Build Coastguard Worker             });
246*ec779b8eSAndroid Build Coastguard Worker     return ret.isOk() ? analyzeResult(retval) : FAILED_TRANSACTION;
247*ec779b8eSAndroid Build Coastguard Worker }
248*ec779b8eSAndroid Build Coastguard Worker 
close()249*ec779b8eSAndroid Build Coastguard Worker status_t EffectHalHidl::close() {
250*ec779b8eSAndroid Build Coastguard Worker     TIME_CHECK();
251*ec779b8eSAndroid Build Coastguard Worker 
252*ec779b8eSAndroid Build Coastguard Worker     if (mEffect == 0) return NO_INIT;
253*ec779b8eSAndroid Build Coastguard Worker     Return<Result> ret = mEffect->close();
254*ec779b8eSAndroid Build Coastguard Worker     return ret.isOk() ? analyzeResult(ret) : FAILED_TRANSACTION;
255*ec779b8eSAndroid Build Coastguard Worker }
256*ec779b8eSAndroid Build Coastguard Worker 
dump(int fd)257*ec779b8eSAndroid Build Coastguard Worker status_t EffectHalHidl::dump(int fd) {
258*ec779b8eSAndroid Build Coastguard Worker     TIME_CHECK();
259*ec779b8eSAndroid Build Coastguard Worker 
260*ec779b8eSAndroid Build Coastguard Worker     if (mEffect == 0) return NO_INIT;
261*ec779b8eSAndroid Build Coastguard Worker     native_handle_t* hidlHandle = native_handle_create(1, 0);
262*ec779b8eSAndroid Build Coastguard Worker     hidlHandle->data[0] = fd;
263*ec779b8eSAndroid Build Coastguard Worker     Return<void> ret = mEffect->debug(hidlHandle, {} /* options */);
264*ec779b8eSAndroid Build Coastguard Worker     native_handle_delete(hidlHandle);
265*ec779b8eSAndroid Build Coastguard Worker 
266*ec779b8eSAndroid Build Coastguard Worker     // TODO(b/111997867, b/177271958)  Workaround - remove when fixed.
267*ec779b8eSAndroid Build Coastguard Worker     // A Binder transmitted fd may not close immediately due to a race condition b/111997867
268*ec779b8eSAndroid Build Coastguard Worker     // when the remote binder thread removes the last refcount to the fd blocks in the
269*ec779b8eSAndroid Build Coastguard Worker     // kernel for binder activity. We send a Binder ping() command to unblock the thread
270*ec779b8eSAndroid Build Coastguard Worker     // and complete the fd close / release.
271*ec779b8eSAndroid Build Coastguard Worker     //
272*ec779b8eSAndroid Build Coastguard Worker     // See DeviceHalHidl::dump(), EffectHalHidl::dump(), StreamHalHidl::dump(),
273*ec779b8eSAndroid Build Coastguard Worker     //     EffectsFactoryHalHidl::dumpEffects().
274*ec779b8eSAndroid Build Coastguard Worker 
275*ec779b8eSAndroid Build Coastguard Worker     (void)mEffect->ping(); // synchronous Binder call
276*ec779b8eSAndroid Build Coastguard Worker 
277*ec779b8eSAndroid Build Coastguard Worker     return ret.isOk() ? OK : FAILED_TRANSACTION;
278*ec779b8eSAndroid Build Coastguard Worker }
279*ec779b8eSAndroid Build Coastguard Worker 
getConfigImpl(uint32_t cmdCode,uint32_t * replySize,void * pReplyData)280*ec779b8eSAndroid Build Coastguard Worker status_t EffectHalHidl::getConfigImpl(
281*ec779b8eSAndroid Build Coastguard Worker         uint32_t cmdCode, uint32_t *replySize, void *pReplyData) {
282*ec779b8eSAndroid Build Coastguard Worker     if (replySize == NULL || *replySize != sizeof(effect_config_t) || pReplyData == NULL) {
283*ec779b8eSAndroid Build Coastguard Worker         return BAD_VALUE;
284*ec779b8eSAndroid Build Coastguard Worker     }
285*ec779b8eSAndroid Build Coastguard Worker     status_t result = FAILED_TRANSACTION;
286*ec779b8eSAndroid Build Coastguard Worker     Return<void> ret;
287*ec779b8eSAndroid Build Coastguard Worker     if (cmdCode == EFFECT_CMD_GET_CONFIG) {
288*ec779b8eSAndroid Build Coastguard Worker         ret = mEffect->getConfig([&] (Result r, const EffectConfig &hidlConfig) {
289*ec779b8eSAndroid Build Coastguard Worker             result = analyzeResult(r);
290*ec779b8eSAndroid Build Coastguard Worker             if (r == Result::OK) {
291*ec779b8eSAndroid Build Coastguard Worker                 EffectUtils::effectConfigToHal(
292*ec779b8eSAndroid Build Coastguard Worker                         hidlConfig, static_cast<effect_config_t*>(pReplyData));
293*ec779b8eSAndroid Build Coastguard Worker             }
294*ec779b8eSAndroid Build Coastguard Worker         });
295*ec779b8eSAndroid Build Coastguard Worker     } else {
296*ec779b8eSAndroid Build Coastguard Worker         ret = mEffect->getConfigReverse([&] (Result r, const EffectConfig &hidlConfig) {
297*ec779b8eSAndroid Build Coastguard Worker             result = analyzeResult(r);
298*ec779b8eSAndroid Build Coastguard Worker             if (r == Result::OK) {
299*ec779b8eSAndroid Build Coastguard Worker                 EffectUtils::effectConfigToHal(
300*ec779b8eSAndroid Build Coastguard Worker                         hidlConfig, static_cast<effect_config_t*>(pReplyData));
301*ec779b8eSAndroid Build Coastguard Worker             }
302*ec779b8eSAndroid Build Coastguard Worker         });
303*ec779b8eSAndroid Build Coastguard Worker     }
304*ec779b8eSAndroid Build Coastguard Worker     if (!ret.isOk()) {
305*ec779b8eSAndroid Build Coastguard Worker         result = FAILED_TRANSACTION;
306*ec779b8eSAndroid Build Coastguard Worker     }
307*ec779b8eSAndroid Build Coastguard Worker     return result;
308*ec779b8eSAndroid Build Coastguard Worker }
309*ec779b8eSAndroid Build Coastguard Worker 
setConfigImpl(uint32_t cmdCode,uint32_t cmdSize,void * pCmdData,uint32_t * replySize,void * pReplyData)310*ec779b8eSAndroid Build Coastguard Worker status_t EffectHalHidl::setConfigImpl(
311*ec779b8eSAndroid Build Coastguard Worker         uint32_t cmdCode, uint32_t cmdSize, void *pCmdData, uint32_t *replySize, void *pReplyData) {
312*ec779b8eSAndroid Build Coastguard Worker     if (pCmdData == NULL || cmdSize != sizeof(effect_config_t) ||
313*ec779b8eSAndroid Build Coastguard Worker             replySize == NULL || *replySize != sizeof(int32_t) || pReplyData == NULL) {
314*ec779b8eSAndroid Build Coastguard Worker         return BAD_VALUE;
315*ec779b8eSAndroid Build Coastguard Worker     }
316*ec779b8eSAndroid Build Coastguard Worker     const effect_config_t *halConfig = static_cast<effect_config_t*>(pCmdData);
317*ec779b8eSAndroid Build Coastguard Worker     if (halConfig->inputCfg.bufferProvider.getBuffer != NULL ||
318*ec779b8eSAndroid Build Coastguard Worker             halConfig->inputCfg.bufferProvider.releaseBuffer != NULL ||
319*ec779b8eSAndroid Build Coastguard Worker             halConfig->outputCfg.bufferProvider.getBuffer != NULL ||
320*ec779b8eSAndroid Build Coastguard Worker             halConfig->outputCfg.bufferProvider.releaseBuffer != NULL) {
321*ec779b8eSAndroid Build Coastguard Worker         ALOGE("Buffer provider callbacks are not supported");
322*ec779b8eSAndroid Build Coastguard Worker     }
323*ec779b8eSAndroid Build Coastguard Worker     EffectConfig hidlConfig;
324*ec779b8eSAndroid Build Coastguard Worker     EffectUtils::effectConfigFromHal(*halConfig, mIsInput, &hidlConfig);
325*ec779b8eSAndroid Build Coastguard Worker     Return<Result> ret = cmdCode == EFFECT_CMD_SET_CONFIG ?
326*ec779b8eSAndroid Build Coastguard Worker             mEffect->setConfig(hidlConfig, nullptr, nullptr) :
327*ec779b8eSAndroid Build Coastguard Worker             mEffect->setConfigReverse(hidlConfig, nullptr, nullptr);
328*ec779b8eSAndroid Build Coastguard Worker     status_t result = FAILED_TRANSACTION;
329*ec779b8eSAndroid Build Coastguard Worker     if (ret.isOk()) {
330*ec779b8eSAndroid Build Coastguard Worker         result = analyzeResult(ret);
331*ec779b8eSAndroid Build Coastguard Worker         *static_cast<int32_t*>(pReplyData) = result;
332*ec779b8eSAndroid Build Coastguard Worker     }
333*ec779b8eSAndroid Build Coastguard Worker     return result;
334*ec779b8eSAndroid Build Coastguard Worker }
335*ec779b8eSAndroid Build Coastguard Worker 
getHalPid(pid_t * pid) const336*ec779b8eSAndroid Build Coastguard Worker status_t EffectHalHidl::getHalPid(pid_t *pid) const {
337*ec779b8eSAndroid Build Coastguard Worker     using ::android::hidl::base::V1_0::DebugInfo;
338*ec779b8eSAndroid Build Coastguard Worker     using ::android::hidl::manager::V1_0::IServiceManager;
339*ec779b8eSAndroid Build Coastguard Worker     DebugInfo debugInfo;
340*ec779b8eSAndroid Build Coastguard Worker     const auto ret = mEffect->getDebugInfo([&] (const auto &info) {
341*ec779b8eSAndroid Build Coastguard Worker         debugInfo = info;
342*ec779b8eSAndroid Build Coastguard Worker     });
343*ec779b8eSAndroid Build Coastguard Worker     if (!ret.isOk()) {
344*ec779b8eSAndroid Build Coastguard Worker         ALOGW("%s: cannot get effect debug info", __func__);
345*ec779b8eSAndroid Build Coastguard Worker         return INVALID_OPERATION;
346*ec779b8eSAndroid Build Coastguard Worker     }
347*ec779b8eSAndroid Build Coastguard Worker     if (debugInfo.pid != (int)IServiceManager::PidConstant::NO_PID) {
348*ec779b8eSAndroid Build Coastguard Worker         *pid = debugInfo.pid;
349*ec779b8eSAndroid Build Coastguard Worker         return NO_ERROR;
350*ec779b8eSAndroid Build Coastguard Worker     }
351*ec779b8eSAndroid Build Coastguard Worker     ALOGW("%s: effect debug info does not contain pid", __func__);
352*ec779b8eSAndroid Build Coastguard Worker     return NAME_NOT_FOUND;
353*ec779b8eSAndroid Build Coastguard Worker }
354*ec779b8eSAndroid Build Coastguard Worker 
getHalWorkerTid(pid_t * tid)355*ec779b8eSAndroid Build Coastguard Worker status_t EffectHalHidl::getHalWorkerTid(pid_t *tid) {
356*ec779b8eSAndroid Build Coastguard Worker     int32_t reply = -1;
357*ec779b8eSAndroid Build Coastguard Worker     uint32_t replySize = sizeof(reply);
358*ec779b8eSAndroid Build Coastguard Worker     const status_t status =
359*ec779b8eSAndroid Build Coastguard Worker             command('gtid', 0 /* cmdSize */, nullptr /* pCmdData */, &replySize, &reply);
360*ec779b8eSAndroid Build Coastguard Worker     if (status == OK) {
361*ec779b8eSAndroid Build Coastguard Worker         *tid = (pid_t)reply;
362*ec779b8eSAndroid Build Coastguard Worker     } else {
363*ec779b8eSAndroid Build Coastguard Worker         ALOGW("%s: failed with status:%d", __func__, status);
364*ec779b8eSAndroid Build Coastguard Worker     }
365*ec779b8eSAndroid Build Coastguard Worker     return status;
366*ec779b8eSAndroid Build Coastguard Worker }
367*ec779b8eSAndroid Build Coastguard Worker 
requestHalThreadPriority(pid_t threadPid,pid_t threadId)368*ec779b8eSAndroid Build Coastguard Worker bool EffectHalHidl::requestHalThreadPriority(pid_t threadPid, pid_t threadId) {
369*ec779b8eSAndroid Build Coastguard Worker     if (mHalThreadPriority == kRTPriorityDisabled) {
370*ec779b8eSAndroid Build Coastguard Worker         return true;
371*ec779b8eSAndroid Build Coastguard Worker     }
372*ec779b8eSAndroid Build Coastguard Worker     const int err = requestPriority(
373*ec779b8eSAndroid Build Coastguard Worker             threadPid, threadId,
374*ec779b8eSAndroid Build Coastguard Worker             mHalThreadPriority, false /*isForApp*/, true /*asynchronous*/);
375*ec779b8eSAndroid Build Coastguard Worker     ALOGW_IF(err, "%s: failed to set RT priority %d for pid %d tid %d; error %d",
376*ec779b8eSAndroid Build Coastguard Worker             __func__, mHalThreadPriority, threadPid, threadId, err);
377*ec779b8eSAndroid Build Coastguard Worker     // Audio will still work, but may be more susceptible to glitches.
378*ec779b8eSAndroid Build Coastguard Worker     return err == 0;
379*ec779b8eSAndroid Build Coastguard Worker }
380*ec779b8eSAndroid Build Coastguard Worker 
checkHalThreadPriority()381*ec779b8eSAndroid Build Coastguard Worker status_t EffectHalHidl::checkHalThreadPriority() {
382*ec779b8eSAndroid Build Coastguard Worker     if (mHalThreadPriority == kRTPriorityDisabled) return OK;
383*ec779b8eSAndroid Build Coastguard Worker     if (mHalThreadPriority < kRTPriorityMin
384*ec779b8eSAndroid Build Coastguard Worker             || mHalThreadPriority > kRTPriorityMax) return BAD_VALUE;
385*ec779b8eSAndroid Build Coastguard Worker 
386*ec779b8eSAndroid Build Coastguard Worker     pid_t halPid, halWorkerTid;
387*ec779b8eSAndroid Build Coastguard Worker     const status_t status = getHalPid(&halPid) ?: getHalWorkerTid(&halWorkerTid);
388*ec779b8eSAndroid Build Coastguard Worker     const bool success = status == OK && requestHalThreadPriority(halPid, halWorkerTid);
389*ec779b8eSAndroid Build Coastguard Worker     ALOGD("%s: effectId %lld RT priority(%d) request %s%s",
390*ec779b8eSAndroid Build Coastguard Worker             __func__, (long long)mEffectId, mHalThreadPriority,
391*ec779b8eSAndroid Build Coastguard Worker             success ? "succeeded" : "failed",
392*ec779b8eSAndroid Build Coastguard Worker             status == OK
393*ec779b8eSAndroid Build Coastguard Worker                     ? base::StringPrintf(" for pid:%d tid:%d", halPid, halWorkerTid).c_str()
394*ec779b8eSAndroid Build Coastguard Worker                     : " (pid / tid cannot be read)");
395*ec779b8eSAndroid Build Coastguard Worker     return success ? OK : status != OK ? status : INVALID_OPERATION /* request failed */;
396*ec779b8eSAndroid Build Coastguard Worker }
397*ec779b8eSAndroid Build Coastguard Worker 
398*ec779b8eSAndroid Build Coastguard Worker } // namespace effect
399*ec779b8eSAndroid Build Coastguard Worker } // namespace android
400