Effects.h revision 022b9953153bdb1984f0abb17d21ef8c1826ad49
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// AudioHandle -> ThreadBase -> EffectChain -> EffectModule 29// In addition, methods that lock the AudioPolicyService mutex (getOutputForEffect(), 30// startOutput(), getInputForAttr(), releaseInput()...) should never be called with AudioFlinger or 31// Threadbase mutex locked to avoid cross deadlock with other clients calling AudioPolicyService 32// methods that in turn call AudioFlinger thus locking the same mutexes in the reverse order. 33 34// The EffectModule class is a wrapper object controlling the effect engine implementation 35// in the effect library. It prevents concurrent calls to process() and command() functions 36// from different client threads. It keeps a list of EffectHandle objects corresponding 37// to all client applications using this effect and notifies applications of effect state, 38// control or parameter changes. It manages the activation state machine to send appropriate 39// reset, enable, disable commands to effect engine and provide volume 40// ramping when effects are activated/deactivated. 41// When controlling an auxiliary effect, the EffectModule also provides an input buffer used by 42// the attached track(s) to accumulate their auxiliary channel. 43class EffectModule : public RefBase { 44public: 45 EffectModule(ThreadBase *thread, 46 const wp<AudioFlinger::EffectChain>& chain, 47 effect_descriptor_t *desc, 48 int id, 49 audio_session_t sessionId, 50 bool pinned); 51 virtual ~EffectModule(); 52 53 enum effect_state { 54 IDLE, 55 RESTART, 56 STARTING, 57 ACTIVE, 58 STOPPING, 59 STOPPED, 60 DESTROYED 61 }; 62 63 int id() const { return mId; } 64 void process(); 65 bool updateState(); 66 status_t command(uint32_t cmdCode, 67 uint32_t cmdSize, 68 void *pCmdData, 69 uint32_t *replySize, 70 void *pReplyData); 71 72 void reset_l(); 73 status_t configure(); 74 status_t init(); 75 effect_state state() const { 76 return mState; 77 } 78 uint32_t status() { 79 return mStatus; 80 } 81 audio_session_t sessionId() const { 82 return mSessionId; 83 } 84 status_t setEnabled(bool enabled); 85 status_t setEnabled_l(bool enabled); 86 bool isEnabled() const; 87 bool isProcessEnabled() const; 88 89 void setInBuffer(const sp<EffectBufferHalInterface>& buffer); 90 int16_t *inBuffer() const { 91 return mInBuffer != 0 ? reinterpret_cast<int16_t*>(mInBuffer->ptr()) : NULL; 92 } 93 void setOutBuffer(const sp<EffectBufferHalInterface>& buffer); 94 int16_t *outBuffer() const { 95 return mOutBuffer != 0 ? reinterpret_cast<int16_t*>(mOutBuffer->ptr()) : NULL; 96 } 97 void setChain(const wp<EffectChain>& chain) { mChain = chain; } 98 void setThread(const wp<ThreadBase>& thread) { mThread = thread; } 99 const wp<ThreadBase>& thread() { return mThread; } 100 101 status_t addHandle(EffectHandle *handle); 102 ssize_t disconnectHandle(EffectHandle *handle, bool unpinIfLast); 103 ssize_t removeHandle(EffectHandle *handle); 104 ssize_t removeHandle_l(EffectHandle *handle); 105 106 const effect_descriptor_t& desc() const { return mDescriptor; } 107 wp<EffectChain>& chain() { return mChain; } 108 109 status_t setDevice(audio_devices_t device); 110 status_t setVolume(uint32_t *left, uint32_t *right, bool controller); 111 status_t setMode(audio_mode_t mode); 112 status_t setAudioSource(audio_source_t source); 113 status_t start(); 114 status_t stop(); 115 void setSuspended(bool suspended); 116 bool suspended() const; 117 118 EffectHandle* controlHandle_l(); 119 120 bool isPinned() const { return mPinned; } 121 void unPin() { mPinned = false; } 122 bool purgeHandles(); 123 void lock() { mLock.lock(); } 124 void unlock() { mLock.unlock(); } 125 bool isOffloadable() const 126 { return (mDescriptor.flags & EFFECT_FLAG_OFFLOAD_SUPPORTED) != 0; } 127 bool isImplementationSoftware() const 128 { return (mDescriptor.flags & EFFECT_FLAG_HW_ACC_MASK) == 0; } 129 bool isProcessImplemented() const 130 { return (mDescriptor.flags & EFFECT_FLAG_NO_PROCESS) == 0; } 131 status_t setOffloaded(bool offloaded, audio_io_handle_t io); 132 bool isOffloaded() const; 133 void addEffectToHal_l(); 134 void release_l(); 135 136 void dump(int fd, const Vector<String16>& args); 137 138protected: 139 friend class AudioFlinger; // for mHandles 140 bool mPinned; 141 142 // Maximum time allocated to effect engines to complete the turn off sequence 143 static const uint32_t MAX_DISABLE_TIME_MS = 10000; 144 145 EffectModule(const EffectModule&); 146 EffectModule& operator = (const EffectModule&); 147 148 status_t start_l(); 149 status_t stop_l(); 150 status_t remove_effect_from_hal_l(); 151 152mutable Mutex mLock; // mutex for process, commands and handles list protection 153 wp<ThreadBase> mThread; // parent thread 154 wp<EffectChain> mChain; // parent effect chain 155 const int mId; // this instance unique ID 156 const audio_session_t mSessionId; // audio session ID 157 const effect_descriptor_t mDescriptor;// effect descriptor received from effect engine 158 effect_config_t mConfig; // input and output audio configuration 159 sp<EffectHalInterface> mEffectInterface; // Effect module HAL 160 sp<EffectBufferHalInterface> mInBuffer; // Buffers for interacting with HAL 161 sp<EffectBufferHalInterface> mOutBuffer; 162 status_t mStatus; // initialization status 163 effect_state mState; // current activation state 164 Vector<EffectHandle *> mHandles; // list of client handles 165 // First handle in mHandles has highest priority and controls the effect module 166 uint32_t mMaxDisableWaitCnt; // maximum grace period before forcing an effect off after 167 // sending disable command. 168 uint32_t mDisableWaitCnt; // current process() calls count during disable period. 169 bool mSuspended; // effect is suspended: temporarily disabled by framework 170 bool mOffloaded; // effect is currently offloaded to the audio DSP 171 wp<AudioFlinger> mAudioFlinger; 172}; 173 174// The EffectHandle class implements the IEffect interface. It provides resources 175// to receive parameter updates, keeps track of effect control 176// ownership and state and has a pointer to the EffectModule object it is controlling. 177// There is one EffectHandle object for each application controlling (or using) 178// an effect module. 179// The EffectHandle is obtained by calling AudioFlinger::createEffect(). 180class EffectHandle: public android::BnEffect { 181public: 182 183 EffectHandle(const sp<EffectModule>& effect, 184 const sp<AudioFlinger::Client>& client, 185 const sp<IEffectClient>& effectClient, 186 int32_t priority); 187 virtual ~EffectHandle(); 188 virtual status_t initCheck(); 189 190 // IEffect 191 virtual status_t enable(); 192 virtual status_t disable(); 193 virtual status_t command(uint32_t cmdCode, 194 uint32_t cmdSize, 195 void *pCmdData, 196 uint32_t *replySize, 197 void *pReplyData); 198 virtual void disconnect(); 199private: 200 void disconnect(bool unpinIfLast); 201public: 202 virtual sp<IMemory> getCblk() const { return mCblkMemory; } 203 virtual status_t onTransact(uint32_t code, const Parcel& data, 204 Parcel* reply, uint32_t flags); 205 206 207 // Give or take control of effect module 208 // - hasControl: true if control is given, false if removed 209 // - signal: true client app should be signaled of change, false otherwise 210 // - enabled: state of the effect when control is passed 211 void setControl(bool hasControl, bool signal, bool enabled); 212 void commandExecuted(uint32_t cmdCode, 213 uint32_t cmdSize, 214 void *pCmdData, 215 uint32_t replySize, 216 void *pReplyData); 217 void setEnabled(bool enabled); 218 bool enabled() const { return mEnabled; } 219 220 // Getters 221 wp<EffectModule> effect() const { return mEffect; } 222 int id() const { 223 sp<EffectModule> effect = mEffect.promote(); 224 if (effect == 0) { 225 return 0; 226 } 227 return effect->id(); 228 } 229 int priority() const { return mPriority; } 230 bool hasControl() const { return mHasControl; } 231 bool disconnected() const { return mDisconnected; } 232 233 void dumpToBuffer(char* buffer, size_t size); 234 235protected: 236 friend class AudioFlinger; // for mEffect, mHasControl, mEnabled 237 EffectHandle(const EffectHandle&); 238 EffectHandle& operator =(const EffectHandle&); 239 240 Mutex mLock; // protects IEffect method calls 241 wp<EffectModule> mEffect; // pointer to controlled EffectModule 242 sp<IEffectClient> mEffectClient; // callback interface for client notifications 243 /*const*/ sp<Client> mClient; // client for shared memory allocation, see disconnect() 244 sp<IMemory> mCblkMemory; // shared memory for control block 245 effect_param_cblk_t* mCblk; // control block for deferred parameter setting via 246 // shared memory 247 uint8_t* mBuffer; // pointer to parameter area in shared memory 248 int mPriority; // client application priority to control the effect 249 bool mHasControl; // true if this handle is controlling the effect 250 bool mEnabled; // cached enable state: needed when the effect is 251 // restored after being suspended 252 bool mDisconnected; // Set to true by disconnect() 253}; 254 255// the EffectChain class represents a group of effects associated to one audio session. 256// There can be any number of EffectChain objects per output mixer thread (PlaybackThread). 257// The EffectChain with session ID AUDIO_SESSION_OUTPUT_MIX contains global effects applied 258// to the output mix. 259// Effects in this chain can be insert or auxiliary. Effects in other chains (attached to 260// tracks) are insert only. The EffectChain maintains an ordered list of effect module, the 261// order corresponding in the effect process order. When attached to a track (session ID != 262// AUDIO_SESSION_OUTPUT_MIX), 263// it also provide it's own input buffer used by the track as accumulation buffer. 264class EffectChain : public RefBase { 265public: 266 EffectChain(const wp<ThreadBase>& wThread, audio_session_t sessionId); 267 EffectChain(ThreadBase *thread, audio_session_t sessionId); 268 virtual ~EffectChain(); 269 270 // special key used for an entry in mSuspendedEffects keyed vector 271 // corresponding to a suspend all request. 272 static const int kKeyForSuspendAll = 0; 273 274 // minimum duration during which we force calling effect process when last track on 275 // a session is stopped or removed to allow effect tail to be rendered 276 static const int kProcessTailDurationMs = 1000; 277 278 void process_l(); 279 280 void lock() { 281 mLock.lock(); 282 } 283 void unlock() { 284 mLock.unlock(); 285 } 286 287 status_t createEffect_l(sp<EffectModule>& effect, 288 ThreadBase *thread, 289 effect_descriptor_t *desc, 290 int id, 291 audio_session_t sessionId, 292 bool pinned); 293 status_t addEffect_l(const sp<EffectModule>& handle); 294 status_t addEffect_ll(const sp<EffectModule>& handle); 295 size_t removeEffect_l(const sp<EffectModule>& handle, bool release = false); 296 297 audio_session_t sessionId() const { return mSessionId; } 298 void setSessionId(audio_session_t sessionId) { mSessionId = sessionId; } 299 300 sp<EffectModule> getEffectFromDesc_l(effect_descriptor_t *descriptor); 301 sp<EffectModule> getEffectFromId_l(int id); 302 sp<EffectModule> getEffectFromType_l(const effect_uuid_t *type); 303 // FIXME use float to improve the dynamic range 304 bool setVolume_l(uint32_t *left, uint32_t *right, bool force = false); 305 void resetVolume_l(); 306 void setDevice_l(audio_devices_t device); 307 void setMode_l(audio_mode_t mode); 308 void setAudioSource_l(audio_source_t source); 309 310 void setInBuffer(const sp<EffectBufferHalInterface>& buffer) { 311 mInBuffer = buffer; 312 } 313 int16_t *inBuffer() const { 314 return mInBuffer != 0 ? reinterpret_cast<int16_t*>(mInBuffer->ptr()) : NULL; 315 } 316 void setOutBuffer(const sp<EffectBufferHalInterface>& buffer) { 317 mOutBuffer = buffer; 318 } 319 int16_t *outBuffer() const { 320 return mOutBuffer != 0 ? reinterpret_cast<int16_t*>(mOutBuffer->ptr()) : NULL; 321 } 322 323 void incTrackCnt() { android_atomic_inc(&mTrackCnt); } 324 void decTrackCnt() { android_atomic_dec(&mTrackCnt); } 325 int32_t trackCnt() const { return android_atomic_acquire_load(&mTrackCnt); } 326 327 void incActiveTrackCnt() { android_atomic_inc(&mActiveTrackCnt); 328 mTailBufferCount = mMaxTailBuffers; } 329 void decActiveTrackCnt() { android_atomic_dec(&mActiveTrackCnt); } 330 int32_t activeTrackCnt() const { return android_atomic_acquire_load(&mActiveTrackCnt); } 331 332 uint32_t strategy() const { return mStrategy; } 333 void setStrategy(uint32_t strategy) 334 { mStrategy = strategy; } 335 336 // suspend effect of the given type 337 void setEffectSuspended_l(const effect_uuid_t *type, 338 bool suspend); 339 // suspend all eligible effects 340 void setEffectSuspendedAll_l(bool suspend); 341 // check if effects should be suspend or restored when a given effect is enable or disabled 342 void checkSuspendOnEffectEnabled(const sp<EffectModule>& effect, 343 bool enabled); 344 345 void clearInputBuffer(); 346 347 // At least one non offloadable effect in the chain is enabled 348 bool isNonOffloadableEnabled(); 349 350 void syncHalEffectsState(); 351 352 // flags is an ORed set of audio_output_flags_t which is updated on return. 353 void checkOutputFlagCompatibility(audio_output_flags_t *flags) const; 354 355 // flags is an ORed set of audio_input_flags_t which is updated on return. 356 void checkInputFlagCompatibility(audio_input_flags_t *flags) const; 357 358 // Is this EffectChain compatible with the RAW audio flag. 359 bool isRawCompatible() const; 360 361 // Is this EffectChain compatible with the FAST audio flag. 362 bool isFastCompatible() const; 363 364 // isCompatibleWithThread_l() must be called with thread->mLock held 365 bool isCompatibleWithThread_l(const sp<ThreadBase>& thread) const; 366 367 void dump(int fd, const Vector<String16>& args); 368 369protected: 370 friend class AudioFlinger; // for mThread, mEffects 371 EffectChain(const EffectChain&); 372 EffectChain& operator =(const EffectChain&); 373 374 class SuspendedEffectDesc : public RefBase { 375 public: 376 SuspendedEffectDesc() : mRefCount(0) {} 377 378 int mRefCount; 379 effect_uuid_t mType; 380 wp<EffectModule> mEffect; 381 }; 382 383 // get a list of effect modules to suspend when an effect of the type 384 // passed is enabled. 385 void getSuspendEligibleEffects(Vector< sp<EffectModule> > &effects); 386 387 // get an effect module if it is currently enable 388 sp<EffectModule> getEffectIfEnabled(const effect_uuid_t *type); 389 // true if the effect whose descriptor is passed can be suspended 390 // OEMs can modify the rules implemented in this method to exclude specific effect 391 // types or implementations from the suspend/restore mechanism. 392 bool isEffectEligibleForSuspend(const effect_descriptor_t& desc); 393 394 void clearInputBuffer_l(const sp<ThreadBase>& thread); 395 396 void setThread(const sp<ThreadBase>& thread); 397 398 wp<ThreadBase> mThread; // parent mixer thread 399 mutable Mutex mLock; // mutex protecting effect list 400 Vector< sp<EffectModule> > mEffects; // list of effect modules 401 audio_session_t mSessionId; // audio session ID 402 sp<EffectBufferHalInterface> mInBuffer; // chain input buffer 403 sp<EffectBufferHalInterface> mOutBuffer; // chain output buffer 404 405 // 'volatile' here means these are accessed with atomic operations instead of mutex 406 volatile int32_t mActiveTrackCnt; // number of active tracks connected 407 volatile int32_t mTrackCnt; // number of tracks connected 408 409 int32_t mTailBufferCount; // current effect tail buffer count 410 int32_t mMaxTailBuffers; // maximum effect tail buffers 411 int mVolumeCtrlIdx; // index of insert effect having control over volume 412 uint32_t mLeftVolume; // previous volume on left channel 413 uint32_t mRightVolume; // previous volume on right channel 414 uint32_t mNewLeftVolume; // new volume on left channel 415 uint32_t mNewRightVolume; // new volume on right channel 416 uint32_t mStrategy; // strategy for this effect chain 417 // mSuspendedEffects lists all effects currently suspended in the chain. 418 // Use effect type UUID timelow field as key. There is no real risk of identical 419 // timeLow fields among effect type UUIDs. 420 // Updated by updateSuspendedSessions_l() only. 421 KeyedVector< int, sp<SuspendedEffectDesc> > mSuspendedEffects; 422}; 423