more support for audio effect offload

Offloading of audio effects is now enabled for offloaded
output threads. If an effect not supporting offload is enabled,
the AudioTrack is invalidated so that it can be recreated in PCM
mode.

Fix some issues in effect proxy related to handling of effect
commands to offloaded and non offloaded effects.

Also fixed a bug on capture index in software Visualizer effect.

Bug: 8174034.

Change-Id: Ib23d3c2d5a652361b0aaec7faee09102f2b18fce
diff --git a/services/audioflinger/Effects.cpp b/services/audioflinger/Effects.cpp
index 86671a9..0ca2107 100644
--- a/services/audioflinger/Effects.cpp
+++ b/services/audioflinger/Effects.cpp
@@ -764,6 +764,46 @@
     return enabled;
 }
 
+status_t AudioFlinger::EffectModule::setOffloaded(bool offloaded, audio_io_handle_t io)
+{
+    Mutex::Autolock _l(mLock);
+    if (mStatus != NO_ERROR) {
+        return mStatus;
+    }
+    status_t status = NO_ERROR;
+    if ((mDescriptor.flags & EFFECT_FLAG_OFFLOAD_SUPPORTED) != 0) {
+        status_t cmdStatus;
+        uint32_t size = sizeof(status_t);
+        effect_offload_param_t cmd;
+
+        cmd.isOffload = offloaded;
+        cmd.ioHandle = io;
+        status = (*mEffectInterface)->command(mEffectInterface,
+                                              EFFECT_CMD_OFFLOAD,
+                                              sizeof(effect_offload_param_t),
+                                              &cmd,
+                                              &size,
+                                              &cmdStatus);
+        if (status == NO_ERROR) {
+            status = cmdStatus;
+        }
+        mOffloaded = (status == NO_ERROR) ? offloaded : false;
+    } else {
+        if (offloaded) {
+            status = INVALID_OPERATION;
+        }
+        mOffloaded = false;
+    }
+    ALOGV("setOffloaded() offloaded %d io %d status %d", offloaded, io, status);
+    return status;
+}
+
+bool AudioFlinger::EffectModule::isOffloaded() const
+{
+    Mutex::Autolock _l(mLock);
+    return mOffloaded;
+}
+
 void AudioFlinger::EffectModule::dump(int fd, const Vector<String16>& args)
 {
     const size_t SIZE = 256;
@@ -932,14 +972,13 @@
         }
         mEnabled = false;
     } else {
-        //TODO: remove when effect offload is implemented
-        if (thread != 0) {
+        if (thread != 0 && !mEffect->isOffloadable()) {
             if ((thread->type() == ThreadBase::OFFLOAD)) {
                 PlaybackThread *t = (PlaybackThread *)thread.get();
                 t->invalidateTracks(AUDIO_STREAM_MUSIC);
             }
             if (mEffect->sessionId() == AUDIO_SESSION_OUTPUT_MIX) {
-                thread->mAudioFlinger->onGlobalEffectEnable();
+                thread->mAudioFlinger->onNonOffloadableGlobalEffectEnable();
             }
         }
     }
@@ -1728,12 +1767,12 @@
     }
 }
 
-bool AudioFlinger::EffectChain::isEnabled()
+bool AudioFlinger::EffectChain::isNonOffloadableEnabled()
 {
     Mutex::Autolock _l(mLock);
     size_t size = mEffects.size();
     for (size_t i = 0; i < size; i++) {
-        if (mEffects[i]->isEnabled()) {
+        if (mEffects[i]->isEnabled() && !mEffects[i]->isOffloadable()) {
             return true;
         }
     }