Loading services/audioflinger/Effects.cpp +34 −23 Original line number Original line Diff line number Diff line Loading @@ -990,13 +990,6 @@ status_t AudioFlinger::EffectModule::configure() &size, &size, &cmdStatus); &cmdStatus); } } if (isVolumeControl()) { // Force initializing the volume as 0 for volume control effect for safer ramping uint32_t left = 0; uint32_t right = 0; setVolumeInternal(&left, &right, true /*controller*/); } } } // mConfig.outputCfg.buffer.frameCount cannot be zero. // mConfig.outputCfg.buffer.frameCount cannot be zero. Loading Loading @@ -2096,7 +2089,7 @@ NO_THREAD_SAFETY_ANALYSIS // conditional try lock AudioFlinger::EffectChain::EffectChain(const wp<ThreadBase>& thread, AudioFlinger::EffectChain::EffectChain(const wp<ThreadBase>& thread, audio_session_t sessionId) audio_session_t sessionId) : mSessionId(sessionId), mActiveTrackCnt(0), mTrackCnt(0), mTailBufferCount(0), : mSessionId(sessionId), mActiveTrackCnt(0), mTrackCnt(0), mTailBufferCount(0), mVolumeCtrlIdx(-1), mLeftVolume(UINT_MAX), mRightVolume(UINT_MAX), mLeftVolume(UINT_MAX), mRightVolume(UINT_MAX), mNewLeftVolume(UINT_MAX), mNewRightVolume(UINT_MAX), mNewLeftVolume(UINT_MAX), mNewRightVolume(UINT_MAX), mEffectCallback(new EffectCallback(wp<EffectChain>(this), thread)) mEffectCallback(new EffectCallback(wp<EffectChain>(this), thread)) { { Loading Loading @@ -2342,6 +2335,15 @@ status_t AudioFlinger::EffectChain::addEffect_ll(const sp<EffectModule>& effect) return NO_ERROR; return NO_ERROR; } } std::optional<size_t> AudioFlinger::EffectChain::findVolumeControl_l(size_t from, size_t to) const { for (size_t i = std::min(to, mEffects.size()); i > from; i--) { if (mEffects[i - 1]->isVolumeControlEnabled()) { return i - 1; } } return std::nullopt; } ssize_t AudioFlinger::EffectChain::getInsertIndex(const effect_descriptor_t& desc) { ssize_t AudioFlinger::EffectChain::getInsertIndex(const effect_descriptor_t& desc) { // Insert effects are inserted at the end of mEffects vector as they are processed // Insert effects are inserted at the end of mEffects vector as they are processed // after track and auxiliary effects. // after track and auxiliary effects. Loading Loading @@ -2511,29 +2513,38 @@ bool AudioFlinger::EffectChain::setVolume_l(uint32_t *left, uint32_t *right, boo { { uint32_t newLeft = *left; uint32_t newLeft = *left; uint32_t newRight = *right; uint32_t newRight = *right; bool hasControl = false; const size_t size = mEffects.size(); int ctrlIdx = -1; size_t size = mEffects.size(); // first update volume controller // first update volume controller for (size_t i = size; i > 0; i--) { const auto volumeControlIndex = findVolumeControl_l(0, size); if (mEffects[i - 1]->isVolumeControlEnabled()) { const int ctrlIdx = volumeControlIndex.value_or(-1); ctrlIdx = i - 1; const sp<EffectModule> volumeControlEffect = hasControl = true; volumeControlIndex.has_value() ? mEffects[ctrlIdx] : nullptr; break; const sp<EffectModule> cachedVolumeControlEffect = mVolumeControlEffect.promote(); } } if (!force && ctrlIdx == mVolumeCtrlIdx && if (!force && volumeControlEffect == cachedVolumeControlEffect && *left == mLeftVolume && *right == mRightVolume) { *left == mLeftVolume && *right == mRightVolume) { if (hasControl) { if (volumeControlIndex.has_value()) { *left = mNewLeftVolume; *left = mNewLeftVolume; *right = mNewRightVolume; *right = mNewRightVolume; } } return hasControl; return volumeControlIndex.has_value(); } } mVolumeCtrlIdx = ctrlIdx; if (volumeControlEffect != cachedVolumeControlEffect) { // The volume control effect is a new one. Set the old one as full volume. Set the new onw // as zero for safe ramping. if (cachedVolumeControlEffect != nullptr) { uint32_t leftMax = 1 << 24; uint32_t rightMax = 1 << 24; cachedVolumeControlEffect->setVolume(&leftMax, &rightMax, true /*controller*/); } if (volumeControlEffect != nullptr) { uint32_t leftZero = 0; uint32_t rightZero = 0; volumeControlEffect->setVolume(&leftZero, &rightZero, true /*controller*/); } } mLeftVolume = newLeft; mLeftVolume = newLeft; mRightVolume = newRight; mRightVolume = newRight; Loading Loading @@ -2570,7 +2581,7 @@ bool AudioFlinger::EffectChain::setVolume_l(uint32_t *left, uint32_t *right, boo setVolumeForOutput_l(*left, *right); setVolumeForOutput_l(*left, *right); return hasControl; return volumeControlIndex.has_value(); } } // resetVolume_l() must be called with ThreadBase::mLock or EffectChain::mLock held // resetVolume_l() must be called with ThreadBase::mLock or EffectChain::mLock held Loading services/audioflinger/Effects.h +4 −1 Original line number Original line Diff line number Diff line Loading @@ -673,6 +673,8 @@ private: ssize_t getInsertIndex(const effect_descriptor_t& desc); ssize_t getInsertIndex(const effect_descriptor_t& desc); std::optional<size_t> findVolumeControl_l(size_t from, size_t to) const; mutable Mutex mLock; // mutex protecting effect list mutable Mutex mLock; // mutex protecting effect list Vector< sp<EffectModule> > mEffects; // list of effect modules Vector< sp<EffectModule> > mEffects; // list of effect modules audio_session_t mSessionId; // audio session ID audio_session_t mSessionId; // audio session ID Loading @@ -685,7 +687,6 @@ private: int32_t mTailBufferCount; // current effect tail buffer count int32_t mTailBufferCount; // current effect tail buffer count int32_t mMaxTailBuffers; // maximum effect tail buffers int32_t mMaxTailBuffers; // maximum effect tail buffers int mVolumeCtrlIdx; // index of insert effect having control over volume uint32_t mLeftVolume; // previous volume on left channel uint32_t mLeftVolume; // previous volume on left channel uint32_t mRightVolume; // previous volume on right channel uint32_t mRightVolume; // previous volume on right channel uint32_t mNewLeftVolume; // new volume on left channel uint32_t mNewLeftVolume; // new volume on left channel Loading @@ -698,6 +699,8 @@ private: KeyedVector< int, sp<SuspendedEffectDesc> > mSuspendedEffects; KeyedVector< int, sp<SuspendedEffectDesc> > mSuspendedEffects; const sp<EffectCallback> mEffectCallback; const sp<EffectCallback> mEffectCallback; wp<EffectModule> mVolumeControlEffect; }; }; class DeviceEffectProxy : public EffectBase { class DeviceEffectProxy : public EffectBase { Loading Loading
services/audioflinger/Effects.cpp +34 −23 Original line number Original line Diff line number Diff line Loading @@ -990,13 +990,6 @@ status_t AudioFlinger::EffectModule::configure() &size, &size, &cmdStatus); &cmdStatus); } } if (isVolumeControl()) { // Force initializing the volume as 0 for volume control effect for safer ramping uint32_t left = 0; uint32_t right = 0; setVolumeInternal(&left, &right, true /*controller*/); } } } // mConfig.outputCfg.buffer.frameCount cannot be zero. // mConfig.outputCfg.buffer.frameCount cannot be zero. Loading Loading @@ -2096,7 +2089,7 @@ NO_THREAD_SAFETY_ANALYSIS // conditional try lock AudioFlinger::EffectChain::EffectChain(const wp<ThreadBase>& thread, AudioFlinger::EffectChain::EffectChain(const wp<ThreadBase>& thread, audio_session_t sessionId) audio_session_t sessionId) : mSessionId(sessionId), mActiveTrackCnt(0), mTrackCnt(0), mTailBufferCount(0), : mSessionId(sessionId), mActiveTrackCnt(0), mTrackCnt(0), mTailBufferCount(0), mVolumeCtrlIdx(-1), mLeftVolume(UINT_MAX), mRightVolume(UINT_MAX), mLeftVolume(UINT_MAX), mRightVolume(UINT_MAX), mNewLeftVolume(UINT_MAX), mNewRightVolume(UINT_MAX), mNewLeftVolume(UINT_MAX), mNewRightVolume(UINT_MAX), mEffectCallback(new EffectCallback(wp<EffectChain>(this), thread)) mEffectCallback(new EffectCallback(wp<EffectChain>(this), thread)) { { Loading Loading @@ -2342,6 +2335,15 @@ status_t AudioFlinger::EffectChain::addEffect_ll(const sp<EffectModule>& effect) return NO_ERROR; return NO_ERROR; } } std::optional<size_t> AudioFlinger::EffectChain::findVolumeControl_l(size_t from, size_t to) const { for (size_t i = std::min(to, mEffects.size()); i > from; i--) { if (mEffects[i - 1]->isVolumeControlEnabled()) { return i - 1; } } return std::nullopt; } ssize_t AudioFlinger::EffectChain::getInsertIndex(const effect_descriptor_t& desc) { ssize_t AudioFlinger::EffectChain::getInsertIndex(const effect_descriptor_t& desc) { // Insert effects are inserted at the end of mEffects vector as they are processed // Insert effects are inserted at the end of mEffects vector as they are processed // after track and auxiliary effects. // after track and auxiliary effects. Loading Loading @@ -2511,29 +2513,38 @@ bool AudioFlinger::EffectChain::setVolume_l(uint32_t *left, uint32_t *right, boo { { uint32_t newLeft = *left; uint32_t newLeft = *left; uint32_t newRight = *right; uint32_t newRight = *right; bool hasControl = false; const size_t size = mEffects.size(); int ctrlIdx = -1; size_t size = mEffects.size(); // first update volume controller // first update volume controller for (size_t i = size; i > 0; i--) { const auto volumeControlIndex = findVolumeControl_l(0, size); if (mEffects[i - 1]->isVolumeControlEnabled()) { const int ctrlIdx = volumeControlIndex.value_or(-1); ctrlIdx = i - 1; const sp<EffectModule> volumeControlEffect = hasControl = true; volumeControlIndex.has_value() ? mEffects[ctrlIdx] : nullptr; break; const sp<EffectModule> cachedVolumeControlEffect = mVolumeControlEffect.promote(); } } if (!force && ctrlIdx == mVolumeCtrlIdx && if (!force && volumeControlEffect == cachedVolumeControlEffect && *left == mLeftVolume && *right == mRightVolume) { *left == mLeftVolume && *right == mRightVolume) { if (hasControl) { if (volumeControlIndex.has_value()) { *left = mNewLeftVolume; *left = mNewLeftVolume; *right = mNewRightVolume; *right = mNewRightVolume; } } return hasControl; return volumeControlIndex.has_value(); } } mVolumeCtrlIdx = ctrlIdx; if (volumeControlEffect != cachedVolumeControlEffect) { // The volume control effect is a new one. Set the old one as full volume. Set the new onw // as zero for safe ramping. if (cachedVolumeControlEffect != nullptr) { uint32_t leftMax = 1 << 24; uint32_t rightMax = 1 << 24; cachedVolumeControlEffect->setVolume(&leftMax, &rightMax, true /*controller*/); } if (volumeControlEffect != nullptr) { uint32_t leftZero = 0; uint32_t rightZero = 0; volumeControlEffect->setVolume(&leftZero, &rightZero, true /*controller*/); } } mLeftVolume = newLeft; mLeftVolume = newLeft; mRightVolume = newRight; mRightVolume = newRight; Loading Loading @@ -2570,7 +2581,7 @@ bool AudioFlinger::EffectChain::setVolume_l(uint32_t *left, uint32_t *right, boo setVolumeForOutput_l(*left, *right); setVolumeForOutput_l(*left, *right); return hasControl; return volumeControlIndex.has_value(); } } // resetVolume_l() must be called with ThreadBase::mLock or EffectChain::mLock held // resetVolume_l() must be called with ThreadBase::mLock or EffectChain::mLock held Loading
services/audioflinger/Effects.h +4 −1 Original line number Original line Diff line number Diff line Loading @@ -673,6 +673,8 @@ private: ssize_t getInsertIndex(const effect_descriptor_t& desc); ssize_t getInsertIndex(const effect_descriptor_t& desc); std::optional<size_t> findVolumeControl_l(size_t from, size_t to) const; mutable Mutex mLock; // mutex protecting effect list mutable Mutex mLock; // mutex protecting effect list Vector< sp<EffectModule> > mEffects; // list of effect modules Vector< sp<EffectModule> > mEffects; // list of effect modules audio_session_t mSessionId; // audio session ID audio_session_t mSessionId; // audio session ID Loading @@ -685,7 +687,6 @@ private: int32_t mTailBufferCount; // current effect tail buffer count int32_t mTailBufferCount; // current effect tail buffer count int32_t mMaxTailBuffers; // maximum effect tail buffers int32_t mMaxTailBuffers; // maximum effect tail buffers int mVolumeCtrlIdx; // index of insert effect having control over volume uint32_t mLeftVolume; // previous volume on left channel uint32_t mLeftVolume; // previous volume on left channel uint32_t mRightVolume; // previous volume on right channel uint32_t mRightVolume; // previous volume on right channel uint32_t mNewLeftVolume; // new volume on left channel uint32_t mNewLeftVolume; // new volume on left channel Loading @@ -698,6 +699,8 @@ private: KeyedVector< int, sp<SuspendedEffectDesc> > mSuspendedEffects; KeyedVector< int, sp<SuspendedEffectDesc> > mSuspendedEffects; const sp<EffectCallback> mEffectCallback; const sp<EffectCallback> mEffectCallback; wp<EffectModule> mVolumeControlEffect; }; }; class DeviceEffectProxy : public EffectBase { class DeviceEffectProxy : public EffectBase { Loading