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/media/libaudioclient/AudioEffect.cpp b/media/libaudioclient/AudioEffect.cpp
index 6ad5483..9091599 100644
--- a/media/libaudioclient/AudioEffect.cpp
+++ b/media/libaudioclient/AudioEffect.cpp
@@ -70,7 +70,8 @@
                 audio_session_t sessionId,
                 audio_io_handle_t io,
                 const AudioDeviceTypeAddr& device,
-                bool probe)
+                bool probe,
+                bool notifyFramesProcessed)
 {
     sp<media::IEffect> iEffect;
     sp<IMemory> cblk;
@@ -124,6 +125,7 @@
     request.device = VALUE_OR_RETURN_STATUS(legacy2aidl_AudioDeviceTypeAddress(device));
     request.attributionSource = mClientAttributionSource;
     request.probe = probe;
+    request.notifyFramesProcessed = notifyFramesProcessed;
 
     media::CreateEffectResponse response;
 
@@ -194,7 +196,8 @@
                 audio_session_t sessionId,
                 audio_io_handle_t io,
                 const AudioDeviceTypeAddr& device,
-                bool probe)
+                bool probe,
+                bool notifyFramesProcessed)
 {
     effect_uuid_t type;
     effect_uuid_t *pType = nullptr;
@@ -211,7 +214,8 @@
         pUuid = &uuid;
     }
 
-    return set(pType, pUuid, priority, cbf, user, sessionId, io, device, probe);
+    return set(pType, pUuid, priority, cbf, user, sessionId, io,
+               device, probe, notifyFramesProcessed);
 }
 
 
@@ -522,6 +526,13 @@
     }
 }
 
+void AudioEffect::framesProcessed(int32_t frames)
+{
+    if (mCbf != NULL) {
+        mCbf(EVENT_FRAMES_PROCESSED, mUserData, &frames);
+    }
+}
+
 // -------------------------------------------------------------------------
 
 status_t AudioEffect::queryNumberEffects(uint32_t *numEffects)
diff --git a/media/libaudioclient/aidl/android/media/CreateEffectRequest.aidl b/media/libaudioclient/aidl/android/media/CreateEffectRequest.aidl
index 2d274f4..35a56eb 100644
--- a/media/libaudioclient/aidl/android/media/CreateEffectRequest.aidl
+++ b/media/libaudioclient/aidl/android/media/CreateEffectRequest.aidl
@@ -37,4 +37,6 @@
     AudioDevice device;
     AttributionSourceState attributionSource;
     boolean probe;
+    /** true if a callback must be sent each time audio frames are processed */
+    boolean notifyFramesProcessed;
 }
diff --git a/media/libaudioclient/aidl/android/media/IEffectClient.aidl b/media/libaudioclient/aidl/android/media/IEffectClient.aidl
index 3b6bcf1..37b442d 100644
--- a/media/libaudioclient/aidl/android/media/IEffectClient.aidl
+++ b/media/libaudioclient/aidl/android/media/IEffectClient.aidl
@@ -43,4 +43,10 @@
      * TODO(ytai): replace opaque byte arrays with strongly typed parameters.
      */
     oneway void commandExecuted(int cmdCode, in byte[] cmdData, in byte[] replyData);
+
+    /**
+     * Called whenever audio frames have been processed by the effect engine.
+     * @param frames number of frames processed.
+     */
+    oneway void framesProcessed(int frames);
 }
diff --git a/media/libaudioclient/fuzzer/audioflinger_fuzzer.cpp b/media/libaudioclient/fuzzer/audioflinger_fuzzer.cpp
index 12473fc..bd9e158 100644
--- a/media/libaudioclient/fuzzer/audioflinger_fuzzer.cpp
+++ b/media/libaudioclient/fuzzer/audioflinger_fuzzer.cpp
@@ -383,6 +383,9 @@
                                    const std::vector<uint8_t> &replyData __unused) override {
         return binder::Status::ok();
     }
+    binder::Status framesProcessed(int32_t frames __unused) override {
+        return binder::Status::ok();
+    }
 };
 
 status_t AudioFlingerFuzzer::invokeAudioEffect() {
@@ -424,6 +427,7 @@
     request.attributionSource.packageName = opPackageName;
     request.attributionSource.pid = VALUE_OR_RETURN_STATUS(legacy2aidl_pid_t_int32_t(getpid()));
     request.probe = false;
+    request.notifyFramesProcessed = false;
 
     media::CreateEffectResponse response{};
     status_t status = af->createEffect(request, &response);
diff --git a/media/libaudioclient/include/media/AudioEffect.h b/media/libaudioclient/include/media/AudioEffect.h
index 3c19ec1..dd4d2da 100644
--- a/media/libaudioclient/include/media/AudioEffect.h
+++ b/media/libaudioclient/include/media/AudioEffect.h
@@ -283,7 +283,8 @@
         EVENT_CONTROL_STATUS_CHANGED = 0,
         EVENT_ENABLE_STATUS_CHANGED = 1,
         EVENT_PARAMETER_CHANGED = 2,
-        EVENT_ERROR = 3
+        EVENT_ERROR = 3,
+        EVENT_FRAMES_PROCESSED = 4,
     };
 
     /* Callback function notifying client application of a change in effect engine state or
@@ -389,7 +390,8 @@
                             audio_session_t sessionId = AUDIO_SESSION_OUTPUT_MIX,
                             audio_io_handle_t io = AUDIO_IO_HANDLE_NONE,
                             const AudioDeviceTypeAddr& device = {},
-                            bool probe = false);
+                            bool probe = false,
+                            bool notifyFramesProcessed = false);
     /*
      * Same as above but with type and uuid specified by character strings.
      */
@@ -401,7 +403,8 @@
                             audio_session_t sessionId = AUDIO_SESSION_OUTPUT_MIX,
                             audio_io_handle_t io = AUDIO_IO_HANDLE_NONE,
                             const AudioDeviceTypeAddr& device = {},
-                            bool probe = false);
+                            bool probe = false,
+                            bool notifyFramesProcessed = false);
 
     /* Result of constructing the AudioEffect. This must be checked
      * before using any AudioEffect API.
@@ -552,6 +555,7 @@
      virtual void commandExecuted(int32_t cmdCode,
                                   const std::vector<uint8_t>& cmdData,
                                   const std::vector<uint8_t>& replyData);
+     virtual void framesProcessed(int32_t frames);
 
 private:
 
@@ -587,6 +591,14 @@
             }
             return binder::Status::ok();
         }
+        binder::Status framesProcessed(int32_t frames) override {
+            sp<AudioEffect> effect = mEffect.promote();
+            if (effect != 0) {
+                effect->framesProcessed(frames);
+            }
+            return binder::Status::ok();
+        }
+
 
         // IBinder::DeathRecipient
         virtual void binderDied(const wp<IBinder>& /*who*/) {