Only set initial volume to 0 for the effect that does volume control.
When the effect for doing volume control is changed, set volume for the
old one as full level and the new one as 0 for safe ramping.
Bug: 280641126
Test: repo steps in the bug
Change-Id: I0f843c8deae907f8584dc18d025ab499319784b5
diff --git a/services/audioflinger/Effects.cpp b/services/audioflinger/Effects.cpp
index 5780d5d..d482d61 100644
--- a/services/audioflinger/Effects.cpp
+++ b/services/audioflinger/Effects.cpp
@@ -995,13 +995,6 @@
&size,
&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.
@@ -2127,7 +2120,7 @@
EffectChain::EffectChain(const wp<IAfThreadBase>& thread,
audio_session_t sessionId)
: 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),
mEffectCallback(new EffectCallback(wp<EffectChain>(this), thread))
{
@@ -2373,6 +2366,15 @@
return NO_ERROR;
}
+std::optional<size_t> 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 EffectChain::getInsertIndex(const effect_descriptor_t& desc) {
// Insert effects are inserted at the end of mEffects vector as they are processed
// after track and auxiliary effects.
@@ -2542,29 +2544,38 @@
{
uint32_t newLeft = *left;
uint32_t newRight = *right;
- bool hasControl = false;
- int ctrlIdx = -1;
- size_t size = mEffects.size();
+ const size_t size = mEffects.size();
// first update volume controller
- for (size_t i = size; i > 0; i--) {
- if (mEffects[i - 1]->isVolumeControlEnabled()) {
- ctrlIdx = i - 1;
- hasControl = true;
- break;
- }
- }
+ const auto volumeControlIndex = findVolumeControl_l(0, size);
+ const int ctrlIdx = volumeControlIndex.value_or(-1);
+ const sp<IAfEffectModule> volumeControlEffect =
+ volumeControlIndex.has_value() ? mEffects[ctrlIdx] : nullptr;
+ const sp<IAfEffectModule> cachedVolumeControlEffect = mVolumeControlEffect.promote();
- if (!force && ctrlIdx == mVolumeCtrlIdx &&
+ if (!force && volumeControlEffect == cachedVolumeControlEffect &&
*left == mLeftVolume && *right == mRightVolume) {
- if (hasControl) {
+ if (volumeControlIndex.has_value()) {
*left = mNewLeftVolume;
*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;
mRightVolume = newRight;
@@ -2601,7 +2612,7 @@
setVolumeForOutput_l(*left, *right);
- return hasControl;
+ return volumeControlIndex.has_value();
}
// resetVolume_l() must be called with IAfThreadBase::mutex() or EffectChain::mLock held