Set volume for output when effect is enabled/disabled.

Even though effect module has "EFFECT_FLAG_VOLUME_CTRL" flag,
there is some case where volume setting is not sent to offload thread.
That leads to sudden increase of audio volume or too low volume.
This change is to support delegation of volume control completely
for offload audio effect.

Bug: 37443095
Test: Enable/Disable Audio effects during offload playback
Change-Id: I7033071edc99fadc519efd7adc895dc10f7b9d86
diff --git a/services/audioflinger/Effects.cpp b/services/audioflinger/Effects.cpp
index 2047dfd..024e7eb 100644
--- a/services/audioflinger/Effects.cpp
+++ b/services/audioflinger/Effects.cpp
@@ -263,7 +263,9 @@
         }
         break;
     case STOPPING:
-        if (stop_l() == NO_ERROR) {
+        // volume control for offload and direct threads must take effect immediately.
+        if (stop_l() == NO_ERROR
+            && !(isVolumeControl() && isOffloadedOrDirect())) {
             mDisableWaitCnt = mMaxDisableWaitCnt;
         } else {
             mDisableWaitCnt = 1; // will cause immediate transition to IDLE
@@ -778,6 +780,16 @@
     }
     status_t cmdStatus = NO_ERROR;
     uint32_t size = sizeof(status_t);
+
+    if (isVolumeControl() && isOffloadedOrDirect()) {
+        sp<EffectChain>chain = mChain.promote();
+        // We have the EffectChain and EffectModule lock, permit a reentrant call to setVolume:
+        // resetVolume_l --> setVolume_l --> EffectModule::setVolume
+        mSetVolumeReentrantTid = gettid();
+        chain->resetVolume_l();
+        mSetVolumeReentrantTid = INVALID_PID;
+    }
+
     status_t status = mEffectInterface->command(EFFECT_CMD_DISABLE,
                                                 0,
                                                 NULL,
@@ -993,6 +1005,16 @@
     }
 }
 
+bool AudioFlinger::EffectModule::isOffloadedOrDirect() const
+{
+    return (mThreadType == ThreadBase::OFFLOAD || mThreadType == ThreadBase::DIRECT);
+}
+
+bool AudioFlinger::EffectModule::isVolumeControlEnabled() const
+{
+    return (isVolumeControl() && (isOffloadedOrDirect() ? isEnabled() : isProcessEnabled()));
+}
+
 void AudioFlinger::EffectModule::setInBuffer(const sp<EffectBufferHalInterface>& buffer) {
     ALOGVV("setInBuffer %p",(&buffer));
 
@@ -1091,7 +1113,7 @@
 
 status_t AudioFlinger::EffectModule::setVolume(uint32_t *left, uint32_t *right, bool controller)
 {
-    Mutex::Autolock _l(mLock);
+    AutoLockReentrant _l(mLock, mSetVolumeReentrantTid);
     if (mStatus != NO_ERROR) {
         return mStatus;
     }
@@ -1122,6 +1144,18 @@
     return status;
 }
 
+void AudioFlinger::EffectChain::setVolumeForOutput_l(uint32_t left, uint32_t right)
+{
+    sp<ThreadBase> thread = mThread.promote();
+    if (thread != 0 &&
+        (thread->type() == ThreadBase::OFFLOAD || thread->type() == ThreadBase::DIRECT)) {
+        PlaybackThread *t = (PlaybackThread *)thread.get();
+        float vol_l = (float)left / (1 << 24);
+        float vol_r = (float)right / (1 << 24);
+        t->setVolumeForOutput_l(vol_l, vol_r);
+    }
+}
+
 status_t AudioFlinger::EffectModule::setDevice(audio_devices_t device)
 {
     if (device == AUDIO_DEVICE_NONE) {
@@ -2200,8 +2234,7 @@
 
     // first update volume controller
     for (size_t i = size; i > 0; i--) {
-        if (mEffects[i - 1]->isProcessEnabled() &&
-            (mEffects[i - 1]->desc().flags & EFFECT_FLAG_VOLUME_MASK) == EFFECT_FLAG_VOLUME_CTRL) {
+        if (mEffects[i - 1]->isVolumeControlEnabled()) {
             ctrlIdx = i - 1;
             hasControl = true;
             break;
@@ -2247,6 +2280,8 @@
     *left = newLeft;
     *right = newRight;
 
+    setVolumeForOutput_l(*left, *right);
+
     return hasControl;
 }