1 /* 2 ** 3 ** Copyright 2012, The Android Open Source Project 4 ** 5 ** Licensed under the Apache License, Version 2.0 (the "License"); 6 ** you may not use this file except in compliance with the License. 7 ** You may obtain a copy of the License at 8 ** 9 ** http://www.apache.org/licenses/LICENSE-2.0 10 ** 11 ** Unless required by applicable law or agreed to in writing, software 12 ** distributed under the License is distributed on an "AS IS" BASIS, 13 ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 ** See the License for the specific language governing permissions and 15 ** limitations under the License. 16 */ 17 18 #ifndef INCLUDING_FROM_AUDIOFLINGER_H 19 #error This header file should only be included from AudioFlinger.h 20 #endif 21 22 //--- Audio Effect Management 23 24 // EffectModule and EffectChain classes both have their own mutex to protect 25 // state changes or resource modifications. Always respect the following order 26 // if multiple mutexes must be acquired to avoid cross deadlock: 27 // AudioFlinger -> ThreadBase -> EffectChain -> EffectModule 28 29 // The EffectModule class is a wrapper object controlling the effect engine implementation 30 // in the effect library. It prevents concurrent calls to process() and command() functions 31 // from different client threads. It keeps a list of EffectHandle objects corresponding 32 // to all client applications using this effect and notifies applications of effect state, 33 // control or parameter changes. It manages the activation state machine to send appropriate 34 // reset, enable, disable commands to effect engine and provide volume 35 // ramping when effects are activated/deactivated. 36 // When controlling an auxiliary effect, the EffectModule also provides an input buffer used by 37 // the attached track(s) to accumulate their auxiliary channel. 38 class EffectModule : public RefBase { 39 public: 40 EffectModule(ThreadBase *thread, 41 const wp<AudioFlinger::EffectChain>& chain, 42 effect_descriptor_t *desc, 43 int id, 44 int sessionId); 45 virtual ~EffectModule(); 46 47 enum effect_state { 48 IDLE, 49 RESTART, 50 STARTING, 51 ACTIVE, 52 STOPPING, 53 STOPPED, 54 DESTROYED 55 }; 56 id()57 int id() const { return mId; } 58 void process(); 59 void updateState(); 60 status_t command(uint32_t cmdCode, 61 uint32_t cmdSize, 62 void *pCmdData, 63 uint32_t *replySize, 64 void *pReplyData); 65 66 void reset_l(); 67 status_t configure(); 68 status_t init(); state()69 effect_state state() const { 70 return mState; 71 } status()72 uint32_t status() { 73 return mStatus; 74 } sessionId()75 int sessionId() const { 76 return mSessionId; 77 } 78 status_t setEnabled(bool enabled); 79 status_t setEnabled_l(bool enabled); 80 bool isEnabled() const; 81 bool isProcessEnabled() const; 82 setInBuffer(int16_t * buffer)83 void setInBuffer(int16_t *buffer) { mConfig.inputCfg.buffer.s16 = buffer; } inBuffer()84 int16_t *inBuffer() { return mConfig.inputCfg.buffer.s16; } setOutBuffer(int16_t * buffer)85 void setOutBuffer(int16_t *buffer) { mConfig.outputCfg.buffer.s16 = buffer; } outBuffer()86 int16_t *outBuffer() { return mConfig.outputCfg.buffer.s16; } setChain(const wp<EffectChain> & chain)87 void setChain(const wp<EffectChain>& chain) { mChain = chain; } setThread(const wp<ThreadBase> & thread)88 void setThread(const wp<ThreadBase>& thread) { mThread = thread; } thread()89 const wp<ThreadBase>& thread() { return mThread; } 90 91 status_t addHandle(EffectHandle *handle); 92 size_t disconnect(EffectHandle *handle, bool unpinIfLast); 93 size_t removeHandle(EffectHandle *handle); 94 desc()95 const effect_descriptor_t& desc() const { return mDescriptor; } chain()96 wp<EffectChain>& chain() { return mChain; } 97 98 status_t setDevice(audio_devices_t device); 99 status_t setVolume(uint32_t *left, uint32_t *right, bool controller); 100 status_t setMode(audio_mode_t mode); 101 status_t setAudioSource(audio_source_t source); 102 status_t start(); 103 status_t stop(); 104 void setSuspended(bool suspended); 105 bool suspended() const; 106 107 EffectHandle* controlHandle_l(); 108 isPinned()109 bool isPinned() const { return mPinned; } unPin()110 void unPin() { mPinned = false; } 111 bool purgeHandles(); lock()112 void lock() { mLock.lock(); } unlock()113 void unlock() { mLock.unlock(); } 114 115 void dump(int fd, const Vector<String16>& args); 116 117 protected: 118 friend class AudioFlinger; // for mHandles 119 bool mPinned; 120 121 // Maximum time allocated to effect engines to complete the turn off sequence 122 static const uint32_t MAX_DISABLE_TIME_MS = 10000; 123 124 EffectModule(const EffectModule&); 125 EffectModule& operator = (const EffectModule&); 126 127 status_t start_l(); 128 status_t stop_l(); 129 130 mutable Mutex mLock; // mutex for process, commands and handles list protection 131 wp<ThreadBase> mThread; // parent thread 132 wp<EffectChain> mChain; // parent effect chain 133 const int mId; // this instance unique ID 134 const int mSessionId; // audio session ID 135 const effect_descriptor_t mDescriptor;// effect descriptor received from effect engine 136 effect_config_t mConfig; // input and output audio configuration 137 effect_handle_t mEffectInterface; // Effect module C API 138 status_t mStatus; // initialization status 139 effect_state mState; // current activation state 140 Vector<EffectHandle *> mHandles; // list of client handles 141 // First handle in mHandles has highest priority and controls the effect module 142 uint32_t mMaxDisableWaitCnt; // maximum grace period before forcing an effect off after 143 // sending disable command. 144 uint32_t mDisableWaitCnt; // current process() calls count during disable period. 145 bool mSuspended; // effect is suspended: temporarily disabled by framework 146 }; 147 148 // The EffectHandle class implements the IEffect interface. It provides resources 149 // to receive parameter updates, keeps track of effect control 150 // ownership and state and has a pointer to the EffectModule object it is controlling. 151 // There is one EffectHandle object for each application controlling (or using) 152 // an effect module. 153 // The EffectHandle is obtained by calling AudioFlinger::createEffect(). 154 class EffectHandle: public android::BnEffect { 155 public: 156 157 EffectHandle(const sp<EffectModule>& effect, 158 const sp<AudioFlinger::Client>& client, 159 const sp<IEffectClient>& effectClient, 160 int32_t priority); 161 virtual ~EffectHandle(); 162 163 // IEffect 164 virtual status_t enable(); 165 virtual status_t disable(); 166 virtual status_t command(uint32_t cmdCode, 167 uint32_t cmdSize, 168 void *pCmdData, 169 uint32_t *replySize, 170 void *pReplyData); 171 virtual void disconnect(); 172 private: 173 void disconnect(bool unpinIfLast); 174 public: getCblk()175 virtual sp<IMemory> getCblk() const { return mCblkMemory; } 176 virtual status_t onTransact(uint32_t code, const Parcel& data, 177 Parcel* reply, uint32_t flags); 178 179 180 // Give or take control of effect module 181 // - hasControl: true if control is given, false if removed 182 // - signal: true client app should be signaled of change, false otherwise 183 // - enabled: state of the effect when control is passed 184 void setControl(bool hasControl, bool signal, bool enabled); 185 void commandExecuted(uint32_t cmdCode, 186 uint32_t cmdSize, 187 void *pCmdData, 188 uint32_t replySize, 189 void *pReplyData); 190 void setEnabled(bool enabled); enabled()191 bool enabled() const { return mEnabled; } 192 193 // Getters id()194 int id() const { return mEffect->id(); } priority()195 int priority() const { return mPriority; } hasControl()196 bool hasControl() const { return mHasControl; } effect()197 sp<EffectModule> effect() const { return mEffect; } 198 // destroyed_l() must be called with the associated EffectModule mLock held destroyed_l()199 bool destroyed_l() const { return mDestroyed; } 200 201 void dump(char* buffer, size_t size); 202 203 protected: 204 friend class AudioFlinger; // for mEffect, mHasControl, mEnabled 205 EffectHandle(const EffectHandle&); 206 EffectHandle& operator =(const EffectHandle&); 207 208 sp<EffectModule> mEffect; // pointer to controlled EffectModule 209 sp<IEffectClient> mEffectClient; // callback interface for client notifications 210 /*const*/ sp<Client> mClient; // client for shared memory allocation, see disconnect() 211 sp<IMemory> mCblkMemory; // shared memory for control block 212 effect_param_cblk_t* mCblk; // control block for deferred parameter setting via 213 // shared memory 214 uint8_t* mBuffer; // pointer to parameter area in shared memory 215 int mPriority; // client application priority to control the effect 216 bool mHasControl; // true if this handle is controlling the effect 217 bool mEnabled; // cached enable state: needed when the effect is 218 // restored after being suspended 219 bool mDestroyed; // Set to true by destructor. Access with EffectModule 220 // mLock held 221 }; 222 223 // the EffectChain class represents a group of effects associated to one audio session. 224 // There can be any number of EffectChain objects per output mixer thread (PlaybackThread). 225 // The EffecChain with session ID 0 contains global effects applied to the output mix. 226 // Effects in this chain can be insert or auxiliary. Effects in other chains (attached to 227 // tracks) are insert only. The EffectChain maintains an ordered list of effect module, the 228 // order corresponding in the effect process order. When attached to a track (session ID != 0), 229 // it also provide it's own input buffer used by the track as accumulation buffer. 230 class EffectChain : public RefBase { 231 public: 232 EffectChain(const wp<ThreadBase>& wThread, int sessionId); 233 EffectChain(ThreadBase *thread, int sessionId); 234 virtual ~EffectChain(); 235 236 // special key used for an entry in mSuspendedEffects keyed vector 237 // corresponding to a suspend all request. 238 static const int kKeyForSuspendAll = 0; 239 240 // minimum duration during which we force calling effect process when last track on 241 // a session is stopped or removed to allow effect tail to be rendered 242 static const int kProcessTailDurationMs = 1000; 243 244 void process_l(); 245 lock()246 void lock() { 247 mLock.lock(); 248 } unlock()249 void unlock() { 250 mLock.unlock(); 251 } 252 253 status_t addEffect_l(const sp<EffectModule>& handle); 254 size_t removeEffect_l(const sp<EffectModule>& handle); 255 sessionId()256 int sessionId() const { return mSessionId; } setSessionId(int sessionId)257 void setSessionId(int sessionId) { mSessionId = sessionId; } 258 259 sp<EffectModule> getEffectFromDesc_l(effect_descriptor_t *descriptor); 260 sp<EffectModule> getEffectFromId_l(int id); 261 sp<EffectModule> getEffectFromType_l(const effect_uuid_t *type); 262 bool setVolume_l(uint32_t *left, uint32_t *right); 263 void setDevice_l(audio_devices_t device); 264 void setMode_l(audio_mode_t mode); 265 void setAudioSource_l(audio_source_t source); 266 267 void setInBuffer(int16_t *buffer, bool ownsBuffer = false) { 268 mInBuffer = buffer; 269 mOwnInBuffer = ownsBuffer; 270 } inBuffer()271 int16_t *inBuffer() const { 272 return mInBuffer; 273 } setOutBuffer(int16_t * buffer)274 void setOutBuffer(int16_t *buffer) { 275 mOutBuffer = buffer; 276 } outBuffer()277 int16_t *outBuffer() const { 278 return mOutBuffer; 279 } 280 incTrackCnt()281 void incTrackCnt() { android_atomic_inc(&mTrackCnt); } decTrackCnt()282 void decTrackCnt() { android_atomic_dec(&mTrackCnt); } trackCnt()283 int32_t trackCnt() const { return android_atomic_acquire_load(&mTrackCnt); } 284 incActiveTrackCnt()285 void incActiveTrackCnt() { android_atomic_inc(&mActiveTrackCnt); 286 mTailBufferCount = mMaxTailBuffers; } decActiveTrackCnt()287 void decActiveTrackCnt() { android_atomic_dec(&mActiveTrackCnt); } activeTrackCnt()288 int32_t activeTrackCnt() const { return android_atomic_acquire_load(&mActiveTrackCnt); } 289 strategy()290 uint32_t strategy() const { return mStrategy; } setStrategy(uint32_t strategy)291 void setStrategy(uint32_t strategy) 292 { mStrategy = strategy; } 293 294 // suspend effect of the given type 295 void setEffectSuspended_l(const effect_uuid_t *type, 296 bool suspend); 297 // suspend all eligible effects 298 void setEffectSuspendedAll_l(bool suspend); 299 // check if effects should be suspend or restored when a given effect is enable or disabled 300 void checkSuspendOnEffectEnabled(const sp<EffectModule>& effect, 301 bool enabled); 302 303 void clearInputBuffer(); 304 305 void dump(int fd, const Vector<String16>& args); 306 307 protected: 308 friend class AudioFlinger; // for mThread, mEffects 309 EffectChain(const EffectChain&); 310 EffectChain& operator =(const EffectChain&); 311 312 class SuspendedEffectDesc : public RefBase { 313 public: SuspendedEffectDesc()314 SuspendedEffectDesc() : mRefCount(0) {} 315 316 int mRefCount; 317 effect_uuid_t mType; 318 wp<EffectModule> mEffect; 319 }; 320 321 // get a list of effect modules to suspend when an effect of the type 322 // passed is enabled. 323 void getSuspendEligibleEffects(Vector< sp<EffectModule> > &effects); 324 325 // get an effect module if it is currently enable 326 sp<EffectModule> getEffectIfEnabled(const effect_uuid_t *type); 327 // true if the effect whose descriptor is passed can be suspended 328 // OEMs can modify the rules implemented in this method to exclude specific effect 329 // types or implementations from the suspend/restore mechanism. 330 bool isEffectEligibleForSuspend(const effect_descriptor_t& desc); 331 332 void clearInputBuffer_l(sp<ThreadBase> thread); 333 334 wp<ThreadBase> mThread; // parent mixer thread 335 Mutex mLock; // mutex protecting effect list 336 Vector< sp<EffectModule> > mEffects; // list of effect modules 337 int mSessionId; // audio session ID 338 int16_t *mInBuffer; // chain input buffer 339 int16_t *mOutBuffer; // chain output buffer 340 341 // 'volatile' here means these are accessed with atomic operations instead of mutex 342 volatile int32_t mActiveTrackCnt; // number of active tracks connected 343 volatile int32_t mTrackCnt; // number of tracks connected 344 345 int32_t mTailBufferCount; // current effect tail buffer count 346 int32_t mMaxTailBuffers; // maximum effect tail buffers 347 bool mOwnInBuffer; // true if the chain owns its input buffer 348 int mVolumeCtrlIdx; // index of insert effect having control over volume 349 uint32_t mLeftVolume; // previous volume on left channel 350 uint32_t mRightVolume; // previous volume on right channel 351 uint32_t mNewLeftVolume; // new volume on left channel 352 uint32_t mNewRightVolume; // new volume on right channel 353 uint32_t mStrategy; // strategy for this effect chain 354 // mSuspendedEffects lists all effects currently suspended in the chain. 355 // Use effect type UUID timelow field as key. There is no real risk of identical 356 // timeLow fields among effect type UUIDs. 357 // Updated by updateSuspendedSessions_l() only. 358 KeyedVector< int, sp<SuspendedEffectDesc> > mSuspendedEffects; 359 }; 360