1*ec779b8eSAndroid Build Coastguard Worker /* 2*ec779b8eSAndroid Build Coastguard Worker ** 3*ec779b8eSAndroid Build Coastguard Worker ** Copyright 2012, The Android Open Source Project 4*ec779b8eSAndroid Build Coastguard Worker ** 5*ec779b8eSAndroid Build Coastguard Worker ** Licensed under the Apache License, Version 2.0 (the "License"); 6*ec779b8eSAndroid Build Coastguard Worker ** you may not use this file except in compliance with the License. 7*ec779b8eSAndroid Build Coastguard Worker ** You may obtain a copy of the License at 8*ec779b8eSAndroid Build Coastguard Worker ** 9*ec779b8eSAndroid Build Coastguard Worker ** http://www.apache.org/licenses/LICENSE-2.0 10*ec779b8eSAndroid Build Coastguard Worker ** 11*ec779b8eSAndroid Build Coastguard Worker ** Unless required by applicable law or agreed to in writing, software 12*ec779b8eSAndroid Build Coastguard Worker ** distributed under the License is distributed on an "AS IS" BASIS, 13*ec779b8eSAndroid Build Coastguard Worker ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14*ec779b8eSAndroid Build Coastguard Worker ** See the License for the specific language governing permissions and 15*ec779b8eSAndroid Build Coastguard Worker ** limitations under the License. 16*ec779b8eSAndroid Build Coastguard Worker */ 17*ec779b8eSAndroid Build Coastguard Worker 18*ec779b8eSAndroid Build Coastguard Worker #pragma once 19*ec779b8eSAndroid Build Coastguard Worker 20*ec779b8eSAndroid Build Coastguard Worker #include "DeviceEffectManager.h" 21*ec779b8eSAndroid Build Coastguard Worker #include "IAfEffect.h" 22*ec779b8eSAndroid Build Coastguard Worker 23*ec779b8eSAndroid Build Coastguard Worker #include <android-base/macros.h> // DISALLOW_COPY_AND_ASSIGN 24*ec779b8eSAndroid Build Coastguard Worker #include <mediautils/Synchronization.h> 25*ec779b8eSAndroid Build Coastguard Worker #include <private/media/AudioEffectShared.h> 26*ec779b8eSAndroid Build Coastguard Worker 27*ec779b8eSAndroid Build Coastguard Worker #include <map> // avoid transitive dependency 28*ec779b8eSAndroid Build Coastguard Worker #include <optional> 29*ec779b8eSAndroid Build Coastguard Worker #include <vector> 30*ec779b8eSAndroid Build Coastguard Worker 31*ec779b8eSAndroid Build Coastguard Worker namespace android { 32*ec779b8eSAndroid Build Coastguard Worker 33*ec779b8eSAndroid Build Coastguard Worker //--- Audio Effect Management 34*ec779b8eSAndroid Build Coastguard Worker 35*ec779b8eSAndroid Build Coastguard Worker // EffectBase(EffectModule) and EffectChain classes both have their own mutex to protect 36*ec779b8eSAndroid Build Coastguard Worker // state changes or resource modifications. Always respect the following order 37*ec779b8eSAndroid Build Coastguard Worker // if multiple mutexes must be acquired to avoid cross deadlock: 38*ec779b8eSAndroid Build Coastguard Worker // AudioFlinger -> ThreadBase -> EffectChain -> EffectBase(EffectModule) 39*ec779b8eSAndroid Build Coastguard Worker // AudioHandle -> ThreadBase -> EffectChain -> EffectBase(EffectModule) 40*ec779b8eSAndroid Build Coastguard Worker 41*ec779b8eSAndroid Build Coastguard Worker // NOTE: When implementing the EffectCallbackInterface, in an EffectChain or other, it is important 42*ec779b8eSAndroid Build Coastguard Worker // to pay attention to this locking order as some callback methods can be called from a state where 43*ec779b8eSAndroid Build Coastguard Worker // EffectModule and/or EffectChain mutexes are held. 44*ec779b8eSAndroid Build Coastguard Worker 45*ec779b8eSAndroid Build Coastguard Worker // In addition, methods that lock the AudioPolicyService mutex (getOutputForEffect(), 46*ec779b8eSAndroid Build Coastguard Worker // startOutput(), getInputForAttr(), releaseInput()...) should never be called with AudioFlinger or 47*ec779b8eSAndroid Build Coastguard Worker // Threadbase mutex locked to avoid cross deadlock with other clients calling AudioPolicyService 48*ec779b8eSAndroid Build Coastguard Worker // methods that in turn call AudioFlinger thus locking the same mutexes in the reverse order. 49*ec779b8eSAndroid Build Coastguard Worker 50*ec779b8eSAndroid Build Coastguard Worker 51*ec779b8eSAndroid Build Coastguard Worker // The EffectBase class contains common properties, state and behavior for and EffectModule or 52*ec779b8eSAndroid Build Coastguard Worker // other derived classes managing an audio effect instance within the effect framework. 53*ec779b8eSAndroid Build Coastguard Worker // It also contains the class mutex (see comment on locking order above). 54*ec779b8eSAndroid Build Coastguard Worker class EffectBase : public virtual IAfEffectBase { 55*ec779b8eSAndroid Build Coastguard Worker public: 56*ec779b8eSAndroid Build Coastguard Worker EffectBase(const sp<EffectCallbackInterface>& callback, 57*ec779b8eSAndroid Build Coastguard Worker effect_descriptor_t *desc, 58*ec779b8eSAndroid Build Coastguard Worker int id, 59*ec779b8eSAndroid Build Coastguard Worker audio_session_t sessionId, 60*ec779b8eSAndroid Build Coastguard Worker bool pinned); 61*ec779b8eSAndroid Build Coastguard Worker id()62*ec779b8eSAndroid Build Coastguard Worker int id() const final { return mId; } state()63*ec779b8eSAndroid Build Coastguard Worker effect_state state() const final { 64*ec779b8eSAndroid Build Coastguard Worker return mState; 65*ec779b8eSAndroid Build Coastguard Worker } sessionId()66*ec779b8eSAndroid Build Coastguard Worker audio_session_t sessionId() const final { 67*ec779b8eSAndroid Build Coastguard Worker return mSessionId; 68*ec779b8eSAndroid Build Coastguard Worker } desc()69*ec779b8eSAndroid Build Coastguard Worker const effect_descriptor_t& desc() const final { return mDescriptor; } isOffloadable()70*ec779b8eSAndroid Build Coastguard Worker bool isOffloadable() const final 71*ec779b8eSAndroid Build Coastguard Worker { return (mDescriptor.flags & EFFECT_FLAG_OFFLOAD_SUPPORTED) != 0; } isImplementationSoftware()72*ec779b8eSAndroid Build Coastguard Worker bool isImplementationSoftware() const final 73*ec779b8eSAndroid Build Coastguard Worker { return (mDescriptor.flags & EFFECT_FLAG_HW_ACC_MASK) == 0; } isProcessImplemented()74*ec779b8eSAndroid Build Coastguard Worker bool isProcessImplemented() const final 75*ec779b8eSAndroid Build Coastguard Worker { return (mDescriptor.flags & EFFECT_FLAG_NO_PROCESS) == 0; } isVolumeControl()76*ec779b8eSAndroid Build Coastguard Worker bool isVolumeControl() const 77*ec779b8eSAndroid Build Coastguard Worker { return (mDescriptor.flags & EFFECT_FLAG_VOLUME_MASK) 78*ec779b8eSAndroid Build Coastguard Worker == EFFECT_FLAG_VOLUME_CTRL; } isVolumeMonitor()79*ec779b8eSAndroid Build Coastguard Worker bool isVolumeMonitor() const final 80*ec779b8eSAndroid Build Coastguard Worker { return (mDescriptor.flags & EFFECT_FLAG_VOLUME_MASK) 81*ec779b8eSAndroid Build Coastguard Worker == EFFECT_FLAG_VOLUME_MONITOR; } 82*ec779b8eSAndroid Build Coastguard Worker 83*ec779b8eSAndroid Build Coastguard Worker status_t setEnabled(bool enabled, bool fromHandle) override EXCLUDES_EffectBase_Mutex; 84*ec779b8eSAndroid Build Coastguard Worker status_t setEnabled_l(bool enabled) final REQUIRES(audio_utils::EffectBase_Mutex); 85*ec779b8eSAndroid Build Coastguard Worker bool isEnabled() const final; 86*ec779b8eSAndroid Build Coastguard Worker void setSuspended(bool suspended) final EXCLUDES_EffectBase_Mutex; 87*ec779b8eSAndroid Build Coastguard Worker bool suspended() const final EXCLUDES_EffectBase_Mutex; 88*ec779b8eSAndroid Build Coastguard Worker command(int32_t __unused,const std::vector<uint8_t> & __unused,int32_t __unused,std::vector<uint8_t> * __unused)89*ec779b8eSAndroid Build Coastguard Worker status_t command(int32_t __unused, 90*ec779b8eSAndroid Build Coastguard Worker const std::vector<uint8_t>& __unused, 91*ec779b8eSAndroid Build Coastguard Worker int32_t __unused, 92*ec779b8eSAndroid Build Coastguard Worker std::vector<uint8_t>* __unused) override { 93*ec779b8eSAndroid Build Coastguard Worker return NO_ERROR; 94*ec779b8eSAndroid Build Coastguard Worker } 95*ec779b8eSAndroid Build Coastguard Worker 96*ec779b8eSAndroid Build Coastguard Worker // mCallback is atomic so this can be lock-free. setCallback(const sp<EffectCallbackInterface> & callback)97*ec779b8eSAndroid Build Coastguard Worker void setCallback(const sp<EffectCallbackInterface>& callback) final { 98*ec779b8eSAndroid Build Coastguard Worker mCallback = callback; 99*ec779b8eSAndroid Build Coastguard Worker } getCallback()100*ec779b8eSAndroid Build Coastguard Worker sp<EffectCallbackInterface> getCallback() const final { 101*ec779b8eSAndroid Build Coastguard Worker return mCallback.load(); 102*ec779b8eSAndroid Build Coastguard Worker } 103*ec779b8eSAndroid Build Coastguard Worker 104*ec779b8eSAndroid Build Coastguard Worker status_t addHandle(IAfEffectHandle* handle) final EXCLUDES_EffectBase_Mutex; 105*ec779b8eSAndroid Build Coastguard Worker ssize_t disconnectHandle(IAfEffectHandle* handle, 106*ec779b8eSAndroid Build Coastguard Worker bool unpinIfLast) final EXCLUDES_EffectBase_Mutex; 107*ec779b8eSAndroid Build Coastguard Worker ssize_t removeHandle(IAfEffectHandle* handle) final EXCLUDES_EffectBase_Mutex; 108*ec779b8eSAndroid Build Coastguard Worker ssize_t removeHandle_l(IAfEffectHandle* handle) final REQUIRES(audio_utils::EffectBase_Mutex); 109*ec779b8eSAndroid Build Coastguard Worker IAfEffectHandle* controlHandle_l() final REQUIRES(audio_utils::EffectBase_Mutex); 110*ec779b8eSAndroid Build Coastguard Worker bool purgeHandles() final EXCLUDES_EffectBase_Mutex; 111*ec779b8eSAndroid Build Coastguard Worker 112*ec779b8eSAndroid Build Coastguard Worker void checkSuspendOnEffectEnabled(bool enabled, bool threadLocked) final; 113*ec779b8eSAndroid Build Coastguard Worker isPinned()114*ec779b8eSAndroid Build Coastguard Worker bool isPinned() const final { return mPinned; } unPin()115*ec779b8eSAndroid Build Coastguard Worker void unPin() final { mPinned = false; } 116*ec779b8eSAndroid Build Coastguard Worker mutex()117*ec779b8eSAndroid Build Coastguard Worker audio_utils::mutex& mutex() const final 118*ec779b8eSAndroid Build Coastguard Worker RETURN_CAPABILITY(android::audio_utils::EffectBase_Mutex) { 119*ec779b8eSAndroid Build Coastguard Worker return mMutex; 120*ec779b8eSAndroid Build Coastguard Worker } 121*ec779b8eSAndroid Build Coastguard Worker 122*ec779b8eSAndroid Build Coastguard Worker status_t updatePolicyState() final EXCLUDES_EffectBase_Mutex; 123*ec779b8eSAndroid Build Coastguard Worker asEffectModule()124*ec779b8eSAndroid Build Coastguard Worker sp<IAfEffectModule> asEffectModule() override { return nullptr; } asDeviceEffectProxy()125*ec779b8eSAndroid Build Coastguard Worker sp<IAfDeviceEffectProxy> asDeviceEffectProxy() override { return nullptr; } 126*ec779b8eSAndroid Build Coastguard Worker 127*ec779b8eSAndroid Build Coastguard Worker void dump(int fd, const Vector<String16>& args) const override; 128*ec779b8eSAndroid Build Coastguard Worker 129*ec779b8eSAndroid Build Coastguard Worker protected: isInternal_l()130*ec779b8eSAndroid Build Coastguard Worker bool isInternal_l() const REQUIRES(audio_utils::EffectBase_Mutex) { 131*ec779b8eSAndroid Build Coastguard Worker for (auto handle : mHandles) { 132*ec779b8eSAndroid Build Coastguard Worker if (handle->client() != nullptr) { 133*ec779b8eSAndroid Build Coastguard Worker return false; 134*ec779b8eSAndroid Build Coastguard Worker } 135*ec779b8eSAndroid Build Coastguard Worker } 136*ec779b8eSAndroid Build Coastguard Worker return true; 137*ec779b8eSAndroid Build Coastguard Worker } 138*ec779b8eSAndroid Build Coastguard Worker 139*ec779b8eSAndroid Build Coastguard Worker bool mPinned = false; 140*ec779b8eSAndroid Build Coastguard Worker 141*ec779b8eSAndroid Build Coastguard Worker DISALLOW_COPY_AND_ASSIGN(EffectBase); 142*ec779b8eSAndroid Build Coastguard Worker 143*ec779b8eSAndroid Build Coastguard Worker // mutex for process, commands and handles list protection 144*ec779b8eSAndroid Build Coastguard Worker mutable audio_utils::mutex mMutex{audio_utils::MutexOrder::kEffectBase_Mutex}; 145*ec779b8eSAndroid Build Coastguard Worker mediautils::atomic_sp<EffectCallbackInterface> mCallback; // parent effect chain 146*ec779b8eSAndroid Build Coastguard Worker const int mId; // this instance unique ID 147*ec779b8eSAndroid Build Coastguard Worker const audio_session_t mSessionId; // audio session ID 148*ec779b8eSAndroid Build Coastguard Worker const effect_descriptor_t mDescriptor;// effect descriptor received from effect engine 149*ec779b8eSAndroid Build Coastguard Worker effect_state mState = IDLE; // current activation state 150*ec779b8eSAndroid Build Coastguard Worker // effect is suspended: temporarily disabled by framework 151*ec779b8eSAndroid Build Coastguard Worker bool mSuspended = false; 152*ec779b8eSAndroid Build Coastguard Worker 153*ec779b8eSAndroid Build Coastguard Worker Vector<IAfEffectHandle *> mHandles; // list of client handles 154*ec779b8eSAndroid Build Coastguard Worker // First handle in mHandles has highest priority and controls the effect module 155*ec779b8eSAndroid Build Coastguard Worker 156*ec779b8eSAndroid Build Coastguard Worker // Audio policy effect state management 157*ec779b8eSAndroid Build Coastguard Worker // Mutex protecting transactions with audio policy manager as mutex() cannot 158*ec779b8eSAndroid Build Coastguard Worker // be held to avoid cross deadlocks with audio policy mutex policyMutex()159*ec779b8eSAndroid Build Coastguard Worker audio_utils::mutex& policyMutex() const 160*ec779b8eSAndroid Build Coastguard Worker RETURN_CAPABILITY(android::audio_utils::EffectBase_PolicyMutex) { 161*ec779b8eSAndroid Build Coastguard Worker return mPolicyMutex; 162*ec779b8eSAndroid Build Coastguard Worker } 163*ec779b8eSAndroid Build Coastguard Worker mutable audio_utils::mutex mPolicyMutex{audio_utils::MutexOrder::kEffectBase_PolicyMutex}; 164*ec779b8eSAndroid Build Coastguard Worker // Effect is registered in APM or not 165*ec779b8eSAndroid Build Coastguard Worker bool mPolicyRegistered = false; 166*ec779b8eSAndroid Build Coastguard Worker // Effect enabled state communicated to APM. Enabled state corresponds to 167*ec779b8eSAndroid Build Coastguard Worker // state requested by the EffectHandle with control 168*ec779b8eSAndroid Build Coastguard Worker bool mPolicyEnabled = false; 169*ec779b8eSAndroid Build Coastguard Worker }; 170*ec779b8eSAndroid Build Coastguard Worker 171*ec779b8eSAndroid Build Coastguard Worker // The EffectModule class is a wrapper object controlling the effect engine implementation 172*ec779b8eSAndroid Build Coastguard Worker // in the effect library. It prevents concurrent calls to process() and command() functions 173*ec779b8eSAndroid Build Coastguard Worker // from different client threads. It keeps a list of EffectHandle objects corresponding 174*ec779b8eSAndroid Build Coastguard Worker // to all client applications using this effect and notifies applications of effect state, 175*ec779b8eSAndroid Build Coastguard Worker // control or parameter changes. It manages the activation state machine to send appropriate 176*ec779b8eSAndroid Build Coastguard Worker // reset, enable, disable commands to effect engine and provide volume 177*ec779b8eSAndroid Build Coastguard Worker // ramping when effects are activated/deactivated. 178*ec779b8eSAndroid Build Coastguard Worker // When controlling an auxiliary effect, the EffectModule also provides an input buffer used by 179*ec779b8eSAndroid Build Coastguard Worker // the attached track(s) to accumulate their auxiliary channel. 180*ec779b8eSAndroid Build Coastguard Worker class EffectModule : public IAfEffectModule, public EffectBase { 181*ec779b8eSAndroid Build Coastguard Worker public: 182*ec779b8eSAndroid Build Coastguard Worker EffectModule(const sp<EffectCallbackInterface>& callback, 183*ec779b8eSAndroid Build Coastguard Worker effect_descriptor_t *desc, 184*ec779b8eSAndroid Build Coastguard Worker int id, 185*ec779b8eSAndroid Build Coastguard Worker audio_session_t sessionId, 186*ec779b8eSAndroid Build Coastguard Worker bool pinned, 187*ec779b8eSAndroid Build Coastguard Worker audio_port_handle_t deviceId) REQUIRES(audio_utils::EffectChain_Mutex); 188*ec779b8eSAndroid Build Coastguard Worker ~EffectModule() override REQUIRES(audio_utils::EffectChain_Mutex); 189*ec779b8eSAndroid Build Coastguard Worker 190*ec779b8eSAndroid Build Coastguard Worker void process() final EXCLUDES_EffectBase_Mutex; 191*ec779b8eSAndroid Build Coastguard Worker bool updateState_l() final REQUIRES(audio_utils::EffectChain_Mutex) EXCLUDES_EffectBase_Mutex; 192*ec779b8eSAndroid Build Coastguard Worker status_t command(int32_t cmdCode, const std::vector<uint8_t>& cmdData, int32_t maxReplySize, 193*ec779b8eSAndroid Build Coastguard Worker std::vector<uint8_t>* reply) final EXCLUDES_EffectBase_Mutex; 194*ec779b8eSAndroid Build Coastguard Worker 195*ec779b8eSAndroid Build Coastguard Worker void reset_l() final REQUIRES(audio_utils::EffectBase_Mutex); 196*ec779b8eSAndroid Build Coastguard Worker status_t configure_l() final REQUIRES(audio_utils::EffectChain_Mutex); 197*ec779b8eSAndroid Build Coastguard Worker status_t init_l() final REQUIRES(audio_utils::EffectChain_Mutex) EXCLUDES_EffectBase_Mutex; status()198*ec779b8eSAndroid Build Coastguard Worker uint32_t status() const final { 199*ec779b8eSAndroid Build Coastguard Worker return mStatus; 200*ec779b8eSAndroid Build Coastguard Worker } 201*ec779b8eSAndroid Build Coastguard Worker bool isProcessEnabled() const final; 202*ec779b8eSAndroid Build Coastguard Worker bool isOffloadedOrDirect_l() const final REQUIRES(audio_utils::EffectChain_Mutex); 203*ec779b8eSAndroid Build Coastguard Worker bool isVolumeControlEnabled_l() const final REQUIRES(audio_utils::EffectChain_Mutex); 204*ec779b8eSAndroid Build Coastguard Worker void setInBuffer(const sp<EffectBufferHalInterface>& buffer) final; inBuffer()205*ec779b8eSAndroid Build Coastguard Worker int16_t *inBuffer() const final { 206*ec779b8eSAndroid Build Coastguard Worker return mInBuffer != 0 ? reinterpret_cast<int16_t*>(mInBuffer->ptr()) : NULL; 207*ec779b8eSAndroid Build Coastguard Worker } 208*ec779b8eSAndroid Build Coastguard Worker void setOutBuffer(const sp<EffectBufferHalInterface>& buffer) final; outBuffer()209*ec779b8eSAndroid Build Coastguard Worker int16_t *outBuffer() const final { 210*ec779b8eSAndroid Build Coastguard Worker return mOutBuffer != 0 ? reinterpret_cast<int16_t*>(mOutBuffer->ptr()) : NULL; 211*ec779b8eSAndroid Build Coastguard Worker } 212*ec779b8eSAndroid Build Coastguard Worker // Updates the access mode if it is out of date. May issue a new effect configure. updateAccessMode_l()213*ec779b8eSAndroid Build Coastguard Worker void updateAccessMode_l() final REQUIRES(audio_utils::EffectChain_Mutex) { 214*ec779b8eSAndroid Build Coastguard Worker if (requiredEffectBufferAccessMode() != mConfig.outputCfg.accessMode) { 215*ec779b8eSAndroid Build Coastguard Worker configure_l(); 216*ec779b8eSAndroid Build Coastguard Worker } 217*ec779b8eSAndroid Build Coastguard Worker } 218*ec779b8eSAndroid Build Coastguard Worker status_t setDevices(const AudioDeviceTypeAddrVector& devices) final EXCLUDES_EffectBase_Mutex; 219*ec779b8eSAndroid Build Coastguard Worker status_t setInputDevice(const AudioDeviceTypeAddr& device) final EXCLUDES_EffectBase_Mutex; 220*ec779b8eSAndroid Build Coastguard Worker status_t setVolume_l(uint32_t* left, uint32_t* right, bool controller, bool force) final 221*ec779b8eSAndroid Build Coastguard Worker REQUIRES(audio_utils::EffectChain_Mutex); 222*ec779b8eSAndroid Build Coastguard Worker status_t setMode(audio_mode_t mode) final EXCLUDES_EffectBase_Mutex; 223*ec779b8eSAndroid Build Coastguard Worker status_t setAudioSource(audio_source_t source) final EXCLUDES_EffectBase_Mutex; 224*ec779b8eSAndroid Build Coastguard Worker status_t start_l() final REQUIRES(audio_utils::EffectChain_Mutex) EXCLUDES_EffectBase_Mutex; 225*ec779b8eSAndroid Build Coastguard Worker status_t stop_l() final REQUIRES(audio_utils::EffectChain_Mutex) EXCLUDES_EffectBase_Mutex; 226*ec779b8eSAndroid Build Coastguard Worker 227*ec779b8eSAndroid Build Coastguard Worker status_t setOffloaded_l(bool offloaded, audio_io_handle_t io) final 228*ec779b8eSAndroid Build Coastguard Worker REQUIRES(audio_utils::EffectChain_Mutex) EXCLUDES_EffectBase_Mutex; 229*ec779b8eSAndroid Build Coastguard Worker bool isOffloaded_l() const final 230*ec779b8eSAndroid Build Coastguard Worker REQUIRES(audio_utils::EffectChain_Mutex) EXCLUDES_EffectBase_Mutex; 231*ec779b8eSAndroid Build Coastguard Worker void addEffectToHal_l() override REQUIRES(audio_utils::EffectChain_Mutex); 232*ec779b8eSAndroid Build Coastguard Worker void release_l(const std::string& from = "") final REQUIRES(audio_utils::EffectChain_Mutex); 233*ec779b8eSAndroid Build Coastguard Worker asEffectModule()234*ec779b8eSAndroid Build Coastguard Worker sp<IAfEffectModule> asEffectModule() final { return this; } 235*ec779b8eSAndroid Build Coastguard Worker 236*ec779b8eSAndroid Build Coastguard Worker bool isHapticGenerator() const final; 237*ec779b8eSAndroid Build Coastguard Worker bool isSpatializer() const final; 238*ec779b8eSAndroid Build Coastguard Worker 239*ec779b8eSAndroid Build Coastguard Worker status_t setHapticScale_l(int id, os::HapticScale hapticScale) final 240*ec779b8eSAndroid Build Coastguard Worker REQUIRES(audio_utils::EffectChain_Mutex) EXCLUDES_EffectBase_Mutex; 241*ec779b8eSAndroid Build Coastguard Worker status_t setVibratorInfo_l(const media::AudioVibratorInfo& vibratorInfo) final 242*ec779b8eSAndroid Build Coastguard Worker REQUIRES(audio_utils::EffectChain_Mutex) EXCLUDES_EffectBase_Mutex; 243*ec779b8eSAndroid Build Coastguard Worker status_t sendMetadata_ll(const std::vector<playback_track_metadata_v7_t>& metadata) final 244*ec779b8eSAndroid Build Coastguard Worker REQUIRES(audio_utils::ThreadBase_Mutex, 245*ec779b8eSAndroid Build Coastguard Worker audio_utils::EffectChain_Mutex) EXCLUDES_EffectBase_Mutex; 246*ec779b8eSAndroid Build Coastguard Worker 247*ec779b8eSAndroid Build Coastguard Worker status_t getConfigs_l(audio_config_base_t* inputCfg, audio_config_base_t* outputCfg, 248*ec779b8eSAndroid Build Coastguard Worker bool* isOutput) const final 249*ec779b8eSAndroid Build Coastguard Worker REQUIRES(audio_utils::EffectHandle_Mutex) EXCLUDES_EffectBase_Mutex; 250*ec779b8eSAndroid Build Coastguard Worker 251*ec779b8eSAndroid Build Coastguard Worker void dump(int fd, const Vector<String16>& args) const final; 252*ec779b8eSAndroid Build Coastguard Worker 253*ec779b8eSAndroid Build Coastguard Worker protected: 254*ec779b8eSAndroid Build Coastguard Worker sp<EffectHalInterface> mEffectInterface; // Effect module HAL 255*ec779b8eSAndroid Build Coastguard Worker 256*ec779b8eSAndroid Build Coastguard Worker private: 257*ec779b8eSAndroid Build Coastguard Worker 258*ec779b8eSAndroid Build Coastguard Worker // Maximum time allocated to effect engines to complete the turn off sequence 259*ec779b8eSAndroid Build Coastguard Worker static const uint32_t MAX_DISABLE_TIME_MS = 10000; 260*ec779b8eSAndroid Build Coastguard Worker 261*ec779b8eSAndroid Build Coastguard Worker DISALLOW_COPY_AND_ASSIGN(EffectModule); 262*ec779b8eSAndroid Build Coastguard Worker 263*ec779b8eSAndroid Build Coastguard Worker status_t start_ll() REQUIRES(audio_utils::EffectChain_Mutex, audio_utils::EffectBase_Mutex); 264*ec779b8eSAndroid Build Coastguard Worker status_t stop_ll() REQUIRES(audio_utils::EffectChain_Mutex, audio_utils::EffectBase_Mutex); 265*ec779b8eSAndroid Build Coastguard Worker status_t removeEffectFromHal_l() override REQUIRES(audio_utils::EffectChain_Mutex); 266*ec779b8eSAndroid Build Coastguard Worker status_t sendSetAudioDevicesCommand(const AudioDeviceTypeAddrVector &devices, uint32_t cmdCode); requiredEffectBufferAccessMode()267*ec779b8eSAndroid Build Coastguard Worker effect_buffer_access_e requiredEffectBufferAccessMode() const { 268*ec779b8eSAndroid Build Coastguard Worker return mConfig.inputCfg.buffer.raw == mConfig.outputCfg.buffer.raw 269*ec779b8eSAndroid Build Coastguard Worker ? EFFECT_BUFFER_ACCESS_WRITE : EFFECT_BUFFER_ACCESS_ACCUMULATE; 270*ec779b8eSAndroid Build Coastguard Worker } 271*ec779b8eSAndroid Build Coastguard Worker 272*ec779b8eSAndroid Build Coastguard Worker status_t setVolumeInternal_ll(uint32_t* left, uint32_t* right, 273*ec779b8eSAndroid Build Coastguard Worker bool controller /* the volume controller effect of the chain */) 274*ec779b8eSAndroid Build Coastguard Worker REQUIRES(audio_utils::EffectChain_Mutex, audio_utils::EffectBase_Mutex); 275*ec779b8eSAndroid Build Coastguard Worker 276*ec779b8eSAndroid Build Coastguard Worker effect_config_t mConfig; // input and output audio configuration 277*ec779b8eSAndroid Build Coastguard Worker sp<EffectBufferHalInterface> mInBuffer; // Buffers for interacting with HAL 278*ec779b8eSAndroid Build Coastguard Worker sp<EffectBufferHalInterface> mOutBuffer; 279*ec779b8eSAndroid Build Coastguard Worker status_t mStatus; // initialization status 280*ec779b8eSAndroid Build Coastguard Worker // First handle in mHandles has highest priority and controls the effect module 281*ec779b8eSAndroid Build Coastguard Worker uint32_t mMaxDisableWaitCnt; // maximum grace period before forcing an effect off after 282*ec779b8eSAndroid Build Coastguard Worker // sending disable command. 283*ec779b8eSAndroid Build Coastguard Worker uint32_t mDisableWaitCnt; // current process() calls count during disable period. 284*ec779b8eSAndroid Build Coastguard Worker bool mOffloaded; // effect is currently offloaded to the audio DSP 285*ec779b8eSAndroid Build Coastguard Worker // effect has been added to this HAL input stream 286*ec779b8eSAndroid Build Coastguard Worker audio_io_handle_t mCurrentHalStream = AUDIO_IO_HANDLE_NONE; 287*ec779b8eSAndroid Build Coastguard Worker bool mIsOutput; // direction of the AF thread 288*ec779b8eSAndroid Build Coastguard Worker 289*ec779b8eSAndroid Build Coastguard Worker bool mSupportsFloat; // effect supports float processing 290*ec779b8eSAndroid Build Coastguard Worker sp<EffectBufferHalInterface> mInConversionBuffer; // Buffers for HAL conversion if needed. 291*ec779b8eSAndroid Build Coastguard Worker sp<EffectBufferHalInterface> mOutConversionBuffer; 292*ec779b8eSAndroid Build Coastguard Worker uint32_t mInChannelCountRequested; 293*ec779b8eSAndroid Build Coastguard Worker uint32_t mOutChannelCountRequested; 294*ec779b8eSAndroid Build Coastguard Worker 295*ec779b8eSAndroid Build Coastguard Worker template <typename MUTEX> 296*ec779b8eSAndroid Build Coastguard Worker class AutoLockReentrant { 297*ec779b8eSAndroid Build Coastguard Worker public: AutoLockReentrant(MUTEX & mutex,pid_t allowedTid)298*ec779b8eSAndroid Build Coastguard Worker AutoLockReentrant(MUTEX& mutex, pid_t allowedTid) ACQUIRE(audio_utils::EffectBase_Mutex) 299*ec779b8eSAndroid Build Coastguard Worker : mMutex(gettid() == allowedTid ? nullptr : &mutex) 300*ec779b8eSAndroid Build Coastguard Worker { 301*ec779b8eSAndroid Build Coastguard Worker if (mMutex != nullptr) mMutex->lock(); 302*ec779b8eSAndroid Build Coastguard Worker } RELEASE(audio_utils::EffectBase_Mutex)303*ec779b8eSAndroid Build Coastguard Worker ~AutoLockReentrant() RELEASE(audio_utils::EffectBase_Mutex) { 304*ec779b8eSAndroid Build Coastguard Worker if (mMutex != nullptr) mMutex->unlock(); 305*ec779b8eSAndroid Build Coastguard Worker } 306*ec779b8eSAndroid Build Coastguard Worker private: 307*ec779b8eSAndroid Build Coastguard Worker MUTEX * const mMutex; 308*ec779b8eSAndroid Build Coastguard Worker }; 309*ec779b8eSAndroid Build Coastguard Worker 310*ec779b8eSAndroid Build Coastguard Worker static constexpr pid_t INVALID_PID = (pid_t)-1; 311*ec779b8eSAndroid Build Coastguard Worker // this tid is allowed to call setVolume() without acquiring the mutex. 312*ec779b8eSAndroid Build Coastguard Worker pid_t mSetVolumeReentrantTid = INVALID_PID; 313*ec779b8eSAndroid Build Coastguard Worker 314*ec779b8eSAndroid Build Coastguard Worker // Cache the volume that has been set successfully. 315*ec779b8eSAndroid Build Coastguard Worker std::optional<std::vector<uint32_t>> mVolume; 316*ec779b8eSAndroid Build Coastguard Worker // Cache the volume that returned from the effect when setting volume successfully. The value 317*ec779b8eSAndroid Build Coastguard Worker // here is used to indicate the volume to apply before this effect. 318*ec779b8eSAndroid Build Coastguard Worker std::optional<std::vector<uint32_t>> mReturnedVolume; 319*ec779b8eSAndroid Build Coastguard Worker // TODO: b/315995877, remove this debugging string after root cause 320*ec779b8eSAndroid Build Coastguard Worker std::string mEffectInterfaceDebug GUARDED_BY(audio_utils::EffectChain_Mutex); 321*ec779b8eSAndroid Build Coastguard Worker }; 322*ec779b8eSAndroid Build Coastguard Worker 323*ec779b8eSAndroid Build Coastguard Worker class HwAccDeviceEffectModule : public EffectModule { 324*ec779b8eSAndroid Build Coastguard Worker public: HwAccDeviceEffectModule(const sp<EffectCallbackInterface> & callback,effect_descriptor_t * desc,int id,audio_port_handle_t deviceId)325*ec779b8eSAndroid Build Coastguard Worker HwAccDeviceEffectModule(const sp<EffectCallbackInterface>& callback, effect_descriptor_t *desc, 326*ec779b8eSAndroid Build Coastguard Worker int id, audio_port_handle_t deviceId) : 327*ec779b8eSAndroid Build Coastguard Worker EffectModule(callback, desc, id, AUDIO_SESSION_DEVICE, /* pinned */ false, deviceId) {} 328*ec779b8eSAndroid Build Coastguard Worker void addEffectToHal_l() final REQUIRES(audio_utils::EffectChain_Mutex); 329*ec779b8eSAndroid Build Coastguard Worker 330*ec779b8eSAndroid Build Coastguard Worker private: 331*ec779b8eSAndroid Build Coastguard Worker status_t removeEffectFromHal_l() final REQUIRES(audio_utils::EffectChain_Mutex); 332*ec779b8eSAndroid Build Coastguard Worker bool mAddedToHal = false; 333*ec779b8eSAndroid Build Coastguard Worker }; 334*ec779b8eSAndroid Build Coastguard Worker 335*ec779b8eSAndroid Build Coastguard Worker // The EffectHandle class implements the IEffect interface. It provides resources 336*ec779b8eSAndroid Build Coastguard Worker // to receive parameter updates, keeps track of effect control 337*ec779b8eSAndroid Build Coastguard Worker // ownership and state and has a pointer to the EffectModule object it is controlling. 338*ec779b8eSAndroid Build Coastguard Worker // There is one EffectHandle object for each application controlling (or using) 339*ec779b8eSAndroid Build Coastguard Worker // an effect module. 340*ec779b8eSAndroid Build Coastguard Worker // The EffectHandle is obtained by calling AudioFlinger::createEffect(). 341*ec779b8eSAndroid Build Coastguard Worker class EffectHandle: public IAfEffectHandle, public android::media::BnEffect { 342*ec779b8eSAndroid Build Coastguard Worker public: 343*ec779b8eSAndroid Build Coastguard Worker 344*ec779b8eSAndroid Build Coastguard Worker EffectHandle(const sp<IAfEffectBase>& effect, 345*ec779b8eSAndroid Build Coastguard Worker const sp<Client>& client, 346*ec779b8eSAndroid Build Coastguard Worker const sp<media::IEffectClient>& effectClient, 347*ec779b8eSAndroid Build Coastguard Worker int32_t priority, bool notifyFramesProcessed, bool isInternal = false, 348*ec779b8eSAndroid Build Coastguard Worker audio_utils::MutexOrder mutexOrder = audio_utils::MutexOrder::kEffectHandle_Mutex); 349*ec779b8eSAndroid Build Coastguard Worker ~EffectHandle() override; 350*ec779b8eSAndroid Build Coastguard Worker status_t onTransact( 351*ec779b8eSAndroid Build Coastguard Worker uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags) final; 352*ec779b8eSAndroid Build Coastguard Worker status_t initCheck() const final; 353*ec779b8eSAndroid Build Coastguard Worker 354*ec779b8eSAndroid Build Coastguard Worker // IEffect 355*ec779b8eSAndroid Build Coastguard Worker android::binder::Status enable(int32_t* _aidl_return) final; 356*ec779b8eSAndroid Build Coastguard Worker android::binder::Status disable(int32_t* _aidl_return) final; 357*ec779b8eSAndroid Build Coastguard Worker android::binder::Status command(int32_t cmdCode, 358*ec779b8eSAndroid Build Coastguard Worker const std::vector<uint8_t>& cmdData, 359*ec779b8eSAndroid Build Coastguard Worker int32_t maxResponseSize, 360*ec779b8eSAndroid Build Coastguard Worker std::vector<uint8_t>* response, 361*ec779b8eSAndroid Build Coastguard Worker int32_t* _aidl_return) final; 362*ec779b8eSAndroid Build Coastguard Worker android::binder::Status disconnect() final; 363*ec779b8eSAndroid Build Coastguard Worker android::binder::Status getCblk(media::SharedFileRegion* _aidl_return) final; 364*ec779b8eSAndroid Build Coastguard Worker android::binder::Status getConfig(media::EffectConfig* _config, 365*ec779b8eSAndroid Build Coastguard Worker int32_t* _aidl_return) final; 366*ec779b8eSAndroid Build Coastguard Worker client()367*ec779b8eSAndroid Build Coastguard Worker const sp<Client>& client() const final { return mClient; } 368*ec779b8eSAndroid Build Coastguard Worker /** 369*ec779b8eSAndroid Build Coastguard Worker * Checks if the handle is internal, aka created by AudioFlinger for internal needs (e.g. 370*ec779b8eSAndroid Build Coastguard Worker * device effect HAL handle or device effect thread handle). 371*ec779b8eSAndroid Build Coastguard Worker */ isInternal()372*ec779b8eSAndroid Build Coastguard Worker virtual bool isInternal() const { return mIsInternal; } 373*ec779b8eSAndroid Build Coastguard Worker asIEffect()374*ec779b8eSAndroid Build Coastguard Worker sp<android::media::IEffect> asIEffect() final { 375*ec779b8eSAndroid Build Coastguard Worker return sp<android::media::IEffect>::fromExisting(this); 376*ec779b8eSAndroid Build Coastguard Worker } 377*ec779b8eSAndroid Build Coastguard Worker 378*ec779b8eSAndroid Build Coastguard Worker private: 379*ec779b8eSAndroid Build Coastguard Worker void disconnect(bool unpinIfLast); 380*ec779b8eSAndroid Build Coastguard Worker 381*ec779b8eSAndroid Build Coastguard Worker // Give or take control of effect module 382*ec779b8eSAndroid Build Coastguard Worker // - hasControl: true if control is given, false if removed 383*ec779b8eSAndroid Build Coastguard Worker // - signal: true client app should be signaled of change, false otherwise 384*ec779b8eSAndroid Build Coastguard Worker // - enabled: state of the effect when control is passed 385*ec779b8eSAndroid Build Coastguard Worker void setControl(bool hasControl, bool signal, bool enabled) final; 386*ec779b8eSAndroid Build Coastguard Worker void commandExecuted(uint32_t cmdCode, 387*ec779b8eSAndroid Build Coastguard Worker const std::vector<uint8_t>& cmdData, 388*ec779b8eSAndroid Build Coastguard Worker const std::vector<uint8_t>& replyData) final; enabled()389*ec779b8eSAndroid Build Coastguard Worker bool enabled() const final { return mEnabled; } 390*ec779b8eSAndroid Build Coastguard Worker void setEnabled(bool enabled) final; 391*ec779b8eSAndroid Build Coastguard Worker void framesProcessed(int32_t frames) const final; 392*ec779b8eSAndroid Build Coastguard Worker 393*ec779b8eSAndroid Build Coastguard Worker public: 394*ec779b8eSAndroid Build Coastguard Worker // Getters effect()395*ec779b8eSAndroid Build Coastguard Worker wp<IAfEffectBase> effect() const final { return mEffect; } id()396*ec779b8eSAndroid Build Coastguard Worker int id() const final { 397*ec779b8eSAndroid Build Coastguard Worker sp<IAfEffectBase> effect = mEffect.promote(); 398*ec779b8eSAndroid Build Coastguard Worker if (effect == 0) { 399*ec779b8eSAndroid Build Coastguard Worker return 0; 400*ec779b8eSAndroid Build Coastguard Worker } 401*ec779b8eSAndroid Build Coastguard Worker return effect->id(); 402*ec779b8eSAndroid Build Coastguard Worker } 403*ec779b8eSAndroid Build Coastguard Worker private: priority()404*ec779b8eSAndroid Build Coastguard Worker int priority() const final { return mPriority; } hasControl()405*ec779b8eSAndroid Build Coastguard Worker bool hasControl() const final { return mHasControl; } disconnected()406*ec779b8eSAndroid Build Coastguard Worker bool disconnected() const final { return mDisconnected; } 407*ec779b8eSAndroid Build Coastguard Worker 408*ec779b8eSAndroid Build Coastguard Worker void dumpToBuffer(char* buffer, size_t size) const final; 409*ec779b8eSAndroid Build Coastguard Worker 410*ec779b8eSAndroid Build Coastguard Worker protected: 411*ec779b8eSAndroid Build Coastguard Worker // protects IEffect method calls 412*ec779b8eSAndroid Build Coastguard Worker mutable audio_utils::mutex mMutex; 413*ec779b8eSAndroid Build Coastguard Worker 414*ec779b8eSAndroid Build Coastguard Worker private: 415*ec779b8eSAndroid Build Coastguard Worker DISALLOW_COPY_AND_ASSIGN(EffectHandle); 416*ec779b8eSAndroid Build Coastguard Worker mutex()417*ec779b8eSAndroid Build Coastguard Worker virtual audio_utils::mutex& mutex() const 418*ec779b8eSAndroid Build Coastguard Worker RETURN_CAPABILITY(android::audio_utils::EffectHandle_Mutex) { 419*ec779b8eSAndroid Build Coastguard Worker return mMutex; 420*ec779b8eSAndroid Build Coastguard Worker } 421*ec779b8eSAndroid Build Coastguard Worker 422*ec779b8eSAndroid Build Coastguard Worker const wp<IAfEffectBase> mEffect; // pointer to controlled EffectModule 423*ec779b8eSAndroid Build Coastguard Worker const sp<media::IEffectClient> mEffectClient; // callback interface for client notifications 424*ec779b8eSAndroid Build Coastguard Worker /*const*/ sp<Client> mClient; // client for shared memory allocation, see 425*ec779b8eSAndroid Build Coastguard Worker // disconnect() 426*ec779b8eSAndroid Build Coastguard Worker sp<IMemory> mCblkMemory; // shared memory for control block 427*ec779b8eSAndroid Build Coastguard Worker effect_param_cblk_t* mCblk; // control block for deferred parameter setting via 428*ec779b8eSAndroid Build Coastguard Worker // shared memory 429*ec779b8eSAndroid Build Coastguard Worker uint8_t* mBuffer; // pointer to parameter area in shared memory 430*ec779b8eSAndroid Build Coastguard Worker int mPriority; // client application priority to control the effect 431*ec779b8eSAndroid Build Coastguard Worker bool mHasControl; // true if this handle is controlling the effect 432*ec779b8eSAndroid Build Coastguard Worker bool mEnabled; // cached enable state: needed when the effect is 433*ec779b8eSAndroid Build Coastguard Worker // restored after being suspended 434*ec779b8eSAndroid Build Coastguard Worker bool mDisconnected; // Set to true by disconnect() 435*ec779b8eSAndroid Build Coastguard Worker const bool mNotifyFramesProcessed; // true if the client callback event 436*ec779b8eSAndroid Build Coastguard Worker // EVENT_FRAMES_PROCESSED must be generated 437*ec779b8eSAndroid Build Coastguard Worker const bool mIsInternal; 438*ec779b8eSAndroid Build Coastguard Worker }; 439*ec779b8eSAndroid Build Coastguard Worker 440*ec779b8eSAndroid Build Coastguard Worker /** 441*ec779b8eSAndroid Build Coastguard Worker * There are 2 types of effects: 442*ec779b8eSAndroid Build Coastguard Worker * -Session Effect: handle is directly called from the client, without AudioFlinger lock. 443*ec779b8eSAndroid Build Coastguard Worker * -Device Effect: a device effect proxy is aggregating a collection of internal effect handles that 444*ec779b8eSAndroid Build Coastguard Worker * controls the same effect added on all audio patches involving the device effect selected port 445*ec779b8eSAndroid Build Coastguard Worker * requested either by a client or by AudioPolicyEffects. These internal effect handles do not have 446*ec779b8eSAndroid Build Coastguard Worker * client. Sequence flow implies a different locking order, hence the lock is specialied. 447*ec779b8eSAndroid Build Coastguard Worker */ 448*ec779b8eSAndroid Build Coastguard Worker class InternalEffectHandle : public EffectHandle { 449*ec779b8eSAndroid Build Coastguard Worker public: InternalEffectHandle(const sp<IAfEffectBase> & effect,bool notifyFramesProcessed)450*ec779b8eSAndroid Build Coastguard Worker InternalEffectHandle(const sp<IAfEffectBase>& effect, bool notifyFramesProcessed) : 451*ec779b8eSAndroid Build Coastguard Worker EffectHandle(effect, /* client= */ nullptr, /* effectClient= */ nullptr, 452*ec779b8eSAndroid Build Coastguard Worker /* priority= */ 0, notifyFramesProcessed, /* isInternal */ true, 453*ec779b8eSAndroid Build Coastguard Worker audio_utils::MutexOrder::kDeviceEffectHandle_Mutex) {} 454*ec779b8eSAndroid Build Coastguard Worker mutex()455*ec779b8eSAndroid Build Coastguard Worker virtual audio_utils::mutex& mutex() const 456*ec779b8eSAndroid Build Coastguard Worker RETURN_CAPABILITY(android::audio_utils::DeviceEffectHandle_Mutex) { 457*ec779b8eSAndroid Build Coastguard Worker return mMutex; 458*ec779b8eSAndroid Build Coastguard Worker } 459*ec779b8eSAndroid Build Coastguard Worker }; 460*ec779b8eSAndroid Build Coastguard Worker 461*ec779b8eSAndroid Build Coastguard Worker // the EffectChain class represents a group of effects associated to one audio session. 462*ec779b8eSAndroid Build Coastguard Worker // There can be any number of EffectChain objects per output mixer thread (PlaybackThread). 463*ec779b8eSAndroid Build Coastguard Worker // The EffectChain with session ID AUDIO_SESSION_OUTPUT_MIX contains global effects applied 464*ec779b8eSAndroid Build Coastguard Worker // to the output mix. 465*ec779b8eSAndroid Build Coastguard Worker // Effects in this chain can be insert or auxiliary. Effects in other chains (attached to 466*ec779b8eSAndroid Build Coastguard Worker // tracks) are insert only. The EffectChain maintains an ordered list of effect module, the 467*ec779b8eSAndroid Build Coastguard Worker // order corresponding in the effect process order. When attached to a track (session ID != 468*ec779b8eSAndroid Build Coastguard Worker // AUDIO_SESSION_OUTPUT_MIX), 469*ec779b8eSAndroid Build Coastguard Worker // it also provide it's own input buffer used by the track as accumulation buffer. 470*ec779b8eSAndroid Build Coastguard Worker class EffectChain : public IAfEffectChain { 471*ec779b8eSAndroid Build Coastguard Worker public: 472*ec779b8eSAndroid Build Coastguard Worker EffectChain(const sp<IAfThreadBase>& thread, 473*ec779b8eSAndroid Build Coastguard Worker audio_session_t sessionId, 474*ec779b8eSAndroid Build Coastguard Worker const sp<IAfThreadCallback>& afThreadCallback); 475*ec779b8eSAndroid Build Coastguard Worker 476*ec779b8eSAndroid Build Coastguard Worker void process_l() final REQUIRES(audio_utils::EffectChain_Mutex); 477*ec779b8eSAndroid Build Coastguard Worker mutex()478*ec779b8eSAndroid Build Coastguard Worker audio_utils::mutex& mutex() const final RETURN_CAPABILITY(audio_utils::EffectChain_Mutex) { 479*ec779b8eSAndroid Build Coastguard Worker return mMutex; 480*ec779b8eSAndroid Build Coastguard Worker } 481*ec779b8eSAndroid Build Coastguard Worker 482*ec779b8eSAndroid Build Coastguard Worker status_t createEffect(sp<IAfEffectModule>& effect, effect_descriptor_t* desc, int id, 483*ec779b8eSAndroid Build Coastguard Worker audio_session_t sessionId, bool pinned) final 484*ec779b8eSAndroid Build Coastguard Worker EXCLUDES_EffectChain_Mutex; 485*ec779b8eSAndroid Build Coastguard Worker status_t addEffect(const sp<IAfEffectModule>& handle) final 486*ec779b8eSAndroid Build Coastguard Worker EXCLUDES_EffectChain_Mutex; 487*ec779b8eSAndroid Build Coastguard Worker status_t addEffect_l(const sp<IAfEffectModule>& handle) final 488*ec779b8eSAndroid Build Coastguard Worker REQUIRES(audio_utils::EffectChain_Mutex); 489*ec779b8eSAndroid Build Coastguard Worker size_t removeEffect(const sp<IAfEffectModule>& handle, bool release = false) final 490*ec779b8eSAndroid Build Coastguard Worker EXCLUDES_EffectChain_Mutex; 491*ec779b8eSAndroid Build Coastguard Worker sessionId()492*ec779b8eSAndroid Build Coastguard Worker audio_session_t sessionId() const final { return mSessionId; } setSessionId(audio_session_t sessionId)493*ec779b8eSAndroid Build Coastguard Worker void setSessionId(audio_session_t sessionId) final { mSessionId = sessionId; } 494*ec779b8eSAndroid Build Coastguard Worker 495*ec779b8eSAndroid Build Coastguard Worker sp<IAfEffectModule> getEffectFromDesc(effect_descriptor_t* descriptor) const final 496*ec779b8eSAndroid Build Coastguard Worker EXCLUDES_EffectChain_Mutex; 497*ec779b8eSAndroid Build Coastguard Worker sp<IAfEffectModule> getEffectFromId_l(int id) const final 498*ec779b8eSAndroid Build Coastguard Worker REQUIRES(audio_utils::ThreadBase_Mutex) EXCLUDES_EffectChain_Mutex; 499*ec779b8eSAndroid Build Coastguard Worker sp<IAfEffectModule> getEffectFromType_l(const effect_uuid_t* type) const final 500*ec779b8eSAndroid Build Coastguard Worker REQUIRES(audio_utils::ThreadBase_Mutex) EXCLUDES_EffectChain_Mutex; 501*ec779b8eSAndroid Build Coastguard Worker std::vector<int> getEffectIds_l() const final REQUIRES(audio_utils::ThreadBase_Mutex); 502*ec779b8eSAndroid Build Coastguard Worker // FIXME use float to improve the dynamic range 503*ec779b8eSAndroid Build Coastguard Worker 504*ec779b8eSAndroid Build Coastguard Worker bool setVolume(uint32_t* left, uint32_t* right, 505*ec779b8eSAndroid Build Coastguard Worker bool force = false) final EXCLUDES_EffectChain_Mutex; 506*ec779b8eSAndroid Build Coastguard Worker void resetVolume_l() final REQUIRES(audio_utils::EffectChain_Mutex); 507*ec779b8eSAndroid Build Coastguard Worker void setDevices_l(const AudioDeviceTypeAddrVector& devices) final 508*ec779b8eSAndroid Build Coastguard Worker REQUIRES(audio_utils::ThreadBase_Mutex) EXCLUDES_EffectChain_Mutex; 509*ec779b8eSAndroid Build Coastguard Worker void setInputDevice_l(const AudioDeviceTypeAddr& device) final 510*ec779b8eSAndroid Build Coastguard Worker REQUIRES(audio_utils::ThreadBase_Mutex) EXCLUDES_EffectChain_Mutex; 511*ec779b8eSAndroid Build Coastguard Worker void setMode_l(audio_mode_t mode) final 512*ec779b8eSAndroid Build Coastguard Worker REQUIRES(audio_utils::ThreadBase_Mutex) EXCLUDES_EffectChain_Mutex; 513*ec779b8eSAndroid Build Coastguard Worker void setAudioSource_l(audio_source_t source) final 514*ec779b8eSAndroid Build Coastguard Worker REQUIRES(audio_utils::ThreadBase_Mutex) EXCLUDES_EffectChain_Mutex; 515*ec779b8eSAndroid Build Coastguard Worker setInBuffer(const sp<EffectBufferHalInterface> & buffer)516*ec779b8eSAndroid Build Coastguard Worker void setInBuffer(const sp<EffectBufferHalInterface>& buffer) final { 517*ec779b8eSAndroid Build Coastguard Worker mInBuffer = buffer; 518*ec779b8eSAndroid Build Coastguard Worker } inBuffer()519*ec779b8eSAndroid Build Coastguard Worker float *inBuffer() const final { 520*ec779b8eSAndroid Build Coastguard Worker return mInBuffer != 0 ? reinterpret_cast<float*>(mInBuffer->ptr()) : NULL; 521*ec779b8eSAndroid Build Coastguard Worker } setOutBuffer(const sp<EffectBufferHalInterface> & buffer)522*ec779b8eSAndroid Build Coastguard Worker void setOutBuffer(const sp<EffectBufferHalInterface>& buffer) final { 523*ec779b8eSAndroid Build Coastguard Worker mOutBuffer = buffer; 524*ec779b8eSAndroid Build Coastguard Worker } outBuffer()525*ec779b8eSAndroid Build Coastguard Worker float *outBuffer() const final { 526*ec779b8eSAndroid Build Coastguard Worker return mOutBuffer != 0 ? reinterpret_cast<float*>(mOutBuffer->ptr()) : NULL; 527*ec779b8eSAndroid Build Coastguard Worker } incTrackCnt()528*ec779b8eSAndroid Build Coastguard Worker void incTrackCnt() final { android_atomic_inc(&mTrackCnt); } decTrackCnt()529*ec779b8eSAndroid Build Coastguard Worker void decTrackCnt() final { android_atomic_dec(&mTrackCnt); } trackCnt()530*ec779b8eSAndroid Build Coastguard Worker int32_t trackCnt() const final { return android_atomic_acquire_load(&mTrackCnt); } 531*ec779b8eSAndroid Build Coastguard Worker incActiveTrackCnt()532*ec779b8eSAndroid Build Coastguard Worker void incActiveTrackCnt() final { android_atomic_inc(&mActiveTrackCnt); 533*ec779b8eSAndroid Build Coastguard Worker mTailBufferCount = mMaxTailBuffers; } decActiveTrackCnt()534*ec779b8eSAndroid Build Coastguard Worker void decActiveTrackCnt() final { android_atomic_dec(&mActiveTrackCnt); } activeTrackCnt()535*ec779b8eSAndroid Build Coastguard Worker int32_t activeTrackCnt() const final { 536*ec779b8eSAndroid Build Coastguard Worker return android_atomic_acquire_load(&mActiveTrackCnt); 537*ec779b8eSAndroid Build Coastguard Worker } 538*ec779b8eSAndroid Build Coastguard Worker strategy()539*ec779b8eSAndroid Build Coastguard Worker product_strategy_t strategy() const final { return mStrategy; } setStrategy(product_strategy_t strategy)540*ec779b8eSAndroid Build Coastguard Worker void setStrategy(product_strategy_t strategy) final 541*ec779b8eSAndroid Build Coastguard Worker { mStrategy = strategy; } 542*ec779b8eSAndroid Build Coastguard Worker 543*ec779b8eSAndroid Build Coastguard Worker // suspend or restore effects of the specified type. The number of suspend requests is counted 544*ec779b8eSAndroid Build Coastguard Worker // and restore occurs once all suspend requests are cancelled. 545*ec779b8eSAndroid Build Coastguard Worker void setEffectSuspended_l(const effect_uuid_t* type, bool suspend) final 546*ec779b8eSAndroid Build Coastguard Worker REQUIRES(audio_utils::ThreadBase_Mutex); 547*ec779b8eSAndroid Build Coastguard Worker // suspend all eligible effects 548*ec779b8eSAndroid Build Coastguard Worker void setEffectSuspendedAll_l(bool suspend) final REQUIRES(audio_utils::ThreadBase_Mutex); 549*ec779b8eSAndroid Build Coastguard Worker // check if effects should be suspended or restored when a given effect is enable or disabled 550*ec779b8eSAndroid Build Coastguard Worker void checkSuspendOnEffectEnabled_l(const sp<IAfEffectModule>& effect, bool enabled) final 551*ec779b8eSAndroid Build Coastguard Worker REQUIRES(audio_utils::ThreadBase_Mutex); 552*ec779b8eSAndroid Build Coastguard Worker 553*ec779b8eSAndroid Build Coastguard Worker void clearInputBuffer() final EXCLUDES_EffectChain_Mutex; 554*ec779b8eSAndroid Build Coastguard Worker 555*ec779b8eSAndroid Build Coastguard Worker // At least one non offloadable effect in the chain is enabled 556*ec779b8eSAndroid Build Coastguard Worker bool isNonOffloadableEnabled() const final EXCLUDES_EffectChain_Mutex; 557*ec779b8eSAndroid Build Coastguard Worker bool isNonOffloadableEnabled_l() const final REQUIRES(audio_utils::EffectChain_Mutex); 558*ec779b8eSAndroid Build Coastguard Worker 559*ec779b8eSAndroid Build Coastguard Worker void syncHalEffectsState_l() 560*ec779b8eSAndroid Build Coastguard Worker REQUIRES(audio_utils::ThreadBase_Mutex) EXCLUDES_EffectChain_Mutex final; 561*ec779b8eSAndroid Build Coastguard Worker 562*ec779b8eSAndroid Build Coastguard Worker // flags is an ORed set of audio_output_flags_t which is updated on return. 563*ec779b8eSAndroid Build Coastguard Worker void checkOutputFlagCompatibility(audio_output_flags_t *flags) const final; 564*ec779b8eSAndroid Build Coastguard Worker 565*ec779b8eSAndroid Build Coastguard Worker // flags is an ORed set of audio_input_flags_t which is updated on return. 566*ec779b8eSAndroid Build Coastguard Worker void checkInputFlagCompatibility(audio_input_flags_t *flags) const final; 567*ec779b8eSAndroid Build Coastguard Worker 568*ec779b8eSAndroid Build Coastguard Worker // Is this EffectChain compatible with the RAW audio flag. 569*ec779b8eSAndroid Build Coastguard Worker bool isRawCompatible() const final; 570*ec779b8eSAndroid Build Coastguard Worker 571*ec779b8eSAndroid Build Coastguard Worker // Is this EffectChain compatible with the FAST audio flag. 572*ec779b8eSAndroid Build Coastguard Worker bool isFastCompatible() const final; 573*ec779b8eSAndroid Build Coastguard Worker 574*ec779b8eSAndroid Build Coastguard Worker // Is this EffectChain compatible with the bit-perfect audio flag. 575*ec779b8eSAndroid Build Coastguard Worker bool isBitPerfectCompatible() const final; 576*ec779b8eSAndroid Build Coastguard Worker 577*ec779b8eSAndroid Build Coastguard Worker // isCompatibleWithThread_l() must be called with thread->mutex() held 578*ec779b8eSAndroid Build Coastguard Worker bool isCompatibleWithThread_l(const sp<IAfThreadBase>& thread) const final 579*ec779b8eSAndroid Build Coastguard Worker REQUIRES(audio_utils::ThreadBase_Mutex) EXCLUDES_EffectChain_Mutex; 580*ec779b8eSAndroid Build Coastguard Worker 581*ec779b8eSAndroid Build Coastguard Worker bool containsHapticGeneratingEffect() final 582*ec779b8eSAndroid Build Coastguard Worker EXCLUDES_EffectChain_Mutex; 583*ec779b8eSAndroid Build Coastguard Worker 584*ec779b8eSAndroid Build Coastguard Worker bool containsHapticGeneratingEffect_l() final 585*ec779b8eSAndroid Build Coastguard Worker REQUIRES(audio_utils::EffectChain_Mutex); 586*ec779b8eSAndroid Build Coastguard Worker 587*ec779b8eSAndroid Build Coastguard Worker void setHapticScale_l(int id, os::HapticScale hapticScale) final 588*ec779b8eSAndroid Build Coastguard Worker REQUIRES(audio_utils::ThreadBase_Mutex) EXCLUDES_EffectChain_Mutex; 589*ec779b8eSAndroid Build Coastguard Worker effectCallback()590*ec779b8eSAndroid Build Coastguard Worker sp<EffectCallbackInterface> effectCallback() const final { return mEffectCallback; } 591*ec779b8eSAndroid Build Coastguard Worker thread()592*ec779b8eSAndroid Build Coastguard Worker wp<IAfThreadBase> thread() const final { return mEffectCallback->thread(); } 593*ec779b8eSAndroid Build Coastguard Worker isFirstEffect_l(int id)594*ec779b8eSAndroid Build Coastguard Worker bool isFirstEffect_l(int id) const final REQUIRES(audio_utils::EffectChain_Mutex) { 595*ec779b8eSAndroid Build Coastguard Worker return !mEffects.isEmpty() && id == mEffects[0]->id(); 596*ec779b8eSAndroid Build Coastguard Worker } 597*ec779b8eSAndroid Build Coastguard Worker 598*ec779b8eSAndroid Build Coastguard Worker void dump(int fd, const Vector<String16>& args) const final; 599*ec779b8eSAndroid Build Coastguard Worker numberOfEffects()600*ec779b8eSAndroid Build Coastguard Worker size_t numberOfEffects() const final { 601*ec779b8eSAndroid Build Coastguard Worker audio_utils::lock_guard _l(mutex()); 602*ec779b8eSAndroid Build Coastguard Worker return mEffects.size(); 603*ec779b8eSAndroid Build Coastguard Worker } 604*ec779b8eSAndroid Build Coastguard Worker getEffectModule(size_t index)605*ec779b8eSAndroid Build Coastguard Worker sp<IAfEffectModule> getEffectModule(size_t index) const final { 606*ec779b8eSAndroid Build Coastguard Worker audio_utils::lock_guard _l(mutex()); 607*ec779b8eSAndroid Build Coastguard Worker return mEffects[index]; 608*ec779b8eSAndroid Build Coastguard Worker } 609*ec779b8eSAndroid Build Coastguard Worker 610*ec779b8eSAndroid Build Coastguard Worker void sendMetadata_l(const std::vector<playback_track_metadata_v7_t>& allMetadata, 611*ec779b8eSAndroid Build Coastguard Worker const std::optional<const std::vector<playback_track_metadata_v7_t>> spatializedMetadata) 612*ec779b8eSAndroid Build Coastguard Worker final REQUIRES(audio_utils::ThreadBase_Mutex); 613*ec779b8eSAndroid Build Coastguard Worker 614*ec779b8eSAndroid Build Coastguard Worker void setThread(const sp<IAfThreadBase>& thread) final EXCLUDES_EffectChain_Mutex; 615*ec779b8eSAndroid Build Coastguard Worker 616*ec779b8eSAndroid Build Coastguard Worker private: 617*ec779b8eSAndroid Build Coastguard Worker bool setVolume_l(uint32_t* left, uint32_t* right, bool force = false) 618*ec779b8eSAndroid Build Coastguard Worker REQUIRES(audio_utils::EffectChain_Mutex); 619*ec779b8eSAndroid Build Coastguard Worker 620*ec779b8eSAndroid Build Coastguard Worker // For transaction consistency, please consider holding the EffectChain lock before 621*ec779b8eSAndroid Build Coastguard Worker // calling the EffectChain::EffectCallback methods, excepting 622*ec779b8eSAndroid Build Coastguard Worker // createEffectHal and allocateHalBuffer. 623*ec779b8eSAndroid Build Coastguard Worker // 624*ec779b8eSAndroid Build Coastguard Worker // This prevents migration of the EffectChain to another PlaybackThread 625*ec779b8eSAndroid Build Coastguard Worker // for the purposes of the EffectCallback. 626*ec779b8eSAndroid Build Coastguard Worker class EffectCallback : public EffectCallbackInterface { 627*ec779b8eSAndroid Build Coastguard Worker public: 628*ec779b8eSAndroid Build Coastguard Worker // Note: ctors taking a weak pointer to their owner must not promote it 629*ec779b8eSAndroid Build Coastguard Worker // during construction (but may keep a reference for later promotion). EffectCallback(const wp<EffectChain> & owner,const sp<IAfThreadBase> & thread,const sp<IAfThreadCallback> & afThreadCallback)630*ec779b8eSAndroid Build Coastguard Worker EffectCallback(const wp<EffectChain>& owner, 631*ec779b8eSAndroid Build Coastguard Worker const sp<IAfThreadBase>& thread, 632*ec779b8eSAndroid Build Coastguard Worker const sp<IAfThreadCallback>& afThreadCallback) // we take a sp<> but store a wp<>. 633*ec779b8eSAndroid Build Coastguard Worker : mChain(owner) 634*ec779b8eSAndroid Build Coastguard Worker , mThread(thread), mAfThreadCallback(afThreadCallback) { 635*ec779b8eSAndroid Build Coastguard Worker if (thread != nullptr) { 636*ec779b8eSAndroid Build Coastguard Worker mThreadType = thread->type(); 637*ec779b8eSAndroid Build Coastguard Worker } 638*ec779b8eSAndroid Build Coastguard Worker } 639*ec779b8eSAndroid Build Coastguard Worker 640*ec779b8eSAndroid Build Coastguard Worker status_t createEffectHal(const effect_uuid_t *pEffectUuid, 641*ec779b8eSAndroid Build Coastguard Worker int32_t sessionId, int32_t deviceId, sp<EffectHalInterface> *effect) override; 642*ec779b8eSAndroid Build Coastguard Worker status_t allocateHalBuffer(size_t size, sp<EffectBufferHalInterface>* buffer) override; 643*ec779b8eSAndroid Build Coastguard Worker bool updateOrphanEffectChains(const sp<IAfEffectBase>& effect) override; 644*ec779b8eSAndroid Build Coastguard Worker 645*ec779b8eSAndroid Build Coastguard Worker audio_io_handle_t io() const override; 646*ec779b8eSAndroid Build Coastguard Worker bool isOutput() const override; 647*ec779b8eSAndroid Build Coastguard Worker bool isOffload() const override; 648*ec779b8eSAndroid Build Coastguard Worker bool isOffloadOrDirect() const override; 649*ec779b8eSAndroid Build Coastguard Worker bool isOffloadOrMmap() const override; 650*ec779b8eSAndroid Build Coastguard Worker bool isSpatializer() const override; 651*ec779b8eSAndroid Build Coastguard Worker 652*ec779b8eSAndroid Build Coastguard Worker uint32_t sampleRate() const override; 653*ec779b8eSAndroid Build Coastguard Worker audio_channel_mask_t inChannelMask(int id) const override; 654*ec779b8eSAndroid Build Coastguard Worker uint32_t inChannelCount(int id) const override; 655*ec779b8eSAndroid Build Coastguard Worker audio_channel_mask_t outChannelMask() const override; 656*ec779b8eSAndroid Build Coastguard Worker uint32_t outChannelCount() const override; 657*ec779b8eSAndroid Build Coastguard Worker audio_channel_mask_t hapticChannelMask() const override; 658*ec779b8eSAndroid Build Coastguard Worker size_t frameCount() const override; 659*ec779b8eSAndroid Build Coastguard Worker uint32_t latency() const override; 660*ec779b8eSAndroid Build Coastguard Worker 661*ec779b8eSAndroid Build Coastguard Worker status_t addEffectToHal(const sp<EffectHalInterface>& effect) override; 662*ec779b8eSAndroid Build Coastguard Worker status_t removeEffectFromHal(const sp<EffectHalInterface>& effect) override; 663*ec779b8eSAndroid Build Coastguard Worker bool disconnectEffectHandle(IAfEffectHandle *handle, bool unpinIfLast) override; 664*ec779b8eSAndroid Build Coastguard Worker void setVolumeForOutput(float left, float right) const override; 665*ec779b8eSAndroid Build Coastguard Worker 666*ec779b8eSAndroid Build Coastguard Worker // check if effects should be suspended/restored when a given effect is enable/disabled 667*ec779b8eSAndroid Build Coastguard Worker void checkSuspendOnEffectEnabled(const sp<IAfEffectBase>& effect, bool enabled, 668*ec779b8eSAndroid Build Coastguard Worker bool threadLocked) override; 669*ec779b8eSAndroid Build Coastguard Worker void resetVolume_l() override 670*ec779b8eSAndroid Build Coastguard Worker REQUIRES(audio_utils::ThreadBase_Mutex, audio_utils::EffectChain_Mutex); 671*ec779b8eSAndroid Build Coastguard Worker product_strategy_t strategy() const override; 672*ec779b8eSAndroid Build Coastguard Worker int32_t activeTrackCnt() const override; 673*ec779b8eSAndroid Build Coastguard Worker void onEffectEnable(const sp<IAfEffectBase>& effect) override; 674*ec779b8eSAndroid Build Coastguard Worker void onEffectDisable(const sp<IAfEffectBase>& effect) override; 675*ec779b8eSAndroid Build Coastguard Worker chain()676*ec779b8eSAndroid Build Coastguard Worker wp<IAfEffectChain> chain() const final { return mChain; } 677*ec779b8eSAndroid Build Coastguard Worker isAudioPolicyReady()678*ec779b8eSAndroid Build Coastguard Worker bool isAudioPolicyReady() const final { 679*ec779b8eSAndroid Build Coastguard Worker if (mAfThreadCallback == nullptr) { 680*ec779b8eSAndroid Build Coastguard Worker return false; 681*ec779b8eSAndroid Build Coastguard Worker } 682*ec779b8eSAndroid Build Coastguard Worker return mAfThreadCallback->isAudioPolicyReady(); 683*ec779b8eSAndroid Build Coastguard Worker } 684*ec779b8eSAndroid Build Coastguard Worker thread()685*ec779b8eSAndroid Build Coastguard Worker wp<IAfThreadBase> thread() const { return mThread.load(); } 686*ec779b8eSAndroid Build Coastguard Worker setThread(const sp<IAfThreadBase> & thread)687*ec779b8eSAndroid Build Coastguard Worker void setThread(const sp<IAfThreadBase>& thread) { 688*ec779b8eSAndroid Build Coastguard Worker mThread = thread; 689*ec779b8eSAndroid Build Coastguard Worker if (thread != nullptr) { 690*ec779b8eSAndroid Build Coastguard Worker mThreadType = thread->type(); 691*ec779b8eSAndroid Build Coastguard Worker mAfThreadCallback = thread->afThreadCallback(); 692*ec779b8eSAndroid Build Coastguard Worker } 693*ec779b8eSAndroid Build Coastguard Worker } hasThreadAttached()694*ec779b8eSAndroid Build Coastguard Worker bool hasThreadAttached() const { 695*ec779b8eSAndroid Build Coastguard Worker return thread().promote() != nullptr; 696*ec779b8eSAndroid Build Coastguard Worker } 697*ec779b8eSAndroid Build Coastguard Worker private: 698*ec779b8eSAndroid Build Coastguard Worker const wp<IAfEffectChain> mChain; 699*ec779b8eSAndroid Build Coastguard Worker mediautils::atomic_wp<IAfThreadBase> mThread; 700*ec779b8eSAndroid Build Coastguard Worker sp<IAfThreadCallback> mAfThreadCallback; 701*ec779b8eSAndroid Build Coastguard Worker IAfThreadBase::type_t mThreadType = IAfThreadBase::MIXER; 702*ec779b8eSAndroid Build Coastguard Worker }; 703*ec779b8eSAndroid Build Coastguard Worker 704*ec779b8eSAndroid Build Coastguard Worker DISALLOW_COPY_AND_ASSIGN(EffectChain); 705*ec779b8eSAndroid Build Coastguard Worker 706*ec779b8eSAndroid Build Coastguard Worker class SuspendedEffectDesc : public RefBase { 707*ec779b8eSAndroid Build Coastguard Worker public: SuspendedEffectDesc()708*ec779b8eSAndroid Build Coastguard Worker SuspendedEffectDesc() : mRefCount(0) {} 709*ec779b8eSAndroid Build Coastguard Worker 710*ec779b8eSAndroid Build Coastguard Worker int mRefCount; // > 0 when suspended 711*ec779b8eSAndroid Build Coastguard Worker effect_uuid_t mType; 712*ec779b8eSAndroid Build Coastguard Worker wp<IAfEffectModule> mEffect; 713*ec779b8eSAndroid Build Coastguard Worker }; 714*ec779b8eSAndroid Build Coastguard Worker 715*ec779b8eSAndroid Build Coastguard Worker // get a list of effect modules to suspend when an effect of the type 716*ec779b8eSAndroid Build Coastguard Worker // passed is enabled. 717*ec779b8eSAndroid Build Coastguard Worker void getSuspendEligibleEffects(Vector<sp<IAfEffectModule>>& effects) 718*ec779b8eSAndroid Build Coastguard Worker EXCLUDES_EffectChain_Mutex; 719*ec779b8eSAndroid Build Coastguard Worker 720*ec779b8eSAndroid Build Coastguard Worker // get an effect module if it is currently enable 721*ec779b8eSAndroid Build Coastguard Worker sp<IAfEffectModule> getEffectIfEnabled_l(const effect_uuid_t* type) 722*ec779b8eSAndroid Build Coastguard Worker REQUIRES(audio_utils::ThreadBase_Mutex); 723*ec779b8eSAndroid Build Coastguard Worker // true if the effect whose descriptor is passed can be suspended 724*ec779b8eSAndroid Build Coastguard Worker // OEMs can modify the rules implemented in this method to exclude specific effect 725*ec779b8eSAndroid Build Coastguard Worker // types or implementations from the suspend/restore mechanism. 726*ec779b8eSAndroid Build Coastguard Worker bool isEffectEligibleForSuspend(const effect_descriptor_t& desc); 727*ec779b8eSAndroid Build Coastguard Worker 728*ec779b8eSAndroid Build Coastguard Worker static bool isEffectEligibleForBtNrecSuspend_l(const effect_uuid_t* type) 729*ec779b8eSAndroid Build Coastguard Worker REQUIRES(audio_utils::ThreadBase_Mutex); 730*ec779b8eSAndroid Build Coastguard Worker 731*ec779b8eSAndroid Build Coastguard Worker void clearInputBuffer_l() REQUIRES(audio_utils::EffectChain_Mutex); 732*ec779b8eSAndroid Build Coastguard Worker 733*ec779b8eSAndroid Build Coastguard Worker // true if any effect module within the chain has volume control 734*ec779b8eSAndroid Build Coastguard Worker bool hasVolumeControlEnabled_l() const REQUIRES(audio_utils::EffectChain_Mutex); 735*ec779b8eSAndroid Build Coastguard Worker 736*ec779b8eSAndroid Build Coastguard Worker void setVolumeForOutput_l(uint32_t left, uint32_t right) 737*ec779b8eSAndroid Build Coastguard Worker REQUIRES(audio_utils::EffectChain_Mutex); 738*ec779b8eSAndroid Build Coastguard Worker 739*ec779b8eSAndroid Build Coastguard Worker ssize_t getInsertIndex_l(const effect_descriptor_t& desc) 740*ec779b8eSAndroid Build Coastguard Worker REQUIRES(audio_utils::EffectChain_Mutex); 741*ec779b8eSAndroid Build Coastguard Worker 742*ec779b8eSAndroid Build Coastguard Worker std::optional<size_t> findVolumeControl_l(size_t from, size_t to) const 743*ec779b8eSAndroid Build Coastguard Worker REQUIRES(audio_utils::EffectChain_Mutex); 744*ec779b8eSAndroid Build Coastguard Worker 745*ec779b8eSAndroid Build Coastguard Worker // mutex protecting effect list 746*ec779b8eSAndroid Build Coastguard Worker mutable audio_utils::mutex mMutex{audio_utils::MutexOrder::kEffectChain_Mutex}; 747*ec779b8eSAndroid Build Coastguard Worker Vector<sp<IAfEffectModule>> mEffects GUARDED_BY(mutex()); // list of effect modules 748*ec779b8eSAndroid Build Coastguard Worker audio_session_t mSessionId; // audio session ID 749*ec779b8eSAndroid Build Coastguard Worker sp<EffectBufferHalInterface> mInBuffer; // chain input buffer 750*ec779b8eSAndroid Build Coastguard Worker sp<EffectBufferHalInterface> mOutBuffer; // chain output buffer 751*ec779b8eSAndroid Build Coastguard Worker 752*ec779b8eSAndroid Build Coastguard Worker // 'volatile' here means these are accessed with atomic operations instead of mutex 753*ec779b8eSAndroid Build Coastguard Worker volatile int32_t mActiveTrackCnt; // number of active tracks connected 754*ec779b8eSAndroid Build Coastguard Worker volatile int32_t mTrackCnt; // number of tracks connected 755*ec779b8eSAndroid Build Coastguard Worker 756*ec779b8eSAndroid Build Coastguard Worker int32_t mTailBufferCount; // current effect tail buffer count 757*ec779b8eSAndroid Build Coastguard Worker int32_t mMaxTailBuffers; // maximum effect tail buffers 758*ec779b8eSAndroid Build Coastguard Worker uint32_t mLeftVolume; // previous volume on left channel 759*ec779b8eSAndroid Build Coastguard Worker uint32_t mRightVolume; // previous volume on right channel 760*ec779b8eSAndroid Build Coastguard Worker uint32_t mNewLeftVolume; // new volume on left channel 761*ec779b8eSAndroid Build Coastguard Worker uint32_t mNewRightVolume; // new volume on right channel 762*ec779b8eSAndroid Build Coastguard Worker product_strategy_t mStrategy = PRODUCT_STRATEGY_NONE; // strategy for this effect chain 763*ec779b8eSAndroid Build Coastguard Worker // mSuspendedEffects lists all effects currently suspended in the chain. 764*ec779b8eSAndroid Build Coastguard Worker // Use effect type UUID timelow field as key. There is no real risk of identical 765*ec779b8eSAndroid Build Coastguard Worker // timeLow fields among effect type UUIDs. 766*ec779b8eSAndroid Build Coastguard Worker // Updated by setEffectSuspended_l() and setEffectSuspendedAll_l() only. 767*ec779b8eSAndroid Build Coastguard Worker KeyedVector< int, sp<SuspendedEffectDesc> > mSuspendedEffects; 768*ec779b8eSAndroid Build Coastguard Worker 769*ec779b8eSAndroid Build Coastguard Worker const sp<EffectCallback> mEffectCallback; 770*ec779b8eSAndroid Build Coastguard Worker 771*ec779b8eSAndroid Build Coastguard Worker wp<IAfEffectModule> mVolumeControlEffect; 772*ec779b8eSAndroid Build Coastguard Worker }; 773*ec779b8eSAndroid Build Coastguard Worker 774*ec779b8eSAndroid Build Coastguard Worker class DeviceEffectProxy : public IAfDeviceEffectProxy, public EffectBase { 775*ec779b8eSAndroid Build Coastguard Worker public: DeviceEffectProxy(const AudioDeviceTypeAddr & device,const sp<DeviceEffectManagerCallback> & callback,effect_descriptor_t * desc,int id,bool notifyFramesProcessed)776*ec779b8eSAndroid Build Coastguard Worker DeviceEffectProxy(const AudioDeviceTypeAddr& device, 777*ec779b8eSAndroid Build Coastguard Worker const sp<DeviceEffectManagerCallback>& callback, 778*ec779b8eSAndroid Build Coastguard Worker effect_descriptor_t *desc, int id, bool notifyFramesProcessed) 779*ec779b8eSAndroid Build Coastguard Worker : EffectBase(callback, desc, id, AUDIO_SESSION_DEVICE, false), 780*ec779b8eSAndroid Build Coastguard Worker mDevice(device), mManagerCallback(callback), 781*ec779b8eSAndroid Build Coastguard Worker mMyCallback(new ProxyCallback(wp<DeviceEffectProxy>(this), callback)), 782*ec779b8eSAndroid Build Coastguard Worker mNotifyFramesProcessed(notifyFramesProcessed) {} 783*ec779b8eSAndroid Build Coastguard Worker 784*ec779b8eSAndroid Build Coastguard Worker status_t setEnabled(bool enabled, bool fromHandle) final; asDeviceEffectProxy()785*ec779b8eSAndroid Build Coastguard Worker sp<IAfDeviceEffectProxy> asDeviceEffectProxy() final { return this; } 786*ec779b8eSAndroid Build Coastguard Worker 787*ec779b8eSAndroid Build Coastguard Worker status_t init_l(const std::map<audio_patch_handle_t, IAfPatchPanel::Patch>& patches) final 788*ec779b8eSAndroid Build Coastguard Worker REQUIRES(audio_utils::DeviceEffectManager_Mutex) EXCLUDES_EffectBase_Mutex; 789*ec779b8eSAndroid Build Coastguard Worker 790*ec779b8eSAndroid Build Coastguard Worker status_t onCreatePatch(audio_patch_handle_t patchHandle, 791*ec779b8eSAndroid Build Coastguard Worker const IAfPatchPanel::Patch& patch) final; 792*ec779b8eSAndroid Build Coastguard Worker 793*ec779b8eSAndroid Build Coastguard Worker status_t onUpdatePatch(audio_patch_handle_t oldPatchHandle, audio_patch_handle_t newPatchHandle, 794*ec779b8eSAndroid Build Coastguard Worker const IAfPatchPanel::Patch& patch) final; 795*ec779b8eSAndroid Build Coastguard Worker 796*ec779b8eSAndroid Build Coastguard Worker sp<IAfEffectHandle> onReleasePatch(audio_patch_handle_t patchHandle) final; 797*ec779b8eSAndroid Build Coastguard Worker 798*ec779b8eSAndroid Build Coastguard Worker size_t removeEffect(const sp<IAfEffectModule>& effect) final; 799*ec779b8eSAndroid Build Coastguard Worker 800*ec779b8eSAndroid Build Coastguard Worker status_t addEffectToHal(const sp<EffectHalInterface>& effect) final; 801*ec779b8eSAndroid Build Coastguard Worker status_t removeEffectFromHal(const sp<EffectHalInterface>& effect) final; 802*ec779b8eSAndroid Build Coastguard Worker device()803*ec779b8eSAndroid Build Coastguard Worker const AudioDeviceTypeAddr& device() const final { return mDevice; }; 804*ec779b8eSAndroid Build Coastguard Worker bool isOutput() const final; 805*ec779b8eSAndroid Build Coastguard Worker uint32_t sampleRate() const final; 806*ec779b8eSAndroid Build Coastguard Worker audio_channel_mask_t channelMask() const final; 807*ec779b8eSAndroid Build Coastguard Worker uint32_t channelCount() const final; 808*ec779b8eSAndroid Build Coastguard Worker 809*ec779b8eSAndroid Build Coastguard Worker status_t command(int32_t cmdCode, const std::vector<uint8_t>& cmdData, int32_t maxReplySize, 810*ec779b8eSAndroid Build Coastguard Worker std::vector<uint8_t>* reply) final EXCLUDES_DeviceEffectProxy_ProxyMutex; 811*ec779b8eSAndroid Build Coastguard Worker 812*ec779b8eSAndroid Build Coastguard Worker void dump2(int fd, int spaces) const final; 813*ec779b8eSAndroid Build Coastguard Worker 814*ec779b8eSAndroid Build Coastguard Worker private: 815*ec779b8eSAndroid Build Coastguard Worker 816*ec779b8eSAndroid Build Coastguard Worker class ProxyCallback : public EffectCallbackInterface { 817*ec779b8eSAndroid Build Coastguard Worker public: 818*ec779b8eSAndroid Build Coastguard Worker // Note: ctors taking a weak pointer to their owner must not promote it 819*ec779b8eSAndroid Build Coastguard Worker // during construction (but may keep a reference for later promotion). ProxyCallback(const wp<DeviceEffectProxy> & owner,const sp<DeviceEffectManagerCallback> & callback)820*ec779b8eSAndroid Build Coastguard Worker ProxyCallback(const wp<DeviceEffectProxy>& owner, 821*ec779b8eSAndroid Build Coastguard Worker const sp<DeviceEffectManagerCallback>& callback) 822*ec779b8eSAndroid Build Coastguard Worker : mProxy(owner), mManagerCallback(callback) {} 823*ec779b8eSAndroid Build Coastguard Worker 824*ec779b8eSAndroid Build Coastguard Worker status_t createEffectHal(const effect_uuid_t *pEffectUuid, 825*ec779b8eSAndroid Build Coastguard Worker int32_t sessionId, int32_t deviceId, sp<EffectHalInterface> *effect) override; allocateHalBuffer(size_t size __unused,sp<EffectBufferHalInterface> * buffer __unused)826*ec779b8eSAndroid Build Coastguard Worker status_t allocateHalBuffer(size_t size __unused, 827*ec779b8eSAndroid Build Coastguard Worker sp<EffectBufferHalInterface>* buffer __unused) override { return NO_ERROR; } updateOrphanEffectChains(const sp<IAfEffectBase> & effect __unused)828*ec779b8eSAndroid Build Coastguard Worker bool updateOrphanEffectChains(const sp<IAfEffectBase>& effect __unused) override { 829*ec779b8eSAndroid Build Coastguard Worker return false; 830*ec779b8eSAndroid Build Coastguard Worker } 831*ec779b8eSAndroid Build Coastguard Worker io()832*ec779b8eSAndroid Build Coastguard Worker audio_io_handle_t io() const override { return AUDIO_IO_HANDLE_NONE; } 833*ec779b8eSAndroid Build Coastguard Worker bool isOutput() const override; isOffload()834*ec779b8eSAndroid Build Coastguard Worker bool isOffload() const override { return false; } isOffloadOrDirect()835*ec779b8eSAndroid Build Coastguard Worker bool isOffloadOrDirect() const override { return false; } isOffloadOrMmap()836*ec779b8eSAndroid Build Coastguard Worker bool isOffloadOrMmap() const override { return false; } isSpatializer()837*ec779b8eSAndroid Build Coastguard Worker bool isSpatializer() const override { return false; } 838*ec779b8eSAndroid Build Coastguard Worker 839*ec779b8eSAndroid Build Coastguard Worker uint32_t sampleRate() const override; 840*ec779b8eSAndroid Build Coastguard Worker audio_channel_mask_t inChannelMask(int id) const override; 841*ec779b8eSAndroid Build Coastguard Worker uint32_t inChannelCount(int id) const override; 842*ec779b8eSAndroid Build Coastguard Worker audio_channel_mask_t outChannelMask() const override; 843*ec779b8eSAndroid Build Coastguard Worker uint32_t outChannelCount() const override; hapticChannelMask()844*ec779b8eSAndroid Build Coastguard Worker audio_channel_mask_t hapticChannelMask() const override { return AUDIO_CHANNEL_NONE; } 845*ec779b8eSAndroid Build Coastguard Worker /** 846*ec779b8eSAndroid Build Coastguard Worker * frameCount cannot be zero. 847*ec779b8eSAndroid Build Coastguard Worker */ frameCount()848*ec779b8eSAndroid Build Coastguard Worker size_t frameCount() const override { return 1; } latency()849*ec779b8eSAndroid Build Coastguard Worker uint32_t latency() const override { return 0; } 850*ec779b8eSAndroid Build Coastguard Worker 851*ec779b8eSAndroid Build Coastguard Worker status_t addEffectToHal(const sp<EffectHalInterface>& effect) override; 852*ec779b8eSAndroid Build Coastguard Worker status_t removeEffectFromHal(const sp<EffectHalInterface>& effect) override; 853*ec779b8eSAndroid Build Coastguard Worker 854*ec779b8eSAndroid Build Coastguard Worker bool disconnectEffectHandle(IAfEffectHandle *handle, bool unpinIfLast) override; setVolumeForOutput(float left __unused,float right __unused)855*ec779b8eSAndroid Build Coastguard Worker void setVolumeForOutput(float left __unused, float right __unused) const override {} 856*ec779b8eSAndroid Build Coastguard Worker checkSuspendOnEffectEnabled(const sp<IAfEffectBase> & effect __unused,bool enabled __unused,bool threadLocked __unused)857*ec779b8eSAndroid Build Coastguard Worker void checkSuspendOnEffectEnabled(const sp<IAfEffectBase>& effect __unused, 858*ec779b8eSAndroid Build Coastguard Worker bool enabled __unused, bool threadLocked __unused) override {} resetVolume_l()859*ec779b8eSAndroid Build Coastguard Worker void resetVolume_l() override REQUIRES(audio_utils::EffectChain_Mutex) {} strategy()860*ec779b8eSAndroid Build Coastguard Worker product_strategy_t strategy() const override { return PRODUCT_STRATEGY_NONE; } activeTrackCnt()861*ec779b8eSAndroid Build Coastguard Worker int32_t activeTrackCnt() const override { return 0; } 862*ec779b8eSAndroid Build Coastguard Worker void onEffectEnable(const sp<IAfEffectBase>& effect __unused) override; 863*ec779b8eSAndroid Build Coastguard Worker void onEffectDisable(const sp<IAfEffectBase>& effect __unused) override; 864*ec779b8eSAndroid Build Coastguard Worker chain()865*ec779b8eSAndroid Build Coastguard Worker wp<IAfEffectChain> chain() const override { return nullptr; } 866*ec779b8eSAndroid Build Coastguard Worker isAudioPolicyReady()867*ec779b8eSAndroid Build Coastguard Worker bool isAudioPolicyReady() const override { 868*ec779b8eSAndroid Build Coastguard Worker return mManagerCallback->isAudioPolicyReady(); 869*ec779b8eSAndroid Build Coastguard Worker } 870*ec779b8eSAndroid Build Coastguard Worker 871*ec779b8eSAndroid Build Coastguard Worker int newEffectId(); 872*ec779b8eSAndroid Build Coastguard Worker 873*ec779b8eSAndroid Build Coastguard Worker private: 874*ec779b8eSAndroid Build Coastguard Worker const wp<DeviceEffectProxy> mProxy; 875*ec779b8eSAndroid Build Coastguard Worker const sp<DeviceEffectManagerCallback> mManagerCallback; 876*ec779b8eSAndroid Build Coastguard Worker }; 877*ec779b8eSAndroid Build Coastguard Worker 878*ec779b8eSAndroid Build Coastguard Worker status_t checkPort(const IAfPatchPanel::Patch& patch, 879*ec779b8eSAndroid Build Coastguard Worker const struct audio_port_config* port, sp<IAfEffectHandle>* handle); 880*ec779b8eSAndroid Build Coastguard Worker 881*ec779b8eSAndroid Build Coastguard Worker const AudioDeviceTypeAddr mDevice; 882*ec779b8eSAndroid Build Coastguard Worker const sp<DeviceEffectManagerCallback> mManagerCallback; 883*ec779b8eSAndroid Build Coastguard Worker const sp<ProxyCallback> mMyCallback; 884*ec779b8eSAndroid Build Coastguard Worker proxyMutex()885*ec779b8eSAndroid Build Coastguard Worker audio_utils::mutex& proxyMutex() const 886*ec779b8eSAndroid Build Coastguard Worker RETURN_CAPABILITY(android::audio_utils::DeviceEffectProxy_ProxyMutex) { 887*ec779b8eSAndroid Build Coastguard Worker return mProxyMutex; 888*ec779b8eSAndroid Build Coastguard Worker } 889*ec779b8eSAndroid Build Coastguard Worker mutable audio_utils::mutex mProxyMutex{ 890*ec779b8eSAndroid Build Coastguard Worker audio_utils::MutexOrder::kDeviceEffectProxy_ProxyMutex}; 891*ec779b8eSAndroid Build Coastguard Worker std::map<audio_patch_handle_t, sp<IAfEffectHandle>> mEffectHandles; // protected by mProxyMutex 892*ec779b8eSAndroid Build Coastguard Worker sp<IAfEffectModule> mHalEffect; // protected by mProxyMutex 893*ec779b8eSAndroid Build Coastguard Worker struct audio_port_config mDevicePort = { .id = AUDIO_PORT_HANDLE_NONE }; 894*ec779b8eSAndroid Build Coastguard Worker const bool mNotifyFramesProcessed; 895*ec779b8eSAndroid Build Coastguard Worker }; 896*ec779b8eSAndroid Build Coastguard Worker 897*ec779b8eSAndroid Build Coastguard Worker } // namespace android 898