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