AudioEffect: Add process callback

Add a callback method to IEffectClient interface to notify the
controlling AudioEffect client when the effect engine has processed
frames in the audio mixer thread.

Bug: 188502620
Test: make
Change-Id: Ibf3078b2fc779102eb8f70698e6ccc308c6f0bad
diff --git a/services/audioflinger/AudioFlinger.cpp b/services/audioflinger/AudioFlinger.cpp
index a130d0a..17ecf21 100644
--- a/services/audioflinger/AudioFlinger.cpp
+++ b/services/audioflinger/AudioFlinger.cpp
@@ -3760,7 +3760,7 @@
             ALOGV("%s device type %#x address %s", __func__, device.mType, device.getAddress());
             handle = mDeviceEffectManager.createEffect_l(
                     &descOut, device, client, effectClient, mPatchPanel.patches_l(),
-                    &enabledOut, &lStatus, probe);
+                    &enabledOut, &lStatus, probe, request.notifyFramesProcessed);
             if (lStatus != NO_ERROR && lStatus != ALREADY_EXISTS) {
                 // remove local strong reference to Client with mClientLock held
                 Mutex::Autolock _cl(mClientLock);
@@ -3880,7 +3880,8 @@
             }
         }
         handle = thread->createEffect_l(client, effectClient, priority, sessionId,
-                                        &descOut, &enabledOut, &lStatus, pinned, probe);
+                                        &descOut, &enabledOut, &lStatus, pinned, probe,
+                                        request.notifyFramesProcessed);
         if (lStatus != NO_ERROR && lStatus != ALREADY_EXISTS) {
             // remove local strong reference to Client with mClientLock held
             Mutex::Autolock _cl(mClientLock);
diff --git a/services/audioflinger/DeviceEffectManager.cpp b/services/audioflinger/DeviceEffectManager.cpp
index cecd52b..53ac5cb 100644
--- a/services/audioflinger/DeviceEffectManager.cpp
+++ b/services/audioflinger/DeviceEffectManager.cpp
@@ -77,7 +77,8 @@
         const std::map<audio_patch_handle_t, PatchPanel::Patch>& patches,
         int *enabled,
         status_t *status,
-        bool probe) {
+        bool probe,
+        bool notifyFramesProcessed) {
     sp<DeviceEffectProxy> effect;
     sp<EffectHandle> handle;
     status_t lStatus;
@@ -95,10 +96,12 @@
             effect = iter->second;
         } else {
             effect = new DeviceEffectProxy(device, mMyCallback,
-                    descriptor, mAudioFlinger.nextUniqueId(AUDIO_UNIQUE_ID_USE_EFFECT));
+                    descriptor, mAudioFlinger.nextUniqueId(AUDIO_UNIQUE_ID_USE_EFFECT),
+                    notifyFramesProcessed);
         }
         // create effect handle and connect it to effect module
-        handle = new EffectHandle(effect, client, effectClient, 0 /*priority*/);
+        handle = new EffectHandle(effect, client, effectClient, 0 /*priority*/,
+                                  notifyFramesProcessed);
         lStatus = handle->initCheck();
         if (lStatus == NO_ERROR) {
             lStatus = effect->addHandle(handle.get());
diff --git a/services/audioflinger/DeviceEffectManager.h b/services/audioflinger/DeviceEffectManager.h
index c222de8..5cfe2fb 100644
--- a/services/audioflinger/DeviceEffectManager.h
+++ b/services/audioflinger/DeviceEffectManager.h
@@ -37,7 +37,8 @@
                 const std::map<audio_patch_handle_t, PatchPanel::Patch>& patches,
                 int *enabled,
                 status_t *status,
-                bool probe);
+                bool probe,
+                bool notifyFramesProcessed);
     void createAudioPatch(audio_patch_handle_t handle, const PatchPanel::Patch& patch);
     void releaseAudioPatch(audio_patch_handle_t handle);
 
diff --git a/services/audioflinger/Effects.cpp b/services/audioflinger/Effects.cpp
index bd661f9..b80943e 100644
--- a/services/audioflinger/Effects.cpp
+++ b/services/audioflinger/Effects.cpp
@@ -648,6 +648,13 @@
             mState = IDLE;
         }
         break;
+    case ACTIVE:
+        for (size_t i = 0; i < mHandles.size(); i++) {
+            if (!mHandles[i]->disconnected()) {
+                mHandles[i]->framesProcessed(mConfig.inputCfg.buffer.frameCount);
+            }
+        }
+        break;
     default: //IDLE , ACTIVE, DESTROYED
         break;
     }
@@ -1716,10 +1723,11 @@
 AudioFlinger::EffectHandle::EffectHandle(const sp<EffectBase>& effect,
                                          const sp<AudioFlinger::Client>& client,
                                          const sp<media::IEffectClient>& effectClient,
-                                         int32_t priority)
+                                         int32_t priority, bool notifyFramesProcessed)
     : BnEffect(),
     mEffect(effect), mEffectClient(effectClient), mClient(client), mCblk(NULL),
-    mPriority(priority), mHasControl(false), mEnabled(false), mDisconnected(false)
+    mPriority(priority), mHasControl(false), mEnabled(false), mDisconnected(false),
+    mNotifyFramesProcessed(notifyFramesProcessed)
 {
     ALOGV("constructor %p client %p", this, client.get());
 
@@ -2028,6 +2036,13 @@
     }
 }
 
+void AudioFlinger::EffectHandle::framesProcessed(int32_t frames) const
+{
+    if (mEffectClient != 0 && mNotifyFramesProcessed) {
+        mEffectClient->framesProcessed(frames);
+    }
+}
+
 void AudioFlinger::EffectHandle::dumpToBuffer(char* buffer, size_t size)
 {
     bool locked = mCblk != NULL && AudioFlinger::dumpTryLock(mCblk->lock);
@@ -3200,7 +3215,8 @@
         } else {
             mHalEffect->setDevices({mDevice});
         }
-        *handle = new EffectHandle(mHalEffect, nullptr, nullptr, 0 /*priority*/);
+        *handle = new EffectHandle(mHalEffect, nullptr, nullptr, 0 /*priority*/,
+                                   mNotifyFramesProcessed);
         status = (*handle)->initCheck();
         if (status == OK) {
             status = mHalEffect->addHandle((*handle).get());
@@ -3226,7 +3242,8 @@
         int enabled;
         *handle = thread->createEffect_l(nullptr, nullptr, 0, AUDIO_SESSION_DEVICE,
                                          const_cast<effect_descriptor_t *>(&mDescriptor),
-                                         &enabled, &status, false, false /*probe*/);
+                                         &enabled, &status, false, false /*probe*/,
+                                         mNotifyFramesProcessed);
         ALOGV("%s thread->createEffect_l status %d", __func__, status);
     } else {
         status = BAD_VALUE;
diff --git a/services/audioflinger/Effects.h b/services/audioflinger/Effects.h
index 1d0d00d..389ff7b 100644
--- a/services/audioflinger/Effects.h
+++ b/services/audioflinger/Effects.h
@@ -341,7 +341,7 @@
     EffectHandle(const sp<EffectBase>& effect,
             const sp<AudioFlinger::Client>& client,
             const sp<media::IEffectClient>& effectClient,
-            int32_t priority);
+            int32_t priority, bool notifyFramesProcessed);
     virtual ~EffectHandle();
     virtual status_t initCheck();
 
@@ -372,6 +372,8 @@
     void setEnabled(bool enabled);
     bool enabled() const { return mEnabled; }
 
+    void framesProcessed(int32_t frames) const;
+
     // Getters
     wp<EffectBase> effect() const { return mEffect; }
     int id() const {
@@ -405,6 +407,8 @@
     bool mEnabled;                           // cached enable state: needed when the effect is
                                              // restored after being suspended
     bool mDisconnected;                      // Set to true by disconnect()
+    const bool mNotifyFramesProcessed;       // true if the client callback event
+                                             // EVENT_FRAMES_PROCESSED must be generated
 };
 
 // the EffectChain class represents a group of effects associated to one audio session.
@@ -667,11 +671,11 @@
 public:
         DeviceEffectProxy (const AudioDeviceTypeAddr& device,
                 const sp<DeviceEffectManagerCallback>& callback,
-                effect_descriptor_t *desc, int id)
+                effect_descriptor_t *desc, int id, bool notifyFramesProcessed)
             : EffectBase(callback, desc, id, AUDIO_SESSION_DEVICE, false),
                 mDevice(device), mManagerCallback(callback),
-                mMyCallback(new ProxyCallback(wp<DeviceEffectProxy>(this),
-                                              callback)) {}
+                mMyCallback(new ProxyCallback(wp<DeviceEffectProxy>(this), callback)),
+                mNotifyFramesProcessed(notifyFramesProcessed) {}
 
     status_t setEnabled(bool enabled, bool fromHandle) override;
     sp<DeviceEffectProxy> asDeviceEffectProxy() override { return this; }
@@ -764,4 +768,5 @@
     std::map<audio_patch_handle_t, sp<EffectHandle>> mEffectHandles; // protected by mProxyLock
     sp<EffectModule> mHalEffect; // protected by mProxyLock
     struct audio_port_config mDevicePort = { .id = AUDIO_PORT_HANDLE_NONE };
+    const bool mNotifyFramesProcessed;
 };
diff --git a/services/audioflinger/Threads.cpp b/services/audioflinger/Threads.cpp
index 7292527..d3cae76 100644
--- a/services/audioflinger/Threads.cpp
+++ b/services/audioflinger/Threads.cpp
@@ -1449,7 +1449,8 @@
         int *enabled,
         status_t *status,
         bool pinned,
-        bool probe)
+        bool probe,
+        bool notifyFramesProcessed)
 {
     sp<EffectModule> effect;
     sp<EffectHandle> handle;
@@ -1516,7 +1517,7 @@
             }
         }
         // create effect handle and connect it to effect module
-        handle = new EffectHandle(effect, client, effectClient, priority);
+        handle = new EffectHandle(effect, client, effectClient, priority, notifyFramesProcessed);
         lStatus = handle->initCheck();
         if (lStatus == OK) {
             lStatus = effect->addHandle(handle.get());
@@ -7107,7 +7108,7 @@
 
         finalDownMixer = createEffect_l(nullptr /*client*/, nullptr /*effectClient*/,
                 0 /*priority*/, AUDIO_SESSION_OUTPUT_STAGE, &descriptors[0], nullptr /*enabled*/,
-                &status, false /*pinned*/, false /*probe*/);
+                &status, false /*pinned*/, false /*probe*/, false /*notifyFramesProcessed*/);
 
         if (finalDownMixer == nullptr || (status != NO_ERROR && status != ALREADY_EXISTS)) {
             ALOGW("%s error creating downmixer %d", __func__, status);
diff --git a/services/audioflinger/Threads.h b/services/audioflinger/Threads.h
index 3001863..b9801c2 100644
--- a/services/audioflinger/Threads.h
+++ b/services/audioflinger/Threads.h
@@ -408,7 +408,8 @@
                                     int *enabled,
                                     status_t *status /*non-NULL*/,
                                     bool pinned,
-                                    bool probe);
+                                    bool probe,
+                                    bool notifyFramesProcessed);
 
                 // return values for hasAudioSession (bit field)
                 enum effect_state {