Loading services/audioflinger/AudioFlinger.cpp +18 −5 Original line number Diff line number Diff line Loading @@ -2355,6 +2355,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 @@ -2768,8 +2780,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 @@ -2966,7 +2979,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 @@ -589,6 +589,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 +121 −93 Original line number Diff line number Diff line Loading @@ -60,8 +60,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 @@ -94,7 +95,9 @@ AudioFlinger::EffectModule::EffectModule(ThreadBase *thread, goto Error; } setOffloaded(thread->type() == ThreadBase::OFFLOAD, thread->id()); ALOGV("Constructor success name %s, Interface %p", mDescriptor.name, mEffectInterface.get()); return; Error: mEffectInterface.clear(); Loading @@ -105,10 +108,10 @@ AudioFlinger::EffectModule::~EffectModule() { ALOGV("Destructor %p", this); if (mEffectInterface != 0) { remove_effect_from_hal_l(); // release effect engine mEffectInterface.clear(); ALOGW("EffectModule %p destructor called with unreleased interface", this); release_l(); } } status_t AudioFlinger::EffectModule::addHandle(EffectHandle *handle) Loading @@ -122,7 +125,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 @@ -150,9 +153,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 @@ -161,9 +169,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 @@ -190,7 +199,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 @@ -198,31 +207,6 @@ AudioFlinger::EffectHandle *AudioFlinger::EffectModule::controlHandle_l() return NULL; } size_t AudioFlinger::EffectModule::disconnect(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); } sp<AudioFlinger> af = mAudioFlinger.promote(); if (af != 0) { af->updateOrphanEffectChains(this); } AudioSystem::unregisterEffect(mId); } } } return mHandles.size(); } bool AudioFlinger::EffectModule::updateState() { Mutex::Autolock _l(mLock); Loading Loading @@ -560,6 +544,16 @@ status_t AudioFlinger::EffectModule::stop_l() return status; } // must be called with EffectChain::mLock held void AudioFlinger::EffectModule::release_l() { if (mEffectInterface != 0) { remove_effect_from_hal_l(); // release effect engine mEffectInterface.clear(); } } status_t AudioFlinger::EffectModule::remove_effect_from_hal_l() { if ((mDescriptor.flags & EFFECT_FLAG_TYPE_MASK) == EFFECT_FLAG_TYPE_PRE_PROC || Loading Loading @@ -653,7 +647,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 @@ -706,7 +700,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 +860,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 @@ -1093,7 +1086,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 @@ -1119,7 +1112,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 @@ -1142,14 +1135,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 @@ -1160,13 +1145,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 @@ -1174,20 +1161,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 @@ -1197,12 +1184,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 @@ -1214,27 +1201,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 @@ -1247,25 +1236,32 @@ 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(); if (thread != 0) { thread->checkSuspendOnEffectEnabled(mEffect, false, mEffect->sessionId()); mDisconnected = true; sp<ThreadBase> thread; { sp<EffectModule> effect = mEffect.promote(); if (effect != 0) { thread = effect->thread().promote(); } } if (thread != 0) { thread->disconnectEffectHandle(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 @@ -1285,15 +1281,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 @@ -1338,7 +1336,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 @@ -1375,7 +1373,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 @@ -1457,7 +1455,6 @@ AudioFlinger::EffectChain::~EffectChain() if (mOwnInBuffer) { delete mInBuffer; } } // getEffectFromDesc_l() must be called with ThreadBase::mLock held Loading Loading @@ -1573,13 +1570,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 @@ -1689,8 +1711,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 @@ -1705,6 +1728,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 @@ -1716,6 +1743,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 @@ -1723,7 +1751,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 @@ -1732,7 +1760,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 @@ -1741,7 +1769,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 @@ -1750,7 +1778,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 @@ -1811,7 +1839,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 @@ -1912,7 +1940,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 +25 −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,8 @@ 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 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 +125,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 +210,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 +229,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 +241,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 +276,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 Original line number Diff line number Diff line Loading @@ -1267,7 +1267,8 @@ sp<AudioFlinger::EffectHandle> AudioFlinger::ThreadBase::createEffect_l( audio_session_t sessionId, effect_descriptor_t *desc, int *enabled, status_t *status) status_t *status, bool pinned) { sp<EffectModule> effect; sp<EffectHandle> handle; Loading Loading @@ -1317,14 +1318,7 @@ sp<AudioFlinger::EffectHandle> AudioFlinger::ThreadBase::createEffect_l( } effectRegistered = true; // create a new effect module if none present in the chain effect = new EffectModule(this, chain, desc, id, sessionId); lStatus = effect->status(); if (lStatus != NO_ERROR) { goto Exit; } effect->setOffloaded(mType == OFFLOAD, mId); lStatus = chain->addEffect_l(effect); lStatus = chain->createEffect_l(effect, this, desc, id, sessionId, pinned); if (lStatus != NO_ERROR) { goto Exit; } Loading Loading @@ -1365,6 +1359,33 @@ Exit: return handle; } void AudioFlinger::ThreadBase::disconnectEffectHandle(EffectHandle *handle, bool unpinIfLast) { bool remove = false; sp<EffectModule> effect; { Mutex::Autolock _l(mLock); effect = handle->effect().promote(); if (effect == 0) { return; } // restore suspended effects if the disconnected handle was enabled and the last one. remove = (effect->removeHandle(handle) == 0) && (!effect->isPinned() || unpinIfLast); if (remove) { removeEffect_l(effect, true); } } if (remove) { mAudioFlinger->updateOrphanEffectChains(effect); AudioSystem::unregisterEffect(effect->id()); if (handle->enabled()) { checkSuspendOnEffectEnabled(effect, false, effect->sessionId()); } } } sp<AudioFlinger::EffectModule> AudioFlinger::ThreadBase::getEffect(audio_session_t sessionId, int effectId) { Loading Loading @@ -1425,9 +1446,9 @@ status_t AudioFlinger::ThreadBase::addEffect_l(const sp<EffectModule>& effect) return NO_ERROR; } void AudioFlinger::ThreadBase::removeEffect_l(const sp<EffectModule>& effect) { void AudioFlinger::ThreadBase::removeEffect_l(const sp<EffectModule>& effect, bool release) { ALOGV("removeEffect_l() %p effect %p", this, effect.get()); ALOGV("%s %p effect %p", __FUNCTION__, this, effect.get()); effect_descriptor_t desc = effect->desc(); if ((desc.flags & EFFECT_FLAG_TYPE_MASK) == EFFECT_FLAG_TYPE_AUXILIARY) { detachAuxEffect_l(effect->id()); Loading @@ -1436,7 +1457,7 @@ void AudioFlinger::ThreadBase::removeEffect_l(const sp<EffectModule>& effect) { sp<EffectChain> chain = effect->chain().promote(); if (chain != 0) { // remove effect chain if removing last effect if (chain->removeEffect_l(effect) == 0) { if (chain->removeEffect_l(effect, release) == 0) { removeEffectChain_l(chain); } } else { Loading Loading
services/audioflinger/AudioFlinger.cpp +18 −5 Original line number Diff line number Diff line Loading @@ -2355,6 +2355,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 @@ -2768,8 +2780,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 @@ -2966,7 +2979,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 @@ -589,6 +589,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 +121 −93 Original line number Diff line number Diff line Loading @@ -60,8 +60,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 @@ -94,7 +95,9 @@ AudioFlinger::EffectModule::EffectModule(ThreadBase *thread, goto Error; } setOffloaded(thread->type() == ThreadBase::OFFLOAD, thread->id()); ALOGV("Constructor success name %s, Interface %p", mDescriptor.name, mEffectInterface.get()); return; Error: mEffectInterface.clear(); Loading @@ -105,10 +108,10 @@ AudioFlinger::EffectModule::~EffectModule() { ALOGV("Destructor %p", this); if (mEffectInterface != 0) { remove_effect_from_hal_l(); // release effect engine mEffectInterface.clear(); ALOGW("EffectModule %p destructor called with unreleased interface", this); release_l(); } } status_t AudioFlinger::EffectModule::addHandle(EffectHandle *handle) Loading @@ -122,7 +125,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 @@ -150,9 +153,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 @@ -161,9 +169,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 @@ -190,7 +199,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 @@ -198,31 +207,6 @@ AudioFlinger::EffectHandle *AudioFlinger::EffectModule::controlHandle_l() return NULL; } size_t AudioFlinger::EffectModule::disconnect(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); } sp<AudioFlinger> af = mAudioFlinger.promote(); if (af != 0) { af->updateOrphanEffectChains(this); } AudioSystem::unregisterEffect(mId); } } } return mHandles.size(); } bool AudioFlinger::EffectModule::updateState() { Mutex::Autolock _l(mLock); Loading Loading @@ -560,6 +544,16 @@ status_t AudioFlinger::EffectModule::stop_l() return status; } // must be called with EffectChain::mLock held void AudioFlinger::EffectModule::release_l() { if (mEffectInterface != 0) { remove_effect_from_hal_l(); // release effect engine mEffectInterface.clear(); } } status_t AudioFlinger::EffectModule::remove_effect_from_hal_l() { if ((mDescriptor.flags & EFFECT_FLAG_TYPE_MASK) == EFFECT_FLAG_TYPE_PRE_PROC || Loading Loading @@ -653,7 +647,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 @@ -706,7 +700,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 +860,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 @@ -1093,7 +1086,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 @@ -1119,7 +1112,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 @@ -1142,14 +1135,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 @@ -1160,13 +1145,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 @@ -1174,20 +1161,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 @@ -1197,12 +1184,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 @@ -1214,27 +1201,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 @@ -1247,25 +1236,32 @@ 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(); if (thread != 0) { thread->checkSuspendOnEffectEnabled(mEffect, false, mEffect->sessionId()); mDisconnected = true; sp<ThreadBase> thread; { sp<EffectModule> effect = mEffect.promote(); if (effect != 0) { thread = effect->thread().promote(); } } if (thread != 0) { thread->disconnectEffectHandle(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 @@ -1285,15 +1281,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 @@ -1338,7 +1336,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 @@ -1375,7 +1373,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 @@ -1457,7 +1455,6 @@ AudioFlinger::EffectChain::~EffectChain() if (mOwnInBuffer) { delete mInBuffer; } } // getEffectFromDesc_l() must be called with ThreadBase::mLock held Loading Loading @@ -1573,13 +1570,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 @@ -1689,8 +1711,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 @@ -1705,6 +1728,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 @@ -1716,6 +1743,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 @@ -1723,7 +1751,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 @@ -1732,7 +1760,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 @@ -1741,7 +1769,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 @@ -1750,7 +1778,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 @@ -1811,7 +1839,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 @@ -1912,7 +1940,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 +25 −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,8 @@ 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 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 +125,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 +210,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 +229,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 +241,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 +276,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 Original line number Diff line number Diff line Loading @@ -1267,7 +1267,8 @@ sp<AudioFlinger::EffectHandle> AudioFlinger::ThreadBase::createEffect_l( audio_session_t sessionId, effect_descriptor_t *desc, int *enabled, status_t *status) status_t *status, bool pinned) { sp<EffectModule> effect; sp<EffectHandle> handle; Loading Loading @@ -1317,14 +1318,7 @@ sp<AudioFlinger::EffectHandle> AudioFlinger::ThreadBase::createEffect_l( } effectRegistered = true; // create a new effect module if none present in the chain effect = new EffectModule(this, chain, desc, id, sessionId); lStatus = effect->status(); if (lStatus != NO_ERROR) { goto Exit; } effect->setOffloaded(mType == OFFLOAD, mId); lStatus = chain->addEffect_l(effect); lStatus = chain->createEffect_l(effect, this, desc, id, sessionId, pinned); if (lStatus != NO_ERROR) { goto Exit; } Loading Loading @@ -1365,6 +1359,33 @@ Exit: return handle; } void AudioFlinger::ThreadBase::disconnectEffectHandle(EffectHandle *handle, bool unpinIfLast) { bool remove = false; sp<EffectModule> effect; { Mutex::Autolock _l(mLock); effect = handle->effect().promote(); if (effect == 0) { return; } // restore suspended effects if the disconnected handle was enabled and the last one. remove = (effect->removeHandle(handle) == 0) && (!effect->isPinned() || unpinIfLast); if (remove) { removeEffect_l(effect, true); } } if (remove) { mAudioFlinger->updateOrphanEffectChains(effect); AudioSystem::unregisterEffect(effect->id()); if (handle->enabled()) { checkSuspendOnEffectEnabled(effect, false, effect->sessionId()); } } } sp<AudioFlinger::EffectModule> AudioFlinger::ThreadBase::getEffect(audio_session_t sessionId, int effectId) { Loading Loading @@ -1425,9 +1446,9 @@ status_t AudioFlinger::ThreadBase::addEffect_l(const sp<EffectModule>& effect) return NO_ERROR; } void AudioFlinger::ThreadBase::removeEffect_l(const sp<EffectModule>& effect) { void AudioFlinger::ThreadBase::removeEffect_l(const sp<EffectModule>& effect, bool release) { ALOGV("removeEffect_l() %p effect %p", this, effect.get()); ALOGV("%s %p effect %p", __FUNCTION__, this, effect.get()); effect_descriptor_t desc = effect->desc(); if ((desc.flags & EFFECT_FLAG_TYPE_MASK) == EFFECT_FLAG_TYPE_AUXILIARY) { detachAuxEffect_l(effect->id()); Loading @@ -1436,7 +1457,7 @@ void AudioFlinger::ThreadBase::removeEffect_l(const sp<EffectModule>& effect) { sp<EffectChain> chain = effect->chain().promote(); if (chain != 0) { // remove effect chain if removing last effect if (chain->removeEffect_l(effect) == 0) { if (chain->removeEffect_l(effect, release) == 0) { removeEffectChain_l(chain); } } else { Loading