Loading services/audioflinger/AudioFlinger.cpp +18 −5 Original line number Diff line number Diff line Loading @@ -2396,6 +2396,18 @@ void AudioFlinger::releaseAudioSessionId(audio_session_t audioSession, pid_t pid ALOGW_IF(caller != getpid_cached, "session id %d not found for pid %d", audioSession, caller); } bool AudioFlinger::isSessionAcquired_l(audio_session_t audioSession) { size_t num = mAudioSessionRefs.size(); for (size_t i = 0; i < num; i++) { AudioSessionRef *ref = mAudioSessionRefs.itemAt(i); if (ref->mSessionid == audioSession) { return true; } } return false; } void AudioFlinger::purgeStaleEffects_l() { ALOGV("purging stale effects"); Loading Loading @@ -2789,8 +2801,9 @@ sp<IEffect> AudioFlinger::createEffect( sp<Client> client = registerPid(pid); // create effect on selected output thread bool pinned = (sessionId > AUDIO_SESSION_OUTPUT_MIX) && isSessionAcquired_l(sessionId); handle = thread->createEffect_l(client, effectClient, priority, sessionId, &desc, enabled, &lStatus); &desc, enabled, &lStatus, pinned); if (handle != 0 && id != NULL) { *id = handle->id(); } Loading Loading @@ -2987,7 +3000,7 @@ bool AudioFlinger::updateOrphanEffectChains(const sp<AudioFlinger::EffectModule> ALOGV("updateOrphanEffectChains session %d index %zd", session, index); if (index >= 0) { sp<EffectChain> chain = mOrphanEffectChains.valueAt(index); if (chain->removeEffect_l(effect) == 0) { if (chain->removeEffect_l(effect, true) == 0) { ALOGV("updateOrphanEffectChains removing effect chain at index %zd", index); mOrphanEffectChains.removeItemsAt(index); } Loading services/audioflinger/AudioFlinger.h +1 −0 Original line number Diff line number Diff line Loading @@ -586,6 +586,7 @@ private: void removeNotificationClient(pid_t pid); bool isNonOffloadableGlobalEffectEnabled_l(); void onNonOffloadableGlobalEffectEnable(); bool isSessionAcquired_l(audio_session_t audioSession); // Store an effect chain to mOrphanEffectChains keyed vector. // Called when a thread exits and effects are still attached to it. Loading services/audioflinger/Effects.cpp +140 −87 Original line number Diff line number Diff line Loading @@ -59,8 +59,9 @@ AudioFlinger::EffectModule::EffectModule(ThreadBase *thread, const wp<AudioFlinger::EffectChain>& chain, effect_descriptor_t *desc, int id, audio_session_t sessionId) : mPinned(sessionId > AUDIO_SESSION_OUTPUT_MIX), audio_session_t sessionId, bool pinned) : mPinned(pinned), mThread(thread), mChain(chain), mId(id), mSessionId(sessionId), mDescriptor(*desc), // mConfig is set by configure() and not used before then Loading @@ -71,7 +72,7 @@ AudioFlinger::EffectModule::EffectModule(ThreadBase *thread, mSuspended(false), mAudioFlinger(thread->mAudioFlinger) { ALOGV("Constructor %p", this); ALOGV("Constructor %p pinned %d", this, pinned); int lStatus; // create effect engine from effect factory Loading @@ -86,6 +87,8 @@ AudioFlinger::EffectModule::EffectModule(ThreadBase *thread, goto Error; } setOffloaded(thread->type() == ThreadBase::OFFLOAD, thread->id()); ALOGV("Constructor success name %s, Interface %p", mDescriptor.name, mEffectInterface); return; Error: Loading @@ -98,9 +101,8 @@ AudioFlinger::EffectModule::~EffectModule() { ALOGV("Destructor %p", this); if (mEffectInterface != NULL) { remove_effect_from_hal_l(); // release effect engine EffectRelease(mEffectInterface); ALOGW("EffectModule %p destructor called with unreleased interface", this); release_l(); } } Loading @@ -115,7 +117,7 @@ status_t AudioFlinger::EffectModule::addHandle(EffectHandle *handle) size_t i; for (i = 0; i < size; i++) { EffectHandle *h = mHandles[i]; if (h == NULL || h->destroyed_l()) { if (h == NULL || h->disconnected()) { continue; } // first non destroyed handle is considered in control Loading Loading @@ -143,9 +145,14 @@ status_t AudioFlinger::EffectModule::addHandle(EffectHandle *handle) return status; } size_t AudioFlinger::EffectModule::removeHandle(EffectHandle *handle) ssize_t AudioFlinger::EffectModule::removeHandle(EffectHandle *handle) { Mutex::Autolock _l(mLock); return removeHandle_l(handle); } ssize_t AudioFlinger::EffectModule::removeHandle_l(EffectHandle *handle) { size_t size = mHandles.size(); size_t i; for (i = 0; i < size; i++) { Loading @@ -154,9 +161,10 @@ size_t AudioFlinger::EffectModule::removeHandle(EffectHandle *handle) } } if (i == size) { return size; ALOGW("%s %p handle not found %p", __FUNCTION__, this, handle); return BAD_VALUE; } ALOGV("removeHandle() %p removed handle %p in position %zu", this, handle, i); ALOGV("removeHandle_l() %p removed handle %p in position %zu", this, handle, i); mHandles.removeAt(i); // if removed from first place, move effect control from this handle to next in line Loading @@ -183,7 +191,7 @@ AudioFlinger::EffectHandle *AudioFlinger::EffectModule::controlHandle_l() // the first valid handle in the list has control over the module for (size_t i = 0; i < mHandles.size(); i++) { EffectHandle *h = mHandles[i]; if (h != NULL && !h->destroyed_l()) { if (h != NULL && !h->disconnected()) { return h; } } Loading @@ -191,29 +199,22 @@ AudioFlinger::EffectHandle *AudioFlinger::EffectModule::controlHandle_l() return NULL; } size_t AudioFlinger::EffectModule::disconnect(EffectHandle *handle, bool unpinIfLast) // unsafe method called when the effect parent thread has been destroyed ssize_t AudioFlinger::EffectModule::disconnectHandle(EffectHandle *handle, bool unpinIfLast) { ALOGV("disconnect() %p handle %p", this, handle); // keep a strong reference on this EffectModule to avoid calling the // destructor before we exit sp<EffectModule> keep(this); { if (removeHandle(handle) == 0) { if (!isPinned() || unpinIfLast) { sp<ThreadBase> thread = mThread.promote(); if (thread != 0) { Mutex::Autolock _l(thread->mLock); thread->removeEffect_l(this); } Mutex::Autolock _l(mLock); ssize_t numHandles = removeHandle_l(handle); if ((numHandles == 0) && (!mPinned || unpinIfLast)) { AudioSystem::unregisterEffect(mId); sp<AudioFlinger> af = mAudioFlinger.promote(); if (af != 0) { mLock.unlock(); af->updateOrphanEffectChains(this); } AudioSystem::unregisterEffect(mId); } mLock.lock(); } } return mHandles.size(); return numHandles; } bool AudioFlinger::EffectModule::updateState() { Loading Loading @@ -557,6 +558,17 @@ status_t AudioFlinger::EffectModule::stop_l() return status; } // must be called with EffectChain::mLock held void AudioFlinger::EffectModule::release_l() { if (mEffectInterface != NULL) { remove_effect_from_hal_l(); // release effect engine EffectRelease(mEffectInterface); mEffectInterface = NULL; } } status_t AudioFlinger::EffectModule::remove_effect_from_hal_l() { if ((mDescriptor.flags & EFFECT_FLAG_TYPE_MASK) == EFFECT_FLAG_TYPE_PRE_PROC || Loading Loading @@ -649,7 +661,7 @@ status_t AudioFlinger::EffectModule::command(uint32_t cmdCode, uint32_t size = (replySize == NULL) ? 0 : *replySize; for (size_t i = 1; i < mHandles.size(); i++) { EffectHandle *h = mHandles[i]; if (h != NULL && !h->destroyed_l()) { if (h != NULL && !h->disconnected()) { h->commandExecuted(cmdCode, cmdSize, pCmdData, size, pReplyData); } } Loading Loading @@ -702,7 +714,7 @@ status_t AudioFlinger::EffectModule::setEnabled_l(bool enabled) } for (size_t i = 1; i < mHandles.size(); i++) { EffectHandle *h = mHandles[i]; if (h != NULL && !h->destroyed_l()) { if (h != NULL && !h->disconnected()) { h->setEnabled(enabled); } } Loading Loading @@ -866,8 +878,7 @@ bool AudioFlinger::EffectModule::purgeHandles() Mutex::Autolock _l(mLock); for (size_t i = 0; i < mHandles.size(); i++) { EffectHandle *handle = mHandles[i]; if (handle != NULL && !handle->destroyed_l()) { handle->effect().clear(); if (handle != NULL && !handle->disconnected()) { if (handle->hasControl()) { enabled = handle->enabled(); } Loading Loading @@ -1094,7 +1105,7 @@ void AudioFlinger::EffectModule::dump(int fd, const Vector<String16>& args __unu result.append("\t\t\t Pid Priority Ctrl Locked client server\n"); for (size_t i = 0; i < mHandles.size(); ++i) { EffectHandle *handle = mHandles[i]; if (handle != NULL && !handle->destroyed_l()) { if (handle != NULL && !handle->disconnected()) { handle->dumpToBuffer(buffer, SIZE); result.append(buffer); } Loading @@ -1120,7 +1131,7 @@ AudioFlinger::EffectHandle::EffectHandle(const sp<EffectModule>& effect, int32_t priority) : BnEffect(), mEffect(effect), mEffectClient(effectClient), mClient(client), mCblk(NULL), mPriority(priority), mHasControl(false), mEnabled(false), mDestroyed(false) mPriority(priority), mHasControl(false), mEnabled(false), mDisconnected(false) { ALOGV("constructor %p", this); Loading @@ -1143,14 +1154,6 @@ AudioFlinger::EffectHandle::EffectHandle(const sp<EffectModule>& effect, AudioFlinger::EffectHandle::~EffectHandle() { ALOGV("Destructor %p", this); if (mEffect == 0) { mDestroyed = true; return; } mEffect->lock(); mDestroyed = true; mEffect->unlock(); disconnect(false); } Loading @@ -1161,13 +1164,15 @@ status_t AudioFlinger::EffectHandle::initCheck() status_t AudioFlinger::EffectHandle::enable() { AutoMutex _l(mLock); ALOGV("enable %p", this); sp<EffectModule> effect = mEffect.promote(); if (effect == 0 || mDisconnected) { return DEAD_OBJECT; } if (!mHasControl) { return INVALID_OPERATION; } if (mEffect == 0) { return DEAD_OBJECT; } if (mEnabled) { return NO_ERROR; Loading @@ -1175,20 +1180,20 @@ status_t AudioFlinger::EffectHandle::enable() mEnabled = true; sp<ThreadBase> thread = mEffect->thread().promote(); sp<ThreadBase> thread = effect->thread().promote(); if (thread != 0) { thread->checkSuspendOnEffectEnabled(mEffect, true, mEffect->sessionId()); thread->checkSuspendOnEffectEnabled(effect, true, effect->sessionId()); } // checkSuspendOnEffectEnabled() can suspend this same effect when enabled if (mEffect->suspended()) { if (effect->suspended()) { return NO_ERROR; } status_t status = mEffect->setEnabled(true); status_t status = effect->setEnabled(true); if (status != NO_ERROR) { if (thread != 0) { thread->checkSuspendOnEffectEnabled(mEffect, false, mEffect->sessionId()); thread->checkSuspendOnEffectEnabled(effect, false, effect->sessionId()); } mEnabled = false; } else { Loading @@ -1198,12 +1203,12 @@ status_t AudioFlinger::EffectHandle::enable() Mutex::Autolock _l(t->mLock); t->broadcast_l(); } if (!mEffect->isOffloadable()) { if (!effect->isOffloadable()) { if (thread->type() == ThreadBase::OFFLOAD) { PlaybackThread *t = (PlaybackThread *)thread.get(); t->invalidateTracks(AUDIO_STREAM_MUSIC); } if (mEffect->sessionId() == AUDIO_SESSION_OUTPUT_MIX) { if (effect->sessionId() == AUDIO_SESSION_OUTPUT_MIX) { thread->mAudioFlinger->onNonOffloadableGlobalEffectEnable(); } } Loading @@ -1215,27 +1220,29 @@ status_t AudioFlinger::EffectHandle::enable() status_t AudioFlinger::EffectHandle::disable() { ALOGV("disable %p", this); AutoMutex _l(mLock); sp<EffectModule> effect = mEffect.promote(); if (effect == 0 || mDisconnected) { return DEAD_OBJECT; } if (!mHasControl) { return INVALID_OPERATION; } if (mEffect == 0) { return DEAD_OBJECT; } if (!mEnabled) { return NO_ERROR; } mEnabled = false; if (mEffect->suspended()) { if (effect->suspended()) { return NO_ERROR; } status_t status = mEffect->setEnabled(false); status_t status = effect->setEnabled(false); sp<ThreadBase> thread = mEffect->thread().promote(); sp<ThreadBase> thread = effect->thread().promote(); if (thread != 0) { thread->checkSuspendOnEffectEnabled(mEffect, false, mEffect->sessionId()); thread->checkSuspendOnEffectEnabled(effect, false, effect->sessionId()); if (thread->type() == ThreadBase::OFFLOAD) { PlaybackThread *t = (PlaybackThread *)thread.get(); Mutex::Autolock _l(t->mLock); Loading @@ -1248,25 +1255,39 @@ status_t AudioFlinger::EffectHandle::disable() void AudioFlinger::EffectHandle::disconnect() { ALOGV("%s %p", __FUNCTION__, this); disconnect(true); } void AudioFlinger::EffectHandle::disconnect(bool unpinIfLast) { ALOGV("disconnect(%s)", unpinIfLast ? "true" : "false"); if (mEffect == 0) { AutoMutex _l(mLock); ALOGV("disconnect(%s) %p", unpinIfLast ? "true" : "false", this); if (mDisconnected) { if (unpinIfLast) { android_errorWriteLog(0x534e4554, "32707507"); } return; } // restore suspended effects if the disconnected handle was enabled and the last one. if ((mEffect->disconnect(this, unpinIfLast) == 0) && mEnabled) { sp<ThreadBase> thread = mEffect->thread().promote(); mDisconnected = true; sp<ThreadBase> thread; { sp<EffectModule> effect = mEffect.promote(); if (effect != 0) { thread = effect->thread().promote(); } } if (thread != 0) { thread->checkSuspendOnEffectEnabled(mEffect, false, mEffect->sessionId()); thread->disconnectEffectHandle(this, unpinIfLast); } else { ALOGW("%s Effect handle %p disconnected after thread destruction", __FUNCTION__, this); // try to cleanup as much as we can sp<EffectModule> effect = mEffect.promote(); if (effect != 0) { effect->disconnectHandle(this, unpinIfLast); } } // release sp on module => module destructor can be called now mEffect.clear(); if (mClient != 0) { if (mCblk != NULL) { // unlike ~TrackBase(), mCblk is never a local new, so don't delete Loading @@ -1286,15 +1307,17 @@ status_t AudioFlinger::EffectHandle::command(uint32_t cmdCode, void *pReplyData) { ALOGVV("command(), cmdCode: %d, mHasControl: %d, mEffect: %p", cmdCode, mHasControl, (mEffect == 0) ? 0 : mEffect.get()); cmdCode, mHasControl, mEffect.unsafe_get()); AutoMutex _l(mLock); sp<EffectModule> effect = mEffect.promote(); if (effect == 0 || mDisconnected) { return DEAD_OBJECT; } // only get parameter command is permitted for applications not controlling the effect if (!mHasControl && cmdCode != EFFECT_CMD_GET_PARAM) { return INVALID_OPERATION; } if (mEffect == 0) { return DEAD_OBJECT; } if (mClient == 0) { return INVALID_OPERATION; } Loading Loading @@ -1339,7 +1362,7 @@ status_t AudioFlinger::EffectHandle::command(uint32_t cmdCode, int reply = 0; uint32_t rsize = sizeof(reply); status_t ret = mEffect->command(EFFECT_CMD_SET_PARAM, status_t ret = effect->command(EFFECT_CMD_SET_PARAM, size, param, &rsize, Loading Loading @@ -1376,7 +1399,7 @@ status_t AudioFlinger::EffectHandle::command(uint32_t cmdCode, return disable(); } return mEffect->command(cmdCode, cmdSize, pCmdData, replySize, pReplyData); return effect->command(cmdCode, cmdSize, pCmdData, replySize, pReplyData); } void AudioFlinger::EffectHandle::setControl(bool hasControl, bool signal, bool enabled) Loading Loading @@ -1458,7 +1481,6 @@ AudioFlinger::EffectChain::~EffectChain() if (mOwnInBuffer) { delete mInBuffer; } } // getEffectFromDesc_l() must be called with ThreadBase::mLock held Loading Loading @@ -1574,13 +1596,38 @@ void AudioFlinger::EffectChain::process_l() } } // addEffect_l() must be called with PlaybackThread::mLock held // createEffect_l() must be called with ThreadBase::mLock held status_t AudioFlinger::EffectChain::createEffect_l(sp<EffectModule>& effect, ThreadBase *thread, effect_descriptor_t *desc, int id, audio_session_t sessionId, bool pinned) { Mutex::Autolock _l(mLock); effect = new EffectModule(thread, this, desc, id, sessionId, pinned); status_t lStatus = effect->status(); if (lStatus == NO_ERROR) { lStatus = addEffect_ll(effect); } if (lStatus != NO_ERROR) { effect.clear(); } return lStatus; } // addEffect_l() must be called with ThreadBase::mLock held status_t AudioFlinger::EffectChain::addEffect_l(const sp<EffectModule>& effect) { Mutex::Autolock _l(mLock); return addEffect_ll(effect); } // addEffect_l() must be called with ThreadBase::mLock and EffectChain::mLock held status_t AudioFlinger::EffectChain::addEffect_ll(const sp<EffectModule>& effect) { effect_descriptor_t desc = effect->desc(); uint32_t insertPref = desc.flags & EFFECT_FLAG_INSERT_MASK; Mutex::Autolock _l(mLock); effect->setChain(this); sp<ThreadBase> thread = mThread.promote(); if (thread == 0) { Loading Loading @@ -1690,8 +1737,9 @@ status_t AudioFlinger::EffectChain::addEffect_l(const sp<EffectModule>& effect) return NO_ERROR; } // removeEffect_l() must be called with PlaybackThread::mLock held size_t AudioFlinger::EffectChain::removeEffect_l(const sp<EffectModule>& effect) // removeEffect_l() must be called with ThreadBase::mLock held size_t AudioFlinger::EffectChain::removeEffect_l(const sp<EffectModule>& effect, bool release) { Mutex::Autolock _l(mLock); size_t size = mEffects.size(); Loading @@ -1706,6 +1754,10 @@ size_t AudioFlinger::EffectChain::removeEffect_l(const sp<EffectModule>& effect) mEffects[i]->state() == EffectModule::STOPPING) { mEffects[i]->stop(); } if (release) { mEffects[i]->release_l(); } if (type == EFFECT_FLAG_TYPE_AUXILIARY) { delete[] effect->inBuffer(); } else { Loading @@ -1717,6 +1769,7 @@ size_t AudioFlinger::EffectChain::removeEffect_l(const sp<EffectModule>& effect) mEffects.removeAt(i); ALOGV("removeEffect_l() effect %p, removed from chain %p at rank %zu", effect.get(), this, i); break; } } Loading @@ -1724,7 +1777,7 @@ size_t AudioFlinger::EffectChain::removeEffect_l(const sp<EffectModule>& effect) return mEffects.size(); } // setDevice_l() must be called with PlaybackThread::mLock held // setDevice_l() must be called with ThreadBase::mLock held void AudioFlinger::EffectChain::setDevice_l(audio_devices_t device) { size_t size = mEffects.size(); Loading @@ -1733,7 +1786,7 @@ void AudioFlinger::EffectChain::setDevice_l(audio_devices_t device) } } // setMode_l() must be called with PlaybackThread::mLock held // setMode_l() must be called with ThreadBase::mLock held void AudioFlinger::EffectChain::setMode_l(audio_mode_t mode) { size_t size = mEffects.size(); Loading @@ -1742,7 +1795,7 @@ void AudioFlinger::EffectChain::setMode_l(audio_mode_t mode) } } // setAudioSource_l() must be called with PlaybackThread::mLock held // setAudioSource_l() must be called with ThreadBase::mLock held void AudioFlinger::EffectChain::setAudioSource_l(audio_source_t source) { size_t size = mEffects.size(); Loading @@ -1751,7 +1804,7 @@ void AudioFlinger::EffectChain::setAudioSource_l(audio_source_t source) } } // setVolume_l() must be called with PlaybackThread::mLock or EffectChain::mLock held // setVolume_l() must be called with ThreadBase::mLock or EffectChain::mLock held bool AudioFlinger::EffectChain::setVolume_l(uint32_t *left, uint32_t *right, bool force) { uint32_t newLeft = *left; Loading Loading @@ -1812,7 +1865,7 @@ bool AudioFlinger::EffectChain::setVolume_l(uint32_t *left, uint32_t *right, boo return hasControl; } // resetVolume_l() must be called with PlaybackThread::mLock or EffectChain::mLock held // resetVolume_l() must be called with ThreadBase::mLock or EffectChain::mLock held void AudioFlinger::EffectChain::resetVolume_l() { if ((mLeftVolume != UINT_MAX) && (mRightVolume != UINT_MAX)) { Loading Loading @@ -1913,7 +1966,7 @@ void AudioFlinger::EffectChain::setEffectSuspended_l( effect->setSuspended(false); effect->lock(); EffectHandle *handle = effect->controlHandle_l(); if (handle != NULL && !handle->destroyed_l()) { if (handle != NULL && !handle->disconnected()) { effect->setEnabled_l(handle->enabled()); } effect->unlock(); Loading services/audioflinger/Effects.h +26 −11 Original line number Diff line number Diff line Loading @@ -45,7 +45,8 @@ public: const wp<AudioFlinger::EffectChain>& chain, effect_descriptor_t *desc, int id, audio_session_t sessionId); audio_session_t sessionId, bool pinned); virtual ~EffectModule(); enum effect_state { Loading Loading @@ -93,8 +94,9 @@ public: const wp<ThreadBase>& thread() { return mThread; } status_t addHandle(EffectHandle *handle); size_t disconnect(EffectHandle *handle, bool unpinIfLast); size_t removeHandle(EffectHandle *handle); ssize_t disconnectHandle(EffectHandle *handle, bool unpinIfLast); ssize_t removeHandle(EffectHandle *handle); ssize_t removeHandle_l(EffectHandle *handle); const effect_descriptor_t& desc() const { return mDescriptor; } wp<EffectChain>& chain() { return mChain; } Loading Loading @@ -124,6 +126,7 @@ public: status_t setOffloaded(bool offloaded, audio_io_handle_t io); bool isOffloaded() const; void addEffectToHal_l(); void release_l(); void dump(int fd, const Vector<String16>& args); Loading Loading @@ -208,12 +211,17 @@ public: bool enabled() const { return mEnabled; } // Getters int id() const { return mEffect->id(); } wp<EffectModule> effect() const { return mEffect; } int id() const { sp<EffectModule> effect = mEffect.promote(); if (effect == 0) { return 0; } return effect->id(); } int priority() const { return mPriority; } bool hasControl() const { return mHasControl; } sp<EffectModule> effect() const { return mEffect; } // destroyed_l() must be called with the associated EffectModule mLock held bool destroyed_l() const { return mDestroyed; } bool disconnected() const { return mDisconnected; } void dumpToBuffer(char* buffer, size_t size); Loading @@ -222,7 +230,8 @@ protected: EffectHandle(const EffectHandle&); EffectHandle& operator =(const EffectHandle&); sp<EffectModule> mEffect; // pointer to controlled EffectModule Mutex mLock; // protects IEffect method calls wp<EffectModule> mEffect; // pointer to controlled EffectModule sp<IEffectClient> mEffectClient; // callback interface for client notifications /*const*/ sp<Client> mClient; // client for shared memory allocation, see disconnect() sp<IMemory> mCblkMemory; // shared memory for control block Loading @@ -233,8 +242,7 @@ protected: bool mHasControl; // true if this handle is controlling the effect bool mEnabled; // cached enable state: needed when the effect is // restored after being suspended bool mDestroyed; // Set to true by destructor. Access with EffectModule // mLock held bool mDisconnected; // Set to true by disconnect() }; // the EffectChain class represents a group of effects associated to one audio session. Loading Loading @@ -269,8 +277,15 @@ public: mLock.unlock(); } status_t createEffect_l(sp<EffectModule>& effect, ThreadBase *thread, effect_descriptor_t *desc, int id, audio_session_t sessionId, bool pinned); status_t addEffect_l(const sp<EffectModule>& handle); size_t removeEffect_l(const sp<EffectModule>& handle); status_t addEffect_ll(const sp<EffectModule>& handle); size_t removeEffect_l(const sp<EffectModule>& handle, bool release = false); audio_session_t sessionId() const { return mSessionId; } void setSessionId(audio_session_t sessionId) { mSessionId = sessionId; } Loading services/audioflinger/Threads.cpp +33 −12 File changed.Preview size limit exceeded, changes collapsed. Show changes Loading
services/audioflinger/AudioFlinger.cpp +18 −5 Original line number Diff line number Diff line Loading @@ -2396,6 +2396,18 @@ void AudioFlinger::releaseAudioSessionId(audio_session_t audioSession, pid_t pid ALOGW_IF(caller != getpid_cached, "session id %d not found for pid %d", audioSession, caller); } bool AudioFlinger::isSessionAcquired_l(audio_session_t audioSession) { size_t num = mAudioSessionRefs.size(); for (size_t i = 0; i < num; i++) { AudioSessionRef *ref = mAudioSessionRefs.itemAt(i); if (ref->mSessionid == audioSession) { return true; } } return false; } void AudioFlinger::purgeStaleEffects_l() { ALOGV("purging stale effects"); Loading Loading @@ -2789,8 +2801,9 @@ sp<IEffect> AudioFlinger::createEffect( sp<Client> client = registerPid(pid); // create effect on selected output thread bool pinned = (sessionId > AUDIO_SESSION_OUTPUT_MIX) && isSessionAcquired_l(sessionId); handle = thread->createEffect_l(client, effectClient, priority, sessionId, &desc, enabled, &lStatus); &desc, enabled, &lStatus, pinned); if (handle != 0 && id != NULL) { *id = handle->id(); } Loading Loading @@ -2987,7 +3000,7 @@ bool AudioFlinger::updateOrphanEffectChains(const sp<AudioFlinger::EffectModule> ALOGV("updateOrphanEffectChains session %d index %zd", session, index); if (index >= 0) { sp<EffectChain> chain = mOrphanEffectChains.valueAt(index); if (chain->removeEffect_l(effect) == 0) { if (chain->removeEffect_l(effect, true) == 0) { ALOGV("updateOrphanEffectChains removing effect chain at index %zd", index); mOrphanEffectChains.removeItemsAt(index); } Loading
services/audioflinger/AudioFlinger.h +1 −0 Original line number Diff line number Diff line Loading @@ -586,6 +586,7 @@ private: void removeNotificationClient(pid_t pid); bool isNonOffloadableGlobalEffectEnabled_l(); void onNonOffloadableGlobalEffectEnable(); bool isSessionAcquired_l(audio_session_t audioSession); // Store an effect chain to mOrphanEffectChains keyed vector. // Called when a thread exits and effects are still attached to it. Loading
services/audioflinger/Effects.cpp +140 −87 Original line number Diff line number Diff line Loading @@ -59,8 +59,9 @@ AudioFlinger::EffectModule::EffectModule(ThreadBase *thread, const wp<AudioFlinger::EffectChain>& chain, effect_descriptor_t *desc, int id, audio_session_t sessionId) : mPinned(sessionId > AUDIO_SESSION_OUTPUT_MIX), audio_session_t sessionId, bool pinned) : mPinned(pinned), mThread(thread), mChain(chain), mId(id), mSessionId(sessionId), mDescriptor(*desc), // mConfig is set by configure() and not used before then Loading @@ -71,7 +72,7 @@ AudioFlinger::EffectModule::EffectModule(ThreadBase *thread, mSuspended(false), mAudioFlinger(thread->mAudioFlinger) { ALOGV("Constructor %p", this); ALOGV("Constructor %p pinned %d", this, pinned); int lStatus; // create effect engine from effect factory Loading @@ -86,6 +87,8 @@ AudioFlinger::EffectModule::EffectModule(ThreadBase *thread, goto Error; } setOffloaded(thread->type() == ThreadBase::OFFLOAD, thread->id()); ALOGV("Constructor success name %s, Interface %p", mDescriptor.name, mEffectInterface); return; Error: Loading @@ -98,9 +101,8 @@ AudioFlinger::EffectModule::~EffectModule() { ALOGV("Destructor %p", this); if (mEffectInterface != NULL) { remove_effect_from_hal_l(); // release effect engine EffectRelease(mEffectInterface); ALOGW("EffectModule %p destructor called with unreleased interface", this); release_l(); } } Loading @@ -115,7 +117,7 @@ status_t AudioFlinger::EffectModule::addHandle(EffectHandle *handle) size_t i; for (i = 0; i < size; i++) { EffectHandle *h = mHandles[i]; if (h == NULL || h->destroyed_l()) { if (h == NULL || h->disconnected()) { continue; } // first non destroyed handle is considered in control Loading Loading @@ -143,9 +145,14 @@ status_t AudioFlinger::EffectModule::addHandle(EffectHandle *handle) return status; } size_t AudioFlinger::EffectModule::removeHandle(EffectHandle *handle) ssize_t AudioFlinger::EffectModule::removeHandle(EffectHandle *handle) { Mutex::Autolock _l(mLock); return removeHandle_l(handle); } ssize_t AudioFlinger::EffectModule::removeHandle_l(EffectHandle *handle) { size_t size = mHandles.size(); size_t i; for (i = 0; i < size; i++) { Loading @@ -154,9 +161,10 @@ size_t AudioFlinger::EffectModule::removeHandle(EffectHandle *handle) } } if (i == size) { return size; ALOGW("%s %p handle not found %p", __FUNCTION__, this, handle); return BAD_VALUE; } ALOGV("removeHandle() %p removed handle %p in position %zu", this, handle, i); ALOGV("removeHandle_l() %p removed handle %p in position %zu", this, handle, i); mHandles.removeAt(i); // if removed from first place, move effect control from this handle to next in line Loading @@ -183,7 +191,7 @@ AudioFlinger::EffectHandle *AudioFlinger::EffectModule::controlHandle_l() // the first valid handle in the list has control over the module for (size_t i = 0; i < mHandles.size(); i++) { EffectHandle *h = mHandles[i]; if (h != NULL && !h->destroyed_l()) { if (h != NULL && !h->disconnected()) { return h; } } Loading @@ -191,29 +199,22 @@ AudioFlinger::EffectHandle *AudioFlinger::EffectModule::controlHandle_l() return NULL; } size_t AudioFlinger::EffectModule::disconnect(EffectHandle *handle, bool unpinIfLast) // unsafe method called when the effect parent thread has been destroyed ssize_t AudioFlinger::EffectModule::disconnectHandle(EffectHandle *handle, bool unpinIfLast) { ALOGV("disconnect() %p handle %p", this, handle); // keep a strong reference on this EffectModule to avoid calling the // destructor before we exit sp<EffectModule> keep(this); { if (removeHandle(handle) == 0) { if (!isPinned() || unpinIfLast) { sp<ThreadBase> thread = mThread.promote(); if (thread != 0) { Mutex::Autolock _l(thread->mLock); thread->removeEffect_l(this); } Mutex::Autolock _l(mLock); ssize_t numHandles = removeHandle_l(handle); if ((numHandles == 0) && (!mPinned || unpinIfLast)) { AudioSystem::unregisterEffect(mId); sp<AudioFlinger> af = mAudioFlinger.promote(); if (af != 0) { mLock.unlock(); af->updateOrphanEffectChains(this); } AudioSystem::unregisterEffect(mId); } mLock.lock(); } } return mHandles.size(); return numHandles; } bool AudioFlinger::EffectModule::updateState() { Loading Loading @@ -557,6 +558,17 @@ status_t AudioFlinger::EffectModule::stop_l() return status; } // must be called with EffectChain::mLock held void AudioFlinger::EffectModule::release_l() { if (mEffectInterface != NULL) { remove_effect_from_hal_l(); // release effect engine EffectRelease(mEffectInterface); mEffectInterface = NULL; } } status_t AudioFlinger::EffectModule::remove_effect_from_hal_l() { if ((mDescriptor.flags & EFFECT_FLAG_TYPE_MASK) == EFFECT_FLAG_TYPE_PRE_PROC || Loading Loading @@ -649,7 +661,7 @@ status_t AudioFlinger::EffectModule::command(uint32_t cmdCode, uint32_t size = (replySize == NULL) ? 0 : *replySize; for (size_t i = 1; i < mHandles.size(); i++) { EffectHandle *h = mHandles[i]; if (h != NULL && !h->destroyed_l()) { if (h != NULL && !h->disconnected()) { h->commandExecuted(cmdCode, cmdSize, pCmdData, size, pReplyData); } } Loading Loading @@ -702,7 +714,7 @@ status_t AudioFlinger::EffectModule::setEnabled_l(bool enabled) } for (size_t i = 1; i < mHandles.size(); i++) { EffectHandle *h = mHandles[i]; if (h != NULL && !h->destroyed_l()) { if (h != NULL && !h->disconnected()) { h->setEnabled(enabled); } } Loading Loading @@ -866,8 +878,7 @@ bool AudioFlinger::EffectModule::purgeHandles() Mutex::Autolock _l(mLock); for (size_t i = 0; i < mHandles.size(); i++) { EffectHandle *handle = mHandles[i]; if (handle != NULL && !handle->destroyed_l()) { handle->effect().clear(); if (handle != NULL && !handle->disconnected()) { if (handle->hasControl()) { enabled = handle->enabled(); } Loading Loading @@ -1094,7 +1105,7 @@ void AudioFlinger::EffectModule::dump(int fd, const Vector<String16>& args __unu result.append("\t\t\t Pid Priority Ctrl Locked client server\n"); for (size_t i = 0; i < mHandles.size(); ++i) { EffectHandle *handle = mHandles[i]; if (handle != NULL && !handle->destroyed_l()) { if (handle != NULL && !handle->disconnected()) { handle->dumpToBuffer(buffer, SIZE); result.append(buffer); } Loading @@ -1120,7 +1131,7 @@ AudioFlinger::EffectHandle::EffectHandle(const sp<EffectModule>& effect, int32_t priority) : BnEffect(), mEffect(effect), mEffectClient(effectClient), mClient(client), mCblk(NULL), mPriority(priority), mHasControl(false), mEnabled(false), mDestroyed(false) mPriority(priority), mHasControl(false), mEnabled(false), mDisconnected(false) { ALOGV("constructor %p", this); Loading @@ -1143,14 +1154,6 @@ AudioFlinger::EffectHandle::EffectHandle(const sp<EffectModule>& effect, AudioFlinger::EffectHandle::~EffectHandle() { ALOGV("Destructor %p", this); if (mEffect == 0) { mDestroyed = true; return; } mEffect->lock(); mDestroyed = true; mEffect->unlock(); disconnect(false); } Loading @@ -1161,13 +1164,15 @@ status_t AudioFlinger::EffectHandle::initCheck() status_t AudioFlinger::EffectHandle::enable() { AutoMutex _l(mLock); ALOGV("enable %p", this); sp<EffectModule> effect = mEffect.promote(); if (effect == 0 || mDisconnected) { return DEAD_OBJECT; } if (!mHasControl) { return INVALID_OPERATION; } if (mEffect == 0) { return DEAD_OBJECT; } if (mEnabled) { return NO_ERROR; Loading @@ -1175,20 +1180,20 @@ status_t AudioFlinger::EffectHandle::enable() mEnabled = true; sp<ThreadBase> thread = mEffect->thread().promote(); sp<ThreadBase> thread = effect->thread().promote(); if (thread != 0) { thread->checkSuspendOnEffectEnabled(mEffect, true, mEffect->sessionId()); thread->checkSuspendOnEffectEnabled(effect, true, effect->sessionId()); } // checkSuspendOnEffectEnabled() can suspend this same effect when enabled if (mEffect->suspended()) { if (effect->suspended()) { return NO_ERROR; } status_t status = mEffect->setEnabled(true); status_t status = effect->setEnabled(true); if (status != NO_ERROR) { if (thread != 0) { thread->checkSuspendOnEffectEnabled(mEffect, false, mEffect->sessionId()); thread->checkSuspendOnEffectEnabled(effect, false, effect->sessionId()); } mEnabled = false; } else { Loading @@ -1198,12 +1203,12 @@ status_t AudioFlinger::EffectHandle::enable() Mutex::Autolock _l(t->mLock); t->broadcast_l(); } if (!mEffect->isOffloadable()) { if (!effect->isOffloadable()) { if (thread->type() == ThreadBase::OFFLOAD) { PlaybackThread *t = (PlaybackThread *)thread.get(); t->invalidateTracks(AUDIO_STREAM_MUSIC); } if (mEffect->sessionId() == AUDIO_SESSION_OUTPUT_MIX) { if (effect->sessionId() == AUDIO_SESSION_OUTPUT_MIX) { thread->mAudioFlinger->onNonOffloadableGlobalEffectEnable(); } } Loading @@ -1215,27 +1220,29 @@ status_t AudioFlinger::EffectHandle::enable() status_t AudioFlinger::EffectHandle::disable() { ALOGV("disable %p", this); AutoMutex _l(mLock); sp<EffectModule> effect = mEffect.promote(); if (effect == 0 || mDisconnected) { return DEAD_OBJECT; } if (!mHasControl) { return INVALID_OPERATION; } if (mEffect == 0) { return DEAD_OBJECT; } if (!mEnabled) { return NO_ERROR; } mEnabled = false; if (mEffect->suspended()) { if (effect->suspended()) { return NO_ERROR; } status_t status = mEffect->setEnabled(false); status_t status = effect->setEnabled(false); sp<ThreadBase> thread = mEffect->thread().promote(); sp<ThreadBase> thread = effect->thread().promote(); if (thread != 0) { thread->checkSuspendOnEffectEnabled(mEffect, false, mEffect->sessionId()); thread->checkSuspendOnEffectEnabled(effect, false, effect->sessionId()); if (thread->type() == ThreadBase::OFFLOAD) { PlaybackThread *t = (PlaybackThread *)thread.get(); Mutex::Autolock _l(t->mLock); Loading @@ -1248,25 +1255,39 @@ status_t AudioFlinger::EffectHandle::disable() void AudioFlinger::EffectHandle::disconnect() { ALOGV("%s %p", __FUNCTION__, this); disconnect(true); } void AudioFlinger::EffectHandle::disconnect(bool unpinIfLast) { ALOGV("disconnect(%s)", unpinIfLast ? "true" : "false"); if (mEffect == 0) { AutoMutex _l(mLock); ALOGV("disconnect(%s) %p", unpinIfLast ? "true" : "false", this); if (mDisconnected) { if (unpinIfLast) { android_errorWriteLog(0x534e4554, "32707507"); } return; } // restore suspended effects if the disconnected handle was enabled and the last one. if ((mEffect->disconnect(this, unpinIfLast) == 0) && mEnabled) { sp<ThreadBase> thread = mEffect->thread().promote(); mDisconnected = true; sp<ThreadBase> thread; { sp<EffectModule> effect = mEffect.promote(); if (effect != 0) { thread = effect->thread().promote(); } } if (thread != 0) { thread->checkSuspendOnEffectEnabled(mEffect, false, mEffect->sessionId()); thread->disconnectEffectHandle(this, unpinIfLast); } else { ALOGW("%s Effect handle %p disconnected after thread destruction", __FUNCTION__, this); // try to cleanup as much as we can sp<EffectModule> effect = mEffect.promote(); if (effect != 0) { effect->disconnectHandle(this, unpinIfLast); } } // release sp on module => module destructor can be called now mEffect.clear(); if (mClient != 0) { if (mCblk != NULL) { // unlike ~TrackBase(), mCblk is never a local new, so don't delete Loading @@ -1286,15 +1307,17 @@ status_t AudioFlinger::EffectHandle::command(uint32_t cmdCode, void *pReplyData) { ALOGVV("command(), cmdCode: %d, mHasControl: %d, mEffect: %p", cmdCode, mHasControl, (mEffect == 0) ? 0 : mEffect.get()); cmdCode, mHasControl, mEffect.unsafe_get()); AutoMutex _l(mLock); sp<EffectModule> effect = mEffect.promote(); if (effect == 0 || mDisconnected) { return DEAD_OBJECT; } // only get parameter command is permitted for applications not controlling the effect if (!mHasControl && cmdCode != EFFECT_CMD_GET_PARAM) { return INVALID_OPERATION; } if (mEffect == 0) { return DEAD_OBJECT; } if (mClient == 0) { return INVALID_OPERATION; } Loading Loading @@ -1339,7 +1362,7 @@ status_t AudioFlinger::EffectHandle::command(uint32_t cmdCode, int reply = 0; uint32_t rsize = sizeof(reply); status_t ret = mEffect->command(EFFECT_CMD_SET_PARAM, status_t ret = effect->command(EFFECT_CMD_SET_PARAM, size, param, &rsize, Loading Loading @@ -1376,7 +1399,7 @@ status_t AudioFlinger::EffectHandle::command(uint32_t cmdCode, return disable(); } return mEffect->command(cmdCode, cmdSize, pCmdData, replySize, pReplyData); return effect->command(cmdCode, cmdSize, pCmdData, replySize, pReplyData); } void AudioFlinger::EffectHandle::setControl(bool hasControl, bool signal, bool enabled) Loading Loading @@ -1458,7 +1481,6 @@ AudioFlinger::EffectChain::~EffectChain() if (mOwnInBuffer) { delete mInBuffer; } } // getEffectFromDesc_l() must be called with ThreadBase::mLock held Loading Loading @@ -1574,13 +1596,38 @@ void AudioFlinger::EffectChain::process_l() } } // addEffect_l() must be called with PlaybackThread::mLock held // createEffect_l() must be called with ThreadBase::mLock held status_t AudioFlinger::EffectChain::createEffect_l(sp<EffectModule>& effect, ThreadBase *thread, effect_descriptor_t *desc, int id, audio_session_t sessionId, bool pinned) { Mutex::Autolock _l(mLock); effect = new EffectModule(thread, this, desc, id, sessionId, pinned); status_t lStatus = effect->status(); if (lStatus == NO_ERROR) { lStatus = addEffect_ll(effect); } if (lStatus != NO_ERROR) { effect.clear(); } return lStatus; } // addEffect_l() must be called with ThreadBase::mLock held status_t AudioFlinger::EffectChain::addEffect_l(const sp<EffectModule>& effect) { Mutex::Autolock _l(mLock); return addEffect_ll(effect); } // addEffect_l() must be called with ThreadBase::mLock and EffectChain::mLock held status_t AudioFlinger::EffectChain::addEffect_ll(const sp<EffectModule>& effect) { effect_descriptor_t desc = effect->desc(); uint32_t insertPref = desc.flags & EFFECT_FLAG_INSERT_MASK; Mutex::Autolock _l(mLock); effect->setChain(this); sp<ThreadBase> thread = mThread.promote(); if (thread == 0) { Loading Loading @@ -1690,8 +1737,9 @@ status_t AudioFlinger::EffectChain::addEffect_l(const sp<EffectModule>& effect) return NO_ERROR; } // removeEffect_l() must be called with PlaybackThread::mLock held size_t AudioFlinger::EffectChain::removeEffect_l(const sp<EffectModule>& effect) // removeEffect_l() must be called with ThreadBase::mLock held size_t AudioFlinger::EffectChain::removeEffect_l(const sp<EffectModule>& effect, bool release) { Mutex::Autolock _l(mLock); size_t size = mEffects.size(); Loading @@ -1706,6 +1754,10 @@ size_t AudioFlinger::EffectChain::removeEffect_l(const sp<EffectModule>& effect) mEffects[i]->state() == EffectModule::STOPPING) { mEffects[i]->stop(); } if (release) { mEffects[i]->release_l(); } if (type == EFFECT_FLAG_TYPE_AUXILIARY) { delete[] effect->inBuffer(); } else { Loading @@ -1717,6 +1769,7 @@ size_t AudioFlinger::EffectChain::removeEffect_l(const sp<EffectModule>& effect) mEffects.removeAt(i); ALOGV("removeEffect_l() effect %p, removed from chain %p at rank %zu", effect.get(), this, i); break; } } Loading @@ -1724,7 +1777,7 @@ size_t AudioFlinger::EffectChain::removeEffect_l(const sp<EffectModule>& effect) return mEffects.size(); } // setDevice_l() must be called with PlaybackThread::mLock held // setDevice_l() must be called with ThreadBase::mLock held void AudioFlinger::EffectChain::setDevice_l(audio_devices_t device) { size_t size = mEffects.size(); Loading @@ -1733,7 +1786,7 @@ void AudioFlinger::EffectChain::setDevice_l(audio_devices_t device) } } // setMode_l() must be called with PlaybackThread::mLock held // setMode_l() must be called with ThreadBase::mLock held void AudioFlinger::EffectChain::setMode_l(audio_mode_t mode) { size_t size = mEffects.size(); Loading @@ -1742,7 +1795,7 @@ void AudioFlinger::EffectChain::setMode_l(audio_mode_t mode) } } // setAudioSource_l() must be called with PlaybackThread::mLock held // setAudioSource_l() must be called with ThreadBase::mLock held void AudioFlinger::EffectChain::setAudioSource_l(audio_source_t source) { size_t size = mEffects.size(); Loading @@ -1751,7 +1804,7 @@ void AudioFlinger::EffectChain::setAudioSource_l(audio_source_t source) } } // setVolume_l() must be called with PlaybackThread::mLock or EffectChain::mLock held // setVolume_l() must be called with ThreadBase::mLock or EffectChain::mLock held bool AudioFlinger::EffectChain::setVolume_l(uint32_t *left, uint32_t *right, bool force) { uint32_t newLeft = *left; Loading Loading @@ -1812,7 +1865,7 @@ bool AudioFlinger::EffectChain::setVolume_l(uint32_t *left, uint32_t *right, boo return hasControl; } // resetVolume_l() must be called with PlaybackThread::mLock or EffectChain::mLock held // resetVolume_l() must be called with ThreadBase::mLock or EffectChain::mLock held void AudioFlinger::EffectChain::resetVolume_l() { if ((mLeftVolume != UINT_MAX) && (mRightVolume != UINT_MAX)) { Loading Loading @@ -1913,7 +1966,7 @@ void AudioFlinger::EffectChain::setEffectSuspended_l( effect->setSuspended(false); effect->lock(); EffectHandle *handle = effect->controlHandle_l(); if (handle != NULL && !handle->destroyed_l()) { if (handle != NULL && !handle->disconnected()) { effect->setEnabled_l(handle->enabled()); } effect->unlock(); Loading
services/audioflinger/Effects.h +26 −11 Original line number Diff line number Diff line Loading @@ -45,7 +45,8 @@ public: const wp<AudioFlinger::EffectChain>& chain, effect_descriptor_t *desc, int id, audio_session_t sessionId); audio_session_t sessionId, bool pinned); virtual ~EffectModule(); enum effect_state { Loading Loading @@ -93,8 +94,9 @@ public: const wp<ThreadBase>& thread() { return mThread; } status_t addHandle(EffectHandle *handle); size_t disconnect(EffectHandle *handle, bool unpinIfLast); size_t removeHandle(EffectHandle *handle); ssize_t disconnectHandle(EffectHandle *handle, bool unpinIfLast); ssize_t removeHandle(EffectHandle *handle); ssize_t removeHandle_l(EffectHandle *handle); const effect_descriptor_t& desc() const { return mDescriptor; } wp<EffectChain>& chain() { return mChain; } Loading Loading @@ -124,6 +126,7 @@ public: status_t setOffloaded(bool offloaded, audio_io_handle_t io); bool isOffloaded() const; void addEffectToHal_l(); void release_l(); void dump(int fd, const Vector<String16>& args); Loading Loading @@ -208,12 +211,17 @@ public: bool enabled() const { return mEnabled; } // Getters int id() const { return mEffect->id(); } wp<EffectModule> effect() const { return mEffect; } int id() const { sp<EffectModule> effect = mEffect.promote(); if (effect == 0) { return 0; } return effect->id(); } int priority() const { return mPriority; } bool hasControl() const { return mHasControl; } sp<EffectModule> effect() const { return mEffect; } // destroyed_l() must be called with the associated EffectModule mLock held bool destroyed_l() const { return mDestroyed; } bool disconnected() const { return mDisconnected; } void dumpToBuffer(char* buffer, size_t size); Loading @@ -222,7 +230,8 @@ protected: EffectHandle(const EffectHandle&); EffectHandle& operator =(const EffectHandle&); sp<EffectModule> mEffect; // pointer to controlled EffectModule Mutex mLock; // protects IEffect method calls wp<EffectModule> mEffect; // pointer to controlled EffectModule sp<IEffectClient> mEffectClient; // callback interface for client notifications /*const*/ sp<Client> mClient; // client for shared memory allocation, see disconnect() sp<IMemory> mCblkMemory; // shared memory for control block Loading @@ -233,8 +242,7 @@ protected: bool mHasControl; // true if this handle is controlling the effect bool mEnabled; // cached enable state: needed when the effect is // restored after being suspended bool mDestroyed; // Set to true by destructor. Access with EffectModule // mLock held bool mDisconnected; // Set to true by disconnect() }; // the EffectChain class represents a group of effects associated to one audio session. Loading Loading @@ -269,8 +277,15 @@ public: mLock.unlock(); } status_t createEffect_l(sp<EffectModule>& effect, ThreadBase *thread, effect_descriptor_t *desc, int id, audio_session_t sessionId, bool pinned); status_t addEffect_l(const sp<EffectModule>& handle); size_t removeEffect_l(const sp<EffectModule>& handle); status_t addEffect_ll(const sp<EffectModule>& handle); size_t removeEffect_l(const sp<EffectModule>& handle, bool release = false); audio_session_t sessionId() const { return mSessionId; } void setSessionId(audio_session_t sessionId) { mSessionId = sessionId; } Loading
services/audioflinger/Threads.cpp +33 −12 File changed.Preview size limit exceeded, changes collapsed. Show changes